From a3996de73d087e491c74ec9d6e40f4b1424c14ce Mon Sep 17 00:00:00 2001
From: Martin Dimov
Date: Mon, 16 Dec 2013 16:56:35 +0100
Subject: [PATCH 001/134] Updated Renci version to last 2013.4.7
---
Renci.SshNet/AuthenticationMethod.cs | 54 +
Renci.SshNet/AuthenticationResult.cs | 26 +
Renci.SshNet/BaseClient.cs | 42 +-
Renci.SshNet/Channels/Channel.cs | 175 +-
.../Channels/ChannelDirectTcpip.NET40.cs | 3 +-
Renci.SshNet/Channels/ChannelDirectTcpip.cs | 155 +-
.../Channels/ChannelForwardedTcpip.NET40.cs | 4 +-
.../Channels/ChannelForwardedTcpip.cs | 18 +-
Renci.SshNet/Channels/ChannelSession.cs | 65 +-
Renci.SshNet/CipherInfo.cs | 4 +-
Renci.SshNet/Common/ASCIIEncoding.cs | 189 ++
Renci.SshNet/Common/AsyncResult.cs | 5 +-
.../AuthenticationPasswordChangeEventArgs.cs | 2 +-
Renci.SshNet/Common/BigInteger.cs | 20 +-
Renci.SshNet/Common/DerData.cs | 2 +-
Renci.SshNet/Common/Extensions.NET.cs | 48 +
Renci.SshNet/Common/Extensions.NET40.cs | 25 -
Renci.SshNet/Common/Extensions.cs | 52 +-
Renci.SshNet/Common/HostKeyEventArgs.cs | 66 +
.../Common/NetConfServerException.NET40.cs | 28 +
Renci.SshNet/Common/NetConfServerException.cs | 41 +
Renci.SshNet/Common/PipeStream.cs | 8 +-
Renci.SshNet/Common/ProxyException.NET40.cs | 26 +
Renci.SshNet/Common/ProxyException.cs | 42 +
Renci.SshNet/Common/ScpDownloadEventArgs.cs | 41 +
Renci.SshNet/Common/ScpException.NET40.cs | 25 +
Renci.SshNet/Common/ScpException.cs | 41 +
Renci.SshNet/Common/ScpUploadEventArgs.cs | 41 +
Renci.SshNet/Common/ShellDataEventArgs.cs | 41 +
Renci.SshNet/Common/SshData.cs | 77 +-
Renci.SshNet/Common/TerminalModes.cs | 293 ++
Renci.SshNet/Compression/Adler32.cs | 88 +
Renci.SshNet/Compression/CompressionMode.cs | 18 +
Renci.SshNet/Compression/Compressor.cs | 119 +-
Renci.SshNet/Compression/Deflate.cs | 1640 +++++++++++
Renci.SshNet/Compression/InfBlocks.cs | 618 +++++
Renci.SshNet/Compression/InfCodes.cs | 611 +++++
Renci.SshNet/Compression/InfTree.cs | 523 ++++
Renci.SshNet/Compression/Inflate.cs | 387 +++
Renci.SshNet/Compression/InflateBlocks.cs | 721 +++++
Renci.SshNet/Compression/InflateCodes.cs | 690 +++++
Renci.SshNet/Compression/InflateTree.cs | 555 ++++
Renci.SshNet/Compression/JZlib.cs | 73 +
Renci.SshNet/Compression/StaticTree.cs | 152 ++
Renci.SshNet/Compression/Tree.cs | 367 +++
Renci.SshNet/Compression/Version.5/Adler32.cs | 95 +
.../Compression/Version.5/CompressionMode.cs | 18 +
.../Compression/Version.5/Compressor.cs | 151 ++
Renci.SshNet/Compression/Version.5/Deflate.cs | 2400 ++++++++++++++++
Renci.SshNet/Compression/Version.5/Inflate.cs | 518 ++++
.../Compression/Version.5/InflateBlocks.cs | 721 +++++
.../Compression/Version.5/InflateCodes.cs | 690 +++++
.../Compression/Version.5/InflateTree.cs | 555 ++++
Renci.SshNet/Compression/Version.5/JZlib.cs | 109 +
.../Compression/Version.5/StaticTree.cs | 98 +
Renci.SshNet/Compression/Version.5/Tree.cs | 334 +++
.../Compression/Version.5/ZInputStream.cs | 205 ++
.../Compression/Version.5/ZOutputStream.cs | 300 ++
Renci.SshNet/Compression/Version.5/ZStream.cs | 76 +
Renci.SshNet/Compression/Version.5/Zlib.cs | 30 +
.../Compression/Version.5/ZlibOpenSsh.cs | 37 +
.../Compression/Version.5/ZlibStream.cs | 51 +
Renci.SshNet/Compression/Version.6/Adler32.cs | 95 +
.../Compression/Version.6/CompressionMode.cs | 18 +
.../Compression/Version.6/Compressor.cs | 151 ++
Renci.SshNet/Compression/Version.6/Deflate.cs | 2401 +++++++++++++++++
Renci.SshNet/Compression/Version.6/Inflate.cs | 517 ++++
.../Compression/Version.6/InflateBlocks.cs | 721 +++++
.../Compression/Version.6/InflateCodes.cs | 690 +++++
.../Compression/Version.6/InflateTree.cs | 555 ++++
Renci.SshNet/Compression/Version.6/JZlib.cs | 109 +
.../Compression/Version.6/StaticTree.cs | 98 +
Renci.SshNet/Compression/Version.6/Tree.cs | 334 +++
.../Compression/Version.6/ZInputStream.cs | 205 ++
.../Compression/Version.6/ZOutputStream.cs | 300 ++
Renci.SshNet/Compression/Version.6/ZStream.cs | 73 +
Renci.SshNet/Compression/Version.6/Zlib.cs | 30 +
.../Compression/Version.6/ZlibOpenSsh.cs | 37 +
.../Compression/Version.6/ZlibStream.cs | 51 +
Renci.SshNet/Compression/Version.7/Adler32.cs | 95 +
.../Compression/Version.7/CompressionMode.cs | 18 +
.../Compression/Version.7/Compressor.cs | 151 ++
Renci.SshNet/Compression/Version.7/Deflate.cs | 2394 ++++++++++++++++
Renci.SshNet/Compression/Version.7/Inflate.cs | 517 ++++
.../Compression/Version.7/InflateBlocks.cs | 721 +++++
.../Compression/Version.7/InflateCodes.cs | 690 +++++
.../Compression/Version.7/InflateTree.cs | 555 ++++
Renci.SshNet/Compression/Version.7/JZlib.cs | 109 +
.../Compression/Version.7/StaticTree.cs | 98 +
Renci.SshNet/Compression/Version.7/Tree.cs | 334 +++
.../Compression/Version.7/ZInputStream.cs | 205 ++
.../Compression/Version.7/ZOutputStream.cs | 287 ++
Renci.SshNet/Compression/Version.7/ZStream.cs | 73 +
Renci.SshNet/Compression/Version.7/Zlib.cs | 30 +
.../Compression/Version.7/ZlibOpenSsh.cs | 37 +
.../Compression/Version.7/ZlibStream.cs | 51 +
Renci.SshNet/Compression/Version.8/Adler32.cs | 95 +
.../Compression/Version.8/CompressionMode.cs | 18 +
.../Compression/Version.8/Compressor.cs | 151 ++
Renci.SshNet/Compression/Version.8/Deflate.cs | 2217 +++++++++++++++
Renci.SshNet/Compression/Version.8/Inflate.cs | 516 ++++
.../Compression/Version.8/InflateBlocks.cs | 721 +++++
.../Compression/Version.8/InflateCodes.cs | 690 +++++
.../Compression/Version.8/InflateTree.cs | 555 ++++
Renci.SshNet/Compression/Version.8/JZlib.cs | 109 +
.../Compression/Version.8/StaticTree.cs | 98 +
Renci.SshNet/Compression/Version.8/Tree.cs | 334 +++
.../Compression/Version.8/ZInputStream.cs | 202 ++
.../Compression/Version.8/ZOutputStream.cs | 256 ++
Renci.SshNet/Compression/Version.8/ZStream.cs | 94 +
Renci.SshNet/Compression/Version.8/Zlib.cs | 30 +
.../Compression/Version.8/ZlibOpenSsh.cs | 37 +
.../Compression/Version.8/ZlibStream.cs | 51 +
.../Compression/Working.1/CompressionMode.cs | 18 +
.../Compression/Working.1/Compressor.cs | 151 ++
Renci.SshNet/Compression/Working.1/Deflate.cs | 2185 +++++++++++++++
.../Compression/Working.1/InfBlocks.cs | 1375 ++++++++++
.../Compression/Working.1/InfCodes.cs | 696 +++++
Renci.SshNet/Compression/Working.1/InfTree.cs | 603 +++++
Renci.SshNet/Compression/Working.1/Inflate.cs | 476 ++++
Renci.SshNet/Compression/Working.1/JZlib.cs | 111 +
.../Compression/Working.1/StaticTree.cs | 98 +
Renci.SshNet/Compression/Working.1/Tree.cs | 333 +++
.../Compression/Working.1/ZInputStream.cs | 192 ++
.../Compression/Working.1/ZOutputStream.cs | 201 ++
Renci.SshNet/Compression/Working.1/ZStream.cs | 274 ++
Renci.SshNet/Compression/Working.1/Zlib.cs | 30 +
.../Compression/Working.1/ZlibOpenSsh.cs | 37 +
.../Compression/Working.1/ZlibStream.cs | 50 +
.../Compression/ZDeflaterOutputStream.cs | 151 ++
.../Compression/ZInflaterInputStream.cs | 127 +
Renci.SshNet/Compression/ZInputStream.cs | 193 ++
Renci.SshNet/Compression/ZOutputStream.cs | 217 ++
Renci.SshNet/Compression/ZStream.cs | 214 ++
Renci.SshNet/Compression/Zlib.cs | 46 +-
Renci.SshNet/Compression/ZlibOpenSsh.cs | 79 +-
Renci.SshNet/Compression/ZlibStream.cs | 49 +
Renci.SshNet/Compression/v10/Adler32.cs | 95 +
.../Compression/v10/CompressionMode.cs | 18 +
Renci.SshNet/Compression/v10/Compressor.cs | 151 ++
Renci.SshNet/Compression/v10/Deflate.cs | 2290 ++++++++++++++++
Renci.SshNet/Compression/v10/Inflate.cs | 524 ++++
Renci.SshNet/Compression/v10/InflateBlocks.cs | 721 +++++
Renci.SshNet/Compression/v10/InflateCodes.cs | 690 +++++
Renci.SshNet/Compression/v10/InflateTree.cs | 555 ++++
Renci.SshNet/Compression/v10/JZlib.cs | 109 +
Renci.SshNet/Compression/v10/StaticTree.cs | 98 +
Renci.SshNet/Compression/v10/Tree.cs | 334 +++
Renci.SshNet/Compression/v10/ZInputStream.cs | 200 ++
Renci.SshNet/Compression/v10/ZOutputStream.cs | 252 ++
Renci.SshNet/Compression/v10/ZStream.cs | 94 +
Renci.SshNet/Compression/v10/Zlib.cs | 30 +
Renci.SshNet/Compression/v10/ZlibOpenSsh.cs | 37 +
Renci.SshNet/Compression/v10/ZlibStream.cs | 51 +
Renci.SshNet/Compression/v11/Adler32.cs | 95 +
.../Compression/v11/CompressionMode.cs | 18 +
Renci.SshNet/Compression/v11/Compressor.cs | 151 ++
Renci.SshNet/Compression/v11/Deflate.cs | 2225 +++++++++++++++
Renci.SshNet/Compression/v11/Inflate.cs | 524 ++++
Renci.SshNet/Compression/v11/InflateBlocks.cs | 721 +++++
Renci.SshNet/Compression/v11/InflateCodes.cs | 690 +++++
Renci.SshNet/Compression/v11/InflateTree.cs | 555 ++++
Renci.SshNet/Compression/v11/JZlib.cs | 109 +
Renci.SshNet/Compression/v11/StaticTree.cs | 98 +
Renci.SshNet/Compression/v11/Tree.cs | 334 +++
Renci.SshNet/Compression/v11/ZInputStream.cs | 202 ++
Renci.SshNet/Compression/v11/ZOutputStream.cs | 252 ++
Renci.SshNet/Compression/v11/ZStream.cs | 94 +
Renci.SshNet/Compression/v11/Zlib.cs | 30 +
Renci.SshNet/Compression/v11/ZlibOpenSsh.cs | 37 +
Renci.SshNet/Compression/v11/ZlibStream.cs | 51 +
Renci.SshNet/Compression/v12/Adler32.cs | 95 +
.../Compression/v12/CompressionMode.cs | 18 +
Renci.SshNet/Compression/v12/Compressor.cs | 151 ++
Renci.SshNet/Compression/v12/Deflate.cs | 2225 +++++++++++++++
Renci.SshNet/Compression/v12/Inflate.cs | 524 ++++
Renci.SshNet/Compression/v12/InflateBlocks.cs | 721 +++++
Renci.SshNet/Compression/v12/InflateCodes.cs | 690 +++++
Renci.SshNet/Compression/v12/InflateTree.cs | 555 ++++
Renci.SshNet/Compression/v12/JZlib.cs | 109 +
Renci.SshNet/Compression/v12/StaticTree.cs | 98 +
Renci.SshNet/Compression/v12/Tree.cs | 334 +++
Renci.SshNet/Compression/v12/ZInputStream.cs | 202 ++
Renci.SshNet/Compression/v12/ZOutputStream.cs | 252 ++
Renci.SshNet/Compression/v12/ZStream.cs | 102 +
Renci.SshNet/Compression/v12/Zlib.cs | 30 +
Renci.SshNet/Compression/v12/ZlibOpenSsh.cs | 37 +
Renci.SshNet/Compression/v12/ZlibStream.cs | 51 +
Renci.SshNet/Compression/v13/Adler32.cs | 95 +
.../Compression/v13/CompressionMode.cs | 18 +
Renci.SshNet/Compression/v13/Compressor.cs | 151 ++
Renci.SshNet/Compression/v13/Deflate.cs | 2225 +++++++++++++++
Renci.SshNet/Compression/v13/Inflate.cs | 524 ++++
Renci.SshNet/Compression/v13/InflateBlocks.cs | 717 +++++
Renci.SshNet/Compression/v13/InflateCodes.cs | 685 +++++
Renci.SshNet/Compression/v13/InflateTree.cs | 554 ++++
Renci.SshNet/Compression/v13/JZlib.cs | 109 +
Renci.SshNet/Compression/v13/StaticTree.cs | 98 +
Renci.SshNet/Compression/v13/Tree.cs | 334 +++
Renci.SshNet/Compression/v13/ZInputStream.cs | 202 ++
Renci.SshNet/Compression/v13/ZOutputStream.cs | 252 ++
Renci.SshNet/Compression/v13/ZStream.cs | 100 +
Renci.SshNet/Compression/v13/Zlib.cs | 30 +
Renci.SshNet/Compression/v13/ZlibOpenSsh.cs | 37 +
Renci.SshNet/Compression/v13/ZlibStream.cs | 51 +
Renci.SshNet/Compression/v9/Adler32.cs | 95 +
.../Compression/v9/CompressionMode.cs | 18 +
Renci.SshNet/Compression/v9/Compressor.cs | 151 ++
Renci.SshNet/Compression/v9/Deflate.cs | 2226 +++++++++++++++
Renci.SshNet/Compression/v9/Inflate.cs | 524 ++++
Renci.SshNet/Compression/v9/InflateBlocks.cs | 721 +++++
Renci.SshNet/Compression/v9/InflateCodes.cs | 690 +++++
Renci.SshNet/Compression/v9/InflateTree.cs | 555 ++++
Renci.SshNet/Compression/v9/JZlib.cs | 109 +
Renci.SshNet/Compression/v9/StaticTree.cs | 98 +
Renci.SshNet/Compression/v9/Tree.cs | 334 +++
Renci.SshNet/Compression/v9/ZInputStream.cs | 202 ++
Renci.SshNet/Compression/v9/ZOutputStream.cs | 252 ++
Renci.SshNet/Compression/v9/ZStream.cs | 94 +
Renci.SshNet/Compression/v9/Zlib.cs | 30 +
Renci.SshNet/Compression/v9/ZlibOpenSsh.cs | 37 +
Renci.SshNet/Compression/v9/ZlibStream.cs | 51 +
...{B60A61FD-33DF-43A1-B48C-A8E3DB53FA13}.tmp | 690 +++++
Renci.SshNet/ConnectionInfo.cs | 422 +--
Renci.SshNet/Documentation/Content/About.aml | 55 -
.../Guide/Guide.Command.Asynchronous.aml | 41 -
.../Content/Guide/Guide.Command.Error.aml | 36 -
.../Guide/Guide.Command.Multitasking.aml | 38 -
.../Guide/Guide.Command.StatusCode.aml | 31 -
.../Content/Guide/Guide.Command.Timeout.aml | 32 -
.../Content/Guide/Guide.Command.aml | 88 -
.../Guide/Guide.Connection.ChangePassword.aml | 34 -
.../Guide/Guide.Connection.Interactive.aml | 41 -
.../Guide/Guide.Connection.Password.aml | 42 -
.../Guide/Guide.Connection.PrivateKey.aml | 37 -
.../Content/Guide/Guide.Connection.Prompt.aml | 35 -
.../Guide/Guide.Connection.Timeout.aml | 32 -
.../Content/Guide/Guide.Connection.aml | 125 -
.../Content/Guide/Guide.PortForward.Local.aml | 30 -
.../Guide/Guide.PortForward.Remote.aml | 30 -
.../Content/Guide/Guide.PortForward.aml | 17 -
.../Content/Guide/Guide.SFtp.aml | 85 -
.../Documentation/Content/Guide/Guide.aml | 75 -
.../Documentation/Content/HowTo.Connect.aml | 44 -
.../Documentation/Content/Reference.aml | 16 -
.../Documentation/Renci.SshClient.content | 28 -
Renci.SshNet/Documentation/SshClient.shfbproj | 140 -
Renci.SshNet/ExpectAction.cs | 60 +
Renci.SshNet/ExpectAsyncResult.cs | 23 +
Renci.SshNet/ForwardedPort.cs | 33 +-
Renci.SshNet/ForwardedPortDynamic.NET.cs | 282 ++
Renci.SshNet/ForwardedPortDynamic.NET40.cs | 14 +
Renci.SshNet/ForwardedPortDynamic.cs | 126 +
Renci.SshNet/ForwardedPortLocal.NET.cs | 119 +
Renci.SshNet/ForwardedPortLocal.NET40.cs | 84 +-
Renci.SshNet/ForwardedPortLocal.cs | 70 +
Renci.SshNet/ForwardedPortRemote.NET.cs | 37 +
Renci.SshNet/ForwardedPortRemote.NET40.cs | 3 +-
Renci.SshNet/ForwardedPortRemote.cs | 74 +-
Renci.SshNet/HashInfo.cs | 39 +
...rdInteractiveAuthenticationMethod.NET40.cs | 21 +
...KeyboardInteractiveAuthenticationMethod.cs | 198 ++
.../KeyboardInteractiveConnectionInfo.cs | 178 +-
Renci.SshNet/MessageEventArgs.cs | 4 +
.../Messages/Authentication/BannerMessage.cs | 2 +-
.../Authentication/PublicKeyMessage.cs | 4 +-
.../Messages/Authentication/RequestMessage.cs | 8 +-
.../Authentication/RequestMessageHost.cs | 4 +-
.../RequestMessageKeyboardInteractive.cs | 2 +-
.../Authentication/RequestMessagePassword.cs | 22 +-
.../Authentication/RequestMessagePublicKey.cs | 2 +-
.../Connection/ChannelExtendedDataMessage.cs | 4 +-
.../ChannelOpen/ChannelOpenMessage.cs | 4 +-
.../ChannelRequest/BreakRequestInfo.cs | 72 +
.../ChannelRequest/ChannelRequestMessage.cs | 4 +-
.../ChannelRequest/ExecRequestInfo.cs | 20 +-
.../ChannelRequest/ExitSignalRequestInfo.cs | 6 +-
.../ChannelRequest/PseudoTerminalInfo.cs | 44 +-
.../ChannelRequest/SignalRequestInfo.cs | 4 +-
.../ChannelRequest/SubsystemRequestInfo.cs | 4 +-
.../X11ForwardingRequestInfo.cs | 4 +-
.../Connection/GlobalRequestMessage.cs | 17 +-
Renci.SshNet/Messages/Message.cs | 21 +-
.../Messages/Transport/DisconnectMessage.cs | 4 +-
.../KeyExchangeDhGroupExchangeInit.cs | 2 +-
.../KeyExchangeDhGroupExchangeRequest.cs | 2 +-
.../Transport/KeyExchangeDhInitMessage.cs | 2 +-
.../Transport/KeyExchangeEcdhInitMessage.cs | 50 +
.../Transport/KeyExchangeEcdhReplyMessage.cs | 50 +
.../Transport/KeyExchangeInitMessage.cs | 2 +-
.../Messages/Transport/NewKeysMessage.cs | 2 +-
.../Transport/ServiceAcceptMessage.cs | 2 +-
.../Transport/ServiceRequestMessage.cs | 4 +-
Renci.SshNet/NetConfClient.cs | 221 ++
Renci.SshNet/Netconf/NetConfSession.cs | 212 ++
Renci.SshNet/NoneAuthenticationMethod.cs | 140 +
Renci.SshNet/NoneConnectionInfo.cs | 101 +-
.../PasswordAuthenticationMethod.NET40.cs | 21 +
Renci.SshNet/PasswordAuthenticationMethod.cs | 217 ++
Renci.SshNet/PasswordConnectionInfo.cs | 285 +-
.../PrivateKeyAuthenticationMethod.cs | 232 ++
Renci.SshNet/PrivateKeyConnectionInfo.cs | 219 +-
Renci.SshNet/PrivateKeyFile.cs | 281 +-
Renci.SshNet/Properties/AssemblyInfo.cs | 13 +-
Renci.SshNet/ProxyTypes.cs | 22 +
Renci.SshNet/Renci.SshNet.csproj | 193 +-
Renci.SshNet/ScpClient.NET.cs | 312 +++
Renci.SshNet/ScpClient.cs | 421 +++
.../Security/CertificateHostAlgorithm.cs | 6 +-
.../Security/Cryptography/AsymmetricCipher.cs | 4 +
.../Security/Cryptography/BlockCipher.cs | 20 +-
Renci.SshNet/Security/Cryptography/Cipher.cs | 28 +-
.../Cryptography/CipherDigitalSignature.cs | 10 +-
.../Cryptography/Ciphers/AesCipher.cs | 147 +-
.../Cryptography/Ciphers/Arc4Cipher.cs | 129 +-
.../Cryptography/Ciphers/BlowfishCipher.cs | 145 +-
.../Cryptography/Ciphers/CastCipher.cs | 89 +-
.../Cryptography/Ciphers/CipherPadding.cs | 2 +-
.../Cryptography/Ciphers/DesCipher.cs | 12 +-
.../Ciphers/Paddings/PKCS5Padding.cs | 35 +
.../Ciphers/Paddings/PKCS7Padding.cs | 6 +-
.../Cryptography/Ciphers/RsaCipher.cs | 22 +-
.../Cryptography/Ciphers/SerpentCipher.cs | 718 ++---
.../Cryptography/Ciphers/TripleDesCipher.cs | 6 +-
.../Cryptography/Ciphers/TwofishCipher.cs | 949 +++----
.../Security/Cryptography/DigitalSignature.cs | 4 +-
.../Cryptography/DsaDigitalSignature.cs | 34 +-
Renci.SshNet/Security/Cryptography/DsaKey.cs | 36 +-
Renci.SshNet/Security/Cryptography/HMAC.cs | 97 +-
.../Security/Cryptography/Hashes/MD5Hash.cs | 22 +-
.../Cryptography/Hashes/RIPEMD160Hash.cs | 522 ++++
.../Security/Cryptography/Hashes/SHA1Hash.cs | 341 ++-
.../Cryptography/Hashes/SHA256Hash.cs | 23 +-
.../Cryptography/Hashes/SHA2HashBase.cs | 366 +++
.../Cryptography/Hashes/SHA384Hash.cs | 85 +
.../Cryptography/Hashes/SHA512Hash.cs | 87 +
Renci.SshNet/Security/Cryptography/Key.cs | 14 +-
.../Cryptography/RsaDigitalSignature.cs | 6 +-
Renci.SshNet/Security/Cryptography/RsaKey.cs | 42 +
.../Security/Cryptography/StreamCipher.cs | 2 +-
Renci.SshNet/Security/HostAlgorithm.cs | 4 +-
Renci.SshNet/Security/KeyExchange.cs | 79 +-
.../Security/KeyExchangeDiffieHellman.cs | 21 +-
.../KeyExchangeDiffieHellmanGroup14Sha1.cs | 115 +-
.../KeyExchangeDiffieHellmanGroup1Sha1.cs | 116 +-
...yExchangeDiffieHellmanGroupExchangeSha1.cs | 4 +-
...xchangeDiffieHellmanGroupExchangeSha256.cs | 6 +-
.../KeyExchangeDiffieHellmanGroupSha1.cs | 132 +
.../KeyExchangeEllipticCurveDiffieHellman.cs | 284 ++
Renci.SshNet/Security/KeyHostAlgorithm.cs | 26 +-
Renci.SshNet/Session.NET.cs | 103 +-
Renci.SshNet/Session.NET40.cs | 2 +-
Renci.SshNet/Session.cs | 550 +++-
Renci.SshNet/Sftp/Flags.cs | 5 +-
.../Sftp/OpenSshFilesytemInformation.cs | 97 -
.../ExtendedRequests/FStatVfsRequest.cs | 33 +
.../ExtendedRequests/HardLinkRequest.cs | 36 +
.../ExtendedRequests/PosixRenameRequest.cs | 40 +
.../ExtendedRequests/StatVfsRequest.cs | 37 +
...RenameRequest.cs => PosixRenameRequest.cs} | 15 +-
.../Sftp/Requests/SftpBlockRequest.cs | 51 +
.../Sftp/Requests/SftpCloseRequest.cs | 4 +-
.../Sftp/Requests/SftpExtendedRequest.cs | 28 +
.../Sftp/Requests/SftpFSetStatRequest.cs | 4 +-
.../Sftp/Requests/SftpFStatRequest.cs | 4 +-
.../Sftp/Requests/SftpLStatRequest.cs | 11 +-
Renci.SshNet/Sftp/Requests/SftpLinkRequest.cs | 55 +
.../Sftp/Requests/SftpMkDirRequest.cs | 17 +-
.../Sftp/Requests/SftpOpenDirRequest.cs | 11 +-
Renci.SshNet/Sftp/Requests/SftpOpenRequest.cs | 14 +-
.../Sftp/Requests/SftpReadDirRequest.cs | 4 +-
.../Sftp/Requests/SftpReadLinkRequest.cs | 11 +-
Renci.SshNet/Sftp/Requests/SftpReadRequest.cs | 4 +-
.../Sftp/Requests/SftpRealPathRequest.cs | 9 +-
.../Sftp/Requests/SftpRemoveRequest.cs | 11 +-
.../Sftp/Requests/SftpRenameRequest.cs | 15 +-
Renci.SshNet/Sftp/Requests/SftpRequest.cs | 5 +-
.../Sftp/Requests/SftpRmDirRequest.cs | 11 +-
.../Sftp/Requests/SftpSetStatRequest.cs | 11 +-
Renci.SshNet/Sftp/Requests/SftpStatRequest.cs | 11 +-
.../Sftp/Requests/SftpSymLinkRequest.cs | 15 +-
.../Sftp/Requests/SftpUnblockRequest.cs | 46 +
.../Sftp/Requests/SftpWriteRequest.cs | 4 +-
...SshStatVfsRequest.cs => StatVfsRequest.cs} | 15 +-
.../ExtendedReplies/ExtendedReplyInfo.cs | 25 +
.../ExtendedReplies/StatVfsReplyInfo.cs | 26 +
.../Sftp/Responses/OpenSshStatVfsResponse.cs | 26 -
.../Sftp/Responses/SftpAttrsResponse.cs | 5 +
.../Sftp/Responses/SftpDataResponse.cs | 5 +
.../Responses/SftpExtendedReplyResponse.cs | 13 +-
.../Sftp/Responses/SftpHandleResponse.cs | 5 +
.../Sftp/Responses/SftpNameResponse.cs | 10 +-
Renci.SshNet/Sftp/Responses/SftpResponse.cs | 9 +-
.../Sftp/Responses/SftpStatusResponse.cs | 15 +-
.../Sftp/Responses/StatVfsResponse.cs | 24 +
Renci.SshNet/Sftp/SftpDownloadAsyncResult.cs | 11 +
Renci.SshNet/Sftp/SftpFile.cs | 51 +
Renci.SshNet/Sftp/SftpFileAttributes.cs | 74 +-
Renci.SshNet/Sftp/SftpFileStream.cs | 78 +-
.../Sftp/SftpFileSystemInformation.cs | 136 +
Renci.SshNet/Sftp/SftpMessage.cs | 82 +-
Renci.SshNet/Sftp/SftpMessageTypes.cs | 15 +-
Renci.SshNet/Sftp/SftpSession.cs | 763 +++---
.../SftpSynchronizeDirectoriesAsyncResult.cs | 40 +
Renci.SshNet/Sftp/SftpUploadAsyncResult.cs | 11 +
Renci.SshNet/Sftp/StatusCodes.cs | 94 +-
Renci.SshNet/SftpClient.NET.cs | 177 ++
Renci.SshNet/SftpClient.NET40.cs | 8 +-
Renci.SshNet/SftpClient.cs | 661 +++--
Renci.SshNet/Shell.NET40.cs | 4 +-
Renci.SshNet/Shell.cs | 28 +-
Renci.SshNet/ShellStream.NET40.cs | 18 +
Renci.SshNet/ShellStream.cs | 759 ++++++
Renci.SshNet/SshClient.cs | 267 +-
Renci.SshNet/SshCommand.NET40.cs | 4 +-
Renci.SshNet/SshCommand.cs | 165 +-
Renci.SshNet/SubsystemSession.cs | 135 +-
Sshfs/Sshfs.sln | 17 +-
Sshfs/Sshfs/SftpContextStream.cs | 6 +-
Sshfs/Sshfs/SftpFilesystem.cs | 15 +-
420 files changed, 84284 insertions(+), 4887 deletions(-)
create mode 100644 Renci.SshNet/AuthenticationMethod.cs
create mode 100644 Renci.SshNet/AuthenticationResult.cs
create mode 100644 Renci.SshNet/Common/ASCIIEncoding.cs
create mode 100644 Renci.SshNet/Common/Extensions.NET.cs
delete mode 100644 Renci.SshNet/Common/Extensions.NET40.cs
create mode 100644 Renci.SshNet/Common/HostKeyEventArgs.cs
create mode 100644 Renci.SshNet/Common/NetConfServerException.NET40.cs
create mode 100644 Renci.SshNet/Common/NetConfServerException.cs
create mode 100644 Renci.SshNet/Common/ProxyException.NET40.cs
create mode 100644 Renci.SshNet/Common/ProxyException.cs
create mode 100644 Renci.SshNet/Common/ScpDownloadEventArgs.cs
create mode 100644 Renci.SshNet/Common/ScpException.NET40.cs
create mode 100644 Renci.SshNet/Common/ScpException.cs
create mode 100644 Renci.SshNet/Common/ScpUploadEventArgs.cs
create mode 100644 Renci.SshNet/Common/ShellDataEventArgs.cs
create mode 100644 Renci.SshNet/Common/TerminalModes.cs
create mode 100644 Renci.SshNet/Compression/Adler32.cs
create mode 100644 Renci.SshNet/Compression/CompressionMode.cs
create mode 100644 Renci.SshNet/Compression/Deflate.cs
create mode 100644 Renci.SshNet/Compression/InfBlocks.cs
create mode 100644 Renci.SshNet/Compression/InfCodes.cs
create mode 100644 Renci.SshNet/Compression/InfTree.cs
create mode 100644 Renci.SshNet/Compression/Inflate.cs
create mode 100644 Renci.SshNet/Compression/InflateBlocks.cs
create mode 100644 Renci.SshNet/Compression/InflateCodes.cs
create mode 100644 Renci.SshNet/Compression/InflateTree.cs
create mode 100644 Renci.SshNet/Compression/JZlib.cs
create mode 100644 Renci.SshNet/Compression/StaticTree.cs
create mode 100644 Renci.SshNet/Compression/Tree.cs
create mode 100644 Renci.SshNet/Compression/Version.5/Adler32.cs
create mode 100644 Renci.SshNet/Compression/Version.5/CompressionMode.cs
create mode 100644 Renci.SshNet/Compression/Version.5/Compressor.cs
create mode 100644 Renci.SshNet/Compression/Version.5/Deflate.cs
create mode 100644 Renci.SshNet/Compression/Version.5/Inflate.cs
create mode 100644 Renci.SshNet/Compression/Version.5/InflateBlocks.cs
create mode 100644 Renci.SshNet/Compression/Version.5/InflateCodes.cs
create mode 100644 Renci.SshNet/Compression/Version.5/InflateTree.cs
create mode 100644 Renci.SshNet/Compression/Version.5/JZlib.cs
create mode 100644 Renci.SshNet/Compression/Version.5/StaticTree.cs
create mode 100644 Renci.SshNet/Compression/Version.5/Tree.cs
create mode 100644 Renci.SshNet/Compression/Version.5/ZInputStream.cs
create mode 100644 Renci.SshNet/Compression/Version.5/ZOutputStream.cs
create mode 100644 Renci.SshNet/Compression/Version.5/ZStream.cs
create mode 100644 Renci.SshNet/Compression/Version.5/Zlib.cs
create mode 100644 Renci.SshNet/Compression/Version.5/ZlibOpenSsh.cs
create mode 100644 Renci.SshNet/Compression/Version.5/ZlibStream.cs
create mode 100644 Renci.SshNet/Compression/Version.6/Adler32.cs
create mode 100644 Renci.SshNet/Compression/Version.6/CompressionMode.cs
create mode 100644 Renci.SshNet/Compression/Version.6/Compressor.cs
create mode 100644 Renci.SshNet/Compression/Version.6/Deflate.cs
create mode 100644 Renci.SshNet/Compression/Version.6/Inflate.cs
create mode 100644 Renci.SshNet/Compression/Version.6/InflateBlocks.cs
create mode 100644 Renci.SshNet/Compression/Version.6/InflateCodes.cs
create mode 100644 Renci.SshNet/Compression/Version.6/InflateTree.cs
create mode 100644 Renci.SshNet/Compression/Version.6/JZlib.cs
create mode 100644 Renci.SshNet/Compression/Version.6/StaticTree.cs
create mode 100644 Renci.SshNet/Compression/Version.6/Tree.cs
create mode 100644 Renci.SshNet/Compression/Version.6/ZInputStream.cs
create mode 100644 Renci.SshNet/Compression/Version.6/ZOutputStream.cs
create mode 100644 Renci.SshNet/Compression/Version.6/ZStream.cs
create mode 100644 Renci.SshNet/Compression/Version.6/Zlib.cs
create mode 100644 Renci.SshNet/Compression/Version.6/ZlibOpenSsh.cs
create mode 100644 Renci.SshNet/Compression/Version.6/ZlibStream.cs
create mode 100644 Renci.SshNet/Compression/Version.7/Adler32.cs
create mode 100644 Renci.SshNet/Compression/Version.7/CompressionMode.cs
create mode 100644 Renci.SshNet/Compression/Version.7/Compressor.cs
create mode 100644 Renci.SshNet/Compression/Version.7/Deflate.cs
create mode 100644 Renci.SshNet/Compression/Version.7/Inflate.cs
create mode 100644 Renci.SshNet/Compression/Version.7/InflateBlocks.cs
create mode 100644 Renci.SshNet/Compression/Version.7/InflateCodes.cs
create mode 100644 Renci.SshNet/Compression/Version.7/InflateTree.cs
create mode 100644 Renci.SshNet/Compression/Version.7/JZlib.cs
create mode 100644 Renci.SshNet/Compression/Version.7/StaticTree.cs
create mode 100644 Renci.SshNet/Compression/Version.7/Tree.cs
create mode 100644 Renci.SshNet/Compression/Version.7/ZInputStream.cs
create mode 100644 Renci.SshNet/Compression/Version.7/ZOutputStream.cs
create mode 100644 Renci.SshNet/Compression/Version.7/ZStream.cs
create mode 100644 Renci.SshNet/Compression/Version.7/Zlib.cs
create mode 100644 Renci.SshNet/Compression/Version.7/ZlibOpenSsh.cs
create mode 100644 Renci.SshNet/Compression/Version.7/ZlibStream.cs
create mode 100644 Renci.SshNet/Compression/Version.8/Adler32.cs
create mode 100644 Renci.SshNet/Compression/Version.8/CompressionMode.cs
create mode 100644 Renci.SshNet/Compression/Version.8/Compressor.cs
create mode 100644 Renci.SshNet/Compression/Version.8/Deflate.cs
create mode 100644 Renci.SshNet/Compression/Version.8/Inflate.cs
create mode 100644 Renci.SshNet/Compression/Version.8/InflateBlocks.cs
create mode 100644 Renci.SshNet/Compression/Version.8/InflateCodes.cs
create mode 100644 Renci.SshNet/Compression/Version.8/InflateTree.cs
create mode 100644 Renci.SshNet/Compression/Version.8/JZlib.cs
create mode 100644 Renci.SshNet/Compression/Version.8/StaticTree.cs
create mode 100644 Renci.SshNet/Compression/Version.8/Tree.cs
create mode 100644 Renci.SshNet/Compression/Version.8/ZInputStream.cs
create mode 100644 Renci.SshNet/Compression/Version.8/ZOutputStream.cs
create mode 100644 Renci.SshNet/Compression/Version.8/ZStream.cs
create mode 100644 Renci.SshNet/Compression/Version.8/Zlib.cs
create mode 100644 Renci.SshNet/Compression/Version.8/ZlibOpenSsh.cs
create mode 100644 Renci.SshNet/Compression/Version.8/ZlibStream.cs
create mode 100644 Renci.SshNet/Compression/Working.1/CompressionMode.cs
create mode 100644 Renci.SshNet/Compression/Working.1/Compressor.cs
create mode 100644 Renci.SshNet/Compression/Working.1/Deflate.cs
create mode 100644 Renci.SshNet/Compression/Working.1/InfBlocks.cs
create mode 100644 Renci.SshNet/Compression/Working.1/InfCodes.cs
create mode 100644 Renci.SshNet/Compression/Working.1/InfTree.cs
create mode 100644 Renci.SshNet/Compression/Working.1/Inflate.cs
create mode 100644 Renci.SshNet/Compression/Working.1/JZlib.cs
create mode 100644 Renci.SshNet/Compression/Working.1/StaticTree.cs
create mode 100644 Renci.SshNet/Compression/Working.1/Tree.cs
create mode 100644 Renci.SshNet/Compression/Working.1/ZInputStream.cs
create mode 100644 Renci.SshNet/Compression/Working.1/ZOutputStream.cs
create mode 100644 Renci.SshNet/Compression/Working.1/ZStream.cs
create mode 100644 Renci.SshNet/Compression/Working.1/Zlib.cs
create mode 100644 Renci.SshNet/Compression/Working.1/ZlibOpenSsh.cs
create mode 100644 Renci.SshNet/Compression/Working.1/ZlibStream.cs
create mode 100644 Renci.SshNet/Compression/ZDeflaterOutputStream.cs
create mode 100644 Renci.SshNet/Compression/ZInflaterInputStream.cs
create mode 100644 Renci.SshNet/Compression/ZInputStream.cs
create mode 100644 Renci.SshNet/Compression/ZOutputStream.cs
create mode 100644 Renci.SshNet/Compression/ZStream.cs
create mode 100644 Renci.SshNet/Compression/ZlibStream.cs
create mode 100644 Renci.SshNet/Compression/v10/Adler32.cs
create mode 100644 Renci.SshNet/Compression/v10/CompressionMode.cs
create mode 100644 Renci.SshNet/Compression/v10/Compressor.cs
create mode 100644 Renci.SshNet/Compression/v10/Deflate.cs
create mode 100644 Renci.SshNet/Compression/v10/Inflate.cs
create mode 100644 Renci.SshNet/Compression/v10/InflateBlocks.cs
create mode 100644 Renci.SshNet/Compression/v10/InflateCodes.cs
create mode 100644 Renci.SshNet/Compression/v10/InflateTree.cs
create mode 100644 Renci.SshNet/Compression/v10/JZlib.cs
create mode 100644 Renci.SshNet/Compression/v10/StaticTree.cs
create mode 100644 Renci.SshNet/Compression/v10/Tree.cs
create mode 100644 Renci.SshNet/Compression/v10/ZInputStream.cs
create mode 100644 Renci.SshNet/Compression/v10/ZOutputStream.cs
create mode 100644 Renci.SshNet/Compression/v10/ZStream.cs
create mode 100644 Renci.SshNet/Compression/v10/Zlib.cs
create mode 100644 Renci.SshNet/Compression/v10/ZlibOpenSsh.cs
create mode 100644 Renci.SshNet/Compression/v10/ZlibStream.cs
create mode 100644 Renci.SshNet/Compression/v11/Adler32.cs
create mode 100644 Renci.SshNet/Compression/v11/CompressionMode.cs
create mode 100644 Renci.SshNet/Compression/v11/Compressor.cs
create mode 100644 Renci.SshNet/Compression/v11/Deflate.cs
create mode 100644 Renci.SshNet/Compression/v11/Inflate.cs
create mode 100644 Renci.SshNet/Compression/v11/InflateBlocks.cs
create mode 100644 Renci.SshNet/Compression/v11/InflateCodes.cs
create mode 100644 Renci.SshNet/Compression/v11/InflateTree.cs
create mode 100644 Renci.SshNet/Compression/v11/JZlib.cs
create mode 100644 Renci.SshNet/Compression/v11/StaticTree.cs
create mode 100644 Renci.SshNet/Compression/v11/Tree.cs
create mode 100644 Renci.SshNet/Compression/v11/ZInputStream.cs
create mode 100644 Renci.SshNet/Compression/v11/ZOutputStream.cs
create mode 100644 Renci.SshNet/Compression/v11/ZStream.cs
create mode 100644 Renci.SshNet/Compression/v11/Zlib.cs
create mode 100644 Renci.SshNet/Compression/v11/ZlibOpenSsh.cs
create mode 100644 Renci.SshNet/Compression/v11/ZlibStream.cs
create mode 100644 Renci.SshNet/Compression/v12/Adler32.cs
create mode 100644 Renci.SshNet/Compression/v12/CompressionMode.cs
create mode 100644 Renci.SshNet/Compression/v12/Compressor.cs
create mode 100644 Renci.SshNet/Compression/v12/Deflate.cs
create mode 100644 Renci.SshNet/Compression/v12/Inflate.cs
create mode 100644 Renci.SshNet/Compression/v12/InflateBlocks.cs
create mode 100644 Renci.SshNet/Compression/v12/InflateCodes.cs
create mode 100644 Renci.SshNet/Compression/v12/InflateTree.cs
create mode 100644 Renci.SshNet/Compression/v12/JZlib.cs
create mode 100644 Renci.SshNet/Compression/v12/StaticTree.cs
create mode 100644 Renci.SshNet/Compression/v12/Tree.cs
create mode 100644 Renci.SshNet/Compression/v12/ZInputStream.cs
create mode 100644 Renci.SshNet/Compression/v12/ZOutputStream.cs
create mode 100644 Renci.SshNet/Compression/v12/ZStream.cs
create mode 100644 Renci.SshNet/Compression/v12/Zlib.cs
create mode 100644 Renci.SshNet/Compression/v12/ZlibOpenSsh.cs
create mode 100644 Renci.SshNet/Compression/v12/ZlibStream.cs
create mode 100644 Renci.SshNet/Compression/v13/Adler32.cs
create mode 100644 Renci.SshNet/Compression/v13/CompressionMode.cs
create mode 100644 Renci.SshNet/Compression/v13/Compressor.cs
create mode 100644 Renci.SshNet/Compression/v13/Deflate.cs
create mode 100644 Renci.SshNet/Compression/v13/Inflate.cs
create mode 100644 Renci.SshNet/Compression/v13/InflateBlocks.cs
create mode 100644 Renci.SshNet/Compression/v13/InflateCodes.cs
create mode 100644 Renci.SshNet/Compression/v13/InflateTree.cs
create mode 100644 Renci.SshNet/Compression/v13/JZlib.cs
create mode 100644 Renci.SshNet/Compression/v13/StaticTree.cs
create mode 100644 Renci.SshNet/Compression/v13/Tree.cs
create mode 100644 Renci.SshNet/Compression/v13/ZInputStream.cs
create mode 100644 Renci.SshNet/Compression/v13/ZOutputStream.cs
create mode 100644 Renci.SshNet/Compression/v13/ZStream.cs
create mode 100644 Renci.SshNet/Compression/v13/Zlib.cs
create mode 100644 Renci.SshNet/Compression/v13/ZlibOpenSsh.cs
create mode 100644 Renci.SshNet/Compression/v13/ZlibStream.cs
create mode 100644 Renci.SshNet/Compression/v9/Adler32.cs
create mode 100644 Renci.SshNet/Compression/v9/CompressionMode.cs
create mode 100644 Renci.SshNet/Compression/v9/Compressor.cs
create mode 100644 Renci.SshNet/Compression/v9/Deflate.cs
create mode 100644 Renci.SshNet/Compression/v9/Inflate.cs
create mode 100644 Renci.SshNet/Compression/v9/InflateBlocks.cs
create mode 100644 Renci.SshNet/Compression/v9/InflateCodes.cs
create mode 100644 Renci.SshNet/Compression/v9/InflateTree.cs
create mode 100644 Renci.SshNet/Compression/v9/JZlib.cs
create mode 100644 Renci.SshNet/Compression/v9/StaticTree.cs
create mode 100644 Renci.SshNet/Compression/v9/Tree.cs
create mode 100644 Renci.SshNet/Compression/v9/ZInputStream.cs
create mode 100644 Renci.SshNet/Compression/v9/ZOutputStream.cs
create mode 100644 Renci.SshNet/Compression/v9/ZStream.cs
create mode 100644 Renci.SshNet/Compression/v9/Zlib.cs
create mode 100644 Renci.SshNet/Compression/v9/ZlibOpenSsh.cs
create mode 100644 Renci.SshNet/Compression/v9/ZlibStream.cs
create mode 100644 Renci.SshNet/Compression/{B60A61FD-33DF-43A1-B48C-A8E3DB53FA13}.tmp
delete mode 100644 Renci.SshNet/Documentation/Content/About.aml
delete mode 100644 Renci.SshNet/Documentation/Content/Guide/Guide.Command.Asynchronous.aml
delete mode 100644 Renci.SshNet/Documentation/Content/Guide/Guide.Command.Error.aml
delete mode 100644 Renci.SshNet/Documentation/Content/Guide/Guide.Command.Multitasking.aml
delete mode 100644 Renci.SshNet/Documentation/Content/Guide/Guide.Command.StatusCode.aml
delete mode 100644 Renci.SshNet/Documentation/Content/Guide/Guide.Command.Timeout.aml
delete mode 100644 Renci.SshNet/Documentation/Content/Guide/Guide.Command.aml
delete mode 100644 Renci.SshNet/Documentation/Content/Guide/Guide.Connection.ChangePassword.aml
delete mode 100644 Renci.SshNet/Documentation/Content/Guide/Guide.Connection.Interactive.aml
delete mode 100644 Renci.SshNet/Documentation/Content/Guide/Guide.Connection.Password.aml
delete mode 100644 Renci.SshNet/Documentation/Content/Guide/Guide.Connection.PrivateKey.aml
delete mode 100644 Renci.SshNet/Documentation/Content/Guide/Guide.Connection.Prompt.aml
delete mode 100644 Renci.SshNet/Documentation/Content/Guide/Guide.Connection.Timeout.aml
delete mode 100644 Renci.SshNet/Documentation/Content/Guide/Guide.Connection.aml
delete mode 100644 Renci.SshNet/Documentation/Content/Guide/Guide.PortForward.Local.aml
delete mode 100644 Renci.SshNet/Documentation/Content/Guide/Guide.PortForward.Remote.aml
delete mode 100644 Renci.SshNet/Documentation/Content/Guide/Guide.PortForward.aml
delete mode 100644 Renci.SshNet/Documentation/Content/Guide/Guide.SFtp.aml
delete mode 100644 Renci.SshNet/Documentation/Content/Guide/Guide.aml
delete mode 100644 Renci.SshNet/Documentation/Content/HowTo.Connect.aml
delete mode 100644 Renci.SshNet/Documentation/Content/Reference.aml
delete mode 100644 Renci.SshNet/Documentation/Renci.SshClient.content
delete mode 100644 Renci.SshNet/Documentation/SshClient.shfbproj
create mode 100644 Renci.SshNet/ExpectAction.cs
create mode 100644 Renci.SshNet/ExpectAsyncResult.cs
create mode 100644 Renci.SshNet/ForwardedPortDynamic.NET.cs
create mode 100644 Renci.SshNet/ForwardedPortDynamic.NET40.cs
create mode 100644 Renci.SshNet/ForwardedPortDynamic.cs
create mode 100644 Renci.SshNet/ForwardedPortLocal.NET.cs
create mode 100644 Renci.SshNet/ForwardedPortRemote.NET.cs
create mode 100644 Renci.SshNet/HashInfo.cs
create mode 100644 Renci.SshNet/KeyboardInteractiveAuthenticationMethod.NET40.cs
create mode 100644 Renci.SshNet/KeyboardInteractiveAuthenticationMethod.cs
create mode 100644 Renci.SshNet/Messages/Connection/ChannelRequest/BreakRequestInfo.cs
create mode 100644 Renci.SshNet/Messages/Transport/KeyExchangeEcdhInitMessage.cs
create mode 100644 Renci.SshNet/Messages/Transport/KeyExchangeEcdhReplyMessage.cs
create mode 100644 Renci.SshNet/NetConfClient.cs
create mode 100644 Renci.SshNet/Netconf/NetConfSession.cs
create mode 100644 Renci.SshNet/NoneAuthenticationMethod.cs
create mode 100644 Renci.SshNet/PasswordAuthenticationMethod.NET40.cs
create mode 100644 Renci.SshNet/PasswordAuthenticationMethod.cs
create mode 100644 Renci.SshNet/PrivateKeyAuthenticationMethod.cs
create mode 100644 Renci.SshNet/ProxyTypes.cs
create mode 100644 Renci.SshNet/ScpClient.NET.cs
create mode 100644 Renci.SshNet/ScpClient.cs
create mode 100644 Renci.SshNet/Security/Cryptography/Ciphers/Paddings/PKCS5Padding.cs
create mode 100644 Renci.SshNet/Security/Cryptography/Hashes/RIPEMD160Hash.cs
create mode 100644 Renci.SshNet/Security/Cryptography/Hashes/SHA2HashBase.cs
create mode 100644 Renci.SshNet/Security/Cryptography/Hashes/SHA384Hash.cs
create mode 100644 Renci.SshNet/Security/Cryptography/Hashes/SHA512Hash.cs
create mode 100644 Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupSha1.cs
create mode 100644 Renci.SshNet/Security/KeyExchangeEllipticCurveDiffieHellman.cs
delete mode 100644 Renci.SshNet/Sftp/OpenSshFilesytemInformation.cs
create mode 100644 Renci.SshNet/Sftp/Requests/ExtendedRequests/FStatVfsRequest.cs
create mode 100644 Renci.SshNet/Sftp/Requests/ExtendedRequests/HardLinkRequest.cs
create mode 100644 Renci.SshNet/Sftp/Requests/ExtendedRequests/PosixRenameRequest.cs
create mode 100644 Renci.SshNet/Sftp/Requests/ExtendedRequests/StatVfsRequest.cs
rename Renci.SshNet/Sftp/Requests/{OpenSshPosixRenameRequest.cs => PosixRenameRequest.cs} (61%)
create mode 100644 Renci.SshNet/Sftp/Requests/SftpBlockRequest.cs
create mode 100644 Renci.SshNet/Sftp/Requests/SftpExtendedRequest.cs
create mode 100644 Renci.SshNet/Sftp/Requests/SftpLinkRequest.cs
create mode 100644 Renci.SshNet/Sftp/Requests/SftpUnblockRequest.cs
rename Renci.SshNet/Sftp/Requests/{OpenSshStatVfsRequest.cs => StatVfsRequest.cs} (57%)
create mode 100644 Renci.SshNet/Sftp/Responses/ExtendedReplies/ExtendedReplyInfo.cs
create mode 100644 Renci.SshNet/Sftp/Responses/ExtendedReplies/StatVfsReplyInfo.cs
delete mode 100644 Renci.SshNet/Sftp/Responses/OpenSshStatVfsResponse.cs
create mode 100644 Renci.SshNet/Sftp/Responses/StatVfsResponse.cs
create mode 100644 Renci.SshNet/Sftp/SftpFileSystemInformation.cs
create mode 100644 Renci.SshNet/Sftp/SftpSynchronizeDirectoriesAsyncResult.cs
create mode 100644 Renci.SshNet/SftpClient.NET.cs
create mode 100644 Renci.SshNet/ShellStream.NET40.cs
create mode 100644 Renci.SshNet/ShellStream.cs
diff --git a/Renci.SshNet/AuthenticationMethod.cs b/Renci.SshNet/AuthenticationMethod.cs
new file mode 100644
index 0000000..3385d98
--- /dev/null
+++ b/Renci.SshNet/AuthenticationMethod.cs
@@ -0,0 +1,54 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Renci.SshNet.Common;
+
+namespace Renci.SshNet
+{
+ ///
+ /// Base class for all supported authentication methods
+ ///
+ public abstract class AuthenticationMethod
+ {
+ ///
+ /// Gets authentication method name
+ ///
+ public abstract string Name { get; }
+
+ ///
+ /// Gets connection username.
+ ///
+ public string Username { get; private set; }
+
+ ///
+ /// Gets the authentication error message.
+ ///
+ public string ErrorMessage { get; private set; }
+
+ ///
+ /// Gets list of allowed authentications.
+ ///
+ public IEnumerable AllowedAuthentications { get; protected set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The username.
+ /// is whitespace or null.
+ protected AuthenticationMethod(string username)
+ {
+ if (username.IsNullOrWhiteSpace())
+ throw new ArgumentException("username");
+
+ this.Username = username;
+ }
+
+ ///
+ /// Authenticates the specified session.
+ ///
+ /// The session to authenticate.
+ /// Result of authentication process.
+ public abstract AuthenticationResult Authenticate(Session session);
+ }
+}
diff --git a/Renci.SshNet/AuthenticationResult.cs b/Renci.SshNet/AuthenticationResult.cs
new file mode 100644
index 0000000..fb6ba37
--- /dev/null
+++ b/Renci.SshNet/AuthenticationResult.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Renci.SshNet
+{
+ ///
+ /// Represents possible authentication methods results
+ ///
+ public enum AuthenticationResult
+ {
+ ///
+ /// Authentication was successful.
+ ///
+ Success,
+ ///
+ /// Authentication completed with partial success.
+ ///
+ PartialSuccess,
+ ///
+ /// Authentication failed.
+ ///
+ Failure
+ }
+}
diff --git a/Renci.SshNet/BaseClient.cs b/Renci.SshNet/BaseClient.cs
index d77a850..104e864 100644
--- a/Renci.SshNet/BaseClient.cs
+++ b/Renci.SshNet/BaseClient.cs
@@ -59,7 +59,7 @@ public TimeSpan KeepAliveInterval
if (this._keepAliveTimer == null)
{
- this._keepAliveTimer = new Timer((state) =>
+ this._keepAliveTimer = new Timer((state) =>
{
this.SendKeepAlive();
});
@@ -72,8 +72,19 @@ public TimeSpan KeepAliveInterval
///
/// Occurs when an error occurred.
///
+ ///
+ ///
+ ///
public event EventHandler ErrorOccurred;
+ ///
+ /// Occurs when host key received.
+ ///
+ ///
+ ///
+ ///
+ public event EventHandler HostKeyReceived;
+
///
/// Initializes a new instance of the class.
///
@@ -101,8 +112,9 @@ public void Connect()
}
this.Session = new Session(this.ConnectionInfo);
- this.Session.Connect();
+ this.Session.HostKeyReceived += Session_HostKeyReceived;
this.Session.ErrorOccured += Session_ErrorOccured;
+ this.Session.Connect();
this.OnConnected();
}
@@ -117,7 +129,7 @@ public void Disconnect()
this.OnDisconnecting();
- this.Dispose();
+ this.Session.Disconnect();
this.OnDisconnected();
}
@@ -167,22 +179,22 @@ protected virtual void OnDisconnected()
{
}
-
- ///
- /// Ensures that client is connected.
- ///
- /// When client not connected.
- protected void EnsureConnection()
+
+ private void Session_ErrorOccured(object sender, ExceptionEventArgs e)
{
- if (!this.Session.IsConnected)
- throw new SshConnectionException("Client not connected.");
+ var handler = this.ErrorOccurred;
+ if (handler != null)
+ {
+ handler(this, e);
+ }
}
- private void Session_ErrorOccured(object sender, ExceptionEventArgs e)
+ private void Session_HostKeyReceived(object sender, HostKeyEventArgs e)
{
- if (this.ErrorOccurred != null)
+ var handler = this.HostKeyReceived;
+ if (handler != null)
{
- this.ErrorOccurred(this, e);
+ handler(this, e);
}
}
@@ -215,12 +227,14 @@ protected virtual void Dispose(bool disposing)
{
// Dispose managed ResourceMessages.
this.Session.ErrorOccured -= Session_ErrorOccured;
+ this.Session.HostKeyReceived -= Session_HostKeyReceived;
if (this.Session != null)
{
this.Session.Dispose();
this.Session = null;
}
+
if (this._keepAliveTimer != null)
{
this._keepAliveTimer.Dispose();
diff --git a/Renci.SshNet/Channels/Channel.cs b/Renci.SshNet/Channels/Channel.cs
index 09516d9..acf99f0 100644
--- a/Renci.SshNet/Channels/Channel.cs
+++ b/Renci.SshNet/Channels/Channel.cs
@@ -1,4 +1,5 @@
using System;
+using System.Linq;
using System.Threading;
using Renci.SshNet.Common;
using Renci.SshNet.Messages;
@@ -12,14 +13,18 @@ namespace Renci.SshNet.Channels
///
internal abstract class Channel : IDisposable
{
- private EventWaitHandle _channelClosedWaitHandle = new AutoResetEvent(false);
+ private EventWaitHandle _channelClosedWaitHandle = new ManualResetEvent(false);
- private EventWaitHandle _channelWindowAdjustWaitHandle = new AutoResetEvent(false);
+ private EventWaitHandle _channelServerWindowAdjustWaitHandle = new ManualResetEvent(false);
private EventWaitHandle _errorOccuredWaitHandle = new ManualResetEvent(false);
private EventWaitHandle _disconnectedWaitHandle = new ManualResetEvent(false);
+ private object _serverWindowSizeLock = new object();
+
+ private bool _closeMessageSent = false;
+
private uint _initialWindowSize = 0x100000;
private uint _maximumPacketSize = 0x8000;
@@ -196,12 +201,26 @@ internal virtual void Initialize(Session session, uint serverChannelNumber, uint
this._session.Disconnected += Session_Disconnected;
}
+ ///
+ /// Sends the SSH_MSG_CHANNEL_EOF message.
+ ///
+ internal void SendEof()
+ {
+ // Send EOF message first when channel need to be closed
+ this.SendMessage(new ChannelEofMessage(this.RemoteChannelNumber));
+ }
+
+ internal void SendData(byte[] buffer)
+ {
+ this.SendMessage(new ChannelDataMessage(this.RemoteChannelNumber, buffer));
+ }
+
///
/// Closes the channel.
///
public virtual void Close()
{
- this.Dispose();
+ this.Close(true);
}
#region Channel virtual methods
@@ -250,7 +269,11 @@ protected virtual void OnOpenFailure(uint reasonCode, string description, string
/// The bytes to add.
protected virtual void OnWindowAdjust(uint bytesToAdd)
{
- this.ServerWindowSize += bytesToAdd;
+ lock (this._serverWindowSizeLock)
+ {
+ this.ServerWindowSize += bytesToAdd;
+ }
+ this._channelServerWindowAdjustWaitHandle.Set();
}
///
@@ -298,24 +321,8 @@ protected virtual void OnEof()
///
protected virtual void OnClose()
{
- // No more channel messages are allowed after Close message received
- this._session.ChannelOpenReceived -= OnChannelOpen;
- this._session.ChannelOpenConfirmationReceived -= OnChannelOpenConfirmation;
- this._session.ChannelOpenFailureReceived -= OnChannelOpenFailure;
- this._session.ChannelWindowAdjustReceived -= OnChannelWindowAdjust;
- this._session.ChannelDataReceived -= OnChannelData;
- this._session.ChannelExtendedDataReceived -= OnChannelExtendedData;
- this._session.ChannelEofReceived -= OnChannelEof;
- this._session.ChannelCloseReceived -= OnChannelClose;
- this._session.ChannelRequestReceived -= OnChannelRequest;
- this._session.ChannelSuccessReceived -= OnChannelSuccess;
- this._session.ChannelFailureReceived -= OnChannelFailure;
- this._session.ErrorOccured -= Session_ErrorOccured;
- this._session.Disconnected -= Session_Disconnected;
-
- // Send close message to channel to confirm channel closing
- this.SendMessage(new ChannelCloseMessage(this.RemoteChannelNumber));
-
+ this.Close(false);
+
if (this.Closed != null)
{
this.Closed(this, new ChannelEventArgs(this.LocalChannelNumber));
@@ -410,20 +417,36 @@ protected void SendMessage(ChannelCloseMessage message)
/// Sends channel data message to the servers.
///
/// This method takes care of managing the window size.
- /// Channel data message.
- public void SendMessage(ChannelDataMessage message)
+ /// Channel data message.
+ protected void SendMessage(ChannelDataMessage message)
{
// Send channel messages only while channel is open
if (!this.IsOpen)
return;
- if (this.ServerWindowSize < 1)
+ var messageLength = message.Data.Length;
+ do
{
- // Wait for window to be adjust
- this._session.WaitHandle(this._channelWindowAdjustWaitHandle);
- }
+ lock (this._serverWindowSizeLock)
+ {
+ var serverWindowSize = this.ServerWindowSize;
+ if (serverWindowSize < messageLength)
+ {
+ // Wait for window to be big enough for this message
+ this._channelServerWindowAdjustWaitHandle.Reset();
+ }
+ else
+ {
+ this.ServerWindowSize -= (uint)messageLength;
+ break;
+ }
+ }
+
+ // Wait for window to change
+ this.WaitHandle(this._channelServerWindowAdjustWaitHandle);
+
+ } while (true);
- this.ServerWindowSize -= (uint)message.Data.Length;
this._session.SendMessage(message);
}
@@ -438,13 +461,29 @@ protected void SendMessage(ChannelExtendedDataMessage message)
if (!this.IsOpen)
return;
- if (this.ServerWindowSize < 1)
+ var messageLength = message.Data.Length;
+ do
{
- // Wait for window to be adjust
- this._session.WaitHandle(this._channelWindowAdjustWaitHandle);
- }
+ lock (this._serverWindowSizeLock)
+ {
+ var serverWindowSize = this.ServerWindowSize;
+ if (serverWindowSize < messageLength)
+ {
+ // Wait for window to be big enough for this message
+ this._channelServerWindowAdjustWaitHandle.Reset();
+ }
+ else
+ {
+ this.ServerWindowSize -= (uint)messageLength;
+ break;
+ }
+ }
+
+ // Wait for window to change
+ this.WaitHandle(this._channelServerWindowAdjustWaitHandle);
+
+ } while (true);
- this.ServerWindowSize -= (uint)message.Data.Length;
this._session.SendMessage(message);
}
@@ -457,13 +496,56 @@ protected void WaitHandle(WaitHandle waitHandle)
this._session.WaitHandle(waitHandle);
}
+ protected virtual void Close(bool wait)
+ {
+ // Send message to close the channel on the server
+ // Ignore sending close message when client not connected
+ if (!_closeMessageSent && this.IsConnected)
+ {
+ lock (this)
+ {
+ if (!_closeMessageSent)
+ {
+ this.SendMessage(new ChannelCloseMessage(this.RemoteChannelNumber));
+ this._closeMessageSent = true;
+ }
+ }
+ }
+
+ // Wait for channel to be closed
+ if (wait)
+ {
+ this._session.WaitHandle(this._channelClosedWaitHandle);
+ }
+ }
+
+ protected virtual void OnDisconnected()
+ {
+ }
+
+ protected virtual void OnErrorOccured(Exception exp)
+ {
+ }
+
private void Session_Disconnected(object sender, EventArgs e)
{
+ this.OnDisconnected();
+
+ // If objected is disposed or being disposed don't handle this event
+ if (this._isDisposed)
+ return;
+
this._disconnectedWaitHandle.Set();
}
private void Session_ErrorOccured(object sender, ExceptionEventArgs e)
{
+ this.OnErrorOccured(e.Exception);
+
+ // If objected is disposed or being disposed don't handle this event
+ if (this._isDisposed)
+ return;
+
this._errorOccuredWaitHandle.Set();
}
@@ -498,8 +580,6 @@ private void OnChannelWindowAdjust(object sender, MessageEventArgs
public void Dispose()
{
- Dispose(true);
+ this.Dispose(true);
GC.SuppressFinalize(this);
}
@@ -608,7 +688,7 @@ public void Dispose()
///
/// true to release both managed and unmanaged resources; false to release only unmanaged resources.
protected virtual void Dispose(bool disposing)
- {
+ {
// Check to see if Dispose has already been called.
if (!this._isDisposed)
{
@@ -616,14 +696,7 @@ protected virtual void Dispose(bool disposing)
// and unmanaged resources.
if (disposing)
{
- // Send EOF message first when channel need to be closed
- this.SendMessage(new ChannelEofMessage(this.RemoteChannelNumber));
-
- // Send message to close the channel on the server
- this.SendMessage(new ChannelCloseMessage(this.RemoteChannelNumber));
-
- // Wait for channel to be closed
- this._session.WaitHandle(this._channelClosedWaitHandle);
+ this.Close(false);
// Dispose managed resources.
if (this._channelClosedWaitHandle != null)
@@ -631,10 +704,10 @@ protected virtual void Dispose(bool disposing)
this._channelClosedWaitHandle.Dispose();
this._channelClosedWaitHandle = null;
}
- if (this._channelWindowAdjustWaitHandle != null)
+ if (this._channelServerWindowAdjustWaitHandle != null)
{
- this._channelWindowAdjustWaitHandle.Dispose();
- this._channelWindowAdjustWaitHandle = null;
+ this._channelServerWindowAdjustWaitHandle.Dispose();
+ this._channelServerWindowAdjustWaitHandle = null;
}
if (this._errorOccuredWaitHandle != null)
{
@@ -665,7 +738,7 @@ protected virtual void Dispose(bool disposing)
// Note disposing has been done.
- _isDisposed = true;
+ this._isDisposed = true;
}
}
@@ -678,7 +751,7 @@ protected virtual void Dispose(bool disposing)
// Do not re-create Dispose clean-up code here.
// Calling Dispose(false) is optimal in terms of
// readability and maintainability.
- Dispose(false);
+ this.Dispose(false);
}
#endregion
diff --git a/Renci.SshNet/Channels/ChannelDirectTcpip.NET40.cs b/Renci.SshNet/Channels/ChannelDirectTcpip.NET40.cs
index f7415b4..9bf7e24 100644
--- a/Renci.SshNet/Channels/ChannelDirectTcpip.NET40.cs
+++ b/Renci.SshNet/Channels/ChannelDirectTcpip.NET40.cs
@@ -1,6 +1,7 @@
using System.Threading.Tasks;
using System;
using System.Net.Sockets;
+using System.Threading;
namespace Renci.SshNet.Channels
{
@@ -11,7 +12,7 @@ internal partial class ChannelDirectTcpip
{
partial void ExecuteThread(Action action)
{
- Task.Factory.StartNew(action, TaskCreationOptions.LongRunning);
+ ThreadPool.QueueUserWorkItem((o) => { action(); });
}
partial void InternalSocketReceive(byte[] buffer, ref int read)
diff --git a/Renci.SshNet/Channels/ChannelDirectTcpip.cs b/Renci.SshNet/Channels/ChannelDirectTcpip.cs
index 9aeb457..6154119 100644
--- a/Renci.SshNet/Channels/ChannelDirectTcpip.cs
+++ b/Renci.SshNet/Channels/ChannelDirectTcpip.cs
@@ -41,18 +41,12 @@ public ChannelDirectTcpip()
}
- ///
- /// Binds channel to specified remote host.
- ///
- /// The remote host.
- /// The port.
- /// The socket.
- public void Bind(string remoteHost, uint port, Socket socket)
+ public void Open(string remoteHost, uint port, Socket socket)
{
this._socket = socket;
IPEndPoint ep = socket.RemoteEndPoint as IPEndPoint;
-
+
if (!this.IsConnected)
{
@@ -65,78 +59,93 @@ public void Bind(string remoteHost, uint port, Socket socket)
// Wait for channel to open
this.WaitHandle(this._channelOpen);
+ }
- // Start reading data from the port and send to channel
- EventWaitHandle readerTaskError = new AutoResetEvent(false);
+ ///
+ /// Binds channel to remote host.
+ ///
+ public void Bind()
+ {
+ // Cannot bind if channel is not open
+ if (!this.IsOpen)
+ return;
- var readerTaskCompleted = new ManualResetEvent(false);
+ // Start reading data from the port and send to channel
Exception exception = null;
- this.ExecuteThread(() =>
+ try
{
- try
- {
- var buffer = new byte[this.PacketSize - 9];
+ var buffer = new byte[this.PacketSize - 9];
- while (this._socket.Connected || this.IsConnected)
+ while (this._socket != null && this._socket.CanRead())
+ {
+ try
{
- try
+ var read = 0;
+ this.InternalSocketReceive(buffer, ref read);
+ if (read > 0)
{
-
- var read = 0;
- this.InternalSocketReceive(buffer, ref read);
- if (read > 0)
- {
- this.SendMessage(new ChannelDataMessage(this.RemoteChannelNumber, buffer.Take(read).ToArray()));
- }
- else
- {
- break;
- }
+ this.SendMessage(new ChannelDataMessage(this.RemoteChannelNumber, buffer.Take(read).ToArray()));
}
- catch (SocketException exp)
+ else
{
- if (exp.SocketErrorCode == SocketError.WouldBlock ||
- exp.SocketErrorCode == SocketError.IOPending ||
- exp.SocketErrorCode == SocketError.NoBufferSpaceAvailable)
- {
- // socket buffer is probably empty, wait and try again
- Thread.Sleep(30);
- }
- else if (exp.SocketErrorCode == SocketError.ConnectionAborted)
- {
- break;
- }
- else
- throw; // throw any other error
+ break;
}
}
+ catch (SocketException exp)
+ {
+ if (exp.SocketErrorCode == SocketError.WouldBlock ||
+ exp.SocketErrorCode == SocketError.IOPending ||
+ exp.SocketErrorCode == SocketError.NoBufferSpaceAvailable)
+ {
+ // socket buffer is probably empty, wait and try again
+ Thread.Sleep(30);
+ }
+ else if (exp.SocketErrorCode == SocketError.ConnectionAborted || exp.SocketErrorCode == SocketError.ConnectionReset)
+ {
+ break;
+ }
+ else
+ throw; // throw any other error
+ }
}
- catch (Exception exp)
- {
- readerTaskError.Set();
- exception = exp;
- }
- finally
- {
- readerTaskCompleted.Set();
- }
- });
+ }
+ catch (Exception exp)
+ {
+ exception = exp;
+ }
// Channel was open and we MUST receive EOF notification,
// data transfer can take longer then connection specified timeout
- System.Threading.WaitHandle.WaitAny(new WaitHandle[] { this._channelEof, readerTaskError });
-
- this._socket.Dispose();
- this._socket = null;
+ // If listener thread is finished then socket was closed
+ System.Threading.WaitHandle.WaitAny(new WaitHandle[] { this._channelEof });
- // Wait for task to finish and will throw any errors if any
- readerTaskCompleted.WaitOne();
+ // Close socket if still open
+ if (this._socket != null)
+ {
+ this._socket.Dispose();
+ this._socket = null;
+ }
if (exception != null)
throw exception;
}
+ public override void Close()
+ {
+ // Close socket if still open
+ if (this._socket != null)
+ {
+ this._socket.Dispose();
+ this._socket = null;
+ }
+
+ // Send EOF message first when channel need to be closed
+ this.SendMessage(new ChannelEofMessage(this.RemoteChannelNumber));
+
+ base.Close();
+ }
+
///
/// Called when channel data is received.
///
@@ -161,6 +170,13 @@ protected override void OnOpenConfirmation(uint remoteChannelNumber, uint initia
this._channelOpen.Set();
}
+ protected override void OnOpenFailure(uint reasonCode, string description, string language)
+ {
+ base.OnOpenFailure(reasonCode, description, language);
+
+ this._channelOpen.Set();
+ }
+
///
/// Called when channel has no more data to receive.
///
@@ -171,6 +187,29 @@ protected override void OnEof()
this._channelEof.Set();
}
+ protected override void OnClose()
+ {
+ base.OnClose();
+
+ this._channelEof.Set();
+ }
+
+ protected override void OnErrorOccured(Exception exp)
+ {
+ base.OnErrorOccured(exp);
+
+ // If error occured, no more data can be received
+ this._channelEof.Set();
+ }
+
+ protected override void OnDisconnected()
+ {
+ base.OnDisconnected();
+
+ // If disconnected, no more data can be received
+ this._channelEof.Set();
+ }
+
partial void ExecuteThread(Action action);
partial void InternalSocketReceive(byte[] buffer, ref int read);
diff --git a/Renci.SshNet/Channels/ChannelForwardedTcpip.NET40.cs b/Renci.SshNet/Channels/ChannelForwardedTcpip.NET40.cs
index 1545927..35060b8 100644
--- a/Renci.SshNet/Channels/ChannelForwardedTcpip.NET40.cs
+++ b/Renci.SshNet/Channels/ChannelForwardedTcpip.NET40.cs
@@ -13,9 +13,9 @@ namespace Renci.SshNet.Channels
///
internal partial class ChannelForwardedTcpip : Channel
{
- partial void OpenSocket(string connectedHost, uint connectedPort)
+ partial void OpenSocket(IPAddress connectedHost, uint connectedPort)
{
- var ep = new IPEndPoint(Dns.GetHostEntry(connectedHost).AddressList[0], (int)connectedPort);
+ var ep = new IPEndPoint(connectedHost, (int)connectedPort);
this._socket = new Socket(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
this._socket.Connect(ep);
this._socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.NoDelay, 1);
diff --git a/Renci.SshNet/Channels/ChannelForwardedTcpip.cs b/Renci.SshNet/Channels/ChannelForwardedTcpip.cs
index 4f1d538..ad7c4be 100644
--- a/Renci.SshNet/Channels/ChannelForwardedTcpip.cs
+++ b/Renci.SshNet/Channels/ChannelForwardedTcpip.cs
@@ -40,7 +40,7 @@ public ChannelForwardedTcpip()
///
/// The connected host.
/// The connected port.
- public void Bind(string connectedHost, uint connectedPort)
+ public void Bind(IPAddress connectedHost, uint connectedPort)
{
byte[] buffer = null;
@@ -71,8 +71,8 @@ public void Bind(string connectedHost, uint connectedPort)
}
// Start reading data from the port and send to channel
- while (this._socket.Connected || this.IsConnected)
- {
+ while (this._socket != null && this._socket.CanRead())
+ {
try
{
int read = 0;
@@ -106,12 +106,18 @@ public void Bind(string connectedHost, uint connectedPort)
}
}
- this.SendMessage(new ChannelEofMessage(this.RemoteChannelNumber));
-
this.Close();
}
- partial void OpenSocket(string connectedHost, uint connectedPort);
+ partial void OpenSocket(IPAddress connectedHost, uint connectedPort);
+
+ public override void Close()
+ {
+ // Send EOF message first when channel need to be closed
+ this.SendMessage(new ChannelEofMessage(this.RemoteChannelNumber));
+
+ base.Close();
+ }
///
/// Called when channel data is received.
diff --git a/Renci.SshNet/Channels/ChannelSession.cs b/Renci.SshNet/Channels/ChannelSession.cs
index bfa4a3f..0946725 100644
--- a/Renci.SshNet/Channels/ChannelSession.cs
+++ b/Renci.SshNet/Channels/ChannelSession.cs
@@ -3,6 +3,8 @@
using Renci.SshNet.Common;
using Renci.SshNet.Messages.Connection;
using System.Globalization;
+using System.Collections.Generic;
+using System.Text;
namespace Renci.SshNet.Channels
{
@@ -80,8 +82,6 @@ protected override void OnOpenFailure(uint reasonCode, string description, strin
{
this._failedOpenAttempts++;
- Debug.WriteLine(string.Format(CultureInfo.CurrentCulture, "Local channel: {0} attempts: {1}.", this.LocalChannelNumber, this._failedOpenAttempts));
-
this.SessionSemaphore.Release();
this._channelOpenResponseWaitHandle.Set();
@@ -101,6 +101,16 @@ protected override void OnClose()
this.SessionSemaphore.Release();
}
+ protected override void Close(bool wait)
+ {
+ base.Close(wait);
+
+ if (!wait)
+ {
+ this.SessionSemaphore.Release();
+ }
+ }
+
///
/// Sends the pseudo terminal request.
///
@@ -109,15 +119,17 @@ protected override void OnClose()
/// The rows.
/// The width.
/// The height.
- /// The terminal mode.
- /// true if request was successful; otherwise false.
- public bool SendPseudoTerminalRequest(string environmentVariable, uint columns, uint rows, uint width, uint height, string terminalMode)
+ /// The terminal mode values.
+ ///
+ /// true if request was successful; otherwise false.
+ ///
+ public bool SendPseudoTerminalRequest(string environmentVariable, uint columns, uint rows, uint width, uint height, IDictionary terminalModeValues)
{
this._channelRequestResponse.Reset();
- this.SendMessage(new ChannelRequestMessage(this.RemoteChannelNumber, new PseudoTerminalRequestInfo(environmentVariable, columns, rows, width, height, terminalMode)));
-
- this._channelRequestResponse.WaitOne();
+ this.SendMessage(new ChannelRequestMessage(this.RemoteChannelNumber, new PseudoTerminalRequestInfo(environmentVariable, columns, rows, width, height, terminalModeValues)));
+
+ this.WaitHandle(this._channelRequestResponse);
return this._channelRequestSucces;
}
@@ -136,7 +148,7 @@ public bool SendX11ForwardingRequest(bool isSingleConnection, string protocol, b
this.SendMessage(new ChannelRequestMessage(this.RemoteChannelNumber, new X11ForwardingRequestInfo(isSingleConnection, protocol, cookie, screenNumber)));
- this._channelRequestResponse.WaitOne();
+ this.WaitHandle(this._channelRequestResponse);
return this._channelRequestSucces;
}
@@ -153,7 +165,7 @@ public bool SendEnvironmentVariableRequest(string variableName, string variableV
this.SendMessage(new ChannelRequestMessage(this.RemoteChannelNumber, new EnvironmentVariableRequestInfo(variableName, variableValue)));
- this._channelRequestResponse.WaitOne();
+ this.WaitHandle(this._channelRequestResponse);
return this._channelRequestSucces;
}
@@ -168,7 +180,7 @@ public bool SendShellRequest()
this.SendMessage(new ChannelRequestMessage(this.RemoteChannelNumber, new ShellRequestInfo()));
- this._channelRequestResponse.WaitOne();
+ this.WaitHandle(this._channelRequestResponse);
return this._channelRequestSucces;
}
@@ -182,9 +194,25 @@ public bool SendExecRequest(string command)
{
this._channelRequestResponse.Reset();
- this.SendMessage(new ChannelRequestMessage(this.RemoteChannelNumber, new ExecRequestInfo(command)));
+ this.SendMessage(new ChannelRequestMessage(this.RemoteChannelNumber, new ExecRequestInfo(command, this.ConnectionInfo.Encoding)));
- this._channelRequestResponse.WaitOne();
+ this.WaitHandle(this._channelRequestResponse);
+
+ return this._channelRequestSucces;
+ }
+
+ ///
+ /// Sends the exec request.
+ ///
+ /// Length of the break.
+ /// true if request was successful; otherwise false.
+ public bool SendBreakRequest(uint breakLength)
+ {
+ this._channelRequestResponse.Reset();
+
+ this.SendMessage(new ChannelRequestMessage(this.RemoteChannelNumber, new BreakRequestInfo(breakLength)));
+
+ this.WaitHandle(this._channelRequestResponse);
return this._channelRequestSucces;
}
@@ -200,7 +228,7 @@ public bool SendSubsystemRequest(string subsystem)
this.SendMessage(new ChannelRequestMessage(this.RemoteChannelNumber, new SubsystemRequestInfo(subsystem)));
- this._channelRequestResponse.WaitOne();
+ this.WaitHandle(this._channelRequestResponse);
return this._channelRequestSucces;
}
@@ -281,7 +309,7 @@ public bool SendEndOfWriteRequest()
this.SendMessage(new ChannelRequestMessage(this.RemoteChannelNumber, new EndOfWriteRequestInfo()));
- this._channelRequestResponse.WaitOne();
+ this.WaitHandle(this._channelRequestResponse);
return this._channelRequestSucces;
}
@@ -296,12 +324,11 @@ public bool SendKeepAliveRequest()
this.SendMessage(new ChannelRequestMessage(this.RemoteChannelNumber, new KeepAliveRequestInfo()));
- this._channelRequestResponse.WaitOne();
+ this.WaitHandle(this._channelRequestResponse);
return this._channelRequestSucces;
}
-
///
/// Called when channel request was successful
///
@@ -356,9 +383,5 @@ protected override void Dispose(bool disposing)
base.Dispose(disposing);
}
-
-
-
-
}
}
diff --git a/Renci.SshNet/CipherInfo.cs b/Renci.SshNet/CipherInfo.cs
index 4cea1e0..4c0ffff 100644
--- a/Renci.SshNet/CipherInfo.cs
+++ b/Renci.SshNet/CipherInfo.cs
@@ -22,14 +22,14 @@ public class CipherInfo
///
/// Gets the cipher.
///
- public Func Cipher { get; private set; }
+ public Func Cipher { get; private set; }
///
/// Initializes a new instance of the class.
///
/// Size of the key.
/// The cipher.
- public CipherInfo(int keySize, Func cipher)
+ public CipherInfo(int keySize, Func cipher)
{
this.KeySize = keySize;
this.Cipher = (key, iv) => (cipher(key.Take(this.KeySize / 8).ToArray(), iv));
diff --git a/Renci.SshNet/Common/ASCIIEncoding.cs b/Renci.SshNet/Common/ASCIIEncoding.cs
new file mode 100644
index 0000000..daae60b
--- /dev/null
+++ b/Renci.SshNet/Common/ASCIIEncoding.cs
@@ -0,0 +1,189 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Renci.SshNet.Common
+{
+ ///
+ /// Implementation of ASCII Encoding
+ ///
+ public class ASCIIEncoding : Encoding
+ {
+ private readonly char _fallbackChar;
+
+ private static char[] _byteToChar;
+
+ static ASCIIEncoding()
+ {
+ if (_byteToChar == null)
+ {
+ _byteToChar = new char[128];
+ var ch = '\0';
+ for (byte i = 0; i < 128; i++)
+ {
+ _byteToChar[i] = ch++;
+ }
+ }
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public ASCIIEncoding()
+ {
+ this._fallbackChar = '?';
+ }
+
+ ///
+ /// Calculates the number of bytes produced by encoding a set of characters from the specified character array.
+ ///
+ /// The character array containing the set of characters to encode.
+ /// The index of the first character to encode.
+ /// The number of characters to encode.
+ ///
+ /// The number of bytes produced by encoding the specified characters.
+ ///
+ ///
+ /// is null.
+ ///
+ ///
+ /// or is less than zero.-or- and do not denote a valid range in .
+ ///
+ /// A fallback occurred (see Understanding Encodings for complete explanation)-and- is set to .
+ public override int GetByteCount(char[] chars, int index, int count)
+ {
+ return count;
+ }
+
+ ///
+ /// Encodes a set of characters from the specified character array into the specified byte array.
+ ///
+ /// The character array containing the set of characters to encode.
+ /// The index of the first character to encode.
+ /// The number of characters to encode.
+ /// The byte array to contain the resulting sequence of bytes.
+ /// The index at which to start writing the resulting sequence of bytes.
+ ///
+ /// The actual number of bytes written into .
+ ///
+ ///
+ /// is null.-or- is null.
+ ///
+ ///
+ /// or or is less than zero.-or- and do not denote a valid range in .-or- is not a valid index in .
+ ///
+ ///
+ /// does not have enough capacity from to the end of the array to accommodate the resulting bytes.
+ ///
+ /// A fallback occurred (see Understanding Encodings for complete explanation)-and- is set to .
+ public override int GetBytes(char[] chars, int charIndex, int charCount, byte[] bytes, int byteIndex)
+ {
+ for (int i = 0; i < charCount && i < chars.Length; i++)
+ {
+ var b = (byte)chars[i + charIndex];
+
+ if (b > 127)
+ b = (byte)this._fallbackChar;
+
+ bytes[i + byteIndex] = b;
+ }
+ return charCount;
+ }
+
+ ///
+ /// Calculates the number of characters produced by decoding a sequence of bytes from the specified byte array.
+ ///
+ /// The byte array containing the sequence of bytes to decode.
+ /// The index of the first byte to decode.
+ /// The number of bytes to decode.
+ ///
+ /// The number of characters produced by decoding the specified sequence of bytes.
+ ///
+ ///
+ /// is null.
+ ///
+ ///
+ /// or is less than zero.-or- and do not denote a valid range in .
+ ///
+ /// A fallback occurred (see Understanding Encodings for complete explanation)-and- is set to .
+ public override int GetCharCount(byte[] bytes, int index, int count)
+ {
+ return count;
+ }
+
+ ///
+ /// Decodes a sequence of bytes from the specified byte array into the specified character array.
+ ///
+ /// The byte array containing the sequence of bytes to decode.
+ /// The index of the first byte to decode.
+ /// The number of bytes to decode.
+ /// The character array to contain the resulting set of characters.
+ /// The index at which to start writing the resulting set of characters.
+ ///
+ /// The actual number of characters written into .
+ ///
+ ///
+ /// is null.-or- is null.
+ ///
+ ///
+ /// or or is less than zero.-or- and do not denote a valid range in .-or- is not a valid index in .
+ ///
+ ///
+ /// does not have enough capacity from to the end of the array to accommodate the resulting characters.
+ ///
+ /// A fallback occurred (see Understanding Encodings for complete explanation)-and- is set to .
+ public override int GetChars(byte[] bytes, int byteIndex, int byteCount, char[] chars, int charIndex)
+ {
+ for (int i = 0; i < byteCount; i++)
+ {
+ var b = bytes[i + byteIndex];
+ char ch;
+
+ if (b > 127)
+ {
+ ch = this._fallbackChar;
+ }
+ else
+ {
+ ch = _byteToChar[b];
+ }
+
+ chars[i + charIndex] = ch;
+ }
+ return byteCount;
+ }
+
+ ///
+ /// Calculates the maximum number of bytes produced by encoding the specified number of characters.
+ ///
+ /// The number of characters to encode.
+ ///
+ /// The maximum number of bytes produced by encoding the specified number of characters.
+ ///
+ ///
+ /// is less than zero.
+ ///
+ /// A fallback occurred (see Understanding Encodings for complete explanation)-and- is set to .
+ public override int GetMaxByteCount(int charCount)
+ {
+ return charCount;
+ }
+
+ ///
+ /// Calculates the maximum number of characters produced by decoding the specified number of bytes.
+ ///
+ /// The number of bytes to decode.
+ ///
+ /// The maximum number of characters produced by decoding the specified number of bytes.
+ ///
+ ///
+ /// is less than zero.
+ ///
+ /// A fallback occurred (see Understanding Encodings for complete explanation)-and- is set to .
+ public override int GetMaxCharCount(int byteCount)
+ {
+ return byteCount;
+ }
+ }
+}
diff --git a/Renci.SshNet/Common/AsyncResult.cs b/Renci.SshNet/Common/AsyncResult.cs
index 919aa53..c28bba2 100644
--- a/Renci.SshNet/Common/AsyncResult.cs
+++ b/Renci.SshNet/Common/AsyncResult.cs
@@ -90,7 +90,7 @@ public void EndInvoke()
// Operation is done: if an exception occurred, throw it
if (this._exception != null)
- throw this._exception;
+ throw new SshException(this._exception.Message, this._exception);
}
#region Implementation of IAsyncResult
@@ -155,6 +155,7 @@ public Boolean IsCompleted
///
/// Base class to encapsulates the results of an asynchronous operation that returns result.
///
+ /// The type of the result.
public abstract class AsyncResult : AsyncResult
{
// Field set when operation completes
@@ -186,7 +187,7 @@ public void SetAsCompleted(TResult result, Boolean completedSynchronously)
///
/// Waits until the asynchronous operation completes, and then returns the value generated by the asynchronous operation.
///
- ///
+ /// Invocation result
new public TResult EndInvoke()
{
base.EndInvoke(); // Wait until operation has completed
diff --git a/Renci.SshNet/Common/AuthenticationPasswordChangeEventArgs.cs b/Renci.SshNet/Common/AuthenticationPasswordChangeEventArgs.cs
index 65cd23b..7b2d1ec 100644
--- a/Renci.SshNet/Common/AuthenticationPasswordChangeEventArgs.cs
+++ b/Renci.SshNet/Common/AuthenticationPasswordChangeEventArgs.cs
@@ -16,7 +16,7 @@ public class AuthenticationPasswordChangeEventArgs : AuthenticationEventArgs
///
/// The new password.
///
- public string NewPassword { get; set; }
+ public byte[] NewPassword { get; set; }
///
/// Initializes a new instance of the class.
diff --git a/Renci.SshNet/Common/BigInteger.cs b/Renci.SshNet/Common/BigInteger.cs
index ffd8d2c..fea8632 100644
--- a/Renci.SshNet/Common/BigInteger.cs
+++ b/Renci.SshNet/Common/BigInteger.cs
@@ -51,6 +51,7 @@
using System.Globalization;
using System.Text;
using System.Threading;
+using System.Security.Cryptography;
/*
Optimization
@@ -69,6 +70,8 @@ namespace Renci.SshNet.Common
///
public struct BigInteger : IComparable, IFormattable, IComparable, IEquatable
{
+ private static RNGCryptoServiceProvider _randomizer = new System.Security.Cryptography.RNGCryptoServiceProvider();
+
private const ulong _BASE = 0x100000000;
private const Int32 _DECIMALSIGNMASK = unchecked((Int32)0x80000000);
private const int _BIAS = 1075;
@@ -1960,6 +1963,19 @@ public int CompareTo(ulong other)
return LongCompare(low, high);
}
+ ///
+ /// Generates random BigInteger number
+ ///
+ /// Length of random number in bits.
+ /// Big random number.
+ public static BigInteger Random(int bitLength)
+ {
+ var bytesArray = new byte[bitLength / 8 + (((bitLength % 8) > 0) ? 1 : 0)];
+ _randomizer.GetBytes(bytesArray);
+ bytesArray[bytesArray.Length - 1] = (byte)(bytesArray[bytesArray.Length - 1] & 0x7F); // Ensure not a negative value
+ return new BigInteger(bytesArray.ToArray());
+ }
+
///
/// Divides one System.Numerics.BigInteger value by another and returns the result.
///
@@ -2312,7 +2328,7 @@ public static BigInteger ModPow(BigInteger value, BigInteger exponent, BigIntege
///
/// The bi.
/// The modulus.
- ///
+ /// Modulus inverted number.
public static BigInteger ModInverse(BigInteger bi, BigInteger modulus)
{
BigInteger a = modulus, b = bi % modulus;
@@ -2383,7 +2399,7 @@ public static BigInteger Negate(BigInteger value)
/// A string that contains a number to convert.
/// A bitwise combination of the enumeration values that specify the permitted format of value.
/// An object that provides culture-specific formatting information about value.
- ///
+ /// Parsed number
public static BigInteger Parse(string value, System.Globalization.NumberStyles style, IFormatProvider provider)
{
Exception ex;
diff --git a/Renci.SshNet/Common/DerData.cs b/Renci.SshNet/Common/DerData.cs
index 70a42e3..6c43cb1 100644
--- a/Renci.SshNet/Common/DerData.cs
+++ b/Renci.SshNet/Common/DerData.cs
@@ -83,7 +83,7 @@ public DerData(byte[] data)
///
/// Encodes written data as DER byte array.
///
- ///
+ /// DER Encoded array.
public byte[] Encode()
{
var length = this._data.Count();
diff --git a/Renci.SshNet/Common/Extensions.NET.cs b/Renci.SshNet/Common/Extensions.NET.cs
new file mode 100644
index 0000000..0a426f7
--- /dev/null
+++ b/Renci.SshNet/Common/Extensions.NET.cs
@@ -0,0 +1,48 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Net.Sockets;
+using System.Text;
+
+namespace Renci.SshNet
+{
+ ///
+ /// Collection of different extension method specific for .NET 4.0
+ ///
+ public static partial class Extensions
+ {
+ ///
+ /// Determines whether [is null or white space] [the specified value].
+ ///
+ /// The value.
+ ///
+ /// true if [is null or white space] [the specified value]; otherwise, false.
+ ///
+ internal static bool IsNullOrWhiteSpace(this string value)
+ {
+ if (string.IsNullOrEmpty(value)) return true;
+
+ return value.All(char.IsWhiteSpace);
+ }
+
+ internal static bool CanRead(this Socket socket)
+ {
+ return socket.Connected && socket.Poll(-1, SelectMode.SelectRead) && socket.Available > 0;
+ }
+
+ internal static bool CanWrite(this Socket socket)
+ {
+ return socket.Connected && socket.Poll(-1, SelectMode.SelectWrite);
+ }
+
+ internal static IPAddress GetIPAddress(this string host)
+ {
+ IPAddress ipAddress;
+ if (!IPAddress.TryParse(host, out ipAddress))
+ ipAddress = Dns.GetHostAddresses(host).First();
+
+ return ipAddress;
+ }
+ }
+}
diff --git a/Renci.SshNet/Common/Extensions.NET40.cs b/Renci.SshNet/Common/Extensions.NET40.cs
deleted file mode 100644
index 1403271..0000000
--- a/Renci.SshNet/Common/Extensions.NET40.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace Renci.SshNet
-{
- ///
- /// Collection of different extension method specific for .NET 4.0
- ///
- public static partial class Extensions
- {
- ///
- /// Indicates whether a specified string is null, empty, or consists only of white-space characters.
- ///
- /// The string to test.
- ///
- /// true if the value parameter is null or System.String.Empty, or if value consists exclusively of white-space characters; otherwise, false.
- ///
- internal static bool IsNullOrWhiteSpace(this string value)
- {
- return string.IsNullOrWhiteSpace(value);
- }
- }
-}
diff --git a/Renci.SshNet/Common/Extensions.cs b/Renci.SshNet/Common/Extensions.cs
index 427e58e..258c1da 100644
--- a/Renci.SshNet/Common/Extensions.cs
+++ b/Renci.SshNet/Common/Extensions.cs
@@ -61,8 +61,8 @@ internal static bool IsEqualTo(this IEnumerable value, IEnumer
}
finally
{
- enumerator1.Dispose();
- enumerator2.Dispose();
+ if (enumerator1 != null) enumerator1.Dispose();
+ if (enumerator2 != null) enumerator2.Dispose();
}
}
}
@@ -79,14 +79,12 @@ internal static bool IsEqualTo(this IEnumerable value, IEnumer
}
#if SILVERLIGHT
-#else
-
+#else
///
/// Prints out
///
/// The bytes.
-
internal static void DebugPrint(this IEnumerable bytes)
{
foreach (var b in bytes)
@@ -101,7 +99,7 @@ internal static void DebugPrint(this IEnumerable bytes)
/// Trims the leading zero from bytes array.
///
/// The data.
- ///
+ /// Data without leading zeros.
internal static IEnumerable TrimLeadingZero(this IEnumerable data)
{
bool leadingZero = true;
@@ -174,30 +172,52 @@ internal static byte[] GetBytes(this Int64 value)
}
#if SILVERLIGHT
- private static Regex _rehost = new Regex(@"^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$|^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$", RegexOptions.IgnoreCase);
+ private static Regex _rehost = new Regex(@"^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$|^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$", RegexOptions.IgnoreCase);
private static Regex _reIPv6 = new Regex(@"^(((?=(?>.*?::)(?!.*::)))(::)?([0-9A-F]{1,4}::?){0,5}|([0-9A-F]{1,4}:){6})(\2([0-9A-F]{1,4}(::?|$)){0,2}|((25[0-5]|(2[0-4]|1\d|[1-9])?\d)(\.|$)){4}|[0-9A-F]{1,4}:[0-9A-F]{1,4})(?.*?::)(?!.*::)))(::)?([0-9A-F]{1,4}::?){0,5}|([0-9A-F]{1,4}:){6})(\2([0-9A-F]{1,4}(::?|$)){0,2}|((25[0-5]|(2[0-4]|1\d|[1-9])?\d)(\.|$)){4}|[0-9A-F]{1,4}:[0-9A-F]{1,4})(?.*?::)(?!.*::)))(::)?([0-9A-F]{1,4}::?){0,5}|([0-9A-F]{1,4}:){6})(\2([0-9A-F]{1,4}(::?|$)){0,2}|((25[0-5]|(2[0-4]|1\d|[1-9])?\d)(\.|$)){4}|[0-9A-F]{1,4}:[0-9A-F]{1,4})(?= IPEndPoint.MinPort && value <= IPEndPoint.MaxPort;
+ if (value < IPEndPoint.MinPort)
+ return false;
+
+ if (value > IPEndPoint.MaxPort)
+ return false;
+ return true;
}
internal static bool IsValidPort(this int value)
{
- return value >= IPEndPoint.MinPort && value <= IPEndPoint.MaxPort;
+ if (value < IPEndPoint.MinPort)
+ return false;
+
+ if (value > IPEndPoint.MaxPort)
+ return false;
+ return true;
}
+
}
}
diff --git a/Renci.SshNet/Common/HostKeyEventArgs.cs b/Renci.SshNet/Common/HostKeyEventArgs.cs
new file mode 100644
index 0000000..8c10615
--- /dev/null
+++ b/Renci.SshNet/Common/HostKeyEventArgs.cs
@@ -0,0 +1,66 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Renci.SshNet.Security.Cryptography;
+using Renci.SshNet.Security;
+
+namespace Renci.SshNet.Common
+{
+ ///
+ /// Provides data for the HostKeyReceived event.
+ ///
+ public class HostKeyEventArgs : EventArgs
+ {
+ ///
+ /// Gets or sets a value indicating whether host key can be trusted.
+ ///
+ ///
+ /// true if host key can be trusted; otherwise, false.
+ ///
+ public bool CanTrust { get; set; }
+
+ ///
+ /// Gets the host key.
+ ///
+ public byte[] HostKey { get; private set; }
+
+ ///
+ /// Gets the host key name.
+ ///
+ public string HostKeyName{ get; private set; }
+
+ ///
+ /// Gets the finger print.
+ ///
+ public byte[] FingerPrint { get; private set; }
+
+ ///
+ /// Gets the length of the key in bits.
+ ///
+ ///
+ /// The length of the key in bits.
+ ///
+ public int KeyLength { get; private set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The host.
+ public HostKeyEventArgs(KeyHostAlgorithm host)
+ {
+ this.CanTrust = true; // Set default value
+
+ this.HostKey = host.Data;
+
+ this.HostKeyName = host.Name;
+
+ this.KeyLength = host.Key.KeyLength;
+
+ using (var md5 = new MD5Hash())
+ {
+ this.FingerPrint = md5.ComputeHash(host.Data);
+ }
+ }
+ }
+}
diff --git a/Renci.SshNet/Common/NetConfServerException.NET40.cs b/Renci.SshNet/Common/NetConfServerException.NET40.cs
new file mode 100644
index 0000000..c723fde
--- /dev/null
+++ b/Renci.SshNet/Common/NetConfServerException.NET40.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Runtime.Serialization;
+
+namespace Renci.SshNet.Common
+{
+ ///
+ /// The exception that is thrown when there is something wrong with the server capabilities.
+ ///
+ [Serializable]
+ public partial class NetConfServerException : SshException
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The that holds the serialized object data about the exception being thrown.
+ /// The that contains contextual information about the source or destination.
+ /// The parameter is null.
+ ///
+ /// The class name is null or is zero (0).
+ protected NetConfServerException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ {
+ }
+ }
+}
diff --git a/Renci.SshNet/Common/NetConfServerException.cs b/Renci.SshNet/Common/NetConfServerException.cs
new file mode 100644
index 0000000..29ff4bd
--- /dev/null
+++ b/Renci.SshNet/Common/NetConfServerException.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Renci.SshNet.Common
+{
+ ///
+ /// The exception that is thrown when there is something wrong with the server capabilities.
+ ///
+ public partial class NetConfServerException : SshException
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public NetConfServerException()
+ {
+
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The message.
+ public NetConfServerException(string message)
+ : base(message)
+ {
+
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The message.
+ /// The inner exception.
+ public NetConfServerException(string message, Exception innerException) :
+ base(message, innerException)
+ {
+ }
+ }
+}
diff --git a/Renci.SshNet/Common/PipeStream.cs b/Renci.SshNet/Common/PipeStream.cs
index 214448c..a542181 100644
--- a/Renci.SshNet/Common/PipeStream.cs
+++ b/Renci.SshNet/Common/PipeStream.cs
@@ -181,7 +181,7 @@ public override int Read(byte[] buffer, int offset, int count)
Monitor.Wait(this._buffer);
// fill the read buffer
- for (; readLength < count && Length > 0; readLength++)
+ for (; readLength < count && Length > 0 && this._buffer.Count > 0; readLength++)
{
buffer[readLength] = this._buffer.Dequeue();
}
@@ -192,10 +192,10 @@ public override int Read(byte[] buffer, int offset, int count)
}
///
- /// Returns true if there are
+ /// Returns true if there are
///
- ///
- ///
+ /// The count.
+ /// True if data available; otherwisefalse.
private bool ReadAvailable(int count)
{
return (this.Length >= count || this._isFlushed) &&
diff --git a/Renci.SshNet/Common/ProxyException.NET40.cs b/Renci.SshNet/Common/ProxyException.NET40.cs
new file mode 100644
index 0000000..527283c
--- /dev/null
+++ b/Renci.SshNet/Common/ProxyException.NET40.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Runtime.Serialization;
+
+namespace Renci.SshNet.Common
+{
+ [Serializable]
+ public partial class ProxyException : SshException
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The that holds the serialized object data about the exception being thrown.
+ /// The that contains contextual information about the source or destination.
+ /// The parameter is null.
+ ///
+ /// The class name is null or is zero (0).
+ protected ProxyException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ {
+ }
+ }
+
+}
diff --git a/Renci.SshNet/Common/ProxyException.cs b/Renci.SshNet/Common/ProxyException.cs
new file mode 100644
index 0000000..304a051
--- /dev/null
+++ b/Renci.SshNet/Common/ProxyException.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Renci.SshNet.Common
+{
+ ///
+ /// The exception that is thrown when SCP error occurred.
+ ///
+ public partial class ProxyException : SshException
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public ProxyException()
+ {
+
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The message.
+ public ProxyException(string message)
+ : base(message)
+ {
+
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The message.
+ /// The inner exception.
+ public ProxyException(string message, Exception innerException) :
+ base(message, innerException)
+ {
+ }
+ }
+
+}
diff --git a/Renci.SshNet/Common/ScpDownloadEventArgs.cs b/Renci.SshNet/Common/ScpDownloadEventArgs.cs
new file mode 100644
index 0000000..a6abbe8
--- /dev/null
+++ b/Renci.SshNet/Common/ScpDownloadEventArgs.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Renci.SshNet.Common
+{
+ ///
+ /// Provides data for the Downloading event.
+ ///
+ public class ScpDownloadEventArgs : EventArgs
+ {
+ ///
+ /// Gets the downloaded filename.
+ ///
+ public string Filename { get; private set; }
+
+ ///
+ /// Gets the downloaded file size.
+ ///
+ public long Size { get; private set; }
+
+ ///
+ /// Gets number of downloaded bytes so far.
+ ///
+ public long Downloaded { get; private set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The downloaded filename.
+ /// The downloaded file size.
+ /// The number of downloaded bytes so far.
+ public ScpDownloadEventArgs(string filename, long size, long downloaded)
+ {
+ this.Filename = filename;
+ this.Size = size;
+ this.Downloaded = downloaded;
+ }
+ }
+}
diff --git a/Renci.SshNet/Common/ScpException.NET40.cs b/Renci.SshNet/Common/ScpException.NET40.cs
new file mode 100644
index 0000000..3b05f87
--- /dev/null
+++ b/Renci.SshNet/Common/ScpException.NET40.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Runtime.Serialization;
+
+namespace Renci.SshNet.Common
+{
+ [Serializable]
+ public partial class ScpException : SshException
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The that holds the serialized object data about the exception being thrown.
+ /// The that contains contextual information about the source or destination.
+ /// The parameter is null.
+ ///
+ /// The class name is null or is zero (0).
+ protected ScpException(SerializationInfo info, StreamingContext context)
+ : base(info, context)
+ {
+ }
+ }
+}
diff --git a/Renci.SshNet/Common/ScpException.cs b/Renci.SshNet/Common/ScpException.cs
new file mode 100644
index 0000000..9a5d8b6
--- /dev/null
+++ b/Renci.SshNet/Common/ScpException.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Renci.SshNet.Common
+{
+ ///
+ /// The exception that is thrown when SCP error occurred.
+ ///
+ public partial class ScpException : SshException
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public ScpException()
+ {
+
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The message.
+ public ScpException(string message)
+ : base(message)
+ {
+
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The message.
+ /// The inner exception.
+ public ScpException(string message, Exception innerException) :
+ base(message, innerException)
+ {
+ }
+ }
+}
diff --git a/Renci.SshNet/Common/ScpUploadEventArgs.cs b/Renci.SshNet/Common/ScpUploadEventArgs.cs
new file mode 100644
index 0000000..5772525
--- /dev/null
+++ b/Renci.SshNet/Common/ScpUploadEventArgs.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Renci.SshNet.Common
+{
+ ///
+ /// Provides data for the Uploading event.
+ ///
+ public class ScpUploadEventArgs : EventArgs
+ {
+ ///
+ /// Gets the uploaded filename.
+ ///
+ public string Filename { get; private set; }
+
+ ///
+ /// Gets the uploaded file size.
+ ///
+ public long Size { get; private set; }
+
+ ///
+ /// Gets number of uploaded bytes so far.
+ ///
+ public long Uploaded { get; private set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The uploaded filename.
+ /// The the uploaded file size.
+ /// The number of uploaded bytes so far.
+ public ScpUploadEventArgs(string filename, long size, long uploaded)
+ {
+ this.Filename = filename;
+ this.Size = size;
+ this.Uploaded = uploaded;
+ }
+ }
+}
diff --git a/Renci.SshNet/Common/ShellDataEventArgs.cs b/Renci.SshNet/Common/ShellDataEventArgs.cs
new file mode 100644
index 0000000..a4d2689
--- /dev/null
+++ b/Renci.SshNet/Common/ShellDataEventArgs.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Renci.SshNet.Common
+{
+ ///
+ /// Provides data for Shell DataReceived event
+ ///
+ public class ShellDataEventArgs : EventArgs
+ {
+ ///
+ /// Gets the data.
+ ///
+ public byte[] Data { get; private set; }
+
+ ///
+ /// Gets the line data.
+ ///
+ public string Line { get; private set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The data.
+ public ShellDataEventArgs(byte[] data)
+ {
+ this.Data = data;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The line.
+ public ShellDataEventArgs(string line)
+ {
+ this.Line = line;
+ }
+ }
+}
diff --git a/Renci.SshNet/Common/SshData.cs b/Renci.SshNet/Common/SshData.cs
index 6a3de60..cea315a 100644
--- a/Renci.SshNet/Common/SshData.cs
+++ b/Renci.SshNet/Common/SshData.cs
@@ -11,6 +11,14 @@ namespace Renci.SshNet.Common
///
public abstract class SshData
{
+ private static Encoding _ascii = new ASCIIEncoding();
+
+#if SILVERLIGHT
+ private static Encoding _utf8 = Encoding.UTF8;
+#else
+ private static Encoding _utf8 = Encoding.Default;
+#endif
+
///
/// Data byte array that hold message unencrypted data
///
@@ -51,7 +59,7 @@ protected virtual int ZeroReaderIndex
///
/// Gets data bytes array
///
- ///
+ /// Byte array representation of data structure.
public virtual byte[] GetBytes()
{
this._data = new List();
@@ -194,7 +202,7 @@ protected UInt32 ReadUInt32()
protected UInt64 ReadUInt64()
{
var data = this.ReadBytes(8);
- return (uint)(data[0] << 56 | data[1] << 48 | data[2] << 40 | data[3] << 32 | data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7]);
+ return ((ulong)data[0] << 56 | (ulong)data[1] << 48 | (ulong)data[2] << 40 | (ulong)data[3] << 32 | (ulong)data[4] << 24 | (ulong)data[5] << 16 | (ulong)data[6] << 8 | data[7]);
}
///
@@ -207,11 +215,35 @@ protected Int64 ReadInt64()
return (int)(data[0] << 56 | data[1] << 48 | data[2] << 40 | data[3] << 32 | data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7]);
}
+ ///
+ /// Reads next string data type from internal buffer.
+ ///
+ /// string read
+ protected string ReadAsciiString()
+ {
+ var length = this.ReadUInt32();
+
+ if (length > (uint)int.MaxValue)
+ {
+ throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Strings longer than {0} is not supported.", int.MaxValue));
+ }
+ return _ascii.GetString(this.ReadBytes((int)length), 0, (int)length);
+ }
+
///
/// Reads next string data type from internal buffer.
///
/// string read
protected string ReadString()
+ {
+ return this.ReadString(SshData._utf8);
+ }
+
+ ///
+ /// Reads next string data type from internal buffer.
+ ///
+ /// string read
+ protected string ReadString(Encoding encoding)
{
var length = this.ReadUInt32();
@@ -219,9 +251,10 @@ protected string ReadString()
{
throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Strings longer than {0} is not supported.", int.MaxValue));
}
- return Encoding.UTF8.GetString(this.ReadBytes((int)length), 0, (int)length);
+ return encoding.GetString(this.ReadBytes((int)length), 0, (int)length);
}
+
///
/// Reads next string data type from internal buffer.
///
@@ -254,7 +287,7 @@ protected BigInteger ReadBigInt()
///
/// Reads next name-list data type from internal buffer.
///
- ///
+ /// String array or read data..
protected string[] ReadNamesList()
{
var namesList = this.ReadString();
@@ -264,7 +297,7 @@ protected string[] ReadNamesList()
///
/// Reads next extension-pair data type from internal buffer.
///
- ///
+ /// Extensions pair dictionary.
protected IDictionary ReadExtensionPair()
{
Dictionary result = new Dictionary();
@@ -348,12 +381,26 @@ protected void Write(Int64 data)
this.Write(data.GetBytes());
}
+
///
- /// Writes string data into internal buffer.
+ /// Writes string data into internal buffer as ASCII.
+ ///
+ /// string data to write.
+ protected void WriteAscii(string data)
+ {
+ this.Write(data, SshData._ascii);
+ }
+
+ ///
+ /// Writes string data into internal buffer using default encoding.
///
/// string data to write.
- /// String text encoding to use.
/// is null.
+ protected void Write(string data)
+ {
+ this.Write(data, SshData._utf8);
+ }
+
protected void Write(string data, Encoding encoding)
{
if (data == null)
@@ -364,15 +411,6 @@ protected void Write(string data, Encoding encoding)
this.Write(bytes);
}
- ///
- /// Writes string data into internal buffer.
- ///
- /// string data to write.
- protected void Write(string data)
- {
- this.Write(data, Encoding.UTF8);
- }
-
///
/// Writes string data into internal buffer.
///
@@ -404,9 +442,10 @@ protected void Write(BigInteger data)
/// name-list data to write.
protected void Write(string[] data)
{
- this.Write(string.Join(",", data));
+ this.WriteAscii(string.Join(",", data));
}
+
///
/// Writes extension-pair data into internal buffer.
///
@@ -415,8 +454,8 @@ protected void Write(IDictionary data)
{
foreach (var item in data)
{
- this.Write(item.Key);
- this.Write(item.Value);
+ this.WriteAscii(item.Key);
+ this.WriteAscii(item.Value);
}
}
}
diff --git a/Renci.SshNet/Common/TerminalModes.cs b/Renci.SshNet/Common/TerminalModes.cs
new file mode 100644
index 0000000..3afbaa2
--- /dev/null
+++ b/Renci.SshNet/Common/TerminalModes.cs
@@ -0,0 +1,293 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Renci.SshNet.Common
+{
+ ///
+ /// Specifies the initial assignments of the opcode values that are used in the 'encoded terminal modes' valu
+ ///
+ public enum TerminalModes : byte
+ {
+ ///
+ /// Indicates end of options.
+ ///
+ TTY_OP_END = 0,
+
+ ///
+ /// Interrupt character; 255 if none. Similarly for the other characters. Not all of these characters are supported on all systems.
+ ///
+ VINTR = 1,
+
+ ///
+ /// The quit character (sends SIGQUIT signal on POSIX systems).
+ ///
+ VQUIT = 2,
+
+ ///
+ /// Erase the character to left of the cursor.
+ ///
+ VERASE = 3,
+
+ ///
+ /// Kill the current input line.
+ ///
+ VKILL = 4,
+
+ ///
+ /// End-of-file character (sends EOF from the terminal).
+ ///
+ VEOF = 5,
+
+ ///
+ /// End-of-line character in addition to carriage return and/or linefeed.
+ ///
+ VEOL = 6,
+
+ ///
+ /// Additional end-of-line character.
+ ///
+ VEOL2 = 7,
+
+ ///
+ /// Continues paused output (normally control-Q).
+ ///
+ VSTART = 8,
+
+ ///
+ /// Pauses output (normally control-S).
+ ///
+ VSTOP = 9,
+
+ ///
+ /// Suspends the current program.
+ ///
+ VSUSP = 10,
+
+ ///
+ /// Another suspend character.
+ ///
+ VDSUSP = 11,
+
+ ///
+ /// Reprints the current input line.
+ ///
+ VREPRINT = 12,
+
+ ///
+ /// Erases a word left of cursor.
+ ///
+ VWERASE = 13,
+
+ ///
+ /// Enter the next character typed literally, even if it is a special character
+ ///
+ VLNEXT = 14,
+
+ ///
+ /// Character to flush output.
+ ///
+ VFLUSH = 15,
+
+ ///
+ /// Switch to a different shell layer.
+ ///
+ VSWTCH = 16,
+
+ ///
+ /// Prints system status line (load, command, pid, etc).
+ ///
+ VSTATUS = 17,
+
+ ///
+ /// Toggles the flushing of terminal output.
+ ///
+ VDISCARD = 18,
+
+ ///
+ /// The ignore parity flag. The parameter SHOULD be 0 if this flag is FALSE, and 1 if it is TRUE.
+ ///
+ IGNPAR = 30,
+
+ ///
+ /// Mark parity and framing errors.
+ ///
+ PARMRK = 31,
+
+ ///
+ /// Enable checking of parity errors.
+ ///
+ INPCK = 32,
+
+ ///
+ /// Strip 8th bit off characters.
+ ///
+ ISTRIP = 33,
+
+ ///
+ /// Map NL into CR on input.
+ ///
+ INLCR = 34,
+
+ ///
+ /// Ignore CR on input.
+ ///
+ IGNCR = 35,
+
+ ///
+ /// Map CR to NL on input.
+ ///
+ ICRNL = 36,
+
+ ///
+ /// Translate uppercase characters to lowercase.
+ ///
+ IUCLC = 37,
+
+ ///
+ /// Enable output flow control.
+ ///
+ IXON = 38,
+
+ ///
+ /// Any char will restart after stop.
+ ///
+ IXANY = 39,
+
+ ///
+ /// Enable input flow control.
+ ///
+ IXOFF = 40,
+
+ ///
+ /// Ring bell on input queue full.
+ ///
+ IMAXBEL = 41,
+
+ ///
+ /// Enable signals INTR, QUIT, [D]SUSP.
+ ///
+ ISIG = 50,
+
+ ///
+ /// Canonicalize input lines.
+ ///
+ ICANON = 51,
+
+ ///
+ /// Enable input and output of uppercase characters by preceding their lowercase equivalents with "\".
+ ///
+ XCASE = 52,
+
+ ///
+ /// Enable echoing.
+ ///
+ ECHO = 53,
+
+ ///
+ /// Visually erase chars.
+ ///
+ ECHOE = 54,
+
+ ///
+ /// Kill character discards current line.
+ ///
+ ECHOK = 55,
+
+ ///
+ /// Echo NL even if ECHO is off.
+ ///
+ ECHONL = 56,
+
+ ///
+ /// Don't flush after interrupt.
+ ///
+ NOFLSH = 57,
+
+ ///
+ /// Stop background jobs from output.
+ ///
+ TOSTOP = 58,
+
+ ///
+ /// Enable extensions.
+ ///
+ IEXTEN = 59,
+
+ ///
+ /// Echo control characters as ^(Char).
+ ///
+ ECHOCTL = 60,
+
+ ///
+ /// Visual erase for line kill.
+ ///
+ ECHOKE = 61,
+
+ ///
+ /// Retype pending input.
+ ///
+ PENDIN = 62,
+
+ ///
+ /// Enable output processing.
+ ///
+ OPOST = 70,
+
+ ///
+ /// Convert lowercase to uppercase.
+ ///
+ OLCUC = 71,
+
+ ///
+ /// Map NL to CR-NL.
+ ///
+ ONLCR = 72,
+
+ ///
+ /// Translate carriage return to newline (output).
+ ///
+ OCRNL = 73,
+
+ ///
+ /// Translate newline to carriage return-newline (output).
+ ///
+ ONOCR = 74,
+
+ ///
+ /// Newline performs a carriage return (output).
+ ///
+ ONLRET = 75,
+
+ ///
+ /// 7 bit mode.
+ ///
+ CS7 = 90,
+
+ ///
+ /// 8 bit mode.
+ ///
+ CS8 = 91,
+
+ ///
+ /// Parity enable.
+ ///
+ PARENB = 92,
+
+ ///
+ /// Odd parity, else even.
+ ///
+ PARODD = 93,
+
+ ///
+ /// Specifies the input baud rate in bits per second.
+ ///
+ TTY_OP_ISPEED = 128,
+
+ ///
+ /// Specifies the output baud rate in bits per second.
+ ///
+ TTY_OP_OSPEED = 129,
+ }
+}
diff --git a/Renci.SshNet/Compression/Adler32.cs b/Renci.SshNet/Compression/Adler32.cs
new file mode 100644
index 0000000..c38258f
--- /dev/null
+++ b/Renci.SshNet/Compression/Adler32.cs
@@ -0,0 +1,88 @@
+using System;
+/*
+ * $Id: Adler32.cs,v 1.1 2006-07-31 13:59:25 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib {
+
+ internal sealed class Adler32{
+
+ // largest prime smaller than 65536
+ private const int BASE=65521;
+ // NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
+ private const int NMAX=5552;
+
+ internal long adler32(long adler, byte[] buf, int index, int len){
+ if(buf == null){ return 1L; }
+
+ long s1=adler&0xffff;
+ long s2=(adler>>16)&0xffff;
+ int k;
+
+ while(len > 0) {
+ k=len=16){
+ s1+=buf[index++]&0xff; s2+=s1;
+ s1+=buf[index++]&0xff; s2+=s1;
+ s1+=buf[index++]&0xff; s2+=s1;
+ s1+=buf[index++]&0xff; s2+=s1;
+ s1+=buf[index++]&0xff; s2+=s1;
+ s1+=buf[index++]&0xff; s2+=s1;
+ s1+=buf[index++]&0xff; s2+=s1;
+ s1+=buf[index++]&0xff; s2+=s1;
+ s1+=buf[index++]&0xff; s2+=s1;
+ s1+=buf[index++]&0xff; s2+=s1;
+ s1+=buf[index++]&0xff; s2+=s1;
+ s1+=buf[index++]&0xff; s2+=s1;
+ s1+=buf[index++]&0xff; s2+=s1;
+ s1+=buf[index++]&0xff; s2+=s1;
+ s1+=buf[index++]&0xff; s2+=s1;
+ s1+=buf[index++]&0xff; s2+=s1;
+ k-=16;
+ }
+ if(k!=0){
+ do{
+ s1+=buf[index++]&0xff; s2+=s1;
+ }
+ while(--k!=0);
+ }
+ s1%=BASE;
+ s2%=BASE;
+ }
+ return (s2<<16)|s1;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/CompressionMode.cs b/Renci.SshNet/Compression/CompressionMode.cs
new file mode 100644
index 0000000..1577e0b
--- /dev/null
+++ b/Renci.SshNet/Compression/CompressionMode.cs
@@ -0,0 +1,18 @@
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Specifies compression modes
+ ///
+ public enum CompressionMode
+ {
+ ///
+ /// Specifies that content should be compressed.
+ ///
+ Compress = 0,
+
+ ///
+ /// Specifies that content should be decompressed.
+ ///
+ Decompress = 1,
+ }
+}
diff --git a/Renci.SshNet/Compression/Compressor.cs b/Renci.SshNet/Compression/Compressor.cs
index e7e84bf..1479bb6 100644
--- a/Renci.SshNet/Compression/Compressor.cs
+++ b/Renci.SshNet/Compression/Compressor.cs
@@ -1,17 +1,46 @@
using System.Collections.Generic;
using Renci.SshNet.Security;
+using System.IO;
+using System;
+
namespace Renci.SshNet.Compression
{
///
/// Represents base class for compression algorithm implementation
///
- 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;
+
+ ///
+ /// Gets or sets a value indicating whether compression is active.
+ ///
+ ///
+ /// true if compression is active; otherwise, false.
+ ///
+ protected bool IsActive { get; set; }
+
///
/// Gets the session.
///
protected Session Session { get; private set; }
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ 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);
+ }
+
///
/// Initializes the algorithm
///
@@ -26,13 +55,97 @@ public virtual void Init(Session session)
///
/// Data to compress.
/// Compressed data
- 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();
+ }
///
/// Decompresses the specified data.
///
/// Compressed data.
/// Decompressed data.
- 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;
+
+ ///
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged ResourceMessages.
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Releases unmanaged and - optionally - managed resources
+ ///
+ /// true to release both managed and unmanaged resources; false to release only unmanaged ResourceMessages.
+ 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;
+ }
+ }
+
+ ///
+ /// Releases unmanaged resources and performs other cleanup operations before the
+ /// is reclaimed by garbage collection.
+ ///
+ ~Compressor()
+ {
+ // Do not re-create Dispose clean-up code here.
+ // Calling Dispose(false) is optimal in terms of
+ // readability and maintainability.
+ Dispose(false);
+ }
+
+ #endregion
}
}
diff --git a/Renci.SshNet/Compression/Deflate.cs b/Renci.SshNet/Compression/Deflate.cs
new file mode 100644
index 0000000..ca04309
--- /dev/null
+++ b/Renci.SshNet/Compression/Deflate.cs
@@ -0,0 +1,1640 @@
+using System;
+/*
+ * $Id: Deflate.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib {
+
+ public sealed class Deflate{
+
+ private const int MAX_MEM_LEVEL=9;
+
+ private const int Z_DEFAULT_COMPRESSION=-1;
+
+ private const int MAX_WBITS=15; // 32K LZ77 window
+ private const int DEF_MEM_LEVEL=8;
+
+ internal class Config{
+ internal int good_length; // reduce lazy search above this match length
+ internal int max_lazy; // do not perform lazy search above this match length
+ internal int nice_length; // quit search above this match length
+ internal int max_chain;
+ internal int func;
+ internal Config(int good_length, int max_lazy,
+ int nice_length, int max_chain, int func){
+ this.good_length=good_length;
+ this.max_lazy=max_lazy;
+ this.nice_length=nice_length;
+ this.max_chain=max_chain;
+ this.func=func;
+ }
+ }
+
+ private const int STORED=0;
+ private const int FAST=1;
+ private const int SLOW=2;
+ private static readonly Config[] config_table;
+
+ static Deflate(){
+ config_table=new Config[10];
+ // good lazy nice chain
+ config_table[0]=new Config(0, 0, 0, 0, STORED);
+ config_table[1]=new Config(4, 4, 8, 4, FAST);
+ config_table[2]=new Config(4, 5, 16, 8, FAST);
+ config_table[3]=new Config(4, 6, 32, 32, FAST);
+
+ config_table[4]=new Config(4, 4, 16, 16, SLOW);
+ config_table[5]=new Config(8, 16, 32, 32, SLOW);
+ config_table[6]=new Config(8, 16, 128, 128, SLOW);
+ config_table[7]=new Config(8, 32, 128, 256, SLOW);
+ config_table[8]=new Config(32, 128, 258, 1024, SLOW);
+ config_table[9]=new Config(32, 258, 258, 4096, SLOW);
+ }
+
+ private static readonly String[] z_errmsg = {
+ "need dictionary", // Z_NEED_DICT 2
+ "stream end", // Z_STREAM_END 1
+ "", // Z_OK 0
+ "file error", // Z_ERRNO (-1)
+ "stream error", // Z_STREAM_ERROR (-2)
+ "data error", // Z_DATA_ERROR (-3)
+ "insufficient memory", // Z_MEM_ERROR (-4)
+ "buffer error", // Z_BUF_ERROR (-5)
+ "incompatible version",// Z_VERSION_ERROR (-6)
+ ""
+ };
+
+ // block not completed, need more input or more output
+ private const int NeedMore=0;
+
+ // block flush performed
+ private const int BlockDone=1;
+
+ // finish started, need only more output at next deflate
+ private const int FinishStarted=2;
+
+ // finish done, accept no more input or output
+ private const int FinishDone=3;
+
+ // preset dictionary flag in zlib header
+ private const int PRESET_DICT=0x20;
+
+ private const int Z_FILTERED=1;
+ private const int Z_HUFFMAN_ONLY=2;
+ private const int Z_DEFAULT_STRATEGY=0;
+
+ private const int Z_NO_FLUSH=0;
+ private const int Z_PARTIAL_FLUSH=1;
+ private const int Z_SYNC_FLUSH=2;
+ private const int Z_FULL_FLUSH=3;
+ private const int Z_FINISH=4;
+
+ private const int Z_OK=0;
+ private const int Z_STREAM_END=1;
+ private const int Z_NEED_DICT=2;
+ private const int Z_ERRNO=-1;
+ private const int Z_STREAM_ERROR=-2;
+ private const int Z_DATA_ERROR=-3;
+ private const int Z_MEM_ERROR=-4;
+ private const int Z_BUF_ERROR=-5;
+ private const int Z_VERSION_ERROR=-6;
+
+ private const int INIT_STATE=42;
+ private const int BUSY_STATE=113;
+ private const int FINISH_STATE=666;
+
+ // The deflate compression method
+ private const int Z_DEFLATED=8;
+
+ private const int STORED_BLOCK=0;
+ private const int STATIC_TREES=1;
+ private const int DYN_TREES=2;
+
+ // The three kinds of block type
+ private const int Z_BINARY=0;
+ private const int Z_ASCII=1;
+ private const int Z_UNKNOWN=2;
+
+ private const int Buf_size=8*2;
+
+ // repeat previous bit length 3-6 times (2 bits of repeat count)
+ private const int REP_3_6=16;
+
+ // repeat a zero length 3-10 times (3 bits of repeat count)
+ private const int REPZ_3_10=17;
+
+ // repeat a zero length 11-138 times (7 bits of repeat count)
+ private const int REPZ_11_138=18;
+
+ private const int MIN_MATCH=3;
+ private const int MAX_MATCH=258;
+ private const int MIN_LOOKAHEAD=(MAX_MATCH+MIN_MATCH+1);
+
+ private const int MAX_BITS=15;
+ private const int D_CODES=30;
+ private const int BL_CODES=19;
+ private const int LENGTH_CODES=29;
+ private const int LITERALS=256;
+ private const int L_CODES=(LITERALS+1+LENGTH_CODES);
+ private const int HEAP_SIZE=(2*L_CODES+1);
+
+ private const int END_BLOCK=256;
+
+ internal ZStream strm; // pointer back to this zlib stream
+ internal int status; // as the name implies
+ internal byte[] pending_buf; // output still pending
+ internal int pending_buf_size; // size of pending_buf
+ internal int pending_out; // next pending byte to output to the stream
+ internal int pending; // nb of bytes in the pending buffer
+ internal int noheader; // suppress zlib header and adler32
+ internal byte data_type; // UNKNOWN, BINARY or ASCII
+ internal byte method; // STORED (for zip only) or DEFLATED
+ internal int last_flush; // value of flush param for previous deflate call
+
+ internal int w_size; // LZ77 window size (32K by default)
+ internal int w_bits; // log2(w_size) (8..16)
+ internal int w_mask; // w_size - 1
+
+ internal byte[] window;
+ // Sliding window. Input bytes are read into the second half of the window,
+ // and move to the first half later to keep a dictionary of at least wSize
+ // bytes. With this organization, matches are limited to a distance of
+ // wSize-MAX_MATCH bytes, but this ensures that IO is always
+ // performed with a length multiple of the block size. Also, it limits
+ // the window size to 64K, which is quite useful on MSDOS.
+ // To do: use the user input buffer as sliding window.
+
+ internal int window_size;
+ // Actual size of window: 2*wSize, except when the user input buffer
+ // is directly used as sliding window.
+
+ internal short[] prev;
+ // Link to older string with same hash index. To limit the size of this
+ // array to 64K, this link is maintained only for the last 32K strings.
+ // An index in this array is thus a window index modulo 32K.
+
+ internal short[] head; // Heads of the hash chains or NIL.
+
+ internal int ins_h; // hash index of string to be inserted
+ internal int hash_size; // number of elements in hash table
+ internal int hash_bits; // log2(hash_size)
+ internal int hash_mask; // hash_size-1
+
+ // Number of bits by which ins_h must be shifted at each input
+ // step. It must be such that after MIN_MATCH steps, the oldest
+ // byte no longer takes part in the hash key, that is:
+ // hash_shift * MIN_MATCH >= hash_bits
+ internal int hash_shift;
+
+ // Window position at the beginning of the current output block. Gets
+ // negative when the window is moved backwards.
+
+ internal int block_start;
+
+ internal int match_length; // length of best match
+ internal int prev_match; // previous match
+ internal int match_available; // set if previous match exists
+ internal int strstart; // start of string to insert
+ internal int match_start; // start of matching string
+ internal int lookahead; // number of valid bytes ahead in window
+
+ // Length of the best match at previous step. Matches not greater than this
+ // are discarded. This is used in the lazy match evaluation.
+ internal int prev_length;
+
+ // To speed up deflation, hash chains are never searched beyond this
+ // length. A higher limit improves compression ratio but degrades the speed.
+ internal int max_chain_length;
+
+ // Attempt to find a better match only when the current match is strictly
+ // smaller than this value. This mechanism is used only for compression
+ // levels >= 4.
+ internal int max_lazy_match;
+
+ // Insert new strings in the hash table only if the match length is not
+ // greater than this length. This saves time but degrades compression.
+ // max_insert_length is used only for compression levels <= 3.
+
+ internal int level; // compression level (1..9)
+ internal int strategy; // favor or force Huffman coding
+
+ // Use a faster search when the previous match is longer than this
+ internal int good_match;
+
+ // Stop searching when current match exceeds this
+ internal int nice_match;
+
+ internal short[] dyn_ltree; // literal and length tree
+ internal short[] dyn_dtree; // distance tree
+ internal short[] bl_tree; // Huffman tree for bit lengths
+
+ internal Tree l_desc=new Tree(); // desc for literal tree
+ internal Tree d_desc=new Tree(); // desc for distance tree
+ internal Tree bl_desc=new Tree(); // desc for bit length tree
+
+ // number of codes at each bit length for an optimal tree
+ internal short[] bl_count=new short[MAX_BITS+1];
+
+ // heap used to build the Huffman trees
+ internal int[] heap=new int[2*L_CODES+1];
+
+ internal int heap_len; // number of elements in the heap
+ internal int heap_max; // element of largest frequency
+ // The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+ // The same heap array is used to build all trees.
+
+ // Depth of each subtree used as tie breaker for trees of equal frequency
+ internal byte[] depth=new byte[2*L_CODES+1];
+
+ internal int l_buf; // index for literals or lengths */
+
+ // Size of match buffer for literals/lengths. There are 4 reasons for
+ // limiting lit_bufsize to 64K:
+ // - frequencies can be kept in 16 bit counters
+ // - if compression is not successful for the first block, all input
+ // data is still in the window so we can still emit a stored block even
+ // when input comes from standard input. (This can also be done for
+ // all blocks if lit_bufsize is not greater than 32K.)
+ // - if compression is not successful for a file smaller than 64K, we can
+ // even emit a stored file instead of a stored block (saving 5 bytes).
+ // This is applicable only for zip (not gzip or zlib).
+ // - creating new Huffman trees less frequently may not provide fast
+ // adaptation to changes in the input data statistics. (Take for
+ // example a binary file with poorly compressible code followed by
+ // a highly compressible string table.) Smaller buffer sizes give
+ // fast adaptation but have of course the overhead of transmitting
+ // trees more frequently.
+ // - I can't count above 4
+ internal int lit_bufsize;
+
+ internal int last_lit; // running index in l_buf
+
+ // Buffer for distances. To simplify the code, d_buf and l_buf have
+ // the same number of elements. To use different lengths, an extra flag
+ // array would be necessary.
+
+ internal int d_buf; // index of pendig_buf
+
+ internal int opt_len; // bit length of current block with optimal trees
+ internal int static_len; // bit length of current block with static trees
+ internal int matches; // number of string matches in current block
+ internal int last_eob_len; // bit length of EOB code for last block
+
+ // Output buffer. bits are inserted starting at the bottom (least
+ // significant bits).
+ internal uint bi_buf;
+
+ // Number of valid bits in bi_buf. All bits above the last valid bit
+ // are always zero.
+ internal int bi_valid;
+
+ internal Deflate(){
+ dyn_ltree=new short[HEAP_SIZE*2];
+ dyn_dtree=new short[(2*D_CODES+1)*2]; // distance tree
+ bl_tree=new short[(2*BL_CODES+1)*2]; // Huffman tree for bit lengths
+ }
+
+ internal void lm_init() {
+ window_size=2*w_size;
+
+ head[hash_size-1]=0;
+ for(int i=0; i= 3; max_blindex--) {
+ if (bl_tree[Tree.bl_order[max_blindex]*2+1] != 0) break;
+ }
+ // Update opt_len to include the bit length tree and counts
+ opt_len += 3*(max_blindex+1) + 5+5+4;
+
+ return max_blindex;
+ }
+
+
+ // Send the header for a block using dynamic Huffman trees: the counts, the
+ // lengths of the bit length codes, the literal tree and the distance tree.
+ // IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
+ internal void send_all_trees(int lcodes, int dcodes, int blcodes){
+ int rank; // index in bl_order
+
+ send_bits(lcodes-257, 5); // not +255 as stated in appnote.txt
+ send_bits(dcodes-1, 5);
+ send_bits(blcodes-4, 4); // not -3 as stated in appnote.txt
+ for (rank = 0; rank < blcodes; rank++) {
+ send_bits(bl_tree[Tree.bl_order[rank]*2+1], 3);
+ }
+ send_tree(dyn_ltree, lcodes-1); // literal tree
+ send_tree(dyn_dtree, dcodes-1); // distance tree
+ }
+
+ // Send a literal or distance tree in compressed form, using the codes in
+ // bl_tree.
+ internal void send_tree (short[] tree,// the tree to be sent
+ int max_code // and its largest code of non zero frequency
+ ){
+ int n; // iterates over all tree elements
+ int prevlen = -1; // last emitted length
+ int curlen; // length of current code
+ int nextlen = tree[0*2+1]; // length of next code
+ int count = 0; // repeat count of the current code
+ int max_count = 7; // max repeat count
+ int min_count = 4; // min repeat count
+
+ if (nextlen == 0){ max_count = 138; min_count = 3; }
+
+ for (n = 0; n <= max_code; n++) {
+ curlen = nextlen; nextlen = tree[(n+1)*2+1];
+ if(++count < max_count && curlen == nextlen) {
+ continue;
+ }
+ else if(count < min_count) {
+ do { send_code(curlen, bl_tree); } while (--count != 0);
+ }
+ else if(curlen != 0){
+ if(curlen != prevlen){
+ send_code(curlen, bl_tree); count--;
+ }
+ send_code(REP_3_6, bl_tree);
+ send_bits(count-3, 2);
+ }
+ else if(count <= 10){
+ send_code(REPZ_3_10, bl_tree);
+ send_bits(count-3, 3);
+ }
+ else{
+ send_code(REPZ_11_138, bl_tree);
+ send_bits(count-11, 7);
+ }
+ count = 0; prevlen = curlen;
+ if(nextlen == 0){
+ max_count = 138; min_count = 3;
+ }
+ else if(curlen == nextlen){
+ max_count = 6; min_count = 3;
+ }
+ else{
+ max_count = 7; min_count = 4;
+ }
+ }
+ }
+
+ // Output a byte on the stream.
+ // IN assertion: there is enough room in pending_buf.
+ internal void put_byte(byte[] p, int start, int len){
+ System.Array.Copy(p, start, pending_buf, pending, len);
+ pending+=len;
+ }
+
+ internal void put_byte(byte c){
+ pending_buf[pending++]=c;
+ }
+ internal void put_short(int w) {
+ pending_buf[pending++]=(byte)(w/*&0xff*/);
+ pending_buf[pending++]=(byte)(w>>8);
+ }
+ internal void putShortMSB(int b){
+ pending_buf[pending++]=(byte)(b>>8);
+ pending_buf[pending++]=(byte)(b/*&0xff*/);
+ }
+
+ internal void send_code(int c, short[] tree){
+ int c2=c*2;
+ send_bits((tree[c2]&0xffff), (tree[c2+1]&0xffff));
+ }
+
+ internal void send_bits(int val, int length){
+ if (bi_valid > Buf_size - length) {
+ bi_buf |= (uint)(val << bi_valid);
+ pending_buf[pending++]=(byte)(bi_buf/*&0xff*/);
+ pending_buf[pending++]=(byte)(bi_buf>>8);
+ bi_buf = ((uint)val) >> (Buf_size - bi_valid);
+ bi_valid += length - Buf_size;
+ } else {
+ bi_buf |= (uint)(val << bi_valid);
+ bi_valid += length;
+ }
+// int len = length;
+// if (bi_valid > (int)Buf_size - len) {
+// int val = value;
+// // bi_buf |= (val << bi_valid);
+// bi_buf = (short)((ushort)bi_buf | (ushort)((val << bi_valid)&0xffff));
+// put_short(bi_buf);
+// bi_buf = (short)(((uint)val) >> (Buf_size - bi_valid));
+// bi_valid += len - Buf_size;
+// } else {
+// // bi_buf |= (value) << bi_valid;
+// bi_buf = (short)((ushort)bi_buf | (ushort)(((value) << bi_valid)&0xffff));
+// bi_valid += len;
+// }
+ }
+
+ // Send one empty static block to give enough lookahead for inflate.
+ // This takes 10 bits, of which 7 may remain in the bit buffer.
+ // The current inflate code requires 9 bits of lookahead. If the
+ // last two codes for the previous block (real code plus EOB) were coded
+ // on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
+ // the last real code. In this case we send two empty static blocks instead
+ // of one. (There are no problems if the previous block is stored or fixed.)
+ // To simplify the code, we assume the worst case of last real code encoded
+ // on one bit only.
+ internal void _tr_align(){
+ send_bits(STATIC_TREES<<1, 3);
+ send_code(END_BLOCK, StaticTree.static_ltree);
+
+ bi_flush();
+
+ // Of the 10 bits for the empty block, we have already sent
+ // (10 - bi_valid) bits. The lookahead for the last real code (before
+ // the EOB of the previous block) was thus at least one plus the length
+ // of the EOB plus what we have just sent of the empty static block.
+ if (1 + last_eob_len + 10 - bi_valid < 9) {
+ send_bits(STATIC_TREES<<1, 3);
+ send_code(END_BLOCK, StaticTree.static_ltree);
+ bi_flush();
+ }
+ last_eob_len = 7;
+ }
+
+
+ // Save the match info and tally the frequency counts. Return true if
+ // the current block must be flushed.
+ internal bool _tr_tally (int dist, // distance of matched string
+ int lc // match length-MIN_MATCH or unmatched char (if dist==0)
+ ){
+
+ pending_buf[d_buf+last_lit*2] = (byte)(dist>>8);
+ pending_buf[d_buf+last_lit*2+1] = (byte)dist;
+
+ pending_buf[l_buf+last_lit] = (byte)lc; last_lit++;
+
+ if (dist == 0) {
+ // lc is the unmatched char
+ dyn_ltree[lc*2]++;
+ }
+ else {
+ matches++;
+ // Here, lc is the match length - MIN_MATCH
+ dist--; // dist = match distance - 1
+ dyn_ltree[(Tree._length_code[lc]+LITERALS+1)*2]++;
+ dyn_dtree[Tree.d_code(dist)*2]++;
+ }
+
+ if ((last_lit & 0x1fff) == 0 && level > 2) {
+ // Compute an upper bound for the compressed length
+ int out_length = last_lit*8;
+ int in_length = strstart - block_start;
+ int dcode;
+ for (dcode = 0; dcode < D_CODES; dcode++) {
+ out_length += (int)((int)dyn_dtree[dcode*2] *
+ (5L+Tree.extra_dbits[dcode]));
+ }
+ out_length >>= 3;
+ if ((matches < (last_lit/2)) && out_length < in_length/2) return true;
+ }
+
+ return (last_lit == lit_bufsize-1);
+ // We avoid equality with lit_bufsize because of wraparound at 64K
+ // on 16 bit machines and because stored blocks are restricted to
+ // 64K-1 bytes.
+ }
+
+ // Send the block data compressed using the given Huffman trees
+ internal void compress_block(short[] ltree, short[] dtree){
+ int dist; // distance of matched string
+ int lc; // match length or unmatched char (if dist == 0)
+ int lx = 0; // running index in l_buf
+ int code; // the code to send
+ int extra; // number of extra bits to send
+
+ if (last_lit != 0){
+ do{
+ dist=((pending_buf[d_buf+lx*2]<<8)&0xff00)|
+ (pending_buf[d_buf+lx*2+1]&0xff);
+ lc=(pending_buf[l_buf+lx])&0xff; lx++;
+
+ if(dist == 0){
+ send_code(lc, ltree); // send a literal byte
+ }
+ else{
+ // Here, lc is the match length - MIN_MATCH
+ code = Tree._length_code[lc];
+
+ send_code(code+LITERALS+1, ltree); // send the length code
+ extra = Tree.extra_lbits[code];
+ if(extra != 0){
+ lc -= Tree.base_length[code];
+ send_bits(lc, extra); // send the extra length bits
+ }
+ dist--; // dist is now the match distance - 1
+ code = Tree.d_code(dist);
+
+ send_code(code, dtree); // send the distance code
+ extra = Tree.extra_dbits[code];
+ if (extra != 0) {
+ dist -= Tree.base_dist[code];
+ send_bits(dist, extra); // send the extra distance bits
+ }
+ } // literal or match pair ?
+
+ // Check that the overlay between pending_buf and d_buf+l_buf is ok:
+ }
+ while (lx < last_lit);
+ }
+
+ send_code(END_BLOCK, ltree);
+ last_eob_len = ltree[END_BLOCK*2+1];
+ }
+
+ // Set the data type to ASCII or BINARY, using a crude approximation:
+ // binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise.
+ // IN assertion: the fields freq of dyn_ltree are set and the total of all
+ // frequencies does not exceed 64K (to fit in an int on 16 bit machines).
+ internal void set_data_type(){
+ int n = 0;
+ int ascii_freq = 0;
+ int bin_freq = 0;
+ while(n<7){ bin_freq += dyn_ltree[n*2]; n++;}
+ while(n<128){ ascii_freq += dyn_ltree[n*2]; n++;}
+ while(n (ascii_freq >> 2) ? Z_BINARY : Z_ASCII);
+ }
+
+ // Flush the bit buffer, keeping at most 7 bits in it.
+ internal void bi_flush(){
+ if (bi_valid == 16) {
+ pending_buf[pending++]=(byte)(bi_buf/*&0xff*/);
+ pending_buf[pending++]=(byte)(bi_buf>>8);
+ bi_buf=0;
+ bi_valid=0;
+ }
+ else if (bi_valid >= 8) {
+ pending_buf[pending++]=(byte)(bi_buf);
+ bi_buf>>=8;
+ bi_buf &= 0x00ff;
+ bi_valid-=8;
+ }
+ }
+
+ // Flush the bit buffer and align the output on a byte boundary
+ internal void bi_windup(){
+ if (bi_valid > 8) {
+ pending_buf[pending++]=(byte)(bi_buf);
+ pending_buf[pending++]=(byte)(bi_buf>>8);
+ } else if (bi_valid > 0) {
+ pending_buf[pending++]=(byte)(bi_buf);
+ }
+ bi_buf = 0;
+ bi_valid = 0;
+ }
+
+ // Copy a stored block, storing first the length and its
+ // one's complement if requested.
+ internal void copy_block(int buf, // the input data
+ int len, // its length
+ bool header // true if block header must be written
+ ){
+ //int index=0;
+ bi_windup(); // align on byte boundary
+ last_eob_len = 8; // enough lookahead for inflate
+
+ if (header) {
+ put_short((short)len);
+ put_short((short)~len);
+ }
+
+ // while(len--!=0) {
+ // put_byte(window[buf+index]);
+ // index++;
+ // }
+ put_byte(window, buf, len);
+ }
+
+ internal void flush_block_only(bool eof){
+ _tr_flush_block(block_start>=0 ? block_start : -1,
+ strstart-block_start,
+ eof);
+ block_start=strstart;
+ strm.flush_pending();
+ }
+
+ // Copy without compression as much as possible from the input stream, return
+ // the current block state.
+ // This function does not insert new strings in the dictionary since
+ // uncompressible data is probably not useful. This function is used
+ // only for the level=0 compression option.
+ // NOTE: this function should be optimized to avoid extra copying from
+ // window to pending_buf.
+ internal int deflate_stored(int flush){
+ // Stored blocks are limited to 0xffff bytes, pending_buf is limited
+ // to pending_buf_size, and each stored block has a 5 byte header:
+
+ int max_block_size = 0xffff;
+ int max_start;
+
+ if(max_block_size > pending_buf_size - 5) {
+ max_block_size = pending_buf_size - 5;
+ }
+
+ // Copy as much as possible from input to output:
+ while(true){
+ // Fill the window as much as possible:
+ if(lookahead<=1){
+ fill_window();
+ if(lookahead==0 && flush==Z_NO_FLUSH) return NeedMore;
+ if(lookahead==0) break; // flush the current block
+ }
+
+ strstart+=lookahead;
+ lookahead=0;
+
+ // Emit a stored block if pending_buf will be full:
+ max_start=block_start+max_block_size;
+ if(strstart==0|| strstart>=max_start) {
+ // strstart == 0 is possible when wraparound on 16-bit machine
+ lookahead = (int)(strstart-max_start);
+ strstart = (int)max_start;
+
+ flush_block_only(false);
+ if(strm.avail_out==0) return NeedMore;
+
+ }
+
+ // Flush if we may have to slide, otherwise block_start may become
+ // negative and the data will be gone:
+ if(strstart-block_start >= w_size-MIN_LOOKAHEAD) {
+ flush_block_only(false);
+ if(strm.avail_out==0) return NeedMore;
+ }
+ }
+
+ flush_block_only(flush == Z_FINISH);
+ if(strm.avail_out==0)
+ return (flush == Z_FINISH) ? FinishStarted : NeedMore;
+
+ return flush == Z_FINISH ? FinishDone : BlockDone;
+ }
+
+ // Send a stored block
+ internal void _tr_stored_block(int buf, // input block
+ int stored_len, // length of input block
+ bool eof // true if this is the last block for a file
+ ){
+ send_bits((STORED_BLOCK<<1)+(eof?1:0), 3); // send block type
+ copy_block(buf, stored_len, true); // with header
+ }
+
+ // Determine the best encoding for the current block: dynamic trees, static
+ // trees or store, and output the encoded block to the zip file.
+ internal void _tr_flush_block(int buf, // input block, or NULL if too old
+ int stored_len, // length of input block
+ bool eof // true if this is the last block for a file
+ ) {
+ int opt_lenb, static_lenb;// opt_len and static_len in bytes
+ int max_blindex = 0; // index of last bit length code of non zero freq
+
+ // Build the Huffman trees unless a stored block is forced
+ if(level > 0) {
+ // Check if the file is ascii or binary
+ if(data_type == Z_UNKNOWN) set_data_type();
+
+ // Construct the literal and distance trees
+ l_desc.build_tree(this);
+
+ d_desc.build_tree(this);
+
+ // At this point, opt_len and static_len are the total bit lengths of
+ // the compressed block data, excluding the tree representations.
+
+ // Build the bit length tree for the above two trees, and get the index
+ // in bl_order of the last bit length code to send.
+ max_blindex=build_bl_tree();
+
+ // Determine the best encoding. Compute first the block length in bytes
+ opt_lenb=(opt_len+3+7)>>3;
+ static_lenb=(static_len+3+7)>>3;
+
+ if(static_lenb<=opt_lenb) opt_lenb=static_lenb;
+ }
+ else {
+ opt_lenb=static_lenb=stored_len+5; // force a stored block
+ }
+
+ if(stored_len+4<=opt_lenb && buf != -1){
+ // 4: two words for the lengths
+ // The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
+ // Otherwise we can't have processed more than WSIZE input bytes since
+ // the last block flush, because compression would have been
+ // successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
+ // transform a block into a stored block.
+ _tr_stored_block(buf, stored_len, eof);
+ }
+ else if(static_lenb == opt_lenb){
+ send_bits((STATIC_TREES<<1)+(eof?1:0), 3);
+ compress_block(StaticTree.static_ltree, StaticTree.static_dtree);
+ }
+ else{
+ send_bits((DYN_TREES<<1)+(eof?1:0), 3);
+ send_all_trees(l_desc.max_code+1, d_desc.max_code+1, max_blindex+1);
+ compress_block(dyn_ltree, dyn_dtree);
+ }
+
+ // The above check is made mod 2^32, for files larger than 512 MB
+ // and uLong implemented on 32 bits.
+
+ init_block();
+
+ if(eof){
+ bi_windup();
+ }
+ }
+
+ // Fill the window when the lookahead becomes insufficient.
+ // Updates strstart and lookahead.
+ //
+ // IN assertion: lookahead < MIN_LOOKAHEAD
+ // OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
+ // At least one byte has been read, or avail_in == 0; reads are
+ // performed for at least two bytes (required for the zip translate_eol
+ // option -- not supported here).
+ internal void fill_window(){
+ int n, m;
+ int p;
+ int more; // Amount of free space at the end of the window.
+
+ do{
+ more = (window_size-lookahead-strstart);
+
+ // Deal with !@#$% 64K limit:
+ if(more==0 && strstart==0 && lookahead==0){
+ more = w_size;
+ }
+ else if(more==-1) {
+ // Very unlikely, but possible on 16 bit machine if strstart == 0
+ // and lookahead == 1 (input done one byte at time)
+ more--;
+
+ // If the window is almost full and there is insufficient lookahead,
+ // move the upper half to the lower one to make room in the upper half.
+ }
+ else if(strstart >= w_size+ w_size-MIN_LOOKAHEAD) {
+ System.Array.Copy(window, w_size, window, 0, w_size);
+ match_start-=w_size;
+ strstart-=w_size; // we now have strstart >= MAX_DIST
+ block_start-=w_size;
+
+ // Slide the hash table (could be avoided with 32 bit values
+ // at the expense of memory usage). We slide even when level == 0
+ // to keep the hash table consistent if we switch back to level > 0
+ // later. (Using level 0 permanently is not an optimal usage of
+ // zlib, so we don't care about this pathological case.)
+
+ n = hash_size;
+ p=n;
+ do {
+ m = (head[--p]&0xffff);
+ head[p]=(short)(m>=w_size ? (m-w_size) : 0);
+ }
+ while (--n != 0);
+
+ n = w_size;
+ p = n;
+ do {
+ m = (prev[--p]&0xffff);
+ prev[p] = (short)(m >= w_size ? (m-w_size) : 0);
+ // If n is not on any hash chain, prev[n] is garbage but
+ // its value will never be used.
+ }
+ while (--n!=0);
+ more += w_size;
+ }
+
+ if (strm.avail_in == 0) return;
+
+ // If there was no sliding:
+ // strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
+ // more == window_size - lookahead - strstart
+ // => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
+ // => more >= window_size - 2*WSIZE + 2
+ // In the BIG_MEM or MMAP case (not yet supported),
+ // window_size == input_size + MIN_LOOKAHEAD &&
+ // strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
+ // Otherwise, window_size == 2*WSIZE so more >= 2.
+ // If there was sliding, more >= WSIZE. So in all cases, more >= 2.
+
+ n = strm.read_buf(window, strstart + lookahead, more);
+ lookahead += n;
+
+ // Initialize the hash value now that we have some input:
+ if(lookahead >= MIN_MATCH) {
+ ins_h = window[strstart]&0xff;
+ ins_h=(((ins_h)<= MIN_MATCH){
+ ins_h=(((ins_h)<=MIN_MATCH){
+ // check_match(strstart, match_start, match_length);
+
+ bflush=_tr_tally(strstart-match_start, match_length-MIN_MATCH);
+
+ lookahead -= match_length;
+
+ // Insert new strings in the hash table only if the match length
+ // is not too large. This saves time but degrades compression.
+ if(match_length <= max_lazy_match &&
+ lookahead >= MIN_MATCH) {
+ match_length--; // string at strstart already in hash table
+ do{
+ strstart++;
+
+ ins_h=((ins_h<= MIN_MATCH) {
+ ins_h=(((ins_h)< 4096))) {
+
+ // If prev_match is also MIN_MATCH, match_start is garbage
+ // but we will ignore the current match anyway.
+ match_length = MIN_MATCH-1;
+ }
+ }
+
+ // If there was a match at the previous step and the current
+ // match is not better, output the previous match:
+ if(prev_length >= MIN_MATCH && match_length <= prev_length) {
+ int max_insert = strstart + lookahead - MIN_MATCH;
+ // Do not insert strings in hash table beyond this.
+
+ // check_match(strstart-1, prev_match, prev_length);
+
+ bflush=_tr_tally(strstart-1-prev_match, prev_length - MIN_MATCH);
+
+ // Insert in hash table all strings up to the end of the match.
+ // strstart-1 and strstart are already inserted. If there is not
+ // enough lookahead, the last two strings are not inserted in
+ // the hash table.
+ lookahead -= prev_length-1;
+ prev_length -= 2;
+ do{
+ if(++strstart <= max_insert) {
+ ins_h=(((ins_h)<(w_size-MIN_LOOKAHEAD) ?
+ strstart-(w_size-MIN_LOOKAHEAD) : 0;
+ int nice_match=this.nice_match;
+
+ // Stop when cur_match becomes <= limit. To simplify the code,
+ // we prevent matches with the string of window index 0.
+
+ int wmask = w_mask;
+
+ int strend = strstart + MAX_MATCH;
+ byte scan_end1 = window[scan+best_len-1];
+ byte scan_end = window[scan+best_len];
+
+ // The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+ // It is easy to get rid of this optimization if necessary.
+
+ // Do not waste too much time if we already have a good match:
+ if (prev_length >= good_match) {
+ chain_length >>= 2;
+ }
+
+ // Do not look for matches beyond the end of the input. This is necessary
+ // to make deflate deterministic.
+ if (nice_match > lookahead) nice_match = lookahead;
+
+ do {
+ match = cur_match;
+
+ // Skip to next match if the match length cannot increase
+ // or if the match length is less than 2:
+ if (window[match+best_len] != scan_end ||
+ window[match+best_len-1] != scan_end1 ||
+ window[match] != window[scan] ||
+ window[++match] != window[scan+1]) continue;
+
+ // The check at best_len-1 can be removed because it will be made
+ // again later. (This heuristic is not always a win.)
+ // It is not necessary to compare scan[2] and match[2] since they
+ // are always equal when the other bytes match, given that
+ // the hash keys are equal and that HASH_BITS >= 8.
+ scan += 2; match++;
+
+ // We check for insufficient lookahead only every 8th comparison;
+ // the 256th check will be made at strstart+258.
+ do {
+ } while (window[++scan] == window[++match] &&
+ window[++scan] == window[++match] &&
+ window[++scan] == window[++match] &&
+ window[++scan] == window[++match] &&
+ window[++scan] == window[++match] &&
+ window[++scan] == window[++match] &&
+ window[++scan] == window[++match] &&
+ window[++scan] == window[++match] &&
+ scan < strend);
+
+ len = MAX_MATCH - (int)(strend - scan);
+ scan = strend - MAX_MATCH;
+
+ if(len>best_len) {
+ match_start = cur_match;
+ best_len = len;
+ if (len >= nice_match) break;
+ scan_end1 = window[scan+best_len-1];
+ scan_end = window[scan+best_len];
+ }
+
+ } while ((cur_match = (prev[cur_match & wmask]&0xffff)) > limit
+ && --chain_length != 0);
+
+ if (best_len <= lookahead) return best_len;
+ return lookahead;
+ }
+
+ internal int deflateInit(ZStream strm, int level, int bits){
+ return deflateInit2(strm, level, Z_DEFLATED, bits, DEF_MEM_LEVEL,
+ Z_DEFAULT_STRATEGY);
+ }
+ internal int deflateInit(ZStream strm, int level){
+ return deflateInit(strm, level, MAX_WBITS);
+ }
+ internal int deflateInit2(ZStream strm, int level, int method, int windowBits,
+ int memLevel, int strategy){
+ int noheader = 0;
+ // byte[] my_version=ZLIB_VERSION;
+
+ //
+ // if (version == null || version[0] != my_version[0]
+ // || stream_size != sizeof(z_stream)) {
+ // return Z_VERSION_ERROR;
+ // }
+
+ strm.msg = null;
+
+ if (level == Z_DEFAULT_COMPRESSION) level = 6;
+
+ if (windowBits < 0) { // undocumented feature: suppress zlib header
+ noheader = 1;
+ windowBits = -windowBits;
+ }
+
+ if (memLevel < 1 || memLevel > MAX_MEM_LEVEL ||
+ method != Z_DEFLATED ||
+ windowBits < 9 || windowBits > 15 || level < 0 || level > 9 ||
+ strategy < 0 || strategy > Z_HUFFMAN_ONLY) {
+ return Z_STREAM_ERROR;
+ }
+
+ strm.dstate = (Deflate)this;
+
+ this.noheader = noheader;
+ w_bits = windowBits;
+ w_size = 1 << w_bits;
+ w_mask = w_size - 1;
+
+ hash_bits = memLevel + 7;
+ hash_size = 1 << hash_bits;
+ hash_mask = hash_size - 1;
+ hash_shift = ((hash_bits+MIN_MATCH-1)/MIN_MATCH);
+
+ window = new byte[w_size*2];
+ prev = new short[w_size];
+ head = new short[hash_size];
+
+ lit_bufsize = 1 << (memLevel + 6); // 16K elements by default
+
+ // We overlay pending_buf and d_buf+l_buf. This works since the average
+ // output size for (length,distance) codes is <= 24 bits.
+ pending_buf = new byte[lit_bufsize*4];
+ pending_buf_size = lit_bufsize*4;
+
+ d_buf = lit_bufsize/2;
+ l_buf = (1+2)*lit_bufsize;
+
+ this.level = level;
+
+ //System.out.println("level="+level);
+
+ this.strategy = strategy;
+ this.method = (byte)method;
+
+ return deflateReset(strm);
+ }
+
+ internal int deflateReset(ZStream strm){
+ strm.total_in = strm.total_out = 0;
+ strm.msg = null; //
+ strm.data_type = Z_UNKNOWN;
+
+ pending = 0;
+ pending_out = 0;
+
+ if(noheader < 0) {
+ noheader = 0; // was set to -1 by deflate(..., Z_FINISH);
+ }
+ status = (noheader!=0) ? BUSY_STATE : INIT_STATE;
+ strm.adler=strm._adler.adler32(0, null, 0, 0);
+
+ last_flush = Z_NO_FLUSH;
+
+ tr_init();
+ lm_init();
+ return Z_OK;
+ }
+
+ internal int deflateEnd(){
+ if(status!=INIT_STATE && status!=BUSY_STATE && status!=FINISH_STATE){
+ return Z_STREAM_ERROR;
+ }
+ // Deallocate in reverse order of allocations:
+ pending_buf=null;
+ head=null;
+ prev=null;
+ window=null;
+ // free
+ // dstate=null;
+ return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK;
+ }
+
+ internal int deflateParams(ZStream strm, int _level, int _strategy){
+ int err=Z_OK;
+
+ if(_level == Z_DEFAULT_COMPRESSION){
+ _level = 6;
+ }
+ if(_level < 0 || _level > 9 ||
+ _strategy < 0 || _strategy > Z_HUFFMAN_ONLY) {
+ return Z_STREAM_ERROR;
+ }
+
+ if(config_table[level].func!=config_table[_level].func &&
+ strm.total_in != 0) {
+ // Flush the last buffer:
+ err = strm.deflate(Z_PARTIAL_FLUSH);
+ }
+
+ if(level != _level) {
+ level = _level;
+ max_lazy_match = config_table[level].max_lazy;
+ good_match = config_table[level].good_length;
+ nice_match = config_table[level].nice_length;
+ max_chain_length = config_table[level].max_chain;
+ }
+ strategy = _strategy;
+ return err;
+ }
+
+ internal int deflateSetDictionary (ZStream strm, byte[] dictionary, int dictLength){
+ int length = dictLength;
+ int index=0;
+
+ if(dictionary == null || status != INIT_STATE)
+ return Z_STREAM_ERROR;
+
+ strm.adler=strm._adler.adler32(strm.adler, dictionary, 0, dictLength);
+
+ if(length < MIN_MATCH) return Z_OK;
+ if(length > w_size-MIN_LOOKAHEAD){
+ length = w_size-MIN_LOOKAHEAD;
+ index=dictLength-length; // use the tail of the dictionary
+ }
+ System.Array.Copy(dictionary, index, window, 0, length);
+ strstart = length;
+ block_start = length;
+
+ // Insert all strings in the hash table (except for the last two bytes).
+ // s->lookahead stays null, so s->ins_h will be recomputed at the next
+ // call of fill_window.
+
+ ins_h = window[0]&0xff;
+ ins_h=(((ins_h)<Z_FINISH || flush<0){
+ return Z_STREAM_ERROR;
+ }
+
+ if(strm.next_out == null ||
+ (strm.next_in == null && strm.avail_in != 0) ||
+ (status == FINISH_STATE && flush != Z_FINISH)) {
+ strm.msg=z_errmsg[Z_NEED_DICT-(Z_STREAM_ERROR)];
+ return Z_STREAM_ERROR;
+ }
+ if(strm.avail_out == 0){
+ strm.msg=z_errmsg[Z_NEED_DICT-(Z_BUF_ERROR)];
+ return Z_BUF_ERROR;
+ }
+
+ this.strm = strm; // just in case
+ old_flush = last_flush;
+ last_flush = flush;
+
+ // Write the zlib header
+ if(status == INIT_STATE) {
+ int header = (Z_DEFLATED+((w_bits-8)<<4))<<8;
+ int level_flags=((level-1)&0xff)>>1;
+
+ if(level_flags>3) level_flags=3;
+ header |= (level_flags<<6);
+ if(strstart!=0) header |= PRESET_DICT;
+ header+=31-(header % 31);
+
+ status=BUSY_STATE;
+ putShortMSB(header);
+
+
+ // Save the adler32 of the preset dictionary:
+ if(strstart!=0){
+ putShortMSB((int)(strm.adler>>16));
+ putShortMSB((int)(strm.adler&0xffff));
+ }
+ strm.adler=strm._adler.adler32(0, null, 0, 0);
+ }
+
+ // Flush as much pending output as possible
+ if(pending != 0) {
+ strm.flush_pending();
+ if(strm.avail_out == 0) {
+ //System.out.println(" avail_out==0");
+ // Since avail_out is 0, deflate will be called again with
+ // more output space, but possibly with both pending and
+ // avail_in equal to zero. There won't be anything to do,
+ // but this is not an error situation so make sure we
+ // return OK instead of BUF_ERROR at next call of deflate:
+ last_flush = -1;
+ return Z_OK;
+ }
+
+ // Make sure there is something to do and avoid duplicate consecutive
+ // flushes. For repeated and useless calls with Z_FINISH, we keep
+ // returning Z_STREAM_END instead of Z_BUFF_ERROR.
+ }
+ else if(strm.avail_in==0 && flush <= old_flush &&
+ flush != Z_FINISH) {
+ strm.msg=z_errmsg[Z_NEED_DICT-(Z_BUF_ERROR)];
+ return Z_BUF_ERROR;
+ }
+
+ // User must not provide more input after the first FINISH:
+ if(status == FINISH_STATE && strm.avail_in != 0) {
+ strm.msg=z_errmsg[Z_NEED_DICT-(Z_BUF_ERROR)];
+ return Z_BUF_ERROR;
+ }
+
+ // Start a new block or continue the current one.
+ if(strm.avail_in!=0 || lookahead!=0 ||
+ (flush != Z_NO_FLUSH && status != FINISH_STATE)) {
+ int bstate=-1;
+ switch(config_table[level].func){
+ case STORED:
+ bstate = deflate_stored(flush);
+ break;
+ case FAST:
+ bstate = deflate_fast(flush);
+ break;
+ case SLOW:
+ bstate = deflate_slow(flush);
+ break;
+ default:
+ break;
+ }
+
+ if (bstate==FinishStarted || bstate==FinishDone) {
+ status = FINISH_STATE;
+ }
+ if (bstate==NeedMore || bstate==FinishStarted) {
+ if(strm.avail_out == 0) {
+ last_flush = -1; // avoid BUF_ERROR next call, see above
+ }
+ return Z_OK;
+ // If flush != Z_NO_FLUSH && avail_out == 0, the next call
+ // of deflate should use the same flush parameter to make sure
+ // that the flush is complete. So we don't have to output an
+ // empty block here, this will be done at next call. This also
+ // ensures that for a very small output buffer, we emit at most
+ // one empty block.
+ }
+
+ if (bstate==BlockDone) {
+ if(flush == Z_PARTIAL_FLUSH) {
+ _tr_align();
+ }
+ else { // FULL_FLUSH or SYNC_FLUSH
+ _tr_stored_block(0, 0, false);
+ // For a full flush, this empty block will be recognized
+ // as a special marker by inflate_sync().
+ if(flush == Z_FULL_FLUSH) {
+ //state.head[s.hash_size-1]=0;
+ for(int i=0; i>16));
+ putShortMSB((int)(strm.adler&0xffff));
+ strm.flush_pending();
+
+ // If avail_out is zero, the application will call deflate again
+ // to flush the rest.
+ noheader = -1; // write the trailer only once!
+ return pending != 0 ? Z_OK : Z_STREAM_END;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/InfBlocks.cs b/Renci.SshNet/Compression/InfBlocks.cs
new file mode 100644
index 0000000..479d9b5
--- /dev/null
+++ b/Renci.SshNet/Compression/InfBlocks.cs
@@ -0,0 +1,618 @@
+using System;
+/*
+ * $Id: InfBlocks.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib {
+
+ internal sealed class InfBlocks{
+ private const int MANY=1440;
+
+ // And'ing with mask[n] masks the lower n bits
+ private static readonly int[] inflate_mask = {
+ 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
+ 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
+ 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
+ 0x00007fff, 0x0000ffff
+ };
+
+ // Table for deflate from PKZIP's appnote.txt.
+ static readonly int[] border = { // Order of the bit length code lengths
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
+ };
+
+ private const int Z_OK=0;
+ private const int Z_STREAM_END=1;
+ private const int Z_NEED_DICT=2;
+ private const int Z_ERRNO=-1;
+ private const int Z_STREAM_ERROR=-2;
+ private const int Z_DATA_ERROR=-3;
+ private const int Z_MEM_ERROR=-4;
+ private const int Z_BUF_ERROR=-5;
+ private const int Z_VERSION_ERROR=-6;
+
+ private const int TYPE=0; // get type bits (3, including end bit)
+ private const int LENS=1; // get lengths for stored
+ private const int STORED=2;// processing stored block
+ private const int TABLE=3; // get table lengths
+ private const int BTREE=4; // get bit lengths tree for a dynamic block
+ private const int DTREE=5; // get length, distance trees for a dynamic block
+ private const int CODES=6; // processing fixed or dynamic block
+ private const int DRY=7; // output remaining window bytes
+ private const int DONE=8; // finished last block, done
+ private const int BAD=9; // ot a data error--stuck here
+
+ internal int mode; // current inflate_block mode
+
+ internal int left; // if STORED, bytes left to copy
+
+ internal int table; // table lengths (14 bits)
+ internal int index; // index into blens (or border)
+ internal int[] blens; // bit lengths of codes
+ internal int[] bb=new int[1]; // bit length tree depth
+ internal int[] tb=new int[1]; // bit length decoding tree
+
+ internal InfCodes codes=new InfCodes(); // if CODES, current state
+
+ int last; // true if this block is the last block
+
+ // mode independent information
+ internal int bitk; // bits in bit buffer
+ internal int bitb; // bit buffer
+ internal int[] hufts; // single malloc for tree space
+ internal byte[] window; // sliding window
+ internal int end; // one byte after sliding window
+ internal int read; // window read pointer
+ internal int write; // window write pointer
+ internal Object checkfn; // check function
+ internal long check; // check on output
+
+ internal InfTree inftree=new InfTree();
+
+ internal InfBlocks(ZStream z, Object checkfn, int w){
+ hufts=new int[MANY*3];
+ window=new byte[w];
+ end=w;
+ this.checkfn = checkfn;
+ mode = TYPE;
+ reset(z, null);
+ }
+
+ internal void reset(ZStream z, long[] c){
+ if(c!=null) c[0]=check;
+ if(mode==BTREE || mode==DTREE){
+ }
+ if(mode==CODES){
+ codes.free(z);
+ }
+ mode=TYPE;
+ bitk=0;
+ bitb=0;
+ read=write=0;
+
+ if(checkfn != null)
+ z.adler=check=z._adler.adler32(0L, null, 0, 0);
+ }
+
+ internal int proc(ZStream z, int r){
+ int t; // temporary storage
+ int b; // bit buffer
+ int k; // bits in bit buffer
+ int p; // input data pointer
+ int n; // bytes available there
+ int q; // output window write pointer
+ int m; { // bytes to end of window or read pointer
+
+ // copy input/output information to locals (UPDATE macro restores)
+ p=z.next_in_index;n=z.avail_in;b=bitb;k=bitk;} {
+ q=write;m=(int)(q> 1){
+ case 0: { // stored
+ b>>=(3);k-=(3);}
+ t = k & 7; { // go to byte boundary
+
+ b>>=(t);k-=(t);}
+ mode = LENS; // get length of stored block
+ break;
+ case 1: { // fixed
+ int[] bl=new int[1];
+ int[] bd=new int[1];
+ int[][] tl=new int[1][];
+ int[][] td=new int[1][];
+
+ InfTree.inflate_trees_fixed(bl, bd, tl, td, z);
+ codes.init(bl[0], bd[0], tl[0], 0, td[0], 0, z);
+ } {
+
+ b>>=(3);k-=(3);}
+
+ mode = CODES;
+ break;
+ case 2: { // dynamic
+
+ b>>=(3);k-=(3);}
+
+ mode = TABLE;
+ break;
+ case 3: { // illegal
+
+ b>>=(3);k-=(3);}
+ mode = BAD;
+ z.msg = "invalid block type";
+ r = Z_DATA_ERROR;
+
+ bitb=b; bitk=k;
+ z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+ write=q;
+ return inflate_flush(z,r);
+ }
+ break;
+ case LENS:
+
+ while(k<(32)){
+ if(n!=0){
+ r=Z_OK;
+ }
+ else{
+ bitb=b; bitk=k;
+ z.avail_in=n;
+ z.total_in+=p-z.next_in_index;z.next_in_index=p;
+ write=q;
+ return inflate_flush(z,r);
+ };
+ n--;
+ b|=(z.next_in[p++]&0xff)<> 16) & 0xffff) != (b & 0xffff)){
+ mode = BAD;
+ z.msg = "invalid stored block lengths";
+ r = Z_DATA_ERROR;
+
+ bitb=b; bitk=k;
+ z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+ write=q;
+ return inflate_flush(z,r);
+ }
+ left = (b & 0xffff);
+ b = k = 0; // dump bits
+ mode = left!=0 ? STORED : (last!=0 ? DRY : TYPE);
+ break;
+ case STORED:
+ if (n == 0){
+ bitb=b; bitk=k;
+ z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+ write=q;
+ return inflate_flush(z,r);
+ }
+
+ if(m==0){
+ if(q==end&&read!=0){
+ q=0; m=(int)(qn) t = n;
+ if(t>m) t = m;
+ System.Array.Copy(z.next_in, p, window, q, t);
+ p += t; n -= t;
+ q += t; m -= t;
+ if ((left -= t) != 0)
+ break;
+ mode = last!=0 ? DRY : TYPE;
+ break;
+ case TABLE:
+
+ while(k<(14)){
+ if(n!=0){
+ r=Z_OK;
+ }
+ else{
+ bitb=b; bitk=k;
+ z.avail_in=n;
+ z.total_in+=p-z.next_in_index;z.next_in_index=p;
+ write=q;
+ return inflate_flush(z,r);
+ };
+ n--;
+ b|=(z.next_in[p++]&0xff)< 29 || ((t >> 5) & 0x1f) > 29) {
+ mode = BAD;
+ z.msg = "too many length or distance symbols";
+ r = Z_DATA_ERROR;
+
+ bitb=b; bitk=k;
+ z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+ write=q;
+ return inflate_flush(z,r);
+ }
+ t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
+ if(blens==null || blens.Length>=(14);k-=(14);}
+
+ index = 0;
+ mode = BTREE;
+ goto case BTREE;
+ case BTREE:
+ while (index < 4 + (table >> 10)){
+ while(k<(3)){
+ if(n!=0){
+ r=Z_OK;
+ }
+ else{
+ bitb=b; bitk=k;
+ z.avail_in=n;
+ z.total_in+=p-z.next_in_index;z.next_in_index=p;
+ write=q;
+ return inflate_flush(z,r);
+ };
+ n--;
+ b|=(z.next_in[p++]&0xff)<>=(3);k-=(3);}
+ }
+
+ while(index < 19){
+ blens[border[index++]] = 0;
+ }
+
+ bb[0] = 7;
+ t = inftree.inflate_trees_bits(blens, bb, tb, hufts, z);
+ if (t != Z_OK){
+ r = t;
+ if (r == Z_DATA_ERROR){
+ blens=null;
+ mode = BAD;
+ }
+
+ bitb=b; bitk=k;
+ z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+ write=q;
+ return inflate_flush(z,r);
+ }
+
+ index = 0;
+ mode = DTREE;
+ goto case DTREE;
+ case DTREE:
+ while (true){
+ t = table;
+ if(!(index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))){
+ break;
+ }
+
+ int i, j, c;
+
+ t = bb[0];
+
+ while(k<(t)){
+ if(n!=0){
+ r=Z_OK;
+ }
+ else{
+ bitb=b; bitk=k;
+ z.avail_in=n;
+ z.total_in+=p-z.next_in_index;z.next_in_index=p;
+ write=q;
+ return inflate_flush(z,r);
+ };
+ n--;
+ b|=(z.next_in[p++]&0xff)<>=(t);k-=(t);
+ blens[index++] = c;
+ }
+ else { // c == 16..18
+ i = c == 18 ? 7 : c - 14;
+ j = c == 18 ? 11 : 3;
+
+ while(k<(t+i)){
+ if(n!=0){
+ r=Z_OK;
+ }
+ else{
+ bitb=b; bitk=k;
+ z.avail_in=n;
+ z.total_in+=p-z.next_in_index;z.next_in_index=p;
+ write=q;
+ return inflate_flush(z,r);
+ };
+ n--;
+ b|=(z.next_in[p++]&0xff)<>=(t);k-=(t);
+
+ j += (b & inflate_mask[i]);
+
+ b>>=(i);k-=(i);
+
+ i = index;
+ t = table;
+ if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
+ (c == 16 && i < 1)){
+ blens=null;
+ mode = BAD;
+ z.msg = "invalid bit length repeat";
+ r = Z_DATA_ERROR;
+
+ bitb=b; bitk=k;
+ z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+ write=q;
+ return inflate_flush(z,r);
+ }
+
+ c = c == 16 ? blens[i-1] : 0;
+ do{
+ blens[i++] = c;
+ }
+ while (--j!=0);
+ index = i;
+ }
+ }
+
+ tb[0]=-1; {
+ int[] bl=new int[1];
+ int[] bd=new int[1];
+ int[] tl=new int[1];
+ int[] td=new int[1];
+ bl[0] = 9; // must be <= 9 for lookahead assumptions
+ bd[0] = 6; // must be <= 9 for lookahead assumptions
+
+ t = table;
+ t = inftree.inflate_trees_dynamic(257 + (t & 0x1f),
+ 1 + ((t >> 5) & 0x1f),
+ blens, bl, bd, tl, td, hufts, z);
+
+ if (t != Z_OK){
+ if (t == Z_DATA_ERROR){
+ blens=null;
+ mode = BAD;
+ }
+ r = t;
+
+ bitb=b; bitk=k;
+ z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+ write=q;
+ return inflate_flush(z,r);
+ }
+ codes.init(bl[0], bd[0], hufts, tl[0], hufts, td[0], z);
+ }
+ mode = CODES;
+ goto case CODES;
+ case CODES:
+ bitb=b; bitk=k;
+ z.avail_in=n; z.total_in+=p-z.next_in_index;z.next_in_index=p;
+ write=q;
+
+ if ((r = codes.proc(this, z, r)) != Z_STREAM_END){
+ return inflate_flush(z, r);
+ }
+ r = Z_OK;
+ codes.free(z);
+
+ p=z.next_in_index; n=z.avail_in;b=bitb;k=bitk;
+ q=write;m=(int)(q z.avail_out) n = z.avail_out;
+ if (n!=0 && r == Z_BUF_ERROR) r = Z_OK;
+
+ // update counters
+ z.avail_out -= n;
+ z.total_out += n;
+
+ // update check information
+ if(checkfn != null)
+ z.adler=check=z._adler.adler32(check, window, q, n);
+
+ // copy as far as end of window
+ System.Array.Copy(window, q, z.next_out, p, n);
+ p += n;
+ q += n;
+
+ // see if more to copy at beginning of window
+ if (q == end){
+ // wrap pointers
+ q = 0;
+ if (write == end)
+ write = 0;
+
+ // compute bytes to copy
+ n = write - q;
+ if (n > z.avail_out) n = z.avail_out;
+ if (n!=0 && r == Z_BUF_ERROR) r = Z_OK;
+
+ // update counters
+ z.avail_out -= n;
+ z.total_out += n;
+
+ // update check information
+ if(checkfn != null)
+ z.adler=check=z._adler.adler32(check, window, q, n);
+
+ // copy
+ System.Array.Copy(window, q, z.next_out, p, n);
+ p += n;
+ q += n;
+ }
+
+ // update pointers
+ z.next_out_index = p;
+ read = q;
+
+ // done
+ return r;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/InfCodes.cs b/Renci.SshNet/Compression/InfCodes.cs
new file mode 100644
index 0000000..6fcafe4
--- /dev/null
+++ b/Renci.SshNet/Compression/InfCodes.cs
@@ -0,0 +1,611 @@
+using System;
+/*
+ * $Id: InfCodes.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib {
+
+ internal sealed class InfCodes{
+
+ private static readonly int[] inflate_mask = {
+ 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
+ 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
+ 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
+ 0x00007fff, 0x0000ffff
+ };
+
+ private const int Z_OK=0;
+ private const int Z_STREAM_END=1;
+ private const int Z_NEED_DICT=2;
+ private const int Z_ERRNO=-1;
+ private const int Z_STREAM_ERROR=-2;
+ private const int Z_DATA_ERROR=-3;
+ private const int Z_MEM_ERROR=-4;
+ private const int Z_BUF_ERROR=-5;
+ private const int Z_VERSION_ERROR=-6;
+
+ // waiting for "i:"=input,
+ // "o:"=output,
+ // "x:"=nothing
+ private const int START=0; // x: set up for LEN
+ private const int LEN=1; // i: get length/literal/eob next
+ private const int LENEXT=2; // i: getting length extra (have base)
+ private const int DIST=3; // i: get distance next
+ private const int DISTEXT=4;// i: getting distance extra
+ private const int COPY=5; // o: copying bytes in window, waiting for space
+ private const int LIT=6; // o: got literal, waiting for output space
+ private const int WASH=7; // o: got eob, possibly still output waiting
+ private const int END=8; // x: got eob and all data flushed
+ private const int BADCODE=9;// x: got error
+
+ int mode; // current inflate_codes mode
+
+ // mode dependent information
+ int len;
+
+ int[] tree; // pointer into tree
+ int tree_index=0;
+ int need; // bits needed
+
+ int lit;
+
+ // if EXT or COPY, where and how much
+ int get; // bits to get for extra
+ int dist; // distance back to copy from
+
+ byte lbits; // ltree bits decoded per branch
+ byte dbits; // dtree bits decoder per branch
+ int[] ltree; // literal/length/eob tree
+ int ltree_index; // literal/length/eob tree
+ int[] dtree; // distance tree
+ int dtree_index; // distance tree
+
+ internal InfCodes(){
+ }
+ internal void init(int bl, int bd,
+ int[] tl, int tl_index,
+ int[] td, int td_index, ZStream z){
+ mode=START;
+ lbits=(byte)bl;
+ dbits=(byte)bd;
+ ltree=tl;
+ ltree_index=tl_index;
+ dtree = td;
+ dtree_index=td_index;
+ tree=null;
+ }
+
+ internal int proc(InfBlocks s, ZStream z, int r){
+ int j; // temporary storage
+ int tindex; // temporary pointer
+ int e; // extra bits or operation
+ int b=0; // bit buffer
+ int k=0; // bits in bit buffer
+ int p=0; // input data pointer
+ int n; // bytes available there
+ int q; // output window write pointer
+ int m; // bytes to end of window or read pointer
+ int f; // pointer to copy strings from
+
+ // copy input/output information to locals (UPDATE macro restores)
+ p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk;
+ q=s.write;m=q= 258 && n >= 10){
+
+ s.bitb=b;s.bitk=k;
+ z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+ s.write=q;
+ r = inflate_fast(lbits, dbits,
+ ltree, ltree_index,
+ dtree, dtree_index,
+ s, z);
+
+ p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk;
+ q=s.write;m=q>=(tree[tindex+1]);
+ k-=(tree[tindex+1]);
+
+ e=tree[tindex];
+
+ if(e == 0){ // literal
+ lit = tree[tindex+2];
+ mode = LIT;
+ break;
+ }
+ if((e & 16)!=0 ){ // length
+ get = e & 15;
+ len = tree[tindex+2];
+ mode = LENEXT;
+ break;
+ }
+ if ((e & 64) == 0){ // next table
+ need = e;
+ tree_index = tindex/3+tree[tindex+2];
+ break;
+ }
+ if ((e & 32)!=0){ // end of block
+ mode = WASH;
+ break;
+ }
+ mode = BADCODE; // invalid code
+ z.msg = "invalid literal/length code";
+ r = Z_DATA_ERROR;
+
+ s.bitb=b;s.bitk=k;
+ z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+ s.write=q;
+ return s.inflate_flush(z,r);
+
+ case LENEXT: // i: getting length extra (have base)
+ j = get;
+
+ while(k<(j)){
+ if(n!=0)r=Z_OK;
+ else{
+
+ s.bitb=b;s.bitk=k;
+ z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+ s.write=q;
+ return s.inflate_flush(z,r);
+ }
+ n--; b|=(z.next_in[p++]&0xff)<>=j;
+ k-=j;
+
+ need = dbits;
+ tree = dtree;
+ tree_index=dtree_index;
+ mode = DIST;
+ goto case DIST;
+ case DIST: // i: get distance next
+ j = need;
+
+ while(k<(j)){
+ if(n!=0)r=Z_OK;
+ else{
+
+ s.bitb=b;s.bitk=k;
+ z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+ s.write=q;
+ return s.inflate_flush(z,r);
+ }
+ n--; b|=(z.next_in[p++]&0xff)<>=tree[tindex+1];
+ k-=tree[tindex+1];
+
+ e = (tree[tindex]);
+ if((e & 16)!=0){ // distance
+ get = e & 15;
+ dist = tree[tindex+2];
+ mode = DISTEXT;
+ break;
+ }
+ if ((e & 64) == 0){ // next table
+ need = e;
+ tree_index = tindex/3 + tree[tindex+2];
+ break;
+ }
+ mode = BADCODE; // invalid code
+ z.msg = "invalid distance code";
+ r = Z_DATA_ERROR;
+
+ s.bitb=b;s.bitk=k;
+ z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+ s.write=q;
+ return s.inflate_flush(z,r);
+
+ case DISTEXT: // i: getting distance extra
+ j = get;
+
+ while(k<(j)){
+ if(n!=0)r=Z_OK;
+ else{
+
+ s.bitb=b;s.bitk=k;
+ z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+ s.write=q;
+ return s.inflate_flush(z,r);
+ }
+ n--; b|=(z.next_in[p++]&0xff)<>=j;
+ k-=j;
+
+ mode = COPY;
+ goto case COPY;
+ case COPY: // o: copying bytes in window, waiting for space
+ f = q - dist;
+ while(f < 0){ // modulo window size-"while" instead
+ f += s.end; // of "if" handles invalid distances
+ }
+ while (len!=0){
+
+ if(m==0){
+ if(q==s.end&&s.read!=0){q=0;m=q 7){ // return unused byte, if any
+ k -= 8;
+ n++;
+ p--; // can always return one
+ }
+
+ s.write=q; r=s.inflate_flush(z,r);
+ q=s.write;m=q= 258 && n >= 10
+ // get literal/length code
+ while(k<(20)){ // max bits for literal/length code
+ n--;
+ b|=(z.next_in[p++]&0xff)<>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);
+
+ s.window[q++] = (byte)tp[tp_index_t_3+2];
+ m--;
+ continue;
+ }
+ do {
+
+ b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);
+
+ if((e&16)!=0){
+ e &= 15;
+ c = tp[tp_index_t_3+2] + ((int)b & inflate_mask[e]);
+
+ b>>=e; k-=e;
+
+ // decode distance base of block to copy
+ while(k<(15)){ // max bits for distance code
+ n--;
+ b|=(z.next_in[p++]&0xff)<>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);
+
+ if((e&16)!=0){
+ // get extra bits to add to distance base
+ e &= 15;
+ while(k<(e)){ // get extra bits (up to 13)
+ n--;
+ b|=(z.next_in[p++]&0xff)<>=(e); k-=(e);
+
+ // do the copy
+ m -= c;
+ if (q >= d){ // offset before dest
+ // just copy
+ r=q-d;
+ if(q-r>0 && 2>(q-r)){
+ s.window[q++]=s.window[r++]; // minimum count is three,
+ s.window[q++]=s.window[r++]; // so unroll loop a little
+ c-=2;
+ }
+ else{
+ System.Array.Copy(s.window, r, s.window, q, 2);
+ q+=2; r+=2; c-=2;
+ }
+ }
+ else{ // else offset after destination
+ r=q-d;
+ do{
+ r+=s.end; // force pointer in window
+ }while(r<0); // covers invalid distances
+ e=s.end-r;
+ if(c>e){ // if source crosses,
+ c-=e; // wrapped copy
+ if(q-r>0 && e>(q-r)){
+ do{s.window[q++] = s.window[r++];}
+ while(--e!=0);
+ }
+ else{
+ System.Array.Copy(s.window, r, s.window, q, e);
+ q+=e; r+=e; e=0;
+ }
+ r = 0; // copy rest from start of window
+ }
+
+ }
+
+ // copy all or what's left
+ if(q-r>0 && c>(q-r)){
+ do{s.window[q++] = s.window[r++];}
+ while(--c!=0);
+ }
+ else{
+ System.Array.Copy(s.window, r, s.window, q, c);
+ q+=c; r+=c; c=0;
+ }
+ break;
+ }
+ else if((e&64)==0){
+ t+=tp[tp_index_t_3+2];
+ t+=(b&inflate_mask[e]);
+ tp_index_t_3=(tp_index+t)*3;
+ e=tp[tp_index_t_3];
+ }
+ else{
+ z.msg = "invalid distance code";
+
+ c=z.avail_in-n;c=(k>>3)>3:c;n+=c;p-=c;k-=c<<3;
+
+ s.bitb=b;s.bitk=k;
+ z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+ s.write=q;
+
+ return Z_DATA_ERROR;
+ }
+ }
+ while(true);
+ break;
+ }
+
+ if((e&64)==0){
+ t+=tp[tp_index_t_3+2];
+ t+=(b&inflate_mask[e]);
+ tp_index_t_3=(tp_index+t)*3;
+ if((e=tp[tp_index_t_3])==0){
+
+ b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);
+
+ s.window[q++]=(byte)tp[tp_index_t_3+2];
+ m--;
+ break;
+ }
+ }
+ else if((e&32)!=0){
+
+ c=z.avail_in-n;c=(k>>3)>3:c;n+=c;p-=c;k-=c<<3;
+
+ s.bitb=b;s.bitk=k;
+ z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+ s.write=q;
+
+ return Z_STREAM_END;
+ }
+ else{
+ z.msg="invalid literal/length code";
+
+ c=z.avail_in-n;c=(k>>3)>3:c;n+=c;p-=c;k-=c<<3;
+
+ s.bitb=b;s.bitk=k;
+ z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+ s.write=q;
+
+ return Z_DATA_ERROR;
+ }
+ }
+ while(true);
+ }
+ while(m>=258 && n>= 10);
+
+ // not enough input or output--restore pointers and return
+ c=z.avail_in-n;c=(k>>3)>3:c;n+=c;p-=c;k-=c<<3;
+
+ s.bitb=b;s.bitk=k;
+ z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+ s.write=q;
+
+ return Z_OK;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/InfTree.cs b/Renci.SshNet/Compression/InfTree.cs
new file mode 100644
index 0000000..6ed7d19
--- /dev/null
+++ b/Renci.SshNet/Compression/InfTree.cs
@@ -0,0 +1,523 @@
+using System;
+/*
+ * $Id: InfTree.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib {
+
+ internal sealed class InfTree{
+
+ private const int MANY=1440;
+
+ private const int Z_OK=0;
+ private const int Z_STREAM_END=1;
+ private const int Z_NEED_DICT=2;
+ private const int Z_ERRNO=-1;
+ private const int Z_STREAM_ERROR=-2;
+ private const int Z_DATA_ERROR=-3;
+ private const int Z_MEM_ERROR=-4;
+ private const int Z_BUF_ERROR=-5;
+ private const int Z_VERSION_ERROR=-6;
+
+ private const int fixed_bl = 9;
+ private const int fixed_bd = 5;
+
+ static readonly int[] fixed_tl = {
+ 96,7,256, 0,8,80, 0,8,16, 84,8,115,
+ 82,7,31, 0,8,112, 0,8,48, 0,9,192,
+ 80,7,10, 0,8,96, 0,8,32, 0,9,160,
+ 0,8,0, 0,8,128, 0,8,64, 0,9,224,
+ 80,7,6, 0,8,88, 0,8,24, 0,9,144,
+ 83,7,59, 0,8,120, 0,8,56, 0,9,208,
+ 81,7,17, 0,8,104, 0,8,40, 0,9,176,
+ 0,8,8, 0,8,136, 0,8,72, 0,9,240,
+ 80,7,4, 0,8,84, 0,8,20, 85,8,227,
+ 83,7,43, 0,8,116, 0,8,52, 0,9,200,
+ 81,7,13, 0,8,100, 0,8,36, 0,9,168,
+ 0,8,4, 0,8,132, 0,8,68, 0,9,232,
+ 80,7,8, 0,8,92, 0,8,28, 0,9,152,
+ 84,7,83, 0,8,124, 0,8,60, 0,9,216,
+ 82,7,23, 0,8,108, 0,8,44, 0,9,184,
+ 0,8,12, 0,8,140, 0,8,76, 0,9,248,
+ 80,7,3, 0,8,82, 0,8,18, 85,8,163,
+ 83,7,35, 0,8,114, 0,8,50, 0,9,196,
+ 81,7,11, 0,8,98, 0,8,34, 0,9,164,
+ 0,8,2, 0,8,130, 0,8,66, 0,9,228,
+ 80,7,7, 0,8,90, 0,8,26, 0,9,148,
+ 84,7,67, 0,8,122, 0,8,58, 0,9,212,
+ 82,7,19, 0,8,106, 0,8,42, 0,9,180,
+ 0,8,10, 0,8,138, 0,8,74, 0,9,244,
+ 80,7,5, 0,8,86, 0,8,22, 192,8,0,
+ 83,7,51, 0,8,118, 0,8,54, 0,9,204,
+ 81,7,15, 0,8,102, 0,8,38, 0,9,172,
+ 0,8,6, 0,8,134, 0,8,70, 0,9,236,
+ 80,7,9, 0,8,94, 0,8,30, 0,9,156,
+ 84,7,99, 0,8,126, 0,8,62, 0,9,220,
+ 82,7,27, 0,8,110, 0,8,46, 0,9,188,
+ 0,8,14, 0,8,142, 0,8,78, 0,9,252,
+ 96,7,256, 0,8,81, 0,8,17, 85,8,131,
+ 82,7,31, 0,8,113, 0,8,49, 0,9,194,
+ 80,7,10, 0,8,97, 0,8,33, 0,9,162,
+ 0,8,1, 0,8,129, 0,8,65, 0,9,226,
+ 80,7,6, 0,8,89, 0,8,25, 0,9,146,
+ 83,7,59, 0,8,121, 0,8,57, 0,9,210,
+ 81,7,17, 0,8,105, 0,8,41, 0,9,178,
+ 0,8,9, 0,8,137, 0,8,73, 0,9,242,
+ 80,7,4, 0,8,85, 0,8,21, 80,8,258,
+ 83,7,43, 0,8,117, 0,8,53, 0,9,202,
+ 81,7,13, 0,8,101, 0,8,37, 0,9,170,
+ 0,8,5, 0,8,133, 0,8,69, 0,9,234,
+ 80,7,8, 0,8,93, 0,8,29, 0,9,154,
+ 84,7,83, 0,8,125, 0,8,61, 0,9,218,
+ 82,7,23, 0,8,109, 0,8,45, 0,9,186,
+ 0,8,13, 0,8,141, 0,8,77, 0,9,250,
+ 80,7,3, 0,8,83, 0,8,19, 85,8,195,
+ 83,7,35, 0,8,115, 0,8,51, 0,9,198,
+ 81,7,11, 0,8,99, 0,8,35, 0,9,166,
+ 0,8,3, 0,8,131, 0,8,67, 0,9,230,
+ 80,7,7, 0,8,91, 0,8,27, 0,9,150,
+ 84,7,67, 0,8,123, 0,8,59, 0,9,214,
+ 82,7,19, 0,8,107, 0,8,43, 0,9,182,
+ 0,8,11, 0,8,139, 0,8,75, 0,9,246,
+ 80,7,5, 0,8,87, 0,8,23, 192,8,0,
+ 83,7,51, 0,8,119, 0,8,55, 0,9,206,
+ 81,7,15, 0,8,103, 0,8,39, 0,9,174,
+ 0,8,7, 0,8,135, 0,8,71, 0,9,238,
+ 80,7,9, 0,8,95, 0,8,31, 0,9,158,
+ 84,7,99, 0,8,127, 0,8,63, 0,9,222,
+ 82,7,27, 0,8,111, 0,8,47, 0,9,190,
+ 0,8,15, 0,8,143, 0,8,79, 0,9,254,
+ 96,7,256, 0,8,80, 0,8,16, 84,8,115,
+ 82,7,31, 0,8,112, 0,8,48, 0,9,193,
+
+ 80,7,10, 0,8,96, 0,8,32, 0,9,161,
+ 0,8,0, 0,8,128, 0,8,64, 0,9,225,
+ 80,7,6, 0,8,88, 0,8,24, 0,9,145,
+ 83,7,59, 0,8,120, 0,8,56, 0,9,209,
+ 81,7,17, 0,8,104, 0,8,40, 0,9,177,
+ 0,8,8, 0,8,136, 0,8,72, 0,9,241,
+ 80,7,4, 0,8,84, 0,8,20, 85,8,227,
+ 83,7,43, 0,8,116, 0,8,52, 0,9,201,
+ 81,7,13, 0,8,100, 0,8,36, 0,9,169,
+ 0,8,4, 0,8,132, 0,8,68, 0,9,233,
+ 80,7,8, 0,8,92, 0,8,28, 0,9,153,
+ 84,7,83, 0,8,124, 0,8,60, 0,9,217,
+ 82,7,23, 0,8,108, 0,8,44, 0,9,185,
+ 0,8,12, 0,8,140, 0,8,76, 0,9,249,
+ 80,7,3, 0,8,82, 0,8,18, 85,8,163,
+ 83,7,35, 0,8,114, 0,8,50, 0,9,197,
+ 81,7,11, 0,8,98, 0,8,34, 0,9,165,
+ 0,8,2, 0,8,130, 0,8,66, 0,9,229,
+ 80,7,7, 0,8,90, 0,8,26, 0,9,149,
+ 84,7,67, 0,8,122, 0,8,58, 0,9,213,
+ 82,7,19, 0,8,106, 0,8,42, 0,9,181,
+ 0,8,10, 0,8,138, 0,8,74, 0,9,245,
+ 80,7,5, 0,8,86, 0,8,22, 192,8,0,
+ 83,7,51, 0,8,118, 0,8,54, 0,9,205,
+ 81,7,15, 0,8,102, 0,8,38, 0,9,173,
+ 0,8,6, 0,8,134, 0,8,70, 0,9,237,
+ 80,7,9, 0,8,94, 0,8,30, 0,9,157,
+ 84,7,99, 0,8,126, 0,8,62, 0,9,221,
+ 82,7,27, 0,8,110, 0,8,46, 0,9,189,
+ 0,8,14, 0,8,142, 0,8,78, 0,9,253,
+ 96,7,256, 0,8,81, 0,8,17, 85,8,131,
+ 82,7,31, 0,8,113, 0,8,49, 0,9,195,
+ 80,7,10, 0,8,97, 0,8,33, 0,9,163,
+ 0,8,1, 0,8,129, 0,8,65, 0,9,227,
+ 80,7,6, 0,8,89, 0,8,25, 0,9,147,
+ 83,7,59, 0,8,121, 0,8,57, 0,9,211,
+ 81,7,17, 0,8,105, 0,8,41, 0,9,179,
+ 0,8,9, 0,8,137, 0,8,73, 0,9,243,
+ 80,7,4, 0,8,85, 0,8,21, 80,8,258,
+ 83,7,43, 0,8,117, 0,8,53, 0,9,203,
+ 81,7,13, 0,8,101, 0,8,37, 0,9,171,
+ 0,8,5, 0,8,133, 0,8,69, 0,9,235,
+ 80,7,8, 0,8,93, 0,8,29, 0,9,155,
+ 84,7,83, 0,8,125, 0,8,61, 0,9,219,
+ 82,7,23, 0,8,109, 0,8,45, 0,9,187,
+ 0,8,13, 0,8,141, 0,8,77, 0,9,251,
+ 80,7,3, 0,8,83, 0,8,19, 85,8,195,
+ 83,7,35, 0,8,115, 0,8,51, 0,9,199,
+ 81,7,11, 0,8,99, 0,8,35, 0,9,167,
+ 0,8,3, 0,8,131, 0,8,67, 0,9,231,
+ 80,7,7, 0,8,91, 0,8,27, 0,9,151,
+ 84,7,67, 0,8,123, 0,8,59, 0,9,215,
+ 82,7,19, 0,8,107, 0,8,43, 0,9,183,
+ 0,8,11, 0,8,139, 0,8,75, 0,9,247,
+ 80,7,5, 0,8,87, 0,8,23, 192,8,0,
+ 83,7,51, 0,8,119, 0,8,55, 0,9,207,
+ 81,7,15, 0,8,103, 0,8,39, 0,9,175,
+ 0,8,7, 0,8,135, 0,8,71, 0,9,239,
+ 80,7,9, 0,8,95, 0,8,31, 0,9,159,
+ 84,7,99, 0,8,127, 0,8,63, 0,9,223,
+ 82,7,27, 0,8,111, 0,8,47, 0,9,191,
+ 0,8,15, 0,8,143, 0,8,79, 0,9,255
+ };
+ static readonly int[] fixed_td = {
+ 80,5,1, 87,5,257, 83,5,17, 91,5,4097,
+ 81,5,5, 89,5,1025, 85,5,65, 93,5,16385,
+ 80,5,3, 88,5,513, 84,5,33, 92,5,8193,
+ 82,5,9, 90,5,2049, 86,5,129, 192,5,24577,
+ 80,5,2, 87,5,385, 83,5,25, 91,5,6145,
+ 81,5,7, 89,5,1537, 85,5,97, 93,5,24577,
+ 80,5,4, 88,5,769, 84,5,49, 92,5,12289,
+ 82,5,13, 90,5,3073, 86,5,193, 192,5,24577
+ };
+
+ // Tables for deflate from PKZIP's appnote.txt.
+ static readonly int[] cplens = { // Copy lengths for literal codes 257..285
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
+ };
+
+ // see note #13 above about 258
+ static readonly int[] cplext = { // Extra bits for literal codes 257..285
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+ 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112 // 112==invalid
+ };
+
+ static readonly int[] cpdist = { // Copy offsets for distance codes 0..29
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+ 8193, 12289, 16385, 24577
+ };
+
+ static readonly int[] cpdext = { // Extra bits for distance codes
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+ 12, 12, 13, 13};
+
+ // If BMAX needs to be larger than 16, then h and x[] should be uLong.
+ const int BMAX=15; // maximum bit length of any code
+
+ int[] hn = null; // hufts used in space
+ int[] v = null; // work area for huft_build
+ int[] c = null; // bit length count table
+ int[] r = null; // table entry for structure assignment
+ int[] u = null; // table stack
+ int[] x = null; // bit offsets, then code stack
+
+ private int huft_build(int[] b, // code lengths in bits (all assumed <= BMAX)
+ int bindex,
+ int n, // number of codes (assumed <= 288)
+ int s, // number of simple-valued codes (0..s-1)
+ int[] d, // list of base values for non-simple codes
+ int[] e, // list of extra bits for non-simple codes
+ int[] t, // result: starting table
+ int[] m, // maximum lookup bits, returns actual
+ int[] hp,// space for trees
+ int[] hn,// hufts used in space
+ int[] v // working area: values in order of bit length
+ ){
+ // Given a list of code lengths and a maximum table size, make a set of
+ // tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR
+ // if the given code set is incomplete (the tables are still built in this
+ // case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of
+ // lengths), or Z_MEM_ERROR if not enough memory.
+
+ int a; // counter for codes of length k
+ int f; // i repeats in table every f entries
+ int g; // maximum code length
+ int h; // table level
+ int i; // counter, current code
+ int j; // counter
+ int k; // number of bits in current code
+ int l; // bits per table (returned in m)
+ int mask; // (1 << w) - 1, to avoid cc -O bug on HP
+ int p; // pointer into c[], b[], or v[]
+ int q; // points to current table
+ int w; // bits before this table == (l * h)
+ int xp; // pointer into x
+ int y; // number of dummy codes added
+ int z; // number of entries in current table
+
+ // Generate counts for each bit length
+
+ p = 0; i = n;
+ do {
+ c[b[bindex+p]]++; p++; i--; // assume all entries <= BMAX
+ }while(i!=0);
+
+ if(c[0] == n){ // null input--all zero length codes
+ t[0] = -1;
+ m[0] = 0;
+ return Z_OK;
+ }
+
+ // Find minimum and maximum length, bound *m by those
+ l = m[0];
+ for (j = 1; j <= BMAX; j++)
+ if(c[j]!=0) break;
+ k = j; // minimum code length
+ if(l < j){
+ l = j;
+ }
+ for (i = BMAX; i!=0; i--){
+ if(c[i]!=0) break;
+ }
+ g = i; // maximum code length
+ if(l > i){
+ l = i;
+ }
+ m[0] = l;
+
+ // Adjust last length count to fill out codes, if needed
+ for (y = 1 << j; j < i; j++, y <<= 1){
+ if ((y -= c[j]) < 0){
+ return Z_DATA_ERROR;
+ }
+ }
+ if ((y -= c[i]) < 0){
+ return Z_DATA_ERROR;
+ }
+ c[i] += y;
+
+ // Generate starting offsets into the value table for each length
+ x[1] = j = 0;
+ p = 1; xp = 2;
+ while (--i!=0) { // note that i == g from above
+ x[xp] = (j += c[p]);
+ xp++;
+ p++;
+ }
+
+ // Make a table of values in order of bit lengths
+ i = 0; p = 0;
+ do {
+ if ((j = b[bindex+p]) != 0){
+ v[x[j]++] = i;
+ }
+ p++;
+ }
+ while (++i < n);
+ n = x[g]; // set n to length of v
+
+ // Generate the Huffman codes and for each, make the table entries
+ x[0] = i = 0; // first Huffman code is zero
+ p = 0; // grab values in bit order
+ h = -1; // no tables yet--level -1
+ w = -l; // bits decoded == (l * h)
+ u[0] = 0; // just to keep compilers happy
+ q = 0; // ditto
+ z = 0; // ditto
+
+ // go through the bit lengths (k already is bits in shortest code)
+ for (; k <= g; k++){
+ a = c[k];
+ while (a--!=0){
+ // here i is the Huffman code of length k bits for value *p
+ // make tables up to required level
+ while (k > w + l){
+ h++;
+ w += l; // previous table always l bits
+ // compute minimum size table less than or equal to l bits
+ z = g - w;
+ z = (z > l) ? l : z; // table size upper limit
+ if((f=1<<(j=k-w))>a+1){ // try a k-w bit table
+ // too few codes for k-w bit table
+ f -= a + 1; // deduct codes from patterns left
+ xp = k;
+ if(j < z){
+ while (++j < z){ // try smaller tables up to z bits
+ if((f <<= 1) <= c[++xp])
+ break; // enough codes to use up j bits
+ f -= c[xp]; // else deduct codes from patterns
+ }
+ }
+ }
+ z = 1 << j; // table entries for j-bit table
+
+ // allocate new table
+ if (hn[0] + z > MANY){ // (note: doesn't matter for fixed)
+ return Z_DATA_ERROR; // overflow of MANY
+ }
+ u[h] = q = /*hp+*/ hn[0]; // DEBUG
+ hn[0] += z;
+
+ // connect to last table, if there is one
+ if(h!=0){
+ x[h]=i; // save pattern for backing up
+ r[0]=(byte)j; // bits in this table
+ r[1]=(byte)l; // bits to dump before this table
+ j=i>>(w - l);
+ r[2] = (int)(q - u[h-1] - j); // offset to this table
+ System.Array.Copy(r, 0, hp, (u[h-1]+j)*3, 3); // connect to last table
+ }
+ else{
+ t[0] = q; // first table is returned result
+ }
+ }
+
+ // set up table entry in r
+ r[1] = (byte)(k - w);
+ if (p >= n){
+ r[0] = 128 + 64; // out of values--invalid code
+ }
+ else if (v[p] < s){
+ r[0] = (byte)(v[p] < 256 ? 0 : 32 + 64); // 256 is end-of-block
+ r[2] = v[p++]; // simple code is just the value
+ }
+ else{
+ r[0]=(byte)(e[v[p]-s]+16+64); // non-simple--look up in lists
+ r[2]=d[v[p++] - s];
+ }
+
+ // fill code-like entries with r
+ f=1<<(k-w);
+ for (j=i>>w;j>= 1){
+ i ^= j;
+ }
+ i ^= j;
+
+ // backup over finished tables
+ mask = (1 << w) - 1; // needed on HP, cc -O bug
+ while ((i & mask) != x[h]){
+ h--; // don't need to update q
+ w -= l;
+ mask = (1 << w) - 1;
+ }
+ }
+ }
+ // Return Z_BUF_ERROR if we were given an incomplete table
+ return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
+ }
+
+ internal int inflate_trees_bits(int[] c, // 19 code lengths
+ int[] bb, // bits tree desired/actual depth
+ int[] tb, // bits tree result
+ int[] hp, // space for trees
+ ZStream z // for messages
+ ){
+ int result;
+ initWorkArea(19);
+ hn[0]=0;
+ result = huft_build(c, 0, 19, 19, null, null, tb, bb, hp, hn, v);
+
+ if(result == Z_DATA_ERROR){
+ z.msg = "oversubscribed dynamic bit lengths tree";
+ }
+ else if(result == Z_BUF_ERROR || bb[0] == 0){
+ z.msg = "incomplete dynamic bit lengths tree";
+ result = Z_DATA_ERROR;
+ }
+ return result;
+ }
+
+ internal int inflate_trees_dynamic(int nl, // number of literal/length codes
+ int nd, // number of distance codes
+ int[] c, // that many (total) code lengths
+ int[] bl, // literal desired/actual bit depth
+ int[] bd, // distance desired/actual bit depth
+ int[] tl, // literal/length tree result
+ int[] td, // distance tree result
+ int[] hp, // space for trees
+ ZStream z // for messages
+ ){
+ int result;
+
+ // build literal/length tree
+ initWorkArea(288);
+ hn[0]=0;
+ result = huft_build(c, 0, nl, 257, cplens, cplext, tl, bl, hp, hn, v);
+ if (result != Z_OK || bl[0] == 0){
+ if(result == Z_DATA_ERROR){
+ z.msg = "oversubscribed literal/length tree";
+ }
+ else if (result != Z_MEM_ERROR){
+ z.msg = "incomplete literal/length tree";
+ result = Z_DATA_ERROR;
+ }
+ return result;
+ }
+
+ // build distance tree
+ initWorkArea(288);
+ result = huft_build(c, nl, nd, 0, cpdist, cpdext, td, bd, hp, hn, v);
+
+ if (result != Z_OK || (bd[0] == 0 && nl > 257)){
+ if (result == Z_DATA_ERROR){
+ z.msg = "oversubscribed distance tree";
+ }
+ else if (result == Z_BUF_ERROR) {
+ z.msg = "incomplete distance tree";
+ result = Z_DATA_ERROR;
+ }
+ else if (result != Z_MEM_ERROR){
+ z.msg = "empty distance tree with lengths";
+ result = Z_DATA_ERROR;
+ }
+ return result;
+ }
+
+ return Z_OK;
+ }
+
+ internal static int inflate_trees_fixed(int[] bl, //literal desired/actual bit depth
+ int[] bd, //distance desired/actual bit depth
+ int[][] tl,//literal/length tree result
+ int[][] td,//distance tree result
+ ZStream z //for memory allocation
+ ){
+ bl[0]=fixed_bl;
+ bd[0]=fixed_bd;
+ tl[0]=fixed_tl;
+ td[0]=fixed_td;
+ return Z_OK;
+ }
+
+ private void initWorkArea(int vsize){
+ if(hn==null){
+ hn=new int[1];
+ v=new int[vsize];
+ c=new int[BMAX+1];
+ r=new int[3];
+ u=new int[BMAX];
+ x=new int[BMAX+1];
+ }
+ if(v.Lengthstate);
+ return Z_OK;
+ }
+
+ internal int inflateInit(ZStream z, int w){
+ z.msg = null;
+ blocks = null;
+
+ // handle undocumented nowrap option (no zlib header or check)
+ nowrap = 0;
+ if(w < 0){
+ w = - w;
+ nowrap = 1;
+ }
+
+ // set window size
+ if(w<8 ||w>15){
+ inflateEnd(z);
+ return Z_STREAM_ERROR;
+ }
+ wbits=w;
+
+ z.istate.blocks=new InfBlocks(z,
+ z.istate.nowrap!=0 ? null : this,
+ 1<>4)+8>z.istate.wbits){
+ z.istate.mode = BAD;
+ z.msg="invalid window size";
+ z.istate.marker = 5; // can't try inflateSync
+ break;
+ }
+ z.istate.mode=FLAG;
+ goto case FLAG;
+ case FLAG:
+
+ if(z.avail_in==0)return r;r=f;
+
+ z.avail_in--; z.total_in++;
+ b = (z.next_in[z.next_in_index++])&0xff;
+
+ if((((z.istate.method << 8)+b) % 31)!=0){
+ z.istate.mode = BAD;
+ z.msg = "incorrect header check";
+ z.istate.marker = 5; // can't try inflateSync
+ break;
+ }
+
+ if((b&PRESET_DICT)==0){
+ z.istate.mode = BLOCKS;
+ break;
+ }
+ z.istate.mode = DICT4;
+ goto case DICT4;
+ case DICT4:
+
+ if(z.avail_in==0)return r;r=f;
+
+ z.avail_in--; z.total_in++;
+ z.istate.need=((z.next_in[z.next_in_index++]&0xff)<<24)&0xff000000L;
+ z.istate.mode=DICT3;
+ goto case DICT3;
+ case DICT3:
+
+ if(z.avail_in==0)return r;r=f;
+
+ z.avail_in--; z.total_in++;
+ z.istate.need+=((z.next_in[z.next_in_index++]&0xff)<<16)&0xff0000L;
+ z.istate.mode=DICT2;
+ goto case DICT2;
+ case DICT2:
+
+ if(z.avail_in==0)return r;r=f;
+
+ z.avail_in--; z.total_in++;
+ z.istate.need+=((z.next_in[z.next_in_index++]&0xff)<<8)&0xff00L;
+ z.istate.mode=DICT1;
+ goto case DICT1;
+ case DICT1:
+
+ if(z.avail_in==0)return r;r=f;
+
+ z.avail_in--; z.total_in++;
+ z.istate.need += (z.next_in[z.next_in_index++]&0xffL);
+ z.adler = z.istate.need;
+ z.istate.mode = DICT0;
+ return Z_NEED_DICT;
+ case DICT0:
+ z.istate.mode = BAD;
+ z.msg = "need dictionary";
+ z.istate.marker = 0; // can try inflateSync
+ return Z_STREAM_ERROR;
+ case BLOCKS:
+
+ r = z.istate.blocks.proc(z, r);
+ if(r == Z_DATA_ERROR){
+ z.istate.mode = BAD;
+ z.istate.marker = 0; // can try inflateSync
+ break;
+ }
+ if(r == Z_OK){
+ r = f;
+ }
+ if(r != Z_STREAM_END){
+ return r;
+ }
+ r = f;
+ z.istate.blocks.reset(z, z.istate.was);
+ if(z.istate.nowrap!=0){
+ z.istate.mode=DONE;
+ break;
+ }
+ z.istate.mode=CHECK4;
+ goto case CHECK4;
+ case CHECK4:
+
+ if(z.avail_in==0)return r;r=f;
+
+ z.avail_in--; z.total_in++;
+ z.istate.need=((z.next_in[z.next_in_index++]&0xff)<<24)&0xff000000L;
+ z.istate.mode=CHECK3;
+ goto case CHECK3;
+ case CHECK3:
+
+ if(z.avail_in==0)return r;r=f;
+
+ z.avail_in--; z.total_in++;
+ z.istate.need+=((z.next_in[z.next_in_index++]&0xff)<<16)&0xff0000L;
+ z.istate.mode = CHECK2;
+ goto case CHECK2;
+ case CHECK2:
+
+ if(z.avail_in==0)return r;r=f;
+
+ z.avail_in--; z.total_in++;
+ z.istate.need+=((z.next_in[z.next_in_index++]&0xff)<<8)&0xff00L;
+ z.istate.mode = CHECK1;
+ goto case CHECK1;
+ case CHECK1:
+
+ if(z.avail_in==0)return r;r=f;
+
+ z.avail_in--; z.total_in++;
+ z.istate.need+=(z.next_in[z.next_in_index++]&0xffL);
+
+ if(((int)(z.istate.was[0])) != ((int)(z.istate.need))){
+ z.istate.mode = BAD;
+ z.msg = "incorrect data check";
+ z.istate.marker = 5; // can't try inflateSync
+ break;
+ }
+
+ z.istate.mode = DONE;
+ goto case DONE;
+ case DONE:
+ return Z_STREAM_END;
+ case BAD:
+ return Z_DATA_ERROR;
+ default:
+ return Z_STREAM_ERROR;
+ }
+ }
+ }
+
+
+ internal int inflateSetDictionary(ZStream z, byte[] dictionary, int dictLength){
+ int index=0;
+ int length = dictLength;
+ if(z==null || z.istate == null|| z.istate.mode != DICT0)
+ return Z_STREAM_ERROR;
+
+ if(z._adler.adler32(1L, dictionary, 0, dictLength)!=z.adler){
+ return Z_DATA_ERROR;
+ }
+
+ z.adler = z._adler.adler32(0, null, 0, 0);
+
+ if(length >= (1<
+ /// get type bits (3, including end bit)
+ ///
+ TYPE = 0,
+ ///
+ /// get lengths for stored
+ ///
+ LENS = 1,
+ ///
+ /// cessing stored block
+ ///
+ STORED = 2,
+ ///
+ /// get table lengths
+ ///
+ TABLE = 3,
+ ///
+ /// get bit lengths tree for a dynamic block
+ ///
+ BTREE = 4,
+ ///
+ /// get length, distance trees for a dynamic block
+ ///
+ DTREE = 5,
+ ///
+ /// processing fixed or dynamic block
+ ///
+ CODES = 6,
+ ///
+ /// output remaining window bytes
+ ///
+ DRY = 7,
+ ///
+ /// finished last block, done
+ ///
+ DONE = 8,
+ ///
+ /// ot a data error--stuck here
+ ///
+ BAD = 9
+ }
+
+ internal sealed class InflateBlocks : InflateCodes
+ {
+ private const int MANY = 1440;
+
+ // And'ing with mask[n] masks the lower n bits
+ private static readonly int[] inflate_mask = {
+ 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
+ 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
+ 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
+ 0x00007fff, 0x0000ffff
+ };
+
+ // Table for deflate from PKZIP's appnote.txt.
+ static readonly int[] border = { // Order of the bit length code lengths
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
+ };
+
+ internal InflateBlockMode mode; // current inflate_block mode
+
+ internal int left; // if STORED, bytes left to copy
+
+ internal int table; // table lengths (14 bits)
+ internal int index; // index into blens (or border)
+ internal int[] blens; // bit lengths of codes
+ internal int[] bb = new int[1]; // bit length tree depth
+ internal int[] tb = new int[1]; // bit length decoding tree
+
+ //internal InfCodes codes = new InfCodes(); // if CODES, current state
+
+ int last; // true if this block is the last block
+
+ // mode independent information
+ internal int bitk; // bits in bit buffer
+ internal int bitb; // bit buffer
+ internal int[] hufts; // single malloc for tree space
+ internal byte[] window; // sliding window
+ internal int end; // one byte after sliding window
+ internal int read; // window read pointer
+ internal int write; // window write pointer
+ internal Object checkfn; // check function
+ internal long check; // check on output
+
+ internal InflateTree inftree = new InflateTree();
+
+ internal InflateBlocks(ZStream z, Object checkfn, int w)
+ {
+ hufts = new int[MANY * 3];
+ window = new byte[w];
+ end = w;
+ this.checkfn = checkfn;
+ mode = InflateBlockMode.TYPE;
+ reset(z, null);
+ }
+
+ internal void reset(ZStream z, long[] c)
+ {
+ if (c != null) c[0] = check;
+ if (mode == InflateBlockMode.BTREE || mode == InflateBlockMode.DTREE)
+ {
+ }
+ if (mode == InflateBlockMode.CODES)
+ {
+ codesfree(z);
+ }
+ mode = InflateBlockMode.TYPE;
+ bitk = 0;
+ bitb = 0;
+ read = write = 0;
+
+ if (checkfn != null)
+ z.adler = check = Adler32.adler32(0L, null, 0, 0);
+ }
+
+ internal ZLibStatus proc(ZStream z, ZLibStatus r)
+ {
+ int t; // temporary storage
+ ZLibStatus tt;
+ int b; // bit buffer
+ int k; // bits in bit buffer
+ int p; // input data pointer
+ int n; // bytes available there
+ int q; // output window write pointer
+ int m;
+ { // bytes to end of window or read pointer
+
+ // copy input/output information to locals (UPDATE macro restores)
+ p = z.next_in_index; n = z.avail_in; b = bitb; k = bitk;
+ }
+ {
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+ }
+
+ // process input based on current state
+ while (true)
+ {
+ switch (mode)
+ {
+ case InflateBlockMode.TYPE:
+
+ while (k < (3))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+ t = (int)(b & 7);
+ last = t & 1;
+
+ switch (t >> 1)
+ {
+ case 0:
+ { // stored
+ b >>= (3); k -= (3);
+ }
+ t = k & 7;
+ { // go to byte boundary
+
+ b >>= (t); k -= (t);
+ }
+ mode = InflateBlockMode.LENS; // get length of stored block
+ break;
+ case 1:
+ { // fixed
+ int[] bl = new int[1];
+ int[] bd = new int[1];
+ int[][] tl = new int[1][];
+ int[][] td = new int[1][];
+
+ InflateTree.InflateTreesFixed(bl, bd, tl, td, z);
+ codesinit(bl[0], bd[0], tl[0], 0, td[0], 0, z);
+ }
+ {
+
+ b >>= (3); k -= (3);
+ }
+
+ mode = InflateBlockMode.CODES;
+ break;
+ case 2:
+ { // dynamic
+
+ b >>= (3); k -= (3);
+ }
+
+ mode = InflateBlockMode.TABLE;
+ break;
+ case 3:
+ { // illegal
+
+ b >>= (3); k -= (3);
+ }
+ mode = InflateBlockMode.BAD;
+ z.msg = "invalid block type";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ break;
+ case InflateBlockMode.LENS:
+
+ while (k < (32))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ if ((((~b) >> 16) & 0xffff) != (b & 0xffff))
+ {
+ mode = InflateBlockMode.BAD;
+ z.msg = "invalid stored block lengths";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ left = (b & 0xffff);
+ b = k = 0; // dump bits
+ mode = left != 0 ? InflateBlockMode.STORED : (last != 0 ? InflateBlockMode.DRY : InflateBlockMode.TYPE);
+ break;
+ case InflateBlockMode.STORED:
+ if (n == 0)
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+
+ if (m == 0)
+ {
+ if (q == end && read != 0)
+ {
+ q = 0; m = (int)(q < read ? read - q - 1 : end - q);
+ }
+ if (m == 0)
+ {
+ write = q;
+ r = inflate_flush(z, r);
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+ if (q == end && read != 0)
+ {
+ q = 0; m = (int)(q < read ? read - q - 1 : end - q);
+ }
+ if (m == 0)
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ }
+ }
+ r = ZLibStatus.Z_OK;
+
+ t = left;
+ if (t > n) t = n;
+ if (t > m) t = m;
+ System.Array.Copy(z.next_in, p, window, q, t);
+ p += t; n -= t;
+ q += t; m -= t;
+ if ((left -= t) != 0)
+ break;
+ mode = last != 0 ? InflateBlockMode.DRY : InflateBlockMode.TYPE;
+ break;
+ case InflateBlockMode.TABLE:
+
+ while (k < (14))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ table = t = (b & 0x3fff);
+ if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
+ {
+ mode = InflateBlockMode.BAD;
+ z.msg = "too many length or distance symbols";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
+ if (blens == null || blens.Length < t)
+ {
+ blens = new int[t];
+ }
+ else
+ {
+ for (int i = 0; i < t; i++) { blens[i] = 0; }
+ }
+ {
+
+ b >>= (14); k -= (14);
+ }
+
+ index = 0;
+ mode = InflateBlockMode.BTREE;
+ goto case InflateBlockMode.BTREE;
+ case InflateBlockMode.BTREE:
+ while (index < 4 + (table >> 10))
+ {
+ while (k < (3))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ blens[border[index++]] = b & 7;
+ {
+
+ b >>= (3); k -= (3);
+ }
+ }
+
+ while (index < 19)
+ {
+ blens[border[index++]] = 0;
+ }
+
+ bb[0] = 7;
+ tt = inftree.InflateTreesBits(blens, bb, tb, hufts, z);
+ if (tt != ZLibStatus.Z_OK)
+ {
+ r = tt;
+ if (r == ZLibStatus.Z_DATA_ERROR)
+ {
+ blens = null;
+ mode = InflateBlockMode.BAD;
+ }
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+
+ index = 0;
+ mode = InflateBlockMode.DTREE;
+ goto case InflateBlockMode.DTREE;
+ case InflateBlockMode.DTREE:
+ while (true)
+ {
+ t = table;
+ if (!(index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)))
+ {
+ break;
+ }
+
+ int i, j, c;
+
+ t = bb[0];
+
+ while (k < (t))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ if (tb[0] == -1)
+ {
+ //System.err.println("null...");
+ }
+
+ t = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 1];
+ c = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 2];
+
+ if (c < 16)
+ {
+ b >>= (t); k -= (t);
+ blens[index++] = c;
+ }
+ else
+ { // c == 16..18
+ i = c == 18 ? 7 : c - 14;
+ j = c == 18 ? 11 : 3;
+
+ while (k < (t + i))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ b >>= (t); k -= (t);
+
+ j += (b & inflate_mask[i]);
+
+ b >>= (i); k -= (i);
+
+ i = index;
+ t = table;
+ if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
+ (c == 16 && i < 1))
+ {
+ blens = null;
+ mode = InflateBlockMode.BAD;
+ z.msg = "invalid bit length repeat";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+
+ c = c == 16 ? blens[i - 1] : 0;
+ do
+ {
+ blens[i++] = c;
+ }
+ while (--j != 0);
+ index = i;
+ }
+ }
+
+ tb[0] = -1;
+ {
+ int[] bl = new int[1];
+ int[] bd = new int[1];
+ int[] tl = new int[1];
+ int[] td = new int[1];
+ bl[0] = 9; // must be <= 9 for lookahead assumptions
+ bd[0] = 6; // must be <= 9 for lookahead assumptions
+
+ t = table;
+ tt = inftree.InflateTreesDynamic(257 + (t & 0x1f),
+ 1 + ((t >> 5) & 0x1f),
+ blens, bl, bd, tl, td, hufts, z);
+
+ if (tt != ZLibStatus.Z_OK)
+ {
+ if (tt == ZLibStatus.Z_DATA_ERROR)
+ {
+ blens = null;
+ mode = InflateBlockMode.BAD;
+ }
+ r = tt;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ codesinit(bl[0], bd[0], hufts, tl[0], hufts, td[0], z);
+ }
+ mode = InflateBlockMode.CODES;
+ goto case InflateBlockMode.CODES;
+ case InflateBlockMode.CODES:
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+
+ if ((r = codesproc(this, z, r)) != ZLibStatus.Z_STREAM_END)
+ {
+ return inflate_flush(z, r);
+ }
+ r = ZLibStatus.Z_OK;
+ codesfree(z);
+
+ p = z.next_in_index; n = z.avail_in; b = bitb; k = bitk;
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+
+ if (last == 0)
+ {
+ mode = InflateBlockMode.TYPE;
+ break;
+ }
+ mode = InflateBlockMode.DRY;
+ goto case InflateBlockMode.DRY;
+ case InflateBlockMode.DRY:
+ write = q;
+ r = inflate_flush(z, r);
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+ if (read != write)
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ mode = InflateBlockMode.DONE;
+ goto case InflateBlockMode.DONE;
+ case InflateBlockMode.DONE:
+ r = ZLibStatus.Z_STREAM_END;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ case InflateBlockMode.BAD:
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+
+ default:
+ r = ZLibStatus.Z_STREAM_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ }
+ }
+
+ internal void free(ZStream z)
+ {
+ reset(z, null);
+ window = null;
+ hufts = null;
+ //ZFREE(z, s);
+ }
+
+ internal void set_dictionary(byte[] d, int start, int n)
+ {
+ System.Array.Copy(d, start, window, 0, n);
+ read = write = n;
+ }
+
+ // Returns true if inflate is currently at the end of a block generated
+ // by Z_SYNC_FLUSH or FlushType.Z_FULL_FLUSH.
+ internal ZLibStatus sync_point()
+ {
+ return mode == InflateBlockMode.LENS ? ZLibStatus.Z_STREAM_END : ZLibStatus.Z_OK;
+ }
+
+ // copy as much as possible from the sliding window to the output area
+ internal ZLibStatus inflate_flush(ZStream z, ZLibStatus r)
+ {
+ int n;
+ int p;
+ int q;
+
+ // local copies of source and destination pointers
+ p = z.next_out_index;
+ q = read;
+
+ // compute number of bytes to copy as far as end of window
+ n = (int)((q <= write ? write : end) - q);
+ if (n > z.avail_out) n = z.avail_out;
+ if (n != 0 && r == ZLibStatus.Z_BUF_ERROR) r = ZLibStatus.Z_OK;
+
+ // update counters
+ z.avail_out -= n;
+ z.total_out += n;
+
+ // update check information
+ if (checkfn != null)
+ z.adler = check = Adler32.adler32(check, window, q, n);
+
+ // copy as far as end of window
+ System.Array.Copy(window, q, z.next_out, p, n);
+ p += n;
+ q += n;
+
+ // see if more to copy at beginning of window
+ if (q == end)
+ {
+ // wrap pointers
+ q = 0;
+ if (write == end)
+ write = 0;
+
+ // compute bytes to copy
+ n = write - q;
+ if (n > z.avail_out) n = z.avail_out;
+ if (n != 0 && r == ZLibStatus.Z_BUF_ERROR) r = ZLibStatus.Z_OK;
+
+ // update counters
+ z.avail_out -= n;
+ z.total_out += n;
+
+ // update check information
+ if (checkfn != null)
+ z.adler = check = Adler32.adler32(check, window, q, n);
+
+ // copy
+ System.Array.Copy(window, q, z.next_out, p, n);
+ p += n;
+ q += n;
+ }
+
+ // update pointers
+ z.next_out_index = p;
+ read = q;
+
+ // done
+ return r;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/InflateCodes.cs b/Renci.SshNet/Compression/InflateCodes.cs
new file mode 100644
index 0000000..3214e56
--- /dev/null
+++ b/Renci.SshNet/Compression/InflateCodes.cs
@@ -0,0 +1,690 @@
+using System;
+/*
+ * $Id: InfCodes.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public enum InflateCodeMode
+ {
+ ///
+ /// x: set up for InflateCodeMode.LEN
+ ///
+ START = 0,
+ ///
+ /// i: get length/literal/eob next
+ ///
+ LEN = 1,
+ ///
+ /// i: getting length extra (have base)
+ ///
+ LENEXT = 2,
+ ///
+ /// i: get distance next
+ ///
+ DIST = 3,
+ ///
+ /// : getting distance extra
+ ///
+ DISTEXT = 4,
+ ///
+ /// o: copying bytes in window, waiting for space
+ ///
+ COPY = 5,
+ ///
+ /// o: got literal, waiting for output space
+ ///
+ LIT = 6,
+ ///
+ /// o: got eob, possibly still output waiting
+ ///
+ WASH = 7,
+ ///
+ /// x: got eob and all data flushed
+ ///
+ END = 8,
+ ///
+ /// x: got error
+ ///
+ BADCODE = 9
+ }
+
+ internal abstract class InflateCodes// : ZStream
+ {
+ private static readonly int[] inflate_mask = {
+ 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
+ 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
+ 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
+ 0x00007fff, 0x0000ffff
+ };
+
+ InflateCodeMode mode; // current inflate_codes mode
+
+ // mode dependent information
+ int len;
+
+ int[] tree; // pointer into tree
+ int tree_index = 0;
+ int need; // bits needed
+
+ int lit;
+
+ // if EXT or COPY, where and how much
+ int get; // bits to get for extra
+ int dist; // distance back to copy from
+
+ byte lbits; // ltree bits decoded per branch
+ byte dbits; // dtree bits decoder per branch
+ int[] ltree; // literal/length/eob tree
+ int ltree_index; // literal/length/eob tree
+ int[] dtree; // distance tree
+ int dtree_index; // distance tree
+
+ internal InflateCodes()
+ {
+ }
+ internal void codesinit(int bl, int bd,
+ int[] tl, int tl_index,
+ int[] td, int td_index, ZStream z)
+ {
+ mode = InflateCodeMode.START;
+ lbits = (byte)bl;
+ dbits = (byte)bd;
+ ltree = tl;
+ ltree_index = tl_index;
+ dtree = td;
+ dtree_index = td_index;
+ tree = null;
+ }
+
+ internal ZLibStatus codesproc(InflateBlocks s, ZStream z, ZLibStatus r)
+ {
+ int j; // temporary storage
+ int tindex; // temporary pointer
+ int e; // extra bits or operation
+ int b = 0; // bit buffer
+ int k = 0; // bits in bit buffer
+ int p = 0; // input data pointer
+ int n; // bytes available there
+ int q; // output window write pointer
+ int m; // bytes to end of window or read pointer
+ int f; // pointer to copy strings from
+
+ // copy input/output information to locals (UPDATE macro restores)
+ p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk;
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ // process input and output based on current state
+ while (true)
+ {
+ switch (mode)
+ {
+ // waiting for "i:"=input, "o:"=output, "x:"=nothing
+ case InflateCodeMode.START: // x: set up for LEN
+ if (m >= 258 && n >= 10)
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ r = inflate_fast(lbits, dbits,
+ ltree, ltree_index,
+ dtree, dtree_index,
+ s, z);
+
+ p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk;
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (r != ZLibStatus.Z_OK)
+ {
+ mode = r == ZLibStatus.Z_STREAM_END ? InflateCodeMode.WASH : InflateCodeMode.BADCODE;
+ break;
+ }
+ }
+ need = lbits;
+ tree = ltree;
+ tree_index = ltree_index;
+
+ mode = InflateCodeMode.LEN;
+ goto case InflateCodeMode.LEN;
+ case InflateCodeMode.LEN: // i: get length/literal/eob next
+ j = need;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ tindex = (tree_index + (b & inflate_mask[j])) * 3;
+
+ b >>= (tree[tindex + 1]);
+ k -= (tree[tindex + 1]);
+
+ e = tree[tindex];
+
+ if (e == 0)
+ { // literal
+ lit = tree[tindex + 2];
+ mode = InflateCodeMode.LIT;
+ break;
+ }
+ if ((e & 16) != 0)
+ { // length
+ get = e & 15;
+ len = tree[tindex + 2];
+ mode = InflateCodeMode.LENEXT;
+ break;
+ }
+ if ((e & 64) == 0)
+ { // next table
+ need = e;
+ tree_index = tindex / 3 + tree[tindex + 2];
+ break;
+ }
+ if ((e & 32) != 0)
+ { // end of block
+ mode = InflateCodeMode.WASH;
+ break;
+ }
+ mode = InflateCodeMode.BADCODE; // invalid code
+ z.msg = "invalid literal/length code";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ case InflateCodeMode.LENEXT: // i: getting length extra (have base)
+ j = get;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--; b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ len += (b & inflate_mask[j]);
+
+ b >>= j;
+ k -= j;
+
+ need = dbits;
+ tree = dtree;
+ tree_index = dtree_index;
+ mode = InflateCodeMode.DIST;
+ goto case InflateCodeMode.DIST;
+ case InflateCodeMode.DIST: // i: get distance next
+ j = need;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--; b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ tindex = (tree_index + (b & inflate_mask[j])) * 3;
+
+ b >>= tree[tindex + 1];
+ k -= tree[tindex + 1];
+
+ e = (tree[tindex]);
+ if ((e & 16) != 0)
+ { // distance
+ get = e & 15;
+ dist = tree[tindex + 2];
+ mode = InflateCodeMode.DISTEXT;
+ break;
+ }
+ if ((e & 64) == 0)
+ { // next table
+ need = e;
+ tree_index = tindex / 3 + tree[tindex + 2];
+ break;
+ }
+ mode = InflateCodeMode.BADCODE; // invalid code
+ z.msg = "invalid distance code";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ case InflateCodeMode.DISTEXT: // i: getting distance extra
+ j = get;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--; b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ dist += (b & inflate_mask[j]);
+
+ b >>= j;
+ k -= j;
+
+ mode = InflateCodeMode.COPY;
+ goto case InflateCodeMode.COPY;
+ case InflateCodeMode.COPY: // o: copying bytes in window, waiting for space
+ f = q - dist;
+ while (f < 0)
+ { // modulo window size-"while" instead
+ f += s.end; // of "if" handles invalid distances
+ }
+ while (len != 0)
+ {
+
+ if (m == 0)
+ {
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+ if (m == 0)
+ {
+ s.write = q; r = s.inflate_flush(z, r);
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+
+ if (m == 0)
+ {
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ }
+ }
+
+ s.window[q++] = s.window[f++]; m--;
+
+ if (f == s.end)
+ f = 0;
+ len--;
+ }
+ mode = InflateCodeMode.START;
+ break;
+ case InflateCodeMode.LIT: // o: got literal, waiting for output space
+ if (m == 0)
+ {
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+ if (m == 0)
+ {
+ s.write = q; r = s.inflate_flush(z, r);
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+ if (m == 0)
+ {
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ }
+ }
+ r = ZLibStatus.Z_OK;
+
+ s.window[q++] = (byte)lit; m--;
+
+ mode = InflateCodeMode.START;
+ break;
+ case InflateCodeMode.WASH: // o: got eob, possibly more output
+ if (k > 7)
+ { // return unused byte, if any
+ k -= 8;
+ n++;
+ p--; // can always return one
+ }
+
+ s.write = q; r = s.inflate_flush(z, r);
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (s.read != s.write)
+ {
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ mode = InflateCodeMode.END;
+ goto case InflateCodeMode.END;
+ case InflateCodeMode.END:
+ r = ZLibStatus.Z_STREAM_END;
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ case InflateCodeMode.BADCODE: // x: got error
+
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ default:
+ r = ZLibStatus.Z_STREAM_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ }
+ }
+
+ internal void codesfree(ZStream z)
+ {
+ // ZFREE(z, c);
+ }
+
+ // Called with number of bytes left to write in window at least 258
+ // (the maximum string length) and number of input bytes available
+ // at least ten. The ten bytes are six bytes for the longest length/
+ // distance pair plus four bytes for overloading the bit buffer.
+
+ internal ZLibStatus inflate_fast(int bl, int bd,
+ int[] tl, int tl_index,
+ int[] td, int td_index,
+ InflateBlocks s, ZStream z)
+ {
+ int t; // temporary pointer
+ int[] tp; // temporary pointer
+ int tp_index; // temporary pointer
+ int e; // extra bits or operation
+ int b; // bit buffer
+ int k; // bits in bit buffer
+ int p; // input data pointer
+ int n; // bytes available there
+ int q; // output window write pointer
+ int m; // bytes to end of window or read pointer
+ int ml; // mask for literal/length tree
+ int md; // mask for distance tree
+ int c; // bytes to copy
+ int d; // distance back to copy from
+ int r; // copy source pointer
+
+ int tp_index_t_3; // (tp_index+t)*3
+
+ // load input, output, bit values
+ p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk;
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ // initialize masks
+ ml = inflate_mask[bl];
+ md = inflate_mask[bd];
+
+ // do until not enough input or output space for fast loop
+ do
+ { // assume called with m >= 258 && n >= 10
+ // get literal/length code
+ while (k < (20))
+ { // max bits for literal/length code
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k; k += 8;
+ }
+
+ t = b & ml;
+ tp = tl;
+ tp_index = tl_index;
+ tp_index_t_3 = (tp_index + t) * 3;
+ if ((e = tp[tp_index_t_3]) == 0)
+ {
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ s.window[q++] = (byte)tp[tp_index_t_3 + 2];
+ m--;
+ continue;
+ }
+ do
+ {
+
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ if ((e & 16) != 0)
+ {
+ e &= 15;
+ c = tp[tp_index_t_3 + 2] + ((int)b & inflate_mask[e]);
+
+ b >>= e; k -= e;
+
+ // decode distance base of block to copy
+ while (k < (15))
+ { // max bits for distance code
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k; k += 8;
+ }
+
+ t = b & md;
+ tp = td;
+ tp_index = td_index;
+ tp_index_t_3 = (tp_index + t) * 3;
+ e = tp[tp_index_t_3];
+
+ do
+ {
+
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ if ((e & 16) != 0)
+ {
+ // get extra bits to add to distance base
+ e &= 15;
+ while (k < (e))
+ { // get extra bits (up to 13)
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k; k += 8;
+ }
+
+ d = tp[tp_index_t_3 + 2] + (b & inflate_mask[e]);
+
+ b >>= (e); k -= (e);
+
+ // do the copy
+ m -= c;
+ if (q >= d)
+ { // offset before dest
+ // just copy
+ r = q - d;
+ if (q - r > 0 && 2 > (q - r))
+ {
+ s.window[q++] = s.window[r++]; // minimum count is three,
+ s.window[q++] = s.window[r++]; // so unroll loop a little
+ c -= 2;
+ }
+ else
+ {
+ System.Array.Copy(s.window, r, s.window, q, 2);
+ q += 2; r += 2; c -= 2;
+ }
+ }
+ else
+ { // else offset after destination
+ r = q - d;
+ do
+ {
+ r += s.end; // force pointer in window
+ } while (r < 0); // covers invalid distances
+ e = s.end - r;
+ if (c > e)
+ { // if source crosses,
+ c -= e; // wrapped copy
+ if (q - r > 0 && e > (q - r))
+ {
+ do { s.window[q++] = s.window[r++]; }
+ while (--e != 0);
+ }
+ else
+ {
+ System.Array.Copy(s.window, r, s.window, q, e);
+ q += e; r += e; e = 0;
+ }
+ r = 0; // copy rest from start of window
+ }
+
+ }
+
+ // copy all or what's left
+ if (q - r > 0 && c > (q - r))
+ {
+ do { s.window[q++] = s.window[r++]; }
+ while (--c != 0);
+ }
+ else
+ {
+ System.Array.Copy(s.window, r, s.window, q, c);
+ q += c; r += c; c = 0;
+ }
+ break;
+ }
+ else if ((e & 64) == 0)
+ {
+ t += tp[tp_index_t_3 + 2];
+ t += (b & inflate_mask[e]);
+ tp_index_t_3 = (tp_index + t) * 3;
+ e = tp[tp_index_t_3];
+ }
+ else
+ {
+ z.msg = "invalid distance code";
+
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ }
+ while (true);
+ break;
+ }
+
+ if ((e & 64) == 0)
+ {
+ t += tp[tp_index_t_3 + 2];
+ t += (b & inflate_mask[e]);
+ tp_index_t_3 = (tp_index + t) * 3;
+ if ((e = tp[tp_index_t_3]) == 0)
+ {
+
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ s.window[q++] = (byte)tp[tp_index_t_3 + 2];
+ m--;
+ break;
+ }
+ }
+ else if ((e & 32) != 0)
+ {
+
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_STREAM_END;
+ }
+ else
+ {
+ z.msg = "invalid literal/length code";
+
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ }
+ while (true);
+ }
+ while (m >= 258 && n >= 10);
+
+ // not enough input or output--restore pointers and return
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_OK;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/InflateTree.cs b/Renci.SshNet/Compression/InflateTree.cs
new file mode 100644
index 0000000..f9da579
--- /dev/null
+++ b/Renci.SshNet/Compression/InflateTree.cs
@@ -0,0 +1,555 @@
+using System;
+/*
+ * $Id: InfTree.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ internal sealed class InflateTree
+ {
+ private const int MANY = 1440;
+
+ private const int fixed_bl = 9;
+ private const int fixed_bd = 5;
+
+ static readonly int[] fixed_tl = {
+ 96,7,256, 0,8,80, 0,8,16, 84,8,115,
+ 82,7,31, 0,8,112, 0,8,48, 0,9,192,
+ 80,7,10, 0,8,96, 0,8,32, 0,9,160,
+ 0,8,0, 0,8,128, 0,8,64, 0,9,224,
+ 80,7,6, 0,8,88, 0,8,24, 0,9,144,
+ 83,7,59, 0,8,120, 0,8,56, 0,9,208,
+ 81,7,17, 0,8,104, 0,8,40, 0,9,176,
+ 0,8,8, 0,8,136, 0,8,72, 0,9,240,
+ 80,7,4, 0,8,84, 0,8,20, 85,8,227,
+ 83,7,43, 0,8,116, 0,8,52, 0,9,200,
+ 81,7,13, 0,8,100, 0,8,36, 0,9,168,
+ 0,8,4, 0,8,132, 0,8,68, 0,9,232,
+ 80,7,8, 0,8,92, 0,8,28, 0,9,152,
+ 84,7,83, 0,8,124, 0,8,60, 0,9,216,
+ 82,7,23, 0,8,108, 0,8,44, 0,9,184,
+ 0,8,12, 0,8,140, 0,8,76, 0,9,248,
+ 80,7,3, 0,8,82, 0,8,18, 85,8,163,
+ 83,7,35, 0,8,114, 0,8,50, 0,9,196,
+ 81,7,11, 0,8,98, 0,8,34, 0,9,164,
+ 0,8,2, 0,8,130, 0,8,66, 0,9,228,
+ 80,7,7, 0,8,90, 0,8,26, 0,9,148,
+ 84,7,67, 0,8,122, 0,8,58, 0,9,212,
+ 82,7,19, 0,8,106, 0,8,42, 0,9,180,
+ 0,8,10, 0,8,138, 0,8,74, 0,9,244,
+ 80,7,5, 0,8,86, 0,8,22, 192,8,0,
+ 83,7,51, 0,8,118, 0,8,54, 0,9,204,
+ 81,7,15, 0,8,102, 0,8,38, 0,9,172,
+ 0,8,6, 0,8,134, 0,8,70, 0,9,236,
+ 80,7,9, 0,8,94, 0,8,30, 0,9,156,
+ 84,7,99, 0,8,126, 0,8,62, 0,9,220,
+ 82,7,27, 0,8,110, 0,8,46, 0,9,188,
+ 0,8,14, 0,8,142, 0,8,78, 0,9,252,
+ 96,7,256, 0,8,81, 0,8,17, 85,8,131,
+ 82,7,31, 0,8,113, 0,8,49, 0,9,194,
+ 80,7,10, 0,8,97, 0,8,33, 0,9,162,
+ 0,8,1, 0,8,129, 0,8,65, 0,9,226,
+ 80,7,6, 0,8,89, 0,8,25, 0,9,146,
+ 83,7,59, 0,8,121, 0,8,57, 0,9,210,
+ 81,7,17, 0,8,105, 0,8,41, 0,9,178,
+ 0,8,9, 0,8,137, 0,8,73, 0,9,242,
+ 80,7,4, 0,8,85, 0,8,21, 80,8,258,
+ 83,7,43, 0,8,117, 0,8,53, 0,9,202,
+ 81,7,13, 0,8,101, 0,8,37, 0,9,170,
+ 0,8,5, 0,8,133, 0,8,69, 0,9,234,
+ 80,7,8, 0,8,93, 0,8,29, 0,9,154,
+ 84,7,83, 0,8,125, 0,8,61, 0,9,218,
+ 82,7,23, 0,8,109, 0,8,45, 0,9,186,
+ 0,8,13, 0,8,141, 0,8,77, 0,9,250,
+ 80,7,3, 0,8,83, 0,8,19, 85,8,195,
+ 83,7,35, 0,8,115, 0,8,51, 0,9,198,
+ 81,7,11, 0,8,99, 0,8,35, 0,9,166,
+ 0,8,3, 0,8,131, 0,8,67, 0,9,230,
+ 80,7,7, 0,8,91, 0,8,27, 0,9,150,
+ 84,7,67, 0,8,123, 0,8,59, 0,9,214,
+ 82,7,19, 0,8,107, 0,8,43, 0,9,182,
+ 0,8,11, 0,8,139, 0,8,75, 0,9,246,
+ 80,7,5, 0,8,87, 0,8,23, 192,8,0,
+ 83,7,51, 0,8,119, 0,8,55, 0,9,206,
+ 81,7,15, 0,8,103, 0,8,39, 0,9,174,
+ 0,8,7, 0,8,135, 0,8,71, 0,9,238,
+ 80,7,9, 0,8,95, 0,8,31, 0,9,158,
+ 84,7,99, 0,8,127, 0,8,63, 0,9,222,
+ 82,7,27, 0,8,111, 0,8,47, 0,9,190,
+ 0,8,15, 0,8,143, 0,8,79, 0,9,254,
+ 96,7,256, 0,8,80, 0,8,16, 84,8,115,
+ 82,7,31, 0,8,112, 0,8,48, 0,9,193,
+
+ 80,7,10, 0,8,96, 0,8,32, 0,9,161,
+ 0,8,0, 0,8,128, 0,8,64, 0,9,225,
+ 80,7,6, 0,8,88, 0,8,24, 0,9,145,
+ 83,7,59, 0,8,120, 0,8,56, 0,9,209,
+ 81,7,17, 0,8,104, 0,8,40, 0,9,177,
+ 0,8,8, 0,8,136, 0,8,72, 0,9,241,
+ 80,7,4, 0,8,84, 0,8,20, 85,8,227,
+ 83,7,43, 0,8,116, 0,8,52, 0,9,201,
+ 81,7,13, 0,8,100, 0,8,36, 0,9,169,
+ 0,8,4, 0,8,132, 0,8,68, 0,9,233,
+ 80,7,8, 0,8,92, 0,8,28, 0,9,153,
+ 84,7,83, 0,8,124, 0,8,60, 0,9,217,
+ 82,7,23, 0,8,108, 0,8,44, 0,9,185,
+ 0,8,12, 0,8,140, 0,8,76, 0,9,249,
+ 80,7,3, 0,8,82, 0,8,18, 85,8,163,
+ 83,7,35, 0,8,114, 0,8,50, 0,9,197,
+ 81,7,11, 0,8,98, 0,8,34, 0,9,165,
+ 0,8,2, 0,8,130, 0,8,66, 0,9,229,
+ 80,7,7, 0,8,90, 0,8,26, 0,9,149,
+ 84,7,67, 0,8,122, 0,8,58, 0,9,213,
+ 82,7,19, 0,8,106, 0,8,42, 0,9,181,
+ 0,8,10, 0,8,138, 0,8,74, 0,9,245,
+ 80,7,5, 0,8,86, 0,8,22, 192,8,0,
+ 83,7,51, 0,8,118, 0,8,54, 0,9,205,
+ 81,7,15, 0,8,102, 0,8,38, 0,9,173,
+ 0,8,6, 0,8,134, 0,8,70, 0,9,237,
+ 80,7,9, 0,8,94, 0,8,30, 0,9,157,
+ 84,7,99, 0,8,126, 0,8,62, 0,9,221,
+ 82,7,27, 0,8,110, 0,8,46, 0,9,189,
+ 0,8,14, 0,8,142, 0,8,78, 0,9,253,
+ 96,7,256, 0,8,81, 0,8,17, 85,8,131,
+ 82,7,31, 0,8,113, 0,8,49, 0,9,195,
+ 80,7,10, 0,8,97, 0,8,33, 0,9,163,
+ 0,8,1, 0,8,129, 0,8,65, 0,9,227,
+ 80,7,6, 0,8,89, 0,8,25, 0,9,147,
+ 83,7,59, 0,8,121, 0,8,57, 0,9,211,
+ 81,7,17, 0,8,105, 0,8,41, 0,9,179,
+ 0,8,9, 0,8,137, 0,8,73, 0,9,243,
+ 80,7,4, 0,8,85, 0,8,21, 80,8,258,
+ 83,7,43, 0,8,117, 0,8,53, 0,9,203,
+ 81,7,13, 0,8,101, 0,8,37, 0,9,171,
+ 0,8,5, 0,8,133, 0,8,69, 0,9,235,
+ 80,7,8, 0,8,93, 0,8,29, 0,9,155,
+ 84,7,83, 0,8,125, 0,8,61, 0,9,219,
+ 82,7,23, 0,8,109, 0,8,45, 0,9,187,
+ 0,8,13, 0,8,141, 0,8,77, 0,9,251,
+ 80,7,3, 0,8,83, 0,8,19, 85,8,195,
+ 83,7,35, 0,8,115, 0,8,51, 0,9,199,
+ 81,7,11, 0,8,99, 0,8,35, 0,9,167,
+ 0,8,3, 0,8,131, 0,8,67, 0,9,231,
+ 80,7,7, 0,8,91, 0,8,27, 0,9,151,
+ 84,7,67, 0,8,123, 0,8,59, 0,9,215,
+ 82,7,19, 0,8,107, 0,8,43, 0,9,183,
+ 0,8,11, 0,8,139, 0,8,75, 0,9,247,
+ 80,7,5, 0,8,87, 0,8,23, 192,8,0,
+ 83,7,51, 0,8,119, 0,8,55, 0,9,207,
+ 81,7,15, 0,8,103, 0,8,39, 0,9,175,
+ 0,8,7, 0,8,135, 0,8,71, 0,9,239,
+ 80,7,9, 0,8,95, 0,8,31, 0,9,159,
+ 84,7,99, 0,8,127, 0,8,63, 0,9,223,
+ 82,7,27, 0,8,111, 0,8,47, 0,9,191,
+ 0,8,15, 0,8,143, 0,8,79, 0,9,255
+ };
+ static readonly int[] fixed_td = {
+ 80,5,1, 87,5,257, 83,5,17, 91,5,4097,
+ 81,5,5, 89,5,1025, 85,5,65, 93,5,16385,
+ 80,5,3, 88,5,513, 84,5,33, 92,5,8193,
+ 82,5,9, 90,5,2049, 86,5,129, 192,5,24577,
+ 80,5,2, 87,5,385, 83,5,25, 91,5,6145,
+ 81,5,7, 89,5,1537, 85,5,97, 93,5,24577,
+ 80,5,4, 88,5,769, 84,5,49, 92,5,12289,
+ 82,5,13, 90,5,3073, 86,5,193, 192,5,24577
+ };
+
+ // Tables for deflate from PKZIP's appnote.txt.
+ static readonly int[] cplens = { // Copy lengths for literal codes 257..285
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
+ };
+
+ // see note #13 above about 258
+ static readonly int[] cplext = { // Extra bits for literal codes 257..285
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+ 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112 // 112==invalid
+ };
+
+ static readonly int[] cpdist = { // Copy offsets for distance codes 0..29
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+ 8193, 12289, 16385, 24577
+ };
+
+ static readonly int[] cpdext = { // Extra bits for distance codes
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+ 12, 12, 13, 13};
+
+ // If BMAX needs to be larger than 16, then h and x[] should be uLong.
+ const int BMAX = 15; // maximum bit length of any code
+
+ int[] hn = null; // hufts used in space
+ int[] v = null; // work area for huft_build
+ int[] c = null; // bit length count table
+ int[] r = null; // table entry for structure assignment
+ int[] u = null; // table stack
+ int[] x = null; // bit offsets, then code stack
+
+ private ZLibStatus HuftBuild(int[] b, // code lengths in bits (all assumed <= BMAX)
+ int bindex,
+ int n, // number of codes (assumed <= 288)
+ int s, // number of simple-valued codes (0..s-1)
+ int[] d, // list of base values for non-simple codes
+ int[] e, // list of extra bits for non-simple codes
+ int[] t, // result: starting table
+ int[] m, // maximum lookup bits, returns actual
+ int[] hp,// space for trees
+ int[] hn,// hufts used in space
+ int[] v // working area: values in order of bit length
+ )
+ {
+ // Given a list of code lengths and a maximum table size, make a set of
+ // tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR
+ // if the given code set is incomplete (the tables are still built in this
+ // case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of
+ // lengths), or Z_MEM_ERROR if not enough memory.
+
+ int a; // counter for codes of length k
+ int f; // i repeats in table every f entries
+ int g; // maximum code length
+ int h; // table level
+ int i; // counter, current code
+ int j; // counter
+ int k; // number of bits in current code
+ int l; // bits per table (returned in m)
+ int mask; // (1 << w) - 1, to avoid cc -O bug on HP
+ int p; // pointer into c[], b[], or v[]
+ int q; // points to current table
+ int w; // bits before this table == (l * h)
+ int xp; // pointer into x
+ int y; // number of dummy codes added
+ int z; // number of entries in current table
+
+ // Generate counts for each bit length
+
+ p = 0; i = n;
+ do
+ {
+ c[b[bindex + p]]++; p++; i--; // assume all entries <= BMAX
+ } while (i != 0);
+
+ if (c[0] == n)
+ { // null input--all zero length codes
+ t[0] = -1;
+ m[0] = 0;
+ return ZLibStatus.Z_OK;
+ }
+
+ // Find minimum and maximum length, bound *m by those
+ l = m[0];
+ for (j = 1; j <= BMAX; j++)
+ if (c[j] != 0) break;
+ k = j; // minimum code length
+ if (l < j)
+ {
+ l = j;
+ }
+ for (i = BMAX; i != 0; i--)
+ {
+ if (c[i] != 0) break;
+ }
+ g = i; // maximum code length
+ if (l > i)
+ {
+ l = i;
+ }
+ m[0] = l;
+
+ // Adjust last length count to fill out codes, if needed
+ for (y = 1 << j; j < i; j++, y <<= 1)
+ {
+ if ((y -= c[j]) < 0)
+ {
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ }
+ if ((y -= c[i]) < 0)
+ {
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ c[i] += y;
+
+ // Generate starting offsets into the value table for each length
+ x[1] = j = 0;
+ p = 1; xp = 2;
+ while (--i != 0)
+ { // note that i == g from above
+ x[xp] = (j += c[p]);
+ xp++;
+ p++;
+ }
+
+ // Make a table of values in order of bit lengths
+ i = 0; p = 0;
+ do
+ {
+ if ((j = b[bindex + p]) != 0)
+ {
+ v[x[j]++] = i;
+ }
+ p++;
+ }
+ while (++i < n);
+ n = x[g]; // set n to length of v
+
+ // Generate the Huffman codes and for each, make the table entries
+ x[0] = i = 0; // first Huffman code is zero
+ p = 0; // grab values in bit order
+ h = -1; // no tables yet--level -1
+ w = -l; // bits decoded == (l * h)
+ u[0] = 0; // just to keep compilers happy
+ q = 0; // ditto
+ z = 0; // ditto
+
+ // go through the bit lengths (k already is bits in shortest code)
+ for (; k <= g; k++)
+ {
+ a = c[k];
+ while (a-- != 0)
+ {
+ // here i is the Huffman code of length k bits for value *p
+ // make tables up to required level
+ while (k > w + l)
+ {
+ h++;
+ w += l; // previous table always l bits
+ // compute minimum size table less than or equal to l bits
+ z = g - w;
+ z = (z > l) ? l : z; // table size upper limit
+ if ((f = 1 << (j = k - w)) > a + 1)
+ { // try a k-w bit table
+ // too few codes for k-w bit table
+ f -= a + 1; // deduct codes from patterns left
+ xp = k;
+ if (j < z)
+ {
+ while (++j < z)
+ { // try smaller tables up to z bits
+ if ((f <<= 1) <= c[++xp])
+ break; // enough codes to use up j bits
+ f -= c[xp]; // else deduct codes from patterns
+ }
+ }
+ }
+ z = 1 << j; // table entries for j-bit table
+
+ // allocate new table
+ if (hn[0] + z > MANY)
+ { // (note: doesn't matter for fixed)
+ return ZLibStatus.Z_DATA_ERROR; // overflow of MANY
+ }
+ u[h] = q = /*hp+*/ hn[0]; // DEBUG
+ hn[0] += z;
+
+ // connect to last table, if there is one
+ if (h != 0)
+ {
+ x[h] = i; // save pattern for backing up
+ r[0] = (byte)j; // bits in this table
+ r[1] = (byte)l; // bits to dump before this table
+ j = i >> (w - l);
+ r[2] = (int)(q - u[h - 1] - j); // offset to this table
+ System.Array.Copy(r, 0, hp, (u[h - 1] + j) * 3, 3); // connect to last table
+ }
+ else
+ {
+ t[0] = q; // first table is returned result
+ }
+ }
+
+ // set up table entry in r
+ r[1] = (byte)(k - w);
+ if (p >= n)
+ {
+ r[0] = 128 + 64; // out of values--invalid code
+ }
+ else if (v[p] < s)
+ {
+ r[0] = (byte)(v[p] < 256 ? 0 : 32 + 64); // 256 is end-of-block
+ r[2] = v[p++]; // simple code is just the value
+ }
+ else
+ {
+ r[0] = (byte)(e[v[p] - s] + 16 + 64); // non-simple--look up in lists
+ r[2] = d[v[p++] - s];
+ }
+
+ // fill code-like entries with r
+ f = 1 << (k - w);
+ for (j = i >> w; j < z; j += f)
+ {
+ System.Array.Copy(r, 0, hp, (q + j) * 3, 3);
+ }
+
+ // backwards increment the k-bit code i
+ for (j = 1 << (k - 1); (i & j) != 0; j >>= 1)
+ {
+ i ^= j;
+ }
+ i ^= j;
+
+ // backup over finished tables
+ mask = (1 << w) - 1; // needed on HP, cc -O bug
+ while ((i & mask) != x[h])
+ {
+ h--; // don't need to update q
+ w -= l;
+ mask = (1 << w) - 1;
+ }
+ }
+ }
+ // Return Z_BUF_ERROR if we were given an incomplete table
+ return y != 0 && g != 1 ? ZLibStatus.Z_BUF_ERROR : ZLibStatus.Z_OK;
+ }
+
+ internal ZLibStatus InflateTreesBits(int[] c, // 19 code lengths
+ int[] bb, // bits tree desired/actual depth
+ int[] tb, // bits tree result
+ int[] hp, // space for trees
+ ZStream z // for messages
+ )
+ {
+ ZLibStatus result;
+ InitWorkArea(19);
+ hn[0] = 0;
+ result = HuftBuild(c, 0, 19, 19, null, null, tb, bb, hp, hn, v);
+
+ if (result == ZLibStatus.Z_DATA_ERROR)
+ {
+ z.msg = "oversubscribed dynamic bit lengths tree";
+ }
+ else if (result == ZLibStatus.Z_BUF_ERROR || bb[0] == 0)
+ {
+ z.msg = "incomplete dynamic bit lengths tree";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ return result;
+ }
+
+ internal ZLibStatus InflateTreesDynamic(int nl, // number of literal/length codes
+ int nd, // number of distance codes
+ int[] c, // that many (total) code lengths
+ int[] bl, // literal desired/actual bit depth
+ int[] bd, // distance desired/actual bit depth
+ int[] tl, // literal/length tree result
+ int[] td, // distance tree result
+ int[] hp, // space for trees
+ ZStream z // for messages
+ )
+ {
+ ZLibStatus result;
+
+ // build literal/length tree
+ InitWorkArea(288);
+ hn[0] = 0;
+ result = HuftBuild(c, 0, nl, 257, cplens, cplext, tl, bl, hp, hn, v);
+ if (result != ZLibStatus.Z_OK || bl[0] == 0)
+ {
+ if (result == ZLibStatus.Z_DATA_ERROR)
+ {
+ z.msg = "oversubscribed literal/length tree";
+ }
+ else if (result != ZLibStatus.Z_MEM_ERROR)
+ {
+ z.msg = "incomplete literal/length tree";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ return result;
+ }
+
+ // build distance tree
+ InitWorkArea(288);
+ result = HuftBuild(c, nl, nd, 0, cpdist, cpdext, td, bd, hp, hn, v);
+
+ if (result != ZLibStatus.Z_OK || (bd[0] == 0 && nl > 257))
+ {
+ if (result == ZLibStatus.Z_DATA_ERROR)
+ {
+ z.msg = "oversubscribed distance tree";
+ }
+ else if (result == ZLibStatus.Z_BUF_ERROR)
+ {
+ z.msg = "incomplete distance tree";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ else if (result != ZLibStatus.Z_MEM_ERROR)
+ {
+ z.msg = "empty distance tree with lengths";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ return result;
+ }
+
+ return ZLibStatus.Z_OK;
+ }
+
+ internal static ZLibStatus InflateTreesFixed(int[] bl, //literal desired/actual bit depth
+ int[] bd, //distance desired/actual bit depth
+ int[][] tl,//literal/length tree result
+ int[][] td,//distance tree result
+ ZStream z //for memory allocation
+ )
+ {
+ bl[0] = fixed_bl;
+ bd[0] = fixed_bd;
+ tl[0] = fixed_tl;
+ td[0] = fixed_td;
+ return ZLibStatus.Z_OK;
+ }
+
+ private void InitWorkArea(int vsize)
+ {
+ if (hn == null)
+ {
+ hn = new int[1];
+ v = new int[vsize];
+ c = new int[BMAX + 1];
+ r = new int[3];
+ u = new int[BMAX];
+ x = new int[BMAX + 1];
+ }
+ if (v.Length < vsize) { v = new int[vsize]; }
+ for (int i = 0; i < vsize; i++) { v[i] = 0; }
+ for (int i = 0; i < BMAX + 1; i++) { c[i] = 0; }
+ for (int i = 0; i < 3; i++) { r[i] = 0; }
+ // for(int i=0; i>7)]);
+ }
+
+ internal short[] dyn_tree; // the dynamic tree
+ internal int max_code; // largest code with non zero frequency
+ internal StaticTree stat_desc; // the corresponding static tree
+
+ // Compute the optimal bit lengths for a tree and update the total bit length
+ // for the current block.
+ // IN assertion: the fields freq and dad are set, heap[heap_max] and
+ // above are the tree nodes sorted by increasing frequency.
+ // OUT assertions: the field len is set to the optimal bit length, the
+ // array bl_count contains the frequencies for each bit length.
+ // The length opt_len is updated; static_len is also updated if stree is
+ // not null.
+ internal void gen_bitlen(Deflate s){
+ short[] tree = dyn_tree;
+ short[] stree = stat_desc.static_tree;
+ int[] extra = stat_desc.extra_bits;
+ int based = stat_desc.extra_base;
+ int max_length = stat_desc.max_length;
+ int h; // heap index
+ int n, m; // iterate over the tree elements
+ int bits; // bit length
+ int xbits; // extra bits
+ short f; // frequency
+ int overflow = 0; // number of elements with bit length too large
+
+ for (bits = 0; bits <= MAX_BITS; bits++) s.bl_count[bits] = 0;
+
+ // In a first pass, compute the optimal bit lengths (which may
+ // overflow in the case of the bit length tree).
+ tree[s.heap[s.heap_max]*2+1] = 0; // root of the heap
+
+ for(h=s.heap_max+1; h max_length){ bits = max_length; overflow++; }
+ tree[n*2+1] = (short)bits;
+ // We overwrite tree[n*2+1] which is no longer needed
+
+ if (n > max_code) continue; // not a leaf node
+
+ s.bl_count[bits]++;
+ xbits = 0;
+ if (n >= based) xbits = extra[n-based];
+ f = tree[n*2];
+ s.opt_len += f * (bits + xbits);
+ if (stree!=null) s.static_len += f * (stree[n*2+1] + xbits);
+ }
+ if (overflow == 0) return;
+
+ // This happens for example on obj2 and pic of the Calgary corpus
+ // Find the first bit length which could increase:
+ do {
+ bits = max_length-1;
+ while(s.bl_count[bits]==0) bits--;
+ s.bl_count[bits]--; // move one leaf down the tree
+ s.bl_count[bits+1]+=2; // move one overflow item as its brother
+ s.bl_count[max_length]--;
+ // The brother of the overflow item also moves one step up,
+ // but this does not affect bl_count[max_length]
+ overflow -= 2;
+ }
+ while (overflow > 0);
+
+ for (bits = max_length; bits != 0; bits--) {
+ n = s.bl_count[bits];
+ while (n != 0) {
+ m = s.heap[--h];
+ if (m > max_code) continue;
+ if (tree[m*2+1] != bits) {
+ s.opt_len += (int)(((long)bits - (long)tree[m*2+1])*(long)tree[m*2]);
+ tree[m*2+1] = (short)bits;
+ }
+ n--;
+ }
+ }
+ }
+
+ // Construct one Huffman tree and assigns the code bit strings and lengths.
+ // Update the total bit length for the current block.
+ // IN assertion: the field freq is set for all tree elements.
+ // OUT assertions: the fields len and code are set to the optimal bit length
+ // and corresponding code. The length opt_len is updated; static_len is
+ // also updated if stree is not null. The field max_code is set.
+ internal void build_tree(Deflate s){
+ short[] tree=dyn_tree;
+ short[] stree=stat_desc.static_tree;
+ int elems=stat_desc.elems;
+ int n, m; // iterate over heap elements
+ int max_code=-1; // largest code with non zero frequency
+ int node; // new node being created
+
+ // Construct the initial heap, with least frequent element in
+ // heap[1]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
+ // heap[0] is not used.
+ s.heap_len = 0;
+ s.heap_max = HEAP_SIZE;
+
+ for(n=0; n=1; n--)
+ s.pqdownheap(tree, n);
+
+ // Construct the Huffman tree by repeatedly combining the least two
+ // frequent nodes.
+
+ node=elems; // next internal node of the tree
+ do{
+ // n = node of least frequency
+ n=s.heap[1];
+ s.heap[1]=s.heap[s.heap_len--];
+ s.pqdownheap(tree, 1);
+ m=s.heap[1]; // m = node of next least frequency
+
+ s.heap[--s.heap_max] = n; // keep the nodes sorted by frequency
+ s.heap[--s.heap_max] = m;
+
+ // Create a new node father of n and m
+ tree[node*2] = (short)(tree[n*2] + tree[m*2]);
+ s.depth[node] = (byte)(System.Math.Max(s.depth[n],s.depth[m])+1);
+ tree[n*2+1] = tree[m*2+1] = (short)node;
+
+ // and insert the new node in the heap
+ s.heap[1] = node++;
+ s.pqdownheap(tree, 1);
+ }
+ while(s.heap_len>=2);
+
+ s.heap[--s.heap_max] = s.heap[1];
+
+ // At this point, the fields freq and dad are set. We can now
+ // generate the bit lengths.
+
+ gen_bitlen(s);
+
+ // The field len is now set, we can generate the bit codes
+ gen_codes(tree, max_code, s.bl_count);
+ }
+
+ // Generate the codes for a given tree and bit counts (which need not be
+ // optimal).
+ // IN assertion: the array bl_count contains the bit length statistics for
+ // the given tree and the field len is set for all tree elements.
+ // OUT assertion: the field code is set for all tree elements of non
+ // zero code length.
+ internal static void gen_codes(short[] tree, // the tree to decorate
+ int max_code, // largest code with non zero frequency
+ short[] bl_count // number of codes at each bit length
+ ){
+ short[] next_code=new short[MAX_BITS+1]; // next code value for each bit length
+ short code = 0; // running code value
+ int bits; // bit index
+ int n; // code index
+
+ // The distribution counts are first used to generate the code values
+ // without bit reversal.
+ for (bits = 1; bits <= MAX_BITS; bits++) {
+ next_code[bits] = code = (short)((code + bl_count[bits-1]) << 1);
+ }
+
+ // Check that the bit counts in bl_count are consistent. The last code
+ // must be all ones.
+ //Assert (code + bl_count[MAX_BITS]-1 == (1<>=1;
+ res<<=1;
+ }
+ while(--len>0);
+ return res>>1;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Version.5/Adler32.cs b/Renci.SshNet/Compression/Version.5/Adler32.cs
new file mode 100644
index 0000000..c132fa9
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.5/Adler32.cs
@@ -0,0 +1,95 @@
+using System;
+/*
+ * $Id: Adler32.cs,v 1.1 2006-07-31 13:59:25 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ internal static class Adler32
+ {
+
+ // largest prime smaller than 65536
+ private const int BASE = 65521;
+ // NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
+ private const int NMAX = 5552;
+
+ internal static long adler32(long adler, byte[] buf, int index, int len)
+ {
+ if (buf == null) { return 1L; }
+
+ long s1 = adler & 0xffff;
+ long s2 = (adler >> 16) & 0xffff;
+ int k;
+
+ while (len > 0)
+ {
+ k = len < NMAX ? len : NMAX;
+ len -= k;
+ while (k >= 16)
+ {
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ k -= 16;
+ }
+ if (k != 0)
+ {
+ do
+ {
+ s1 += buf[index++] & 0xff; s2 += s1;
+ }
+ while (--k != 0);
+ }
+ s1 %= BASE;
+ s2 %= BASE;
+ }
+ return (s2 << 16) | s1;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Version.5/CompressionMode.cs b/Renci.SshNet/Compression/Version.5/CompressionMode.cs
new file mode 100644
index 0000000..1577e0b
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.5/CompressionMode.cs
@@ -0,0 +1,18 @@
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Specifies compression modes
+ ///
+ public enum CompressionMode
+ {
+ ///
+ /// Specifies that content should be compressed.
+ ///
+ Compress = 0,
+
+ ///
+ /// Specifies that content should be decompressed.
+ ///
+ Decompress = 1,
+ }
+}
diff --git a/Renci.SshNet/Compression/Version.5/Compressor.cs b/Renci.SshNet/Compression/Version.5/Compressor.cs
new file mode 100644
index 0000000..1479bb6
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.5/Compressor.cs
@@ -0,0 +1,151 @@
+using System.Collections.Generic;
+using Renci.SshNet.Security;
+using System.IO;
+using System;
+
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Represents base class for compression algorithm implementation
+ ///
+ public abstract class Compressor : Algorithm, IDisposable
+ {
+ private readonly ZlibStream _compressor;
+ private readonly ZlibStream _decompressor;
+
+ private MemoryStream _compressorStream;
+ private MemoryStream _decompressorStream;
+
+ ///
+ /// Gets or sets a value indicating whether compression is active.
+ ///
+ ///
+ /// true if compression is active; otherwise, false.
+ ///
+ protected bool IsActive { get; set; }
+
+ ///
+ /// Gets the session.
+ ///
+ protected Session Session { get; private set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ 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);
+ }
+
+ ///
+ /// Initializes the algorithm
+ ///
+ /// The session.
+ public virtual void Init(Session session)
+ {
+ this.Session = session;
+ }
+
+ ///
+ /// Compresses the specified data.
+ ///
+ /// Data to compress.
+ /// Compressed 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();
+ }
+
+ ///
+ /// Decompresses the specified data.
+ ///
+ /// Compressed data.
+ /// Decompressed 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;
+
+ ///
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged ResourceMessages.
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Releases unmanaged and - optionally - managed resources
+ ///
+ /// true to release both managed and unmanaged resources; false to release only unmanaged ResourceMessages.
+ 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;
+ }
+ }
+
+ ///
+ /// Releases unmanaged resources and performs other cleanup operations before the
+ /// is reclaimed by garbage collection.
+ ///
+ ~Compressor()
+ {
+ // Do not re-create Dispose clean-up code here.
+ // Calling Dispose(false) is optimal in terms of
+ // readability and maintainability.
+ Dispose(false);
+ }
+
+ #endregion
+ }
+}
diff --git a/Renci.SshNet/Compression/Version.5/Deflate.cs b/Renci.SshNet/Compression/Version.5/Deflate.cs
new file mode 100644
index 0000000..4779218
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.5/Deflate.cs
@@ -0,0 +1,2400 @@
+using System;
+using System.Collections.Generic;
+/*
+ * $Id: Deflate.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public enum BlockType : byte
+ {
+ Z_BINARY = 0,
+ Z_ASCII = 1,
+ Z_UNKNOWN = 2
+ }
+
+ public enum DefalteFlavor : int
+ {
+ STORED = 0,
+ FAST = 1,
+ SLOW = 2
+ }
+
+ public sealed class Deflate : ZStream, ICompressor
+ {
+ private const int MAX_MEM_LEVEL = 9;
+
+ private const int Z_DEFAULT_COMPRESSION = -1;
+
+ private const int MAX_WBITS = 15; // 32K LZ77 window
+
+ private const int DEF_MEM_LEVEL = 8;
+
+ ///
+ /// The Bit length codes must not exceed MAX_BL_BITS bits
+ ///
+ private const int MAX_BL_BITS = 7;
+
+ // block not completed, need more input or more output
+ private const int NeedMore = 0;
+
+ // block flush performed
+ private const int BlockDone = 1;
+
+ // finish started, need only more output at next deflate
+ private const int FinishStarted = 2;
+
+ // finish done, accept no more input or output
+ private const int FinishDone = 3;
+
+ // preset dictionary flag in zlib header
+ private const int PRESET_DICT = 0x20;
+
+ private const int Z_VERSION_ERROR = -6;
+
+ private const int INIT_STATE = 42;
+ private const int BUSY_STATE = 113;
+ private const int FINISH_STATE = 666;
+
+ // The deflate compression method
+ private const int Z_DEFLATED = 8;
+
+ private const int STORED_BLOCK = 0;
+ private const int STATIC_TREES = 1;
+ private const int DYN_TREES = 2;
+
+ private const int Buf_size = 8 * 2;
+
+ // repeat previous bit length 3-6 times (2 bits of repeat count)
+ private const int REP_3_6 = 16;
+
+ // repeat a zero length 3-10 times (3 bits of repeat count)
+ private const int REPZ_3_10 = 17;
+
+ // repeat a zero length 11-138 times (7 bits of repeat count)
+ private const int REPZ_11_138 = 18;
+
+ private const int MIN_MATCH = 3;
+ private const int MAX_MATCH = 258;
+ private const int MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1);
+
+ private const int MAX_BITS = 15;
+ private const int D_CODES = 30;
+ private const int BL_CODES = 19;
+ private const int LENGTH_CODES = 29;
+ private const int LITERALS = 256;
+ private const int L_CODES = (LITERALS + 1 + LENGTH_CODES);
+ private const int HEAP_SIZE = (2 * L_CODES + 1);
+
+ private const int END_BLOCK = 256;
+
+ private static readonly IDictionary config_table = new Dictionary() {
+ {(CompressionLevel)0, new Config(0, 0, 0, 0, DefalteFlavor.STORED)},
+ {(CompressionLevel)1, new Config(4, 4, 8, 4, DefalteFlavor.FAST)},
+ {(CompressionLevel)2, new Config(4, 5, 16, 8, DefalteFlavor.FAST)},
+ {(CompressionLevel)3, new Config(4, 6, 32, 32, DefalteFlavor.FAST)},
+
+ {(CompressionLevel)4, new Config(4, 4, 16, 16, DefalteFlavor.SLOW)},
+ {(CompressionLevel)5, new Config(8, 16, 32, 32, DefalteFlavor.SLOW)},
+ {(CompressionLevel)6, new Config(8, 16, 128, 128, DefalteFlavor.SLOW)},
+ {(CompressionLevel)7, new Config(8, 32, 128, 256, DefalteFlavor.SLOW)},
+ {(CompressionLevel)8, new Config(32, 128, 258, 1024, DefalteFlavor.SLOW)},
+ {(CompressionLevel)9, new Config(32, 258, 258, 4096, DefalteFlavor.SLOW)},
+ };
+
+ #region Static definitions
+
+ private static readonly byte[] _length_code ={
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12,
+ 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
+ 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
+ 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
+ };
+
+ private static readonly int[] base_length = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
+ 64, 80, 96, 112, 128, 160, 192, 224, 0
+ };
+
+ private static readonly int[] base_dist = {
+ 0, 1, 2, 3, 4, 6, 8, 12, 16, 24,
+ 32, 48, 64, 96, 128, 192, 256, 384, 512, 768,
+ 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576
+ };
+
+ // extra bits for each length code
+ private static readonly int[] extra_lbits ={
+ 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0
+ };
+
+ // extra bits for each distance code
+ private static readonly int[] extra_dbits ={
+ 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13
+ };
+
+ // extra bits for each bit length code
+ private static readonly int[] extra_blbits ={
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7
+ };
+
+ private static readonly byte[] bl_order ={
+ 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
+
+ private static readonly short[] static_ltree = {
+ 12, 8, 140, 8, 76, 8, 204, 8, 44, 8,
+ 172, 8, 108, 8, 236, 8, 28, 8, 156, 8,
+ 92, 8, 220, 8, 60, 8, 188, 8, 124, 8,
+ 252, 8, 2, 8, 130, 8, 66, 8, 194, 8,
+ 34, 8, 162, 8, 98, 8, 226, 8, 18, 8,
+ 146, 8, 82, 8, 210, 8, 50, 8, 178, 8,
+ 114, 8, 242, 8, 10, 8, 138, 8, 74, 8,
+ 202, 8, 42, 8, 170, 8, 106, 8, 234, 8,
+ 26, 8, 154, 8, 90, 8, 218, 8, 58, 8,
+ 186, 8, 122, 8, 250, 8, 6, 8, 134, 8,
+ 70, 8, 198, 8, 38, 8, 166, 8, 102, 8,
+ 230, 8, 22, 8, 150, 8, 86, 8, 214, 8,
+ 54, 8, 182, 8, 118, 8, 246, 8, 14, 8,
+ 142, 8, 78, 8, 206, 8, 46, 8, 174, 8,
+ 110, 8, 238, 8, 30, 8, 158, 8, 94, 8,
+ 222, 8, 62, 8, 190, 8, 126, 8, 254, 8,
+ 1, 8, 129, 8, 65, 8, 193, 8, 33, 8,
+ 161, 8, 97, 8, 225, 8, 17, 8, 145, 8,
+ 81, 8, 209, 8, 49, 8, 177, 8, 113, 8,
+ 241, 8, 9, 8, 137, 8, 73, 8, 201, 8,
+ 41, 8, 169, 8, 105, 8, 233, 8, 25, 8,
+ 153, 8, 89, 8, 217, 8, 57, 8, 185, 8,
+ 121, 8, 249, 8, 5, 8, 133, 8, 69, 8,
+ 197, 8, 37, 8, 165, 8, 101, 8, 229, 8,
+ 21, 8, 149, 8, 85, 8, 213, 8, 53, 8,
+ 181, 8, 117, 8, 245, 8, 13, 8, 141, 8,
+ 77, 8, 205, 8, 45, 8, 173, 8, 109, 8,
+ 237, 8, 29, 8, 157, 8, 93, 8, 221, 8,
+ 61, 8, 189, 8, 125, 8, 253, 8, 19, 9,
+ 275, 9, 147, 9, 403, 9, 83, 9, 339, 9,
+ 211, 9, 467, 9, 51, 9, 307, 9, 179, 9,
+ 435, 9, 115, 9, 371, 9, 243, 9, 499, 9,
+ 11, 9, 267, 9, 139, 9, 395, 9, 75, 9,
+ 331, 9, 203, 9, 459, 9, 43, 9, 299, 9,
+ 171, 9, 427, 9, 107, 9, 363, 9, 235, 9,
+ 491, 9, 27, 9, 283, 9, 155, 9, 411, 9,
+ 91, 9, 347, 9, 219, 9, 475, 9, 59, 9,
+ 315, 9, 187, 9, 443, 9, 123, 9, 379, 9,
+ 251, 9, 507, 9, 7, 9, 263, 9, 135, 9,
+ 391, 9, 71, 9, 327, 9, 199, 9, 455, 9,
+ 39, 9, 295, 9, 167, 9, 423, 9, 103, 9,
+ 359, 9, 231, 9, 487, 9, 23, 9, 279, 9,
+ 151, 9, 407, 9, 87, 9, 343, 9, 215, 9,
+ 471, 9, 55, 9, 311, 9, 183, 9, 439, 9,
+ 119, 9, 375, 9, 247, 9, 503, 9, 15, 9,
+ 271, 9, 143, 9, 399, 9, 79, 9, 335, 9,
+ 207, 9, 463, 9, 47, 9, 303, 9, 175, 9,
+ 431, 9, 111, 9, 367, 9, 239, 9, 495, 9,
+ 31, 9, 287, 9, 159, 9, 415, 9, 95, 9,
+ 351, 9, 223, 9, 479, 9, 63, 9, 319, 9,
+ 191, 9, 447, 9, 127, 9, 383, 9, 255, 9,
+ 511, 9, 0, 7, 64, 7, 32, 7, 96, 7,
+ 16, 7, 80, 7, 48, 7, 112, 7, 8, 7,
+ 72, 7, 40, 7, 104, 7, 24, 7, 88, 7,
+ 56, 7, 120, 7, 4, 7, 68, 7, 36, 7,
+ 100, 7, 20, 7, 84, 7, 52, 7, 116, 7,
+ 3, 8, 131, 8, 67, 8, 195, 8, 35, 8,
+ 163, 8, 99, 8, 227, 8
+ };
+
+ private static readonly short[] static_dtree = {
+ 0, 5, 16, 5, 8, 5, 24, 5, 4, 5,
+ 20, 5, 12, 5, 28, 5, 2, 5, 18, 5,
+ 10, 5, 26, 5, 6, 5, 22, 5, 14, 5,
+ 30, 5, 1, 5, 17, 5, 9, 5, 25, 5,
+ 5, 5, 21, 5, 13, 5, 29, 5, 3, 5,
+ 19, 5, 11, 5, 27, 5, 7, 5, 23, 5
+ };
+ #endregion
+
+ private static readonly String[] z_errmsg = {
+ "need dictionary", // ZLibStatus.Z_NEED_DICT 2
+ "stream end", // ZLibStatus.Z_STREAM_END 1
+ "", // ZLibStatus.Z_OK 0
+ "file error", // ZLibStatus.Z_ERRNO (-1)
+ "stream error", // ZLibStatus.Z_STREAM_ERROR (-2)
+ "data error", // ZLibStatus.Z_DATA_ERROR (-3)
+ "insufficient memory", // Z_MEM_ERROR (-4)
+ "buffer error", // ZLibStatus.Z_BUF_ERROR (-5)
+ "incompatible version",// Z_VERSION_ERROR (-6)
+ ""
+ };
+
+
+
+ ///
+ /// pointer back to this zlib stream
+ ///
+ //private ZStream _stream;
+
+ ///
+ /// as the name implies
+ ///
+ private int _status;
+
+ private BlockType _dataType;
+
+ ///
+ /// STORED (for zip only) or DEFLATED
+ ///
+ private byte _method;
+
+ ///
+ /// size of pending_buf
+ ///
+ private int _pendingBufferSize;
+
+ ///
+ /// LZ77 window size (32K by default)
+ ///
+ private int _windowSize;
+
+ ///
+ /// log2(w_size) (8..16)
+ ///
+ private int _windowBits;
+
+ ///
+ /// w_size - 1
+ ///
+ private int _windowMask;
+
+ ///
+ /// Sliding window. Input bytes are read into the second half of the window,
+ /// and move to the first half later to keep a dictionary of at least wSize
+ /// bytes. With this organization, matches are limited to a distance of
+ /// wSize-MAX_MATCH bytes, but this ensures that IO is always
+ /// performed with a length multiple of the block size. Also, it limits
+ /// the window size to 64K, which is quite useful on MSDOS.
+ /// To do: use the user input buffer as sliding window.
+ ///
+ private byte[] _window;
+
+ ///
+ /// Actual size of window: 2*wSize, except when the user input buffer
+ /// is directly used as sliding window.
+ ///
+ private int _windowActualSize;
+
+ ///
+ /// Link to older string with same hash index. To limit the size of this
+ /// array to 64K, this link is maintained only for the last 32K strings.
+ /// An index in this array is thus a window index modulo 32K.
+ ///
+ private short[] _previous;
+
+ ///
+ /// Heads of the hash chains or NIL.
+ ///
+ private short[] _head;
+
+ ///
+ /// hash index of string to be inserted
+ ///
+ private int _insertedHashIndex;
+
+ ///
+ /// number of elements in hash table
+ ///
+ private int _hashSize;
+
+ ///
+ /// log2(hash_size)
+ ///
+ private int _hashBits;
+
+ ///
+ /// hash_size-1
+ ///
+ private int _hashMask;
+
+ ///
+ /// Number of bits by which ins_h must be shifted at each input
+ /// step. It must be such that after MIN_MATCH steps, the oldest
+ /// byte no longer takes part in the hash key, that is:
+ /// hash_shift * MIN_MATCH >= hash_bits
+ ///
+ private int _hashShift;
+
+ ///
+ /// Window position at the beginning of the current output block. Gets
+ /// negative when the window is moved backwards.
+ ///
+ private int _blockStart;
+
+ ///
+ /// length of best match
+ ///
+ private int _matchLength;
+
+ ///
+ /// previous match
+ ///
+ private int _previousMatch;
+
+ ///
+ /// set if previous match exists
+ ///
+ private bool _matchAvailable;
+
+ ///
+ /// start of string to insert
+ ///
+ private int _startInsertString;
+
+ ///
+ /// start of matching string
+ ///
+ private int _startMatchString;
+
+ ///
+ /// number of valid bytes ahead in window
+ ///
+ private int _validBytesAhead;
+
+ ///
+ /// Length of the best match at previous step. Matches not greater than this
+ /// are discarded. This is used in the lazy match evaluation.
+ ///
+ private int _previousLength;
+
+ ///
+ /// To speed up deflation, hash chains are never searched beyond this
+ /// length. A higher limit improves compression ratio but degrades the speed.
+ ///
+ private int _maxChainLength;
+
+ ///
+ /// Attempt to find a better match only when the current match is strictly
+ /// smaller than this value. This mechanism is used only for compression
+ /// levels >= 4.
+ ///
+ private int _maxLazyMatch;
+
+ // Insert new strings in the hash table only if the match length is not
+ // greater than this length. This saves time but degrades compression.
+ // max_insert_length is used only for compression levels <= 3.
+
+ ///
+ /// The compression level (1..9)
+ ///
+ private CompressionLevel level;
+
+ ///
+ /// The favor or force Huffman coding
+ ///
+ private CompressionStrategy strategy;
+
+ ///
+ /// Use a faster search when the previous match is longer than this
+ ///
+ private int good_match;
+
+ ///
+ /// Stop searching when current match exceeds this
+ ///
+ private int nice_match;
+
+ ///
+ /// literal and length tree
+ ///
+ private short[] dyn_ltree;
+
+ ///
+ /// The distance tree
+ ///
+ private short[] dyn_dtree;
+
+ ///
+ /// The Huffman tree for bit lengths
+ ///
+ private short[] bl_tree;
+
+ ///
+ /// The desc for literal tree
+ ///
+ private Tree l_desc = new Tree();
+
+ ///
+ /// The desc for distance tree
+ ///
+ private Tree d_desc = new Tree();
+
+ ///
+ /// The desc for bit length tree
+ ///
+ private Tree bl_desc = new Tree();
+
+ ///
+ /// index for literals or lengths
+ ///
+ private int l_buf;
+
+ ///
+ /// Size of match buffer for literals/lengths. There are 4 reasons for
+ /// limiting lit_bufsize to 64K:
+ /// - frequencies can be kept in 16 bit counters
+ /// - if compression is not successful for the first block, all input
+ /// data is still in the window so we can still emit a stored block even
+ /// when input comes from standard input. (This can also be done for
+ /// all blocks if lit_bufsize is not greater than 32K.)
+ /// - if compression is not successful for a file smaller than 64K, we can
+ /// even emit a stored file instead of a stored block (saving 5 bytes).
+ /// This is applicable only for zip (not gzip or zlib).
+ /// - creating new Huffman trees less frequently may not provide fast
+ /// adaptation to changes in the input data statistics. (Take for
+ /// example a binary file with poorly compressible code followed by
+ /// a highly compressible string table.) Smaller buffer sizes give
+ /// fast adaptation but have of course the overhead of transmitting
+ /// trees more frequently.
+ /// - I can't count above 4
+ ///
+ private int lit_bufsize;
+
+ ///
+ /// running index in l_buf
+ ///
+ private int last_lit;
+
+ // Buffer for distances. To simplify the code, d_buf and l_buf have
+ // the same number of elements. To use different lengths, an extra flag
+ // array would be necessary.
+
+ ///
+ /// The index of pendig_buf
+ ///
+ private int d_buf;
+
+ ///
+ /// The number of string matches in current block
+ ///
+ private int matches;
+
+ ///
+ /// The bit length of EOB code for last block
+ ///
+ private int last_eob_len;
+
+ ///
+ /// Output buffer. bits are inserted starting at the bottom (least
+ /// significant bits).
+ ///
+ private uint bi_buf;
+
+ ///
+ /// Number of valid bits in bi_buf. All bits above the last valid bit
+ /// are always zero.
+ ///
+ private int bi_valid;
+
+ ///
+ /// value of flush param for previous deflate call
+ ///
+ private FlushType last_flush;
+
+ ///
+ /// bit length of current block with optimal trees
+ ///
+ internal int opt_len;
+
+ ///
+ /// bit length of current block with static trees
+ ///
+ internal int static_len;
+
+ ///
+ /// The output still pending
+ ///
+ internal byte[] pending_buf;
+
+ ///
+ /// next pending byte to output to the stream
+ ///
+ internal int pending_out;
+
+ ///
+ /// nb of bytes in the pending buffer
+ ///
+ internal int pending;
+
+ ///
+ /// suppress zlib header and adler32
+ ///
+ internal int noheader;
+
+ ///
+ /// number of codes at each bit length for an optimal tree
+ ///
+ internal short[] bl_count = new short[MAX_BITS + 1];
+
+ ///
+ /// heap used to build the Huffman trees
+ ///
+ internal int[] heap = new int[2 * L_CODES + 1];
+
+ ///
+ /// The number of elements in the heap
+ ///
+ internal int heap_len;
+ ///
+ /// The element of largest frequency
+ ///
+ internal int heap_max;
+
+ // The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+ // The same heap array is used to build all trees.
+
+ ///
+ /// Depth of each subtree used as tie breaker for trees of equal frequency
+ ///
+ internal byte[] depth = new byte[2 * L_CODES + 1];
+
+ public Deflate()
+ {
+ dyn_ltree = new short[HEAP_SIZE * 2];
+ dyn_dtree = new short[(2 * D_CODES + 1) * 2]; // distance tree
+ bl_tree = new short[(2 * BL_CODES + 1) * 2]; // Huffman tree for bit lengths
+ }
+
+ // Restore the heap property by moving down the tree starting at node k,
+ // exchanging a node with the smallest of its two sons if necessary, stopping
+ // when the heap property is re-established (each father smaller than its
+ // two sons).
+ internal void pqdownheap(short[] tree, // the tree to restore
+ int k // node to move down
+ )
+ {
+ int v = heap[k];
+ int j = k << 1; // left son of k
+ while (j <= heap_len)
+ {
+ // Set j to the smallest of the two sons:
+ if (j < heap_len &&
+ smaller(tree, heap[j + 1], heap[j], depth))
+ {
+ j++;
+ }
+ // Exit if v is smaller than both sons
+ if (smaller(tree, v, heap[j], depth)) break;
+
+ // Exchange v with the smallest son
+ heap[k] = heap[j]; k = j;
+ // And continue down the tree, setting j to the left son of k
+ j <<= 1;
+ }
+ heap[k] = v;
+ }
+ internal ZLibStatus deflateInit(ZStream strm, CompressionLevel level, int bits)
+ {
+ return deflateInit2(strm, level, Z_DEFLATED, bits, DEF_MEM_LEVEL, CompressionStrategy.Z_DEFAULT_STRATEGY);
+ }
+
+ private ZLibStatus deflateInit2(ZStream strm, CompressionLevel level, int method, int windowBits, int memLevel, CompressionStrategy strategy)
+ {
+ int noheader = 0;
+ // byte[] my_version=ZLIB_VERSION;
+
+ //
+ // if (version == null || version[0] != my_version[0]
+ // || stream_size != sizeof(z_stream)) {
+ // return Z_VERSION_ERROR;
+ // }
+
+ strm.msg = null;
+
+ if (level == CompressionLevel.Z_DEFAULT_COMPRESSION) level = (CompressionLevel)6;
+
+ if (windowBits < 0)
+ { // undocumented feature: suppress zlib header
+ noheader = 1;
+ windowBits = -windowBits;
+ }
+
+ if (memLevel < 1 || memLevel > MAX_MEM_LEVEL ||
+ method != Z_DEFLATED ||
+ windowBits < 9 || windowBits > 15 || level < 0 || level > (CompressionLevel)9 ||
+ strategy < 0 || strategy > CompressionStrategy.Z_HUFFMAN_ONLY)
+ {
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+
+ this.noheader = noheader;
+ _windowBits = windowBits;
+ _windowSize = 1 << _windowBits;
+ _windowMask = _windowSize - 1;
+
+ _hashBits = memLevel + 7;
+ _hashSize = 1 << _hashBits;
+ _hashMask = _hashSize - 1;
+ _hashShift = ((_hashBits + MIN_MATCH - 1) / MIN_MATCH);
+
+ _window = new byte[_windowSize * 2];
+ _previous = new short[_windowSize];
+ _head = new short[_hashSize];
+
+ lit_bufsize = 1 << (memLevel + 6); // 16K elements by default
+
+ // We overlay pending_buf and d_buf+l_buf. This works since the average
+ // output size for (length,distance) codes is <= 24 bits.
+ pending_buf = new byte[lit_bufsize * 4];
+ _pendingBufferSize = lit_bufsize * 4;
+
+ d_buf = lit_bufsize / 2;
+ l_buf = (1 + 2) * lit_bufsize;
+
+ this.level = level;
+
+ //System.out.println("level="+level);
+
+ this.strategy = strategy;
+ this._method = (byte)method;
+
+ return deflateReset(strm);
+ }
+
+ private ZLibStatus deflateReset(ZStream strm)
+ {
+ strm.total_in = strm.total_out = 0;
+ strm.msg = null; //
+ strm.data_type = BlockType.Z_UNKNOWN;
+
+ pending = 0;
+ pending_out = 0;
+
+ if (noheader < 0)
+ {
+ noheader = 0; // was set to -1 by deflate(..., FlushType.Z_FINISH);
+ }
+ _status = (noheader != 0) ? BUSY_STATE : INIT_STATE;
+ strm.adler = Adler32.adler32(0, null, 0, 0);
+
+ last_flush = FlushType.Z_NO_FLUSH;
+
+ tr_init();
+ lm_init();
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus deflateEnd()
+ {
+ if (_status != INIT_STATE && _status != BUSY_STATE && _status != FINISH_STATE)
+ {
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+ // Deallocate in reverse order of allocations:
+ pending_buf = null;
+ _head = null;
+ _previous = null;
+ _window = null;
+ // free
+ // dstate=null;
+ return _status == BUSY_STATE ? ZLibStatus.Z_DATA_ERROR : ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus deflateParams(ZStream strm, CompressionLevel _level, CompressionStrategy _strategy)
+ {
+ ZLibStatus err = ZLibStatus.Z_OK;
+
+ if (_level == CompressionLevel.Z_DEFAULT_COMPRESSION)
+ {
+ _level = (CompressionLevel)6;
+ }
+ if (_level < 0 || _level > (CompressionLevel)9 ||
+ _strategy < 0 || _strategy > CompressionStrategy.Z_HUFFMAN_ONLY)
+ {
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+
+ if (config_table[level].Function != config_table[_level].Function &&
+ strm.total_in != 0)
+ {
+ // Flush the last buffer:
+ err = this.deflate(FlushType.Z_PARTIAL_FLUSH);
+ }
+
+ if (level != _level)
+ {
+ level = _level;
+ _maxLazyMatch = config_table[level].MaxLazy;
+ good_match = config_table[level].GoodLength;
+ nice_match = config_table[level].NiceLength;
+ _maxChainLength = config_table[level].MaxChain;
+ }
+ strategy = _strategy;
+ return err;
+ }
+
+ public ZLibStatus deflateSetDictionary(ZStream strm, byte[] dictionary, int dictLength)
+ {
+ int length = dictLength;
+ int index = 0;
+
+ if (dictionary == null || _status != INIT_STATE)
+ return ZLibStatus.Z_STREAM_ERROR;
+
+ strm.adler = Adler32.adler32(strm.adler, dictionary, 0, dictLength);
+
+ if (length < MIN_MATCH) return ZLibStatus.Z_OK;
+ if (length > _windowSize - MIN_LOOKAHEAD)
+ {
+ length = _windowSize - MIN_LOOKAHEAD;
+ index = dictLength - length; // use the tail of the dictionary
+ }
+ System.Array.Copy(dictionary, index, _window, 0, length);
+ _startInsertString = length;
+ _blockStart = length;
+
+ // Insert all strings in the hash table (except for the last two bytes).
+ // s->lookahead stays null, so s->ins_h will be recomputed at the next
+ // call of fill_window.
+
+ _insertedHashIndex = _window[0] & 0xff;
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[1] & 0xff)) & _hashMask;
+
+ for (int n = 0; n <= length - MIN_MATCH; n++)
+ {
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[(n) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+ _previous[n & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)n;
+ }
+ return ZLibStatus.Z_OK;
+ }
+
+ //public ZLibStatus deflate(ZStream strm, FlushType flush)
+ //{
+ // FlushType old_flush;
+
+ // if (flush > FlushType.Z_FINISH || flush < 0)
+ // {
+ // return ZLibStatus.Z_STREAM_ERROR;
+ // }
+
+ // if (strm.next_out == null ||
+ // (strm.next_in == null && strm.avail_in != 0) ||
+ // (_status == FINISH_STATE && flush != FlushType.Z_FINISH))
+ // {
+ // strm.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_STREAM_ERROR)];
+ // return ZLibStatus.Z_STREAM_ERROR;
+ // }
+ // if (strm.avail_out == 0)
+ // {
+ // strm.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_BUF_ERROR)];
+ // return ZLibStatus.Z_BUF_ERROR;
+ // }
+
+ // this._stream = strm; // just in case
+ // old_flush = last_flush;
+ // last_flush = flush;
+
+ // // Write the zlib header
+ // if (_status == INIT_STATE)
+ // {
+ // int header = (Z_DEFLATED + ((_windowBits - 8) << 4)) << 8;
+ // int level_flags = (((int)level - 1) & 0xff) >> 1;
+
+ // if (level_flags > 3) level_flags = 3;
+ // header |= (level_flags << 6);
+ // if (_startInsertString != 0) header |= PRESET_DICT;
+ // header += 31 - (header % 31);
+
+ // _status = BUSY_STATE;
+ // putShortMSB(header);
+
+
+ // // Save the adler32 of the preset dictionary:
+ // if (_startInsertString != 0)
+ // {
+ // putShortMSB((int)(strm.adler >> 16));
+ // putShortMSB((int)(strm.adler & 0xffff));
+ // }
+ // strm.adler = Adler32.adler32(0, null, 0, 0);
+ // }
+
+ // // Flush as much pending output as possible
+ // if (pending != 0)
+ // {
+ // strm.flush_pending();
+ // if (strm.avail_out == 0)
+ // {
+ // //System.out.println(" avail_out==0");
+ // // Since avail_out is 0, deflate will be called again with
+ // // more output space, but possibly with both pending and
+ // // avail_in equal to zero. There won't be anything to do,
+ // // but this is not an error situation so make sure we
+ // // return OK instead of BUF_ERROR at next call of deflate:
+ // last_flush = (FlushType)(-1);
+ // return ZLibStatus.Z_OK;
+ // }
+
+ // // Make sure there is something to do and avoid duplicate consecutive
+ // // flushes. For repeated and useless calls with FlushType.Z_FINISH, we keep
+ // // returning ZLibStatus.Z_STREAM_END instead of Z_BUFF_ERROR.
+ // }
+ // else if (strm.avail_in == 0 && flush <= old_flush &&
+ // flush != FlushType.Z_FINISH)
+ // {
+ // strm.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_BUF_ERROR)];
+ // return ZLibStatus.Z_BUF_ERROR;
+ // }
+
+ // // User must not provide more input after the first FINISH:
+ // if (_status == FINISH_STATE && strm.avail_in != 0)
+ // {
+ // strm.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_BUF_ERROR)];
+ // return ZLibStatus.Z_BUF_ERROR;
+ // }
+
+ // // Start a new block or continue the current one.
+ // if (strm.avail_in != 0 || _validBytesAhead != 0 ||
+ // (flush != FlushType.Z_NO_FLUSH && _status != FINISH_STATE))
+ // {
+ // int bstate = -1;
+ // switch (config_table[level].Function)
+ // {
+ // case DefalteFlavor.STORED:
+ // bstate = deflate_stored(flush);
+ // break;
+ // case DefalteFlavor.FAST:
+ // bstate = deflate_fast(flush);
+ // break;
+ // case DefalteFlavor.SLOW:
+ // bstate = deflate_slow(flush);
+ // break;
+ // default:
+ // break;
+ // }
+
+ // if (bstate == FinishStarted || bstate == FinishDone)
+ // {
+ // _status = FINISH_STATE;
+ // }
+ // if (bstate == NeedMore || bstate == FinishStarted)
+ // {
+ // if (strm.avail_out == 0)
+ // {
+ // last_flush = (FlushType)(-1); // avoid BUF_ERROR next call, see above
+ // }
+ // return ZLibStatus.Z_OK;
+ // // If flush != FlushType.Z_NO_FLUSH && avail_out == 0, the next call
+ // // of deflate should use the same flush parameter to make sure
+ // // that the flush is complete. So we don't have to output an
+ // // empty block here, this will be done at next call. This also
+ // // ensures that for a very small output buffer, we emit at most
+ // // one empty block.
+ // }
+
+ // if (bstate == BlockDone)
+ // {
+ // if (flush == FlushType.Z_PARTIAL_FLUSH)
+ // {
+ // _tr_align();
+ // }
+ // else
+ // { // FULL_FLUSH or SYNC_FLUSH
+ // _tr_stored_block(0, 0, false);
+ // // For a full flush, this empty block will be recognized
+ // // as a special marker by inflate_sync().
+ // if (flush == FlushType.Z_FULL_FLUSH)
+ // {
+ // //state.head[s.hash_size-1]=0;
+ // for (int i = 0; i < _hashSize/*-1*/; i++) // forget history
+ // _head[i] = 0;
+ // }
+ // }
+ // strm.flush_pending();
+ // if (strm.avail_out == 0)
+ // {
+ // last_flush = (FlushType)(-1); // avoid BUF_ERROR at next call, see above
+ // return ZLibStatus.Z_OK;
+ // }
+ // }
+ // }
+
+ // if (flush != FlushType.Z_FINISH) return ZLibStatus.Z_OK;
+ // if (noheader != 0) return ZLibStatus.Z_STREAM_END;
+
+ // // Write the zlib trailer (adler32)
+ // putShortMSB((int)(strm.adler >> 16));
+ // putShortMSB((int)(strm.adler & 0xffff));
+ // strm.flush_pending();
+
+ // // If avail_out is zero, the application will call deflate again
+ // // to flush the rest.
+ // noheader = -1; // write the trailer only once!
+ // return pending != 0 ? ZLibStatus.Z_OK : ZLibStatus.Z_STREAM_END;
+ //}
+
+ private void lm_init()
+ {
+ _windowActualSize = 2 * _windowSize;
+
+ _head[_hashSize - 1] = 0;
+ for (int i = 0; i < _hashSize - 1; i++)
+ {
+ _head[i] = 0;
+ }
+
+ // Set the default configuration parameters:
+ _maxLazyMatch = Deflate.config_table[level].MaxLazy;
+ good_match = Deflate.config_table[level].GoodLength;
+ nice_match = Deflate.config_table[level].NiceLength;
+ _maxChainLength = Deflate.config_table[level].MaxChain;
+
+ _startInsertString = 0;
+ _blockStart = 0;
+ _validBytesAhead = 0;
+ _matchLength = _previousLength = MIN_MATCH - 1;
+ _matchAvailable = false;
+ _insertedHashIndex = 0;
+ }
+
+ // Initialize the tree data structures for a new zlib stream.
+ private void tr_init()
+ {
+
+ l_desc.Init(dyn_ltree, Deflate.static_l_desc);
+
+ d_desc.Init(dyn_dtree, Deflate.static_d_desc);
+
+ bl_desc.Init(bl_tree, Deflate.static_bl_desc);
+
+
+ bi_buf = 0;
+ bi_valid = 0;
+ last_eob_len = 8; // enough lookahead for inflate
+
+ // Initialize the first block of the first file:
+ init_block();
+ }
+
+ private void init_block()
+ {
+ // Initialize the trees.
+ for (int i = 0; i < L_CODES; i++) dyn_ltree[i * 2] = 0;
+ for (int i = 0; i < D_CODES; i++) dyn_dtree[i * 2] = 0;
+ for (int i = 0; i < BL_CODES; i++) bl_tree[i * 2] = 0;
+
+ dyn_ltree[END_BLOCK * 2] = 1;
+ opt_len = static_len = 0;
+ last_lit = matches = 0;
+ }
+
+ private static bool smaller(short[] tree, int n, int m, byte[] depth)
+ {
+ short tn2 = tree[n * 2];
+ short tm2 = tree[m * 2];
+ return (tn2 < tm2 ||
+ (tn2 == tm2 && depth[n] <= depth[m]));
+ }
+
+ // Scan a literal or distance tree to determine the frequencies of the codes
+ // in the bit length tree.
+ private void scan_tree(short[] tree,// the tree to be scanned
+ int max_code // and its largest code of non zero frequency
+ )
+ {
+ int n; // iterates over all tree elements
+ int prevlen = -1; // last emitted length
+ int curlen; // length of current code
+ int nextlen = tree[0 * 2 + 1]; // length of next code
+ int count = 0; // repeat count of the current code
+ int max_count = 7; // max repeat count
+ int min_count = 4; // min repeat count
+
+ if (nextlen == 0) { max_count = 138; min_count = 3; }
+ tree[(max_code + 1) * 2 + 1] = -1; // guard
+
+ for (n = 0; n <= max_code; n++)
+ {
+ curlen = nextlen; nextlen = tree[(n + 1) * 2 + 1];
+ if (++count < max_count && curlen == nextlen)
+ {
+ continue;
+ }
+ else if (count < min_count)
+ {
+ bl_tree[curlen * 2] += (short)count;
+ }
+ else if (curlen != 0)
+ {
+ if (curlen != prevlen) bl_tree[curlen * 2]++;
+ bl_tree[REP_3_6 * 2]++;
+ }
+ else if (count <= 10)
+ {
+ bl_tree[REPZ_3_10 * 2]++;
+ }
+ else
+ {
+ bl_tree[REPZ_11_138 * 2]++;
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0)
+ {
+ max_count = 138; min_count = 3;
+ }
+ else if (curlen == nextlen)
+ {
+ max_count = 6; min_count = 3;
+ }
+ else
+ {
+ max_count = 7; min_count = 4;
+ }
+ }
+ }
+
+ // Construct the Huffman tree for the bit lengths and return the index in
+ // bl_order of the last bit length code to send.
+ private int build_bl_tree()
+ {
+ int max_blindex; // index of last bit length code of non zero freq
+
+ // Determine the bit length frequencies for literal and distance trees
+ scan_tree(dyn_ltree, l_desc.LargestCode);
+ scan_tree(dyn_dtree, d_desc.LargestCode);
+
+ // Build the bit length tree:
+ bl_desc.BuildTree(this);
+ // opt_len now includes the length of the tree representations, except
+ // the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
+
+ // Determine the number of bit length codes to send. The pkzip format
+ // requires that at least 4 bit length codes be sent. (appnote.txt says
+ // 3 but the actual value used is 4.)
+ for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--)
+ {
+ if (bl_tree[Deflate.bl_order[max_blindex] * 2 + 1] != 0) break;
+ }
+ // Update opt_len to include the bit length tree and counts
+ opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4;
+
+ return max_blindex;
+ }
+
+
+ // Send the header for a block using dynamic Huffman trees: the counts, the
+ // lengths of the bit length codes, the literal tree and the distance tree.
+ // IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
+ private void send_all_trees(int lcodes, int dcodes, int blcodes)
+ {
+ int rank; // index in bl_order
+
+ send_bits(lcodes - 257, 5); // not +255 as stated in appnote.txt
+ send_bits(dcodes - 1, 5);
+ send_bits(blcodes - 4, 4); // not -3 as stated in appnote.txt
+ for (rank = 0; rank < blcodes; rank++)
+ {
+ send_bits(bl_tree[Deflate.bl_order[rank] * 2 + 1], 3);
+ }
+ send_tree(dyn_ltree, lcodes - 1); // literal tree
+ send_tree(dyn_dtree, dcodes - 1); // distance tree
+ }
+
+ // Send a literal or distance tree in compressed form, using the codes in
+ // bl_tree.
+ private void send_tree(short[] tree,// the tree to be sent
+ int max_code // and its largest code of non zero frequency
+ )
+ {
+ int n; // iterates over all tree elements
+ int prevlen = -1; // last emitted length
+ int curlen; // length of current code
+ int nextlen = tree[0 * 2 + 1]; // length of next code
+ int count = 0; // repeat count of the current code
+ int max_count = 7; // max repeat count
+ int min_count = 4; // min repeat count
+
+ if (nextlen == 0) { max_count = 138; min_count = 3; }
+
+ for (n = 0; n <= max_code; n++)
+ {
+ curlen = nextlen; nextlen = tree[(n + 1) * 2 + 1];
+ if (++count < max_count && curlen == nextlen)
+ {
+ continue;
+ }
+ else if (count < min_count)
+ {
+ do { send_code(curlen, bl_tree); } while (--count != 0);
+ }
+ else if (curlen != 0)
+ {
+ if (curlen != prevlen)
+ {
+ send_code(curlen, bl_tree); count--;
+ }
+ send_code(REP_3_6, bl_tree);
+ send_bits(count - 3, 2);
+ }
+ else if (count <= 10)
+ {
+ send_code(REPZ_3_10, bl_tree);
+ send_bits(count - 3, 3);
+ }
+ else
+ {
+ send_code(REPZ_11_138, bl_tree);
+ send_bits(count - 11, 7);
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0)
+ {
+ max_count = 138; min_count = 3;
+ }
+ else if (curlen == nextlen)
+ {
+ max_count = 6; min_count = 3;
+ }
+ else
+ {
+ max_count = 7; min_count = 4;
+ }
+ }
+ }
+
+ // Output a byte on the stream.
+ // IN assertion: there is enough room in pending_buf.
+ private void put_byte(byte[] p, int start, int len)
+ {
+ System.Array.Copy(p, start, pending_buf, pending, len);
+ pending += len;
+ }
+
+ private void put_byte(byte c)
+ {
+ pending_buf[pending++] = c;
+ }
+ private void put_short(int w)
+ {
+ pending_buf[pending++] = (byte)(w/*&0xff*/);
+ pending_buf[pending++] = (byte)(w >> 8);
+ }
+ private void putShortMSB(int b)
+ {
+ pending_buf[pending++] = (byte)(b >> 8);
+ pending_buf[pending++] = (byte)(b/*&0xff*/);
+ }
+
+ private void send_code(int c, short[] tree)
+ {
+ int c2 = c * 2;
+ send_bits((tree[c2] & 0xffff), (tree[c2 + 1] & 0xffff));
+ }
+
+ private void send_bits(int val, int length)
+ {
+ if (bi_valid > Buf_size - length)
+ {
+ bi_buf |= (uint)(val << bi_valid);
+ pending_buf[pending++] = (byte)(bi_buf/*&0xff*/);
+ pending_buf[pending++] = (byte)(bi_buf >> 8);
+ bi_buf = ((uint)val) >> (Buf_size - bi_valid);
+ bi_valid += length - Buf_size;
+ }
+ else
+ {
+ bi_buf |= (uint)(val << bi_valid);
+ bi_valid += length;
+ }
+ // int len = length;
+ // if (bi_valid > (int)Buf_size - len) {
+ // int val = value;
+ // // bi_buf |= (val << bi_valid);
+ // bi_buf = (short)((ushort)bi_buf | (ushort)((val << bi_valid)&0xffff));
+ // put_short(bi_buf);
+ // bi_buf = (short)(((uint)val) >> (Buf_size - bi_valid));
+ // bi_valid += len - Buf_size;
+ // } else {
+ // // bi_buf |= (value) << bi_valid;
+ // bi_buf = (short)((ushort)bi_buf | (ushort)(((value) << bi_valid)&0xffff));
+ // bi_valid += len;
+ // }
+ }
+
+ // Send one empty static block to give enough lookahead for inflate.
+ // This takes 10 bits, of which 7 may remain in the bit buffer.
+ // The current inflate code requires 9 bits of lookahead. If the
+ // last two codes for the previous block (real code plus EOB) were coded
+ // on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
+ // the last real code. In this case we send two empty static blocks instead
+ // of one. (There are no problems if the previous block is stored or fixed.)
+ // To simplify the code, we assume the worst case of last real code encoded
+ // on one bit only.
+ private void _tr_align()
+ {
+ send_bits(STATIC_TREES << 1, 3);
+ send_code(END_BLOCK, Deflate.static_ltree);
+
+ bi_flush();
+
+ // Of the 10 bits for the empty block, we have already sent
+ // (10 - bi_valid) bits. The lookahead for the last real code (before
+ // the EOB of the previous block) was thus at least one plus the length
+ // of the EOB plus what we have just sent of the empty static block.
+ if (1 + last_eob_len + 10 - bi_valid < 9)
+ {
+ send_bits(STATIC_TREES << 1, 3);
+ send_code(END_BLOCK, Deflate.static_ltree);
+ bi_flush();
+ }
+ last_eob_len = 7;
+ }
+
+
+ // Save the match info and tally the frequency counts. Return true if
+ // the current block must be flushed.
+ private bool _tr_tally(int dist, // distance of matched string
+ int lc // match length-MIN_MATCH or unmatched char (if dist==0)
+ )
+ {
+
+ pending_buf[d_buf + last_lit * 2] = (byte)(dist >> 8);
+ pending_buf[d_buf + last_lit * 2 + 1] = (byte)dist;
+
+ pending_buf[l_buf + last_lit] = (byte)lc; last_lit++;
+
+ if (dist == 0)
+ {
+ // lc is the unmatched char
+ dyn_ltree[lc * 2]++;
+ }
+ else
+ {
+ matches++;
+ // Here, lc is the match length - MIN_MATCH
+ dist--; // dist = match distance - 1
+ dyn_ltree[(Deflate._length_code[lc] + LITERALS + 1) * 2]++;
+ dyn_dtree[Tree.DistanceCode(dist) * 2]++;
+ }
+
+ if ((last_lit & 0x1fff) == 0 && level > (CompressionLevel)2)
+ {
+ // Compute an upper bound for the compressed length
+ int out_length = last_lit * 8;
+ int in_length = _startInsertString - _blockStart;
+ int dcode;
+ for (dcode = 0; dcode < D_CODES; dcode++)
+ {
+ out_length += (int)((int)dyn_dtree[dcode * 2] *
+ (5L + Deflate.extra_dbits[dcode]));
+ }
+ out_length >>= 3;
+ if ((matches < (last_lit / 2)) && out_length < in_length / 2) return true;
+ }
+
+ return (last_lit == lit_bufsize - 1);
+ // We avoid equality with lit_bufsize because of wraparound at 64K
+ // on 16 bit machines and because stored blocks are restricted to
+ // 64K-1 bytes.
+ }
+
+ // Send the block data compressed using the given Huffman trees
+ private void compress_block(short[] ltree, short[] dtree)
+ {
+ int dist; // distance of matched string
+ int lc; // match length or unmatched char (if dist == 0)
+ int lx = 0; // running index in l_buf
+ int code; // the code to send
+ int extra; // number of extra bits to send
+
+ if (last_lit != 0)
+ {
+ do
+ {
+ dist = ((pending_buf[d_buf + lx * 2] << 8) & 0xff00) |
+ (pending_buf[d_buf + lx * 2 + 1] & 0xff);
+ lc = (pending_buf[l_buf + lx]) & 0xff; lx++;
+
+ if (dist == 0)
+ {
+ send_code(lc, ltree); // send a literal byte
+ }
+ else
+ {
+ // Here, lc is the match length - MIN_MATCH
+ code = Deflate._length_code[lc];
+
+ send_code(code + LITERALS + 1, ltree); // send the length code
+ extra = Deflate.extra_lbits[code];
+ if (extra != 0)
+ {
+ lc -= Deflate.base_length[code];
+ send_bits(lc, extra); // send the extra length bits
+ }
+ dist--; // dist is now the match distance - 1
+ code = Tree.DistanceCode(dist);
+
+ send_code(code, dtree); // send the distance code
+ extra = Deflate.extra_dbits[code];
+ if (extra != 0)
+ {
+ dist -= Deflate.base_dist[code];
+ send_bits(dist, extra); // send the extra distance bits
+ }
+ } // literal or match pair ?
+
+ // Check that the overlay between pending_buf and d_buf+l_buf is ok:
+ }
+ while (lx < last_lit);
+ }
+
+ send_code(END_BLOCK, ltree);
+ last_eob_len = ltree[END_BLOCK * 2 + 1];
+ }
+
+ // Set the data type to ASCII or BINARY, using a crude approximation:
+ // binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise.
+ // IN assertion: the fields freq of dyn_ltree are set and the total of all
+ // frequencies does not exceed 64K (to fit in an int on 16 bit machines).
+ private void set_data_type()
+ {
+ int n = 0;
+ int ascii_freq = 0;
+ int bin_freq = 0;
+ while (n < 7) { bin_freq += dyn_ltree[n * 2]; n++; }
+ while (n < 128) { ascii_freq += dyn_ltree[n * 2]; n++; }
+ while (n < LITERALS) { bin_freq += dyn_ltree[n * 2]; n++; }
+ this._dataType = (bin_freq > (ascii_freq >> 2) ? BlockType.Z_BINARY : BlockType.Z_ASCII);
+ }
+
+ // Flush the bit buffer, keeping at most 7 bits in it.
+ private void bi_flush()
+ {
+ if (bi_valid == 16)
+ {
+ pending_buf[pending++] = (byte)(bi_buf/*&0xff*/);
+ pending_buf[pending++] = (byte)(bi_buf >> 8);
+ bi_buf = 0;
+ bi_valid = 0;
+ }
+ else if (bi_valid >= 8)
+ {
+ pending_buf[pending++] = (byte)(bi_buf);
+ bi_buf >>= 8;
+ bi_buf &= 0x00ff;
+ bi_valid -= 8;
+ }
+ }
+
+ // Flush the bit buffer and align the output on a byte boundary
+ private void bi_windup()
+ {
+ if (bi_valid > 8)
+ {
+ pending_buf[pending++] = (byte)(bi_buf);
+ pending_buf[pending++] = (byte)(bi_buf >> 8);
+ }
+ else if (bi_valid > 0)
+ {
+ pending_buf[pending++] = (byte)(bi_buf);
+ }
+ bi_buf = 0;
+ bi_valid = 0;
+ }
+
+ // Copy a stored block, storing first the length and its
+ // one's complement if requested.
+ private void copy_block(int buf, // the input data
+ int len, // its length
+ bool header // true if block header must be written
+ )
+ {
+ //int index=0;
+ bi_windup(); // align on byte boundary
+ last_eob_len = 8; // enough lookahead for inflate
+
+ if (header)
+ {
+ put_short((short)len);
+ put_short((short)~len);
+ }
+
+ // while(len--!=0) {
+ // put_byte(window[buf+index]);
+ // index++;
+ // }
+ put_byte(_window, buf, len);
+ }
+
+ private void flush_block_only(bool eof)
+ {
+ _tr_flush_block(_blockStart >= 0 ? _blockStart : -1,
+ _startInsertString - _blockStart,
+ eof);
+ _blockStart = _startInsertString;
+ this.flush_pending();
+ }
+
+ // Copy without compression as much as possible from the input stream, return
+ // the current block state.
+ // This function does not insert new strings in the dictionary since
+ // uncompressible data is probably not useful. This function is used
+ // only for the level=0 compression option.
+ // NOTE: this function should be optimized to avoid extra copying from
+ // window to pending_buf.
+ private int deflate_stored(FlushType flush)
+ {
+ // Stored blocks are limited to 0xffff bytes, pending_buf is limited
+ // to pending_buf_size, and each stored block has a 5 byte header:
+
+ int max_block_size = 0xffff;
+ int max_start;
+
+ if (max_block_size > _pendingBufferSize - 5)
+ {
+ max_block_size = _pendingBufferSize - 5;
+ }
+
+ // Copy as much as possible from input to output:
+ while (true)
+ {
+ // Fill the window as much as possible:
+ if (_validBytesAhead <= 1)
+ {
+ fill_window();
+ if (_validBytesAhead == 0 && flush == FlushType.Z_NO_FLUSH) return NeedMore;
+ if (_validBytesAhead == 0) break; // flush the current block
+ }
+
+ _startInsertString += _validBytesAhead;
+ _validBytesAhead = 0;
+
+ // Emit a stored block if pending_buf will be full:
+ max_start = _blockStart + max_block_size;
+ if (_startInsertString == 0 || _startInsertString >= max_start)
+ {
+ // strstart == 0 is possible when wraparound on 16-bit machine
+ _validBytesAhead = (int)(_startInsertString - max_start);
+ _startInsertString = (int)max_start;
+
+ flush_block_only(false);
+ if (base.avail_out == 0) return NeedMore;
+
+ }
+
+ // Flush if we may have to slide, otherwise block_start may become
+ // negative and the data will be gone:
+ if (_startInsertString - _blockStart >= _windowSize - MIN_LOOKAHEAD)
+ {
+ flush_block_only(false);
+ if (base.avail_out == 0) return NeedMore;
+ }
+ }
+
+ flush_block_only(flush == FlushType.Z_FINISH);
+ if (base.avail_out == 0)
+ return (flush == FlushType.Z_FINISH) ? FinishStarted : NeedMore;
+
+ return flush == FlushType.Z_FINISH ? FinishDone : BlockDone;
+ }
+
+ // Send a stored block
+ private void _tr_stored_block(int buf, // input block
+ int stored_len, // length of input block
+ bool eof // true if this is the last block for a file
+ )
+ {
+ send_bits((STORED_BLOCK << 1) + (eof ? 1 : 0), 3); // send block type
+ copy_block(buf, stored_len, true); // with header
+ }
+
+ // Determine the best encoding for the current block: dynamic trees, static
+ // trees or store, and output the encoded block to the zip file.
+ private void _tr_flush_block(int buf, // input block, or NULL if too old
+ int stored_len, // length of input block
+ bool eof // true if this is the last block for a file
+ )
+ {
+ int opt_lenb, static_lenb;// opt_len and static_len in bytes
+ int max_blindex = 0; // index of last bit length code of non zero freq
+
+ // Build the Huffman trees unless a stored block is forced
+ if (level > 0)
+ {
+ // Check if the file is ascii or binary
+ if (this._dataType == BlockType.Z_UNKNOWN) set_data_type();
+
+ // Construct the literal and distance trees
+ l_desc.BuildTree(this);
+
+ d_desc.BuildTree(this);
+
+ // At this point, opt_len and static_len are the total bit lengths of
+ // the compressed block data, excluding the tree representations.
+
+ // Build the bit length tree for the above two trees, and get the index
+ // in bl_order of the last bit length code to send.
+ max_blindex = build_bl_tree();
+
+ // Determine the best encoding. Compute first the block length in bytes
+ opt_lenb = (opt_len + 3 + 7) >> 3;
+ static_lenb = (static_len + 3 + 7) >> 3;
+
+ if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
+ }
+ else
+ {
+ opt_lenb = static_lenb = stored_len + 5; // force a stored block
+ }
+
+ if (stored_len + 4 <= opt_lenb && buf != -1)
+ {
+ // 4: two words for the lengths
+ // The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
+ // Otherwise we can't have processed more than WSIZE input bytes since
+ // the last block flush, because compression would have been
+ // successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
+ // transform a block into a stored block.
+ _tr_stored_block(buf, stored_len, eof);
+ }
+ else if (static_lenb == opt_lenb)
+ {
+ send_bits((STATIC_TREES << 1) + (eof ? 1 : 0), 3);
+ compress_block(Deflate.static_ltree, Deflate.static_dtree);
+ }
+ else
+ {
+ send_bits((DYN_TREES << 1) + (eof ? 1 : 0), 3);
+ send_all_trees(l_desc.LargestCode + 1, d_desc.LargestCode + 1, max_blindex + 1);
+ compress_block(dyn_ltree, dyn_dtree);
+ }
+
+ // The above check is made mod 2^32, for files larger than 512 MB
+ // and uLong implemented on 32 bits.
+
+ init_block();
+
+ if (eof)
+ {
+ bi_windup();
+ }
+ }
+
+ // Fill the window when the lookahead becomes insufficient.
+ // Updates strstart and lookahead.
+ //
+ // IN assertion: lookahead < MIN_LOOKAHEAD
+ // OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
+ // At least one byte has been read, or avail_in == 0; reads are
+ // performed for at least two bytes (required for the zip translate_eol
+ // option -- not supported here).
+ private void fill_window()
+ {
+ int n, m;
+ int p;
+ int more; // Amount of free space at the end of the window.
+
+ do
+ {
+ more = (_windowActualSize - _validBytesAhead - _startInsertString);
+
+ // Deal with !@#$% 64K limit:
+ if (more == 0 && _startInsertString == 0 && _validBytesAhead == 0)
+ {
+ more = _windowSize;
+ }
+ else if (more == -1)
+ {
+ // Very unlikely, but possible on 16 bit machine if strstart == 0
+ // and lookahead == 1 (input done one byte at time)
+ more--;
+
+ // If the window is almost full and there is insufficient lookahead,
+ // move the upper half to the lower one to make room in the upper half.
+ }
+ else if (_startInsertString >= _windowSize + _windowSize - MIN_LOOKAHEAD)
+ {
+ System.Array.Copy(_window, _windowSize, _window, 0, _windowSize);
+ _startMatchString -= _windowSize;
+ _startInsertString -= _windowSize; // we now have strstart >= MAX_DIST
+ _blockStart -= _windowSize;
+
+ // Slide the hash table (could be avoided with 32 bit values
+ // at the expense of memory usage). We slide even when level == 0
+ // to keep the hash table consistent if we switch back to level > 0
+ // later. (Using level 0 permanently is not an optimal usage of
+ // zlib, so we don't care about this pathological case.)
+
+ n = _hashSize;
+ p = n;
+ do
+ {
+ m = (_head[--p] & 0xffff);
+ _head[p] = (short)(m >= _windowSize ? (m - _windowSize) : 0);
+ }
+ while (--n != 0);
+
+ n = _windowSize;
+ p = n;
+ do
+ {
+ m = (_previous[--p] & 0xffff);
+ _previous[p] = (short)(m >= _windowSize ? (m - _windowSize) : 0);
+ // If n is not on any hash chain, prev[n] is garbage but
+ // its value will never be used.
+ }
+ while (--n != 0);
+ more += _windowSize;
+ }
+
+ if (base.avail_in == 0) return;
+
+ // If there was no sliding:
+ // strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
+ // more == window_size - lookahead - strstart
+ // => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
+ // => more >= window_size - 2*WSIZE + 2
+ // In the BIG_MEM or MMAP case (not yet supported),
+ // window_size == input_size + MIN_LOOKAHEAD &&
+ // strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
+ // Otherwise, window_size == 2*WSIZE so more >= 2.
+ // If there was sliding, more >= WSIZE. So in all cases, more >= 2.
+
+ n = this.read_buf(_window, _startInsertString + _validBytesAhead, more);
+ _validBytesAhead += n;
+
+ // Initialize the hash value now that we have some input:
+ if (_validBytesAhead >= MIN_MATCH)
+ {
+ _insertedHashIndex = _window[_startInsertString] & 0xff;
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[_startInsertString + 1] & 0xff)) & _hashMask;
+ }
+ // If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
+ // but this is not important since only literal bytes will be emitted.
+ }
+ while (_validBytesAhead < MIN_LOOKAHEAD && base.avail_in != 0);
+ }
+
+ // Compress as much as possible from the input stream, return the current
+ // block state.
+ // This function does not perform lazy evaluation of matches and inserts
+ // new strings in the dictionary only for unmatched strings or for short
+ // matches. It is used only for the fast compression options.
+ private int deflate_fast(FlushType flush)
+ {
+ // short hash_head = 0; // head of the hash chain
+ int hash_head = 0; // head of the hash chain
+ bool bflush; // set if current block must be flushed
+
+ while (true)
+ {
+ // Make sure that we always have enough lookahead, except
+ // at the end of the input file. We need MAX_MATCH bytes
+ // for the next match, plus MIN_MATCH bytes to insert the
+ // string following the next match.
+ if (_validBytesAhead < MIN_LOOKAHEAD)
+ {
+ fill_window();
+ if (_validBytesAhead < MIN_LOOKAHEAD && flush == FlushType.Z_NO_FLUSH)
+ {
+ return NeedMore;
+ }
+ if (_validBytesAhead == 0) break; // flush the current block
+ }
+
+ // Insert the string window[strstart .. strstart+2] in the
+ // dictionary, and set hash_head to the head of the hash chain:
+ if (_validBytesAhead >= MIN_MATCH)
+ {
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[(_startInsertString) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+
+ // prev[strstart&w_mask]=hash_head=head[ins_h];
+ hash_head = (_head[_insertedHashIndex] & 0xffff);
+ _previous[_startInsertString & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)_startInsertString;
+ }
+
+ // Find the longest match, discarding those <= prev_length.
+ // At this point we have always match_length < MIN_MATCH
+
+ if (hash_head != 0L &&
+ ((_startInsertString - hash_head) & 0xffff) <= _windowSize - MIN_LOOKAHEAD
+ )
+ {
+ // To simplify the code, we prevent matches with the string
+ // of window index 0 (in particular we have to avoid a match
+ // of the string with itself at the start of the input file).
+ if (strategy != CompressionStrategy.Z_HUFFMAN_ONLY)
+ {
+ _matchLength = longest_match(hash_head);
+ }
+ // longest_match() sets match_start
+ }
+ if (_matchLength >= MIN_MATCH)
+ {
+ // check_match(strstart, match_start, match_length);
+
+ bflush = _tr_tally(_startInsertString - _startMatchString, _matchLength - MIN_MATCH);
+
+ _validBytesAhead -= _matchLength;
+
+ // Insert new strings in the hash table only if the match length
+ // is not too large. This saves time but degrades compression.
+ if (_matchLength <= _maxLazyMatch &&
+ _validBytesAhead >= MIN_MATCH)
+ {
+ _matchLength--; // string at strstart already in hash table
+ do
+ {
+ _startInsertString++;
+
+ _insertedHashIndex = ((_insertedHashIndex << _hashShift) ^ (_window[(_startInsertString) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+ // prev[strstart&w_mask]=hash_head=head[ins_h];
+ hash_head = (_head[_insertedHashIndex] & 0xffff);
+ _previous[_startInsertString & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)_startInsertString;
+
+ // strstart never exceeds WSIZE-MAX_MATCH, so there are
+ // always MIN_MATCH bytes ahead.
+ }
+ while (--_matchLength != 0);
+ _startInsertString++;
+ }
+ else
+ {
+ _startInsertString += _matchLength;
+ _matchLength = 0;
+ _insertedHashIndex = _window[_startInsertString] & 0xff;
+
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[_startInsertString + 1] & 0xff)) & _hashMask;
+ // If lookahead < MIN_MATCH, ins_h is garbage, but it does not
+ // matter since it will be recomputed at next deflate call.
+ }
+ }
+ else
+ {
+ // No match, output a literal byte
+
+ bflush = _tr_tally(0, _window[_startInsertString] & 0xff);
+ _validBytesAhead--;
+ _startInsertString++;
+ }
+ if (bflush)
+ {
+
+ flush_block_only(false);
+ if (base.avail_out == 0) return NeedMore;
+ }
+ }
+
+ flush_block_only(flush == FlushType.Z_FINISH);
+ if (base.avail_out == 0)
+ {
+ if (flush == FlushType.Z_FINISH) return FinishStarted;
+ else return NeedMore;
+ }
+ return flush == FlushType.Z_FINISH ? FinishDone : BlockDone;
+ }
+
+ // Same as above, but achieves better compression. We use a lazy
+ // evaluation for matches: a match is finally adopted only if there is
+ // no better match at the next window position.
+ private int deflate_slow(FlushType flush)
+ {
+ // short hash_head = 0; // head of hash chain
+ int hash_head = 0; // head of hash chain
+ bool bflush; // set if current block must be flushed
+
+ // Process the input block.
+ while (true)
+ {
+ // Make sure that we always have enough lookahead, except
+ // at the end of the input file. We need MAX_MATCH bytes
+ // for the next match, plus MIN_MATCH bytes to insert the
+ // string following the next match.
+
+ if (_validBytesAhead < MIN_LOOKAHEAD)
+ {
+ fill_window();
+ if (_validBytesAhead < MIN_LOOKAHEAD && flush == FlushType.Z_NO_FLUSH)
+ {
+ return NeedMore;
+ }
+ if (_validBytesAhead == 0) break; // flush the current block
+ }
+
+ // Insert the string window[strstart .. strstart+2] in the
+ // dictionary, and set hash_head to the head of the hash chain:
+
+ if (_validBytesAhead >= MIN_MATCH)
+ {
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[(_startInsertString) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+ // prev[strstart&w_mask]=hash_head=head[ins_h];
+ hash_head = (_head[_insertedHashIndex] & 0xffff);
+ _previous[_startInsertString & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)_startInsertString;
+ }
+
+ // Find the longest match, discarding those <= prev_length.
+ _previousLength = _matchLength; _previousMatch = _startMatchString;
+ _matchLength = MIN_MATCH - 1;
+
+ if (hash_head != 0 && _previousLength < _maxLazyMatch &&
+ ((_startInsertString - hash_head) & 0xffff) <= _windowSize - MIN_LOOKAHEAD
+ )
+ {
+ // To simplify the code, we prevent matches with the string
+ // of window index 0 (in particular we have to avoid a match
+ // of the string with itself at the start of the input file).
+
+ if (strategy != CompressionStrategy.Z_HUFFMAN_ONLY)
+ {
+ _matchLength = longest_match(hash_head);
+ }
+ // longest_match() sets match_start
+
+ if (_matchLength <= 5 && (strategy == CompressionStrategy.Z_FILTERED ||
+ (_matchLength == MIN_MATCH &&
+ _startInsertString - _startMatchString > 4096)))
+ {
+
+ // If prev_match is also MIN_MATCH, match_start is garbage
+ // but we will ignore the current match anyway.
+ _matchLength = MIN_MATCH - 1;
+ }
+ }
+
+ // If there was a match at the previous step and the current
+ // match is not better, output the previous match:
+ if (_previousLength >= MIN_MATCH && _matchLength <= _previousLength)
+ {
+ int max_insert = _startInsertString + _validBytesAhead - MIN_MATCH;
+ // Do not insert strings in hash table beyond this.
+
+ // check_match(strstart-1, prev_match, prev_length);
+
+ bflush = _tr_tally(_startInsertString - 1 - _previousMatch, _previousLength - MIN_MATCH);
+
+ // Insert in hash table all strings up to the end of the match.
+ // strstart-1 and strstart are already inserted. If there is not
+ // enough lookahead, the last two strings are not inserted in
+ // the hash table.
+ _validBytesAhead -= _previousLength - 1;
+ _previousLength -= 2;
+ do
+ {
+ if (++_startInsertString <= max_insert)
+ {
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[(_startInsertString) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+ //prev[strstart&w_mask]=hash_head=head[ins_h];
+ hash_head = (_head[_insertedHashIndex] & 0xffff);
+ _previous[_startInsertString & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)_startInsertString;
+ }
+ }
+ while (--_previousLength != 0);
+ _matchAvailable = false;
+ _matchLength = MIN_MATCH - 1;
+ _startInsertString++;
+
+ if (bflush)
+ {
+ flush_block_only(false);
+ if (base.avail_out == 0) return NeedMore;
+ }
+ }
+ else if (_matchAvailable != false)
+ {
+
+ // If there was no match at the previous position, output a
+ // single literal. If there was a match but the current match
+ // is longer, truncate the previous match to a single literal.
+
+ bflush = _tr_tally(0, _window[_startInsertString - 1] & 0xff);
+
+ if (bflush)
+ {
+ flush_block_only(false);
+ }
+ _startInsertString++;
+ _validBytesAhead--;
+ if (base.avail_out == 0) return NeedMore;
+ }
+ else
+ {
+ // There is no previous match to compare with, wait for
+ // the next step to decide.
+
+ _matchAvailable = true;
+ _startInsertString++;
+ _validBytesAhead--;
+ }
+ }
+
+ if (_matchAvailable != false)
+ {
+ bflush = _tr_tally(0, _window[_startInsertString - 1] & 0xff);
+ _matchAvailable = false;
+ }
+ flush_block_only(flush == FlushType.Z_FINISH);
+
+ if (base.avail_out == 0)
+ {
+ if (flush == FlushType.Z_FINISH) return FinishStarted;
+ else return NeedMore;
+ }
+
+ return flush == FlushType.Z_FINISH ? FinishDone : BlockDone;
+ }
+
+ private int longest_match(int cur_match)
+ {
+ int chain_length = _maxChainLength; // max hash chain length
+ int scan = _startInsertString; // current string
+ int match; // matched string
+ int len; // length of current match
+ int best_len = _previousLength; // best match length so far
+ int limit = _startInsertString > (_windowSize - MIN_LOOKAHEAD) ?
+ _startInsertString - (_windowSize - MIN_LOOKAHEAD) : 0;
+ int nice_match = this.nice_match;
+
+ // Stop when cur_match becomes <= limit. To simplify the code,
+ // we prevent matches with the string of window index 0.
+
+ int wmask = _windowMask;
+
+ int strend = _startInsertString + MAX_MATCH;
+ byte scan_end1 = _window[scan + best_len - 1];
+ byte scan_end = _window[scan + best_len];
+
+ // The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+ // It is easy to get rid of this optimization if necessary.
+
+ // Do not waste too much time if we already have a good match:
+ if (_previousLength >= good_match)
+ {
+ chain_length >>= 2;
+ }
+
+ // Do not look for matches beyond the end of the input. This is necessary
+ // to make deflate deterministic.
+ if (nice_match > _validBytesAhead) nice_match = _validBytesAhead;
+
+ do
+ {
+ match = cur_match;
+
+ // Skip to next match if the match length cannot increase
+ // or if the match length is less than 2:
+ if (_window[match + best_len] != scan_end ||
+ _window[match + best_len - 1] != scan_end1 ||
+ _window[match] != _window[scan] ||
+ _window[++match] != _window[scan + 1]) continue;
+
+ // The check at best_len-1 can be removed because it will be made
+ // again later. (This heuristic is not always a win.)
+ // It is not necessary to compare scan[2] and match[2] since they
+ // are always equal when the other bytes match, given that
+ // the hash keys are equal and that HASH_BITS >= 8.
+ scan += 2; match++;
+
+ // We check for insufficient lookahead only every 8th comparison;
+ // the 256th check will be made at strstart+258.
+ do
+ {
+ } while (_window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ scan < strend);
+
+ len = MAX_MATCH - (int)(strend - scan);
+ scan = strend - MAX_MATCH;
+
+ if (len > best_len)
+ {
+ _startMatchString = cur_match;
+ best_len = len;
+ if (len >= nice_match) break;
+ scan_end1 = _window[scan + best_len - 1];
+ scan_end = _window[scan + best_len];
+ }
+
+ } while ((cur_match = (_previous[cur_match & wmask] & 0xffff)) > limit
+ && --chain_length != 0);
+
+ if (best_len <= _validBytesAhead) return best_len;
+ return _validBytesAhead;
+ }
+
+ internal ZLibStatus deflate(ZStream strm, FlushType flush)
+ {
+ FlushType old_flush;
+
+ if (flush > FlushType.Z_FINISH || flush < 0)
+ {
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+
+ if (strm.next_out == null ||
+ (strm.next_in == null && strm.avail_in != 0) ||
+ (_status == FINISH_STATE && flush != FlushType.Z_FINISH))
+ {
+ strm.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_STREAM_ERROR)];
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+ if (strm.avail_out == 0)
+ {
+ strm.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_BUF_ERROR)];
+ return ZLibStatus.Z_BUF_ERROR;
+ }
+
+ old_flush = last_flush;
+ last_flush = flush;
+
+ // Write the zlib header
+ if (_status == INIT_STATE)
+ {
+ int header = (Z_DEFLATED + ((this._windowBits - 8) << 4)) << 8;
+ int level_flags = (((int)this.level - 1) & 0xff) >> 1;
+
+ if (level_flags > 3) level_flags = 3;
+ header |= (level_flags << 6);
+ if (this._startInsertString != 0) header |= PRESET_DICT;
+ header += 31 - (header % 31);
+
+ _status = BUSY_STATE;
+ putShortMSB(header);
+
+
+ // Save the adler32 of the preset dictionary:
+ if (this._startInsertString != 0)
+ {
+ putShortMSB((int)(strm.adler >> 16));
+ putShortMSB((int)(strm.adler & 0xffff));
+ }
+ strm.adler = Adler32.adler32(0, null, 0, 0);
+ }
+
+ // Flush as much pending output as possible
+ if (pending != 0)
+ {
+ this.flush_pending();
+ if (strm.avail_out == 0)
+ {
+ //System.out.println(" avail_out==0");
+ // Since avail_out is 0, deflate will be called again with
+ // more output space, but possibly with both pending and
+ // avail_in equal to zero. There won't be anything to do,
+ // but this is not an error situation so make sure we
+ // return OK instead of BUF_ERROR at next call of deflate:
+ last_flush = (FlushType)(-1);
+ return ZLibStatus.Z_OK;
+ }
+
+ // Make sure there is something to do and avoid duplicate consecutive
+ // flushes. For repeated and useless calls with Z_FINISH, we keep
+ // returning Z_STREAM_END instead of Z_BUFF_ERROR.
+ }
+ else if (strm.avail_in == 0 && flush <= old_flush &&
+ flush != FlushType.Z_FINISH)
+ {
+ strm.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_BUF_ERROR)];
+ return ZLibStatus.Z_BUF_ERROR;
+ }
+
+ // User must not provide more input after the first FINISH:
+ if (_status == FINISH_STATE && strm.avail_in != 0)
+ {
+ strm.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_BUF_ERROR)];
+ return ZLibStatus.Z_BUF_ERROR;
+ }
+
+ // Start a new block or continue the current one.
+ if (strm.avail_in != 0 || this._validBytesAhead != 0 ||
+ (flush != FlushType.Z_NO_FLUSH && _status != FINISH_STATE))
+ {
+ int bstate = -1;
+ switch (config_table[level].Function)
+ {
+ case DefalteFlavor.STORED:
+ bstate = deflate_stored(flush);
+ break;
+ case DefalteFlavor.FAST:
+ bstate = deflate_fast(flush);
+ break;
+ case DefalteFlavor.SLOW:
+ bstate = deflate_slow(flush);
+ break;
+ default:
+ break;
+ }
+
+ if (bstate == FinishStarted || bstate == FinishDone)
+ {
+ _status = FINISH_STATE;
+ }
+ if (bstate == NeedMore || bstate == FinishStarted)
+ {
+ if (strm.avail_out == 0)
+ {
+ last_flush = (FlushType)(-1); // avoid BUF_ERROR next call, see above
+ }
+ return ZLibStatus.Z_OK;
+ // If flush != Z_NO_FLUSH && avail_out == 0, the next call
+ // of deflate should use the same flush parameter to make sure
+ // that the flush is complete. So we don't have to output an
+ // empty block here, this will be done at next call. This also
+ // ensures that for a very small output buffer, we emit at most
+ // one empty block.
+ }
+
+ if (bstate == BlockDone)
+ {
+ if (flush == FlushType.Z_PARTIAL_FLUSH)
+ {
+ _tr_align();
+ }
+ else
+ { // FULL_FLUSH or SYNC_FLUSH
+ _tr_stored_block(0, 0, false);
+ // For a full flush, this empty block will be recognized
+ // as a special marker by inflate_sync().
+ if (flush == FlushType.Z_FULL_FLUSH)
+ {
+ //state.head[s.hash_size-1]=0;
+ for (int i = 0; i < this._hashSize/*-1*/; i++) // forget history
+ this._head[i] = 0;
+ }
+ }
+ this.flush_pending();
+ if (strm.avail_out == 0)
+ {
+ last_flush = (FlushType)(-1); // avoid BUF_ERROR at next call, see above
+ return ZLibStatus.Z_OK;
+ }
+ }
+ }
+
+ if (flush != FlushType.Z_FINISH) return ZLibStatus.Z_OK;
+ if (noheader != 0) return ZLibStatus.Z_STREAM_END;
+
+ // Write the zlib trailer (adler32)
+ putShortMSB((int)(strm.adler >> 16));
+ putShortMSB((int)(strm.adler & 0xffff));
+ this.flush_pending();
+
+ // If avail_out is zero, the application will call deflate again
+ // to flush the rest.
+ noheader = -1; // write the trailer only once!
+ return pending != 0 ? ZLibStatus.Z_OK : ZLibStatus.Z_STREAM_END;
+ }
+
+
+ private static readonly StaticTree static_l_desc = new StaticTree(static_ltree, Deflate.extra_lbits, LITERALS + 1, L_CODES, MAX_BITS);
+
+ private static readonly StaticTree static_d_desc = new StaticTree(static_dtree, Deflate.extra_dbits, 0, D_CODES, MAX_BITS);
+
+ private static readonly StaticTree static_bl_desc = new StaticTree(null, Deflate.extra_blbits, 0, BL_CODES, MAX_BL_BITS);
+
+ private class Config
+ {
+ ///
+ /// Reduce lazy search above this match length
+ ///
+ internal int GoodLength { get; private set; }
+ ///
+ /// Gets or sets whether not to perform lazy search above this match length
+ ///
+ ///
+ /// The max lazy.
+ ///
+ internal int MaxLazy { get; private set; }
+ ///
+ /// Gets or sets whether to quit search above this match length
+ ///
+ ///
+ /// The length of the nice.
+ ///
+ internal int NiceLength { get; private set; }
+ internal int MaxChain { get; private set; }
+ internal DefalteFlavor Function { get; private set; }
+ internal Config(int goodLength, int maxLazy, int niceLength, int maxChain, DefalteFlavor function)
+ {
+ this.GoodLength = goodLength;
+ this.MaxLazy = maxLazy;
+ this.NiceLength = niceLength;
+ this.MaxChain = maxChain;
+ this.Function = function;
+ }
+ }
+
+ public ZLibStatus deflateInit(CompressionLevel level)
+ {
+ return deflateInit(level, MAX_WBITS);
+ }
+ public ZLibStatus deflateInit(CompressionLevel level, bool nowrap)
+ {
+ return deflateInit(level, MAX_WBITS, nowrap);
+ }
+ public ZLibStatus deflateInit(CompressionLevel level, int bits)
+ {
+ return deflateInit(level, bits, false);
+ }
+ public ZLibStatus deflateInit(CompressionLevel level, int bits, bool nowrap)
+ {
+ return this.deflateInit(this, level, nowrap ? -bits : bits);
+ }
+
+ public ZLibStatus deflate(FlushType flush)
+ {
+ return this.deflate(this, flush);
+ }
+ public ZLibStatus deflateParams(CompressionLevel level, CompressionStrategy strategy)
+ {
+ return this.deflateParams(this, level, strategy);
+ }
+ public ZLibStatus deflateSetDictionary(byte[] dictionary, int dictLength)
+ {
+ return this.deflateSetDictionary(this, dictionary, dictLength);
+ }
+
+
+ // Flush as much pending output as possible. All deflate() output goes
+ // through this function so some applications may wish to modify it
+ // to avoid allocating a large strm->next_out buffer and copying into it.
+ // (See also read_buf()).
+ internal void flush_pending()
+ {
+ int len = this.pending;
+
+ if (len > avail_out) len = avail_out;
+ if (len == 0) return;
+
+ if (this.pending_buf.Length <= this.pending_out ||
+ next_out.Length <= next_out_index ||
+ this.pending_buf.Length < (this.pending_out + len) ||
+ next_out.Length < (next_out_index + len))
+ {
+ // System.out.println(this.pending_buf.length+", "+this.pending_out+
+ // ", "+next_out.length+", "+next_out_index+", "+len);
+ // System.out.println("avail_out="+avail_out);
+ }
+
+ System.Array.Copy(this.pending_buf, this.pending_out,
+ next_out, next_out_index, len);
+
+ next_out_index += len;
+ this.pending_out += len;
+ total_out += len;
+ avail_out -= len;
+ this.pending -= len;
+ if (this.pending == 0)
+ {
+ this.pending_out = 0;
+ }
+ }
+
+ // Read a new buffer from the current input stream, update the adler32
+ // and total number of bytes read. All deflate() input goes through
+ // this function so some applications may wish to modify it to avoid
+ // allocating a large strm->next_in buffer and copying from it.
+ // (See also flush_pending()).
+ internal int read_buf(byte[] buf, int start, int size)
+ {
+ int len = avail_in;
+
+ if (len > size) len = size;
+ if (len == 0) return 0;
+
+ avail_in -= len;
+
+ if (this.noheader == 0)
+ {
+ adler = Adler32.adler32(adler, next_in, next_in_index, len);
+ }
+ System.Array.Copy(next_in, next_in_index, buf, start, len);
+ next_in_index += len;
+ total_in += len;
+ return len;
+ }
+
+ public ZLibStatus deflate(byte[] inputBufer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType)
+ {
+ this.next_in = inputBufer;
+ this.next_in_index = inputOffset;
+ this.avail_in = inputCount;
+ this.next_out = outputBuffer;
+ this.next_out_index = outputOffset;
+ this.avail_out = outputCount;
+ return this.deflate(flushType);
+ }
+
+ // TODO: Delete this
+ public ZLibStatus inflateInit()
+ {
+ throw new NotImplementedException();
+ }
+
+ public ZLibStatus inflateEnd()
+ {
+ throw new NotImplementedException();
+ }
+
+ public ZLibStatus inflate(FlushType flushType)
+ {
+ throw new NotImplementedException();
+ }
+
+ public ZLibStatus inflateInit(bool nowrap)
+ {
+ throw new NotImplementedException();
+ }
+
+
+ public ZLibStatus inflate(byte[] bufer, int offset, int count, byte[] p1, int p2, int p3, FlushType flushType)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Version.5/Inflate.cs b/Renci.SshNet/Compression/Version.5/Inflate.cs
new file mode 100644
index 0000000..60658d0
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.5/Inflate.cs
@@ -0,0 +1,518 @@
+using System;
+/*
+ * $Id: Inflate.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public enum InflateMode : int
+ {
+ ///
+ ///waiting for method byte
+ ///
+ METHOD = 0,
+ ///
+ /// waiting for flag byte
+ ///
+ FLAG = 1,
+ ///
+ /// four dictionary check bytes to go
+ ///
+ DICT4 = 2,
+ ///
+ /// three dictionary check bytes to go
+ ///
+ DICT3 = 3,
+ ///
+ /// two dictionary check bytes to go
+ ///
+ DICT2 = 4,
+ ///
+ /// one dictionary check byte to go
+ ///
+ DICT1 = 5,
+ ///
+ /// waiting for inflateSetDictionary
+ ///
+ DICT0 = 6,
+ ///
+ /// decompressing blocks
+ ///
+ BLOCKS = 7,
+ ///
+ /// four check bytes to go
+ ///
+ CHECK4 = 8,
+ ///
+ /// three check bytes to go
+ ///
+ CHECK3 = 9,
+ ///
+ /// two check bytes to go
+ ///
+ CHECK2 = 10,
+ ///
+ /// one check byte to go
+ ///
+ CHECK1 = 11,
+ ///
+ /// finished check, done
+ ///
+ DONE = 12,
+ ///
+ /// got an error--stay here
+ ///
+ BAD = 13
+ }
+
+ internal sealed class Inflate : ZStream, ICompressor
+ {
+ // preset dictionary flag in zlib header
+ private const int PRESET_DICT = 0x20;
+
+ private const int Z_DEFLATED = 8;
+
+ private static readonly byte[] mark = { (byte)0, (byte)0, (byte)0xff, (byte)0xff };
+
+ ///
+ /// The current inflate mode
+ ///
+ private InflateMode _mode;
+
+ ///
+ /// if FLAGS, method byte
+ ///
+ private int method;
+
+ ///
+ /// Computed check value
+ ///
+ private long[] _was = new long[1];
+
+ ///
+ /// The stream check value
+ ///
+ private long _need;
+
+ ///
+ /// if BAD, inflateSync's marker bytes count
+ ///
+ private int _marker;
+
+ // mode independent information
+ ///
+ /// Flag for no wrapper
+ ///
+ private int _nowrap;
+
+ ///
+ /// log2(window size) (8..15, defaults to 15)
+ ///
+ private int _wbits;
+
+ ///
+ /// Current inflate_blocks state
+ ///
+ private InflateBlocks _blocks;
+
+ private ZLibStatus InflateReset()
+ {
+ base.total_in = base.total_out = 0;
+ base.msg = null;
+ this._mode = this._nowrap != 0 ? InflateMode.BLOCKS : InflateMode.METHOD;
+ this._blocks.reset(this, null);
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus InflateEnd(ZStream z)
+ {
+ if (_blocks != null)
+ _blocks.free(z);
+ _blocks = null;
+ // ZFREE(z, z->state);
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus InflateInit(ZStream z, int w)
+ {
+ base.msg = null;
+ _blocks = null;
+
+ // handle undocumented nowrap option (no zlib header or check)
+ _nowrap = 0;
+ if (w < 0)
+ {
+ w = -w;
+ _nowrap = 1;
+ }
+
+ // set window size
+ if (w < 8 || w > 15)
+ {
+ InflateEnd(z);
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+ _wbits = w;
+
+ this._blocks = new InflateBlocks(z,
+ this._nowrap != 0 ? null : this,
+ 1 << w);
+
+ // reset state
+ InflateReset();
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus inflate(FlushType ff)
+ {
+ ZLibStatus r;
+ int b;
+
+ if (base.next_in == null)
+ return ZLibStatus.Z_STREAM_ERROR;
+ var f = ff == FlushType.Z_FINISH ? ZLibStatus.Z_BUF_ERROR : ZLibStatus.Z_OK;
+ r = ZLibStatus.Z_BUF_ERROR;
+ while (true)
+ {
+ //System.out.println("mode: "+this.mode);
+ switch (this._mode)
+ {
+ case InflateMode.METHOD:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ if (((this.method = base.next_in[base.next_in_index++]) & 0xf) != Z_DEFLATED)
+ {
+ this._mode = InflateMode.BAD;
+ base.msg = "unknown compression method";
+ this._marker = 5; // can't try inflateSync
+ break;
+ }
+ if ((this.method >> 4) + 8 > this._wbits)
+ {
+ this._mode = InflateMode.BAD;
+ base.msg = "invalid window size";
+ this._marker = 5; // can't try inflateSync
+ break;
+ }
+ this._mode = InflateMode.FLAG;
+ goto case InflateMode.FLAG;
+ case InflateMode.FLAG:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ b = (base.next_in[base.next_in_index++]) & 0xff;
+
+ if ((((this.method << 8) + b) % 31) != 0)
+ {
+ this._mode = InflateMode.BAD;
+ base.msg = "incorrect header check";
+ this._marker = 5; // can't try inflateSync
+ break;
+ }
+
+ if ((b & PRESET_DICT) == 0)
+ {
+ this._mode = InflateMode.BLOCKS;
+ break;
+ }
+ this._mode = InflateMode.DICT4;
+ goto case InflateMode.DICT4;
+ case InflateMode.DICT4:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need = ((base.next_in[base.next_in_index++] & 0xff) << 24) & 0xff000000L;
+ this._mode = InflateMode.DICT3;
+ goto case InflateMode.DICT3;
+ case InflateMode.DICT3:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += ((base.next_in[base.next_in_index++] & 0xff) << 16) & 0xff0000L;
+ this._mode = InflateMode.DICT2;
+ goto case InflateMode.DICT2;
+ case InflateMode.DICT2:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += ((base.next_in[base.next_in_index++] & 0xff) << 8) & 0xff00L;
+ this._mode = InflateMode.DICT1;
+ goto case InflateMode.DICT1;
+ case InflateMode.DICT1:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += (base.next_in[base.next_in_index++] & 0xffL);
+ base.adler = this._need;
+ this._mode = InflateMode.DICT0;
+ return ZLibStatus.Z_NEED_DICT;
+ case InflateMode.DICT0:
+ this._mode = InflateMode.BAD;
+ base.msg = "need dictionary";
+ this._marker = 0; // can try inflateSync
+ return ZLibStatus.Z_STREAM_ERROR;
+ case InflateMode.BLOCKS:
+
+ r = this._blocks.proc(this, r);
+ if (r == ZLibStatus.Z_DATA_ERROR)
+ {
+ this._mode = InflateMode.BAD;
+ this._marker = 0; // can try inflateSync
+ break;
+ }
+ if (r == ZLibStatus.Z_OK)
+ {
+ r = f;
+ }
+ if (r != ZLibStatus.Z_STREAM_END)
+ {
+ return r;
+ }
+ r = f;
+ this._blocks.reset(this, this._was);
+ if (this._nowrap != 0)
+ {
+ this._mode = InflateMode.DONE;
+ break;
+ }
+ this._mode = InflateMode.CHECK4;
+ goto case InflateMode.CHECK4;
+ case InflateMode.CHECK4:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need = ((base.next_in[base.next_in_index++] & 0xff) << 24) & 0xff000000L;
+ this._mode = InflateMode.CHECK3;
+ goto case InflateMode.CHECK3;
+ case InflateMode.CHECK3:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += ((base.next_in[base.next_in_index++] & 0xff) << 16) & 0xff0000L;
+ this._mode = InflateMode.CHECK2;
+ goto case InflateMode.CHECK2;
+ case InflateMode.CHECK2:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += ((base.next_in[base.next_in_index++] & 0xff) << 8) & 0xff00L;
+ this._mode = InflateMode.CHECK1;
+ goto case InflateMode.CHECK1;
+ case InflateMode.CHECK1:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += (base.next_in[base.next_in_index++] & 0xffL);
+
+ if (((int)(this._was[0])) != ((int)(this._need)))
+ {
+ this._mode = InflateMode.BAD;
+ base.msg = "incorrect data check";
+ this._marker = 5; // can't try inflateSync
+ break;
+ }
+
+ this._mode = InflateMode.DONE;
+ goto case InflateMode.DONE;
+ case InflateMode.DONE:
+ return ZLibStatus.Z_STREAM_END;
+ case InflateMode.BAD:
+ return ZLibStatus.Z_DATA_ERROR;
+ default:
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+ }
+ }
+
+ public ZLibStatus InflateSetDictionary(byte[] dictionary, int dictLength)
+ {
+ int index = 0;
+ int length = dictLength;
+ if (this._mode != InflateMode.DICT0)
+ return ZLibStatus.Z_STREAM_ERROR;
+
+ if (Adler32.adler32(1L, dictionary, 0, dictLength) != base.adler)
+ {
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+
+ base.adler = Adler32.adler32(0, null, 0, 0);
+
+ if (length >= (1 << this._wbits))
+ {
+ length = (1 << this._wbits) - 1;
+ index = dictLength - length;
+ }
+ this._blocks.set_dictionary(dictionary, index, length);
+ this._mode = InflateMode.BLOCKS;
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus InflateSync(ZStream z)
+ {
+ int n; // number of bytes to look at
+ int p; // pointer to bytes
+ int m; // number of marker bytes found in a row
+ long r, w; // temporaries to save total_in and total_out
+
+ // set up
+ if (this._mode != InflateMode.BAD)
+ {
+ this._mode = InflateMode.BAD;
+ this._marker = 0;
+ }
+ if ((n = base.avail_in) == 0)
+ return ZLibStatus.Z_BUF_ERROR;
+ p = base.next_in_index;
+ m = this._marker;
+
+ // search
+ while (n != 0 && m < 4)
+ {
+ if (base.next_in[p] == mark[m])
+ {
+ m++;
+ }
+ else if (base.next_in[p] != 0)
+ {
+ m = 0;
+ }
+ else
+ {
+ m = 4 - m;
+ }
+ p++; n--;
+ }
+
+ // restore
+ base.total_in += p - base.next_in_index;
+ base.next_in_index = p;
+ base.avail_in = n;
+ this._marker = m;
+
+ // return no joy or set up to restart on a new block
+ if (m != 4)
+ {
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ r = base.total_in; w = base.total_out;
+ InflateReset();
+ base.total_in = r; base.total_out = w;
+ this._mode = InflateMode.BLOCKS;
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus inflateInit()
+ {
+ return inflateInit(DEF_WBITS);
+ }
+ public ZLibStatus inflateInit(bool nowrap)
+ {
+ return inflateInit(DEF_WBITS, nowrap);
+ }
+ public ZLibStatus inflateInit(int w)
+ {
+ return inflateInit(w, false);
+ }
+
+ public ZLibStatus inflateInit(int w, bool nowrap)
+ {
+ return this.InflateInit(this, nowrap ? -w : w);
+ }
+
+ public ZLibStatus inflateEnd()
+ {
+ var ret = this.InflateEnd(this);
+ return ret;
+ }
+ public ZLibStatus inflateSync()
+ {
+ return this.InflateSync(this);
+ }
+ public ZLibStatus inflateSetDictionary(byte[] dictionary, int dictLength)
+ {
+ return this.InflateSetDictionary(dictionary, dictLength);
+ }
+
+ public ZLibStatus inflate(byte[] inputBufer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType)
+ {
+ this.next_in = inputBufer;
+ this.next_in_index = inputOffset;
+ this.avail_in = inputCount;
+ this.next_out = outputBuffer;
+ this.next_out_index = outputOffset;
+ this.avail_out = outputCount;
+ return this.inflate(flushType);
+ }
+
+ // TODO: Dlete this
+
+ public ZLibStatus deflateInit(CompressionLevel level, bool nowrap)
+ {
+ throw new NotImplementedException();
+ }
+
+ public ZLibStatus deflate(byte[] bufer, int offset, int count, byte[] p1, int p2, int p3, FlushType flushType)
+ {
+ throw new NotImplementedException();
+ }
+
+ public ZLibStatus deflateEnd()
+ {
+ throw new NotImplementedException();
+ }
+
+ public ZLibStatus deflate(FlushType flushType)
+ {
+ throw new NotImplementedException();
+ }
+
+ public ZLibStatus deflateInit(CompressionLevel level)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Version.5/InflateBlocks.cs b/Renci.SshNet/Compression/Version.5/InflateBlocks.cs
new file mode 100644
index 0000000..273389f
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.5/InflateBlocks.cs
@@ -0,0 +1,721 @@
+using System;
+/*
+ * $Id: InfBlocks.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public enum InflateBlockMode
+ {
+ ///
+ /// get type bits (3, including end bit)
+ ///
+ TYPE = 0,
+ ///
+ /// get lengths for stored
+ ///
+ LENS = 1,
+ ///
+ /// cessing stored block
+ ///
+ STORED = 2,
+ ///
+ /// get table lengths
+ ///
+ TABLE = 3,
+ ///
+ /// get bit lengths tree for a dynamic block
+ ///
+ BTREE = 4,
+ ///
+ /// get length, distance trees for a dynamic block
+ ///
+ DTREE = 5,
+ ///
+ /// processing fixed or dynamic block
+ ///
+ CODES = 6,
+ ///
+ /// output remaining window bytes
+ ///
+ DRY = 7,
+ ///
+ /// finished last block, done
+ ///
+ DONE = 8,
+ ///
+ /// ot a data error--stuck here
+ ///
+ BAD = 9
+ }
+
+ internal sealed class InflateBlocks : InflateCodes
+ {
+ private const int MANY = 1440;
+
+ // And'ing with mask[n] masks the lower n bits
+ private static readonly int[] inflate_mask = {
+ 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
+ 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
+ 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
+ 0x00007fff, 0x0000ffff
+ };
+
+ // Table for deflate from PKZIP's appnote.txt.
+ static readonly int[] border = { // Order of the bit length code lengths
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
+ };
+
+ internal InflateBlockMode mode; // current inflate_block mode
+
+ internal int left; // if STORED, bytes left to copy
+
+ internal int table; // table lengths (14 bits)
+ internal int index; // index into blens (or border)
+ internal int[] blens; // bit lengths of codes
+ internal int[] bb = new int[1]; // bit length tree depth
+ internal int[] tb = new int[1]; // bit length decoding tree
+
+ //internal InfCodes codes = new InfCodes(); // if CODES, current state
+
+ int last; // true if this block is the last block
+
+ // mode independent information
+ internal int bitk; // bits in bit buffer
+ internal int bitb; // bit buffer
+ internal int[] hufts; // single malloc for tree space
+ internal byte[] window; // sliding window
+ internal int end; // one byte after sliding window
+ internal int read; // window read pointer
+ internal int write; // window write pointer
+ internal Object checkfn; // check function
+ internal long check; // check on output
+
+ internal InflateTree inftree = new InflateTree();
+
+ internal InflateBlocks(ZStream z, Object checkfn, int w)
+ {
+ hufts = new int[MANY * 3];
+ window = new byte[w];
+ end = w;
+ this.checkfn = checkfn;
+ mode = InflateBlockMode.TYPE;
+ reset(z, null);
+ }
+
+ internal void reset(ZStream z, long[] c)
+ {
+ if (c != null) c[0] = check;
+ if (mode == InflateBlockMode.BTREE || mode == InflateBlockMode.DTREE)
+ {
+ }
+ if (mode == InflateBlockMode.CODES)
+ {
+ codesfree(z);
+ }
+ mode = InflateBlockMode.TYPE;
+ bitk = 0;
+ bitb = 0;
+ read = write = 0;
+
+ if (checkfn != null)
+ z.adler = check = Adler32.adler32(0L, null, 0, 0);
+ }
+
+ internal ZLibStatus proc(ZStream z, ZLibStatus r)
+ {
+ int t; // temporary storage
+ ZLibStatus tt;
+ int b; // bit buffer
+ int k; // bits in bit buffer
+ int p; // input data pointer
+ int n; // bytes available there
+ int q; // output window write pointer
+ int m;
+ { // bytes to end of window or read pointer
+
+ // copy input/output information to locals (UPDATE macro restores)
+ p = z.next_in_index; n = z.avail_in; b = bitb; k = bitk;
+ }
+ {
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+ }
+
+ // process input based on current state
+ while (true)
+ {
+ switch (mode)
+ {
+ case InflateBlockMode.TYPE:
+
+ while (k < (3))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+ t = (int)(b & 7);
+ last = t & 1;
+
+ switch (t >> 1)
+ {
+ case 0:
+ { // stored
+ b >>= (3); k -= (3);
+ }
+ t = k & 7;
+ { // go to byte boundary
+
+ b >>= (t); k -= (t);
+ }
+ mode = InflateBlockMode.LENS; // get length of stored block
+ break;
+ case 1:
+ { // fixed
+ int[] bl = new int[1];
+ int[] bd = new int[1];
+ int[][] tl = new int[1][];
+ int[][] td = new int[1][];
+
+ InflateTree.InflateTreesFixed(bl, bd, tl, td, z);
+ codesinit(bl[0], bd[0], tl[0], 0, td[0], 0, z);
+ }
+ {
+
+ b >>= (3); k -= (3);
+ }
+
+ mode = InflateBlockMode.CODES;
+ break;
+ case 2:
+ { // dynamic
+
+ b >>= (3); k -= (3);
+ }
+
+ mode = InflateBlockMode.TABLE;
+ break;
+ case 3:
+ { // illegal
+
+ b >>= (3); k -= (3);
+ }
+ mode = InflateBlockMode.BAD;
+ z.msg = "invalid block type";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ break;
+ case InflateBlockMode.LENS:
+
+ while (k < (32))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ if ((((~b) >> 16) & 0xffff) != (b & 0xffff))
+ {
+ mode = InflateBlockMode.BAD;
+ z.msg = "invalid stored block lengths";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ left = (b & 0xffff);
+ b = k = 0; // dump bits
+ mode = left != 0 ? InflateBlockMode.STORED : (last != 0 ? InflateBlockMode.DRY : InflateBlockMode.TYPE);
+ break;
+ case InflateBlockMode.STORED:
+ if (n == 0)
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+
+ if (m == 0)
+ {
+ if (q == end && read != 0)
+ {
+ q = 0; m = (int)(q < read ? read - q - 1 : end - q);
+ }
+ if (m == 0)
+ {
+ write = q;
+ r = inflate_flush(z, r);
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+ if (q == end && read != 0)
+ {
+ q = 0; m = (int)(q < read ? read - q - 1 : end - q);
+ }
+ if (m == 0)
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ }
+ }
+ r = ZLibStatus.Z_OK;
+
+ t = left;
+ if (t > n) t = n;
+ if (t > m) t = m;
+ System.Array.Copy(z.next_in, p, window, q, t);
+ p += t; n -= t;
+ q += t; m -= t;
+ if ((left -= t) != 0)
+ break;
+ mode = last != 0 ? InflateBlockMode.DRY : InflateBlockMode.TYPE;
+ break;
+ case InflateBlockMode.TABLE:
+
+ while (k < (14))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ table = t = (b & 0x3fff);
+ if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
+ {
+ mode = InflateBlockMode.BAD;
+ z.msg = "too many length or distance symbols";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
+ if (blens == null || blens.Length < t)
+ {
+ blens = new int[t];
+ }
+ else
+ {
+ for (int i = 0; i < t; i++) { blens[i] = 0; }
+ }
+ {
+
+ b >>= (14); k -= (14);
+ }
+
+ index = 0;
+ mode = InflateBlockMode.BTREE;
+ goto case InflateBlockMode.BTREE;
+ case InflateBlockMode.BTREE:
+ while (index < 4 + (table >> 10))
+ {
+ while (k < (3))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ blens[border[index++]] = b & 7;
+ {
+
+ b >>= (3); k -= (3);
+ }
+ }
+
+ while (index < 19)
+ {
+ blens[border[index++]] = 0;
+ }
+
+ bb[0] = 7;
+ tt = inftree.InflateTreesBits(blens, bb, tb, hufts, z);
+ if (tt != ZLibStatus.Z_OK)
+ {
+ r = tt;
+ if (r == ZLibStatus.Z_DATA_ERROR)
+ {
+ blens = null;
+ mode = InflateBlockMode.BAD;
+ }
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+
+ index = 0;
+ mode = InflateBlockMode.DTREE;
+ goto case InflateBlockMode.DTREE;
+ case InflateBlockMode.DTREE:
+ while (true)
+ {
+ t = table;
+ if (!(index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)))
+ {
+ break;
+ }
+
+ int i, j, c;
+
+ t = bb[0];
+
+ while (k < (t))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ if (tb[0] == -1)
+ {
+ //System.err.println("null...");
+ }
+
+ t = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 1];
+ c = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 2];
+
+ if (c < 16)
+ {
+ b >>= (t); k -= (t);
+ blens[index++] = c;
+ }
+ else
+ { // c == 16..18
+ i = c == 18 ? 7 : c - 14;
+ j = c == 18 ? 11 : 3;
+
+ while (k < (t + i))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ b >>= (t); k -= (t);
+
+ j += (b & inflate_mask[i]);
+
+ b >>= (i); k -= (i);
+
+ i = index;
+ t = table;
+ if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
+ (c == 16 && i < 1))
+ {
+ blens = null;
+ mode = InflateBlockMode.BAD;
+ z.msg = "invalid bit length repeat";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+
+ c = c == 16 ? blens[i - 1] : 0;
+ do
+ {
+ blens[i++] = c;
+ }
+ while (--j != 0);
+ index = i;
+ }
+ }
+
+ tb[0] = -1;
+ {
+ int[] bl = new int[1];
+ int[] bd = new int[1];
+ int[] tl = new int[1];
+ int[] td = new int[1];
+ bl[0] = 9; // must be <= 9 for lookahead assumptions
+ bd[0] = 6; // must be <= 9 for lookahead assumptions
+
+ t = table;
+ tt = inftree.InflateTreesDynamic(257 + (t & 0x1f),
+ 1 + ((t >> 5) & 0x1f),
+ blens, bl, bd, tl, td, hufts, z);
+
+ if (tt != ZLibStatus.Z_OK)
+ {
+ if (tt == ZLibStatus.Z_DATA_ERROR)
+ {
+ blens = null;
+ mode = InflateBlockMode.BAD;
+ }
+ r = tt;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ codesinit(bl[0], bd[0], hufts, tl[0], hufts, td[0], z);
+ }
+ mode = InflateBlockMode.CODES;
+ goto case InflateBlockMode.CODES;
+ case InflateBlockMode.CODES:
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+
+ if ((r = codesproc(this, z, r)) != ZLibStatus.Z_STREAM_END)
+ {
+ return inflate_flush(z, r);
+ }
+ r = ZLibStatus.Z_OK;
+ codesfree(z);
+
+ p = z.next_in_index; n = z.avail_in; b = bitb; k = bitk;
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+
+ if (last == 0)
+ {
+ mode = InflateBlockMode.TYPE;
+ break;
+ }
+ mode = InflateBlockMode.DRY;
+ goto case InflateBlockMode.DRY;
+ case InflateBlockMode.DRY:
+ write = q;
+ r = inflate_flush(z, r);
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+ if (read != write)
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ mode = InflateBlockMode.DONE;
+ goto case InflateBlockMode.DONE;
+ case InflateBlockMode.DONE:
+ r = ZLibStatus.Z_STREAM_END;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ case InflateBlockMode.BAD:
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+
+ default:
+ r = ZLibStatus.Z_STREAM_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ }
+ }
+
+ internal void free(ZStream z)
+ {
+ reset(z, null);
+ window = null;
+ hufts = null;
+ //ZFREE(z, s);
+ }
+
+ internal void set_dictionary(byte[] d, int start, int n)
+ {
+ System.Array.Copy(d, start, window, 0, n);
+ read = write = n;
+ }
+
+ // Returns true if inflate is currently at the end of a block generated
+ // by Z_SYNC_FLUSH or FlushType.Z_FULL_FLUSH.
+ internal ZLibStatus sync_point()
+ {
+ return mode == InflateBlockMode.LENS ? ZLibStatus.Z_STREAM_END : ZLibStatus.Z_OK;
+ }
+
+ // copy as much as possible from the sliding window to the output area
+ internal ZLibStatus inflate_flush(ZStream z, ZLibStatus r)
+ {
+ int n;
+ int p;
+ int q;
+
+ // local copies of source and destination pointers
+ p = z.next_out_index;
+ q = read;
+
+ // compute number of bytes to copy as far as end of window
+ n = (int)((q <= write ? write : end) - q);
+ if (n > z.avail_out) n = z.avail_out;
+ if (n != 0 && r == ZLibStatus.Z_BUF_ERROR) r = ZLibStatus.Z_OK;
+
+ // update counters
+ z.avail_out -= n;
+ z.total_out += n;
+
+ // update check information
+ if (checkfn != null)
+ z.adler = check = Adler32.adler32(check, window, q, n);
+
+ // copy as far as end of window
+ System.Array.Copy(window, q, z.next_out, p, n);
+ p += n;
+ q += n;
+
+ // see if more to copy at beginning of window
+ if (q == end)
+ {
+ // wrap pointers
+ q = 0;
+ if (write == end)
+ write = 0;
+
+ // compute bytes to copy
+ n = write - q;
+ if (n > z.avail_out) n = z.avail_out;
+ if (n != 0 && r == ZLibStatus.Z_BUF_ERROR) r = ZLibStatus.Z_OK;
+
+ // update counters
+ z.avail_out -= n;
+ z.total_out += n;
+
+ // update check information
+ if (checkfn != null)
+ z.adler = check = Adler32.adler32(check, window, q, n);
+
+ // copy
+ System.Array.Copy(window, q, z.next_out, p, n);
+ p += n;
+ q += n;
+ }
+
+ // update pointers
+ z.next_out_index = p;
+ read = q;
+
+ // done
+ return r;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Version.5/InflateCodes.cs b/Renci.SshNet/Compression/Version.5/InflateCodes.cs
new file mode 100644
index 0000000..3214e56
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.5/InflateCodes.cs
@@ -0,0 +1,690 @@
+using System;
+/*
+ * $Id: InfCodes.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public enum InflateCodeMode
+ {
+ ///
+ /// x: set up for InflateCodeMode.LEN
+ ///
+ START = 0,
+ ///
+ /// i: get length/literal/eob next
+ ///
+ LEN = 1,
+ ///
+ /// i: getting length extra (have base)
+ ///
+ LENEXT = 2,
+ ///
+ /// i: get distance next
+ ///
+ DIST = 3,
+ ///
+ /// : getting distance extra
+ ///
+ DISTEXT = 4,
+ ///
+ /// o: copying bytes in window, waiting for space
+ ///
+ COPY = 5,
+ ///
+ /// o: got literal, waiting for output space
+ ///
+ LIT = 6,
+ ///
+ /// o: got eob, possibly still output waiting
+ ///
+ WASH = 7,
+ ///
+ /// x: got eob and all data flushed
+ ///
+ END = 8,
+ ///
+ /// x: got error
+ ///
+ BADCODE = 9
+ }
+
+ internal abstract class InflateCodes// : ZStream
+ {
+ private static readonly int[] inflate_mask = {
+ 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
+ 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
+ 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
+ 0x00007fff, 0x0000ffff
+ };
+
+ InflateCodeMode mode; // current inflate_codes mode
+
+ // mode dependent information
+ int len;
+
+ int[] tree; // pointer into tree
+ int tree_index = 0;
+ int need; // bits needed
+
+ int lit;
+
+ // if EXT or COPY, where and how much
+ int get; // bits to get for extra
+ int dist; // distance back to copy from
+
+ byte lbits; // ltree bits decoded per branch
+ byte dbits; // dtree bits decoder per branch
+ int[] ltree; // literal/length/eob tree
+ int ltree_index; // literal/length/eob tree
+ int[] dtree; // distance tree
+ int dtree_index; // distance tree
+
+ internal InflateCodes()
+ {
+ }
+ internal void codesinit(int bl, int bd,
+ int[] tl, int tl_index,
+ int[] td, int td_index, ZStream z)
+ {
+ mode = InflateCodeMode.START;
+ lbits = (byte)bl;
+ dbits = (byte)bd;
+ ltree = tl;
+ ltree_index = tl_index;
+ dtree = td;
+ dtree_index = td_index;
+ tree = null;
+ }
+
+ internal ZLibStatus codesproc(InflateBlocks s, ZStream z, ZLibStatus r)
+ {
+ int j; // temporary storage
+ int tindex; // temporary pointer
+ int e; // extra bits or operation
+ int b = 0; // bit buffer
+ int k = 0; // bits in bit buffer
+ int p = 0; // input data pointer
+ int n; // bytes available there
+ int q; // output window write pointer
+ int m; // bytes to end of window or read pointer
+ int f; // pointer to copy strings from
+
+ // copy input/output information to locals (UPDATE macro restores)
+ p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk;
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ // process input and output based on current state
+ while (true)
+ {
+ switch (mode)
+ {
+ // waiting for "i:"=input, "o:"=output, "x:"=nothing
+ case InflateCodeMode.START: // x: set up for LEN
+ if (m >= 258 && n >= 10)
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ r = inflate_fast(lbits, dbits,
+ ltree, ltree_index,
+ dtree, dtree_index,
+ s, z);
+
+ p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk;
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (r != ZLibStatus.Z_OK)
+ {
+ mode = r == ZLibStatus.Z_STREAM_END ? InflateCodeMode.WASH : InflateCodeMode.BADCODE;
+ break;
+ }
+ }
+ need = lbits;
+ tree = ltree;
+ tree_index = ltree_index;
+
+ mode = InflateCodeMode.LEN;
+ goto case InflateCodeMode.LEN;
+ case InflateCodeMode.LEN: // i: get length/literal/eob next
+ j = need;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ tindex = (tree_index + (b & inflate_mask[j])) * 3;
+
+ b >>= (tree[tindex + 1]);
+ k -= (tree[tindex + 1]);
+
+ e = tree[tindex];
+
+ if (e == 0)
+ { // literal
+ lit = tree[tindex + 2];
+ mode = InflateCodeMode.LIT;
+ break;
+ }
+ if ((e & 16) != 0)
+ { // length
+ get = e & 15;
+ len = tree[tindex + 2];
+ mode = InflateCodeMode.LENEXT;
+ break;
+ }
+ if ((e & 64) == 0)
+ { // next table
+ need = e;
+ tree_index = tindex / 3 + tree[tindex + 2];
+ break;
+ }
+ if ((e & 32) != 0)
+ { // end of block
+ mode = InflateCodeMode.WASH;
+ break;
+ }
+ mode = InflateCodeMode.BADCODE; // invalid code
+ z.msg = "invalid literal/length code";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ case InflateCodeMode.LENEXT: // i: getting length extra (have base)
+ j = get;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--; b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ len += (b & inflate_mask[j]);
+
+ b >>= j;
+ k -= j;
+
+ need = dbits;
+ tree = dtree;
+ tree_index = dtree_index;
+ mode = InflateCodeMode.DIST;
+ goto case InflateCodeMode.DIST;
+ case InflateCodeMode.DIST: // i: get distance next
+ j = need;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--; b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ tindex = (tree_index + (b & inflate_mask[j])) * 3;
+
+ b >>= tree[tindex + 1];
+ k -= tree[tindex + 1];
+
+ e = (tree[tindex]);
+ if ((e & 16) != 0)
+ { // distance
+ get = e & 15;
+ dist = tree[tindex + 2];
+ mode = InflateCodeMode.DISTEXT;
+ break;
+ }
+ if ((e & 64) == 0)
+ { // next table
+ need = e;
+ tree_index = tindex / 3 + tree[tindex + 2];
+ break;
+ }
+ mode = InflateCodeMode.BADCODE; // invalid code
+ z.msg = "invalid distance code";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ case InflateCodeMode.DISTEXT: // i: getting distance extra
+ j = get;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--; b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ dist += (b & inflate_mask[j]);
+
+ b >>= j;
+ k -= j;
+
+ mode = InflateCodeMode.COPY;
+ goto case InflateCodeMode.COPY;
+ case InflateCodeMode.COPY: // o: copying bytes in window, waiting for space
+ f = q - dist;
+ while (f < 0)
+ { // modulo window size-"while" instead
+ f += s.end; // of "if" handles invalid distances
+ }
+ while (len != 0)
+ {
+
+ if (m == 0)
+ {
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+ if (m == 0)
+ {
+ s.write = q; r = s.inflate_flush(z, r);
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+
+ if (m == 0)
+ {
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ }
+ }
+
+ s.window[q++] = s.window[f++]; m--;
+
+ if (f == s.end)
+ f = 0;
+ len--;
+ }
+ mode = InflateCodeMode.START;
+ break;
+ case InflateCodeMode.LIT: // o: got literal, waiting for output space
+ if (m == 0)
+ {
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+ if (m == 0)
+ {
+ s.write = q; r = s.inflate_flush(z, r);
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+ if (m == 0)
+ {
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ }
+ }
+ r = ZLibStatus.Z_OK;
+
+ s.window[q++] = (byte)lit; m--;
+
+ mode = InflateCodeMode.START;
+ break;
+ case InflateCodeMode.WASH: // o: got eob, possibly more output
+ if (k > 7)
+ { // return unused byte, if any
+ k -= 8;
+ n++;
+ p--; // can always return one
+ }
+
+ s.write = q; r = s.inflate_flush(z, r);
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (s.read != s.write)
+ {
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ mode = InflateCodeMode.END;
+ goto case InflateCodeMode.END;
+ case InflateCodeMode.END:
+ r = ZLibStatus.Z_STREAM_END;
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ case InflateCodeMode.BADCODE: // x: got error
+
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ default:
+ r = ZLibStatus.Z_STREAM_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ }
+ }
+
+ internal void codesfree(ZStream z)
+ {
+ // ZFREE(z, c);
+ }
+
+ // Called with number of bytes left to write in window at least 258
+ // (the maximum string length) and number of input bytes available
+ // at least ten. The ten bytes are six bytes for the longest length/
+ // distance pair plus four bytes for overloading the bit buffer.
+
+ internal ZLibStatus inflate_fast(int bl, int bd,
+ int[] tl, int tl_index,
+ int[] td, int td_index,
+ InflateBlocks s, ZStream z)
+ {
+ int t; // temporary pointer
+ int[] tp; // temporary pointer
+ int tp_index; // temporary pointer
+ int e; // extra bits or operation
+ int b; // bit buffer
+ int k; // bits in bit buffer
+ int p; // input data pointer
+ int n; // bytes available there
+ int q; // output window write pointer
+ int m; // bytes to end of window or read pointer
+ int ml; // mask for literal/length tree
+ int md; // mask for distance tree
+ int c; // bytes to copy
+ int d; // distance back to copy from
+ int r; // copy source pointer
+
+ int tp_index_t_3; // (tp_index+t)*3
+
+ // load input, output, bit values
+ p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk;
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ // initialize masks
+ ml = inflate_mask[bl];
+ md = inflate_mask[bd];
+
+ // do until not enough input or output space for fast loop
+ do
+ { // assume called with m >= 258 && n >= 10
+ // get literal/length code
+ while (k < (20))
+ { // max bits for literal/length code
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k; k += 8;
+ }
+
+ t = b & ml;
+ tp = tl;
+ tp_index = tl_index;
+ tp_index_t_3 = (tp_index + t) * 3;
+ if ((e = tp[tp_index_t_3]) == 0)
+ {
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ s.window[q++] = (byte)tp[tp_index_t_3 + 2];
+ m--;
+ continue;
+ }
+ do
+ {
+
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ if ((e & 16) != 0)
+ {
+ e &= 15;
+ c = tp[tp_index_t_3 + 2] + ((int)b & inflate_mask[e]);
+
+ b >>= e; k -= e;
+
+ // decode distance base of block to copy
+ while (k < (15))
+ { // max bits for distance code
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k; k += 8;
+ }
+
+ t = b & md;
+ tp = td;
+ tp_index = td_index;
+ tp_index_t_3 = (tp_index + t) * 3;
+ e = tp[tp_index_t_3];
+
+ do
+ {
+
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ if ((e & 16) != 0)
+ {
+ // get extra bits to add to distance base
+ e &= 15;
+ while (k < (e))
+ { // get extra bits (up to 13)
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k; k += 8;
+ }
+
+ d = tp[tp_index_t_3 + 2] + (b & inflate_mask[e]);
+
+ b >>= (e); k -= (e);
+
+ // do the copy
+ m -= c;
+ if (q >= d)
+ { // offset before dest
+ // just copy
+ r = q - d;
+ if (q - r > 0 && 2 > (q - r))
+ {
+ s.window[q++] = s.window[r++]; // minimum count is three,
+ s.window[q++] = s.window[r++]; // so unroll loop a little
+ c -= 2;
+ }
+ else
+ {
+ System.Array.Copy(s.window, r, s.window, q, 2);
+ q += 2; r += 2; c -= 2;
+ }
+ }
+ else
+ { // else offset after destination
+ r = q - d;
+ do
+ {
+ r += s.end; // force pointer in window
+ } while (r < 0); // covers invalid distances
+ e = s.end - r;
+ if (c > e)
+ { // if source crosses,
+ c -= e; // wrapped copy
+ if (q - r > 0 && e > (q - r))
+ {
+ do { s.window[q++] = s.window[r++]; }
+ while (--e != 0);
+ }
+ else
+ {
+ System.Array.Copy(s.window, r, s.window, q, e);
+ q += e; r += e; e = 0;
+ }
+ r = 0; // copy rest from start of window
+ }
+
+ }
+
+ // copy all or what's left
+ if (q - r > 0 && c > (q - r))
+ {
+ do { s.window[q++] = s.window[r++]; }
+ while (--c != 0);
+ }
+ else
+ {
+ System.Array.Copy(s.window, r, s.window, q, c);
+ q += c; r += c; c = 0;
+ }
+ break;
+ }
+ else if ((e & 64) == 0)
+ {
+ t += tp[tp_index_t_3 + 2];
+ t += (b & inflate_mask[e]);
+ tp_index_t_3 = (tp_index + t) * 3;
+ e = tp[tp_index_t_3];
+ }
+ else
+ {
+ z.msg = "invalid distance code";
+
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ }
+ while (true);
+ break;
+ }
+
+ if ((e & 64) == 0)
+ {
+ t += tp[tp_index_t_3 + 2];
+ t += (b & inflate_mask[e]);
+ tp_index_t_3 = (tp_index + t) * 3;
+ if ((e = tp[tp_index_t_3]) == 0)
+ {
+
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ s.window[q++] = (byte)tp[tp_index_t_3 + 2];
+ m--;
+ break;
+ }
+ }
+ else if ((e & 32) != 0)
+ {
+
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_STREAM_END;
+ }
+ else
+ {
+ z.msg = "invalid literal/length code";
+
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ }
+ while (true);
+ }
+ while (m >= 258 && n >= 10);
+
+ // not enough input or output--restore pointers and return
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_OK;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Version.5/InflateTree.cs b/Renci.SshNet/Compression/Version.5/InflateTree.cs
new file mode 100644
index 0000000..f9da579
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.5/InflateTree.cs
@@ -0,0 +1,555 @@
+using System;
+/*
+ * $Id: InfTree.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ internal sealed class InflateTree
+ {
+ private const int MANY = 1440;
+
+ private const int fixed_bl = 9;
+ private const int fixed_bd = 5;
+
+ static readonly int[] fixed_tl = {
+ 96,7,256, 0,8,80, 0,8,16, 84,8,115,
+ 82,7,31, 0,8,112, 0,8,48, 0,9,192,
+ 80,7,10, 0,8,96, 0,8,32, 0,9,160,
+ 0,8,0, 0,8,128, 0,8,64, 0,9,224,
+ 80,7,6, 0,8,88, 0,8,24, 0,9,144,
+ 83,7,59, 0,8,120, 0,8,56, 0,9,208,
+ 81,7,17, 0,8,104, 0,8,40, 0,9,176,
+ 0,8,8, 0,8,136, 0,8,72, 0,9,240,
+ 80,7,4, 0,8,84, 0,8,20, 85,8,227,
+ 83,7,43, 0,8,116, 0,8,52, 0,9,200,
+ 81,7,13, 0,8,100, 0,8,36, 0,9,168,
+ 0,8,4, 0,8,132, 0,8,68, 0,9,232,
+ 80,7,8, 0,8,92, 0,8,28, 0,9,152,
+ 84,7,83, 0,8,124, 0,8,60, 0,9,216,
+ 82,7,23, 0,8,108, 0,8,44, 0,9,184,
+ 0,8,12, 0,8,140, 0,8,76, 0,9,248,
+ 80,7,3, 0,8,82, 0,8,18, 85,8,163,
+ 83,7,35, 0,8,114, 0,8,50, 0,9,196,
+ 81,7,11, 0,8,98, 0,8,34, 0,9,164,
+ 0,8,2, 0,8,130, 0,8,66, 0,9,228,
+ 80,7,7, 0,8,90, 0,8,26, 0,9,148,
+ 84,7,67, 0,8,122, 0,8,58, 0,9,212,
+ 82,7,19, 0,8,106, 0,8,42, 0,9,180,
+ 0,8,10, 0,8,138, 0,8,74, 0,9,244,
+ 80,7,5, 0,8,86, 0,8,22, 192,8,0,
+ 83,7,51, 0,8,118, 0,8,54, 0,9,204,
+ 81,7,15, 0,8,102, 0,8,38, 0,9,172,
+ 0,8,6, 0,8,134, 0,8,70, 0,9,236,
+ 80,7,9, 0,8,94, 0,8,30, 0,9,156,
+ 84,7,99, 0,8,126, 0,8,62, 0,9,220,
+ 82,7,27, 0,8,110, 0,8,46, 0,9,188,
+ 0,8,14, 0,8,142, 0,8,78, 0,9,252,
+ 96,7,256, 0,8,81, 0,8,17, 85,8,131,
+ 82,7,31, 0,8,113, 0,8,49, 0,9,194,
+ 80,7,10, 0,8,97, 0,8,33, 0,9,162,
+ 0,8,1, 0,8,129, 0,8,65, 0,9,226,
+ 80,7,6, 0,8,89, 0,8,25, 0,9,146,
+ 83,7,59, 0,8,121, 0,8,57, 0,9,210,
+ 81,7,17, 0,8,105, 0,8,41, 0,9,178,
+ 0,8,9, 0,8,137, 0,8,73, 0,9,242,
+ 80,7,4, 0,8,85, 0,8,21, 80,8,258,
+ 83,7,43, 0,8,117, 0,8,53, 0,9,202,
+ 81,7,13, 0,8,101, 0,8,37, 0,9,170,
+ 0,8,5, 0,8,133, 0,8,69, 0,9,234,
+ 80,7,8, 0,8,93, 0,8,29, 0,9,154,
+ 84,7,83, 0,8,125, 0,8,61, 0,9,218,
+ 82,7,23, 0,8,109, 0,8,45, 0,9,186,
+ 0,8,13, 0,8,141, 0,8,77, 0,9,250,
+ 80,7,3, 0,8,83, 0,8,19, 85,8,195,
+ 83,7,35, 0,8,115, 0,8,51, 0,9,198,
+ 81,7,11, 0,8,99, 0,8,35, 0,9,166,
+ 0,8,3, 0,8,131, 0,8,67, 0,9,230,
+ 80,7,7, 0,8,91, 0,8,27, 0,9,150,
+ 84,7,67, 0,8,123, 0,8,59, 0,9,214,
+ 82,7,19, 0,8,107, 0,8,43, 0,9,182,
+ 0,8,11, 0,8,139, 0,8,75, 0,9,246,
+ 80,7,5, 0,8,87, 0,8,23, 192,8,0,
+ 83,7,51, 0,8,119, 0,8,55, 0,9,206,
+ 81,7,15, 0,8,103, 0,8,39, 0,9,174,
+ 0,8,7, 0,8,135, 0,8,71, 0,9,238,
+ 80,7,9, 0,8,95, 0,8,31, 0,9,158,
+ 84,7,99, 0,8,127, 0,8,63, 0,9,222,
+ 82,7,27, 0,8,111, 0,8,47, 0,9,190,
+ 0,8,15, 0,8,143, 0,8,79, 0,9,254,
+ 96,7,256, 0,8,80, 0,8,16, 84,8,115,
+ 82,7,31, 0,8,112, 0,8,48, 0,9,193,
+
+ 80,7,10, 0,8,96, 0,8,32, 0,9,161,
+ 0,8,0, 0,8,128, 0,8,64, 0,9,225,
+ 80,7,6, 0,8,88, 0,8,24, 0,9,145,
+ 83,7,59, 0,8,120, 0,8,56, 0,9,209,
+ 81,7,17, 0,8,104, 0,8,40, 0,9,177,
+ 0,8,8, 0,8,136, 0,8,72, 0,9,241,
+ 80,7,4, 0,8,84, 0,8,20, 85,8,227,
+ 83,7,43, 0,8,116, 0,8,52, 0,9,201,
+ 81,7,13, 0,8,100, 0,8,36, 0,9,169,
+ 0,8,4, 0,8,132, 0,8,68, 0,9,233,
+ 80,7,8, 0,8,92, 0,8,28, 0,9,153,
+ 84,7,83, 0,8,124, 0,8,60, 0,9,217,
+ 82,7,23, 0,8,108, 0,8,44, 0,9,185,
+ 0,8,12, 0,8,140, 0,8,76, 0,9,249,
+ 80,7,3, 0,8,82, 0,8,18, 85,8,163,
+ 83,7,35, 0,8,114, 0,8,50, 0,9,197,
+ 81,7,11, 0,8,98, 0,8,34, 0,9,165,
+ 0,8,2, 0,8,130, 0,8,66, 0,9,229,
+ 80,7,7, 0,8,90, 0,8,26, 0,9,149,
+ 84,7,67, 0,8,122, 0,8,58, 0,9,213,
+ 82,7,19, 0,8,106, 0,8,42, 0,9,181,
+ 0,8,10, 0,8,138, 0,8,74, 0,9,245,
+ 80,7,5, 0,8,86, 0,8,22, 192,8,0,
+ 83,7,51, 0,8,118, 0,8,54, 0,9,205,
+ 81,7,15, 0,8,102, 0,8,38, 0,9,173,
+ 0,8,6, 0,8,134, 0,8,70, 0,9,237,
+ 80,7,9, 0,8,94, 0,8,30, 0,9,157,
+ 84,7,99, 0,8,126, 0,8,62, 0,9,221,
+ 82,7,27, 0,8,110, 0,8,46, 0,9,189,
+ 0,8,14, 0,8,142, 0,8,78, 0,9,253,
+ 96,7,256, 0,8,81, 0,8,17, 85,8,131,
+ 82,7,31, 0,8,113, 0,8,49, 0,9,195,
+ 80,7,10, 0,8,97, 0,8,33, 0,9,163,
+ 0,8,1, 0,8,129, 0,8,65, 0,9,227,
+ 80,7,6, 0,8,89, 0,8,25, 0,9,147,
+ 83,7,59, 0,8,121, 0,8,57, 0,9,211,
+ 81,7,17, 0,8,105, 0,8,41, 0,9,179,
+ 0,8,9, 0,8,137, 0,8,73, 0,9,243,
+ 80,7,4, 0,8,85, 0,8,21, 80,8,258,
+ 83,7,43, 0,8,117, 0,8,53, 0,9,203,
+ 81,7,13, 0,8,101, 0,8,37, 0,9,171,
+ 0,8,5, 0,8,133, 0,8,69, 0,9,235,
+ 80,7,8, 0,8,93, 0,8,29, 0,9,155,
+ 84,7,83, 0,8,125, 0,8,61, 0,9,219,
+ 82,7,23, 0,8,109, 0,8,45, 0,9,187,
+ 0,8,13, 0,8,141, 0,8,77, 0,9,251,
+ 80,7,3, 0,8,83, 0,8,19, 85,8,195,
+ 83,7,35, 0,8,115, 0,8,51, 0,9,199,
+ 81,7,11, 0,8,99, 0,8,35, 0,9,167,
+ 0,8,3, 0,8,131, 0,8,67, 0,9,231,
+ 80,7,7, 0,8,91, 0,8,27, 0,9,151,
+ 84,7,67, 0,8,123, 0,8,59, 0,9,215,
+ 82,7,19, 0,8,107, 0,8,43, 0,9,183,
+ 0,8,11, 0,8,139, 0,8,75, 0,9,247,
+ 80,7,5, 0,8,87, 0,8,23, 192,8,0,
+ 83,7,51, 0,8,119, 0,8,55, 0,9,207,
+ 81,7,15, 0,8,103, 0,8,39, 0,9,175,
+ 0,8,7, 0,8,135, 0,8,71, 0,9,239,
+ 80,7,9, 0,8,95, 0,8,31, 0,9,159,
+ 84,7,99, 0,8,127, 0,8,63, 0,9,223,
+ 82,7,27, 0,8,111, 0,8,47, 0,9,191,
+ 0,8,15, 0,8,143, 0,8,79, 0,9,255
+ };
+ static readonly int[] fixed_td = {
+ 80,5,1, 87,5,257, 83,5,17, 91,5,4097,
+ 81,5,5, 89,5,1025, 85,5,65, 93,5,16385,
+ 80,5,3, 88,5,513, 84,5,33, 92,5,8193,
+ 82,5,9, 90,5,2049, 86,5,129, 192,5,24577,
+ 80,5,2, 87,5,385, 83,5,25, 91,5,6145,
+ 81,5,7, 89,5,1537, 85,5,97, 93,5,24577,
+ 80,5,4, 88,5,769, 84,5,49, 92,5,12289,
+ 82,5,13, 90,5,3073, 86,5,193, 192,5,24577
+ };
+
+ // Tables for deflate from PKZIP's appnote.txt.
+ static readonly int[] cplens = { // Copy lengths for literal codes 257..285
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
+ };
+
+ // see note #13 above about 258
+ static readonly int[] cplext = { // Extra bits for literal codes 257..285
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+ 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112 // 112==invalid
+ };
+
+ static readonly int[] cpdist = { // Copy offsets for distance codes 0..29
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+ 8193, 12289, 16385, 24577
+ };
+
+ static readonly int[] cpdext = { // Extra bits for distance codes
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+ 12, 12, 13, 13};
+
+ // If BMAX needs to be larger than 16, then h and x[] should be uLong.
+ const int BMAX = 15; // maximum bit length of any code
+
+ int[] hn = null; // hufts used in space
+ int[] v = null; // work area for huft_build
+ int[] c = null; // bit length count table
+ int[] r = null; // table entry for structure assignment
+ int[] u = null; // table stack
+ int[] x = null; // bit offsets, then code stack
+
+ private ZLibStatus HuftBuild(int[] b, // code lengths in bits (all assumed <= BMAX)
+ int bindex,
+ int n, // number of codes (assumed <= 288)
+ int s, // number of simple-valued codes (0..s-1)
+ int[] d, // list of base values for non-simple codes
+ int[] e, // list of extra bits for non-simple codes
+ int[] t, // result: starting table
+ int[] m, // maximum lookup bits, returns actual
+ int[] hp,// space for trees
+ int[] hn,// hufts used in space
+ int[] v // working area: values in order of bit length
+ )
+ {
+ // Given a list of code lengths and a maximum table size, make a set of
+ // tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR
+ // if the given code set is incomplete (the tables are still built in this
+ // case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of
+ // lengths), or Z_MEM_ERROR if not enough memory.
+
+ int a; // counter for codes of length k
+ int f; // i repeats in table every f entries
+ int g; // maximum code length
+ int h; // table level
+ int i; // counter, current code
+ int j; // counter
+ int k; // number of bits in current code
+ int l; // bits per table (returned in m)
+ int mask; // (1 << w) - 1, to avoid cc -O bug on HP
+ int p; // pointer into c[], b[], or v[]
+ int q; // points to current table
+ int w; // bits before this table == (l * h)
+ int xp; // pointer into x
+ int y; // number of dummy codes added
+ int z; // number of entries in current table
+
+ // Generate counts for each bit length
+
+ p = 0; i = n;
+ do
+ {
+ c[b[bindex + p]]++; p++; i--; // assume all entries <= BMAX
+ } while (i != 0);
+
+ if (c[0] == n)
+ { // null input--all zero length codes
+ t[0] = -1;
+ m[0] = 0;
+ return ZLibStatus.Z_OK;
+ }
+
+ // Find minimum and maximum length, bound *m by those
+ l = m[0];
+ for (j = 1; j <= BMAX; j++)
+ if (c[j] != 0) break;
+ k = j; // minimum code length
+ if (l < j)
+ {
+ l = j;
+ }
+ for (i = BMAX; i != 0; i--)
+ {
+ if (c[i] != 0) break;
+ }
+ g = i; // maximum code length
+ if (l > i)
+ {
+ l = i;
+ }
+ m[0] = l;
+
+ // Adjust last length count to fill out codes, if needed
+ for (y = 1 << j; j < i; j++, y <<= 1)
+ {
+ if ((y -= c[j]) < 0)
+ {
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ }
+ if ((y -= c[i]) < 0)
+ {
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ c[i] += y;
+
+ // Generate starting offsets into the value table for each length
+ x[1] = j = 0;
+ p = 1; xp = 2;
+ while (--i != 0)
+ { // note that i == g from above
+ x[xp] = (j += c[p]);
+ xp++;
+ p++;
+ }
+
+ // Make a table of values in order of bit lengths
+ i = 0; p = 0;
+ do
+ {
+ if ((j = b[bindex + p]) != 0)
+ {
+ v[x[j]++] = i;
+ }
+ p++;
+ }
+ while (++i < n);
+ n = x[g]; // set n to length of v
+
+ // Generate the Huffman codes and for each, make the table entries
+ x[0] = i = 0; // first Huffman code is zero
+ p = 0; // grab values in bit order
+ h = -1; // no tables yet--level -1
+ w = -l; // bits decoded == (l * h)
+ u[0] = 0; // just to keep compilers happy
+ q = 0; // ditto
+ z = 0; // ditto
+
+ // go through the bit lengths (k already is bits in shortest code)
+ for (; k <= g; k++)
+ {
+ a = c[k];
+ while (a-- != 0)
+ {
+ // here i is the Huffman code of length k bits for value *p
+ // make tables up to required level
+ while (k > w + l)
+ {
+ h++;
+ w += l; // previous table always l bits
+ // compute minimum size table less than or equal to l bits
+ z = g - w;
+ z = (z > l) ? l : z; // table size upper limit
+ if ((f = 1 << (j = k - w)) > a + 1)
+ { // try a k-w bit table
+ // too few codes for k-w bit table
+ f -= a + 1; // deduct codes from patterns left
+ xp = k;
+ if (j < z)
+ {
+ while (++j < z)
+ { // try smaller tables up to z bits
+ if ((f <<= 1) <= c[++xp])
+ break; // enough codes to use up j bits
+ f -= c[xp]; // else deduct codes from patterns
+ }
+ }
+ }
+ z = 1 << j; // table entries for j-bit table
+
+ // allocate new table
+ if (hn[0] + z > MANY)
+ { // (note: doesn't matter for fixed)
+ return ZLibStatus.Z_DATA_ERROR; // overflow of MANY
+ }
+ u[h] = q = /*hp+*/ hn[0]; // DEBUG
+ hn[0] += z;
+
+ // connect to last table, if there is one
+ if (h != 0)
+ {
+ x[h] = i; // save pattern for backing up
+ r[0] = (byte)j; // bits in this table
+ r[1] = (byte)l; // bits to dump before this table
+ j = i >> (w - l);
+ r[2] = (int)(q - u[h - 1] - j); // offset to this table
+ System.Array.Copy(r, 0, hp, (u[h - 1] + j) * 3, 3); // connect to last table
+ }
+ else
+ {
+ t[0] = q; // first table is returned result
+ }
+ }
+
+ // set up table entry in r
+ r[1] = (byte)(k - w);
+ if (p >= n)
+ {
+ r[0] = 128 + 64; // out of values--invalid code
+ }
+ else if (v[p] < s)
+ {
+ r[0] = (byte)(v[p] < 256 ? 0 : 32 + 64); // 256 is end-of-block
+ r[2] = v[p++]; // simple code is just the value
+ }
+ else
+ {
+ r[0] = (byte)(e[v[p] - s] + 16 + 64); // non-simple--look up in lists
+ r[2] = d[v[p++] - s];
+ }
+
+ // fill code-like entries with r
+ f = 1 << (k - w);
+ for (j = i >> w; j < z; j += f)
+ {
+ System.Array.Copy(r, 0, hp, (q + j) * 3, 3);
+ }
+
+ // backwards increment the k-bit code i
+ for (j = 1 << (k - 1); (i & j) != 0; j >>= 1)
+ {
+ i ^= j;
+ }
+ i ^= j;
+
+ // backup over finished tables
+ mask = (1 << w) - 1; // needed on HP, cc -O bug
+ while ((i & mask) != x[h])
+ {
+ h--; // don't need to update q
+ w -= l;
+ mask = (1 << w) - 1;
+ }
+ }
+ }
+ // Return Z_BUF_ERROR if we were given an incomplete table
+ return y != 0 && g != 1 ? ZLibStatus.Z_BUF_ERROR : ZLibStatus.Z_OK;
+ }
+
+ internal ZLibStatus InflateTreesBits(int[] c, // 19 code lengths
+ int[] bb, // bits tree desired/actual depth
+ int[] tb, // bits tree result
+ int[] hp, // space for trees
+ ZStream z // for messages
+ )
+ {
+ ZLibStatus result;
+ InitWorkArea(19);
+ hn[0] = 0;
+ result = HuftBuild(c, 0, 19, 19, null, null, tb, bb, hp, hn, v);
+
+ if (result == ZLibStatus.Z_DATA_ERROR)
+ {
+ z.msg = "oversubscribed dynamic bit lengths tree";
+ }
+ else if (result == ZLibStatus.Z_BUF_ERROR || bb[0] == 0)
+ {
+ z.msg = "incomplete dynamic bit lengths tree";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ return result;
+ }
+
+ internal ZLibStatus InflateTreesDynamic(int nl, // number of literal/length codes
+ int nd, // number of distance codes
+ int[] c, // that many (total) code lengths
+ int[] bl, // literal desired/actual bit depth
+ int[] bd, // distance desired/actual bit depth
+ int[] tl, // literal/length tree result
+ int[] td, // distance tree result
+ int[] hp, // space for trees
+ ZStream z // for messages
+ )
+ {
+ ZLibStatus result;
+
+ // build literal/length tree
+ InitWorkArea(288);
+ hn[0] = 0;
+ result = HuftBuild(c, 0, nl, 257, cplens, cplext, tl, bl, hp, hn, v);
+ if (result != ZLibStatus.Z_OK || bl[0] == 0)
+ {
+ if (result == ZLibStatus.Z_DATA_ERROR)
+ {
+ z.msg = "oversubscribed literal/length tree";
+ }
+ else if (result != ZLibStatus.Z_MEM_ERROR)
+ {
+ z.msg = "incomplete literal/length tree";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ return result;
+ }
+
+ // build distance tree
+ InitWorkArea(288);
+ result = HuftBuild(c, nl, nd, 0, cpdist, cpdext, td, bd, hp, hn, v);
+
+ if (result != ZLibStatus.Z_OK || (bd[0] == 0 && nl > 257))
+ {
+ if (result == ZLibStatus.Z_DATA_ERROR)
+ {
+ z.msg = "oversubscribed distance tree";
+ }
+ else if (result == ZLibStatus.Z_BUF_ERROR)
+ {
+ z.msg = "incomplete distance tree";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ else if (result != ZLibStatus.Z_MEM_ERROR)
+ {
+ z.msg = "empty distance tree with lengths";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ return result;
+ }
+
+ return ZLibStatus.Z_OK;
+ }
+
+ internal static ZLibStatus InflateTreesFixed(int[] bl, //literal desired/actual bit depth
+ int[] bd, //distance desired/actual bit depth
+ int[][] tl,//literal/length tree result
+ int[][] td,//distance tree result
+ ZStream z //for memory allocation
+ )
+ {
+ bl[0] = fixed_bl;
+ bd[0] = fixed_bd;
+ tl[0] = fixed_tl;
+ td[0] = fixed_td;
+ return ZLibStatus.Z_OK;
+ }
+
+ private void InitWorkArea(int vsize)
+ {
+ if (hn == null)
+ {
+ hn = new int[1];
+ v = new int[vsize];
+ c = new int[BMAX + 1];
+ r = new int[3];
+ u = new int[BMAX];
+ x = new int[BMAX + 1];
+ }
+ if (v.Length < vsize) { v = new int[vsize]; }
+ for (int i = 0; i < vsize; i++) { v[i] = 0; }
+ for (int i = 0; i < BMAX + 1; i++) { c[i] = 0; }
+ for (int i = 0; i < 3; i++) { r[i] = 0; }
+ // for(int i=0; i
+ /// Gets the static tree or null
+ ///
+ ///
+ /// The static_tree.
+ ///
+ public short[] TreeData { get; private set; }
+
+ ///
+ /// Gets the extra bits for each code or null.
+ ///
+ ///
+ /// The extra bits.
+ ///
+ public int[] ExtraBits { get; private set; }
+
+ ///
+ /// Gets the base index for extra_bits.
+ ///
+ ///
+ /// The extra base.
+ ///
+ public int ExtraBase { get; private set; }
+
+ ///
+ /// Gets the max number of elements in the tree.
+ ///
+ ///
+ /// The elements.
+ ///
+ public int Elements { get; private set; }
+
+ ///
+ /// Gets the max bit length for the codes.
+ ///
+ ///
+ /// The length of the max.
+ ///
+ public int MaxLength { get; private set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The tree data.
+ /// The extra bits.
+ /// The extra base.
+ /// The elements.
+ /// Length of the max.
+ public StaticTree(short[] treeData, int[] extraBits, int extraBase, int elements, int maxLength)
+ {
+ this.TreeData = treeData;
+ this.ExtraBits = extraBits;
+ this.ExtraBase = extraBase;
+ this.Elements = elements;
+ this.MaxLength = maxLength;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Version.5/Tree.cs b/Renci.SshNet/Compression/Version.5/Tree.cs
new file mode 100644
index 0000000..d2142c9
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.5/Tree.cs
@@ -0,0 +1,334 @@
+using System;
+/*
+ * $Id: Tree.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+ internal sealed class Tree
+ {
+ private const int MAX_BITS = 15;
+
+ private const int LITERALS = 256;
+
+ private const int LENGTH_CODES = 29;
+
+ private const int L_CODES = (LITERALS + 1 + LENGTH_CODES);
+
+ private const int HEAP_SIZE = (2 * L_CODES + 1);
+
+ private static byte[] _dist_code = {
+ 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8,
+ 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17,
+ 18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
+ 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
+ };
+
+
+ ///
+ /// The corresponding static tree
+ ///
+ private StaticTree _staticTree;
+
+ ///
+ /// The dynamic tree
+ ///
+ private short[] _dynamicTree;
+
+ ///
+ /// Gets the largest code with non zero frequency.
+ ///
+ ///
+ /// The max_code.
+ ///
+ public int LargestCode { get; private set; }
+
+ public void Init(short[] dynamicTree, StaticTree staticTree)
+ {
+ this._staticTree = staticTree;
+ this._dynamicTree = dynamicTree;
+ }
+
+ ///
+ /// Mapping from a distance to a distance code. dist is the distance - 1 and must not have side effects. _dist_code[256] and _dist_code[257] are never used.
+ ///
+ /// The dist.
+ ///
+ public static int DistanceCode(int dist)
+ {
+ // TODO: Under multiple port forward after more then 50K requests gets index out of range
+ return ((dist) < 256 ? _dist_code[dist] : _dist_code[256 + ((dist) >> 7)]);
+ }
+
+ ///
+ /// Construct one Huffman tree and assigns the code bit strings and lengths. Update the total bit length for the current block.
+ ///
+ /// The s.
+ public void BuildTree(Deflate s)
+ {
+ short[] tree = _dynamicTree;
+ short[] stree = _staticTree.TreeData;
+ int elems = _staticTree.Elements;
+ int n, m; // iterate over heap elements
+ int max_code = -1; // largest code with non zero frequency
+ int node; // new node being created
+
+ // Construct the initial heap, with least frequent element in
+ // heap[1]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
+ // heap[0] is not used.
+ s.heap_len = 0;
+ s.heap_max = HEAP_SIZE;
+
+ for (n = 0; n < elems; n++)
+ {
+ if (tree[n * 2] != 0)
+ {
+ s.heap[++s.heap_len] = max_code = n;
+ s.depth[n] = 0;
+ }
+ else
+ {
+ tree[n * 2 + 1] = 0;
+ }
+ }
+
+ // The pkzip format requires that at least one distance code exists,
+ // and that at least one bit should be sent even if there is only one
+ // possible code. So to avoid special checks later on we force at least
+ // two codes of non zero frequency.
+ while (s.heap_len < 2)
+ {
+ node = s.heap[++s.heap_len] = (max_code < 2 ? ++max_code : 0);
+ tree[node * 2] = 1;
+ s.depth[node] = 0;
+ s.opt_len--; if (stree != null) s.static_len -= stree[node * 2 + 1];
+ // node is 0 or 1 so it does not have extra bits
+ }
+ this.LargestCode = max_code;
+
+ // The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
+ // establish sub-heaps of increasing lengths:
+
+ for (n = s.heap_len / 2; n >= 1; n--)
+ s.pqdownheap(tree, n);
+
+ // Construct the Huffman tree by repeatedly combining the least two
+ // frequent nodes.
+
+ node = elems; // next internal node of the tree
+ do
+ {
+ // n = node of least frequency
+ n = s.heap[1];
+ s.heap[1] = s.heap[s.heap_len--];
+ s.pqdownheap(tree, 1);
+ m = s.heap[1]; // m = node of next least frequency
+
+ s.heap[--s.heap_max] = n; // keep the nodes sorted by frequency
+ s.heap[--s.heap_max] = m;
+
+ // Create a new node father of n and m
+ tree[node * 2] = (short)(tree[n * 2] + tree[m * 2]);
+ s.depth[node] = (byte)(System.Math.Max(s.depth[n], s.depth[m]) + 1);
+ tree[n * 2 + 1] = tree[m * 2 + 1] = (short)node;
+
+ // and insert the new node in the heap
+ s.heap[1] = node++;
+ s.pqdownheap(tree, 1);
+ }
+ while (s.heap_len >= 2);
+
+ s.heap[--s.heap_max] = s.heap[1];
+
+ // At this point, the fields freq and dad are set. We can now
+ // generate the bit lengths.
+
+ ComputeBitLength(s);
+
+ // The field len is now set, we can generate the bit codes
+ GenerateCodes(tree, max_code, s.bl_count);
+ }
+
+ ///
+ /// Compute the optimal bit lengths for a tree and update the total bit length for the current block.
+ ///
+ /// The s.
+ private void ComputeBitLength(Deflate s)
+ {
+ short[] tree = _dynamicTree;
+ short[] stree = _staticTree.TreeData;
+ int[] extra = _staticTree.ExtraBits;
+ int based = _staticTree.ExtraBase;
+ int max_length = _staticTree.MaxLength;
+ int h; // heap index
+ int n, m; // iterate over the tree elements
+ int bits; // bit length
+ int xbits; // extra bits
+ short f; // frequency
+ int overflow = 0; // number of elements with bit length too large
+
+ for (bits = 0; bits <= MAX_BITS; bits++) s.bl_count[bits] = 0;
+
+ // In a first pass, compute the optimal bit lengths (which may
+ // overflow in the case of the bit length tree).
+ tree[s.heap[s.heap_max] * 2 + 1] = 0; // root of the heap
+
+ for (h = s.heap_max + 1; h < HEAP_SIZE; h++)
+ {
+ n = s.heap[h];
+ bits = tree[tree[n * 2 + 1] * 2 + 1] + 1;
+ if (bits > max_length) { bits = max_length; overflow++; }
+ tree[n * 2 + 1] = (short)bits;
+ // We overwrite tree[n*2+1] which is no longer needed
+
+ if (n > LargestCode) continue; // not a leaf node
+
+ s.bl_count[bits]++;
+ xbits = 0;
+ if (n >= based) xbits = extra[n - based];
+ f = tree[n * 2];
+ s.opt_len += f * (bits + xbits);
+ if (stree != null) s.static_len += f * (stree[n * 2 + 1] + xbits);
+ }
+ if (overflow == 0) return;
+
+ // This happens for example on obj2 and pic of the Calgary corpus
+ // Find the first bit length which could increase:
+ do
+ {
+ bits = max_length - 1;
+ while (s.bl_count[bits] == 0) bits--;
+ s.bl_count[bits]--; // move one leaf down the tree
+ s.bl_count[bits + 1] += 2; // move one overflow item as its brother
+ s.bl_count[max_length]--;
+ // The brother of the overflow item also moves one step up,
+ // but this does not affect bl_count[max_length]
+ overflow -= 2;
+ }
+ while (overflow > 0);
+
+ for (bits = max_length; bits != 0; bits--)
+ {
+ n = s.bl_count[bits];
+ while (n != 0)
+ {
+ m = s.heap[--h];
+ if (m > LargestCode) continue;
+ if (tree[m * 2 + 1] != bits)
+ {
+ s.opt_len += (int)(((long)bits - (long)tree[m * 2 + 1]) * (long)tree[m * 2]);
+ tree[m * 2 + 1] = (short)bits;
+ }
+ n--;
+ }
+ }
+ }
+
+ ///
+ /// Generate the codes for a given tree and bit counts (which need not be optimal).
+ ///
+ /// The tree to decorate.
+ /// The largest code with non zero frequency.
+ /// The number of codes at each bit length.
+ private static void GenerateCodes(short[] tree, int max_code, short[] bl_count)
+ {
+ short[] next_code = new short[MAX_BITS + 1]; // next code value for each bit length
+ short code = 0; // running code value
+ int bits; // bit index
+ int n; // code index
+
+ // The distribution counts are first used to generate the code values
+ // without bit reversal.
+ for (bits = 1; bits <= MAX_BITS; bits++)
+ {
+ next_code[bits] = code = (short)((code + bl_count[bits - 1]) << 1);
+ }
+
+ // Check that the bit counts in bl_count are consistent. The last code
+ // must be all ones.
+ //Assert (code + bl_count[MAX_BITS]-1 == (1<
+ /// Reverse the first len bits of a code, using straightforward code (a faster method would use a table)
+ ///
+ /// The value to invert.
+ /// The bit length.
+ ///
+ private static int BiReverse(int code, int len)
+ {
+ int res = 0;
+ do
+ {
+ res |= code & 1;
+ code >>= 1;
+ res <<= 1;
+ }
+ while (--len > 0);
+ return res >> 1;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Version.5/ZInputStream.cs b/Renci.SshNet/Compression/Version.5/ZInputStream.cs
new file mode 100644
index 0000000..e7ca814
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.5/ZInputStream.cs
@@ -0,0 +1,205 @@
+/*
+Copyright (c) 2001 Lapo Luchini.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS
+OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+/* This file is a port of jzlib v1.0.7, com.jcraft.jzlib.ZInputStream.java
+ */
+
+using Renci.SshNet.Compression;
+using System;
+using System.Diagnostics;
+using System.IO;
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+ public class ZInputStream : Stream
+ {
+ private const int BufferSize = 512;
+ //private ZStream z = new ZStream();
+ private ICompressor _compressor;
+
+ // TODO Allow custom buf
+ private byte[] _buffer = new byte[BufferSize];
+ private CompressionMode _compressionMode;
+ private Stream _input;
+ private bool _isClosed;
+ private bool _noMoreInput = false;
+
+ public FlushType FlushMode { get; private set; }
+
+ public ZInputStream()
+ {
+ this.FlushMode = FlushType.Z_PARTIAL_FLUSH;
+ }
+
+ public ZInputStream(Stream input)
+ : this(input, false)
+ {
+ }
+
+ public ZInputStream(Stream input, bool nowrap)
+ : this()
+ {
+ Debug.Assert(input.CanRead);
+
+ this._input = input;
+ this._compressor = new Inflate();
+ this._compressor.inflateInit(nowrap);
+ this._compressionMode = CompressionMode.Decompress;
+ this._compressor.next_in = _buffer;
+ this._compressor.next_in_index = 0;
+ this._compressor.avail_in = 0;
+ }
+
+ public ZInputStream(Stream input, CompressionLevel level)
+ : this()
+ {
+ Debug.Assert(input.CanRead);
+
+ this._input = input;
+ this._compressor = new Deflate();
+ this._compressor.deflateInit(level);
+ this._compressionMode = CompressionMode.Compress;
+ this._compressor.next_in = _buffer;
+ this._compressor.next_in_index = 0;
+ this._compressor.avail_in = 0;
+ }
+
+ #region Stream implementation
+
+ public sealed override bool CanRead
+ {
+ get { return !_isClosed; }
+ }
+
+ public sealed override bool CanSeek
+ {
+ get { return false; }
+ }
+
+ public sealed override bool CanWrite
+ {
+ get { return false; }
+ }
+
+ public override void Flush()
+ {
+ }
+
+ public override long Length
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ public override long Position
+ {
+ get { throw new NotSupportedException(); }
+ set { throw new NotSupportedException(); }
+ }
+
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ if (count == 0)
+ return 0;
+
+ this._compressor.next_out = buffer;
+ this._compressor.next_out_index = offset;
+ this._compressor.avail_out = count;
+
+ ZLibStatus err = ZLibStatus.Z_OK;
+ do
+ {
+ if (this._compressor.avail_in == 0 && !_noMoreInput)
+ {
+ // if buffer is empty and more input is available, refill it
+ this._compressor.next_in_index = 0;
+ this._compressor.avail_in = _input.Read(_buffer, 0, _buffer.Length); //(bufsize 0 || this._compressor.avail_out == 0);
+ }
+
+ #endregion
+
+ public override void Close()
+ {
+ if (this._isClosed)
+ return;
+
+ try
+ {
+ try
+ {
+ Finish();
+ }
+ catch (IOException)
+ {
+ // Ignore
+ }
+ }
+ finally
+ {
+ this._isClosed = true;
+ End();
+ _output.Close();
+ _output = null;
+ }
+ }
+
+ private void End()
+ {
+ if (this._compressor == null)
+ return;
+ switch (this._compressionMode)
+ {
+ case CompressionMode.Compress:
+ this._compressor.deflateEnd();
+ break;
+ case CompressionMode.Decompress:
+ this._compressor.inflateEnd();
+ break;
+ default:
+ break;
+ }
+
+ this._compressor.free();
+ this._compressor = null;
+ }
+
+ private void Finish()
+ {
+ do
+ {
+ this._compressor.next_out = _buffer;
+ this._compressor.next_out_index = 0;
+ this._compressor.avail_out = _buffer.Length;
+
+ var err = ZLibStatus.Z_OK;
+ switch (this._compressionMode)
+ {
+ case CompressionMode.Compress:
+ err = this._compressor.deflate(FlushType.Z_FINISH);
+ break;
+ case CompressionMode.Decompress:
+ err = this._compressor.inflate(FlushType.Z_FINISH);
+ break;
+ default:
+ break;
+ }
+
+ if (err != ZLibStatus.Z_STREAM_END && err != ZLibStatus.Z_OK)
+ // TODO
+ // throw new ZStreamException((compress?"de":"in")+"flating: "+z.msg);
+ //throw new IOException((_compressionMode ? "de" : "in") + "flating: " + z.msg);
+ throw new IOException(string.Format("{0}ion error: {1}", _compressionMode, this._compressor.msg));
+
+ int count = _buffer.Length - this._compressor.avail_out;
+ if (count > 0)
+ {
+ _output.Write(_buffer, 0, count);
+ }
+ }
+ while (this._compressor.avail_in > 0 || this._compressor.avail_out == 0);
+
+ Flush();
+ }
+ }
+}
diff --git a/Renci.SshNet/Compression/Version.5/ZStream.cs b/Renci.SshNet/Compression/Version.5/ZStream.cs
new file mode 100644
index 0000000..1162e00
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.5/ZStream.cs
@@ -0,0 +1,76 @@
+using System;
+using System.IO;
+/*
+ * $Id: ZStream.cs,v 1.1 2006-07-31 13:59:26 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public abstract class ZStream
+ {
+
+ protected const int MAX_WBITS = 15; // 32K LZ77 window
+ protected const int DEF_WBITS = MAX_WBITS;
+
+ private const int MAX_MEM_LEVEL = 9;
+
+ public byte[] next_in { get; set; } // next input byte
+ public int next_in_index { get; set; }
+ public int avail_in { get; set; } // number of bytes available at next_in
+ public long total_in { get; set; } // total nb of input bytes read so far
+
+ public byte[] next_out { get; set; } // next output byte should be put there
+ public int next_out_index { get; set; }
+ public int avail_out { get; set; } // remaining free space at next_out
+ public long total_out { get; set; } // total nb of bytes output so far
+
+ public String msg { get; set; }
+
+ //internal Deflate dstate;
+ //internal Inflate istate;
+
+ internal BlockType data_type; // best guess about the data type: ascii or binary
+
+ public long adler;
+
+ public void free()
+ {
+ next_in = null;
+ next_out = null;
+ msg = null;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Version.5/Zlib.cs b/Renci.SshNet/Compression/Version.5/Zlib.cs
new file mode 100644
index 0000000..5890675
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.5/Zlib.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Represents "zlib" compression implementation
+ ///
+ internal class Zlib : Compressor
+ {
+ ///
+ /// Gets algorithm name.
+ ///
+ public override string Name
+ {
+ get { return "zlib"; }
+ }
+
+ ///
+ /// Initializes the algorithm
+ ///
+ /// The session.
+ public override void Init(Session session)
+ {
+ base.Init(session);
+ this.IsActive = true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Version.5/ZlibOpenSsh.cs b/Renci.SshNet/Compression/Version.5/ZlibOpenSsh.cs
new file mode 100644
index 0000000..f82a4c0
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.5/ZlibOpenSsh.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Represents "zlib@openssh.org" compression implementation
+ ///
+ public class ZlibOpenSsh : Compressor
+ {
+ ///
+ /// Gets algorithm name.
+ ///
+ public override string Name
+ {
+ get { return "zlib@openssh.org"; }
+ }
+
+ ///
+ /// Initializes the algorithm
+ ///
+ /// The session.
+ public override void Init(Session session)
+ {
+ base.Init(session);
+
+ session.UserAuthenticationSuccessReceived += Session_UserAuthenticationSuccessReceived;
+ }
+
+ private void Session_UserAuthenticationSuccessReceived(object sender, MessageEventArgs e)
+ {
+ this.IsActive = true;
+ this.Session.UserAuthenticationSuccessReceived -= Session_UserAuthenticationSuccessReceived;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Version.5/ZlibStream.cs b/Renci.SshNet/Compression/Version.5/ZlibStream.cs
new file mode 100644
index 0000000..fb5f9d2
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.5/ZlibStream.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.IO;
+using Org.BouncyCastle.Utilities.Zlib;
+
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Implements Zlib compression algorithm.
+ ///
+ public class ZlibStream
+ {
+ private readonly Stream _baseStream;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The stream.
+ /// The mode.
+ public ZlibStream(Stream stream, CompressionMode mode)
+ {
+ switch (mode)
+ {
+ case CompressionMode.Compress:
+ //this._baseStream = new ZOutputStream(stream, CompressionLevel.Z_DEFAULT_COMPRESSION);
+ this._baseStream = new ZOutputStream(stream, CompressionLevel.Z_DEFAULT_COMPRESSION);
+ break;
+ case CompressionMode.Decompress:
+ this._baseStream = new ZOutputStream(stream);
+ break;
+ default:
+ break;
+ }
+
+ //this._baseStream.FlushMode = Ionic.Zlib.FlushType.Partial;
+ }
+
+ ///
+ /// Writes the specified buffer.
+ ///
+ /// The buffer.
+ /// The offset.
+ /// The count.
+ public void Write(byte[] buffer, int offset, int count)
+ {
+ this._baseStream.Write(buffer, offset, count);
+ }
+ }
+}
diff --git a/Renci.SshNet/Compression/Version.6/Adler32.cs b/Renci.SshNet/Compression/Version.6/Adler32.cs
new file mode 100644
index 0000000..c132fa9
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.6/Adler32.cs
@@ -0,0 +1,95 @@
+using System;
+/*
+ * $Id: Adler32.cs,v 1.1 2006-07-31 13:59:25 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ internal static class Adler32
+ {
+
+ // largest prime smaller than 65536
+ private const int BASE = 65521;
+ // NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
+ private const int NMAX = 5552;
+
+ internal static long adler32(long adler, byte[] buf, int index, int len)
+ {
+ if (buf == null) { return 1L; }
+
+ long s1 = adler & 0xffff;
+ long s2 = (adler >> 16) & 0xffff;
+ int k;
+
+ while (len > 0)
+ {
+ k = len < NMAX ? len : NMAX;
+ len -= k;
+ while (k >= 16)
+ {
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ k -= 16;
+ }
+ if (k != 0)
+ {
+ do
+ {
+ s1 += buf[index++] & 0xff; s2 += s1;
+ }
+ while (--k != 0);
+ }
+ s1 %= BASE;
+ s2 %= BASE;
+ }
+ return (s2 << 16) | s1;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Version.6/CompressionMode.cs b/Renci.SshNet/Compression/Version.6/CompressionMode.cs
new file mode 100644
index 0000000..1577e0b
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.6/CompressionMode.cs
@@ -0,0 +1,18 @@
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Specifies compression modes
+ ///
+ public enum CompressionMode
+ {
+ ///
+ /// Specifies that content should be compressed.
+ ///
+ Compress = 0,
+
+ ///
+ /// Specifies that content should be decompressed.
+ ///
+ Decompress = 1,
+ }
+}
diff --git a/Renci.SshNet/Compression/Version.6/Compressor.cs b/Renci.SshNet/Compression/Version.6/Compressor.cs
new file mode 100644
index 0000000..1479bb6
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.6/Compressor.cs
@@ -0,0 +1,151 @@
+using System.Collections.Generic;
+using Renci.SshNet.Security;
+using System.IO;
+using System;
+
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Represents base class for compression algorithm implementation
+ ///
+ public abstract class Compressor : Algorithm, IDisposable
+ {
+ private readonly ZlibStream _compressor;
+ private readonly ZlibStream _decompressor;
+
+ private MemoryStream _compressorStream;
+ private MemoryStream _decompressorStream;
+
+ ///
+ /// Gets or sets a value indicating whether compression is active.
+ ///
+ ///
+ /// true if compression is active; otherwise, false.
+ ///
+ protected bool IsActive { get; set; }
+
+ ///
+ /// Gets the session.
+ ///
+ protected Session Session { get; private set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ 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);
+ }
+
+ ///
+ /// Initializes the algorithm
+ ///
+ /// The session.
+ public virtual void Init(Session session)
+ {
+ this.Session = session;
+ }
+
+ ///
+ /// Compresses the specified data.
+ ///
+ /// Data to compress.
+ /// Compressed 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();
+ }
+
+ ///
+ /// Decompresses the specified data.
+ ///
+ /// Compressed data.
+ /// Decompressed 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;
+
+ ///
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged ResourceMessages.
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Releases unmanaged and - optionally - managed resources
+ ///
+ /// true to release both managed and unmanaged resources; false to release only unmanaged ResourceMessages.
+ 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;
+ }
+ }
+
+ ///
+ /// Releases unmanaged resources and performs other cleanup operations before the
+ /// is reclaimed by garbage collection.
+ ///
+ ~Compressor()
+ {
+ // Do not re-create Dispose clean-up code here.
+ // Calling Dispose(false) is optimal in terms of
+ // readability and maintainability.
+ Dispose(false);
+ }
+
+ #endregion
+ }
+}
diff --git a/Renci.SshNet/Compression/Version.6/Deflate.cs b/Renci.SshNet/Compression/Version.6/Deflate.cs
new file mode 100644
index 0000000..fb8fb30
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.6/Deflate.cs
@@ -0,0 +1,2401 @@
+using System;
+using System.Collections.Generic;
+/*
+ * $Id: Deflate.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public enum BlockType : byte
+ {
+ Z_BINARY = 0,
+ Z_ASCII = 1,
+ Z_UNKNOWN = 2
+ }
+
+ public enum DefalteFlavor : int
+ {
+ STORED = 0,
+ FAST = 1,
+ SLOW = 2
+ }
+
+ public sealed class Deflate : ZStream, ICompressor
+ {
+ private const int MAX_MEM_LEVEL = 9;
+
+ private const int Z_DEFAULT_COMPRESSION = -1;
+
+ private const int MAX_WBITS = 15; // 32K LZ77 window
+
+ private const int DEF_MEM_LEVEL = 8;
+
+ ///
+ /// The Bit length codes must not exceed MAX_BL_BITS bits
+ ///
+ private const int MAX_BL_BITS = 7;
+
+ // block not completed, need more input or more output
+ private const int NeedMore = 0;
+
+ // block flush performed
+ private const int BlockDone = 1;
+
+ // finish started, need only more output at next deflate
+ private const int FinishStarted = 2;
+
+ // finish done, accept no more input or output
+ private const int FinishDone = 3;
+
+ // preset dictionary flag in zlib header
+ private const int PRESET_DICT = 0x20;
+
+ private const int Z_VERSION_ERROR = -6;
+
+ private const int INIT_STATE = 42;
+ private const int BUSY_STATE = 113;
+ private const int FINISH_STATE = 666;
+
+ // The deflate compression method
+ private const int Z_DEFLATED = 8;
+
+ private const int STORED_BLOCK = 0;
+ private const int STATIC_TREES = 1;
+ private const int DYN_TREES = 2;
+
+ private const int Buf_size = 8 * 2;
+
+ // repeat previous bit length 3-6 times (2 bits of repeat count)
+ private const int REP_3_6 = 16;
+
+ // repeat a zero length 3-10 times (3 bits of repeat count)
+ private const int REPZ_3_10 = 17;
+
+ // repeat a zero length 11-138 times (7 bits of repeat count)
+ private const int REPZ_11_138 = 18;
+
+ private const int MIN_MATCH = 3;
+ private const int MAX_MATCH = 258;
+ private const int MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1);
+
+ private const int MAX_BITS = 15;
+ private const int D_CODES = 30;
+ private const int BL_CODES = 19;
+ private const int LENGTH_CODES = 29;
+ private const int LITERALS = 256;
+ private const int L_CODES = (LITERALS + 1 + LENGTH_CODES);
+ private const int HEAP_SIZE = (2 * L_CODES + 1);
+
+ private const int END_BLOCK = 256;
+
+ private static readonly IDictionary config_table = new Dictionary() {
+ {(CompressionLevel)0, new Config(0, 0, 0, 0, DefalteFlavor.STORED)},
+ {(CompressionLevel)1, new Config(4, 4, 8, 4, DefalteFlavor.FAST)},
+ {(CompressionLevel)2, new Config(4, 5, 16, 8, DefalteFlavor.FAST)},
+ {(CompressionLevel)3, new Config(4, 6, 32, 32, DefalteFlavor.FAST)},
+
+ {(CompressionLevel)4, new Config(4, 4, 16, 16, DefalteFlavor.SLOW)},
+ {(CompressionLevel)5, new Config(8, 16, 32, 32, DefalteFlavor.SLOW)},
+ {(CompressionLevel)6, new Config(8, 16, 128, 128, DefalteFlavor.SLOW)},
+ {(CompressionLevel)7, new Config(8, 32, 128, 256, DefalteFlavor.SLOW)},
+ {(CompressionLevel)8, new Config(32, 128, 258, 1024, DefalteFlavor.SLOW)},
+ {(CompressionLevel)9, new Config(32, 258, 258, 4096, DefalteFlavor.SLOW)},
+ };
+
+ #region Static definitions
+
+ private static readonly byte[] _length_code ={
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12,
+ 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
+ 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
+ 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
+ };
+
+ private static readonly int[] base_length = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
+ 64, 80, 96, 112, 128, 160, 192, 224, 0
+ };
+
+ private static readonly int[] base_dist = {
+ 0, 1, 2, 3, 4, 6, 8, 12, 16, 24,
+ 32, 48, 64, 96, 128, 192, 256, 384, 512, 768,
+ 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576
+ };
+
+ // extra bits for each length code
+ private static readonly int[] extra_lbits ={
+ 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0
+ };
+
+ // extra bits for each distance code
+ private static readonly int[] extra_dbits ={
+ 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13
+ };
+
+ // extra bits for each bit length code
+ private static readonly int[] extra_blbits ={
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7
+ };
+
+ private static readonly byte[] bl_order ={
+ 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
+
+ private static readonly short[] static_ltree = {
+ 12, 8, 140, 8, 76, 8, 204, 8, 44, 8,
+ 172, 8, 108, 8, 236, 8, 28, 8, 156, 8,
+ 92, 8, 220, 8, 60, 8, 188, 8, 124, 8,
+ 252, 8, 2, 8, 130, 8, 66, 8, 194, 8,
+ 34, 8, 162, 8, 98, 8, 226, 8, 18, 8,
+ 146, 8, 82, 8, 210, 8, 50, 8, 178, 8,
+ 114, 8, 242, 8, 10, 8, 138, 8, 74, 8,
+ 202, 8, 42, 8, 170, 8, 106, 8, 234, 8,
+ 26, 8, 154, 8, 90, 8, 218, 8, 58, 8,
+ 186, 8, 122, 8, 250, 8, 6, 8, 134, 8,
+ 70, 8, 198, 8, 38, 8, 166, 8, 102, 8,
+ 230, 8, 22, 8, 150, 8, 86, 8, 214, 8,
+ 54, 8, 182, 8, 118, 8, 246, 8, 14, 8,
+ 142, 8, 78, 8, 206, 8, 46, 8, 174, 8,
+ 110, 8, 238, 8, 30, 8, 158, 8, 94, 8,
+ 222, 8, 62, 8, 190, 8, 126, 8, 254, 8,
+ 1, 8, 129, 8, 65, 8, 193, 8, 33, 8,
+ 161, 8, 97, 8, 225, 8, 17, 8, 145, 8,
+ 81, 8, 209, 8, 49, 8, 177, 8, 113, 8,
+ 241, 8, 9, 8, 137, 8, 73, 8, 201, 8,
+ 41, 8, 169, 8, 105, 8, 233, 8, 25, 8,
+ 153, 8, 89, 8, 217, 8, 57, 8, 185, 8,
+ 121, 8, 249, 8, 5, 8, 133, 8, 69, 8,
+ 197, 8, 37, 8, 165, 8, 101, 8, 229, 8,
+ 21, 8, 149, 8, 85, 8, 213, 8, 53, 8,
+ 181, 8, 117, 8, 245, 8, 13, 8, 141, 8,
+ 77, 8, 205, 8, 45, 8, 173, 8, 109, 8,
+ 237, 8, 29, 8, 157, 8, 93, 8, 221, 8,
+ 61, 8, 189, 8, 125, 8, 253, 8, 19, 9,
+ 275, 9, 147, 9, 403, 9, 83, 9, 339, 9,
+ 211, 9, 467, 9, 51, 9, 307, 9, 179, 9,
+ 435, 9, 115, 9, 371, 9, 243, 9, 499, 9,
+ 11, 9, 267, 9, 139, 9, 395, 9, 75, 9,
+ 331, 9, 203, 9, 459, 9, 43, 9, 299, 9,
+ 171, 9, 427, 9, 107, 9, 363, 9, 235, 9,
+ 491, 9, 27, 9, 283, 9, 155, 9, 411, 9,
+ 91, 9, 347, 9, 219, 9, 475, 9, 59, 9,
+ 315, 9, 187, 9, 443, 9, 123, 9, 379, 9,
+ 251, 9, 507, 9, 7, 9, 263, 9, 135, 9,
+ 391, 9, 71, 9, 327, 9, 199, 9, 455, 9,
+ 39, 9, 295, 9, 167, 9, 423, 9, 103, 9,
+ 359, 9, 231, 9, 487, 9, 23, 9, 279, 9,
+ 151, 9, 407, 9, 87, 9, 343, 9, 215, 9,
+ 471, 9, 55, 9, 311, 9, 183, 9, 439, 9,
+ 119, 9, 375, 9, 247, 9, 503, 9, 15, 9,
+ 271, 9, 143, 9, 399, 9, 79, 9, 335, 9,
+ 207, 9, 463, 9, 47, 9, 303, 9, 175, 9,
+ 431, 9, 111, 9, 367, 9, 239, 9, 495, 9,
+ 31, 9, 287, 9, 159, 9, 415, 9, 95, 9,
+ 351, 9, 223, 9, 479, 9, 63, 9, 319, 9,
+ 191, 9, 447, 9, 127, 9, 383, 9, 255, 9,
+ 511, 9, 0, 7, 64, 7, 32, 7, 96, 7,
+ 16, 7, 80, 7, 48, 7, 112, 7, 8, 7,
+ 72, 7, 40, 7, 104, 7, 24, 7, 88, 7,
+ 56, 7, 120, 7, 4, 7, 68, 7, 36, 7,
+ 100, 7, 20, 7, 84, 7, 52, 7, 116, 7,
+ 3, 8, 131, 8, 67, 8, 195, 8, 35, 8,
+ 163, 8, 99, 8, 227, 8
+ };
+
+ private static readonly short[] static_dtree = {
+ 0, 5, 16, 5, 8, 5, 24, 5, 4, 5,
+ 20, 5, 12, 5, 28, 5, 2, 5, 18, 5,
+ 10, 5, 26, 5, 6, 5, 22, 5, 14, 5,
+ 30, 5, 1, 5, 17, 5, 9, 5, 25, 5,
+ 5, 5, 21, 5, 13, 5, 29, 5, 3, 5,
+ 19, 5, 11, 5, 27, 5, 7, 5, 23, 5
+ };
+ #endregion
+
+ private static readonly String[] z_errmsg = {
+ "need dictionary", // ZLibStatus.Z_NEED_DICT 2
+ "stream end", // ZLibStatus.Z_STREAM_END 1
+ "", // ZLibStatus.Z_OK 0
+ "file error", // ZLibStatus.Z_ERRNO (-1)
+ "stream error", // ZLibStatus.Z_STREAM_ERROR (-2)
+ "data error", // ZLibStatus.Z_DATA_ERROR (-3)
+ "insufficient memory", // Z_MEM_ERROR (-4)
+ "buffer error", // ZLibStatus.Z_BUF_ERROR (-5)
+ "incompatible version",// Z_VERSION_ERROR (-6)
+ ""
+ };
+
+
+
+ ///
+ /// pointer back to this zlib stream
+ ///
+ //private ZStream _stream;
+
+ ///
+ /// as the name implies
+ ///
+ private int _status;
+
+ private BlockType _dataType;
+
+ ///
+ /// STORED (for zip only) or DEFLATED
+ ///
+ private byte _method;
+
+ ///
+ /// size of pending_buf
+ ///
+ private int _pendingBufferSize;
+
+ ///
+ /// LZ77 window size (32K by default)
+ ///
+ private int _windowSize;
+
+ ///
+ /// log2(w_size) (8..16)
+ ///
+ private int _windowBits;
+
+ ///
+ /// w_size - 1
+ ///
+ private int _windowMask;
+
+ ///
+ /// Sliding window. Input bytes are read into the second half of the window,
+ /// and move to the first half later to keep a dictionary of at least wSize
+ /// bytes. With this organization, matches are limited to a distance of
+ /// wSize-MAX_MATCH bytes, but this ensures that IO is always
+ /// performed with a length multiple of the block size. Also, it limits
+ /// the window size to 64K, which is quite useful on MSDOS.
+ /// To do: use the user input buffer as sliding window.
+ ///
+ private byte[] _window;
+
+ ///
+ /// Actual size of window: 2*wSize, except when the user input buffer
+ /// is directly used as sliding window.
+ ///
+ private int _windowActualSize;
+
+ ///
+ /// Link to older string with same hash index. To limit the size of this
+ /// array to 64K, this link is maintained only for the last 32K strings.
+ /// An index in this array is thus a window index modulo 32K.
+ ///
+ private short[] _previous;
+
+ ///
+ /// Heads of the hash chains or NIL.
+ ///
+ private short[] _head;
+
+ ///
+ /// hash index of string to be inserted
+ ///
+ private int _insertedHashIndex;
+
+ ///
+ /// number of elements in hash table
+ ///
+ private int _hashSize;
+
+ ///
+ /// log2(hash_size)
+ ///
+ private int _hashBits;
+
+ ///
+ /// hash_size-1
+ ///
+ private int _hashMask;
+
+ ///
+ /// Number of bits by which ins_h must be shifted at each input
+ /// step. It must be such that after MIN_MATCH steps, the oldest
+ /// byte no longer takes part in the hash key, that is:
+ /// hash_shift * MIN_MATCH >= hash_bits
+ ///
+ private int _hashShift;
+
+ ///
+ /// Window position at the beginning of the current output block. Gets
+ /// negative when the window is moved backwards.
+ ///
+ private int _blockStart;
+
+ ///
+ /// length of best match
+ ///
+ private int _matchLength;
+
+ ///
+ /// previous match
+ ///
+ private int _previousMatch;
+
+ ///
+ /// set if previous match exists
+ ///
+ private bool _matchAvailable;
+
+ ///
+ /// start of string to insert
+ ///
+ private int _startInsertString;
+
+ ///
+ /// start of matching string
+ ///
+ private int _startMatchString;
+
+ ///
+ /// number of valid bytes ahead in window
+ ///
+ private int _validBytesAhead;
+
+ ///
+ /// Length of the best match at previous step. Matches not greater than this
+ /// are discarded. This is used in the lazy match evaluation.
+ ///
+ private int _previousLength;
+
+ ///
+ /// To speed up deflation, hash chains are never searched beyond this
+ /// length. A higher limit improves compression ratio but degrades the speed.
+ ///
+ private int _maxChainLength;
+
+ ///
+ /// Attempt to find a better match only when the current match is strictly
+ /// smaller than this value. This mechanism is used only for compression
+ /// levels >= 4.
+ ///
+ private int _maxLazyMatch;
+
+ // Insert new strings in the hash table only if the match length is not
+ // greater than this length. This saves time but degrades compression.
+ // max_insert_length is used only for compression levels <= 3.
+
+ ///
+ /// The compression level (1..9)
+ ///
+ private CompressionLevel level;
+
+ ///
+ /// The favor or force Huffman coding
+ ///
+ private CompressionStrategy strategy;
+
+ ///
+ /// Use a faster search when the previous match is longer than this
+ ///
+ private int good_match;
+
+ ///
+ /// Stop searching when current match exceeds this
+ ///
+ private int nice_match;
+
+ ///
+ /// literal and length tree
+ ///
+ private short[] dyn_ltree;
+
+ ///
+ /// The distance tree
+ ///
+ private short[] dyn_dtree;
+
+ ///
+ /// The Huffman tree for bit lengths
+ ///
+ private short[] bl_tree;
+
+ ///
+ /// The desc for literal tree
+ ///
+ private Tree l_desc = new Tree();
+
+ ///
+ /// The desc for distance tree
+ ///
+ private Tree d_desc = new Tree();
+
+ ///
+ /// The desc for bit length tree
+ ///
+ private Tree bl_desc = new Tree();
+
+ ///
+ /// index for literals or lengths
+ ///
+ private int l_buf;
+
+ ///
+ /// Size of match buffer for literals/lengths. There are 4 reasons for
+ /// limiting lit_bufsize to 64K:
+ /// - frequencies can be kept in 16 bit counters
+ /// - if compression is not successful for the first block, all input
+ /// data is still in the window so we can still emit a stored block even
+ /// when input comes from standard input. (This can also be done for
+ /// all blocks if lit_bufsize is not greater than 32K.)
+ /// - if compression is not successful for a file smaller than 64K, we can
+ /// even emit a stored file instead of a stored block (saving 5 bytes).
+ /// This is applicable only for zip (not gzip or zlib).
+ /// - creating new Huffman trees less frequently may not provide fast
+ /// adaptation to changes in the input data statistics. (Take for
+ /// example a binary file with poorly compressible code followed by
+ /// a highly compressible string table.) Smaller buffer sizes give
+ /// fast adaptation but have of course the overhead of transmitting
+ /// trees more frequently.
+ /// - I can't count above 4
+ ///
+ private int lit_bufsize;
+
+ ///
+ /// running index in l_buf
+ ///
+ private int last_lit;
+
+ // Buffer for distances. To simplify the code, d_buf and l_buf have
+ // the same number of elements. To use different lengths, an extra flag
+ // array would be necessary.
+
+ ///
+ /// The index of pendig_buf
+ ///
+ private int d_buf;
+
+ ///
+ /// The number of string matches in current block
+ ///
+ private int matches;
+
+ ///
+ /// The bit length of EOB code for last block
+ ///
+ private int last_eob_len;
+
+ ///
+ /// Output buffer. bits are inserted starting at the bottom (least
+ /// significant bits).
+ ///
+ private uint bi_buf;
+
+ ///
+ /// Number of valid bits in bi_buf. All bits above the last valid bit
+ /// are always zero.
+ ///
+ private int bi_valid;
+
+ ///
+ /// value of flush param for previous deflate call
+ ///
+ private FlushType last_flush;
+
+ ///
+ /// bit length of current block with optimal trees
+ ///
+ internal int opt_len;
+
+ ///
+ /// bit length of current block with static trees
+ ///
+ internal int static_len;
+
+ ///
+ /// The output still pending
+ ///
+ internal byte[] pending_buf;
+
+ ///
+ /// next pending byte to output to the stream
+ ///
+ internal int pending_out;
+
+ ///
+ /// nb of bytes in the pending buffer
+ ///
+ internal int pending;
+
+ ///
+ /// suppress zlib header and adler32
+ ///
+ internal int noheader;
+
+ ///
+ /// number of codes at each bit length for an optimal tree
+ ///
+ internal short[] bl_count = new short[MAX_BITS + 1];
+
+ ///
+ /// heap used to build the Huffman trees
+ ///
+ internal int[] heap = new int[2 * L_CODES + 1];
+
+ ///
+ /// The number of elements in the heap
+ ///
+ internal int heap_len;
+ ///
+ /// The element of largest frequency
+ ///
+ internal int heap_max;
+
+ // The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+ // The same heap array is used to build all trees.
+
+ ///
+ /// Depth of each subtree used as tie breaker for trees of equal frequency
+ ///
+ internal byte[] depth = new byte[2 * L_CODES + 1];
+
+ public Deflate()
+ {
+ dyn_ltree = new short[HEAP_SIZE * 2];
+ dyn_dtree = new short[(2 * D_CODES + 1) * 2]; // distance tree
+ bl_tree = new short[(2 * BL_CODES + 1) * 2]; // Huffman tree for bit lengths
+ }
+
+ public Deflate(CompressionLevel level)
+ : this()
+ {
+ this.deflateInit(level);
+ }
+
+ public Deflate(CompressionLevel level, bool nowrap)
+ : this()
+ {
+ this.deflateInit(level, nowrap);
+ }
+
+ // Restore the heap property by moving down the tree starting at node k,
+ // exchanging a node with the smallest of its two sons if necessary, stopping
+ // when the heap property is re-established (each father smaller than its
+ // two sons).
+ internal void pqdownheap(short[] tree, // the tree to restore
+ int k // node to move down
+ )
+ {
+ int v = heap[k];
+ int j = k << 1; // left son of k
+ while (j <= heap_len)
+ {
+ // Set j to the smallest of the two sons:
+ if (j < heap_len &&
+ smaller(tree, heap[j + 1], heap[j], depth))
+ {
+ j++;
+ }
+ // Exit if v is smaller than both sons
+ if (smaller(tree, v, heap[j], depth)) break;
+
+ // Exchange v with the smallest son
+ heap[k] = heap[j]; k = j;
+ // And continue down the tree, setting j to the left son of k
+ j <<= 1;
+ }
+ heap[k] = v;
+ }
+ internal ZLibStatus deflateInit(ZStream strm, CompressionLevel level, int bits)
+ {
+ return deflateInit2(strm, level, Z_DEFLATED, bits, DEF_MEM_LEVEL, CompressionStrategy.Z_DEFAULT_STRATEGY);
+ }
+
+ private ZLibStatus deflateInit2(ZStream strm, CompressionLevel level, int method, int windowBits, int memLevel, CompressionStrategy strategy)
+ {
+ int noheader = 0;
+ // byte[] my_version=ZLIB_VERSION;
+
+ //
+ // if (version == null || version[0] != my_version[0]
+ // || stream_size != sizeof(z_stream)) {
+ // return Z_VERSION_ERROR;
+ // }
+
+ strm.msg = null;
+
+ if (level == CompressionLevel.Z_DEFAULT_COMPRESSION) level = (CompressionLevel)6;
+
+ if (windowBits < 0)
+ { // undocumented feature: suppress zlib header
+ noheader = 1;
+ windowBits = -windowBits;
+ }
+
+ if (memLevel < 1 || memLevel > MAX_MEM_LEVEL ||
+ method != Z_DEFLATED ||
+ windowBits < 9 || windowBits > 15 || level < 0 || level > (CompressionLevel)9 ||
+ strategy < 0 || strategy > CompressionStrategy.Z_HUFFMAN_ONLY)
+ {
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+
+ this.noheader = noheader;
+ _windowBits = windowBits;
+ _windowSize = 1 << _windowBits;
+ _windowMask = _windowSize - 1;
+
+ _hashBits = memLevel + 7;
+ _hashSize = 1 << _hashBits;
+ _hashMask = _hashSize - 1;
+ _hashShift = ((_hashBits + MIN_MATCH - 1) / MIN_MATCH);
+
+ _window = new byte[_windowSize * 2];
+ _previous = new short[_windowSize];
+ _head = new short[_hashSize];
+
+ lit_bufsize = 1 << (memLevel + 6); // 16K elements by default
+
+ // We overlay pending_buf and d_buf+l_buf. This works since the average
+ // output size for (length,distance) codes is <= 24 bits.
+ pending_buf = new byte[lit_bufsize * 4];
+ _pendingBufferSize = lit_bufsize * 4;
+
+ d_buf = lit_bufsize / 2;
+ l_buf = (1 + 2) * lit_bufsize;
+
+ this.level = level;
+
+ //System.out.println("level="+level);
+
+ this.strategy = strategy;
+ this._method = (byte)method;
+
+ return deflateReset(strm);
+ }
+
+ private ZLibStatus deflateReset(ZStream strm)
+ {
+ strm.total_in = strm.total_out = 0;
+ strm.msg = null; //
+ strm.data_type = BlockType.Z_UNKNOWN;
+
+ pending = 0;
+ pending_out = 0;
+
+ if (noheader < 0)
+ {
+ noheader = 0; // was set to -1 by deflate(..., FlushType.Z_FINISH);
+ }
+ _status = (noheader != 0) ? BUSY_STATE : INIT_STATE;
+ strm.adler = Adler32.adler32(0, null, 0, 0);
+
+ last_flush = FlushType.Z_NO_FLUSH;
+
+ tr_init();
+ lm_init();
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus deflateEnd()
+ {
+ if (_status != INIT_STATE && _status != BUSY_STATE && _status != FINISH_STATE)
+ {
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+ // Deallocate in reverse order of allocations:
+ pending_buf = null;
+ _head = null;
+ _previous = null;
+ _window = null;
+ // free
+ // dstate=null;
+ return _status == BUSY_STATE ? ZLibStatus.Z_DATA_ERROR : ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus deflateParams(ZStream strm, CompressionLevel _level, CompressionStrategy _strategy)
+ {
+ ZLibStatus err = ZLibStatus.Z_OK;
+
+ if (_level == CompressionLevel.Z_DEFAULT_COMPRESSION)
+ {
+ _level = (CompressionLevel)6;
+ }
+ if (_level < 0 || _level > (CompressionLevel)9 ||
+ _strategy < 0 || _strategy > CompressionStrategy.Z_HUFFMAN_ONLY)
+ {
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+
+ if (config_table[level].Function != config_table[_level].Function &&
+ strm.total_in != 0)
+ {
+ // Flush the last buffer:
+ err = this.deflate(FlushType.Z_PARTIAL_FLUSH);
+ }
+
+ if (level != _level)
+ {
+ level = _level;
+ _maxLazyMatch = config_table[level].MaxLazy;
+ good_match = config_table[level].GoodLength;
+ nice_match = config_table[level].NiceLength;
+ _maxChainLength = config_table[level].MaxChain;
+ }
+ strategy = _strategy;
+ return err;
+ }
+
+ public ZLibStatus deflateSetDictionary(ZStream strm, byte[] dictionary, int dictLength)
+ {
+ int length = dictLength;
+ int index = 0;
+
+ if (dictionary == null || _status != INIT_STATE)
+ return ZLibStatus.Z_STREAM_ERROR;
+
+ strm.adler = Adler32.adler32(strm.adler, dictionary, 0, dictLength);
+
+ if (length < MIN_MATCH) return ZLibStatus.Z_OK;
+ if (length > _windowSize - MIN_LOOKAHEAD)
+ {
+ length = _windowSize - MIN_LOOKAHEAD;
+ index = dictLength - length; // use the tail of the dictionary
+ }
+ System.Array.Copy(dictionary, index, _window, 0, length);
+ _startInsertString = length;
+ _blockStart = length;
+
+ // Insert all strings in the hash table (except for the last two bytes).
+ // s->lookahead stays null, so s->ins_h will be recomputed at the next
+ // call of fill_window.
+
+ _insertedHashIndex = _window[0] & 0xff;
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[1] & 0xff)) & _hashMask;
+
+ for (int n = 0; n <= length - MIN_MATCH; n++)
+ {
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[(n) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+ _previous[n & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)n;
+ }
+ return ZLibStatus.Z_OK;
+ }
+
+ //public ZLibStatus deflate(ZStream strm, FlushType flush)
+ //{
+ // FlushType old_flush;
+
+ // if (flush > FlushType.Z_FINISH || flush < 0)
+ // {
+ // return ZLibStatus.Z_STREAM_ERROR;
+ // }
+
+ // if (strm.next_out == null ||
+ // (strm.next_in == null && strm.avail_in != 0) ||
+ // (_status == FINISH_STATE && flush != FlushType.Z_FINISH))
+ // {
+ // strm.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_STREAM_ERROR)];
+ // return ZLibStatus.Z_STREAM_ERROR;
+ // }
+ // if (strm.avail_out == 0)
+ // {
+ // strm.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_BUF_ERROR)];
+ // return ZLibStatus.Z_BUF_ERROR;
+ // }
+
+ // this._stream = strm; // just in case
+ // old_flush = last_flush;
+ // last_flush = flush;
+
+ // // Write the zlib header
+ // if (_status == INIT_STATE)
+ // {
+ // int header = (Z_DEFLATED + ((_windowBits - 8) << 4)) << 8;
+ // int level_flags = (((int)level - 1) & 0xff) >> 1;
+
+ // if (level_flags > 3) level_flags = 3;
+ // header |= (level_flags << 6);
+ // if (_startInsertString != 0) header |= PRESET_DICT;
+ // header += 31 - (header % 31);
+
+ // _status = BUSY_STATE;
+ // putShortMSB(header);
+
+
+ // // Save the adler32 of the preset dictionary:
+ // if (_startInsertString != 0)
+ // {
+ // putShortMSB((int)(strm.adler >> 16));
+ // putShortMSB((int)(strm.adler & 0xffff));
+ // }
+ // strm.adler = Adler32.adler32(0, null, 0, 0);
+ // }
+
+ // // Flush as much pending output as possible
+ // if (pending != 0)
+ // {
+ // strm.flush_pending();
+ // if (strm.avail_out == 0)
+ // {
+ // //System.out.println(" avail_out==0");
+ // // Since avail_out is 0, deflate will be called again with
+ // // more output space, but possibly with both pending and
+ // // avail_in equal to zero. There won't be anything to do,
+ // // but this is not an error situation so make sure we
+ // // return OK instead of BUF_ERROR at next call of deflate:
+ // last_flush = (FlushType)(-1);
+ // return ZLibStatus.Z_OK;
+ // }
+
+ // // Make sure there is something to do and avoid duplicate consecutive
+ // // flushes. For repeated and useless calls with FlushType.Z_FINISH, we keep
+ // // returning ZLibStatus.Z_STREAM_END instead of Z_BUFF_ERROR.
+ // }
+ // else if (strm.avail_in == 0 && flush <= old_flush &&
+ // flush != FlushType.Z_FINISH)
+ // {
+ // strm.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_BUF_ERROR)];
+ // return ZLibStatus.Z_BUF_ERROR;
+ // }
+
+ // // User must not provide more input after the first FINISH:
+ // if (_status == FINISH_STATE && strm.avail_in != 0)
+ // {
+ // strm.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_BUF_ERROR)];
+ // return ZLibStatus.Z_BUF_ERROR;
+ // }
+
+ // // Start a new block or continue the current one.
+ // if (strm.avail_in != 0 || _validBytesAhead != 0 ||
+ // (flush != FlushType.Z_NO_FLUSH && _status != FINISH_STATE))
+ // {
+ // int bstate = -1;
+ // switch (config_table[level].Function)
+ // {
+ // case DefalteFlavor.STORED:
+ // bstate = deflate_stored(flush);
+ // break;
+ // case DefalteFlavor.FAST:
+ // bstate = deflate_fast(flush);
+ // break;
+ // case DefalteFlavor.SLOW:
+ // bstate = deflate_slow(flush);
+ // break;
+ // default:
+ // break;
+ // }
+
+ // if (bstate == FinishStarted || bstate == FinishDone)
+ // {
+ // _status = FINISH_STATE;
+ // }
+ // if (bstate == NeedMore || bstate == FinishStarted)
+ // {
+ // if (strm.avail_out == 0)
+ // {
+ // last_flush = (FlushType)(-1); // avoid BUF_ERROR next call, see above
+ // }
+ // return ZLibStatus.Z_OK;
+ // // If flush != FlushType.Z_NO_FLUSH && avail_out == 0, the next call
+ // // of deflate should use the same flush parameter to make sure
+ // // that the flush is complete. So we don't have to output an
+ // // empty block here, this will be done at next call. This also
+ // // ensures that for a very small output buffer, we emit at most
+ // // one empty block.
+ // }
+
+ // if (bstate == BlockDone)
+ // {
+ // if (flush == FlushType.Z_PARTIAL_FLUSH)
+ // {
+ // _tr_align();
+ // }
+ // else
+ // { // FULL_FLUSH or SYNC_FLUSH
+ // _tr_stored_block(0, 0, false);
+ // // For a full flush, this empty block will be recognized
+ // // as a special marker by inflate_sync().
+ // if (flush == FlushType.Z_FULL_FLUSH)
+ // {
+ // //state.head[s.hash_size-1]=0;
+ // for (int i = 0; i < _hashSize/*-1*/; i++) // forget history
+ // _head[i] = 0;
+ // }
+ // }
+ // strm.flush_pending();
+ // if (strm.avail_out == 0)
+ // {
+ // last_flush = (FlushType)(-1); // avoid BUF_ERROR at next call, see above
+ // return ZLibStatus.Z_OK;
+ // }
+ // }
+ // }
+
+ // if (flush != FlushType.Z_FINISH) return ZLibStatus.Z_OK;
+ // if (noheader != 0) return ZLibStatus.Z_STREAM_END;
+
+ // // Write the zlib trailer (adler32)
+ // putShortMSB((int)(strm.adler >> 16));
+ // putShortMSB((int)(strm.adler & 0xffff));
+ // strm.flush_pending();
+
+ // // If avail_out is zero, the application will call deflate again
+ // // to flush the rest.
+ // noheader = -1; // write the trailer only once!
+ // return pending != 0 ? ZLibStatus.Z_OK : ZLibStatus.Z_STREAM_END;
+ //}
+
+ private void lm_init()
+ {
+ _windowActualSize = 2 * _windowSize;
+
+ _head[_hashSize - 1] = 0;
+ for (int i = 0; i < _hashSize - 1; i++)
+ {
+ _head[i] = 0;
+ }
+
+ // Set the default configuration parameters:
+ _maxLazyMatch = Deflate.config_table[level].MaxLazy;
+ good_match = Deflate.config_table[level].GoodLength;
+ nice_match = Deflate.config_table[level].NiceLength;
+ _maxChainLength = Deflate.config_table[level].MaxChain;
+
+ _startInsertString = 0;
+ _blockStart = 0;
+ _validBytesAhead = 0;
+ _matchLength = _previousLength = MIN_MATCH - 1;
+ _matchAvailable = false;
+ _insertedHashIndex = 0;
+ }
+
+ // Initialize the tree data structures for a new zlib stream.
+ private void tr_init()
+ {
+
+ l_desc.Init(dyn_ltree, Deflate.static_l_desc);
+
+ d_desc.Init(dyn_dtree, Deflate.static_d_desc);
+
+ bl_desc.Init(bl_tree, Deflate.static_bl_desc);
+
+
+ bi_buf = 0;
+ bi_valid = 0;
+ last_eob_len = 8; // enough lookahead for inflate
+
+ // Initialize the first block of the first file:
+ init_block();
+ }
+
+ private void init_block()
+ {
+ // Initialize the trees.
+ for (int i = 0; i < L_CODES; i++) dyn_ltree[i * 2] = 0;
+ for (int i = 0; i < D_CODES; i++) dyn_dtree[i * 2] = 0;
+ for (int i = 0; i < BL_CODES; i++) bl_tree[i * 2] = 0;
+
+ dyn_ltree[END_BLOCK * 2] = 1;
+ opt_len = static_len = 0;
+ last_lit = matches = 0;
+ }
+
+ private static bool smaller(short[] tree, int n, int m, byte[] depth)
+ {
+ short tn2 = tree[n * 2];
+ short tm2 = tree[m * 2];
+ return (tn2 < tm2 ||
+ (tn2 == tm2 && depth[n] <= depth[m]));
+ }
+
+ // Scan a literal or distance tree to determine the frequencies of the codes
+ // in the bit length tree.
+ private void scan_tree(short[] tree,// the tree to be scanned
+ int max_code // and its largest code of non zero frequency
+ )
+ {
+ int n; // iterates over all tree elements
+ int prevlen = -1; // last emitted length
+ int curlen; // length of current code
+ int nextlen = tree[0 * 2 + 1]; // length of next code
+ int count = 0; // repeat count of the current code
+ int max_count = 7; // max repeat count
+ int min_count = 4; // min repeat count
+
+ if (nextlen == 0) { max_count = 138; min_count = 3; }
+ tree[(max_code + 1) * 2 + 1] = -1; // guard
+
+ for (n = 0; n <= max_code; n++)
+ {
+ curlen = nextlen; nextlen = tree[(n + 1) * 2 + 1];
+ if (++count < max_count && curlen == nextlen)
+ {
+ continue;
+ }
+ else if (count < min_count)
+ {
+ bl_tree[curlen * 2] += (short)count;
+ }
+ else if (curlen != 0)
+ {
+ if (curlen != prevlen) bl_tree[curlen * 2]++;
+ bl_tree[REP_3_6 * 2]++;
+ }
+ else if (count <= 10)
+ {
+ bl_tree[REPZ_3_10 * 2]++;
+ }
+ else
+ {
+ bl_tree[REPZ_11_138 * 2]++;
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0)
+ {
+ max_count = 138; min_count = 3;
+ }
+ else if (curlen == nextlen)
+ {
+ max_count = 6; min_count = 3;
+ }
+ else
+ {
+ max_count = 7; min_count = 4;
+ }
+ }
+ }
+
+ // Construct the Huffman tree for the bit lengths and return the index in
+ // bl_order of the last bit length code to send.
+ private int build_bl_tree()
+ {
+ int max_blindex; // index of last bit length code of non zero freq
+
+ // Determine the bit length frequencies for literal and distance trees
+ scan_tree(dyn_ltree, l_desc.LargestCode);
+ scan_tree(dyn_dtree, d_desc.LargestCode);
+
+ // Build the bit length tree:
+ bl_desc.BuildTree(this);
+ // opt_len now includes the length of the tree representations, except
+ // the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
+
+ // Determine the number of bit length codes to send. The pkzip format
+ // requires that at least 4 bit length codes be sent. (appnote.txt says
+ // 3 but the actual value used is 4.)
+ for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--)
+ {
+ if (bl_tree[Deflate.bl_order[max_blindex] * 2 + 1] != 0) break;
+ }
+ // Update opt_len to include the bit length tree and counts
+ opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4;
+
+ return max_blindex;
+ }
+
+
+ // Send the header for a block using dynamic Huffman trees: the counts, the
+ // lengths of the bit length codes, the literal tree and the distance tree.
+ // IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
+ private void send_all_trees(int lcodes, int dcodes, int blcodes)
+ {
+ int rank; // index in bl_order
+
+ send_bits(lcodes - 257, 5); // not +255 as stated in appnote.txt
+ send_bits(dcodes - 1, 5);
+ send_bits(blcodes - 4, 4); // not -3 as stated in appnote.txt
+ for (rank = 0; rank < blcodes; rank++)
+ {
+ send_bits(bl_tree[Deflate.bl_order[rank] * 2 + 1], 3);
+ }
+ send_tree(dyn_ltree, lcodes - 1); // literal tree
+ send_tree(dyn_dtree, dcodes - 1); // distance tree
+ }
+
+ // Send a literal or distance tree in compressed form, using the codes in
+ // bl_tree.
+ private void send_tree(short[] tree,// the tree to be sent
+ int max_code // and its largest code of non zero frequency
+ )
+ {
+ int n; // iterates over all tree elements
+ int prevlen = -1; // last emitted length
+ int curlen; // length of current code
+ int nextlen = tree[0 * 2 + 1]; // length of next code
+ int count = 0; // repeat count of the current code
+ int max_count = 7; // max repeat count
+ int min_count = 4; // min repeat count
+
+ if (nextlen == 0) { max_count = 138; min_count = 3; }
+
+ for (n = 0; n <= max_code; n++)
+ {
+ curlen = nextlen; nextlen = tree[(n + 1) * 2 + 1];
+ if (++count < max_count && curlen == nextlen)
+ {
+ continue;
+ }
+ else if (count < min_count)
+ {
+ do { send_code(curlen, bl_tree); } while (--count != 0);
+ }
+ else if (curlen != 0)
+ {
+ if (curlen != prevlen)
+ {
+ send_code(curlen, bl_tree); count--;
+ }
+ send_code(REP_3_6, bl_tree);
+ send_bits(count - 3, 2);
+ }
+ else if (count <= 10)
+ {
+ send_code(REPZ_3_10, bl_tree);
+ send_bits(count - 3, 3);
+ }
+ else
+ {
+ send_code(REPZ_11_138, bl_tree);
+ send_bits(count - 11, 7);
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0)
+ {
+ max_count = 138; min_count = 3;
+ }
+ else if (curlen == nextlen)
+ {
+ max_count = 6; min_count = 3;
+ }
+ else
+ {
+ max_count = 7; min_count = 4;
+ }
+ }
+ }
+
+ // Output a byte on the stream.
+ // IN assertion: there is enough room in pending_buf.
+ private void put_byte(byte[] p, int start, int len)
+ {
+ System.Array.Copy(p, start, pending_buf, pending, len);
+ pending += len;
+ }
+
+ private void put_byte(byte c)
+ {
+ pending_buf[pending++] = c;
+ }
+ private void put_short(int w)
+ {
+ pending_buf[pending++] = (byte)(w/*&0xff*/);
+ pending_buf[pending++] = (byte)(w >> 8);
+ }
+ private void putShortMSB(int b)
+ {
+ pending_buf[pending++] = (byte)(b >> 8);
+ pending_buf[pending++] = (byte)(b/*&0xff*/);
+ }
+
+ private void send_code(int c, short[] tree)
+ {
+ int c2 = c * 2;
+ send_bits((tree[c2] & 0xffff), (tree[c2 + 1] & 0xffff));
+ }
+
+ private void send_bits(int val, int length)
+ {
+ if (bi_valid > Buf_size - length)
+ {
+ bi_buf |= (uint)(val << bi_valid);
+ pending_buf[pending++] = (byte)(bi_buf/*&0xff*/);
+ pending_buf[pending++] = (byte)(bi_buf >> 8);
+ bi_buf = ((uint)val) >> (Buf_size - bi_valid);
+ bi_valid += length - Buf_size;
+ }
+ else
+ {
+ bi_buf |= (uint)(val << bi_valid);
+ bi_valid += length;
+ }
+ // int len = length;
+ // if (bi_valid > (int)Buf_size - len) {
+ // int val = value;
+ // // bi_buf |= (val << bi_valid);
+ // bi_buf = (short)((ushort)bi_buf | (ushort)((val << bi_valid)&0xffff));
+ // put_short(bi_buf);
+ // bi_buf = (short)(((uint)val) >> (Buf_size - bi_valid));
+ // bi_valid += len - Buf_size;
+ // } else {
+ // // bi_buf |= (value) << bi_valid;
+ // bi_buf = (short)((ushort)bi_buf | (ushort)(((value) << bi_valid)&0xffff));
+ // bi_valid += len;
+ // }
+ }
+
+ // Send one empty static block to give enough lookahead for inflate.
+ // This takes 10 bits, of which 7 may remain in the bit buffer.
+ // The current inflate code requires 9 bits of lookahead. If the
+ // last two codes for the previous block (real code plus EOB) were coded
+ // on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
+ // the last real code. In this case we send two empty static blocks instead
+ // of one. (There are no problems if the previous block is stored or fixed.)
+ // To simplify the code, we assume the worst case of last real code encoded
+ // on one bit only.
+ private void _tr_align()
+ {
+ send_bits(STATIC_TREES << 1, 3);
+ send_code(END_BLOCK, Deflate.static_ltree);
+
+ bi_flush();
+
+ // Of the 10 bits for the empty block, we have already sent
+ // (10 - bi_valid) bits. The lookahead for the last real code (before
+ // the EOB of the previous block) was thus at least one plus the length
+ // of the EOB plus what we have just sent of the empty static block.
+ if (1 + last_eob_len + 10 - bi_valid < 9)
+ {
+ send_bits(STATIC_TREES << 1, 3);
+ send_code(END_BLOCK, Deflate.static_ltree);
+ bi_flush();
+ }
+ last_eob_len = 7;
+ }
+
+
+ // Save the match info and tally the frequency counts. Return true if
+ // the current block must be flushed.
+ private bool _tr_tally(int dist, // distance of matched string
+ int lc // match length-MIN_MATCH or unmatched char (if dist==0)
+ )
+ {
+
+ pending_buf[d_buf + last_lit * 2] = (byte)(dist >> 8);
+ pending_buf[d_buf + last_lit * 2 + 1] = (byte)dist;
+
+ pending_buf[l_buf + last_lit] = (byte)lc; last_lit++;
+
+ if (dist == 0)
+ {
+ // lc is the unmatched char
+ dyn_ltree[lc * 2]++;
+ }
+ else
+ {
+ matches++;
+ // Here, lc is the match length - MIN_MATCH
+ dist--; // dist = match distance - 1
+ dyn_ltree[(Deflate._length_code[lc] + LITERALS + 1) * 2]++;
+ dyn_dtree[Tree.DistanceCode(dist) * 2]++;
+ }
+
+ if ((last_lit & 0x1fff) == 0 && level > (CompressionLevel)2)
+ {
+ // Compute an upper bound for the compressed length
+ int out_length = last_lit * 8;
+ int in_length = _startInsertString - _blockStart;
+ int dcode;
+ for (dcode = 0; dcode < D_CODES; dcode++)
+ {
+ out_length += (int)((int)dyn_dtree[dcode * 2] *
+ (5L + Deflate.extra_dbits[dcode]));
+ }
+ out_length >>= 3;
+ if ((matches < (last_lit / 2)) && out_length < in_length / 2) return true;
+ }
+
+ return (last_lit == lit_bufsize - 1);
+ // We avoid equality with lit_bufsize because of wraparound at 64K
+ // on 16 bit machines and because stored blocks are restricted to
+ // 64K-1 bytes.
+ }
+
+ // Send the block data compressed using the given Huffman trees
+ private void compress_block(short[] ltree, short[] dtree)
+ {
+ int dist; // distance of matched string
+ int lc; // match length or unmatched char (if dist == 0)
+ int lx = 0; // running index in l_buf
+ int code; // the code to send
+ int extra; // number of extra bits to send
+
+ if (last_lit != 0)
+ {
+ do
+ {
+ dist = ((pending_buf[d_buf + lx * 2] << 8) & 0xff00) |
+ (pending_buf[d_buf + lx * 2 + 1] & 0xff);
+ lc = (pending_buf[l_buf + lx]) & 0xff; lx++;
+
+ if (dist == 0)
+ {
+ send_code(lc, ltree); // send a literal byte
+ }
+ else
+ {
+ // Here, lc is the match length - MIN_MATCH
+ code = Deflate._length_code[lc];
+
+ send_code(code + LITERALS + 1, ltree); // send the length code
+ extra = Deflate.extra_lbits[code];
+ if (extra != 0)
+ {
+ lc -= Deflate.base_length[code];
+ send_bits(lc, extra); // send the extra length bits
+ }
+ dist--; // dist is now the match distance - 1
+ code = Tree.DistanceCode(dist);
+
+ send_code(code, dtree); // send the distance code
+ extra = Deflate.extra_dbits[code];
+ if (extra != 0)
+ {
+ dist -= Deflate.base_dist[code];
+ send_bits(dist, extra); // send the extra distance bits
+ }
+ } // literal or match pair ?
+
+ // Check that the overlay between pending_buf and d_buf+l_buf is ok:
+ }
+ while (lx < last_lit);
+ }
+
+ send_code(END_BLOCK, ltree);
+ last_eob_len = ltree[END_BLOCK * 2 + 1];
+ }
+
+ // Set the data type to ASCII or BINARY, using a crude approximation:
+ // binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise.
+ // IN assertion: the fields freq of dyn_ltree are set and the total of all
+ // frequencies does not exceed 64K (to fit in an int on 16 bit machines).
+ private void set_data_type()
+ {
+ int n = 0;
+ int ascii_freq = 0;
+ int bin_freq = 0;
+ while (n < 7) { bin_freq += dyn_ltree[n * 2]; n++; }
+ while (n < 128) { ascii_freq += dyn_ltree[n * 2]; n++; }
+ while (n < LITERALS) { bin_freq += dyn_ltree[n * 2]; n++; }
+ this._dataType = (bin_freq > (ascii_freq >> 2) ? BlockType.Z_BINARY : BlockType.Z_ASCII);
+ }
+
+ // Flush the bit buffer, keeping at most 7 bits in it.
+ private void bi_flush()
+ {
+ if (bi_valid == 16)
+ {
+ pending_buf[pending++] = (byte)(bi_buf/*&0xff*/);
+ pending_buf[pending++] = (byte)(bi_buf >> 8);
+ bi_buf = 0;
+ bi_valid = 0;
+ }
+ else if (bi_valid >= 8)
+ {
+ pending_buf[pending++] = (byte)(bi_buf);
+ bi_buf >>= 8;
+ bi_buf &= 0x00ff;
+ bi_valid -= 8;
+ }
+ }
+
+ // Flush the bit buffer and align the output on a byte boundary
+ private void bi_windup()
+ {
+ if (bi_valid > 8)
+ {
+ pending_buf[pending++] = (byte)(bi_buf);
+ pending_buf[pending++] = (byte)(bi_buf >> 8);
+ }
+ else if (bi_valid > 0)
+ {
+ pending_buf[pending++] = (byte)(bi_buf);
+ }
+ bi_buf = 0;
+ bi_valid = 0;
+ }
+
+ // Copy a stored block, storing first the length and its
+ // one's complement if requested.
+ private void copy_block(int buf, // the input data
+ int len, // its length
+ bool header // true if block header must be written
+ )
+ {
+ //int index=0;
+ bi_windup(); // align on byte boundary
+ last_eob_len = 8; // enough lookahead for inflate
+
+ if (header)
+ {
+ put_short((short)len);
+ put_short((short)~len);
+ }
+
+ // while(len--!=0) {
+ // put_byte(window[buf+index]);
+ // index++;
+ // }
+ put_byte(_window, buf, len);
+ }
+
+ private void flush_block_only(bool eof)
+ {
+ _tr_flush_block(_blockStart >= 0 ? _blockStart : -1,
+ _startInsertString - _blockStart,
+ eof);
+ _blockStart = _startInsertString;
+ this.flush_pending();
+ }
+
+ // Copy without compression as much as possible from the input stream, return
+ // the current block state.
+ // This function does not insert new strings in the dictionary since
+ // uncompressible data is probably not useful. This function is used
+ // only for the level=0 compression option.
+ // NOTE: this function should be optimized to avoid extra copying from
+ // window to pending_buf.
+ private int deflate_stored(FlushType flush)
+ {
+ // Stored blocks are limited to 0xffff bytes, pending_buf is limited
+ // to pending_buf_size, and each stored block has a 5 byte header:
+
+ int max_block_size = 0xffff;
+ int max_start;
+
+ if (max_block_size > _pendingBufferSize - 5)
+ {
+ max_block_size = _pendingBufferSize - 5;
+ }
+
+ // Copy as much as possible from input to output:
+ while (true)
+ {
+ // Fill the window as much as possible:
+ if (_validBytesAhead <= 1)
+ {
+ fill_window();
+ if (_validBytesAhead == 0 && flush == FlushType.Z_NO_FLUSH) return NeedMore;
+ if (_validBytesAhead == 0) break; // flush the current block
+ }
+
+ _startInsertString += _validBytesAhead;
+ _validBytesAhead = 0;
+
+ // Emit a stored block if pending_buf will be full:
+ max_start = _blockStart + max_block_size;
+ if (_startInsertString == 0 || _startInsertString >= max_start)
+ {
+ // strstart == 0 is possible when wraparound on 16-bit machine
+ _validBytesAhead = (int)(_startInsertString - max_start);
+ _startInsertString = (int)max_start;
+
+ flush_block_only(false);
+ if (base.avail_out == 0) return NeedMore;
+
+ }
+
+ // Flush if we may have to slide, otherwise block_start may become
+ // negative and the data will be gone:
+ if (_startInsertString - _blockStart >= _windowSize - MIN_LOOKAHEAD)
+ {
+ flush_block_only(false);
+ if (base.avail_out == 0) return NeedMore;
+ }
+ }
+
+ flush_block_only(flush == FlushType.Z_FINISH);
+ if (base.avail_out == 0)
+ return (flush == FlushType.Z_FINISH) ? FinishStarted : NeedMore;
+
+ return flush == FlushType.Z_FINISH ? FinishDone : BlockDone;
+ }
+
+ // Send a stored block
+ private void _tr_stored_block(int buf, // input block
+ int stored_len, // length of input block
+ bool eof // true if this is the last block for a file
+ )
+ {
+ send_bits((STORED_BLOCK << 1) + (eof ? 1 : 0), 3); // send block type
+ copy_block(buf, stored_len, true); // with header
+ }
+
+ // Determine the best encoding for the current block: dynamic trees, static
+ // trees or store, and output the encoded block to the zip file.
+ private void _tr_flush_block(int buf, // input block, or NULL if too old
+ int stored_len, // length of input block
+ bool eof // true if this is the last block for a file
+ )
+ {
+ int opt_lenb, static_lenb;// opt_len and static_len in bytes
+ int max_blindex = 0; // index of last bit length code of non zero freq
+
+ // Build the Huffman trees unless a stored block is forced
+ if (level > 0)
+ {
+ // Check if the file is ascii or binary
+ if (this._dataType == BlockType.Z_UNKNOWN) set_data_type();
+
+ // Construct the literal and distance trees
+ l_desc.BuildTree(this);
+
+ d_desc.BuildTree(this);
+
+ // At this point, opt_len and static_len are the total bit lengths of
+ // the compressed block data, excluding the tree representations.
+
+ // Build the bit length tree for the above two trees, and get the index
+ // in bl_order of the last bit length code to send.
+ max_blindex = build_bl_tree();
+
+ // Determine the best encoding. Compute first the block length in bytes
+ opt_lenb = (opt_len + 3 + 7) >> 3;
+ static_lenb = (static_len + 3 + 7) >> 3;
+
+ if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
+ }
+ else
+ {
+ opt_lenb = static_lenb = stored_len + 5; // force a stored block
+ }
+
+ if (stored_len + 4 <= opt_lenb && buf != -1)
+ {
+ // 4: two words for the lengths
+ // The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
+ // Otherwise we can't have processed more than WSIZE input bytes since
+ // the last block flush, because compression would have been
+ // successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
+ // transform a block into a stored block.
+ _tr_stored_block(buf, stored_len, eof);
+ }
+ else if (static_lenb == opt_lenb)
+ {
+ send_bits((STATIC_TREES << 1) + (eof ? 1 : 0), 3);
+ compress_block(Deflate.static_ltree, Deflate.static_dtree);
+ }
+ else
+ {
+ send_bits((DYN_TREES << 1) + (eof ? 1 : 0), 3);
+ send_all_trees(l_desc.LargestCode + 1, d_desc.LargestCode + 1, max_blindex + 1);
+ compress_block(dyn_ltree, dyn_dtree);
+ }
+
+ // The above check is made mod 2^32, for files larger than 512 MB
+ // and uLong implemented on 32 bits.
+
+ init_block();
+
+ if (eof)
+ {
+ bi_windup();
+ }
+ }
+
+ // Fill the window when the lookahead becomes insufficient.
+ // Updates strstart and lookahead.
+ //
+ // IN assertion: lookahead < MIN_LOOKAHEAD
+ // OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
+ // At least one byte has been read, or avail_in == 0; reads are
+ // performed for at least two bytes (required for the zip translate_eol
+ // option -- not supported here).
+ private void fill_window()
+ {
+ int n, m;
+ int p;
+ int more; // Amount of free space at the end of the window.
+
+ do
+ {
+ more = (_windowActualSize - _validBytesAhead - _startInsertString);
+
+ // Deal with !@#$% 64K limit:
+ if (more == 0 && _startInsertString == 0 && _validBytesAhead == 0)
+ {
+ more = _windowSize;
+ }
+ else if (more == -1)
+ {
+ // Very unlikely, but possible on 16 bit machine if strstart == 0
+ // and lookahead == 1 (input done one byte at time)
+ more--;
+
+ // If the window is almost full and there is insufficient lookahead,
+ // move the upper half to the lower one to make room in the upper half.
+ }
+ else if (_startInsertString >= _windowSize + _windowSize - MIN_LOOKAHEAD)
+ {
+ System.Array.Copy(_window, _windowSize, _window, 0, _windowSize);
+ _startMatchString -= _windowSize;
+ _startInsertString -= _windowSize; // we now have strstart >= MAX_DIST
+ _blockStart -= _windowSize;
+
+ // Slide the hash table (could be avoided with 32 bit values
+ // at the expense of memory usage). We slide even when level == 0
+ // to keep the hash table consistent if we switch back to level > 0
+ // later. (Using level 0 permanently is not an optimal usage of
+ // zlib, so we don't care about this pathological case.)
+
+ n = _hashSize;
+ p = n;
+ do
+ {
+ m = (_head[--p] & 0xffff);
+ _head[p] = (short)(m >= _windowSize ? (m - _windowSize) : 0);
+ }
+ while (--n != 0);
+
+ n = _windowSize;
+ p = n;
+ do
+ {
+ m = (_previous[--p] & 0xffff);
+ _previous[p] = (short)(m >= _windowSize ? (m - _windowSize) : 0);
+ // If n is not on any hash chain, prev[n] is garbage but
+ // its value will never be used.
+ }
+ while (--n != 0);
+ more += _windowSize;
+ }
+
+ if (base.avail_in == 0) return;
+
+ // If there was no sliding:
+ // strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
+ // more == window_size - lookahead - strstart
+ // => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
+ // => more >= window_size - 2*WSIZE + 2
+ // In the BIG_MEM or MMAP case (not yet supported),
+ // window_size == input_size + MIN_LOOKAHEAD &&
+ // strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
+ // Otherwise, window_size == 2*WSIZE so more >= 2.
+ // If there was sliding, more >= WSIZE. So in all cases, more >= 2.
+
+ n = this.read_buf(_window, _startInsertString + _validBytesAhead, more);
+ _validBytesAhead += n;
+
+ // Initialize the hash value now that we have some input:
+ if (_validBytesAhead >= MIN_MATCH)
+ {
+ _insertedHashIndex = _window[_startInsertString] & 0xff;
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[_startInsertString + 1] & 0xff)) & _hashMask;
+ }
+ // If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
+ // but this is not important since only literal bytes will be emitted.
+ }
+ while (_validBytesAhead < MIN_LOOKAHEAD && base.avail_in != 0);
+ }
+
+ // Compress as much as possible from the input stream, return the current
+ // block state.
+ // This function does not perform lazy evaluation of matches and inserts
+ // new strings in the dictionary only for unmatched strings or for short
+ // matches. It is used only for the fast compression options.
+ private int deflate_fast(FlushType flush)
+ {
+ // short hash_head = 0; // head of the hash chain
+ int hash_head = 0; // head of the hash chain
+ bool bflush; // set if current block must be flushed
+
+ while (true)
+ {
+ // Make sure that we always have enough lookahead, except
+ // at the end of the input file. We need MAX_MATCH bytes
+ // for the next match, plus MIN_MATCH bytes to insert the
+ // string following the next match.
+ if (_validBytesAhead < MIN_LOOKAHEAD)
+ {
+ fill_window();
+ if (_validBytesAhead < MIN_LOOKAHEAD && flush == FlushType.Z_NO_FLUSH)
+ {
+ return NeedMore;
+ }
+ if (_validBytesAhead == 0) break; // flush the current block
+ }
+
+ // Insert the string window[strstart .. strstart+2] in the
+ // dictionary, and set hash_head to the head of the hash chain:
+ if (_validBytesAhead >= MIN_MATCH)
+ {
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[(_startInsertString) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+
+ // prev[strstart&w_mask]=hash_head=head[ins_h];
+ hash_head = (_head[_insertedHashIndex] & 0xffff);
+ _previous[_startInsertString & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)_startInsertString;
+ }
+
+ // Find the longest match, discarding those <= prev_length.
+ // At this point we have always match_length < MIN_MATCH
+
+ if (hash_head != 0L &&
+ ((_startInsertString - hash_head) & 0xffff) <= _windowSize - MIN_LOOKAHEAD
+ )
+ {
+ // To simplify the code, we prevent matches with the string
+ // of window index 0 (in particular we have to avoid a match
+ // of the string with itself at the start of the input file).
+ if (strategy != CompressionStrategy.Z_HUFFMAN_ONLY)
+ {
+ _matchLength = longest_match(hash_head);
+ }
+ // longest_match() sets match_start
+ }
+ if (_matchLength >= MIN_MATCH)
+ {
+ // check_match(strstart, match_start, match_length);
+
+ bflush = _tr_tally(_startInsertString - _startMatchString, _matchLength - MIN_MATCH);
+
+ _validBytesAhead -= _matchLength;
+
+ // Insert new strings in the hash table only if the match length
+ // is not too large. This saves time but degrades compression.
+ if (_matchLength <= _maxLazyMatch &&
+ _validBytesAhead >= MIN_MATCH)
+ {
+ _matchLength--; // string at strstart already in hash table
+ do
+ {
+ _startInsertString++;
+
+ _insertedHashIndex = ((_insertedHashIndex << _hashShift) ^ (_window[(_startInsertString) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+ // prev[strstart&w_mask]=hash_head=head[ins_h];
+ hash_head = (_head[_insertedHashIndex] & 0xffff);
+ _previous[_startInsertString & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)_startInsertString;
+
+ // strstart never exceeds WSIZE-MAX_MATCH, so there are
+ // always MIN_MATCH bytes ahead.
+ }
+ while (--_matchLength != 0);
+ _startInsertString++;
+ }
+ else
+ {
+ _startInsertString += _matchLength;
+ _matchLength = 0;
+ _insertedHashIndex = _window[_startInsertString] & 0xff;
+
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[_startInsertString + 1] & 0xff)) & _hashMask;
+ // If lookahead < MIN_MATCH, ins_h is garbage, but it does not
+ // matter since it will be recomputed at next deflate call.
+ }
+ }
+ else
+ {
+ // No match, output a literal byte
+
+ bflush = _tr_tally(0, _window[_startInsertString] & 0xff);
+ _validBytesAhead--;
+ _startInsertString++;
+ }
+ if (bflush)
+ {
+
+ flush_block_only(false);
+ if (base.avail_out == 0) return NeedMore;
+ }
+ }
+
+ flush_block_only(flush == FlushType.Z_FINISH);
+ if (base.avail_out == 0)
+ {
+ if (flush == FlushType.Z_FINISH) return FinishStarted;
+ else return NeedMore;
+ }
+ return flush == FlushType.Z_FINISH ? FinishDone : BlockDone;
+ }
+
+ // Same as above, but achieves better compression. We use a lazy
+ // evaluation for matches: a match is finally adopted only if there is
+ // no better match at the next window position.
+ private int deflate_slow(FlushType flush)
+ {
+ // short hash_head = 0; // head of hash chain
+ int hash_head = 0; // head of hash chain
+ bool bflush; // set if current block must be flushed
+
+ // Process the input block.
+ while (true)
+ {
+ // Make sure that we always have enough lookahead, except
+ // at the end of the input file. We need MAX_MATCH bytes
+ // for the next match, plus MIN_MATCH bytes to insert the
+ // string following the next match.
+
+ if (_validBytesAhead < MIN_LOOKAHEAD)
+ {
+ fill_window();
+ if (_validBytesAhead < MIN_LOOKAHEAD && flush == FlushType.Z_NO_FLUSH)
+ {
+ return NeedMore;
+ }
+ if (_validBytesAhead == 0) break; // flush the current block
+ }
+
+ // Insert the string window[strstart .. strstart+2] in the
+ // dictionary, and set hash_head to the head of the hash chain:
+
+ if (_validBytesAhead >= MIN_MATCH)
+ {
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[(_startInsertString) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+ // prev[strstart&w_mask]=hash_head=head[ins_h];
+ hash_head = (_head[_insertedHashIndex] & 0xffff);
+ _previous[_startInsertString & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)_startInsertString;
+ }
+
+ // Find the longest match, discarding those <= prev_length.
+ _previousLength = _matchLength; _previousMatch = _startMatchString;
+ _matchLength = MIN_MATCH - 1;
+
+ if (hash_head != 0 && _previousLength < _maxLazyMatch &&
+ ((_startInsertString - hash_head) & 0xffff) <= _windowSize - MIN_LOOKAHEAD
+ )
+ {
+ // To simplify the code, we prevent matches with the string
+ // of window index 0 (in particular we have to avoid a match
+ // of the string with itself at the start of the input file).
+
+ if (strategy != CompressionStrategy.Z_HUFFMAN_ONLY)
+ {
+ _matchLength = longest_match(hash_head);
+ }
+ // longest_match() sets match_start
+
+ if (_matchLength <= 5 && (strategy == CompressionStrategy.Z_FILTERED ||
+ (_matchLength == MIN_MATCH &&
+ _startInsertString - _startMatchString > 4096)))
+ {
+
+ // If prev_match is also MIN_MATCH, match_start is garbage
+ // but we will ignore the current match anyway.
+ _matchLength = MIN_MATCH - 1;
+ }
+ }
+
+ // If there was a match at the previous step and the current
+ // match is not better, output the previous match:
+ if (_previousLength >= MIN_MATCH && _matchLength <= _previousLength)
+ {
+ int max_insert = _startInsertString + _validBytesAhead - MIN_MATCH;
+ // Do not insert strings in hash table beyond this.
+
+ // check_match(strstart-1, prev_match, prev_length);
+
+ bflush = _tr_tally(_startInsertString - 1 - _previousMatch, _previousLength - MIN_MATCH);
+
+ // Insert in hash table all strings up to the end of the match.
+ // strstart-1 and strstart are already inserted. If there is not
+ // enough lookahead, the last two strings are not inserted in
+ // the hash table.
+ _validBytesAhead -= _previousLength - 1;
+ _previousLength -= 2;
+ do
+ {
+ if (++_startInsertString <= max_insert)
+ {
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[(_startInsertString) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+ //prev[strstart&w_mask]=hash_head=head[ins_h];
+ hash_head = (_head[_insertedHashIndex] & 0xffff);
+ _previous[_startInsertString & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)_startInsertString;
+ }
+ }
+ while (--_previousLength != 0);
+ _matchAvailable = false;
+ _matchLength = MIN_MATCH - 1;
+ _startInsertString++;
+
+ if (bflush)
+ {
+ flush_block_only(false);
+ if (base.avail_out == 0) return NeedMore;
+ }
+ }
+ else if (_matchAvailable != false)
+ {
+
+ // If there was no match at the previous position, output a
+ // single literal. If there was a match but the current match
+ // is longer, truncate the previous match to a single literal.
+
+ bflush = _tr_tally(0, _window[_startInsertString - 1] & 0xff);
+
+ if (bflush)
+ {
+ flush_block_only(false);
+ }
+ _startInsertString++;
+ _validBytesAhead--;
+ if (base.avail_out == 0) return NeedMore;
+ }
+ else
+ {
+ // There is no previous match to compare with, wait for
+ // the next step to decide.
+
+ _matchAvailable = true;
+ _startInsertString++;
+ _validBytesAhead--;
+ }
+ }
+
+ if (_matchAvailable != false)
+ {
+ bflush = _tr_tally(0, _window[_startInsertString - 1] & 0xff);
+ _matchAvailable = false;
+ }
+ flush_block_only(flush == FlushType.Z_FINISH);
+
+ if (base.avail_out == 0)
+ {
+ if (flush == FlushType.Z_FINISH) return FinishStarted;
+ else return NeedMore;
+ }
+
+ return flush == FlushType.Z_FINISH ? FinishDone : BlockDone;
+ }
+
+ private int longest_match(int cur_match)
+ {
+ int chain_length = _maxChainLength; // max hash chain length
+ int scan = _startInsertString; // current string
+ int match; // matched string
+ int len; // length of current match
+ int best_len = _previousLength; // best match length so far
+ int limit = _startInsertString > (_windowSize - MIN_LOOKAHEAD) ?
+ _startInsertString - (_windowSize - MIN_LOOKAHEAD) : 0;
+ int nice_match = this.nice_match;
+
+ // Stop when cur_match becomes <= limit. To simplify the code,
+ // we prevent matches with the string of window index 0.
+
+ int wmask = _windowMask;
+
+ int strend = _startInsertString + MAX_MATCH;
+ byte scan_end1 = _window[scan + best_len - 1];
+ byte scan_end = _window[scan + best_len];
+
+ // The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+ // It is easy to get rid of this optimization if necessary.
+
+ // Do not waste too much time if we already have a good match:
+ if (_previousLength >= good_match)
+ {
+ chain_length >>= 2;
+ }
+
+ // Do not look for matches beyond the end of the input. This is necessary
+ // to make deflate deterministic.
+ if (nice_match > _validBytesAhead) nice_match = _validBytesAhead;
+
+ do
+ {
+ match = cur_match;
+
+ // Skip to next match if the match length cannot increase
+ // or if the match length is less than 2:
+ if (_window[match + best_len] != scan_end ||
+ _window[match + best_len - 1] != scan_end1 ||
+ _window[match] != _window[scan] ||
+ _window[++match] != _window[scan + 1]) continue;
+
+ // The check at best_len-1 can be removed because it will be made
+ // again later. (This heuristic is not always a win.)
+ // It is not necessary to compare scan[2] and match[2] since they
+ // are always equal when the other bytes match, given that
+ // the hash keys are equal and that HASH_BITS >= 8.
+ scan += 2; match++;
+
+ // We check for insufficient lookahead only every 8th comparison;
+ // the 256th check will be made at strstart+258.
+ do
+ {
+ } while (_window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ scan < strend);
+
+ len = MAX_MATCH - (int)(strend - scan);
+ scan = strend - MAX_MATCH;
+
+ if (len > best_len)
+ {
+ _startMatchString = cur_match;
+ best_len = len;
+ if (len >= nice_match) break;
+ scan_end1 = _window[scan + best_len - 1];
+ scan_end = _window[scan + best_len];
+ }
+
+ } while ((cur_match = (_previous[cur_match & wmask] & 0xffff)) > limit
+ && --chain_length != 0);
+
+ if (best_len <= _validBytesAhead) return best_len;
+ return _validBytesAhead;
+ }
+
+ internal ZLibStatus deflate(ZStream strm, FlushType flush)
+ {
+ FlushType old_flush;
+
+ if (flush > FlushType.Z_FINISH || flush < 0)
+ {
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+
+ if (strm.next_out == null ||
+ (strm.next_in == null && strm.avail_in != 0) ||
+ (_status == FINISH_STATE && flush != FlushType.Z_FINISH))
+ {
+ strm.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_STREAM_ERROR)];
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+ if (strm.avail_out == 0)
+ {
+ strm.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_BUF_ERROR)];
+ return ZLibStatus.Z_BUF_ERROR;
+ }
+
+ old_flush = last_flush;
+ last_flush = flush;
+
+ // Write the zlib header
+ if (_status == INIT_STATE)
+ {
+ int header = (Z_DEFLATED + ((this._windowBits - 8) << 4)) << 8;
+ int level_flags = (((int)this.level - 1) & 0xff) >> 1;
+
+ if (level_flags > 3) level_flags = 3;
+ header |= (level_flags << 6);
+ if (this._startInsertString != 0) header |= PRESET_DICT;
+ header += 31 - (header % 31);
+
+ _status = BUSY_STATE;
+ putShortMSB(header);
+
+
+ // Save the adler32 of the preset dictionary:
+ if (this._startInsertString != 0)
+ {
+ putShortMSB((int)(strm.adler >> 16));
+ putShortMSB((int)(strm.adler & 0xffff));
+ }
+ strm.adler = Adler32.adler32(0, null, 0, 0);
+ }
+
+ // Flush as much pending output as possible
+ if (pending != 0)
+ {
+ this.flush_pending();
+ if (strm.avail_out == 0)
+ {
+ //System.out.println(" avail_out==0");
+ // Since avail_out is 0, deflate will be called again with
+ // more output space, but possibly with both pending and
+ // avail_in equal to zero. There won't be anything to do,
+ // but this is not an error situation so make sure we
+ // return OK instead of BUF_ERROR at next call of deflate:
+ last_flush = (FlushType)(-1);
+ return ZLibStatus.Z_OK;
+ }
+
+ // Make sure there is something to do and avoid duplicate consecutive
+ // flushes. For repeated and useless calls with Z_FINISH, we keep
+ // returning Z_STREAM_END instead of Z_BUFF_ERROR.
+ }
+ else if (strm.avail_in == 0 && flush <= old_flush &&
+ flush != FlushType.Z_FINISH)
+ {
+ strm.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_BUF_ERROR)];
+ return ZLibStatus.Z_BUF_ERROR;
+ }
+
+ // User must not provide more input after the first FINISH:
+ if (_status == FINISH_STATE && strm.avail_in != 0)
+ {
+ strm.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_BUF_ERROR)];
+ return ZLibStatus.Z_BUF_ERROR;
+ }
+
+ // Start a new block or continue the current one.
+ if (strm.avail_in != 0 || this._validBytesAhead != 0 ||
+ (flush != FlushType.Z_NO_FLUSH && _status != FINISH_STATE))
+ {
+ int bstate = -1;
+ switch (config_table[level].Function)
+ {
+ case DefalteFlavor.STORED:
+ bstate = deflate_stored(flush);
+ break;
+ case DefalteFlavor.FAST:
+ bstate = deflate_fast(flush);
+ break;
+ case DefalteFlavor.SLOW:
+ bstate = deflate_slow(flush);
+ break;
+ default:
+ break;
+ }
+
+ if (bstate == FinishStarted || bstate == FinishDone)
+ {
+ _status = FINISH_STATE;
+ }
+ if (bstate == NeedMore || bstate == FinishStarted)
+ {
+ if (strm.avail_out == 0)
+ {
+ last_flush = (FlushType)(-1); // avoid BUF_ERROR next call, see above
+ }
+ return ZLibStatus.Z_OK;
+ // If flush != Z_NO_FLUSH && avail_out == 0, the next call
+ // of deflate should use the same flush parameter to make sure
+ // that the flush is complete. So we don't have to output an
+ // empty block here, this will be done at next call. This also
+ // ensures that for a very small output buffer, we emit at most
+ // one empty block.
+ }
+
+ if (bstate == BlockDone)
+ {
+ if (flush == FlushType.Z_PARTIAL_FLUSH)
+ {
+ _tr_align();
+ }
+ else
+ { // FULL_FLUSH or SYNC_FLUSH
+ _tr_stored_block(0, 0, false);
+ // For a full flush, this empty block will be recognized
+ // as a special marker by inflate_sync().
+ if (flush == FlushType.Z_FULL_FLUSH)
+ {
+ //state.head[s.hash_size-1]=0;
+ for (int i = 0; i < this._hashSize/*-1*/; i++) // forget history
+ this._head[i] = 0;
+ }
+ }
+ this.flush_pending();
+ if (strm.avail_out == 0)
+ {
+ last_flush = (FlushType)(-1); // avoid BUF_ERROR at next call, see above
+ return ZLibStatus.Z_OK;
+ }
+ }
+ }
+
+ if (flush != FlushType.Z_FINISH) return ZLibStatus.Z_OK;
+ if (noheader != 0) return ZLibStatus.Z_STREAM_END;
+
+ // Write the zlib trailer (adler32)
+ putShortMSB((int)(strm.adler >> 16));
+ putShortMSB((int)(strm.adler & 0xffff));
+ this.flush_pending();
+
+ // If avail_out is zero, the application will call deflate again
+ // to flush the rest.
+ noheader = -1; // write the trailer only once!
+ return pending != 0 ? ZLibStatus.Z_OK : ZLibStatus.Z_STREAM_END;
+ }
+
+
+ private static readonly StaticTree static_l_desc = new StaticTree(static_ltree, Deflate.extra_lbits, LITERALS + 1, L_CODES, MAX_BITS);
+
+ private static readonly StaticTree static_d_desc = new StaticTree(static_dtree, Deflate.extra_dbits, 0, D_CODES, MAX_BITS);
+
+ private static readonly StaticTree static_bl_desc = new StaticTree(null, Deflate.extra_blbits, 0, BL_CODES, MAX_BL_BITS);
+
+ private class Config
+ {
+ ///
+ /// Reduce lazy search above this match length
+ ///
+ internal int GoodLength { get; private set; }
+ ///
+ /// Gets or sets whether not to perform lazy search above this match length
+ ///
+ ///
+ /// The max lazy.
+ ///
+ internal int MaxLazy { get; private set; }
+ ///
+ /// Gets or sets whether to quit search above this match length
+ ///
+ ///
+ /// The length of the nice.
+ ///
+ internal int NiceLength { get; private set; }
+ internal int MaxChain { get; private set; }
+ internal DefalteFlavor Function { get; private set; }
+ internal Config(int goodLength, int maxLazy, int niceLength, int maxChain, DefalteFlavor function)
+ {
+ this.GoodLength = goodLength;
+ this.MaxLazy = maxLazy;
+ this.NiceLength = niceLength;
+ this.MaxChain = maxChain;
+ this.Function = function;
+ }
+ }
+
+ public ZLibStatus deflateInit(CompressionLevel level)
+ {
+ return deflateInit(level, MAX_WBITS);
+ }
+ public ZLibStatus deflateInit(CompressionLevel level, bool nowrap)
+ {
+ return deflateInit(level, MAX_WBITS, nowrap);
+ }
+ public ZLibStatus deflateInit(CompressionLevel level, int bits)
+ {
+ return deflateInit(level, bits, false);
+ }
+ public ZLibStatus deflateInit(CompressionLevel level, int bits, bool nowrap)
+ {
+ return this.deflateInit(this, level, nowrap ? -bits : bits);
+ }
+
+ public ZLibStatus deflate(FlushType flush)
+ {
+ return this.deflate(this, flush);
+ }
+ public ZLibStatus deflateParams(CompressionLevel level, CompressionStrategy strategy)
+ {
+ return this.deflateParams(this, level, strategy);
+ }
+ public ZLibStatus deflateSetDictionary(byte[] dictionary, int dictLength)
+ {
+ return this.deflateSetDictionary(this, dictionary, dictLength);
+ }
+
+
+ // Flush as much pending output as possible. All deflate() output goes
+ // through this function so some applications may wish to modify it
+ // to avoid allocating a large strm->next_out buffer and copying into it.
+ // (See also read_buf()).
+ internal void flush_pending()
+ {
+ int len = this.pending;
+
+ if (len > avail_out) len = avail_out;
+ if (len == 0) return;
+
+ if (this.pending_buf.Length <= this.pending_out ||
+ next_out.Length <= next_out_index ||
+ this.pending_buf.Length < (this.pending_out + len) ||
+ next_out.Length < (next_out_index + len))
+ {
+ // System.out.println(this.pending_buf.length+", "+this.pending_out+
+ // ", "+next_out.length+", "+next_out_index+", "+len);
+ // System.out.println("avail_out="+avail_out);
+ }
+
+ System.Array.Copy(this.pending_buf, this.pending_out,
+ next_out, next_out_index, len);
+
+ next_out_index += len;
+ this.pending_out += len;
+ total_out += len;
+ avail_out -= len;
+ this.pending -= len;
+ if (this.pending == 0)
+ {
+ this.pending_out = 0;
+ }
+ }
+
+ // Read a new buffer from the current input stream, update the adler32
+ // and total number of bytes read. All deflate() input goes through
+ // this function so some applications may wish to modify it to avoid
+ // allocating a large strm->next_in buffer and copying from it.
+ // (See also flush_pending()).
+ internal int read_buf(byte[] buf, int start, int size)
+ {
+ int len = avail_in;
+
+ if (len > size) len = size;
+ if (len == 0) return 0;
+
+ avail_in -= len;
+
+ if (this.noheader == 0)
+ {
+ adler = Adler32.adler32(adler, next_in, next_in_index, len);
+ }
+ System.Array.Copy(next_in, next_in_index, buf, start, len);
+ next_in_index += len;
+ total_in += len;
+ return len;
+ }
+
+ public ZLibStatus deflate(byte[] inputBufer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType)
+ {
+ this.next_in = inputBufer;
+ this.next_in_index = inputOffset;
+ this.avail_in = inputCount;
+ this.next_out = outputBuffer;
+ this.next_out_index = outputOffset;
+ this.avail_out = outputCount;
+ return this.deflate(flushType);
+ }
+
+ // TODO: Delete this
+ public ZLibStatus inflateEnd()
+ {
+ throw new NotImplementedException();
+ }
+
+ public ZLibStatus inflate(FlushType flushType)
+ {
+ throw new NotImplementedException();
+ }
+
+ public ZLibStatus inflate(byte[] bufer, int offset, int count, byte[] p1, int p2, int p3, FlushType flushType)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Version.6/Inflate.cs b/Renci.SshNet/Compression/Version.6/Inflate.cs
new file mode 100644
index 0000000..8019fd0
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.6/Inflate.cs
@@ -0,0 +1,517 @@
+using System;
+/*
+ * $Id: Inflate.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public enum InflateMode : int
+ {
+ ///
+ ///waiting for method byte
+ ///
+ METHOD = 0,
+ ///
+ /// waiting for flag byte
+ ///
+ FLAG = 1,
+ ///
+ /// four dictionary check bytes to go
+ ///
+ DICT4 = 2,
+ ///
+ /// three dictionary check bytes to go
+ ///
+ DICT3 = 3,
+ ///
+ /// two dictionary check bytes to go
+ ///
+ DICT2 = 4,
+ ///
+ /// one dictionary check byte to go
+ ///
+ DICT1 = 5,
+ ///
+ /// waiting for inflateSetDictionary
+ ///
+ DICT0 = 6,
+ ///
+ /// decompressing blocks
+ ///
+ BLOCKS = 7,
+ ///
+ /// four check bytes to go
+ ///
+ CHECK4 = 8,
+ ///
+ /// three check bytes to go
+ ///
+ CHECK3 = 9,
+ ///
+ /// two check bytes to go
+ ///
+ CHECK2 = 10,
+ ///
+ /// one check byte to go
+ ///
+ CHECK1 = 11,
+ ///
+ /// finished check, done
+ ///
+ DONE = 12,
+ ///
+ /// got an error--stay here
+ ///
+ BAD = 13
+ }
+
+ internal sealed class Inflate : ZStream, ICompressor
+ {
+ // preset dictionary flag in zlib header
+ private const int PRESET_DICT = 0x20;
+
+ private const int Z_DEFLATED = 8;
+
+ private static readonly byte[] mark = { (byte)0, (byte)0, (byte)0xff, (byte)0xff };
+
+ ///
+ /// The current inflate mode
+ ///
+ private InflateMode _mode;
+
+ ///
+ /// if FLAGS, method byte
+ ///
+ private int method;
+
+ ///
+ /// Computed check value
+ ///
+ private long[] _was = new long[1];
+
+ ///
+ /// The stream check value
+ ///
+ private long _need;
+
+ ///
+ /// if BAD, inflateSync's marker bytes count
+ ///
+ private int _marker;
+
+ // mode independent information
+ ///
+ /// Flag for no wrapper
+ ///
+ private int _nowrap;
+
+ ///
+ /// log2(window size) (8..15, defaults to 15)
+ ///
+ private int _wbits;
+
+ ///
+ /// Current inflate_blocks state
+ ///
+ private InflateBlocks _blocks;
+
+ public Inflate()
+ {
+ this.inflateInit();
+ }
+
+ public Inflate(bool nowrap)
+ {
+ this.inflateInit(nowrap);
+ }
+
+ private ZLibStatus InflateReset()
+ {
+ base.total_in = base.total_out = 0;
+ base.msg = null;
+ this._mode = this._nowrap != 0 ? InflateMode.BLOCKS : InflateMode.METHOD;
+ this._blocks.reset(this, null);
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus InflateEnd(ZStream z)
+ {
+ if (_blocks != null)
+ _blocks.free(z);
+ _blocks = null;
+ // ZFREE(z, z->state);
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus InflateInit(ZStream z, int w)
+ {
+ base.msg = null;
+ _blocks = null;
+
+ // handle undocumented nowrap option (no zlib header or check)
+ _nowrap = 0;
+ if (w < 0)
+ {
+ w = -w;
+ _nowrap = 1;
+ }
+
+ // set window size
+ if (w < 8 || w > 15)
+ {
+ InflateEnd(z);
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+ _wbits = w;
+
+ this._blocks = new InflateBlocks(z,
+ this._nowrap != 0 ? null : this,
+ 1 << w);
+
+ // reset state
+ InflateReset();
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus inflate(FlushType ff)
+ {
+ ZLibStatus r;
+ int b;
+
+ if (base.next_in == null)
+ return ZLibStatus.Z_STREAM_ERROR;
+ var f = ff == FlushType.Z_FINISH ? ZLibStatus.Z_BUF_ERROR : ZLibStatus.Z_OK;
+ r = ZLibStatus.Z_BUF_ERROR;
+ while (true)
+ {
+ //System.out.println("mode: "+this.mode);
+ switch (this._mode)
+ {
+ case InflateMode.METHOD:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ if (((this.method = base.next_in[base.next_in_index++]) & 0xf) != Z_DEFLATED)
+ {
+ this._mode = InflateMode.BAD;
+ base.msg = "unknown compression method";
+ this._marker = 5; // can't try inflateSync
+ break;
+ }
+ if ((this.method >> 4) + 8 > this._wbits)
+ {
+ this._mode = InflateMode.BAD;
+ base.msg = "invalid window size";
+ this._marker = 5; // can't try inflateSync
+ break;
+ }
+ this._mode = InflateMode.FLAG;
+ goto case InflateMode.FLAG;
+ case InflateMode.FLAG:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ b = (base.next_in[base.next_in_index++]) & 0xff;
+
+ if ((((this.method << 8) + b) % 31) != 0)
+ {
+ this._mode = InflateMode.BAD;
+ base.msg = "incorrect header check";
+ this._marker = 5; // can't try inflateSync
+ break;
+ }
+
+ if ((b & PRESET_DICT) == 0)
+ {
+ this._mode = InflateMode.BLOCKS;
+ break;
+ }
+ this._mode = InflateMode.DICT4;
+ goto case InflateMode.DICT4;
+ case InflateMode.DICT4:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need = ((base.next_in[base.next_in_index++] & 0xff) << 24) & 0xff000000L;
+ this._mode = InflateMode.DICT3;
+ goto case InflateMode.DICT3;
+ case InflateMode.DICT3:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += ((base.next_in[base.next_in_index++] & 0xff) << 16) & 0xff0000L;
+ this._mode = InflateMode.DICT2;
+ goto case InflateMode.DICT2;
+ case InflateMode.DICT2:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += ((base.next_in[base.next_in_index++] & 0xff) << 8) & 0xff00L;
+ this._mode = InflateMode.DICT1;
+ goto case InflateMode.DICT1;
+ case InflateMode.DICT1:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += (base.next_in[base.next_in_index++] & 0xffL);
+ base.adler = this._need;
+ this._mode = InflateMode.DICT0;
+ return ZLibStatus.Z_NEED_DICT;
+ case InflateMode.DICT0:
+ this._mode = InflateMode.BAD;
+ base.msg = "need dictionary";
+ this._marker = 0; // can try inflateSync
+ return ZLibStatus.Z_STREAM_ERROR;
+ case InflateMode.BLOCKS:
+
+ r = this._blocks.proc(this, r);
+ if (r == ZLibStatus.Z_DATA_ERROR)
+ {
+ this._mode = InflateMode.BAD;
+ this._marker = 0; // can try inflateSync
+ break;
+ }
+ if (r == ZLibStatus.Z_OK)
+ {
+ r = f;
+ }
+ if (r != ZLibStatus.Z_STREAM_END)
+ {
+ return r;
+ }
+ r = f;
+ this._blocks.reset(this, this._was);
+ if (this._nowrap != 0)
+ {
+ this._mode = InflateMode.DONE;
+ break;
+ }
+ this._mode = InflateMode.CHECK4;
+ goto case InflateMode.CHECK4;
+ case InflateMode.CHECK4:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need = ((base.next_in[base.next_in_index++] & 0xff) << 24) & 0xff000000L;
+ this._mode = InflateMode.CHECK3;
+ goto case InflateMode.CHECK3;
+ case InflateMode.CHECK3:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += ((base.next_in[base.next_in_index++] & 0xff) << 16) & 0xff0000L;
+ this._mode = InflateMode.CHECK2;
+ goto case InflateMode.CHECK2;
+ case InflateMode.CHECK2:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += ((base.next_in[base.next_in_index++] & 0xff) << 8) & 0xff00L;
+ this._mode = InflateMode.CHECK1;
+ goto case InflateMode.CHECK1;
+ case InflateMode.CHECK1:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += (base.next_in[base.next_in_index++] & 0xffL);
+
+ if (((int)(this._was[0])) != ((int)(this._need)))
+ {
+ this._mode = InflateMode.BAD;
+ base.msg = "incorrect data check";
+ this._marker = 5; // can't try inflateSync
+ break;
+ }
+
+ this._mode = InflateMode.DONE;
+ goto case InflateMode.DONE;
+ case InflateMode.DONE:
+ return ZLibStatus.Z_STREAM_END;
+ case InflateMode.BAD:
+ return ZLibStatus.Z_DATA_ERROR;
+ default:
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+ }
+ }
+
+ public ZLibStatus InflateSetDictionary(byte[] dictionary, int dictLength)
+ {
+ int index = 0;
+ int length = dictLength;
+ if (this._mode != InflateMode.DICT0)
+ return ZLibStatus.Z_STREAM_ERROR;
+
+ if (Adler32.adler32(1L, dictionary, 0, dictLength) != base.adler)
+ {
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+
+ base.adler = Adler32.adler32(0, null, 0, 0);
+
+ if (length >= (1 << this._wbits))
+ {
+ length = (1 << this._wbits) - 1;
+ index = dictLength - length;
+ }
+ this._blocks.set_dictionary(dictionary, index, length);
+ this._mode = InflateMode.BLOCKS;
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus InflateSync(ZStream z)
+ {
+ int n; // number of bytes to look at
+ int p; // pointer to bytes
+ int m; // number of marker bytes found in a row
+ long r, w; // temporaries to save total_in and total_out
+
+ // set up
+ if (this._mode != InflateMode.BAD)
+ {
+ this._mode = InflateMode.BAD;
+ this._marker = 0;
+ }
+ if ((n = base.avail_in) == 0)
+ return ZLibStatus.Z_BUF_ERROR;
+ p = base.next_in_index;
+ m = this._marker;
+
+ // search
+ while (n != 0 && m < 4)
+ {
+ if (base.next_in[p] == mark[m])
+ {
+ m++;
+ }
+ else if (base.next_in[p] != 0)
+ {
+ m = 0;
+ }
+ else
+ {
+ m = 4 - m;
+ }
+ p++; n--;
+ }
+
+ // restore
+ base.total_in += p - base.next_in_index;
+ base.next_in_index = p;
+ base.avail_in = n;
+ this._marker = m;
+
+ // return no joy or set up to restart on a new block
+ if (m != 4)
+ {
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ r = base.total_in; w = base.total_out;
+ InflateReset();
+ base.total_in = r; base.total_out = w;
+ this._mode = InflateMode.BLOCKS;
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus inflateInit()
+ {
+ return inflateInit(DEF_WBITS);
+ }
+ public ZLibStatus inflateInit(bool nowrap)
+ {
+ return inflateInit(DEF_WBITS, nowrap);
+ }
+ public ZLibStatus inflateInit(int w)
+ {
+ return inflateInit(w, false);
+ }
+
+ public ZLibStatus inflateInit(int w, bool nowrap)
+ {
+ return this.InflateInit(this, nowrap ? -w : w);
+ }
+
+ public ZLibStatus inflateEnd()
+ {
+ var ret = this.InflateEnd(this);
+ return ret;
+ }
+ public ZLibStatus inflateSync()
+ {
+ return this.InflateSync(this);
+ }
+ public ZLibStatus inflateSetDictionary(byte[] dictionary, int dictLength)
+ {
+ return this.InflateSetDictionary(dictionary, dictLength);
+ }
+
+ public ZLibStatus inflate(byte[] inputBufer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType)
+ {
+ this.next_in = inputBufer;
+ this.next_in_index = inputOffset;
+ this.avail_in = inputCount;
+ this.next_out = outputBuffer;
+ this.next_out_index = outputOffset;
+ this.avail_out = outputCount;
+ return this.inflate(flushType);
+ }
+
+ // TODO: Dlete this
+ public ZLibStatus deflate(byte[] bufer, int offset, int count, byte[] p1, int p2, int p3, FlushType flushType)
+ {
+ throw new NotImplementedException();
+ }
+
+ public ZLibStatus deflateEnd()
+ {
+ throw new NotImplementedException();
+ }
+
+ public ZLibStatus deflate(FlushType flushType)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Version.6/InflateBlocks.cs b/Renci.SshNet/Compression/Version.6/InflateBlocks.cs
new file mode 100644
index 0000000..273389f
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.6/InflateBlocks.cs
@@ -0,0 +1,721 @@
+using System;
+/*
+ * $Id: InfBlocks.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public enum InflateBlockMode
+ {
+ ///
+ /// get type bits (3, including end bit)
+ ///
+ TYPE = 0,
+ ///
+ /// get lengths for stored
+ ///
+ LENS = 1,
+ ///
+ /// cessing stored block
+ ///
+ STORED = 2,
+ ///
+ /// get table lengths
+ ///
+ TABLE = 3,
+ ///
+ /// get bit lengths tree for a dynamic block
+ ///
+ BTREE = 4,
+ ///
+ /// get length, distance trees for a dynamic block
+ ///
+ DTREE = 5,
+ ///
+ /// processing fixed or dynamic block
+ ///
+ CODES = 6,
+ ///
+ /// output remaining window bytes
+ ///
+ DRY = 7,
+ ///
+ /// finished last block, done
+ ///
+ DONE = 8,
+ ///
+ /// ot a data error--stuck here
+ ///
+ BAD = 9
+ }
+
+ internal sealed class InflateBlocks : InflateCodes
+ {
+ private const int MANY = 1440;
+
+ // And'ing with mask[n] masks the lower n bits
+ private static readonly int[] inflate_mask = {
+ 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
+ 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
+ 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
+ 0x00007fff, 0x0000ffff
+ };
+
+ // Table for deflate from PKZIP's appnote.txt.
+ static readonly int[] border = { // Order of the bit length code lengths
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
+ };
+
+ internal InflateBlockMode mode; // current inflate_block mode
+
+ internal int left; // if STORED, bytes left to copy
+
+ internal int table; // table lengths (14 bits)
+ internal int index; // index into blens (or border)
+ internal int[] blens; // bit lengths of codes
+ internal int[] bb = new int[1]; // bit length tree depth
+ internal int[] tb = new int[1]; // bit length decoding tree
+
+ //internal InfCodes codes = new InfCodes(); // if CODES, current state
+
+ int last; // true if this block is the last block
+
+ // mode independent information
+ internal int bitk; // bits in bit buffer
+ internal int bitb; // bit buffer
+ internal int[] hufts; // single malloc for tree space
+ internal byte[] window; // sliding window
+ internal int end; // one byte after sliding window
+ internal int read; // window read pointer
+ internal int write; // window write pointer
+ internal Object checkfn; // check function
+ internal long check; // check on output
+
+ internal InflateTree inftree = new InflateTree();
+
+ internal InflateBlocks(ZStream z, Object checkfn, int w)
+ {
+ hufts = new int[MANY * 3];
+ window = new byte[w];
+ end = w;
+ this.checkfn = checkfn;
+ mode = InflateBlockMode.TYPE;
+ reset(z, null);
+ }
+
+ internal void reset(ZStream z, long[] c)
+ {
+ if (c != null) c[0] = check;
+ if (mode == InflateBlockMode.BTREE || mode == InflateBlockMode.DTREE)
+ {
+ }
+ if (mode == InflateBlockMode.CODES)
+ {
+ codesfree(z);
+ }
+ mode = InflateBlockMode.TYPE;
+ bitk = 0;
+ bitb = 0;
+ read = write = 0;
+
+ if (checkfn != null)
+ z.adler = check = Adler32.adler32(0L, null, 0, 0);
+ }
+
+ internal ZLibStatus proc(ZStream z, ZLibStatus r)
+ {
+ int t; // temporary storage
+ ZLibStatus tt;
+ int b; // bit buffer
+ int k; // bits in bit buffer
+ int p; // input data pointer
+ int n; // bytes available there
+ int q; // output window write pointer
+ int m;
+ { // bytes to end of window or read pointer
+
+ // copy input/output information to locals (UPDATE macro restores)
+ p = z.next_in_index; n = z.avail_in; b = bitb; k = bitk;
+ }
+ {
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+ }
+
+ // process input based on current state
+ while (true)
+ {
+ switch (mode)
+ {
+ case InflateBlockMode.TYPE:
+
+ while (k < (3))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+ t = (int)(b & 7);
+ last = t & 1;
+
+ switch (t >> 1)
+ {
+ case 0:
+ { // stored
+ b >>= (3); k -= (3);
+ }
+ t = k & 7;
+ { // go to byte boundary
+
+ b >>= (t); k -= (t);
+ }
+ mode = InflateBlockMode.LENS; // get length of stored block
+ break;
+ case 1:
+ { // fixed
+ int[] bl = new int[1];
+ int[] bd = new int[1];
+ int[][] tl = new int[1][];
+ int[][] td = new int[1][];
+
+ InflateTree.InflateTreesFixed(bl, bd, tl, td, z);
+ codesinit(bl[0], bd[0], tl[0], 0, td[0], 0, z);
+ }
+ {
+
+ b >>= (3); k -= (3);
+ }
+
+ mode = InflateBlockMode.CODES;
+ break;
+ case 2:
+ { // dynamic
+
+ b >>= (3); k -= (3);
+ }
+
+ mode = InflateBlockMode.TABLE;
+ break;
+ case 3:
+ { // illegal
+
+ b >>= (3); k -= (3);
+ }
+ mode = InflateBlockMode.BAD;
+ z.msg = "invalid block type";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ break;
+ case InflateBlockMode.LENS:
+
+ while (k < (32))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ if ((((~b) >> 16) & 0xffff) != (b & 0xffff))
+ {
+ mode = InflateBlockMode.BAD;
+ z.msg = "invalid stored block lengths";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ left = (b & 0xffff);
+ b = k = 0; // dump bits
+ mode = left != 0 ? InflateBlockMode.STORED : (last != 0 ? InflateBlockMode.DRY : InflateBlockMode.TYPE);
+ break;
+ case InflateBlockMode.STORED:
+ if (n == 0)
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+
+ if (m == 0)
+ {
+ if (q == end && read != 0)
+ {
+ q = 0; m = (int)(q < read ? read - q - 1 : end - q);
+ }
+ if (m == 0)
+ {
+ write = q;
+ r = inflate_flush(z, r);
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+ if (q == end && read != 0)
+ {
+ q = 0; m = (int)(q < read ? read - q - 1 : end - q);
+ }
+ if (m == 0)
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ }
+ }
+ r = ZLibStatus.Z_OK;
+
+ t = left;
+ if (t > n) t = n;
+ if (t > m) t = m;
+ System.Array.Copy(z.next_in, p, window, q, t);
+ p += t; n -= t;
+ q += t; m -= t;
+ if ((left -= t) != 0)
+ break;
+ mode = last != 0 ? InflateBlockMode.DRY : InflateBlockMode.TYPE;
+ break;
+ case InflateBlockMode.TABLE:
+
+ while (k < (14))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ table = t = (b & 0x3fff);
+ if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
+ {
+ mode = InflateBlockMode.BAD;
+ z.msg = "too many length or distance symbols";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
+ if (blens == null || blens.Length < t)
+ {
+ blens = new int[t];
+ }
+ else
+ {
+ for (int i = 0; i < t; i++) { blens[i] = 0; }
+ }
+ {
+
+ b >>= (14); k -= (14);
+ }
+
+ index = 0;
+ mode = InflateBlockMode.BTREE;
+ goto case InflateBlockMode.BTREE;
+ case InflateBlockMode.BTREE:
+ while (index < 4 + (table >> 10))
+ {
+ while (k < (3))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ blens[border[index++]] = b & 7;
+ {
+
+ b >>= (3); k -= (3);
+ }
+ }
+
+ while (index < 19)
+ {
+ blens[border[index++]] = 0;
+ }
+
+ bb[0] = 7;
+ tt = inftree.InflateTreesBits(blens, bb, tb, hufts, z);
+ if (tt != ZLibStatus.Z_OK)
+ {
+ r = tt;
+ if (r == ZLibStatus.Z_DATA_ERROR)
+ {
+ blens = null;
+ mode = InflateBlockMode.BAD;
+ }
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+
+ index = 0;
+ mode = InflateBlockMode.DTREE;
+ goto case InflateBlockMode.DTREE;
+ case InflateBlockMode.DTREE:
+ while (true)
+ {
+ t = table;
+ if (!(index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)))
+ {
+ break;
+ }
+
+ int i, j, c;
+
+ t = bb[0];
+
+ while (k < (t))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ if (tb[0] == -1)
+ {
+ //System.err.println("null...");
+ }
+
+ t = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 1];
+ c = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 2];
+
+ if (c < 16)
+ {
+ b >>= (t); k -= (t);
+ blens[index++] = c;
+ }
+ else
+ { // c == 16..18
+ i = c == 18 ? 7 : c - 14;
+ j = c == 18 ? 11 : 3;
+
+ while (k < (t + i))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ b >>= (t); k -= (t);
+
+ j += (b & inflate_mask[i]);
+
+ b >>= (i); k -= (i);
+
+ i = index;
+ t = table;
+ if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
+ (c == 16 && i < 1))
+ {
+ blens = null;
+ mode = InflateBlockMode.BAD;
+ z.msg = "invalid bit length repeat";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+
+ c = c == 16 ? blens[i - 1] : 0;
+ do
+ {
+ blens[i++] = c;
+ }
+ while (--j != 0);
+ index = i;
+ }
+ }
+
+ tb[0] = -1;
+ {
+ int[] bl = new int[1];
+ int[] bd = new int[1];
+ int[] tl = new int[1];
+ int[] td = new int[1];
+ bl[0] = 9; // must be <= 9 for lookahead assumptions
+ bd[0] = 6; // must be <= 9 for lookahead assumptions
+
+ t = table;
+ tt = inftree.InflateTreesDynamic(257 + (t & 0x1f),
+ 1 + ((t >> 5) & 0x1f),
+ blens, bl, bd, tl, td, hufts, z);
+
+ if (tt != ZLibStatus.Z_OK)
+ {
+ if (tt == ZLibStatus.Z_DATA_ERROR)
+ {
+ blens = null;
+ mode = InflateBlockMode.BAD;
+ }
+ r = tt;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ codesinit(bl[0], bd[0], hufts, tl[0], hufts, td[0], z);
+ }
+ mode = InflateBlockMode.CODES;
+ goto case InflateBlockMode.CODES;
+ case InflateBlockMode.CODES:
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+
+ if ((r = codesproc(this, z, r)) != ZLibStatus.Z_STREAM_END)
+ {
+ return inflate_flush(z, r);
+ }
+ r = ZLibStatus.Z_OK;
+ codesfree(z);
+
+ p = z.next_in_index; n = z.avail_in; b = bitb; k = bitk;
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+
+ if (last == 0)
+ {
+ mode = InflateBlockMode.TYPE;
+ break;
+ }
+ mode = InflateBlockMode.DRY;
+ goto case InflateBlockMode.DRY;
+ case InflateBlockMode.DRY:
+ write = q;
+ r = inflate_flush(z, r);
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+ if (read != write)
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ mode = InflateBlockMode.DONE;
+ goto case InflateBlockMode.DONE;
+ case InflateBlockMode.DONE:
+ r = ZLibStatus.Z_STREAM_END;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ case InflateBlockMode.BAD:
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+
+ default:
+ r = ZLibStatus.Z_STREAM_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ }
+ }
+
+ internal void free(ZStream z)
+ {
+ reset(z, null);
+ window = null;
+ hufts = null;
+ //ZFREE(z, s);
+ }
+
+ internal void set_dictionary(byte[] d, int start, int n)
+ {
+ System.Array.Copy(d, start, window, 0, n);
+ read = write = n;
+ }
+
+ // Returns true if inflate is currently at the end of a block generated
+ // by Z_SYNC_FLUSH or FlushType.Z_FULL_FLUSH.
+ internal ZLibStatus sync_point()
+ {
+ return mode == InflateBlockMode.LENS ? ZLibStatus.Z_STREAM_END : ZLibStatus.Z_OK;
+ }
+
+ // copy as much as possible from the sliding window to the output area
+ internal ZLibStatus inflate_flush(ZStream z, ZLibStatus r)
+ {
+ int n;
+ int p;
+ int q;
+
+ // local copies of source and destination pointers
+ p = z.next_out_index;
+ q = read;
+
+ // compute number of bytes to copy as far as end of window
+ n = (int)((q <= write ? write : end) - q);
+ if (n > z.avail_out) n = z.avail_out;
+ if (n != 0 && r == ZLibStatus.Z_BUF_ERROR) r = ZLibStatus.Z_OK;
+
+ // update counters
+ z.avail_out -= n;
+ z.total_out += n;
+
+ // update check information
+ if (checkfn != null)
+ z.adler = check = Adler32.adler32(check, window, q, n);
+
+ // copy as far as end of window
+ System.Array.Copy(window, q, z.next_out, p, n);
+ p += n;
+ q += n;
+
+ // see if more to copy at beginning of window
+ if (q == end)
+ {
+ // wrap pointers
+ q = 0;
+ if (write == end)
+ write = 0;
+
+ // compute bytes to copy
+ n = write - q;
+ if (n > z.avail_out) n = z.avail_out;
+ if (n != 0 && r == ZLibStatus.Z_BUF_ERROR) r = ZLibStatus.Z_OK;
+
+ // update counters
+ z.avail_out -= n;
+ z.total_out += n;
+
+ // update check information
+ if (checkfn != null)
+ z.adler = check = Adler32.adler32(check, window, q, n);
+
+ // copy
+ System.Array.Copy(window, q, z.next_out, p, n);
+ p += n;
+ q += n;
+ }
+
+ // update pointers
+ z.next_out_index = p;
+ read = q;
+
+ // done
+ return r;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Version.6/InflateCodes.cs b/Renci.SshNet/Compression/Version.6/InflateCodes.cs
new file mode 100644
index 0000000..3214e56
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.6/InflateCodes.cs
@@ -0,0 +1,690 @@
+using System;
+/*
+ * $Id: InfCodes.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public enum InflateCodeMode
+ {
+ ///
+ /// x: set up for InflateCodeMode.LEN
+ ///
+ START = 0,
+ ///
+ /// i: get length/literal/eob next
+ ///
+ LEN = 1,
+ ///
+ /// i: getting length extra (have base)
+ ///
+ LENEXT = 2,
+ ///
+ /// i: get distance next
+ ///
+ DIST = 3,
+ ///
+ /// : getting distance extra
+ ///
+ DISTEXT = 4,
+ ///
+ /// o: copying bytes in window, waiting for space
+ ///
+ COPY = 5,
+ ///
+ /// o: got literal, waiting for output space
+ ///
+ LIT = 6,
+ ///
+ /// o: got eob, possibly still output waiting
+ ///
+ WASH = 7,
+ ///
+ /// x: got eob and all data flushed
+ ///
+ END = 8,
+ ///
+ /// x: got error
+ ///
+ BADCODE = 9
+ }
+
+ internal abstract class InflateCodes// : ZStream
+ {
+ private static readonly int[] inflate_mask = {
+ 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
+ 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
+ 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
+ 0x00007fff, 0x0000ffff
+ };
+
+ InflateCodeMode mode; // current inflate_codes mode
+
+ // mode dependent information
+ int len;
+
+ int[] tree; // pointer into tree
+ int tree_index = 0;
+ int need; // bits needed
+
+ int lit;
+
+ // if EXT or COPY, where and how much
+ int get; // bits to get for extra
+ int dist; // distance back to copy from
+
+ byte lbits; // ltree bits decoded per branch
+ byte dbits; // dtree bits decoder per branch
+ int[] ltree; // literal/length/eob tree
+ int ltree_index; // literal/length/eob tree
+ int[] dtree; // distance tree
+ int dtree_index; // distance tree
+
+ internal InflateCodes()
+ {
+ }
+ internal void codesinit(int bl, int bd,
+ int[] tl, int tl_index,
+ int[] td, int td_index, ZStream z)
+ {
+ mode = InflateCodeMode.START;
+ lbits = (byte)bl;
+ dbits = (byte)bd;
+ ltree = tl;
+ ltree_index = tl_index;
+ dtree = td;
+ dtree_index = td_index;
+ tree = null;
+ }
+
+ internal ZLibStatus codesproc(InflateBlocks s, ZStream z, ZLibStatus r)
+ {
+ int j; // temporary storage
+ int tindex; // temporary pointer
+ int e; // extra bits or operation
+ int b = 0; // bit buffer
+ int k = 0; // bits in bit buffer
+ int p = 0; // input data pointer
+ int n; // bytes available there
+ int q; // output window write pointer
+ int m; // bytes to end of window or read pointer
+ int f; // pointer to copy strings from
+
+ // copy input/output information to locals (UPDATE macro restores)
+ p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk;
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ // process input and output based on current state
+ while (true)
+ {
+ switch (mode)
+ {
+ // waiting for "i:"=input, "o:"=output, "x:"=nothing
+ case InflateCodeMode.START: // x: set up for LEN
+ if (m >= 258 && n >= 10)
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ r = inflate_fast(lbits, dbits,
+ ltree, ltree_index,
+ dtree, dtree_index,
+ s, z);
+
+ p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk;
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (r != ZLibStatus.Z_OK)
+ {
+ mode = r == ZLibStatus.Z_STREAM_END ? InflateCodeMode.WASH : InflateCodeMode.BADCODE;
+ break;
+ }
+ }
+ need = lbits;
+ tree = ltree;
+ tree_index = ltree_index;
+
+ mode = InflateCodeMode.LEN;
+ goto case InflateCodeMode.LEN;
+ case InflateCodeMode.LEN: // i: get length/literal/eob next
+ j = need;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ tindex = (tree_index + (b & inflate_mask[j])) * 3;
+
+ b >>= (tree[tindex + 1]);
+ k -= (tree[tindex + 1]);
+
+ e = tree[tindex];
+
+ if (e == 0)
+ { // literal
+ lit = tree[tindex + 2];
+ mode = InflateCodeMode.LIT;
+ break;
+ }
+ if ((e & 16) != 0)
+ { // length
+ get = e & 15;
+ len = tree[tindex + 2];
+ mode = InflateCodeMode.LENEXT;
+ break;
+ }
+ if ((e & 64) == 0)
+ { // next table
+ need = e;
+ tree_index = tindex / 3 + tree[tindex + 2];
+ break;
+ }
+ if ((e & 32) != 0)
+ { // end of block
+ mode = InflateCodeMode.WASH;
+ break;
+ }
+ mode = InflateCodeMode.BADCODE; // invalid code
+ z.msg = "invalid literal/length code";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ case InflateCodeMode.LENEXT: // i: getting length extra (have base)
+ j = get;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--; b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ len += (b & inflate_mask[j]);
+
+ b >>= j;
+ k -= j;
+
+ need = dbits;
+ tree = dtree;
+ tree_index = dtree_index;
+ mode = InflateCodeMode.DIST;
+ goto case InflateCodeMode.DIST;
+ case InflateCodeMode.DIST: // i: get distance next
+ j = need;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--; b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ tindex = (tree_index + (b & inflate_mask[j])) * 3;
+
+ b >>= tree[tindex + 1];
+ k -= tree[tindex + 1];
+
+ e = (tree[tindex]);
+ if ((e & 16) != 0)
+ { // distance
+ get = e & 15;
+ dist = tree[tindex + 2];
+ mode = InflateCodeMode.DISTEXT;
+ break;
+ }
+ if ((e & 64) == 0)
+ { // next table
+ need = e;
+ tree_index = tindex / 3 + tree[tindex + 2];
+ break;
+ }
+ mode = InflateCodeMode.BADCODE; // invalid code
+ z.msg = "invalid distance code";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ case InflateCodeMode.DISTEXT: // i: getting distance extra
+ j = get;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--; b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ dist += (b & inflate_mask[j]);
+
+ b >>= j;
+ k -= j;
+
+ mode = InflateCodeMode.COPY;
+ goto case InflateCodeMode.COPY;
+ case InflateCodeMode.COPY: // o: copying bytes in window, waiting for space
+ f = q - dist;
+ while (f < 0)
+ { // modulo window size-"while" instead
+ f += s.end; // of "if" handles invalid distances
+ }
+ while (len != 0)
+ {
+
+ if (m == 0)
+ {
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+ if (m == 0)
+ {
+ s.write = q; r = s.inflate_flush(z, r);
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+
+ if (m == 0)
+ {
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ }
+ }
+
+ s.window[q++] = s.window[f++]; m--;
+
+ if (f == s.end)
+ f = 0;
+ len--;
+ }
+ mode = InflateCodeMode.START;
+ break;
+ case InflateCodeMode.LIT: // o: got literal, waiting for output space
+ if (m == 0)
+ {
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+ if (m == 0)
+ {
+ s.write = q; r = s.inflate_flush(z, r);
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+ if (m == 0)
+ {
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ }
+ }
+ r = ZLibStatus.Z_OK;
+
+ s.window[q++] = (byte)lit; m--;
+
+ mode = InflateCodeMode.START;
+ break;
+ case InflateCodeMode.WASH: // o: got eob, possibly more output
+ if (k > 7)
+ { // return unused byte, if any
+ k -= 8;
+ n++;
+ p--; // can always return one
+ }
+
+ s.write = q; r = s.inflate_flush(z, r);
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (s.read != s.write)
+ {
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ mode = InflateCodeMode.END;
+ goto case InflateCodeMode.END;
+ case InflateCodeMode.END:
+ r = ZLibStatus.Z_STREAM_END;
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ case InflateCodeMode.BADCODE: // x: got error
+
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ default:
+ r = ZLibStatus.Z_STREAM_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ }
+ }
+
+ internal void codesfree(ZStream z)
+ {
+ // ZFREE(z, c);
+ }
+
+ // Called with number of bytes left to write in window at least 258
+ // (the maximum string length) and number of input bytes available
+ // at least ten. The ten bytes are six bytes for the longest length/
+ // distance pair plus four bytes for overloading the bit buffer.
+
+ internal ZLibStatus inflate_fast(int bl, int bd,
+ int[] tl, int tl_index,
+ int[] td, int td_index,
+ InflateBlocks s, ZStream z)
+ {
+ int t; // temporary pointer
+ int[] tp; // temporary pointer
+ int tp_index; // temporary pointer
+ int e; // extra bits or operation
+ int b; // bit buffer
+ int k; // bits in bit buffer
+ int p; // input data pointer
+ int n; // bytes available there
+ int q; // output window write pointer
+ int m; // bytes to end of window or read pointer
+ int ml; // mask for literal/length tree
+ int md; // mask for distance tree
+ int c; // bytes to copy
+ int d; // distance back to copy from
+ int r; // copy source pointer
+
+ int tp_index_t_3; // (tp_index+t)*3
+
+ // load input, output, bit values
+ p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk;
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ // initialize masks
+ ml = inflate_mask[bl];
+ md = inflate_mask[bd];
+
+ // do until not enough input or output space for fast loop
+ do
+ { // assume called with m >= 258 && n >= 10
+ // get literal/length code
+ while (k < (20))
+ { // max bits for literal/length code
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k; k += 8;
+ }
+
+ t = b & ml;
+ tp = tl;
+ tp_index = tl_index;
+ tp_index_t_3 = (tp_index + t) * 3;
+ if ((e = tp[tp_index_t_3]) == 0)
+ {
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ s.window[q++] = (byte)tp[tp_index_t_3 + 2];
+ m--;
+ continue;
+ }
+ do
+ {
+
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ if ((e & 16) != 0)
+ {
+ e &= 15;
+ c = tp[tp_index_t_3 + 2] + ((int)b & inflate_mask[e]);
+
+ b >>= e; k -= e;
+
+ // decode distance base of block to copy
+ while (k < (15))
+ { // max bits for distance code
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k; k += 8;
+ }
+
+ t = b & md;
+ tp = td;
+ tp_index = td_index;
+ tp_index_t_3 = (tp_index + t) * 3;
+ e = tp[tp_index_t_3];
+
+ do
+ {
+
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ if ((e & 16) != 0)
+ {
+ // get extra bits to add to distance base
+ e &= 15;
+ while (k < (e))
+ { // get extra bits (up to 13)
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k; k += 8;
+ }
+
+ d = tp[tp_index_t_3 + 2] + (b & inflate_mask[e]);
+
+ b >>= (e); k -= (e);
+
+ // do the copy
+ m -= c;
+ if (q >= d)
+ { // offset before dest
+ // just copy
+ r = q - d;
+ if (q - r > 0 && 2 > (q - r))
+ {
+ s.window[q++] = s.window[r++]; // minimum count is three,
+ s.window[q++] = s.window[r++]; // so unroll loop a little
+ c -= 2;
+ }
+ else
+ {
+ System.Array.Copy(s.window, r, s.window, q, 2);
+ q += 2; r += 2; c -= 2;
+ }
+ }
+ else
+ { // else offset after destination
+ r = q - d;
+ do
+ {
+ r += s.end; // force pointer in window
+ } while (r < 0); // covers invalid distances
+ e = s.end - r;
+ if (c > e)
+ { // if source crosses,
+ c -= e; // wrapped copy
+ if (q - r > 0 && e > (q - r))
+ {
+ do { s.window[q++] = s.window[r++]; }
+ while (--e != 0);
+ }
+ else
+ {
+ System.Array.Copy(s.window, r, s.window, q, e);
+ q += e; r += e; e = 0;
+ }
+ r = 0; // copy rest from start of window
+ }
+
+ }
+
+ // copy all or what's left
+ if (q - r > 0 && c > (q - r))
+ {
+ do { s.window[q++] = s.window[r++]; }
+ while (--c != 0);
+ }
+ else
+ {
+ System.Array.Copy(s.window, r, s.window, q, c);
+ q += c; r += c; c = 0;
+ }
+ break;
+ }
+ else if ((e & 64) == 0)
+ {
+ t += tp[tp_index_t_3 + 2];
+ t += (b & inflate_mask[e]);
+ tp_index_t_3 = (tp_index + t) * 3;
+ e = tp[tp_index_t_3];
+ }
+ else
+ {
+ z.msg = "invalid distance code";
+
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ }
+ while (true);
+ break;
+ }
+
+ if ((e & 64) == 0)
+ {
+ t += tp[tp_index_t_3 + 2];
+ t += (b & inflate_mask[e]);
+ tp_index_t_3 = (tp_index + t) * 3;
+ if ((e = tp[tp_index_t_3]) == 0)
+ {
+
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ s.window[q++] = (byte)tp[tp_index_t_3 + 2];
+ m--;
+ break;
+ }
+ }
+ else if ((e & 32) != 0)
+ {
+
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_STREAM_END;
+ }
+ else
+ {
+ z.msg = "invalid literal/length code";
+
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ }
+ while (true);
+ }
+ while (m >= 258 && n >= 10);
+
+ // not enough input or output--restore pointers and return
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_OK;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Version.6/InflateTree.cs b/Renci.SshNet/Compression/Version.6/InflateTree.cs
new file mode 100644
index 0000000..f9da579
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.6/InflateTree.cs
@@ -0,0 +1,555 @@
+using System;
+/*
+ * $Id: InfTree.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ internal sealed class InflateTree
+ {
+ private const int MANY = 1440;
+
+ private const int fixed_bl = 9;
+ private const int fixed_bd = 5;
+
+ static readonly int[] fixed_tl = {
+ 96,7,256, 0,8,80, 0,8,16, 84,8,115,
+ 82,7,31, 0,8,112, 0,8,48, 0,9,192,
+ 80,7,10, 0,8,96, 0,8,32, 0,9,160,
+ 0,8,0, 0,8,128, 0,8,64, 0,9,224,
+ 80,7,6, 0,8,88, 0,8,24, 0,9,144,
+ 83,7,59, 0,8,120, 0,8,56, 0,9,208,
+ 81,7,17, 0,8,104, 0,8,40, 0,9,176,
+ 0,8,8, 0,8,136, 0,8,72, 0,9,240,
+ 80,7,4, 0,8,84, 0,8,20, 85,8,227,
+ 83,7,43, 0,8,116, 0,8,52, 0,9,200,
+ 81,7,13, 0,8,100, 0,8,36, 0,9,168,
+ 0,8,4, 0,8,132, 0,8,68, 0,9,232,
+ 80,7,8, 0,8,92, 0,8,28, 0,9,152,
+ 84,7,83, 0,8,124, 0,8,60, 0,9,216,
+ 82,7,23, 0,8,108, 0,8,44, 0,9,184,
+ 0,8,12, 0,8,140, 0,8,76, 0,9,248,
+ 80,7,3, 0,8,82, 0,8,18, 85,8,163,
+ 83,7,35, 0,8,114, 0,8,50, 0,9,196,
+ 81,7,11, 0,8,98, 0,8,34, 0,9,164,
+ 0,8,2, 0,8,130, 0,8,66, 0,9,228,
+ 80,7,7, 0,8,90, 0,8,26, 0,9,148,
+ 84,7,67, 0,8,122, 0,8,58, 0,9,212,
+ 82,7,19, 0,8,106, 0,8,42, 0,9,180,
+ 0,8,10, 0,8,138, 0,8,74, 0,9,244,
+ 80,7,5, 0,8,86, 0,8,22, 192,8,0,
+ 83,7,51, 0,8,118, 0,8,54, 0,9,204,
+ 81,7,15, 0,8,102, 0,8,38, 0,9,172,
+ 0,8,6, 0,8,134, 0,8,70, 0,9,236,
+ 80,7,9, 0,8,94, 0,8,30, 0,9,156,
+ 84,7,99, 0,8,126, 0,8,62, 0,9,220,
+ 82,7,27, 0,8,110, 0,8,46, 0,9,188,
+ 0,8,14, 0,8,142, 0,8,78, 0,9,252,
+ 96,7,256, 0,8,81, 0,8,17, 85,8,131,
+ 82,7,31, 0,8,113, 0,8,49, 0,9,194,
+ 80,7,10, 0,8,97, 0,8,33, 0,9,162,
+ 0,8,1, 0,8,129, 0,8,65, 0,9,226,
+ 80,7,6, 0,8,89, 0,8,25, 0,9,146,
+ 83,7,59, 0,8,121, 0,8,57, 0,9,210,
+ 81,7,17, 0,8,105, 0,8,41, 0,9,178,
+ 0,8,9, 0,8,137, 0,8,73, 0,9,242,
+ 80,7,4, 0,8,85, 0,8,21, 80,8,258,
+ 83,7,43, 0,8,117, 0,8,53, 0,9,202,
+ 81,7,13, 0,8,101, 0,8,37, 0,9,170,
+ 0,8,5, 0,8,133, 0,8,69, 0,9,234,
+ 80,7,8, 0,8,93, 0,8,29, 0,9,154,
+ 84,7,83, 0,8,125, 0,8,61, 0,9,218,
+ 82,7,23, 0,8,109, 0,8,45, 0,9,186,
+ 0,8,13, 0,8,141, 0,8,77, 0,9,250,
+ 80,7,3, 0,8,83, 0,8,19, 85,8,195,
+ 83,7,35, 0,8,115, 0,8,51, 0,9,198,
+ 81,7,11, 0,8,99, 0,8,35, 0,9,166,
+ 0,8,3, 0,8,131, 0,8,67, 0,9,230,
+ 80,7,7, 0,8,91, 0,8,27, 0,9,150,
+ 84,7,67, 0,8,123, 0,8,59, 0,9,214,
+ 82,7,19, 0,8,107, 0,8,43, 0,9,182,
+ 0,8,11, 0,8,139, 0,8,75, 0,9,246,
+ 80,7,5, 0,8,87, 0,8,23, 192,8,0,
+ 83,7,51, 0,8,119, 0,8,55, 0,9,206,
+ 81,7,15, 0,8,103, 0,8,39, 0,9,174,
+ 0,8,7, 0,8,135, 0,8,71, 0,9,238,
+ 80,7,9, 0,8,95, 0,8,31, 0,9,158,
+ 84,7,99, 0,8,127, 0,8,63, 0,9,222,
+ 82,7,27, 0,8,111, 0,8,47, 0,9,190,
+ 0,8,15, 0,8,143, 0,8,79, 0,9,254,
+ 96,7,256, 0,8,80, 0,8,16, 84,8,115,
+ 82,7,31, 0,8,112, 0,8,48, 0,9,193,
+
+ 80,7,10, 0,8,96, 0,8,32, 0,9,161,
+ 0,8,0, 0,8,128, 0,8,64, 0,9,225,
+ 80,7,6, 0,8,88, 0,8,24, 0,9,145,
+ 83,7,59, 0,8,120, 0,8,56, 0,9,209,
+ 81,7,17, 0,8,104, 0,8,40, 0,9,177,
+ 0,8,8, 0,8,136, 0,8,72, 0,9,241,
+ 80,7,4, 0,8,84, 0,8,20, 85,8,227,
+ 83,7,43, 0,8,116, 0,8,52, 0,9,201,
+ 81,7,13, 0,8,100, 0,8,36, 0,9,169,
+ 0,8,4, 0,8,132, 0,8,68, 0,9,233,
+ 80,7,8, 0,8,92, 0,8,28, 0,9,153,
+ 84,7,83, 0,8,124, 0,8,60, 0,9,217,
+ 82,7,23, 0,8,108, 0,8,44, 0,9,185,
+ 0,8,12, 0,8,140, 0,8,76, 0,9,249,
+ 80,7,3, 0,8,82, 0,8,18, 85,8,163,
+ 83,7,35, 0,8,114, 0,8,50, 0,9,197,
+ 81,7,11, 0,8,98, 0,8,34, 0,9,165,
+ 0,8,2, 0,8,130, 0,8,66, 0,9,229,
+ 80,7,7, 0,8,90, 0,8,26, 0,9,149,
+ 84,7,67, 0,8,122, 0,8,58, 0,9,213,
+ 82,7,19, 0,8,106, 0,8,42, 0,9,181,
+ 0,8,10, 0,8,138, 0,8,74, 0,9,245,
+ 80,7,5, 0,8,86, 0,8,22, 192,8,0,
+ 83,7,51, 0,8,118, 0,8,54, 0,9,205,
+ 81,7,15, 0,8,102, 0,8,38, 0,9,173,
+ 0,8,6, 0,8,134, 0,8,70, 0,9,237,
+ 80,7,9, 0,8,94, 0,8,30, 0,9,157,
+ 84,7,99, 0,8,126, 0,8,62, 0,9,221,
+ 82,7,27, 0,8,110, 0,8,46, 0,9,189,
+ 0,8,14, 0,8,142, 0,8,78, 0,9,253,
+ 96,7,256, 0,8,81, 0,8,17, 85,8,131,
+ 82,7,31, 0,8,113, 0,8,49, 0,9,195,
+ 80,7,10, 0,8,97, 0,8,33, 0,9,163,
+ 0,8,1, 0,8,129, 0,8,65, 0,9,227,
+ 80,7,6, 0,8,89, 0,8,25, 0,9,147,
+ 83,7,59, 0,8,121, 0,8,57, 0,9,211,
+ 81,7,17, 0,8,105, 0,8,41, 0,9,179,
+ 0,8,9, 0,8,137, 0,8,73, 0,9,243,
+ 80,7,4, 0,8,85, 0,8,21, 80,8,258,
+ 83,7,43, 0,8,117, 0,8,53, 0,9,203,
+ 81,7,13, 0,8,101, 0,8,37, 0,9,171,
+ 0,8,5, 0,8,133, 0,8,69, 0,9,235,
+ 80,7,8, 0,8,93, 0,8,29, 0,9,155,
+ 84,7,83, 0,8,125, 0,8,61, 0,9,219,
+ 82,7,23, 0,8,109, 0,8,45, 0,9,187,
+ 0,8,13, 0,8,141, 0,8,77, 0,9,251,
+ 80,7,3, 0,8,83, 0,8,19, 85,8,195,
+ 83,7,35, 0,8,115, 0,8,51, 0,9,199,
+ 81,7,11, 0,8,99, 0,8,35, 0,9,167,
+ 0,8,3, 0,8,131, 0,8,67, 0,9,231,
+ 80,7,7, 0,8,91, 0,8,27, 0,9,151,
+ 84,7,67, 0,8,123, 0,8,59, 0,9,215,
+ 82,7,19, 0,8,107, 0,8,43, 0,9,183,
+ 0,8,11, 0,8,139, 0,8,75, 0,9,247,
+ 80,7,5, 0,8,87, 0,8,23, 192,8,0,
+ 83,7,51, 0,8,119, 0,8,55, 0,9,207,
+ 81,7,15, 0,8,103, 0,8,39, 0,9,175,
+ 0,8,7, 0,8,135, 0,8,71, 0,9,239,
+ 80,7,9, 0,8,95, 0,8,31, 0,9,159,
+ 84,7,99, 0,8,127, 0,8,63, 0,9,223,
+ 82,7,27, 0,8,111, 0,8,47, 0,9,191,
+ 0,8,15, 0,8,143, 0,8,79, 0,9,255
+ };
+ static readonly int[] fixed_td = {
+ 80,5,1, 87,5,257, 83,5,17, 91,5,4097,
+ 81,5,5, 89,5,1025, 85,5,65, 93,5,16385,
+ 80,5,3, 88,5,513, 84,5,33, 92,5,8193,
+ 82,5,9, 90,5,2049, 86,5,129, 192,5,24577,
+ 80,5,2, 87,5,385, 83,5,25, 91,5,6145,
+ 81,5,7, 89,5,1537, 85,5,97, 93,5,24577,
+ 80,5,4, 88,5,769, 84,5,49, 92,5,12289,
+ 82,5,13, 90,5,3073, 86,5,193, 192,5,24577
+ };
+
+ // Tables for deflate from PKZIP's appnote.txt.
+ static readonly int[] cplens = { // Copy lengths for literal codes 257..285
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
+ };
+
+ // see note #13 above about 258
+ static readonly int[] cplext = { // Extra bits for literal codes 257..285
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+ 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112 // 112==invalid
+ };
+
+ static readonly int[] cpdist = { // Copy offsets for distance codes 0..29
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+ 8193, 12289, 16385, 24577
+ };
+
+ static readonly int[] cpdext = { // Extra bits for distance codes
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+ 12, 12, 13, 13};
+
+ // If BMAX needs to be larger than 16, then h and x[] should be uLong.
+ const int BMAX = 15; // maximum bit length of any code
+
+ int[] hn = null; // hufts used in space
+ int[] v = null; // work area for huft_build
+ int[] c = null; // bit length count table
+ int[] r = null; // table entry for structure assignment
+ int[] u = null; // table stack
+ int[] x = null; // bit offsets, then code stack
+
+ private ZLibStatus HuftBuild(int[] b, // code lengths in bits (all assumed <= BMAX)
+ int bindex,
+ int n, // number of codes (assumed <= 288)
+ int s, // number of simple-valued codes (0..s-1)
+ int[] d, // list of base values for non-simple codes
+ int[] e, // list of extra bits for non-simple codes
+ int[] t, // result: starting table
+ int[] m, // maximum lookup bits, returns actual
+ int[] hp,// space for trees
+ int[] hn,// hufts used in space
+ int[] v // working area: values in order of bit length
+ )
+ {
+ // Given a list of code lengths and a maximum table size, make a set of
+ // tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR
+ // if the given code set is incomplete (the tables are still built in this
+ // case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of
+ // lengths), or Z_MEM_ERROR if not enough memory.
+
+ int a; // counter for codes of length k
+ int f; // i repeats in table every f entries
+ int g; // maximum code length
+ int h; // table level
+ int i; // counter, current code
+ int j; // counter
+ int k; // number of bits in current code
+ int l; // bits per table (returned in m)
+ int mask; // (1 << w) - 1, to avoid cc -O bug on HP
+ int p; // pointer into c[], b[], or v[]
+ int q; // points to current table
+ int w; // bits before this table == (l * h)
+ int xp; // pointer into x
+ int y; // number of dummy codes added
+ int z; // number of entries in current table
+
+ // Generate counts for each bit length
+
+ p = 0; i = n;
+ do
+ {
+ c[b[bindex + p]]++; p++; i--; // assume all entries <= BMAX
+ } while (i != 0);
+
+ if (c[0] == n)
+ { // null input--all zero length codes
+ t[0] = -1;
+ m[0] = 0;
+ return ZLibStatus.Z_OK;
+ }
+
+ // Find minimum and maximum length, bound *m by those
+ l = m[0];
+ for (j = 1; j <= BMAX; j++)
+ if (c[j] != 0) break;
+ k = j; // minimum code length
+ if (l < j)
+ {
+ l = j;
+ }
+ for (i = BMAX; i != 0; i--)
+ {
+ if (c[i] != 0) break;
+ }
+ g = i; // maximum code length
+ if (l > i)
+ {
+ l = i;
+ }
+ m[0] = l;
+
+ // Adjust last length count to fill out codes, if needed
+ for (y = 1 << j; j < i; j++, y <<= 1)
+ {
+ if ((y -= c[j]) < 0)
+ {
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ }
+ if ((y -= c[i]) < 0)
+ {
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ c[i] += y;
+
+ // Generate starting offsets into the value table for each length
+ x[1] = j = 0;
+ p = 1; xp = 2;
+ while (--i != 0)
+ { // note that i == g from above
+ x[xp] = (j += c[p]);
+ xp++;
+ p++;
+ }
+
+ // Make a table of values in order of bit lengths
+ i = 0; p = 0;
+ do
+ {
+ if ((j = b[bindex + p]) != 0)
+ {
+ v[x[j]++] = i;
+ }
+ p++;
+ }
+ while (++i < n);
+ n = x[g]; // set n to length of v
+
+ // Generate the Huffman codes and for each, make the table entries
+ x[0] = i = 0; // first Huffman code is zero
+ p = 0; // grab values in bit order
+ h = -1; // no tables yet--level -1
+ w = -l; // bits decoded == (l * h)
+ u[0] = 0; // just to keep compilers happy
+ q = 0; // ditto
+ z = 0; // ditto
+
+ // go through the bit lengths (k already is bits in shortest code)
+ for (; k <= g; k++)
+ {
+ a = c[k];
+ while (a-- != 0)
+ {
+ // here i is the Huffman code of length k bits for value *p
+ // make tables up to required level
+ while (k > w + l)
+ {
+ h++;
+ w += l; // previous table always l bits
+ // compute minimum size table less than or equal to l bits
+ z = g - w;
+ z = (z > l) ? l : z; // table size upper limit
+ if ((f = 1 << (j = k - w)) > a + 1)
+ { // try a k-w bit table
+ // too few codes for k-w bit table
+ f -= a + 1; // deduct codes from patterns left
+ xp = k;
+ if (j < z)
+ {
+ while (++j < z)
+ { // try smaller tables up to z bits
+ if ((f <<= 1) <= c[++xp])
+ break; // enough codes to use up j bits
+ f -= c[xp]; // else deduct codes from patterns
+ }
+ }
+ }
+ z = 1 << j; // table entries for j-bit table
+
+ // allocate new table
+ if (hn[0] + z > MANY)
+ { // (note: doesn't matter for fixed)
+ return ZLibStatus.Z_DATA_ERROR; // overflow of MANY
+ }
+ u[h] = q = /*hp+*/ hn[0]; // DEBUG
+ hn[0] += z;
+
+ // connect to last table, if there is one
+ if (h != 0)
+ {
+ x[h] = i; // save pattern for backing up
+ r[0] = (byte)j; // bits in this table
+ r[1] = (byte)l; // bits to dump before this table
+ j = i >> (w - l);
+ r[2] = (int)(q - u[h - 1] - j); // offset to this table
+ System.Array.Copy(r, 0, hp, (u[h - 1] + j) * 3, 3); // connect to last table
+ }
+ else
+ {
+ t[0] = q; // first table is returned result
+ }
+ }
+
+ // set up table entry in r
+ r[1] = (byte)(k - w);
+ if (p >= n)
+ {
+ r[0] = 128 + 64; // out of values--invalid code
+ }
+ else if (v[p] < s)
+ {
+ r[0] = (byte)(v[p] < 256 ? 0 : 32 + 64); // 256 is end-of-block
+ r[2] = v[p++]; // simple code is just the value
+ }
+ else
+ {
+ r[0] = (byte)(e[v[p] - s] + 16 + 64); // non-simple--look up in lists
+ r[2] = d[v[p++] - s];
+ }
+
+ // fill code-like entries with r
+ f = 1 << (k - w);
+ for (j = i >> w; j < z; j += f)
+ {
+ System.Array.Copy(r, 0, hp, (q + j) * 3, 3);
+ }
+
+ // backwards increment the k-bit code i
+ for (j = 1 << (k - 1); (i & j) != 0; j >>= 1)
+ {
+ i ^= j;
+ }
+ i ^= j;
+
+ // backup over finished tables
+ mask = (1 << w) - 1; // needed on HP, cc -O bug
+ while ((i & mask) != x[h])
+ {
+ h--; // don't need to update q
+ w -= l;
+ mask = (1 << w) - 1;
+ }
+ }
+ }
+ // Return Z_BUF_ERROR if we were given an incomplete table
+ return y != 0 && g != 1 ? ZLibStatus.Z_BUF_ERROR : ZLibStatus.Z_OK;
+ }
+
+ internal ZLibStatus InflateTreesBits(int[] c, // 19 code lengths
+ int[] bb, // bits tree desired/actual depth
+ int[] tb, // bits tree result
+ int[] hp, // space for trees
+ ZStream z // for messages
+ )
+ {
+ ZLibStatus result;
+ InitWorkArea(19);
+ hn[0] = 0;
+ result = HuftBuild(c, 0, 19, 19, null, null, tb, bb, hp, hn, v);
+
+ if (result == ZLibStatus.Z_DATA_ERROR)
+ {
+ z.msg = "oversubscribed dynamic bit lengths tree";
+ }
+ else if (result == ZLibStatus.Z_BUF_ERROR || bb[0] == 0)
+ {
+ z.msg = "incomplete dynamic bit lengths tree";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ return result;
+ }
+
+ internal ZLibStatus InflateTreesDynamic(int nl, // number of literal/length codes
+ int nd, // number of distance codes
+ int[] c, // that many (total) code lengths
+ int[] bl, // literal desired/actual bit depth
+ int[] bd, // distance desired/actual bit depth
+ int[] tl, // literal/length tree result
+ int[] td, // distance tree result
+ int[] hp, // space for trees
+ ZStream z // for messages
+ )
+ {
+ ZLibStatus result;
+
+ // build literal/length tree
+ InitWorkArea(288);
+ hn[0] = 0;
+ result = HuftBuild(c, 0, nl, 257, cplens, cplext, tl, bl, hp, hn, v);
+ if (result != ZLibStatus.Z_OK || bl[0] == 0)
+ {
+ if (result == ZLibStatus.Z_DATA_ERROR)
+ {
+ z.msg = "oversubscribed literal/length tree";
+ }
+ else if (result != ZLibStatus.Z_MEM_ERROR)
+ {
+ z.msg = "incomplete literal/length tree";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ return result;
+ }
+
+ // build distance tree
+ InitWorkArea(288);
+ result = HuftBuild(c, nl, nd, 0, cpdist, cpdext, td, bd, hp, hn, v);
+
+ if (result != ZLibStatus.Z_OK || (bd[0] == 0 && nl > 257))
+ {
+ if (result == ZLibStatus.Z_DATA_ERROR)
+ {
+ z.msg = "oversubscribed distance tree";
+ }
+ else if (result == ZLibStatus.Z_BUF_ERROR)
+ {
+ z.msg = "incomplete distance tree";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ else if (result != ZLibStatus.Z_MEM_ERROR)
+ {
+ z.msg = "empty distance tree with lengths";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ return result;
+ }
+
+ return ZLibStatus.Z_OK;
+ }
+
+ internal static ZLibStatus InflateTreesFixed(int[] bl, //literal desired/actual bit depth
+ int[] bd, //distance desired/actual bit depth
+ int[][] tl,//literal/length tree result
+ int[][] td,//distance tree result
+ ZStream z //for memory allocation
+ )
+ {
+ bl[0] = fixed_bl;
+ bd[0] = fixed_bd;
+ tl[0] = fixed_tl;
+ td[0] = fixed_td;
+ return ZLibStatus.Z_OK;
+ }
+
+ private void InitWorkArea(int vsize)
+ {
+ if (hn == null)
+ {
+ hn = new int[1];
+ v = new int[vsize];
+ c = new int[BMAX + 1];
+ r = new int[3];
+ u = new int[BMAX];
+ x = new int[BMAX + 1];
+ }
+ if (v.Length < vsize) { v = new int[vsize]; }
+ for (int i = 0; i < vsize; i++) { v[i] = 0; }
+ for (int i = 0; i < BMAX + 1; i++) { c[i] = 0; }
+ for (int i = 0; i < 3; i++) { r[i] = 0; }
+ // for(int i=0; i
+ /// Gets the static tree or null
+ ///
+ ///
+ /// The static_tree.
+ ///
+ public short[] TreeData { get; private set; }
+
+ ///
+ /// Gets the extra bits for each code or null.
+ ///
+ ///
+ /// The extra bits.
+ ///
+ public int[] ExtraBits { get; private set; }
+
+ ///
+ /// Gets the base index for extra_bits.
+ ///
+ ///
+ /// The extra base.
+ ///
+ public int ExtraBase { get; private set; }
+
+ ///
+ /// Gets the max number of elements in the tree.
+ ///
+ ///
+ /// The elements.
+ ///
+ public int Elements { get; private set; }
+
+ ///
+ /// Gets the max bit length for the codes.
+ ///
+ ///
+ /// The length of the max.
+ ///
+ public int MaxLength { get; private set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The tree data.
+ /// The extra bits.
+ /// The extra base.
+ /// The elements.
+ /// Length of the max.
+ public StaticTree(short[] treeData, int[] extraBits, int extraBase, int elements, int maxLength)
+ {
+ this.TreeData = treeData;
+ this.ExtraBits = extraBits;
+ this.ExtraBase = extraBase;
+ this.Elements = elements;
+ this.MaxLength = maxLength;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Version.6/Tree.cs b/Renci.SshNet/Compression/Version.6/Tree.cs
new file mode 100644
index 0000000..d2142c9
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.6/Tree.cs
@@ -0,0 +1,334 @@
+using System;
+/*
+ * $Id: Tree.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+ internal sealed class Tree
+ {
+ private const int MAX_BITS = 15;
+
+ private const int LITERALS = 256;
+
+ private const int LENGTH_CODES = 29;
+
+ private const int L_CODES = (LITERALS + 1 + LENGTH_CODES);
+
+ private const int HEAP_SIZE = (2 * L_CODES + 1);
+
+ private static byte[] _dist_code = {
+ 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8,
+ 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17,
+ 18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
+ 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
+ };
+
+
+ ///
+ /// The corresponding static tree
+ ///
+ private StaticTree _staticTree;
+
+ ///
+ /// The dynamic tree
+ ///
+ private short[] _dynamicTree;
+
+ ///
+ /// Gets the largest code with non zero frequency.
+ ///
+ ///
+ /// The max_code.
+ ///
+ public int LargestCode { get; private set; }
+
+ public void Init(short[] dynamicTree, StaticTree staticTree)
+ {
+ this._staticTree = staticTree;
+ this._dynamicTree = dynamicTree;
+ }
+
+ ///
+ /// Mapping from a distance to a distance code. dist is the distance - 1 and must not have side effects. _dist_code[256] and _dist_code[257] are never used.
+ ///
+ /// The dist.
+ ///
+ public static int DistanceCode(int dist)
+ {
+ // TODO: Under multiple port forward after more then 50K requests gets index out of range
+ return ((dist) < 256 ? _dist_code[dist] : _dist_code[256 + ((dist) >> 7)]);
+ }
+
+ ///
+ /// Construct one Huffman tree and assigns the code bit strings and lengths. Update the total bit length for the current block.
+ ///
+ /// The s.
+ public void BuildTree(Deflate s)
+ {
+ short[] tree = _dynamicTree;
+ short[] stree = _staticTree.TreeData;
+ int elems = _staticTree.Elements;
+ int n, m; // iterate over heap elements
+ int max_code = -1; // largest code with non zero frequency
+ int node; // new node being created
+
+ // Construct the initial heap, with least frequent element in
+ // heap[1]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
+ // heap[0] is not used.
+ s.heap_len = 0;
+ s.heap_max = HEAP_SIZE;
+
+ for (n = 0; n < elems; n++)
+ {
+ if (tree[n * 2] != 0)
+ {
+ s.heap[++s.heap_len] = max_code = n;
+ s.depth[n] = 0;
+ }
+ else
+ {
+ tree[n * 2 + 1] = 0;
+ }
+ }
+
+ // The pkzip format requires that at least one distance code exists,
+ // and that at least one bit should be sent even if there is only one
+ // possible code. So to avoid special checks later on we force at least
+ // two codes of non zero frequency.
+ while (s.heap_len < 2)
+ {
+ node = s.heap[++s.heap_len] = (max_code < 2 ? ++max_code : 0);
+ tree[node * 2] = 1;
+ s.depth[node] = 0;
+ s.opt_len--; if (stree != null) s.static_len -= stree[node * 2 + 1];
+ // node is 0 or 1 so it does not have extra bits
+ }
+ this.LargestCode = max_code;
+
+ // The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
+ // establish sub-heaps of increasing lengths:
+
+ for (n = s.heap_len / 2; n >= 1; n--)
+ s.pqdownheap(tree, n);
+
+ // Construct the Huffman tree by repeatedly combining the least two
+ // frequent nodes.
+
+ node = elems; // next internal node of the tree
+ do
+ {
+ // n = node of least frequency
+ n = s.heap[1];
+ s.heap[1] = s.heap[s.heap_len--];
+ s.pqdownheap(tree, 1);
+ m = s.heap[1]; // m = node of next least frequency
+
+ s.heap[--s.heap_max] = n; // keep the nodes sorted by frequency
+ s.heap[--s.heap_max] = m;
+
+ // Create a new node father of n and m
+ tree[node * 2] = (short)(tree[n * 2] + tree[m * 2]);
+ s.depth[node] = (byte)(System.Math.Max(s.depth[n], s.depth[m]) + 1);
+ tree[n * 2 + 1] = tree[m * 2 + 1] = (short)node;
+
+ // and insert the new node in the heap
+ s.heap[1] = node++;
+ s.pqdownheap(tree, 1);
+ }
+ while (s.heap_len >= 2);
+
+ s.heap[--s.heap_max] = s.heap[1];
+
+ // At this point, the fields freq and dad are set. We can now
+ // generate the bit lengths.
+
+ ComputeBitLength(s);
+
+ // The field len is now set, we can generate the bit codes
+ GenerateCodes(tree, max_code, s.bl_count);
+ }
+
+ ///
+ /// Compute the optimal bit lengths for a tree and update the total bit length for the current block.
+ ///
+ /// The s.
+ private void ComputeBitLength(Deflate s)
+ {
+ short[] tree = _dynamicTree;
+ short[] stree = _staticTree.TreeData;
+ int[] extra = _staticTree.ExtraBits;
+ int based = _staticTree.ExtraBase;
+ int max_length = _staticTree.MaxLength;
+ int h; // heap index
+ int n, m; // iterate over the tree elements
+ int bits; // bit length
+ int xbits; // extra bits
+ short f; // frequency
+ int overflow = 0; // number of elements with bit length too large
+
+ for (bits = 0; bits <= MAX_BITS; bits++) s.bl_count[bits] = 0;
+
+ // In a first pass, compute the optimal bit lengths (which may
+ // overflow in the case of the bit length tree).
+ tree[s.heap[s.heap_max] * 2 + 1] = 0; // root of the heap
+
+ for (h = s.heap_max + 1; h < HEAP_SIZE; h++)
+ {
+ n = s.heap[h];
+ bits = tree[tree[n * 2 + 1] * 2 + 1] + 1;
+ if (bits > max_length) { bits = max_length; overflow++; }
+ tree[n * 2 + 1] = (short)bits;
+ // We overwrite tree[n*2+1] which is no longer needed
+
+ if (n > LargestCode) continue; // not a leaf node
+
+ s.bl_count[bits]++;
+ xbits = 0;
+ if (n >= based) xbits = extra[n - based];
+ f = tree[n * 2];
+ s.opt_len += f * (bits + xbits);
+ if (stree != null) s.static_len += f * (stree[n * 2 + 1] + xbits);
+ }
+ if (overflow == 0) return;
+
+ // This happens for example on obj2 and pic of the Calgary corpus
+ // Find the first bit length which could increase:
+ do
+ {
+ bits = max_length - 1;
+ while (s.bl_count[bits] == 0) bits--;
+ s.bl_count[bits]--; // move one leaf down the tree
+ s.bl_count[bits + 1] += 2; // move one overflow item as its brother
+ s.bl_count[max_length]--;
+ // The brother of the overflow item also moves one step up,
+ // but this does not affect bl_count[max_length]
+ overflow -= 2;
+ }
+ while (overflow > 0);
+
+ for (bits = max_length; bits != 0; bits--)
+ {
+ n = s.bl_count[bits];
+ while (n != 0)
+ {
+ m = s.heap[--h];
+ if (m > LargestCode) continue;
+ if (tree[m * 2 + 1] != bits)
+ {
+ s.opt_len += (int)(((long)bits - (long)tree[m * 2 + 1]) * (long)tree[m * 2]);
+ tree[m * 2 + 1] = (short)bits;
+ }
+ n--;
+ }
+ }
+ }
+
+ ///
+ /// Generate the codes for a given tree and bit counts (which need not be optimal).
+ ///
+ /// The tree to decorate.
+ /// The largest code with non zero frequency.
+ /// The number of codes at each bit length.
+ private static void GenerateCodes(short[] tree, int max_code, short[] bl_count)
+ {
+ short[] next_code = new short[MAX_BITS + 1]; // next code value for each bit length
+ short code = 0; // running code value
+ int bits; // bit index
+ int n; // code index
+
+ // The distribution counts are first used to generate the code values
+ // without bit reversal.
+ for (bits = 1; bits <= MAX_BITS; bits++)
+ {
+ next_code[bits] = code = (short)((code + bl_count[bits - 1]) << 1);
+ }
+
+ // Check that the bit counts in bl_count are consistent. The last code
+ // must be all ones.
+ //Assert (code + bl_count[MAX_BITS]-1 == (1<
+ /// Reverse the first len bits of a code, using straightforward code (a faster method would use a table)
+ ///
+ /// The value to invert.
+ /// The bit length.
+ ///
+ private static int BiReverse(int code, int len)
+ {
+ int res = 0;
+ do
+ {
+ res |= code & 1;
+ code >>= 1;
+ res <<= 1;
+ }
+ while (--len > 0);
+ return res >> 1;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Version.6/ZInputStream.cs b/Renci.SshNet/Compression/Version.6/ZInputStream.cs
new file mode 100644
index 0000000..2e5aaa6
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.6/ZInputStream.cs
@@ -0,0 +1,205 @@
+/*
+Copyright (c) 2001 Lapo Luchini.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS
+OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+/* This file is a port of jzlib v1.0.7, com.jcraft.jzlib.ZInputStream.java
+ */
+
+using Renci.SshNet.Compression;
+using System;
+using System.Diagnostics;
+using System.IO;
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+ public class ZInputStream : Stream
+ {
+ private const int BufferSize = 512;
+ //private ZStream z = new ZStream();
+ private ICompressor _compressor;
+
+ // TODO Allow custom buf
+ private byte[] _buffer = new byte[BufferSize];
+ private CompressionMode _compressionMode;
+ private Stream _input;
+ private bool _isClosed;
+ private bool _noMoreInput = false;
+
+ public FlushType FlushMode { get; private set; }
+
+ public ZInputStream()
+ {
+ this.FlushMode = FlushType.Z_PARTIAL_FLUSH;
+ }
+
+ public ZInputStream(Stream input)
+ : this(input, false)
+ {
+ }
+
+ public ZInputStream(Stream input, bool nowrap)
+ : this()
+ {
+ Debug.Assert(input.CanRead);
+
+ this._input = input;
+ this._compressor = new Inflate(nowrap);
+ //this._compressor.inflateInit(nowrap);
+ this._compressionMode = CompressionMode.Decompress;
+ this._compressor.next_in = _buffer;
+ this._compressor.next_in_index = 0;
+ this._compressor.avail_in = 0;
+ }
+
+ public ZInputStream(Stream input, CompressionLevel level)
+ : this()
+ {
+ Debug.Assert(input.CanRead);
+
+ this._input = input;
+ this._compressor = new Deflate(level);
+ //this._compressor.deflateInit(level);
+ this._compressionMode = CompressionMode.Compress;
+ this._compressor.next_in = _buffer;
+ this._compressor.next_in_index = 0;
+ this._compressor.avail_in = 0;
+ }
+
+ #region Stream implementation
+
+ public sealed override bool CanRead
+ {
+ get { return !_isClosed; }
+ }
+
+ public sealed override bool CanSeek
+ {
+ get { return false; }
+ }
+
+ public sealed override bool CanWrite
+ {
+ get { return false; }
+ }
+
+ public override void Flush()
+ {
+ }
+
+ public override long Length
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ public override long Position
+ {
+ get { throw new NotSupportedException(); }
+ set { throw new NotSupportedException(); }
+ }
+
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ if (count == 0)
+ return 0;
+
+ this._compressor.next_out = buffer;
+ this._compressor.next_out_index = offset;
+ this._compressor.avail_out = count;
+
+ ZLibStatus err = ZLibStatus.Z_OK;
+ do
+ {
+ if (this._compressor.avail_in == 0 && !_noMoreInput)
+ {
+ // if buffer is empty and more input is available, refill it
+ this._compressor.next_in_index = 0;
+ this._compressor.avail_in = _input.Read(_buffer, 0, _buffer.Length); //(bufsize 0 || this._compressor.avail_out == 0);
+ }
+
+ #endregion
+
+ public override void Close()
+ {
+ if (this._isClosed)
+ return;
+
+ try
+ {
+ try
+ {
+ Finish();
+ }
+ catch (IOException)
+ {
+ // Ignore
+ }
+ }
+ finally
+ {
+ this._isClosed = true;
+ End();
+ _output.Close();
+ _output = null;
+ }
+ }
+
+ private void End()
+ {
+ if (this._compressor == null)
+ return;
+ switch (this._compressionMode)
+ {
+ case CompressionMode.Compress:
+ this._compressor.deflateEnd();
+ break;
+ case CompressionMode.Decompress:
+ this._compressor.inflateEnd();
+ break;
+ default:
+ break;
+ }
+
+ this._compressor.free();
+ this._compressor = null;
+ }
+
+ private void Finish()
+ {
+ do
+ {
+ this._compressor.next_out = _buffer;
+ this._compressor.next_out_index = 0;
+ this._compressor.avail_out = _buffer.Length;
+
+ var err = ZLibStatus.Z_OK;
+ switch (this._compressionMode)
+ {
+ case CompressionMode.Compress:
+ err = this._compressor.deflate(FlushType.Z_FINISH);
+ break;
+ case CompressionMode.Decompress:
+ err = this._compressor.inflate(FlushType.Z_FINISH);
+ break;
+ default:
+ break;
+ }
+
+ if (err != ZLibStatus.Z_STREAM_END && err != ZLibStatus.Z_OK)
+ // TODO
+ // throw new ZStreamException((compress?"de":"in")+"flating: "+z.msg);
+ //throw new IOException((_compressionMode ? "de" : "in") + "flating: " + z.msg);
+ throw new IOException(string.Format("{0}ion error: {1}", _compressionMode, this._compressor.msg));
+
+ int count = _buffer.Length - this._compressor.avail_out;
+ if (count > 0)
+ {
+ _output.Write(_buffer, 0, count);
+ }
+ }
+ while (this._compressor.avail_in > 0 || this._compressor.avail_out == 0);
+
+ Flush();
+ }
+ }
+}
diff --git a/Renci.SshNet/Compression/Version.6/ZStream.cs b/Renci.SshNet/Compression/Version.6/ZStream.cs
new file mode 100644
index 0000000..6269735
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.6/ZStream.cs
@@ -0,0 +1,73 @@
+using System;
+using System.IO;
+/*
+ * $Id: ZStream.cs,v 1.1 2006-07-31 13:59:26 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public abstract class ZStream
+ {
+
+ protected const int MAX_WBITS = 15; // 32K LZ77 window
+ protected const int DEF_WBITS = MAX_WBITS;
+
+ private const int MAX_MEM_LEVEL = 9;
+
+ public byte[] next_in { get; set; } // next input byte
+ public int next_in_index { get; set; }
+ public int avail_in { get; set; } // number of bytes available at next_in
+ public long total_in { get; set; } // total nb of input bytes read so far
+
+ public byte[] next_out { get; set; } // next output byte should be put there
+ public int next_out_index { get; set; }
+ public int avail_out { get; set; } // remaining free space at next_out
+ public long total_out { get; set; } // total nb of bytes output so far
+
+ public String msg { get; set; }
+
+ internal BlockType data_type; // best guess about the data type: ascii or binary
+
+ public long adler;
+
+ public void free()
+ {
+ next_in = null;
+ next_out = null;
+ msg = null;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Version.6/Zlib.cs b/Renci.SshNet/Compression/Version.6/Zlib.cs
new file mode 100644
index 0000000..5890675
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.6/Zlib.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Represents "zlib" compression implementation
+ ///
+ internal class Zlib : Compressor
+ {
+ ///
+ /// Gets algorithm name.
+ ///
+ public override string Name
+ {
+ get { return "zlib"; }
+ }
+
+ ///
+ /// Initializes the algorithm
+ ///
+ /// The session.
+ public override void Init(Session session)
+ {
+ base.Init(session);
+ this.IsActive = true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Version.6/ZlibOpenSsh.cs b/Renci.SshNet/Compression/Version.6/ZlibOpenSsh.cs
new file mode 100644
index 0000000..f82a4c0
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.6/ZlibOpenSsh.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Represents "zlib@openssh.org" compression implementation
+ ///
+ public class ZlibOpenSsh : Compressor
+ {
+ ///
+ /// Gets algorithm name.
+ ///
+ public override string Name
+ {
+ get { return "zlib@openssh.org"; }
+ }
+
+ ///
+ /// Initializes the algorithm
+ ///
+ /// The session.
+ public override void Init(Session session)
+ {
+ base.Init(session);
+
+ session.UserAuthenticationSuccessReceived += Session_UserAuthenticationSuccessReceived;
+ }
+
+ private void Session_UserAuthenticationSuccessReceived(object sender, MessageEventArgs e)
+ {
+ this.IsActive = true;
+ this.Session.UserAuthenticationSuccessReceived -= Session_UserAuthenticationSuccessReceived;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Version.6/ZlibStream.cs b/Renci.SshNet/Compression/Version.6/ZlibStream.cs
new file mode 100644
index 0000000..fb5f9d2
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.6/ZlibStream.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.IO;
+using Org.BouncyCastle.Utilities.Zlib;
+
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Implements Zlib compression algorithm.
+ ///
+ public class ZlibStream
+ {
+ private readonly Stream _baseStream;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The stream.
+ /// The mode.
+ public ZlibStream(Stream stream, CompressionMode mode)
+ {
+ switch (mode)
+ {
+ case CompressionMode.Compress:
+ //this._baseStream = new ZOutputStream(stream, CompressionLevel.Z_DEFAULT_COMPRESSION);
+ this._baseStream = new ZOutputStream(stream, CompressionLevel.Z_DEFAULT_COMPRESSION);
+ break;
+ case CompressionMode.Decompress:
+ this._baseStream = new ZOutputStream(stream);
+ break;
+ default:
+ break;
+ }
+
+ //this._baseStream.FlushMode = Ionic.Zlib.FlushType.Partial;
+ }
+
+ ///
+ /// Writes the specified buffer.
+ ///
+ /// The buffer.
+ /// The offset.
+ /// The count.
+ public void Write(byte[] buffer, int offset, int count)
+ {
+ this._baseStream.Write(buffer, offset, count);
+ }
+ }
+}
diff --git a/Renci.SshNet/Compression/Version.7/Adler32.cs b/Renci.SshNet/Compression/Version.7/Adler32.cs
new file mode 100644
index 0000000..c132fa9
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.7/Adler32.cs
@@ -0,0 +1,95 @@
+using System;
+/*
+ * $Id: Adler32.cs,v 1.1 2006-07-31 13:59:25 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ internal static class Adler32
+ {
+
+ // largest prime smaller than 65536
+ private const int BASE = 65521;
+ // NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
+ private const int NMAX = 5552;
+
+ internal static long adler32(long adler, byte[] buf, int index, int len)
+ {
+ if (buf == null) { return 1L; }
+
+ long s1 = adler & 0xffff;
+ long s2 = (adler >> 16) & 0xffff;
+ int k;
+
+ while (len > 0)
+ {
+ k = len < NMAX ? len : NMAX;
+ len -= k;
+ while (k >= 16)
+ {
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ k -= 16;
+ }
+ if (k != 0)
+ {
+ do
+ {
+ s1 += buf[index++] & 0xff; s2 += s1;
+ }
+ while (--k != 0);
+ }
+ s1 %= BASE;
+ s2 %= BASE;
+ }
+ return (s2 << 16) | s1;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Version.7/CompressionMode.cs b/Renci.SshNet/Compression/Version.7/CompressionMode.cs
new file mode 100644
index 0000000..1577e0b
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.7/CompressionMode.cs
@@ -0,0 +1,18 @@
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Specifies compression modes
+ ///
+ public enum CompressionMode
+ {
+ ///
+ /// Specifies that content should be compressed.
+ ///
+ Compress = 0,
+
+ ///
+ /// Specifies that content should be decompressed.
+ ///
+ Decompress = 1,
+ }
+}
diff --git a/Renci.SshNet/Compression/Version.7/Compressor.cs b/Renci.SshNet/Compression/Version.7/Compressor.cs
new file mode 100644
index 0000000..1479bb6
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.7/Compressor.cs
@@ -0,0 +1,151 @@
+using System.Collections.Generic;
+using Renci.SshNet.Security;
+using System.IO;
+using System;
+
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Represents base class for compression algorithm implementation
+ ///
+ public abstract class Compressor : Algorithm, IDisposable
+ {
+ private readonly ZlibStream _compressor;
+ private readonly ZlibStream _decompressor;
+
+ private MemoryStream _compressorStream;
+ private MemoryStream _decompressorStream;
+
+ ///
+ /// Gets or sets a value indicating whether compression is active.
+ ///
+ ///
+ /// true if compression is active; otherwise, false.
+ ///
+ protected bool IsActive { get; set; }
+
+ ///
+ /// Gets the session.
+ ///
+ protected Session Session { get; private set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ 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);
+ }
+
+ ///
+ /// Initializes the algorithm
+ ///
+ /// The session.
+ public virtual void Init(Session session)
+ {
+ this.Session = session;
+ }
+
+ ///
+ /// Compresses the specified data.
+ ///
+ /// Data to compress.
+ /// Compressed 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();
+ }
+
+ ///
+ /// Decompresses the specified data.
+ ///
+ /// Compressed data.
+ /// Decompressed 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;
+
+ ///
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged ResourceMessages.
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Releases unmanaged and - optionally - managed resources
+ ///
+ /// true to release both managed and unmanaged resources; false to release only unmanaged ResourceMessages.
+ 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;
+ }
+ }
+
+ ///
+ /// Releases unmanaged resources and performs other cleanup operations before the
+ /// is reclaimed by garbage collection.
+ ///
+ ~Compressor()
+ {
+ // Do not re-create Dispose clean-up code here.
+ // Calling Dispose(false) is optimal in terms of
+ // readability and maintainability.
+ Dispose(false);
+ }
+
+ #endregion
+ }
+}
diff --git a/Renci.SshNet/Compression/Version.7/Deflate.cs b/Renci.SshNet/Compression/Version.7/Deflate.cs
new file mode 100644
index 0000000..ea08bfa
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.7/Deflate.cs
@@ -0,0 +1,2394 @@
+using System;
+using System.Collections.Generic;
+/*
+ * $Id: Deflate.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public enum BlockType : byte
+ {
+ Z_BINARY = 0,
+ Z_ASCII = 1,
+ Z_UNKNOWN = 2
+ }
+
+ public enum DefalteFlavor : int
+ {
+ STORED = 0,
+ FAST = 1,
+ SLOW = 2
+ }
+
+ public sealed class Deflate : ZStream, ICompressor
+ {
+ private const int MAX_MEM_LEVEL = 9;
+
+ private const int Z_DEFAULT_COMPRESSION = -1;
+
+ private const int MAX_WBITS = 15; // 32K LZ77 window
+
+ private const int DEF_MEM_LEVEL = 8;
+
+ ///
+ /// The Bit length codes must not exceed MAX_BL_BITS bits
+ ///
+ private const int MAX_BL_BITS = 7;
+
+ // block not completed, need more input or more output
+ private const int NeedMore = 0;
+
+ // block flush performed
+ private const int BlockDone = 1;
+
+ // finish started, need only more output at next deflate
+ private const int FinishStarted = 2;
+
+ // finish done, accept no more input or output
+ private const int FinishDone = 3;
+
+ // preset dictionary flag in zlib header
+ private const int PRESET_DICT = 0x20;
+
+ private const int Z_VERSION_ERROR = -6;
+
+ private const int INIT_STATE = 42;
+ private const int BUSY_STATE = 113;
+ private const int FINISH_STATE = 666;
+
+ // The deflate compression method
+ private const int Z_DEFLATED = 8;
+
+ private const int STORED_BLOCK = 0;
+ private const int STATIC_TREES = 1;
+ private const int DYN_TREES = 2;
+
+ private const int Buf_size = 8 * 2;
+
+ // repeat previous bit length 3-6 times (2 bits of repeat count)
+ private const int REP_3_6 = 16;
+
+ // repeat a zero length 3-10 times (3 bits of repeat count)
+ private const int REPZ_3_10 = 17;
+
+ // repeat a zero length 11-138 times (7 bits of repeat count)
+ private const int REPZ_11_138 = 18;
+
+ private const int MIN_MATCH = 3;
+ private const int MAX_MATCH = 258;
+ private const int MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1);
+
+ private const int MAX_BITS = 15;
+ private const int D_CODES = 30;
+ private const int BL_CODES = 19;
+ private const int LENGTH_CODES = 29;
+ private const int LITERALS = 256;
+ private const int L_CODES = (LITERALS + 1 + LENGTH_CODES);
+ private const int HEAP_SIZE = (2 * L_CODES + 1);
+
+ private const int END_BLOCK = 256;
+
+ private static readonly IDictionary config_table = new Dictionary() {
+ {(CompressionLevel)0, new Config(0, 0, 0, 0, DefalteFlavor.STORED)},
+ {(CompressionLevel)1, new Config(4, 4, 8, 4, DefalteFlavor.FAST)},
+ {(CompressionLevel)2, new Config(4, 5, 16, 8, DefalteFlavor.FAST)},
+ {(CompressionLevel)3, new Config(4, 6, 32, 32, DefalteFlavor.FAST)},
+
+ {(CompressionLevel)4, new Config(4, 4, 16, 16, DefalteFlavor.SLOW)},
+ {(CompressionLevel)5, new Config(8, 16, 32, 32, DefalteFlavor.SLOW)},
+ {(CompressionLevel)6, new Config(8, 16, 128, 128, DefalteFlavor.SLOW)},
+ {(CompressionLevel)7, new Config(8, 32, 128, 256, DefalteFlavor.SLOW)},
+ {(CompressionLevel)8, new Config(32, 128, 258, 1024, DefalteFlavor.SLOW)},
+ {(CompressionLevel)9, new Config(32, 258, 258, 4096, DefalteFlavor.SLOW)},
+ };
+
+ #region Static definitions
+
+ private static readonly byte[] _length_code ={
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12,
+ 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
+ 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
+ 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
+ };
+
+ private static readonly int[] base_length = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
+ 64, 80, 96, 112, 128, 160, 192, 224, 0
+ };
+
+ private static readonly int[] base_dist = {
+ 0, 1, 2, 3, 4, 6, 8, 12, 16, 24,
+ 32, 48, 64, 96, 128, 192, 256, 384, 512, 768,
+ 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576
+ };
+
+ // extra bits for each length code
+ private static readonly int[] extra_lbits ={
+ 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0
+ };
+
+ // extra bits for each distance code
+ private static readonly int[] extra_dbits ={
+ 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13
+ };
+
+ // extra bits for each bit length code
+ private static readonly int[] extra_blbits ={
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7
+ };
+
+ private static readonly byte[] bl_order ={
+ 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
+
+ private static readonly short[] static_ltree = {
+ 12, 8, 140, 8, 76, 8, 204, 8, 44, 8,
+ 172, 8, 108, 8, 236, 8, 28, 8, 156, 8,
+ 92, 8, 220, 8, 60, 8, 188, 8, 124, 8,
+ 252, 8, 2, 8, 130, 8, 66, 8, 194, 8,
+ 34, 8, 162, 8, 98, 8, 226, 8, 18, 8,
+ 146, 8, 82, 8, 210, 8, 50, 8, 178, 8,
+ 114, 8, 242, 8, 10, 8, 138, 8, 74, 8,
+ 202, 8, 42, 8, 170, 8, 106, 8, 234, 8,
+ 26, 8, 154, 8, 90, 8, 218, 8, 58, 8,
+ 186, 8, 122, 8, 250, 8, 6, 8, 134, 8,
+ 70, 8, 198, 8, 38, 8, 166, 8, 102, 8,
+ 230, 8, 22, 8, 150, 8, 86, 8, 214, 8,
+ 54, 8, 182, 8, 118, 8, 246, 8, 14, 8,
+ 142, 8, 78, 8, 206, 8, 46, 8, 174, 8,
+ 110, 8, 238, 8, 30, 8, 158, 8, 94, 8,
+ 222, 8, 62, 8, 190, 8, 126, 8, 254, 8,
+ 1, 8, 129, 8, 65, 8, 193, 8, 33, 8,
+ 161, 8, 97, 8, 225, 8, 17, 8, 145, 8,
+ 81, 8, 209, 8, 49, 8, 177, 8, 113, 8,
+ 241, 8, 9, 8, 137, 8, 73, 8, 201, 8,
+ 41, 8, 169, 8, 105, 8, 233, 8, 25, 8,
+ 153, 8, 89, 8, 217, 8, 57, 8, 185, 8,
+ 121, 8, 249, 8, 5, 8, 133, 8, 69, 8,
+ 197, 8, 37, 8, 165, 8, 101, 8, 229, 8,
+ 21, 8, 149, 8, 85, 8, 213, 8, 53, 8,
+ 181, 8, 117, 8, 245, 8, 13, 8, 141, 8,
+ 77, 8, 205, 8, 45, 8, 173, 8, 109, 8,
+ 237, 8, 29, 8, 157, 8, 93, 8, 221, 8,
+ 61, 8, 189, 8, 125, 8, 253, 8, 19, 9,
+ 275, 9, 147, 9, 403, 9, 83, 9, 339, 9,
+ 211, 9, 467, 9, 51, 9, 307, 9, 179, 9,
+ 435, 9, 115, 9, 371, 9, 243, 9, 499, 9,
+ 11, 9, 267, 9, 139, 9, 395, 9, 75, 9,
+ 331, 9, 203, 9, 459, 9, 43, 9, 299, 9,
+ 171, 9, 427, 9, 107, 9, 363, 9, 235, 9,
+ 491, 9, 27, 9, 283, 9, 155, 9, 411, 9,
+ 91, 9, 347, 9, 219, 9, 475, 9, 59, 9,
+ 315, 9, 187, 9, 443, 9, 123, 9, 379, 9,
+ 251, 9, 507, 9, 7, 9, 263, 9, 135, 9,
+ 391, 9, 71, 9, 327, 9, 199, 9, 455, 9,
+ 39, 9, 295, 9, 167, 9, 423, 9, 103, 9,
+ 359, 9, 231, 9, 487, 9, 23, 9, 279, 9,
+ 151, 9, 407, 9, 87, 9, 343, 9, 215, 9,
+ 471, 9, 55, 9, 311, 9, 183, 9, 439, 9,
+ 119, 9, 375, 9, 247, 9, 503, 9, 15, 9,
+ 271, 9, 143, 9, 399, 9, 79, 9, 335, 9,
+ 207, 9, 463, 9, 47, 9, 303, 9, 175, 9,
+ 431, 9, 111, 9, 367, 9, 239, 9, 495, 9,
+ 31, 9, 287, 9, 159, 9, 415, 9, 95, 9,
+ 351, 9, 223, 9, 479, 9, 63, 9, 319, 9,
+ 191, 9, 447, 9, 127, 9, 383, 9, 255, 9,
+ 511, 9, 0, 7, 64, 7, 32, 7, 96, 7,
+ 16, 7, 80, 7, 48, 7, 112, 7, 8, 7,
+ 72, 7, 40, 7, 104, 7, 24, 7, 88, 7,
+ 56, 7, 120, 7, 4, 7, 68, 7, 36, 7,
+ 100, 7, 20, 7, 84, 7, 52, 7, 116, 7,
+ 3, 8, 131, 8, 67, 8, 195, 8, 35, 8,
+ 163, 8, 99, 8, 227, 8
+ };
+
+ private static readonly short[] static_dtree = {
+ 0, 5, 16, 5, 8, 5, 24, 5, 4, 5,
+ 20, 5, 12, 5, 28, 5, 2, 5, 18, 5,
+ 10, 5, 26, 5, 6, 5, 22, 5, 14, 5,
+ 30, 5, 1, 5, 17, 5, 9, 5, 25, 5,
+ 5, 5, 21, 5, 13, 5, 29, 5, 3, 5,
+ 19, 5, 11, 5, 27, 5, 7, 5, 23, 5
+ };
+ #endregion
+
+ private static readonly String[] z_errmsg = {
+ "need dictionary", // ZLibStatus.Z_NEED_DICT 2
+ "stream end", // ZLibStatus.Z_STREAM_END 1
+ "", // ZLibStatus.Z_OK 0
+ "file error", // ZLibStatus.Z_ERRNO (-1)
+ "stream error", // ZLibStatus.Z_STREAM_ERROR (-2)
+ "data error", // ZLibStatus.Z_DATA_ERROR (-3)
+ "insufficient memory", // Z_MEM_ERROR (-4)
+ "buffer error", // ZLibStatus.Z_BUF_ERROR (-5)
+ "incompatible version",// Z_VERSION_ERROR (-6)
+ ""
+ };
+
+
+
+ ///
+ /// as the name implies
+ ///
+ private int _status;
+
+ private BlockType _dataType;
+
+ ///
+ /// STORED (for zip only) or DEFLATED
+ ///
+ private byte _method;
+
+ ///
+ /// size of pending_buf
+ ///
+ private int _pendingBufferSize;
+
+ ///
+ /// LZ77 window size (32K by default)
+ ///
+ private int _windowSize;
+
+ ///
+ /// log2(w_size) (8..16)
+ ///
+ private int _windowBits;
+
+ ///
+ /// w_size - 1
+ ///
+ private int _windowMask;
+
+ ///
+ /// Sliding window. Input bytes are read into the second half of the window,
+ /// and move to the first half later to keep a dictionary of at least wSize
+ /// bytes. With this organization, matches are limited to a distance of
+ /// wSize-MAX_MATCH bytes, but this ensures that IO is always
+ /// performed with a length multiple of the block size. Also, it limits
+ /// the window size to 64K, which is quite useful on MSDOS.
+ /// To do: use the user input buffer as sliding window.
+ ///
+ private byte[] _window;
+
+ ///
+ /// Actual size of window: 2*wSize, except when the user input buffer
+ /// is directly used as sliding window.
+ ///
+ private int _windowActualSize;
+
+ ///
+ /// Link to older string with same hash index. To limit the size of this
+ /// array to 64K, this link is maintained only for the last 32K strings.
+ /// An index in this array is thus a window index modulo 32K.
+ ///
+ private short[] _previous;
+
+ ///
+ /// Heads of the hash chains or NIL.
+ ///
+ private short[] _head;
+
+ ///
+ /// hash index of string to be inserted
+ ///
+ private int _insertedHashIndex;
+
+ ///
+ /// number of elements in hash table
+ ///
+ private int _hashSize;
+
+ ///
+ /// log2(hash_size)
+ ///
+ private int _hashBits;
+
+ ///
+ /// hash_size-1
+ ///
+ private int _hashMask;
+
+ ///
+ /// Number of bits by which ins_h must be shifted at each input
+ /// step. It must be such that after MIN_MATCH steps, the oldest
+ /// byte no longer takes part in the hash key, that is:
+ /// hash_shift * MIN_MATCH >= hash_bits
+ ///
+ private int _hashShift;
+
+ ///
+ /// Window position at the beginning of the current output block. Gets
+ /// negative when the window is moved backwards.
+ ///
+ private int _blockStart;
+
+ ///
+ /// length of best match
+ ///
+ private int _matchLength;
+
+ ///
+ /// previous match
+ ///
+ private int _previousMatch;
+
+ ///
+ /// set if previous match exists
+ ///
+ private bool _matchAvailable;
+
+ ///
+ /// start of string to insert
+ ///
+ private int _startInsertString;
+
+ ///
+ /// start of matching string
+ ///
+ private int _startMatchString;
+
+ ///
+ /// number of valid bytes ahead in window
+ ///
+ private int _validBytesAhead;
+
+ ///
+ /// Length of the best match at previous step. Matches not greater than this
+ /// are discarded. This is used in the lazy match evaluation.
+ ///
+ private int _previousLength;
+
+ ///
+ /// To speed up deflation, hash chains are never searched beyond this
+ /// length. A higher limit improves compression ratio but degrades the speed.
+ ///
+ private int _maxChainLength;
+
+ ///
+ /// Attempt to find a better match only when the current match is strictly
+ /// smaller than this value. This mechanism is used only for compression
+ /// levels >= 4.
+ ///
+ private int _maxLazyMatch;
+
+ // Insert new strings in the hash table only if the match length is not
+ // greater than this length. This saves time but degrades compression.
+ // max_insert_length is used only for compression levels <= 3.
+
+ ///
+ /// The compression level (1..9)
+ ///
+ private CompressionLevel level;
+
+ ///
+ /// The favor or force Huffman coding
+ ///
+ private CompressionStrategy strategy;
+
+ ///
+ /// Use a faster search when the previous match is longer than this
+ ///
+ private int good_match;
+
+ ///
+ /// Stop searching when current match exceeds this
+ ///
+ private int nice_match;
+
+ ///
+ /// literal and length tree
+ ///
+ private short[] dyn_ltree;
+
+ ///
+ /// The distance tree
+ ///
+ private short[] dyn_dtree;
+
+ ///
+ /// The Huffman tree for bit lengths
+ ///
+ private short[] bl_tree;
+
+ ///
+ /// The desc for literal tree
+ ///
+ private Tree l_desc = new Tree();
+
+ ///
+ /// The desc for distance tree
+ ///
+ private Tree d_desc = new Tree();
+
+ ///
+ /// The desc for bit length tree
+ ///
+ private Tree bl_desc = new Tree();
+
+ ///
+ /// index for literals or lengths
+ ///
+ private int l_buf;
+
+ ///
+ /// Size of match buffer for literals/lengths. There are 4 reasons for
+ /// limiting lit_bufsize to 64K:
+ /// - frequencies can be kept in 16 bit counters
+ /// - if compression is not successful for the first block, all input
+ /// data is still in the window so we can still emit a stored block even
+ /// when input comes from standard input. (This can also be done for
+ /// all blocks if lit_bufsize is not greater than 32K.)
+ /// - if compression is not successful for a file smaller than 64K, we can
+ /// even emit a stored file instead of a stored block (saving 5 bytes).
+ /// This is applicable only for zip (not gzip or zlib).
+ /// - creating new Huffman trees less frequently may not provide fast
+ /// adaptation to changes in the input data statistics. (Take for
+ /// example a binary file with poorly compressible code followed by
+ /// a highly compressible string table.) Smaller buffer sizes give
+ /// fast adaptation but have of course the overhead of transmitting
+ /// trees more frequently.
+ /// - I can't count above 4
+ ///
+ private int lit_bufsize;
+
+ ///
+ /// running index in l_buf
+ ///
+ private int last_lit;
+
+ // Buffer for distances. To simplify the code, d_buf and l_buf have
+ // the same number of elements. To use different lengths, an extra flag
+ // array would be necessary.
+
+ ///
+ /// The index of pendig_buf
+ ///
+ private int d_buf;
+
+ ///
+ /// The number of string matches in current block
+ ///
+ private int matches;
+
+ ///
+ /// The bit length of EOB code for last block
+ ///
+ private int last_eob_len;
+
+ ///
+ /// Output buffer. bits are inserted starting at the bottom (least
+ /// significant bits).
+ ///
+ private uint bi_buf;
+
+ ///
+ /// Number of valid bits in bi_buf. All bits above the last valid bit
+ /// are always zero.
+ ///
+ private int bi_valid;
+
+ ///
+ /// value of flush param for previous deflate call
+ ///
+ private FlushType last_flush;
+
+ ///
+ /// bit length of current block with optimal trees
+ ///
+ internal int opt_len;
+
+ ///
+ /// bit length of current block with static trees
+ ///
+ internal int static_len;
+
+ ///
+ /// The output still pending
+ ///
+ internal byte[] pending_buf;
+
+ ///
+ /// next pending byte to output to the stream
+ ///
+ internal int pending_out;
+
+ ///
+ /// nb of bytes in the pending buffer
+ ///
+ internal int pending;
+
+ ///
+ /// suppress zlib header and adler32
+ ///
+ internal int noheader;
+
+ ///
+ /// number of codes at each bit length for an optimal tree
+ ///
+ internal short[] bl_count = new short[MAX_BITS + 1];
+
+ ///
+ /// heap used to build the Huffman trees
+ ///
+ internal int[] heap = new int[2 * L_CODES + 1];
+
+ ///
+ /// The number of elements in the heap
+ ///
+ internal int heap_len;
+ ///
+ /// The element of largest frequency
+ ///
+ internal int heap_max;
+
+ // The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+ // The same heap array is used to build all trees.
+
+ ///
+ /// Depth of each subtree used as tie breaker for trees of equal frequency
+ ///
+ internal byte[] depth = new byte[2 * L_CODES + 1];
+
+ public Deflate()
+ {
+ dyn_ltree = new short[HEAP_SIZE * 2];
+ dyn_dtree = new short[(2 * D_CODES + 1) * 2]; // distance tree
+ bl_tree = new short[(2 * BL_CODES + 1) * 2]; // Huffman tree for bit lengths
+ }
+
+ public Deflate(CompressionLevel level)
+ : this()
+ {
+ this.deflateInit(level);
+ }
+
+ public Deflate(CompressionLevel level, bool nowrap)
+ : this()
+ {
+ this.deflateInit(level, nowrap);
+ }
+
+ // Restore the heap property by moving down the tree starting at node k,
+ // exchanging a node with the smallest of its two sons if necessary, stopping
+ // when the heap property is re-established (each father smaller than its
+ // two sons).
+ internal void pqdownheap(short[] tree, // the tree to restore
+ int k // node to move down
+ )
+ {
+ int v = heap[k];
+ int j = k << 1; // left son of k
+ while (j <= heap_len)
+ {
+ // Set j to the smallest of the two sons:
+ if (j < heap_len &&
+ smaller(tree, heap[j + 1], heap[j], depth))
+ {
+ j++;
+ }
+ // Exit if v is smaller than both sons
+ if (smaller(tree, v, heap[j], depth)) break;
+
+ // Exchange v with the smallest son
+ heap[k] = heap[j]; k = j;
+ // And continue down the tree, setting j to the left son of k
+ j <<= 1;
+ }
+ heap[k] = v;
+ }
+
+ public ZLibStatus deflateInit(CompressionLevel level)
+ {
+ return deflateInit(level, MAX_WBITS);
+ }
+ public ZLibStatus deflateInit(CompressionLevel level, bool nowrap)
+ {
+ return deflateInit(level, MAX_WBITS, nowrap);
+ }
+
+ public ZLibStatus deflateInit(CompressionLevel level, int bits, bool nowrap)
+ {
+ return this.deflateInit(level, nowrap ? -bits : bits);
+ }
+
+ internal ZLibStatus deflateInit(CompressionLevel level, int bits)
+ {
+ return deflateInit2(level, Z_DEFLATED, bits, DEF_MEM_LEVEL, CompressionStrategy.Z_DEFAULT_STRATEGY);
+ }
+
+ private ZLibStatus deflateInit2(CompressionLevel level, int method, int windowBits, int memLevel, CompressionStrategy strategy)
+ {
+ int noheader = 0;
+ // byte[] my_version=ZLIB_VERSION;
+
+ //
+ // if (version == null || version[0] != my_version[0]
+ // || stream_size != sizeof(z_stream)) {
+ // return Z_VERSION_ERROR;
+ // }
+
+ base.msg = null;
+
+ if (level == CompressionLevel.Z_DEFAULT_COMPRESSION) level = (CompressionLevel)6;
+
+ if (windowBits < 0)
+ { // undocumented feature: suppress zlib header
+ noheader = 1;
+ windowBits = -windowBits;
+ }
+
+ if (memLevel < 1 || memLevel > MAX_MEM_LEVEL ||
+ method != Z_DEFLATED ||
+ windowBits < 9 || windowBits > 15 || level < 0 || level > (CompressionLevel)9 ||
+ strategy < 0 || strategy > CompressionStrategy.Z_HUFFMAN_ONLY)
+ {
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+
+ this.noheader = noheader;
+ _windowBits = windowBits;
+ _windowSize = 1 << _windowBits;
+ _windowMask = _windowSize - 1;
+
+ _hashBits = memLevel + 7;
+ _hashSize = 1 << _hashBits;
+ _hashMask = _hashSize - 1;
+ _hashShift = ((_hashBits + MIN_MATCH - 1) / MIN_MATCH);
+
+ _window = new byte[_windowSize * 2];
+ _previous = new short[_windowSize];
+ _head = new short[_hashSize];
+
+ lit_bufsize = 1 << (memLevel + 6); // 16K elements by default
+
+ // We overlay pending_buf and d_buf+l_buf. This works since the average
+ // output size for (length,distance) codes is <= 24 bits.
+ pending_buf = new byte[lit_bufsize * 4];
+ _pendingBufferSize = lit_bufsize * 4;
+
+ d_buf = lit_bufsize / 2;
+ l_buf = (1 + 2) * lit_bufsize;
+
+ this.level = level;
+
+ //System.out.println("level="+level);
+
+ this.strategy = strategy;
+ this._method = (byte)method;
+
+ return deflateReset();
+ }
+
+ private ZLibStatus deflateReset()
+ {
+ base.total_in = base.total_out = 0;
+ base.msg = null; //
+ base.data_type = BlockType.Z_UNKNOWN;
+
+ pending = 0;
+ pending_out = 0;
+
+ if (noheader < 0)
+ {
+ noheader = 0; // was set to -1 by deflate(..., FlushType.Z_FINISH);
+ }
+ _status = (noheader != 0) ? BUSY_STATE : INIT_STATE;
+ base.adler = Adler32.adler32(0, null, 0, 0);
+
+ last_flush = FlushType.Z_NO_FLUSH;
+
+ tr_init();
+ lm_init();
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus deflateEnd()
+ {
+ if (_status != INIT_STATE && _status != BUSY_STATE && _status != FINISH_STATE)
+ {
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+ // Deallocate in reverse order of allocations:
+ pending_buf = null;
+ _head = null;
+ _previous = null;
+ _window = null;
+ // free
+ // dstate=null;
+ return _status == BUSY_STATE ? ZLibStatus.Z_DATA_ERROR : ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus deflateParams(ZStream strm, CompressionLevel _level, CompressionStrategy _strategy)
+ {
+ ZLibStatus err = ZLibStatus.Z_OK;
+
+ if (_level == CompressionLevel.Z_DEFAULT_COMPRESSION)
+ {
+ _level = (CompressionLevel)6;
+ }
+ if (_level < 0 || _level > (CompressionLevel)9 ||
+ _strategy < 0 || _strategy > CompressionStrategy.Z_HUFFMAN_ONLY)
+ {
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+
+ if (config_table[level].Function != config_table[_level].Function &&
+ strm.total_in != 0)
+ {
+ // Flush the last buffer:
+ err = this.deflate(FlushType.Z_PARTIAL_FLUSH);
+ }
+
+ if (level != _level)
+ {
+ level = _level;
+ _maxLazyMatch = config_table[level].MaxLazy;
+ good_match = config_table[level].GoodLength;
+ nice_match = config_table[level].NiceLength;
+ _maxChainLength = config_table[level].MaxChain;
+ }
+ strategy = _strategy;
+ return err;
+ }
+
+ public ZLibStatus deflateSetDictionary(ZStream strm, byte[] dictionary, int dictLength)
+ {
+ int length = dictLength;
+ int index = 0;
+
+ if (dictionary == null || _status != INIT_STATE)
+ return ZLibStatus.Z_STREAM_ERROR;
+
+ strm.adler = Adler32.adler32(strm.adler, dictionary, 0, dictLength);
+
+ if (length < MIN_MATCH) return ZLibStatus.Z_OK;
+ if (length > _windowSize - MIN_LOOKAHEAD)
+ {
+ length = _windowSize - MIN_LOOKAHEAD;
+ index = dictLength - length; // use the tail of the dictionary
+ }
+ System.Array.Copy(dictionary, index, _window, 0, length);
+ _startInsertString = length;
+ _blockStart = length;
+
+ // Insert all strings in the hash table (except for the last two bytes).
+ // s->lookahead stays null, so s->ins_h will be recomputed at the next
+ // call of fill_window.
+
+ _insertedHashIndex = _window[0] & 0xff;
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[1] & 0xff)) & _hashMask;
+
+ for (int n = 0; n <= length - MIN_MATCH; n++)
+ {
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[(n) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+ _previous[n & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)n;
+ }
+ return ZLibStatus.Z_OK;
+ }
+
+ //public ZLibStatus deflate(ZStream strm, FlushType flush)
+ //{
+ // FlushType old_flush;
+
+ // if (flush > FlushType.Z_FINISH || flush < 0)
+ // {
+ // return ZLibStatus.Z_STREAM_ERROR;
+ // }
+
+ // if (strm.next_out == null ||
+ // (strm.next_in == null && strm.avail_in != 0) ||
+ // (_status == FINISH_STATE && flush != FlushType.Z_FINISH))
+ // {
+ // strm.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_STREAM_ERROR)];
+ // return ZLibStatus.Z_STREAM_ERROR;
+ // }
+ // if (strm.avail_out == 0)
+ // {
+ // strm.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_BUF_ERROR)];
+ // return ZLibStatus.Z_BUF_ERROR;
+ // }
+
+ // this._stream = strm; // just in case
+ // old_flush = last_flush;
+ // last_flush = flush;
+
+ // // Write the zlib header
+ // if (_status == INIT_STATE)
+ // {
+ // int header = (Z_DEFLATED + ((_windowBits - 8) << 4)) << 8;
+ // int level_flags = (((int)level - 1) & 0xff) >> 1;
+
+ // if (level_flags > 3) level_flags = 3;
+ // header |= (level_flags << 6);
+ // if (_startInsertString != 0) header |= PRESET_DICT;
+ // header += 31 - (header % 31);
+
+ // _status = BUSY_STATE;
+ // putShortMSB(header);
+
+
+ // // Save the adler32 of the preset dictionary:
+ // if (_startInsertString != 0)
+ // {
+ // putShortMSB((int)(strm.adler >> 16));
+ // putShortMSB((int)(strm.adler & 0xffff));
+ // }
+ // strm.adler = Adler32.adler32(0, null, 0, 0);
+ // }
+
+ // // Flush as much pending output as possible
+ // if (pending != 0)
+ // {
+ // strm.flush_pending();
+ // if (strm.avail_out == 0)
+ // {
+ // //System.out.println(" avail_out==0");
+ // // Since avail_out is 0, deflate will be called again with
+ // // more output space, but possibly with both pending and
+ // // avail_in equal to zero. There won't be anything to do,
+ // // but this is not an error situation so make sure we
+ // // return OK instead of BUF_ERROR at next call of deflate:
+ // last_flush = (FlushType)(-1);
+ // return ZLibStatus.Z_OK;
+ // }
+
+ // // Make sure there is something to do and avoid duplicate consecutive
+ // // flushes. For repeated and useless calls with FlushType.Z_FINISH, we keep
+ // // returning ZLibStatus.Z_STREAM_END instead of Z_BUFF_ERROR.
+ // }
+ // else if (strm.avail_in == 0 && flush <= old_flush &&
+ // flush != FlushType.Z_FINISH)
+ // {
+ // strm.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_BUF_ERROR)];
+ // return ZLibStatus.Z_BUF_ERROR;
+ // }
+
+ // // User must not provide more input after the first FINISH:
+ // if (_status == FINISH_STATE && strm.avail_in != 0)
+ // {
+ // strm.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_BUF_ERROR)];
+ // return ZLibStatus.Z_BUF_ERROR;
+ // }
+
+ // // Start a new block or continue the current one.
+ // if (strm.avail_in != 0 || _validBytesAhead != 0 ||
+ // (flush != FlushType.Z_NO_FLUSH && _status != FINISH_STATE))
+ // {
+ // int bstate = -1;
+ // switch (config_table[level].Function)
+ // {
+ // case DefalteFlavor.STORED:
+ // bstate = deflate_stored(flush);
+ // break;
+ // case DefalteFlavor.FAST:
+ // bstate = deflate_fast(flush);
+ // break;
+ // case DefalteFlavor.SLOW:
+ // bstate = deflate_slow(flush);
+ // break;
+ // default:
+ // break;
+ // }
+
+ // if (bstate == FinishStarted || bstate == FinishDone)
+ // {
+ // _status = FINISH_STATE;
+ // }
+ // if (bstate == NeedMore || bstate == FinishStarted)
+ // {
+ // if (strm.avail_out == 0)
+ // {
+ // last_flush = (FlushType)(-1); // avoid BUF_ERROR next call, see above
+ // }
+ // return ZLibStatus.Z_OK;
+ // // If flush != FlushType.Z_NO_FLUSH && avail_out == 0, the next call
+ // // of deflate should use the same flush parameter to make sure
+ // // that the flush is complete. So we don't have to output an
+ // // empty block here, this will be done at next call. This also
+ // // ensures that for a very small output buffer, we emit at most
+ // // one empty block.
+ // }
+
+ // if (bstate == BlockDone)
+ // {
+ // if (flush == FlushType.Z_PARTIAL_FLUSH)
+ // {
+ // _tr_align();
+ // }
+ // else
+ // { // FULL_FLUSH or SYNC_FLUSH
+ // _tr_stored_block(0, 0, false);
+ // // For a full flush, this empty block will be recognized
+ // // as a special marker by inflate_sync().
+ // if (flush == FlushType.Z_FULL_FLUSH)
+ // {
+ // //state.head[s.hash_size-1]=0;
+ // for (int i = 0; i < _hashSize/*-1*/; i++) // forget history
+ // _head[i] = 0;
+ // }
+ // }
+ // strm.flush_pending();
+ // if (strm.avail_out == 0)
+ // {
+ // last_flush = (FlushType)(-1); // avoid BUF_ERROR at next call, see above
+ // return ZLibStatus.Z_OK;
+ // }
+ // }
+ // }
+
+ // if (flush != FlushType.Z_FINISH) return ZLibStatus.Z_OK;
+ // if (noheader != 0) return ZLibStatus.Z_STREAM_END;
+
+ // // Write the zlib trailer (adler32)
+ // putShortMSB((int)(strm.adler >> 16));
+ // putShortMSB((int)(strm.adler & 0xffff));
+ // strm.flush_pending();
+
+ // // If avail_out is zero, the application will call deflate again
+ // // to flush the rest.
+ // noheader = -1; // write the trailer only once!
+ // return pending != 0 ? ZLibStatus.Z_OK : ZLibStatus.Z_STREAM_END;
+ //}
+
+ private void lm_init()
+ {
+ _windowActualSize = 2 * _windowSize;
+
+ _head[_hashSize - 1] = 0;
+ for (int i = 0; i < _hashSize - 1; i++)
+ {
+ _head[i] = 0;
+ }
+
+ // Set the default configuration parameters:
+ _maxLazyMatch = Deflate.config_table[level].MaxLazy;
+ good_match = Deflate.config_table[level].GoodLength;
+ nice_match = Deflate.config_table[level].NiceLength;
+ _maxChainLength = Deflate.config_table[level].MaxChain;
+
+ _startInsertString = 0;
+ _blockStart = 0;
+ _validBytesAhead = 0;
+ _matchLength = _previousLength = MIN_MATCH - 1;
+ _matchAvailable = false;
+ _insertedHashIndex = 0;
+ }
+
+ // Initialize the tree data structures for a new zlib stream.
+ private void tr_init()
+ {
+
+ l_desc.Init(dyn_ltree, Deflate.static_l_desc);
+
+ d_desc.Init(dyn_dtree, Deflate.static_d_desc);
+
+ bl_desc.Init(bl_tree, Deflate.static_bl_desc);
+
+
+ bi_buf = 0;
+ bi_valid = 0;
+ last_eob_len = 8; // enough lookahead for inflate
+
+ // Initialize the first block of the first file:
+ init_block();
+ }
+
+ private void init_block()
+ {
+ // Initialize the trees.
+ for (int i = 0; i < L_CODES; i++) dyn_ltree[i * 2] = 0;
+ for (int i = 0; i < D_CODES; i++) dyn_dtree[i * 2] = 0;
+ for (int i = 0; i < BL_CODES; i++) bl_tree[i * 2] = 0;
+
+ dyn_ltree[END_BLOCK * 2] = 1;
+ opt_len = static_len = 0;
+ last_lit = matches = 0;
+ }
+
+ private static bool smaller(short[] tree, int n, int m, byte[] depth)
+ {
+ short tn2 = tree[n * 2];
+ short tm2 = tree[m * 2];
+ return (tn2 < tm2 ||
+ (tn2 == tm2 && depth[n] <= depth[m]));
+ }
+
+ // Scan a literal or distance tree to determine the frequencies of the codes
+ // in the bit length tree.
+ private void scan_tree(short[] tree,// the tree to be scanned
+ int max_code // and its largest code of non zero frequency
+ )
+ {
+ int n; // iterates over all tree elements
+ int prevlen = -1; // last emitted length
+ int curlen; // length of current code
+ int nextlen = tree[0 * 2 + 1]; // length of next code
+ int count = 0; // repeat count of the current code
+ int max_count = 7; // max repeat count
+ int min_count = 4; // min repeat count
+
+ if (nextlen == 0) { max_count = 138; min_count = 3; }
+ tree[(max_code + 1) * 2 + 1] = -1; // guard
+
+ for (n = 0; n <= max_code; n++)
+ {
+ curlen = nextlen; nextlen = tree[(n + 1) * 2 + 1];
+ if (++count < max_count && curlen == nextlen)
+ {
+ continue;
+ }
+ else if (count < min_count)
+ {
+ bl_tree[curlen * 2] += (short)count;
+ }
+ else if (curlen != 0)
+ {
+ if (curlen != prevlen) bl_tree[curlen * 2]++;
+ bl_tree[REP_3_6 * 2]++;
+ }
+ else if (count <= 10)
+ {
+ bl_tree[REPZ_3_10 * 2]++;
+ }
+ else
+ {
+ bl_tree[REPZ_11_138 * 2]++;
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0)
+ {
+ max_count = 138; min_count = 3;
+ }
+ else if (curlen == nextlen)
+ {
+ max_count = 6; min_count = 3;
+ }
+ else
+ {
+ max_count = 7; min_count = 4;
+ }
+ }
+ }
+
+ // Construct the Huffman tree for the bit lengths and return the index in
+ // bl_order of the last bit length code to send.
+ private int build_bl_tree()
+ {
+ int max_blindex; // index of last bit length code of non zero freq
+
+ // Determine the bit length frequencies for literal and distance trees
+ scan_tree(dyn_ltree, l_desc.LargestCode);
+ scan_tree(dyn_dtree, d_desc.LargestCode);
+
+ // Build the bit length tree:
+ bl_desc.BuildTree(this);
+ // opt_len now includes the length of the tree representations, except
+ // the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
+
+ // Determine the number of bit length codes to send. The pkzip format
+ // requires that at least 4 bit length codes be sent. (appnote.txt says
+ // 3 but the actual value used is 4.)
+ for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--)
+ {
+ if (bl_tree[Deflate.bl_order[max_blindex] * 2 + 1] != 0) break;
+ }
+ // Update opt_len to include the bit length tree and counts
+ opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4;
+
+ return max_blindex;
+ }
+
+
+ // Send the header for a block using dynamic Huffman trees: the counts, the
+ // lengths of the bit length codes, the literal tree and the distance tree.
+ // IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
+ private void send_all_trees(int lcodes, int dcodes, int blcodes)
+ {
+ int rank; // index in bl_order
+
+ send_bits(lcodes - 257, 5); // not +255 as stated in appnote.txt
+ send_bits(dcodes - 1, 5);
+ send_bits(blcodes - 4, 4); // not -3 as stated in appnote.txt
+ for (rank = 0; rank < blcodes; rank++)
+ {
+ send_bits(bl_tree[Deflate.bl_order[rank] * 2 + 1], 3);
+ }
+ send_tree(dyn_ltree, lcodes - 1); // literal tree
+ send_tree(dyn_dtree, dcodes - 1); // distance tree
+ }
+
+ // Send a literal or distance tree in compressed form, using the codes in
+ // bl_tree.
+ private void send_tree(short[] tree,// the tree to be sent
+ int max_code // and its largest code of non zero frequency
+ )
+ {
+ int n; // iterates over all tree elements
+ int prevlen = -1; // last emitted length
+ int curlen; // length of current code
+ int nextlen = tree[0 * 2 + 1]; // length of next code
+ int count = 0; // repeat count of the current code
+ int max_count = 7; // max repeat count
+ int min_count = 4; // min repeat count
+
+ if (nextlen == 0) { max_count = 138; min_count = 3; }
+
+ for (n = 0; n <= max_code; n++)
+ {
+ curlen = nextlen; nextlen = tree[(n + 1) * 2 + 1];
+ if (++count < max_count && curlen == nextlen)
+ {
+ continue;
+ }
+ else if (count < min_count)
+ {
+ do { send_code(curlen, bl_tree); } while (--count != 0);
+ }
+ else if (curlen != 0)
+ {
+ if (curlen != prevlen)
+ {
+ send_code(curlen, bl_tree); count--;
+ }
+ send_code(REP_3_6, bl_tree);
+ send_bits(count - 3, 2);
+ }
+ else if (count <= 10)
+ {
+ send_code(REPZ_3_10, bl_tree);
+ send_bits(count - 3, 3);
+ }
+ else
+ {
+ send_code(REPZ_11_138, bl_tree);
+ send_bits(count - 11, 7);
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0)
+ {
+ max_count = 138; min_count = 3;
+ }
+ else if (curlen == nextlen)
+ {
+ max_count = 6; min_count = 3;
+ }
+ else
+ {
+ max_count = 7; min_count = 4;
+ }
+ }
+ }
+
+ // Output a byte on the stream.
+ // IN assertion: there is enough room in pending_buf.
+ private void put_byte(byte[] p, int start, int len)
+ {
+ System.Array.Copy(p, start, pending_buf, pending, len);
+ pending += len;
+ }
+
+ private void put_byte(byte c)
+ {
+ pending_buf[pending++] = c;
+ }
+ private void put_short(int w)
+ {
+ pending_buf[pending++] = (byte)(w/*&0xff*/);
+ pending_buf[pending++] = (byte)(w >> 8);
+ }
+ private void putShortMSB(int b)
+ {
+ pending_buf[pending++] = (byte)(b >> 8);
+ pending_buf[pending++] = (byte)(b/*&0xff*/);
+ }
+
+ private void send_code(int c, short[] tree)
+ {
+ int c2 = c * 2;
+ send_bits((tree[c2] & 0xffff), (tree[c2 + 1] & 0xffff));
+ }
+
+ private void send_bits(int val, int length)
+ {
+ if (bi_valid > Buf_size - length)
+ {
+ bi_buf |= (uint)(val << bi_valid);
+ pending_buf[pending++] = (byte)(bi_buf/*&0xff*/);
+ pending_buf[pending++] = (byte)(bi_buf >> 8);
+ bi_buf = ((uint)val) >> (Buf_size - bi_valid);
+ bi_valid += length - Buf_size;
+ }
+ else
+ {
+ bi_buf |= (uint)(val << bi_valid);
+ bi_valid += length;
+ }
+ // int len = length;
+ // if (bi_valid > (int)Buf_size - len) {
+ // int val = value;
+ // // bi_buf |= (val << bi_valid);
+ // bi_buf = (short)((ushort)bi_buf | (ushort)((val << bi_valid)&0xffff));
+ // put_short(bi_buf);
+ // bi_buf = (short)(((uint)val) >> (Buf_size - bi_valid));
+ // bi_valid += len - Buf_size;
+ // } else {
+ // // bi_buf |= (value) << bi_valid;
+ // bi_buf = (short)((ushort)bi_buf | (ushort)(((value) << bi_valid)&0xffff));
+ // bi_valid += len;
+ // }
+ }
+
+ // Send one empty static block to give enough lookahead for inflate.
+ // This takes 10 bits, of which 7 may remain in the bit buffer.
+ // The current inflate code requires 9 bits of lookahead. If the
+ // last two codes for the previous block (real code plus EOB) were coded
+ // on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
+ // the last real code. In this case we send two empty static blocks instead
+ // of one. (There are no problems if the previous block is stored or fixed.)
+ // To simplify the code, we assume the worst case of last real code encoded
+ // on one bit only.
+ private void _tr_align()
+ {
+ send_bits(STATIC_TREES << 1, 3);
+ send_code(END_BLOCK, Deflate.static_ltree);
+
+ bi_flush();
+
+ // Of the 10 bits for the empty block, we have already sent
+ // (10 - bi_valid) bits. The lookahead for the last real code (before
+ // the EOB of the previous block) was thus at least one plus the length
+ // of the EOB plus what we have just sent of the empty static block.
+ if (1 + last_eob_len + 10 - bi_valid < 9)
+ {
+ send_bits(STATIC_TREES << 1, 3);
+ send_code(END_BLOCK, Deflate.static_ltree);
+ bi_flush();
+ }
+ last_eob_len = 7;
+ }
+
+
+ // Save the match info and tally the frequency counts. Return true if
+ // the current block must be flushed.
+ private bool _tr_tally(int dist, // distance of matched string
+ int lc // match length-MIN_MATCH or unmatched char (if dist==0)
+ )
+ {
+
+ pending_buf[d_buf + last_lit * 2] = (byte)(dist >> 8);
+ pending_buf[d_buf + last_lit * 2 + 1] = (byte)dist;
+
+ pending_buf[l_buf + last_lit] = (byte)lc; last_lit++;
+
+ if (dist == 0)
+ {
+ // lc is the unmatched char
+ dyn_ltree[lc * 2]++;
+ }
+ else
+ {
+ matches++;
+ // Here, lc is the match length - MIN_MATCH
+ dist--; // dist = match distance - 1
+ dyn_ltree[(Deflate._length_code[lc] + LITERALS + 1) * 2]++;
+ dyn_dtree[Tree.DistanceCode(dist) * 2]++;
+ }
+
+ if ((last_lit & 0x1fff) == 0 && level > (CompressionLevel)2)
+ {
+ // Compute an upper bound for the compressed length
+ int out_length = last_lit * 8;
+ int in_length = _startInsertString - _blockStart;
+ int dcode;
+ for (dcode = 0; dcode < D_CODES; dcode++)
+ {
+ out_length += (int)((int)dyn_dtree[dcode * 2] *
+ (5L + Deflate.extra_dbits[dcode]));
+ }
+ out_length >>= 3;
+ if ((matches < (last_lit / 2)) && out_length < in_length / 2) return true;
+ }
+
+ return (last_lit == lit_bufsize - 1);
+ // We avoid equality with lit_bufsize because of wraparound at 64K
+ // on 16 bit machines and because stored blocks are restricted to
+ // 64K-1 bytes.
+ }
+
+ // Send the block data compressed using the given Huffman trees
+ private void compress_block(short[] ltree, short[] dtree)
+ {
+ int dist; // distance of matched string
+ int lc; // match length or unmatched char (if dist == 0)
+ int lx = 0; // running index in l_buf
+ int code; // the code to send
+ int extra; // number of extra bits to send
+
+ if (last_lit != 0)
+ {
+ do
+ {
+ dist = ((pending_buf[d_buf + lx * 2] << 8) & 0xff00) |
+ (pending_buf[d_buf + lx * 2 + 1] & 0xff);
+ lc = (pending_buf[l_buf + lx]) & 0xff; lx++;
+
+ if (dist == 0)
+ {
+ send_code(lc, ltree); // send a literal byte
+ }
+ else
+ {
+ // Here, lc is the match length - MIN_MATCH
+ code = Deflate._length_code[lc];
+
+ send_code(code + LITERALS + 1, ltree); // send the length code
+ extra = Deflate.extra_lbits[code];
+ if (extra != 0)
+ {
+ lc -= Deflate.base_length[code];
+ send_bits(lc, extra); // send the extra length bits
+ }
+ dist--; // dist is now the match distance - 1
+ code = Tree.DistanceCode(dist);
+
+ send_code(code, dtree); // send the distance code
+ extra = Deflate.extra_dbits[code];
+ if (extra != 0)
+ {
+ dist -= Deflate.base_dist[code];
+ send_bits(dist, extra); // send the extra distance bits
+ }
+ } // literal or match pair ?
+
+ // Check that the overlay between pending_buf and d_buf+l_buf is ok:
+ }
+ while (lx < last_lit);
+ }
+
+ send_code(END_BLOCK, ltree);
+ last_eob_len = ltree[END_BLOCK * 2 + 1];
+ }
+
+ // Set the data type to ASCII or BINARY, using a crude approximation:
+ // binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise.
+ // IN assertion: the fields freq of dyn_ltree are set and the total of all
+ // frequencies does not exceed 64K (to fit in an int on 16 bit machines).
+ private void set_data_type()
+ {
+ int n = 0;
+ int ascii_freq = 0;
+ int bin_freq = 0;
+ while (n < 7) { bin_freq += dyn_ltree[n * 2]; n++; }
+ while (n < 128) { ascii_freq += dyn_ltree[n * 2]; n++; }
+ while (n < LITERALS) { bin_freq += dyn_ltree[n * 2]; n++; }
+ this._dataType = (bin_freq > (ascii_freq >> 2) ? BlockType.Z_BINARY : BlockType.Z_ASCII);
+ }
+
+ // Flush the bit buffer, keeping at most 7 bits in it.
+ private void bi_flush()
+ {
+ if (bi_valid == 16)
+ {
+ pending_buf[pending++] = (byte)(bi_buf/*&0xff*/);
+ pending_buf[pending++] = (byte)(bi_buf >> 8);
+ bi_buf = 0;
+ bi_valid = 0;
+ }
+ else if (bi_valid >= 8)
+ {
+ pending_buf[pending++] = (byte)(bi_buf);
+ bi_buf >>= 8;
+ bi_buf &= 0x00ff;
+ bi_valid -= 8;
+ }
+ }
+
+ // Flush the bit buffer and align the output on a byte boundary
+ private void bi_windup()
+ {
+ if (bi_valid > 8)
+ {
+ pending_buf[pending++] = (byte)(bi_buf);
+ pending_buf[pending++] = (byte)(bi_buf >> 8);
+ }
+ else if (bi_valid > 0)
+ {
+ pending_buf[pending++] = (byte)(bi_buf);
+ }
+ bi_buf = 0;
+ bi_valid = 0;
+ }
+
+ // Copy a stored block, storing first the length and its
+ // one's complement if requested.
+ private void copy_block(int buf, // the input data
+ int len, // its length
+ bool header // true if block header must be written
+ )
+ {
+ //int index=0;
+ bi_windup(); // align on byte boundary
+ last_eob_len = 8; // enough lookahead for inflate
+
+ if (header)
+ {
+ put_short((short)len);
+ put_short((short)~len);
+ }
+
+ // while(len--!=0) {
+ // put_byte(window[buf+index]);
+ // index++;
+ // }
+ put_byte(_window, buf, len);
+ }
+
+ private void flush_block_only(bool eof)
+ {
+ _tr_flush_block(_blockStart >= 0 ? _blockStart : -1,
+ _startInsertString - _blockStart,
+ eof);
+ _blockStart = _startInsertString;
+ this.flush_pending();
+ }
+
+ // Copy without compression as much as possible from the input stream, return
+ // the current block state.
+ // This function does not insert new strings in the dictionary since
+ // uncompressible data is probably not useful. This function is used
+ // only for the level=0 compression option.
+ // NOTE: this function should be optimized to avoid extra copying from
+ // window to pending_buf.
+ private int deflate_stored(FlushType flush)
+ {
+ // Stored blocks are limited to 0xffff bytes, pending_buf is limited
+ // to pending_buf_size, and each stored block has a 5 byte header:
+
+ int max_block_size = 0xffff;
+ int max_start;
+
+ if (max_block_size > _pendingBufferSize - 5)
+ {
+ max_block_size = _pendingBufferSize - 5;
+ }
+
+ // Copy as much as possible from input to output:
+ while (true)
+ {
+ // Fill the window as much as possible:
+ if (_validBytesAhead <= 1)
+ {
+ fill_window();
+ if (_validBytesAhead == 0 && flush == FlushType.Z_NO_FLUSH) return NeedMore;
+ if (_validBytesAhead == 0) break; // flush the current block
+ }
+
+ _startInsertString += _validBytesAhead;
+ _validBytesAhead = 0;
+
+ // Emit a stored block if pending_buf will be full:
+ max_start = _blockStart + max_block_size;
+ if (_startInsertString == 0 || _startInsertString >= max_start)
+ {
+ // strstart == 0 is possible when wraparound on 16-bit machine
+ _validBytesAhead = (int)(_startInsertString - max_start);
+ _startInsertString = (int)max_start;
+
+ flush_block_only(false);
+ if (base.avail_out == 0) return NeedMore;
+
+ }
+
+ // Flush if we may have to slide, otherwise block_start may become
+ // negative and the data will be gone:
+ if (_startInsertString - _blockStart >= _windowSize - MIN_LOOKAHEAD)
+ {
+ flush_block_only(false);
+ if (base.avail_out == 0) return NeedMore;
+ }
+ }
+
+ flush_block_only(flush == FlushType.Z_FINISH);
+ if (base.avail_out == 0)
+ return (flush == FlushType.Z_FINISH) ? FinishStarted : NeedMore;
+
+ return flush == FlushType.Z_FINISH ? FinishDone : BlockDone;
+ }
+
+ // Send a stored block
+ private void _tr_stored_block(int buf, // input block
+ int stored_len, // length of input block
+ bool eof // true if this is the last block for a file
+ )
+ {
+ send_bits((STORED_BLOCK << 1) + (eof ? 1 : 0), 3); // send block type
+ copy_block(buf, stored_len, true); // with header
+ }
+
+ // Determine the best encoding for the current block: dynamic trees, static
+ // trees or store, and output the encoded block to the zip file.
+ private void _tr_flush_block(int buf, // input block, or NULL if too old
+ int stored_len, // length of input block
+ bool eof // true if this is the last block for a file
+ )
+ {
+ int opt_lenb, static_lenb;// opt_len and static_len in bytes
+ int max_blindex = 0; // index of last bit length code of non zero freq
+
+ // Build the Huffman trees unless a stored block is forced
+ if (level > 0)
+ {
+ // Check if the file is ascii or binary
+ if (this._dataType == BlockType.Z_UNKNOWN) set_data_type();
+
+ // Construct the literal and distance trees
+ l_desc.BuildTree(this);
+
+ d_desc.BuildTree(this);
+
+ // At this point, opt_len and static_len are the total bit lengths of
+ // the compressed block data, excluding the tree representations.
+
+ // Build the bit length tree for the above two trees, and get the index
+ // in bl_order of the last bit length code to send.
+ max_blindex = build_bl_tree();
+
+ // Determine the best encoding. Compute first the block length in bytes
+ opt_lenb = (opt_len + 3 + 7) >> 3;
+ static_lenb = (static_len + 3 + 7) >> 3;
+
+ if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
+ }
+ else
+ {
+ opt_lenb = static_lenb = stored_len + 5; // force a stored block
+ }
+
+ if (stored_len + 4 <= opt_lenb && buf != -1)
+ {
+ // 4: two words for the lengths
+ // The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
+ // Otherwise we can't have processed more than WSIZE input bytes since
+ // the last block flush, because compression would have been
+ // successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
+ // transform a block into a stored block.
+ _tr_stored_block(buf, stored_len, eof);
+ }
+ else if (static_lenb == opt_lenb)
+ {
+ send_bits((STATIC_TREES << 1) + (eof ? 1 : 0), 3);
+ compress_block(Deflate.static_ltree, Deflate.static_dtree);
+ }
+ else
+ {
+ send_bits((DYN_TREES << 1) + (eof ? 1 : 0), 3);
+ send_all_trees(l_desc.LargestCode + 1, d_desc.LargestCode + 1, max_blindex + 1);
+ compress_block(dyn_ltree, dyn_dtree);
+ }
+
+ // The above check is made mod 2^32, for files larger than 512 MB
+ // and uLong implemented on 32 bits.
+
+ init_block();
+
+ if (eof)
+ {
+ bi_windup();
+ }
+ }
+
+ // Fill the window when the lookahead becomes insufficient.
+ // Updates strstart and lookahead.
+ //
+ // IN assertion: lookahead < MIN_LOOKAHEAD
+ // OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
+ // At least one byte has been read, or avail_in == 0; reads are
+ // performed for at least two bytes (required for the zip translate_eol
+ // option -- not supported here).
+ private void fill_window()
+ {
+ int n, m;
+ int p;
+ int more; // Amount of free space at the end of the window.
+
+ do
+ {
+ more = (_windowActualSize - _validBytesAhead - _startInsertString);
+
+ // Deal with !@#$% 64K limit:
+ if (more == 0 && _startInsertString == 0 && _validBytesAhead == 0)
+ {
+ more = _windowSize;
+ }
+ else if (more == -1)
+ {
+ // Very unlikely, but possible on 16 bit machine if strstart == 0
+ // and lookahead == 1 (input done one byte at time)
+ more--;
+
+ // If the window is almost full and there is insufficient lookahead,
+ // move the upper half to the lower one to make room in the upper half.
+ }
+ else if (_startInsertString >= _windowSize + _windowSize - MIN_LOOKAHEAD)
+ {
+ System.Array.Copy(_window, _windowSize, _window, 0, _windowSize);
+ _startMatchString -= _windowSize;
+ _startInsertString -= _windowSize; // we now have strstart >= MAX_DIST
+ _blockStart -= _windowSize;
+
+ // Slide the hash table (could be avoided with 32 bit values
+ // at the expense of memory usage). We slide even when level == 0
+ // to keep the hash table consistent if we switch back to level > 0
+ // later. (Using level 0 permanently is not an optimal usage of
+ // zlib, so we don't care about this pathological case.)
+
+ n = _hashSize;
+ p = n;
+ do
+ {
+ m = (_head[--p] & 0xffff);
+ _head[p] = (short)(m >= _windowSize ? (m - _windowSize) : 0);
+ }
+ while (--n != 0);
+
+ n = _windowSize;
+ p = n;
+ do
+ {
+ m = (_previous[--p] & 0xffff);
+ _previous[p] = (short)(m >= _windowSize ? (m - _windowSize) : 0);
+ // If n is not on any hash chain, prev[n] is garbage but
+ // its value will never be used.
+ }
+ while (--n != 0);
+ more += _windowSize;
+ }
+
+ if (base.avail_in == 0) return;
+
+ // If there was no sliding:
+ // strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
+ // more == window_size - lookahead - strstart
+ // => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
+ // => more >= window_size - 2*WSIZE + 2
+ // In the BIG_MEM or MMAP case (not yet supported),
+ // window_size == input_size + MIN_LOOKAHEAD &&
+ // strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
+ // Otherwise, window_size == 2*WSIZE so more >= 2.
+ // If there was sliding, more >= WSIZE. So in all cases, more >= 2.
+
+ n = this.read_buf(_window, _startInsertString + _validBytesAhead, more);
+ _validBytesAhead += n;
+
+ // Initialize the hash value now that we have some input:
+ if (_validBytesAhead >= MIN_MATCH)
+ {
+ _insertedHashIndex = _window[_startInsertString] & 0xff;
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[_startInsertString + 1] & 0xff)) & _hashMask;
+ }
+ // If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
+ // but this is not important since only literal bytes will be emitted.
+ }
+ while (_validBytesAhead < MIN_LOOKAHEAD && base.avail_in != 0);
+ }
+
+ // Compress as much as possible from the input stream, return the current
+ // block state.
+ // This function does not perform lazy evaluation of matches and inserts
+ // new strings in the dictionary only for unmatched strings or for short
+ // matches. It is used only for the fast compression options.
+ private int deflate_fast(FlushType flush)
+ {
+ // short hash_head = 0; // head of the hash chain
+ int hash_head = 0; // head of the hash chain
+ bool bflush; // set if current block must be flushed
+
+ while (true)
+ {
+ // Make sure that we always have enough lookahead, except
+ // at the end of the input file. We need MAX_MATCH bytes
+ // for the next match, plus MIN_MATCH bytes to insert the
+ // string following the next match.
+ if (_validBytesAhead < MIN_LOOKAHEAD)
+ {
+ fill_window();
+ if (_validBytesAhead < MIN_LOOKAHEAD && flush == FlushType.Z_NO_FLUSH)
+ {
+ return NeedMore;
+ }
+ if (_validBytesAhead == 0) break; // flush the current block
+ }
+
+ // Insert the string window[strstart .. strstart+2] in the
+ // dictionary, and set hash_head to the head of the hash chain:
+ if (_validBytesAhead >= MIN_MATCH)
+ {
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[(_startInsertString) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+
+ // prev[strstart&w_mask]=hash_head=head[ins_h];
+ hash_head = (_head[_insertedHashIndex] & 0xffff);
+ _previous[_startInsertString & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)_startInsertString;
+ }
+
+ // Find the longest match, discarding those <= prev_length.
+ // At this point we have always match_length < MIN_MATCH
+
+ if (hash_head != 0L &&
+ ((_startInsertString - hash_head) & 0xffff) <= _windowSize - MIN_LOOKAHEAD
+ )
+ {
+ // To simplify the code, we prevent matches with the string
+ // of window index 0 (in particular we have to avoid a match
+ // of the string with itself at the start of the input file).
+ if (strategy != CompressionStrategy.Z_HUFFMAN_ONLY)
+ {
+ _matchLength = longest_match(hash_head);
+ }
+ // longest_match() sets match_start
+ }
+ if (_matchLength >= MIN_MATCH)
+ {
+ // check_match(strstart, match_start, match_length);
+
+ bflush = _tr_tally(_startInsertString - _startMatchString, _matchLength - MIN_MATCH);
+
+ _validBytesAhead -= _matchLength;
+
+ // Insert new strings in the hash table only if the match length
+ // is not too large. This saves time but degrades compression.
+ if (_matchLength <= _maxLazyMatch &&
+ _validBytesAhead >= MIN_MATCH)
+ {
+ _matchLength--; // string at strstart already in hash table
+ do
+ {
+ _startInsertString++;
+
+ _insertedHashIndex = ((_insertedHashIndex << _hashShift) ^ (_window[(_startInsertString) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+ // prev[strstart&w_mask]=hash_head=head[ins_h];
+ hash_head = (_head[_insertedHashIndex] & 0xffff);
+ _previous[_startInsertString & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)_startInsertString;
+
+ // strstart never exceeds WSIZE-MAX_MATCH, so there are
+ // always MIN_MATCH bytes ahead.
+ }
+ while (--_matchLength != 0);
+ _startInsertString++;
+ }
+ else
+ {
+ _startInsertString += _matchLength;
+ _matchLength = 0;
+ _insertedHashIndex = _window[_startInsertString] & 0xff;
+
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[_startInsertString + 1] & 0xff)) & _hashMask;
+ // If lookahead < MIN_MATCH, ins_h is garbage, but it does not
+ // matter since it will be recomputed at next deflate call.
+ }
+ }
+ else
+ {
+ // No match, output a literal byte
+
+ bflush = _tr_tally(0, _window[_startInsertString] & 0xff);
+ _validBytesAhead--;
+ _startInsertString++;
+ }
+ if (bflush)
+ {
+
+ flush_block_only(false);
+ if (base.avail_out == 0) return NeedMore;
+ }
+ }
+
+ flush_block_only(flush == FlushType.Z_FINISH);
+ if (base.avail_out == 0)
+ {
+ if (flush == FlushType.Z_FINISH) return FinishStarted;
+ else return NeedMore;
+ }
+ return flush == FlushType.Z_FINISH ? FinishDone : BlockDone;
+ }
+
+ // Same as above, but achieves better compression. We use a lazy
+ // evaluation for matches: a match is finally adopted only if there is
+ // no better match at the next window position.
+ private int deflate_slow(FlushType flush)
+ {
+ // short hash_head = 0; // head of hash chain
+ int hash_head = 0; // head of hash chain
+ bool bflush; // set if current block must be flushed
+
+ // Process the input block.
+ while (true)
+ {
+ // Make sure that we always have enough lookahead, except
+ // at the end of the input file. We need MAX_MATCH bytes
+ // for the next match, plus MIN_MATCH bytes to insert the
+ // string following the next match.
+
+ if (_validBytesAhead < MIN_LOOKAHEAD)
+ {
+ fill_window();
+ if (_validBytesAhead < MIN_LOOKAHEAD && flush == FlushType.Z_NO_FLUSH)
+ {
+ return NeedMore;
+ }
+ if (_validBytesAhead == 0) break; // flush the current block
+ }
+
+ // Insert the string window[strstart .. strstart+2] in the
+ // dictionary, and set hash_head to the head of the hash chain:
+
+ if (_validBytesAhead >= MIN_MATCH)
+ {
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[(_startInsertString) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+ // prev[strstart&w_mask]=hash_head=head[ins_h];
+ hash_head = (_head[_insertedHashIndex] & 0xffff);
+ _previous[_startInsertString & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)_startInsertString;
+ }
+
+ // Find the longest match, discarding those <= prev_length.
+ _previousLength = _matchLength; _previousMatch = _startMatchString;
+ _matchLength = MIN_MATCH - 1;
+
+ if (hash_head != 0 && _previousLength < _maxLazyMatch &&
+ ((_startInsertString - hash_head) & 0xffff) <= _windowSize - MIN_LOOKAHEAD
+ )
+ {
+ // To simplify the code, we prevent matches with the string
+ // of window index 0 (in particular we have to avoid a match
+ // of the string with itself at the start of the input file).
+
+ if (strategy != CompressionStrategy.Z_HUFFMAN_ONLY)
+ {
+ _matchLength = longest_match(hash_head);
+ }
+ // longest_match() sets match_start
+
+ if (_matchLength <= 5 && (strategy == CompressionStrategy.Z_FILTERED ||
+ (_matchLength == MIN_MATCH &&
+ _startInsertString - _startMatchString > 4096)))
+ {
+
+ // If prev_match is also MIN_MATCH, match_start is garbage
+ // but we will ignore the current match anyway.
+ _matchLength = MIN_MATCH - 1;
+ }
+ }
+
+ // If there was a match at the previous step and the current
+ // match is not better, output the previous match:
+ if (_previousLength >= MIN_MATCH && _matchLength <= _previousLength)
+ {
+ int max_insert = _startInsertString + _validBytesAhead - MIN_MATCH;
+ // Do not insert strings in hash table beyond this.
+
+ // check_match(strstart-1, prev_match, prev_length);
+
+ bflush = _tr_tally(_startInsertString - 1 - _previousMatch, _previousLength - MIN_MATCH);
+
+ // Insert in hash table all strings up to the end of the match.
+ // strstart-1 and strstart are already inserted. If there is not
+ // enough lookahead, the last two strings are not inserted in
+ // the hash table.
+ _validBytesAhead -= _previousLength - 1;
+ _previousLength -= 2;
+ do
+ {
+ if (++_startInsertString <= max_insert)
+ {
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[(_startInsertString) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+ //prev[strstart&w_mask]=hash_head=head[ins_h];
+ hash_head = (_head[_insertedHashIndex] & 0xffff);
+ _previous[_startInsertString & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)_startInsertString;
+ }
+ }
+ while (--_previousLength != 0);
+ _matchAvailable = false;
+ _matchLength = MIN_MATCH - 1;
+ _startInsertString++;
+
+ if (bflush)
+ {
+ flush_block_only(false);
+ if (base.avail_out == 0) return NeedMore;
+ }
+ }
+ else if (_matchAvailable != false)
+ {
+
+ // If there was no match at the previous position, output a
+ // single literal. If there was a match but the current match
+ // is longer, truncate the previous match to a single literal.
+
+ bflush = _tr_tally(0, _window[_startInsertString - 1] & 0xff);
+
+ if (bflush)
+ {
+ flush_block_only(false);
+ }
+ _startInsertString++;
+ _validBytesAhead--;
+ if (base.avail_out == 0) return NeedMore;
+ }
+ else
+ {
+ // There is no previous match to compare with, wait for
+ // the next step to decide.
+
+ _matchAvailable = true;
+ _startInsertString++;
+ _validBytesAhead--;
+ }
+ }
+
+ if (_matchAvailable != false)
+ {
+ bflush = _tr_tally(0, _window[_startInsertString - 1] & 0xff);
+ _matchAvailable = false;
+ }
+ flush_block_only(flush == FlushType.Z_FINISH);
+
+ if (base.avail_out == 0)
+ {
+ if (flush == FlushType.Z_FINISH) return FinishStarted;
+ else return NeedMore;
+ }
+
+ return flush == FlushType.Z_FINISH ? FinishDone : BlockDone;
+ }
+
+ private int longest_match(int cur_match)
+ {
+ int chain_length = _maxChainLength; // max hash chain length
+ int scan = _startInsertString; // current string
+ int match; // matched string
+ int len; // length of current match
+ int best_len = _previousLength; // best match length so far
+ int limit = _startInsertString > (_windowSize - MIN_LOOKAHEAD) ?
+ _startInsertString - (_windowSize - MIN_LOOKAHEAD) : 0;
+ int nice_match = this.nice_match;
+
+ // Stop when cur_match becomes <= limit. To simplify the code,
+ // we prevent matches with the string of window index 0.
+
+ int wmask = _windowMask;
+
+ int strend = _startInsertString + MAX_MATCH;
+ byte scan_end1 = _window[scan + best_len - 1];
+ byte scan_end = _window[scan + best_len];
+
+ // The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+ // It is easy to get rid of this optimization if necessary.
+
+ // Do not waste too much time if we already have a good match:
+ if (_previousLength >= good_match)
+ {
+ chain_length >>= 2;
+ }
+
+ // Do not look for matches beyond the end of the input. This is necessary
+ // to make deflate deterministic.
+ if (nice_match > _validBytesAhead) nice_match = _validBytesAhead;
+
+ do
+ {
+ match = cur_match;
+
+ // Skip to next match if the match length cannot increase
+ // or if the match length is less than 2:
+ if (_window[match + best_len] != scan_end ||
+ _window[match + best_len - 1] != scan_end1 ||
+ _window[match] != _window[scan] ||
+ _window[++match] != _window[scan + 1]) continue;
+
+ // The check at best_len-1 can be removed because it will be made
+ // again later. (This heuristic is not always a win.)
+ // It is not necessary to compare scan[2] and match[2] since they
+ // are always equal when the other bytes match, given that
+ // the hash keys are equal and that HASH_BITS >= 8.
+ scan += 2; match++;
+
+ // We check for insufficient lookahead only every 8th comparison;
+ // the 256th check will be made at strstart+258.
+ do
+ {
+ } while (_window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ scan < strend);
+
+ len = MAX_MATCH - (int)(strend - scan);
+ scan = strend - MAX_MATCH;
+
+ if (len > best_len)
+ {
+ _startMatchString = cur_match;
+ best_len = len;
+ if (len >= nice_match) break;
+ scan_end1 = _window[scan + best_len - 1];
+ scan_end = _window[scan + best_len];
+ }
+
+ } while ((cur_match = (_previous[cur_match & wmask] & 0xffff)) > limit
+ && --chain_length != 0);
+
+ if (best_len <= _validBytesAhead) return best_len;
+ return _validBytesAhead;
+ }
+
+ internal ZLibStatus deflate(ZStream strm, FlushType flush)
+ {
+ FlushType old_flush;
+
+ if (flush > FlushType.Z_FINISH || flush < 0)
+ {
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+
+ if (strm.next_out == null ||
+ (strm.next_in == null && strm.avail_in != 0) ||
+ (_status == FINISH_STATE && flush != FlushType.Z_FINISH))
+ {
+ strm.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_STREAM_ERROR)];
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+ if (strm.avail_out == 0)
+ {
+ strm.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_BUF_ERROR)];
+ return ZLibStatus.Z_BUF_ERROR;
+ }
+
+ old_flush = last_flush;
+ last_flush = flush;
+
+ // Write the zlib header
+ if (_status == INIT_STATE)
+ {
+ int header = (Z_DEFLATED + ((this._windowBits - 8) << 4)) << 8;
+ int level_flags = (((int)this.level - 1) & 0xff) >> 1;
+
+ if (level_flags > 3) level_flags = 3;
+ header |= (level_flags << 6);
+ if (this._startInsertString != 0) header |= PRESET_DICT;
+ header += 31 - (header % 31);
+
+ _status = BUSY_STATE;
+ putShortMSB(header);
+
+
+ // Save the adler32 of the preset dictionary:
+ if (this._startInsertString != 0)
+ {
+ putShortMSB((int)(strm.adler >> 16));
+ putShortMSB((int)(strm.adler & 0xffff));
+ }
+ strm.adler = Adler32.adler32(0, null, 0, 0);
+ }
+
+ // Flush as much pending output as possible
+ if (pending != 0)
+ {
+ this.flush_pending();
+ if (strm.avail_out == 0)
+ {
+ //System.out.println(" avail_out==0");
+ // Since avail_out is 0, deflate will be called again with
+ // more output space, but possibly with both pending and
+ // avail_in equal to zero. There won't be anything to do,
+ // but this is not an error situation so make sure we
+ // return OK instead of BUF_ERROR at next call of deflate:
+ last_flush = (FlushType)(-1);
+ return ZLibStatus.Z_OK;
+ }
+
+ // Make sure there is something to do and avoid duplicate consecutive
+ // flushes. For repeated and useless calls with Z_FINISH, we keep
+ // returning Z_STREAM_END instead of Z_BUFF_ERROR.
+ }
+ else if (strm.avail_in == 0 && flush <= old_flush &&
+ flush != FlushType.Z_FINISH)
+ {
+ strm.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_BUF_ERROR)];
+ return ZLibStatus.Z_BUF_ERROR;
+ }
+
+ // User must not provide more input after the first FINISH:
+ if (_status == FINISH_STATE && strm.avail_in != 0)
+ {
+ strm.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_BUF_ERROR)];
+ return ZLibStatus.Z_BUF_ERROR;
+ }
+
+ // Start a new block or continue the current one.
+ if (strm.avail_in != 0 || this._validBytesAhead != 0 ||
+ (flush != FlushType.Z_NO_FLUSH && _status != FINISH_STATE))
+ {
+ int bstate = -1;
+ switch (config_table[level].Function)
+ {
+ case DefalteFlavor.STORED:
+ bstate = deflate_stored(flush);
+ break;
+ case DefalteFlavor.FAST:
+ bstate = deflate_fast(flush);
+ break;
+ case DefalteFlavor.SLOW:
+ bstate = deflate_slow(flush);
+ break;
+ default:
+ break;
+ }
+
+ if (bstate == FinishStarted || bstate == FinishDone)
+ {
+ _status = FINISH_STATE;
+ }
+ if (bstate == NeedMore || bstate == FinishStarted)
+ {
+ if (strm.avail_out == 0)
+ {
+ last_flush = (FlushType)(-1); // avoid BUF_ERROR next call, see above
+ }
+ return ZLibStatus.Z_OK;
+ // If flush != Z_NO_FLUSH && avail_out == 0, the next call
+ // of deflate should use the same flush parameter to make sure
+ // that the flush is complete. So we don't have to output an
+ // empty block here, this will be done at next call. This also
+ // ensures that for a very small output buffer, we emit at most
+ // one empty block.
+ }
+
+ if (bstate == BlockDone)
+ {
+ if (flush == FlushType.Z_PARTIAL_FLUSH)
+ {
+ _tr_align();
+ }
+ else
+ { // FULL_FLUSH or SYNC_FLUSH
+ _tr_stored_block(0, 0, false);
+ // For a full flush, this empty block will be recognized
+ // as a special marker by inflate_sync().
+ if (flush == FlushType.Z_FULL_FLUSH)
+ {
+ //state.head[s.hash_size-1]=0;
+ for (int i = 0; i < this._hashSize/*-1*/; i++) // forget history
+ this._head[i] = 0;
+ }
+ }
+ this.flush_pending();
+ if (strm.avail_out == 0)
+ {
+ last_flush = (FlushType)(-1); // avoid BUF_ERROR at next call, see above
+ return ZLibStatus.Z_OK;
+ }
+ }
+ }
+
+ if (flush != FlushType.Z_FINISH) return ZLibStatus.Z_OK;
+ if (noheader != 0) return ZLibStatus.Z_STREAM_END;
+
+ // Write the zlib trailer (adler32)
+ putShortMSB((int)(strm.adler >> 16));
+ putShortMSB((int)(strm.adler & 0xffff));
+ this.flush_pending();
+
+ // If avail_out is zero, the application will call deflate again
+ // to flush the rest.
+ noheader = -1; // write the trailer only once!
+ return pending != 0 ? ZLibStatus.Z_OK : ZLibStatus.Z_STREAM_END;
+ }
+
+
+ private static readonly StaticTree static_l_desc = new StaticTree(static_ltree, Deflate.extra_lbits, LITERALS + 1, L_CODES, MAX_BITS);
+
+ private static readonly StaticTree static_d_desc = new StaticTree(static_dtree, Deflate.extra_dbits, 0, D_CODES, MAX_BITS);
+
+ private static readonly StaticTree static_bl_desc = new StaticTree(null, Deflate.extra_blbits, 0, BL_CODES, MAX_BL_BITS);
+
+ private class Config
+ {
+ ///
+ /// Reduce lazy search above this match length
+ ///
+ internal int GoodLength { get; private set; }
+ ///
+ /// Gets or sets whether not to perform lazy search above this match length
+ ///
+ ///
+ /// The max lazy.
+ ///
+ internal int MaxLazy { get; private set; }
+ ///
+ /// Gets or sets whether to quit search above this match length
+ ///
+ ///
+ /// The length of the nice.
+ ///
+ internal int NiceLength { get; private set; }
+ internal int MaxChain { get; private set; }
+ internal DefalteFlavor Function { get; private set; }
+ internal Config(int goodLength, int maxLazy, int niceLength, int maxChain, DefalteFlavor function)
+ {
+ this.GoodLength = goodLength;
+ this.MaxLazy = maxLazy;
+ this.NiceLength = niceLength;
+ this.MaxChain = maxChain;
+ this.Function = function;
+ }
+ }
+
+ public ZLibStatus deflate(FlushType flush)
+ {
+ return this.deflate(this, flush);
+ }
+ public ZLibStatus deflateParams(CompressionLevel level, CompressionStrategy strategy)
+ {
+ return this.deflateParams(this, level, strategy);
+ }
+ public ZLibStatus deflateSetDictionary(byte[] dictionary, int dictLength)
+ {
+ return this.deflateSetDictionary(this, dictionary, dictLength);
+ }
+
+
+ // Flush as much pending output as possible. All deflate() output goes
+ // through this function so some applications may wish to modify it
+ // to avoid allocating a large strm->next_out buffer and copying into it.
+ // (See also read_buf()).
+ internal void flush_pending()
+ {
+ int len = this.pending;
+
+ if (len > avail_out) len = avail_out;
+ if (len == 0) return;
+
+ if (this.pending_buf.Length <= this.pending_out ||
+ next_out.Length <= next_out_index ||
+ this.pending_buf.Length < (this.pending_out + len) ||
+ next_out.Length < (next_out_index + len))
+ {
+ // System.out.println(this.pending_buf.length+", "+this.pending_out+
+ // ", "+next_out.length+", "+next_out_index+", "+len);
+ // System.out.println("avail_out="+avail_out);
+ }
+
+ System.Array.Copy(this.pending_buf, this.pending_out,
+ next_out, next_out_index, len);
+
+ next_out_index += len;
+ this.pending_out += len;
+ total_out += len;
+ avail_out -= len;
+ this.pending -= len;
+ if (this.pending == 0)
+ {
+ this.pending_out = 0;
+ }
+ }
+
+ // Read a new buffer from the current input stream, update the adler32
+ // and total number of bytes read. All deflate() input goes through
+ // this function so some applications may wish to modify it to avoid
+ // allocating a large strm->next_in buffer and copying from it.
+ // (See also flush_pending()).
+ internal int read_buf(byte[] buf, int start, int size)
+ {
+ int len = avail_in;
+
+ if (len > size) len = size;
+ if (len == 0) return 0;
+
+ avail_in -= len;
+
+ if (this.noheader == 0)
+ {
+ adler = Adler32.adler32(adler, next_in, next_in_index, len);
+ }
+ System.Array.Copy(next_in, next_in_index, buf, start, len);
+ next_in_index += len;
+ total_in += len;
+ return len;
+ }
+
+ public ZLibStatus deflate(byte[] inputBufer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType)
+ {
+ this.next_in = inputBufer;
+ this.next_in_index = inputOffset;
+ this.avail_in = inputCount;
+ this.next_out = outputBuffer;
+ this.next_out_index = outputOffset;
+ this.avail_out = outputCount;
+ return this.deflate(flushType);
+ }
+
+ // TODO: Delete this
+ public ZLibStatus inflateEnd()
+ {
+ throw new NotImplementedException();
+ }
+
+ public ZLibStatus inflate(FlushType flushType)
+ {
+ throw new NotImplementedException();
+ }
+
+ public ZLibStatus inflate(byte[] bufer, int offset, int count, byte[] p1, int p2, int p3, FlushType flushType)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Version.7/Inflate.cs b/Renci.SshNet/Compression/Version.7/Inflate.cs
new file mode 100644
index 0000000..8019fd0
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.7/Inflate.cs
@@ -0,0 +1,517 @@
+using System;
+/*
+ * $Id: Inflate.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public enum InflateMode : int
+ {
+ ///
+ ///waiting for method byte
+ ///
+ METHOD = 0,
+ ///
+ /// waiting for flag byte
+ ///
+ FLAG = 1,
+ ///
+ /// four dictionary check bytes to go
+ ///
+ DICT4 = 2,
+ ///
+ /// three dictionary check bytes to go
+ ///
+ DICT3 = 3,
+ ///
+ /// two dictionary check bytes to go
+ ///
+ DICT2 = 4,
+ ///
+ /// one dictionary check byte to go
+ ///
+ DICT1 = 5,
+ ///
+ /// waiting for inflateSetDictionary
+ ///
+ DICT0 = 6,
+ ///
+ /// decompressing blocks
+ ///
+ BLOCKS = 7,
+ ///
+ /// four check bytes to go
+ ///
+ CHECK4 = 8,
+ ///
+ /// three check bytes to go
+ ///
+ CHECK3 = 9,
+ ///
+ /// two check bytes to go
+ ///
+ CHECK2 = 10,
+ ///
+ /// one check byte to go
+ ///
+ CHECK1 = 11,
+ ///
+ /// finished check, done
+ ///
+ DONE = 12,
+ ///
+ /// got an error--stay here
+ ///
+ BAD = 13
+ }
+
+ internal sealed class Inflate : ZStream, ICompressor
+ {
+ // preset dictionary flag in zlib header
+ private const int PRESET_DICT = 0x20;
+
+ private const int Z_DEFLATED = 8;
+
+ private static readonly byte[] mark = { (byte)0, (byte)0, (byte)0xff, (byte)0xff };
+
+ ///
+ /// The current inflate mode
+ ///
+ private InflateMode _mode;
+
+ ///
+ /// if FLAGS, method byte
+ ///
+ private int method;
+
+ ///
+ /// Computed check value
+ ///
+ private long[] _was = new long[1];
+
+ ///
+ /// The stream check value
+ ///
+ private long _need;
+
+ ///
+ /// if BAD, inflateSync's marker bytes count
+ ///
+ private int _marker;
+
+ // mode independent information
+ ///
+ /// Flag for no wrapper
+ ///
+ private int _nowrap;
+
+ ///
+ /// log2(window size) (8..15, defaults to 15)
+ ///
+ private int _wbits;
+
+ ///
+ /// Current inflate_blocks state
+ ///
+ private InflateBlocks _blocks;
+
+ public Inflate()
+ {
+ this.inflateInit();
+ }
+
+ public Inflate(bool nowrap)
+ {
+ this.inflateInit(nowrap);
+ }
+
+ private ZLibStatus InflateReset()
+ {
+ base.total_in = base.total_out = 0;
+ base.msg = null;
+ this._mode = this._nowrap != 0 ? InflateMode.BLOCKS : InflateMode.METHOD;
+ this._blocks.reset(this, null);
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus InflateEnd(ZStream z)
+ {
+ if (_blocks != null)
+ _blocks.free(z);
+ _blocks = null;
+ // ZFREE(z, z->state);
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus InflateInit(ZStream z, int w)
+ {
+ base.msg = null;
+ _blocks = null;
+
+ // handle undocumented nowrap option (no zlib header or check)
+ _nowrap = 0;
+ if (w < 0)
+ {
+ w = -w;
+ _nowrap = 1;
+ }
+
+ // set window size
+ if (w < 8 || w > 15)
+ {
+ InflateEnd(z);
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+ _wbits = w;
+
+ this._blocks = new InflateBlocks(z,
+ this._nowrap != 0 ? null : this,
+ 1 << w);
+
+ // reset state
+ InflateReset();
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus inflate(FlushType ff)
+ {
+ ZLibStatus r;
+ int b;
+
+ if (base.next_in == null)
+ return ZLibStatus.Z_STREAM_ERROR;
+ var f = ff == FlushType.Z_FINISH ? ZLibStatus.Z_BUF_ERROR : ZLibStatus.Z_OK;
+ r = ZLibStatus.Z_BUF_ERROR;
+ while (true)
+ {
+ //System.out.println("mode: "+this.mode);
+ switch (this._mode)
+ {
+ case InflateMode.METHOD:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ if (((this.method = base.next_in[base.next_in_index++]) & 0xf) != Z_DEFLATED)
+ {
+ this._mode = InflateMode.BAD;
+ base.msg = "unknown compression method";
+ this._marker = 5; // can't try inflateSync
+ break;
+ }
+ if ((this.method >> 4) + 8 > this._wbits)
+ {
+ this._mode = InflateMode.BAD;
+ base.msg = "invalid window size";
+ this._marker = 5; // can't try inflateSync
+ break;
+ }
+ this._mode = InflateMode.FLAG;
+ goto case InflateMode.FLAG;
+ case InflateMode.FLAG:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ b = (base.next_in[base.next_in_index++]) & 0xff;
+
+ if ((((this.method << 8) + b) % 31) != 0)
+ {
+ this._mode = InflateMode.BAD;
+ base.msg = "incorrect header check";
+ this._marker = 5; // can't try inflateSync
+ break;
+ }
+
+ if ((b & PRESET_DICT) == 0)
+ {
+ this._mode = InflateMode.BLOCKS;
+ break;
+ }
+ this._mode = InflateMode.DICT4;
+ goto case InflateMode.DICT4;
+ case InflateMode.DICT4:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need = ((base.next_in[base.next_in_index++] & 0xff) << 24) & 0xff000000L;
+ this._mode = InflateMode.DICT3;
+ goto case InflateMode.DICT3;
+ case InflateMode.DICT3:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += ((base.next_in[base.next_in_index++] & 0xff) << 16) & 0xff0000L;
+ this._mode = InflateMode.DICT2;
+ goto case InflateMode.DICT2;
+ case InflateMode.DICT2:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += ((base.next_in[base.next_in_index++] & 0xff) << 8) & 0xff00L;
+ this._mode = InflateMode.DICT1;
+ goto case InflateMode.DICT1;
+ case InflateMode.DICT1:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += (base.next_in[base.next_in_index++] & 0xffL);
+ base.adler = this._need;
+ this._mode = InflateMode.DICT0;
+ return ZLibStatus.Z_NEED_DICT;
+ case InflateMode.DICT0:
+ this._mode = InflateMode.BAD;
+ base.msg = "need dictionary";
+ this._marker = 0; // can try inflateSync
+ return ZLibStatus.Z_STREAM_ERROR;
+ case InflateMode.BLOCKS:
+
+ r = this._blocks.proc(this, r);
+ if (r == ZLibStatus.Z_DATA_ERROR)
+ {
+ this._mode = InflateMode.BAD;
+ this._marker = 0; // can try inflateSync
+ break;
+ }
+ if (r == ZLibStatus.Z_OK)
+ {
+ r = f;
+ }
+ if (r != ZLibStatus.Z_STREAM_END)
+ {
+ return r;
+ }
+ r = f;
+ this._blocks.reset(this, this._was);
+ if (this._nowrap != 0)
+ {
+ this._mode = InflateMode.DONE;
+ break;
+ }
+ this._mode = InflateMode.CHECK4;
+ goto case InflateMode.CHECK4;
+ case InflateMode.CHECK4:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need = ((base.next_in[base.next_in_index++] & 0xff) << 24) & 0xff000000L;
+ this._mode = InflateMode.CHECK3;
+ goto case InflateMode.CHECK3;
+ case InflateMode.CHECK3:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += ((base.next_in[base.next_in_index++] & 0xff) << 16) & 0xff0000L;
+ this._mode = InflateMode.CHECK2;
+ goto case InflateMode.CHECK2;
+ case InflateMode.CHECK2:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += ((base.next_in[base.next_in_index++] & 0xff) << 8) & 0xff00L;
+ this._mode = InflateMode.CHECK1;
+ goto case InflateMode.CHECK1;
+ case InflateMode.CHECK1:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += (base.next_in[base.next_in_index++] & 0xffL);
+
+ if (((int)(this._was[0])) != ((int)(this._need)))
+ {
+ this._mode = InflateMode.BAD;
+ base.msg = "incorrect data check";
+ this._marker = 5; // can't try inflateSync
+ break;
+ }
+
+ this._mode = InflateMode.DONE;
+ goto case InflateMode.DONE;
+ case InflateMode.DONE:
+ return ZLibStatus.Z_STREAM_END;
+ case InflateMode.BAD:
+ return ZLibStatus.Z_DATA_ERROR;
+ default:
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+ }
+ }
+
+ public ZLibStatus InflateSetDictionary(byte[] dictionary, int dictLength)
+ {
+ int index = 0;
+ int length = dictLength;
+ if (this._mode != InflateMode.DICT0)
+ return ZLibStatus.Z_STREAM_ERROR;
+
+ if (Adler32.adler32(1L, dictionary, 0, dictLength) != base.adler)
+ {
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+
+ base.adler = Adler32.adler32(0, null, 0, 0);
+
+ if (length >= (1 << this._wbits))
+ {
+ length = (1 << this._wbits) - 1;
+ index = dictLength - length;
+ }
+ this._blocks.set_dictionary(dictionary, index, length);
+ this._mode = InflateMode.BLOCKS;
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus InflateSync(ZStream z)
+ {
+ int n; // number of bytes to look at
+ int p; // pointer to bytes
+ int m; // number of marker bytes found in a row
+ long r, w; // temporaries to save total_in and total_out
+
+ // set up
+ if (this._mode != InflateMode.BAD)
+ {
+ this._mode = InflateMode.BAD;
+ this._marker = 0;
+ }
+ if ((n = base.avail_in) == 0)
+ return ZLibStatus.Z_BUF_ERROR;
+ p = base.next_in_index;
+ m = this._marker;
+
+ // search
+ while (n != 0 && m < 4)
+ {
+ if (base.next_in[p] == mark[m])
+ {
+ m++;
+ }
+ else if (base.next_in[p] != 0)
+ {
+ m = 0;
+ }
+ else
+ {
+ m = 4 - m;
+ }
+ p++; n--;
+ }
+
+ // restore
+ base.total_in += p - base.next_in_index;
+ base.next_in_index = p;
+ base.avail_in = n;
+ this._marker = m;
+
+ // return no joy or set up to restart on a new block
+ if (m != 4)
+ {
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ r = base.total_in; w = base.total_out;
+ InflateReset();
+ base.total_in = r; base.total_out = w;
+ this._mode = InflateMode.BLOCKS;
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus inflateInit()
+ {
+ return inflateInit(DEF_WBITS);
+ }
+ public ZLibStatus inflateInit(bool nowrap)
+ {
+ return inflateInit(DEF_WBITS, nowrap);
+ }
+ public ZLibStatus inflateInit(int w)
+ {
+ return inflateInit(w, false);
+ }
+
+ public ZLibStatus inflateInit(int w, bool nowrap)
+ {
+ return this.InflateInit(this, nowrap ? -w : w);
+ }
+
+ public ZLibStatus inflateEnd()
+ {
+ var ret = this.InflateEnd(this);
+ return ret;
+ }
+ public ZLibStatus inflateSync()
+ {
+ return this.InflateSync(this);
+ }
+ public ZLibStatus inflateSetDictionary(byte[] dictionary, int dictLength)
+ {
+ return this.InflateSetDictionary(dictionary, dictLength);
+ }
+
+ public ZLibStatus inflate(byte[] inputBufer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType)
+ {
+ this.next_in = inputBufer;
+ this.next_in_index = inputOffset;
+ this.avail_in = inputCount;
+ this.next_out = outputBuffer;
+ this.next_out_index = outputOffset;
+ this.avail_out = outputCount;
+ return this.inflate(flushType);
+ }
+
+ // TODO: Dlete this
+ public ZLibStatus deflate(byte[] bufer, int offset, int count, byte[] p1, int p2, int p3, FlushType flushType)
+ {
+ throw new NotImplementedException();
+ }
+
+ public ZLibStatus deflateEnd()
+ {
+ throw new NotImplementedException();
+ }
+
+ public ZLibStatus deflate(FlushType flushType)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Version.7/InflateBlocks.cs b/Renci.SshNet/Compression/Version.7/InflateBlocks.cs
new file mode 100644
index 0000000..273389f
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.7/InflateBlocks.cs
@@ -0,0 +1,721 @@
+using System;
+/*
+ * $Id: InfBlocks.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public enum InflateBlockMode
+ {
+ ///
+ /// get type bits (3, including end bit)
+ ///
+ TYPE = 0,
+ ///
+ /// get lengths for stored
+ ///
+ LENS = 1,
+ ///
+ /// cessing stored block
+ ///
+ STORED = 2,
+ ///
+ /// get table lengths
+ ///
+ TABLE = 3,
+ ///
+ /// get bit lengths tree for a dynamic block
+ ///
+ BTREE = 4,
+ ///
+ /// get length, distance trees for a dynamic block
+ ///
+ DTREE = 5,
+ ///
+ /// processing fixed or dynamic block
+ ///
+ CODES = 6,
+ ///
+ /// output remaining window bytes
+ ///
+ DRY = 7,
+ ///
+ /// finished last block, done
+ ///
+ DONE = 8,
+ ///
+ /// ot a data error--stuck here
+ ///
+ BAD = 9
+ }
+
+ internal sealed class InflateBlocks : InflateCodes
+ {
+ private const int MANY = 1440;
+
+ // And'ing with mask[n] masks the lower n bits
+ private static readonly int[] inflate_mask = {
+ 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
+ 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
+ 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
+ 0x00007fff, 0x0000ffff
+ };
+
+ // Table for deflate from PKZIP's appnote.txt.
+ static readonly int[] border = { // Order of the bit length code lengths
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
+ };
+
+ internal InflateBlockMode mode; // current inflate_block mode
+
+ internal int left; // if STORED, bytes left to copy
+
+ internal int table; // table lengths (14 bits)
+ internal int index; // index into blens (or border)
+ internal int[] blens; // bit lengths of codes
+ internal int[] bb = new int[1]; // bit length tree depth
+ internal int[] tb = new int[1]; // bit length decoding tree
+
+ //internal InfCodes codes = new InfCodes(); // if CODES, current state
+
+ int last; // true if this block is the last block
+
+ // mode independent information
+ internal int bitk; // bits in bit buffer
+ internal int bitb; // bit buffer
+ internal int[] hufts; // single malloc for tree space
+ internal byte[] window; // sliding window
+ internal int end; // one byte after sliding window
+ internal int read; // window read pointer
+ internal int write; // window write pointer
+ internal Object checkfn; // check function
+ internal long check; // check on output
+
+ internal InflateTree inftree = new InflateTree();
+
+ internal InflateBlocks(ZStream z, Object checkfn, int w)
+ {
+ hufts = new int[MANY * 3];
+ window = new byte[w];
+ end = w;
+ this.checkfn = checkfn;
+ mode = InflateBlockMode.TYPE;
+ reset(z, null);
+ }
+
+ internal void reset(ZStream z, long[] c)
+ {
+ if (c != null) c[0] = check;
+ if (mode == InflateBlockMode.BTREE || mode == InflateBlockMode.DTREE)
+ {
+ }
+ if (mode == InflateBlockMode.CODES)
+ {
+ codesfree(z);
+ }
+ mode = InflateBlockMode.TYPE;
+ bitk = 0;
+ bitb = 0;
+ read = write = 0;
+
+ if (checkfn != null)
+ z.adler = check = Adler32.adler32(0L, null, 0, 0);
+ }
+
+ internal ZLibStatus proc(ZStream z, ZLibStatus r)
+ {
+ int t; // temporary storage
+ ZLibStatus tt;
+ int b; // bit buffer
+ int k; // bits in bit buffer
+ int p; // input data pointer
+ int n; // bytes available there
+ int q; // output window write pointer
+ int m;
+ { // bytes to end of window or read pointer
+
+ // copy input/output information to locals (UPDATE macro restores)
+ p = z.next_in_index; n = z.avail_in; b = bitb; k = bitk;
+ }
+ {
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+ }
+
+ // process input based on current state
+ while (true)
+ {
+ switch (mode)
+ {
+ case InflateBlockMode.TYPE:
+
+ while (k < (3))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+ t = (int)(b & 7);
+ last = t & 1;
+
+ switch (t >> 1)
+ {
+ case 0:
+ { // stored
+ b >>= (3); k -= (3);
+ }
+ t = k & 7;
+ { // go to byte boundary
+
+ b >>= (t); k -= (t);
+ }
+ mode = InflateBlockMode.LENS; // get length of stored block
+ break;
+ case 1:
+ { // fixed
+ int[] bl = new int[1];
+ int[] bd = new int[1];
+ int[][] tl = new int[1][];
+ int[][] td = new int[1][];
+
+ InflateTree.InflateTreesFixed(bl, bd, tl, td, z);
+ codesinit(bl[0], bd[0], tl[0], 0, td[0], 0, z);
+ }
+ {
+
+ b >>= (3); k -= (3);
+ }
+
+ mode = InflateBlockMode.CODES;
+ break;
+ case 2:
+ { // dynamic
+
+ b >>= (3); k -= (3);
+ }
+
+ mode = InflateBlockMode.TABLE;
+ break;
+ case 3:
+ { // illegal
+
+ b >>= (3); k -= (3);
+ }
+ mode = InflateBlockMode.BAD;
+ z.msg = "invalid block type";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ break;
+ case InflateBlockMode.LENS:
+
+ while (k < (32))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ if ((((~b) >> 16) & 0xffff) != (b & 0xffff))
+ {
+ mode = InflateBlockMode.BAD;
+ z.msg = "invalid stored block lengths";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ left = (b & 0xffff);
+ b = k = 0; // dump bits
+ mode = left != 0 ? InflateBlockMode.STORED : (last != 0 ? InflateBlockMode.DRY : InflateBlockMode.TYPE);
+ break;
+ case InflateBlockMode.STORED:
+ if (n == 0)
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+
+ if (m == 0)
+ {
+ if (q == end && read != 0)
+ {
+ q = 0; m = (int)(q < read ? read - q - 1 : end - q);
+ }
+ if (m == 0)
+ {
+ write = q;
+ r = inflate_flush(z, r);
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+ if (q == end && read != 0)
+ {
+ q = 0; m = (int)(q < read ? read - q - 1 : end - q);
+ }
+ if (m == 0)
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ }
+ }
+ r = ZLibStatus.Z_OK;
+
+ t = left;
+ if (t > n) t = n;
+ if (t > m) t = m;
+ System.Array.Copy(z.next_in, p, window, q, t);
+ p += t; n -= t;
+ q += t; m -= t;
+ if ((left -= t) != 0)
+ break;
+ mode = last != 0 ? InflateBlockMode.DRY : InflateBlockMode.TYPE;
+ break;
+ case InflateBlockMode.TABLE:
+
+ while (k < (14))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ table = t = (b & 0x3fff);
+ if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
+ {
+ mode = InflateBlockMode.BAD;
+ z.msg = "too many length or distance symbols";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
+ if (blens == null || blens.Length < t)
+ {
+ blens = new int[t];
+ }
+ else
+ {
+ for (int i = 0; i < t; i++) { blens[i] = 0; }
+ }
+ {
+
+ b >>= (14); k -= (14);
+ }
+
+ index = 0;
+ mode = InflateBlockMode.BTREE;
+ goto case InflateBlockMode.BTREE;
+ case InflateBlockMode.BTREE:
+ while (index < 4 + (table >> 10))
+ {
+ while (k < (3))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ blens[border[index++]] = b & 7;
+ {
+
+ b >>= (3); k -= (3);
+ }
+ }
+
+ while (index < 19)
+ {
+ blens[border[index++]] = 0;
+ }
+
+ bb[0] = 7;
+ tt = inftree.InflateTreesBits(blens, bb, tb, hufts, z);
+ if (tt != ZLibStatus.Z_OK)
+ {
+ r = tt;
+ if (r == ZLibStatus.Z_DATA_ERROR)
+ {
+ blens = null;
+ mode = InflateBlockMode.BAD;
+ }
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+
+ index = 0;
+ mode = InflateBlockMode.DTREE;
+ goto case InflateBlockMode.DTREE;
+ case InflateBlockMode.DTREE:
+ while (true)
+ {
+ t = table;
+ if (!(index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)))
+ {
+ break;
+ }
+
+ int i, j, c;
+
+ t = bb[0];
+
+ while (k < (t))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ if (tb[0] == -1)
+ {
+ //System.err.println("null...");
+ }
+
+ t = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 1];
+ c = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 2];
+
+ if (c < 16)
+ {
+ b >>= (t); k -= (t);
+ blens[index++] = c;
+ }
+ else
+ { // c == 16..18
+ i = c == 18 ? 7 : c - 14;
+ j = c == 18 ? 11 : 3;
+
+ while (k < (t + i))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ b >>= (t); k -= (t);
+
+ j += (b & inflate_mask[i]);
+
+ b >>= (i); k -= (i);
+
+ i = index;
+ t = table;
+ if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
+ (c == 16 && i < 1))
+ {
+ blens = null;
+ mode = InflateBlockMode.BAD;
+ z.msg = "invalid bit length repeat";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+
+ c = c == 16 ? blens[i - 1] : 0;
+ do
+ {
+ blens[i++] = c;
+ }
+ while (--j != 0);
+ index = i;
+ }
+ }
+
+ tb[0] = -1;
+ {
+ int[] bl = new int[1];
+ int[] bd = new int[1];
+ int[] tl = new int[1];
+ int[] td = new int[1];
+ bl[0] = 9; // must be <= 9 for lookahead assumptions
+ bd[0] = 6; // must be <= 9 for lookahead assumptions
+
+ t = table;
+ tt = inftree.InflateTreesDynamic(257 + (t & 0x1f),
+ 1 + ((t >> 5) & 0x1f),
+ blens, bl, bd, tl, td, hufts, z);
+
+ if (tt != ZLibStatus.Z_OK)
+ {
+ if (tt == ZLibStatus.Z_DATA_ERROR)
+ {
+ blens = null;
+ mode = InflateBlockMode.BAD;
+ }
+ r = tt;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ codesinit(bl[0], bd[0], hufts, tl[0], hufts, td[0], z);
+ }
+ mode = InflateBlockMode.CODES;
+ goto case InflateBlockMode.CODES;
+ case InflateBlockMode.CODES:
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+
+ if ((r = codesproc(this, z, r)) != ZLibStatus.Z_STREAM_END)
+ {
+ return inflate_flush(z, r);
+ }
+ r = ZLibStatus.Z_OK;
+ codesfree(z);
+
+ p = z.next_in_index; n = z.avail_in; b = bitb; k = bitk;
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+
+ if (last == 0)
+ {
+ mode = InflateBlockMode.TYPE;
+ break;
+ }
+ mode = InflateBlockMode.DRY;
+ goto case InflateBlockMode.DRY;
+ case InflateBlockMode.DRY:
+ write = q;
+ r = inflate_flush(z, r);
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+ if (read != write)
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ mode = InflateBlockMode.DONE;
+ goto case InflateBlockMode.DONE;
+ case InflateBlockMode.DONE:
+ r = ZLibStatus.Z_STREAM_END;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ case InflateBlockMode.BAD:
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+
+ default:
+ r = ZLibStatus.Z_STREAM_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ }
+ }
+
+ internal void free(ZStream z)
+ {
+ reset(z, null);
+ window = null;
+ hufts = null;
+ //ZFREE(z, s);
+ }
+
+ internal void set_dictionary(byte[] d, int start, int n)
+ {
+ System.Array.Copy(d, start, window, 0, n);
+ read = write = n;
+ }
+
+ // Returns true if inflate is currently at the end of a block generated
+ // by Z_SYNC_FLUSH or FlushType.Z_FULL_FLUSH.
+ internal ZLibStatus sync_point()
+ {
+ return mode == InflateBlockMode.LENS ? ZLibStatus.Z_STREAM_END : ZLibStatus.Z_OK;
+ }
+
+ // copy as much as possible from the sliding window to the output area
+ internal ZLibStatus inflate_flush(ZStream z, ZLibStatus r)
+ {
+ int n;
+ int p;
+ int q;
+
+ // local copies of source and destination pointers
+ p = z.next_out_index;
+ q = read;
+
+ // compute number of bytes to copy as far as end of window
+ n = (int)((q <= write ? write : end) - q);
+ if (n > z.avail_out) n = z.avail_out;
+ if (n != 0 && r == ZLibStatus.Z_BUF_ERROR) r = ZLibStatus.Z_OK;
+
+ // update counters
+ z.avail_out -= n;
+ z.total_out += n;
+
+ // update check information
+ if (checkfn != null)
+ z.adler = check = Adler32.adler32(check, window, q, n);
+
+ // copy as far as end of window
+ System.Array.Copy(window, q, z.next_out, p, n);
+ p += n;
+ q += n;
+
+ // see if more to copy at beginning of window
+ if (q == end)
+ {
+ // wrap pointers
+ q = 0;
+ if (write == end)
+ write = 0;
+
+ // compute bytes to copy
+ n = write - q;
+ if (n > z.avail_out) n = z.avail_out;
+ if (n != 0 && r == ZLibStatus.Z_BUF_ERROR) r = ZLibStatus.Z_OK;
+
+ // update counters
+ z.avail_out -= n;
+ z.total_out += n;
+
+ // update check information
+ if (checkfn != null)
+ z.adler = check = Adler32.adler32(check, window, q, n);
+
+ // copy
+ System.Array.Copy(window, q, z.next_out, p, n);
+ p += n;
+ q += n;
+ }
+
+ // update pointers
+ z.next_out_index = p;
+ read = q;
+
+ // done
+ return r;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Version.7/InflateCodes.cs b/Renci.SshNet/Compression/Version.7/InflateCodes.cs
new file mode 100644
index 0000000..3214e56
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.7/InflateCodes.cs
@@ -0,0 +1,690 @@
+using System;
+/*
+ * $Id: InfCodes.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public enum InflateCodeMode
+ {
+ ///
+ /// x: set up for InflateCodeMode.LEN
+ ///
+ START = 0,
+ ///
+ /// i: get length/literal/eob next
+ ///
+ LEN = 1,
+ ///
+ /// i: getting length extra (have base)
+ ///
+ LENEXT = 2,
+ ///
+ /// i: get distance next
+ ///
+ DIST = 3,
+ ///
+ /// : getting distance extra
+ ///
+ DISTEXT = 4,
+ ///
+ /// o: copying bytes in window, waiting for space
+ ///
+ COPY = 5,
+ ///
+ /// o: got literal, waiting for output space
+ ///
+ LIT = 6,
+ ///
+ /// o: got eob, possibly still output waiting
+ ///
+ WASH = 7,
+ ///
+ /// x: got eob and all data flushed
+ ///
+ END = 8,
+ ///
+ /// x: got error
+ ///
+ BADCODE = 9
+ }
+
+ internal abstract class InflateCodes// : ZStream
+ {
+ private static readonly int[] inflate_mask = {
+ 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
+ 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
+ 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
+ 0x00007fff, 0x0000ffff
+ };
+
+ InflateCodeMode mode; // current inflate_codes mode
+
+ // mode dependent information
+ int len;
+
+ int[] tree; // pointer into tree
+ int tree_index = 0;
+ int need; // bits needed
+
+ int lit;
+
+ // if EXT or COPY, where and how much
+ int get; // bits to get for extra
+ int dist; // distance back to copy from
+
+ byte lbits; // ltree bits decoded per branch
+ byte dbits; // dtree bits decoder per branch
+ int[] ltree; // literal/length/eob tree
+ int ltree_index; // literal/length/eob tree
+ int[] dtree; // distance tree
+ int dtree_index; // distance tree
+
+ internal InflateCodes()
+ {
+ }
+ internal void codesinit(int bl, int bd,
+ int[] tl, int tl_index,
+ int[] td, int td_index, ZStream z)
+ {
+ mode = InflateCodeMode.START;
+ lbits = (byte)bl;
+ dbits = (byte)bd;
+ ltree = tl;
+ ltree_index = tl_index;
+ dtree = td;
+ dtree_index = td_index;
+ tree = null;
+ }
+
+ internal ZLibStatus codesproc(InflateBlocks s, ZStream z, ZLibStatus r)
+ {
+ int j; // temporary storage
+ int tindex; // temporary pointer
+ int e; // extra bits or operation
+ int b = 0; // bit buffer
+ int k = 0; // bits in bit buffer
+ int p = 0; // input data pointer
+ int n; // bytes available there
+ int q; // output window write pointer
+ int m; // bytes to end of window or read pointer
+ int f; // pointer to copy strings from
+
+ // copy input/output information to locals (UPDATE macro restores)
+ p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk;
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ // process input and output based on current state
+ while (true)
+ {
+ switch (mode)
+ {
+ // waiting for "i:"=input, "o:"=output, "x:"=nothing
+ case InflateCodeMode.START: // x: set up for LEN
+ if (m >= 258 && n >= 10)
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ r = inflate_fast(lbits, dbits,
+ ltree, ltree_index,
+ dtree, dtree_index,
+ s, z);
+
+ p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk;
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (r != ZLibStatus.Z_OK)
+ {
+ mode = r == ZLibStatus.Z_STREAM_END ? InflateCodeMode.WASH : InflateCodeMode.BADCODE;
+ break;
+ }
+ }
+ need = lbits;
+ tree = ltree;
+ tree_index = ltree_index;
+
+ mode = InflateCodeMode.LEN;
+ goto case InflateCodeMode.LEN;
+ case InflateCodeMode.LEN: // i: get length/literal/eob next
+ j = need;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ tindex = (tree_index + (b & inflate_mask[j])) * 3;
+
+ b >>= (tree[tindex + 1]);
+ k -= (tree[tindex + 1]);
+
+ e = tree[tindex];
+
+ if (e == 0)
+ { // literal
+ lit = tree[tindex + 2];
+ mode = InflateCodeMode.LIT;
+ break;
+ }
+ if ((e & 16) != 0)
+ { // length
+ get = e & 15;
+ len = tree[tindex + 2];
+ mode = InflateCodeMode.LENEXT;
+ break;
+ }
+ if ((e & 64) == 0)
+ { // next table
+ need = e;
+ tree_index = tindex / 3 + tree[tindex + 2];
+ break;
+ }
+ if ((e & 32) != 0)
+ { // end of block
+ mode = InflateCodeMode.WASH;
+ break;
+ }
+ mode = InflateCodeMode.BADCODE; // invalid code
+ z.msg = "invalid literal/length code";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ case InflateCodeMode.LENEXT: // i: getting length extra (have base)
+ j = get;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--; b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ len += (b & inflate_mask[j]);
+
+ b >>= j;
+ k -= j;
+
+ need = dbits;
+ tree = dtree;
+ tree_index = dtree_index;
+ mode = InflateCodeMode.DIST;
+ goto case InflateCodeMode.DIST;
+ case InflateCodeMode.DIST: // i: get distance next
+ j = need;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--; b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ tindex = (tree_index + (b & inflate_mask[j])) * 3;
+
+ b >>= tree[tindex + 1];
+ k -= tree[tindex + 1];
+
+ e = (tree[tindex]);
+ if ((e & 16) != 0)
+ { // distance
+ get = e & 15;
+ dist = tree[tindex + 2];
+ mode = InflateCodeMode.DISTEXT;
+ break;
+ }
+ if ((e & 64) == 0)
+ { // next table
+ need = e;
+ tree_index = tindex / 3 + tree[tindex + 2];
+ break;
+ }
+ mode = InflateCodeMode.BADCODE; // invalid code
+ z.msg = "invalid distance code";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ case InflateCodeMode.DISTEXT: // i: getting distance extra
+ j = get;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--; b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ dist += (b & inflate_mask[j]);
+
+ b >>= j;
+ k -= j;
+
+ mode = InflateCodeMode.COPY;
+ goto case InflateCodeMode.COPY;
+ case InflateCodeMode.COPY: // o: copying bytes in window, waiting for space
+ f = q - dist;
+ while (f < 0)
+ { // modulo window size-"while" instead
+ f += s.end; // of "if" handles invalid distances
+ }
+ while (len != 0)
+ {
+
+ if (m == 0)
+ {
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+ if (m == 0)
+ {
+ s.write = q; r = s.inflate_flush(z, r);
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+
+ if (m == 0)
+ {
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ }
+ }
+
+ s.window[q++] = s.window[f++]; m--;
+
+ if (f == s.end)
+ f = 0;
+ len--;
+ }
+ mode = InflateCodeMode.START;
+ break;
+ case InflateCodeMode.LIT: // o: got literal, waiting for output space
+ if (m == 0)
+ {
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+ if (m == 0)
+ {
+ s.write = q; r = s.inflate_flush(z, r);
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+ if (m == 0)
+ {
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ }
+ }
+ r = ZLibStatus.Z_OK;
+
+ s.window[q++] = (byte)lit; m--;
+
+ mode = InflateCodeMode.START;
+ break;
+ case InflateCodeMode.WASH: // o: got eob, possibly more output
+ if (k > 7)
+ { // return unused byte, if any
+ k -= 8;
+ n++;
+ p--; // can always return one
+ }
+
+ s.write = q; r = s.inflate_flush(z, r);
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (s.read != s.write)
+ {
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ mode = InflateCodeMode.END;
+ goto case InflateCodeMode.END;
+ case InflateCodeMode.END:
+ r = ZLibStatus.Z_STREAM_END;
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ case InflateCodeMode.BADCODE: // x: got error
+
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ default:
+ r = ZLibStatus.Z_STREAM_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ }
+ }
+
+ internal void codesfree(ZStream z)
+ {
+ // ZFREE(z, c);
+ }
+
+ // Called with number of bytes left to write in window at least 258
+ // (the maximum string length) and number of input bytes available
+ // at least ten. The ten bytes are six bytes for the longest length/
+ // distance pair plus four bytes for overloading the bit buffer.
+
+ internal ZLibStatus inflate_fast(int bl, int bd,
+ int[] tl, int tl_index,
+ int[] td, int td_index,
+ InflateBlocks s, ZStream z)
+ {
+ int t; // temporary pointer
+ int[] tp; // temporary pointer
+ int tp_index; // temporary pointer
+ int e; // extra bits or operation
+ int b; // bit buffer
+ int k; // bits in bit buffer
+ int p; // input data pointer
+ int n; // bytes available there
+ int q; // output window write pointer
+ int m; // bytes to end of window or read pointer
+ int ml; // mask for literal/length tree
+ int md; // mask for distance tree
+ int c; // bytes to copy
+ int d; // distance back to copy from
+ int r; // copy source pointer
+
+ int tp_index_t_3; // (tp_index+t)*3
+
+ // load input, output, bit values
+ p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk;
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ // initialize masks
+ ml = inflate_mask[bl];
+ md = inflate_mask[bd];
+
+ // do until not enough input or output space for fast loop
+ do
+ { // assume called with m >= 258 && n >= 10
+ // get literal/length code
+ while (k < (20))
+ { // max bits for literal/length code
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k; k += 8;
+ }
+
+ t = b & ml;
+ tp = tl;
+ tp_index = tl_index;
+ tp_index_t_3 = (tp_index + t) * 3;
+ if ((e = tp[tp_index_t_3]) == 0)
+ {
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ s.window[q++] = (byte)tp[tp_index_t_3 + 2];
+ m--;
+ continue;
+ }
+ do
+ {
+
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ if ((e & 16) != 0)
+ {
+ e &= 15;
+ c = tp[tp_index_t_3 + 2] + ((int)b & inflate_mask[e]);
+
+ b >>= e; k -= e;
+
+ // decode distance base of block to copy
+ while (k < (15))
+ { // max bits for distance code
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k; k += 8;
+ }
+
+ t = b & md;
+ tp = td;
+ tp_index = td_index;
+ tp_index_t_3 = (tp_index + t) * 3;
+ e = tp[tp_index_t_3];
+
+ do
+ {
+
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ if ((e & 16) != 0)
+ {
+ // get extra bits to add to distance base
+ e &= 15;
+ while (k < (e))
+ { // get extra bits (up to 13)
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k; k += 8;
+ }
+
+ d = tp[tp_index_t_3 + 2] + (b & inflate_mask[e]);
+
+ b >>= (e); k -= (e);
+
+ // do the copy
+ m -= c;
+ if (q >= d)
+ { // offset before dest
+ // just copy
+ r = q - d;
+ if (q - r > 0 && 2 > (q - r))
+ {
+ s.window[q++] = s.window[r++]; // minimum count is three,
+ s.window[q++] = s.window[r++]; // so unroll loop a little
+ c -= 2;
+ }
+ else
+ {
+ System.Array.Copy(s.window, r, s.window, q, 2);
+ q += 2; r += 2; c -= 2;
+ }
+ }
+ else
+ { // else offset after destination
+ r = q - d;
+ do
+ {
+ r += s.end; // force pointer in window
+ } while (r < 0); // covers invalid distances
+ e = s.end - r;
+ if (c > e)
+ { // if source crosses,
+ c -= e; // wrapped copy
+ if (q - r > 0 && e > (q - r))
+ {
+ do { s.window[q++] = s.window[r++]; }
+ while (--e != 0);
+ }
+ else
+ {
+ System.Array.Copy(s.window, r, s.window, q, e);
+ q += e; r += e; e = 0;
+ }
+ r = 0; // copy rest from start of window
+ }
+
+ }
+
+ // copy all or what's left
+ if (q - r > 0 && c > (q - r))
+ {
+ do { s.window[q++] = s.window[r++]; }
+ while (--c != 0);
+ }
+ else
+ {
+ System.Array.Copy(s.window, r, s.window, q, c);
+ q += c; r += c; c = 0;
+ }
+ break;
+ }
+ else if ((e & 64) == 0)
+ {
+ t += tp[tp_index_t_3 + 2];
+ t += (b & inflate_mask[e]);
+ tp_index_t_3 = (tp_index + t) * 3;
+ e = tp[tp_index_t_3];
+ }
+ else
+ {
+ z.msg = "invalid distance code";
+
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ }
+ while (true);
+ break;
+ }
+
+ if ((e & 64) == 0)
+ {
+ t += tp[tp_index_t_3 + 2];
+ t += (b & inflate_mask[e]);
+ tp_index_t_3 = (tp_index + t) * 3;
+ if ((e = tp[tp_index_t_3]) == 0)
+ {
+
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ s.window[q++] = (byte)tp[tp_index_t_3 + 2];
+ m--;
+ break;
+ }
+ }
+ else if ((e & 32) != 0)
+ {
+
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_STREAM_END;
+ }
+ else
+ {
+ z.msg = "invalid literal/length code";
+
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ }
+ while (true);
+ }
+ while (m >= 258 && n >= 10);
+
+ // not enough input or output--restore pointers and return
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_OK;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Version.7/InflateTree.cs b/Renci.SshNet/Compression/Version.7/InflateTree.cs
new file mode 100644
index 0000000..f9da579
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.7/InflateTree.cs
@@ -0,0 +1,555 @@
+using System;
+/*
+ * $Id: InfTree.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ internal sealed class InflateTree
+ {
+ private const int MANY = 1440;
+
+ private const int fixed_bl = 9;
+ private const int fixed_bd = 5;
+
+ static readonly int[] fixed_tl = {
+ 96,7,256, 0,8,80, 0,8,16, 84,8,115,
+ 82,7,31, 0,8,112, 0,8,48, 0,9,192,
+ 80,7,10, 0,8,96, 0,8,32, 0,9,160,
+ 0,8,0, 0,8,128, 0,8,64, 0,9,224,
+ 80,7,6, 0,8,88, 0,8,24, 0,9,144,
+ 83,7,59, 0,8,120, 0,8,56, 0,9,208,
+ 81,7,17, 0,8,104, 0,8,40, 0,9,176,
+ 0,8,8, 0,8,136, 0,8,72, 0,9,240,
+ 80,7,4, 0,8,84, 0,8,20, 85,8,227,
+ 83,7,43, 0,8,116, 0,8,52, 0,9,200,
+ 81,7,13, 0,8,100, 0,8,36, 0,9,168,
+ 0,8,4, 0,8,132, 0,8,68, 0,9,232,
+ 80,7,8, 0,8,92, 0,8,28, 0,9,152,
+ 84,7,83, 0,8,124, 0,8,60, 0,9,216,
+ 82,7,23, 0,8,108, 0,8,44, 0,9,184,
+ 0,8,12, 0,8,140, 0,8,76, 0,9,248,
+ 80,7,3, 0,8,82, 0,8,18, 85,8,163,
+ 83,7,35, 0,8,114, 0,8,50, 0,9,196,
+ 81,7,11, 0,8,98, 0,8,34, 0,9,164,
+ 0,8,2, 0,8,130, 0,8,66, 0,9,228,
+ 80,7,7, 0,8,90, 0,8,26, 0,9,148,
+ 84,7,67, 0,8,122, 0,8,58, 0,9,212,
+ 82,7,19, 0,8,106, 0,8,42, 0,9,180,
+ 0,8,10, 0,8,138, 0,8,74, 0,9,244,
+ 80,7,5, 0,8,86, 0,8,22, 192,8,0,
+ 83,7,51, 0,8,118, 0,8,54, 0,9,204,
+ 81,7,15, 0,8,102, 0,8,38, 0,9,172,
+ 0,8,6, 0,8,134, 0,8,70, 0,9,236,
+ 80,7,9, 0,8,94, 0,8,30, 0,9,156,
+ 84,7,99, 0,8,126, 0,8,62, 0,9,220,
+ 82,7,27, 0,8,110, 0,8,46, 0,9,188,
+ 0,8,14, 0,8,142, 0,8,78, 0,9,252,
+ 96,7,256, 0,8,81, 0,8,17, 85,8,131,
+ 82,7,31, 0,8,113, 0,8,49, 0,9,194,
+ 80,7,10, 0,8,97, 0,8,33, 0,9,162,
+ 0,8,1, 0,8,129, 0,8,65, 0,9,226,
+ 80,7,6, 0,8,89, 0,8,25, 0,9,146,
+ 83,7,59, 0,8,121, 0,8,57, 0,9,210,
+ 81,7,17, 0,8,105, 0,8,41, 0,9,178,
+ 0,8,9, 0,8,137, 0,8,73, 0,9,242,
+ 80,7,4, 0,8,85, 0,8,21, 80,8,258,
+ 83,7,43, 0,8,117, 0,8,53, 0,9,202,
+ 81,7,13, 0,8,101, 0,8,37, 0,9,170,
+ 0,8,5, 0,8,133, 0,8,69, 0,9,234,
+ 80,7,8, 0,8,93, 0,8,29, 0,9,154,
+ 84,7,83, 0,8,125, 0,8,61, 0,9,218,
+ 82,7,23, 0,8,109, 0,8,45, 0,9,186,
+ 0,8,13, 0,8,141, 0,8,77, 0,9,250,
+ 80,7,3, 0,8,83, 0,8,19, 85,8,195,
+ 83,7,35, 0,8,115, 0,8,51, 0,9,198,
+ 81,7,11, 0,8,99, 0,8,35, 0,9,166,
+ 0,8,3, 0,8,131, 0,8,67, 0,9,230,
+ 80,7,7, 0,8,91, 0,8,27, 0,9,150,
+ 84,7,67, 0,8,123, 0,8,59, 0,9,214,
+ 82,7,19, 0,8,107, 0,8,43, 0,9,182,
+ 0,8,11, 0,8,139, 0,8,75, 0,9,246,
+ 80,7,5, 0,8,87, 0,8,23, 192,8,0,
+ 83,7,51, 0,8,119, 0,8,55, 0,9,206,
+ 81,7,15, 0,8,103, 0,8,39, 0,9,174,
+ 0,8,7, 0,8,135, 0,8,71, 0,9,238,
+ 80,7,9, 0,8,95, 0,8,31, 0,9,158,
+ 84,7,99, 0,8,127, 0,8,63, 0,9,222,
+ 82,7,27, 0,8,111, 0,8,47, 0,9,190,
+ 0,8,15, 0,8,143, 0,8,79, 0,9,254,
+ 96,7,256, 0,8,80, 0,8,16, 84,8,115,
+ 82,7,31, 0,8,112, 0,8,48, 0,9,193,
+
+ 80,7,10, 0,8,96, 0,8,32, 0,9,161,
+ 0,8,0, 0,8,128, 0,8,64, 0,9,225,
+ 80,7,6, 0,8,88, 0,8,24, 0,9,145,
+ 83,7,59, 0,8,120, 0,8,56, 0,9,209,
+ 81,7,17, 0,8,104, 0,8,40, 0,9,177,
+ 0,8,8, 0,8,136, 0,8,72, 0,9,241,
+ 80,7,4, 0,8,84, 0,8,20, 85,8,227,
+ 83,7,43, 0,8,116, 0,8,52, 0,9,201,
+ 81,7,13, 0,8,100, 0,8,36, 0,9,169,
+ 0,8,4, 0,8,132, 0,8,68, 0,9,233,
+ 80,7,8, 0,8,92, 0,8,28, 0,9,153,
+ 84,7,83, 0,8,124, 0,8,60, 0,9,217,
+ 82,7,23, 0,8,108, 0,8,44, 0,9,185,
+ 0,8,12, 0,8,140, 0,8,76, 0,9,249,
+ 80,7,3, 0,8,82, 0,8,18, 85,8,163,
+ 83,7,35, 0,8,114, 0,8,50, 0,9,197,
+ 81,7,11, 0,8,98, 0,8,34, 0,9,165,
+ 0,8,2, 0,8,130, 0,8,66, 0,9,229,
+ 80,7,7, 0,8,90, 0,8,26, 0,9,149,
+ 84,7,67, 0,8,122, 0,8,58, 0,9,213,
+ 82,7,19, 0,8,106, 0,8,42, 0,9,181,
+ 0,8,10, 0,8,138, 0,8,74, 0,9,245,
+ 80,7,5, 0,8,86, 0,8,22, 192,8,0,
+ 83,7,51, 0,8,118, 0,8,54, 0,9,205,
+ 81,7,15, 0,8,102, 0,8,38, 0,9,173,
+ 0,8,6, 0,8,134, 0,8,70, 0,9,237,
+ 80,7,9, 0,8,94, 0,8,30, 0,9,157,
+ 84,7,99, 0,8,126, 0,8,62, 0,9,221,
+ 82,7,27, 0,8,110, 0,8,46, 0,9,189,
+ 0,8,14, 0,8,142, 0,8,78, 0,9,253,
+ 96,7,256, 0,8,81, 0,8,17, 85,8,131,
+ 82,7,31, 0,8,113, 0,8,49, 0,9,195,
+ 80,7,10, 0,8,97, 0,8,33, 0,9,163,
+ 0,8,1, 0,8,129, 0,8,65, 0,9,227,
+ 80,7,6, 0,8,89, 0,8,25, 0,9,147,
+ 83,7,59, 0,8,121, 0,8,57, 0,9,211,
+ 81,7,17, 0,8,105, 0,8,41, 0,9,179,
+ 0,8,9, 0,8,137, 0,8,73, 0,9,243,
+ 80,7,4, 0,8,85, 0,8,21, 80,8,258,
+ 83,7,43, 0,8,117, 0,8,53, 0,9,203,
+ 81,7,13, 0,8,101, 0,8,37, 0,9,171,
+ 0,8,5, 0,8,133, 0,8,69, 0,9,235,
+ 80,7,8, 0,8,93, 0,8,29, 0,9,155,
+ 84,7,83, 0,8,125, 0,8,61, 0,9,219,
+ 82,7,23, 0,8,109, 0,8,45, 0,9,187,
+ 0,8,13, 0,8,141, 0,8,77, 0,9,251,
+ 80,7,3, 0,8,83, 0,8,19, 85,8,195,
+ 83,7,35, 0,8,115, 0,8,51, 0,9,199,
+ 81,7,11, 0,8,99, 0,8,35, 0,9,167,
+ 0,8,3, 0,8,131, 0,8,67, 0,9,231,
+ 80,7,7, 0,8,91, 0,8,27, 0,9,151,
+ 84,7,67, 0,8,123, 0,8,59, 0,9,215,
+ 82,7,19, 0,8,107, 0,8,43, 0,9,183,
+ 0,8,11, 0,8,139, 0,8,75, 0,9,247,
+ 80,7,5, 0,8,87, 0,8,23, 192,8,0,
+ 83,7,51, 0,8,119, 0,8,55, 0,9,207,
+ 81,7,15, 0,8,103, 0,8,39, 0,9,175,
+ 0,8,7, 0,8,135, 0,8,71, 0,9,239,
+ 80,7,9, 0,8,95, 0,8,31, 0,9,159,
+ 84,7,99, 0,8,127, 0,8,63, 0,9,223,
+ 82,7,27, 0,8,111, 0,8,47, 0,9,191,
+ 0,8,15, 0,8,143, 0,8,79, 0,9,255
+ };
+ static readonly int[] fixed_td = {
+ 80,5,1, 87,5,257, 83,5,17, 91,5,4097,
+ 81,5,5, 89,5,1025, 85,5,65, 93,5,16385,
+ 80,5,3, 88,5,513, 84,5,33, 92,5,8193,
+ 82,5,9, 90,5,2049, 86,5,129, 192,5,24577,
+ 80,5,2, 87,5,385, 83,5,25, 91,5,6145,
+ 81,5,7, 89,5,1537, 85,5,97, 93,5,24577,
+ 80,5,4, 88,5,769, 84,5,49, 92,5,12289,
+ 82,5,13, 90,5,3073, 86,5,193, 192,5,24577
+ };
+
+ // Tables for deflate from PKZIP's appnote.txt.
+ static readonly int[] cplens = { // Copy lengths for literal codes 257..285
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
+ };
+
+ // see note #13 above about 258
+ static readonly int[] cplext = { // Extra bits for literal codes 257..285
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+ 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112 // 112==invalid
+ };
+
+ static readonly int[] cpdist = { // Copy offsets for distance codes 0..29
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+ 8193, 12289, 16385, 24577
+ };
+
+ static readonly int[] cpdext = { // Extra bits for distance codes
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+ 12, 12, 13, 13};
+
+ // If BMAX needs to be larger than 16, then h and x[] should be uLong.
+ const int BMAX = 15; // maximum bit length of any code
+
+ int[] hn = null; // hufts used in space
+ int[] v = null; // work area for huft_build
+ int[] c = null; // bit length count table
+ int[] r = null; // table entry for structure assignment
+ int[] u = null; // table stack
+ int[] x = null; // bit offsets, then code stack
+
+ private ZLibStatus HuftBuild(int[] b, // code lengths in bits (all assumed <= BMAX)
+ int bindex,
+ int n, // number of codes (assumed <= 288)
+ int s, // number of simple-valued codes (0..s-1)
+ int[] d, // list of base values for non-simple codes
+ int[] e, // list of extra bits for non-simple codes
+ int[] t, // result: starting table
+ int[] m, // maximum lookup bits, returns actual
+ int[] hp,// space for trees
+ int[] hn,// hufts used in space
+ int[] v // working area: values in order of bit length
+ )
+ {
+ // Given a list of code lengths and a maximum table size, make a set of
+ // tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR
+ // if the given code set is incomplete (the tables are still built in this
+ // case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of
+ // lengths), or Z_MEM_ERROR if not enough memory.
+
+ int a; // counter for codes of length k
+ int f; // i repeats in table every f entries
+ int g; // maximum code length
+ int h; // table level
+ int i; // counter, current code
+ int j; // counter
+ int k; // number of bits in current code
+ int l; // bits per table (returned in m)
+ int mask; // (1 << w) - 1, to avoid cc -O bug on HP
+ int p; // pointer into c[], b[], or v[]
+ int q; // points to current table
+ int w; // bits before this table == (l * h)
+ int xp; // pointer into x
+ int y; // number of dummy codes added
+ int z; // number of entries in current table
+
+ // Generate counts for each bit length
+
+ p = 0; i = n;
+ do
+ {
+ c[b[bindex + p]]++; p++; i--; // assume all entries <= BMAX
+ } while (i != 0);
+
+ if (c[0] == n)
+ { // null input--all zero length codes
+ t[0] = -1;
+ m[0] = 0;
+ return ZLibStatus.Z_OK;
+ }
+
+ // Find minimum and maximum length, bound *m by those
+ l = m[0];
+ for (j = 1; j <= BMAX; j++)
+ if (c[j] != 0) break;
+ k = j; // minimum code length
+ if (l < j)
+ {
+ l = j;
+ }
+ for (i = BMAX; i != 0; i--)
+ {
+ if (c[i] != 0) break;
+ }
+ g = i; // maximum code length
+ if (l > i)
+ {
+ l = i;
+ }
+ m[0] = l;
+
+ // Adjust last length count to fill out codes, if needed
+ for (y = 1 << j; j < i; j++, y <<= 1)
+ {
+ if ((y -= c[j]) < 0)
+ {
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ }
+ if ((y -= c[i]) < 0)
+ {
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ c[i] += y;
+
+ // Generate starting offsets into the value table for each length
+ x[1] = j = 0;
+ p = 1; xp = 2;
+ while (--i != 0)
+ { // note that i == g from above
+ x[xp] = (j += c[p]);
+ xp++;
+ p++;
+ }
+
+ // Make a table of values in order of bit lengths
+ i = 0; p = 0;
+ do
+ {
+ if ((j = b[bindex + p]) != 0)
+ {
+ v[x[j]++] = i;
+ }
+ p++;
+ }
+ while (++i < n);
+ n = x[g]; // set n to length of v
+
+ // Generate the Huffman codes and for each, make the table entries
+ x[0] = i = 0; // first Huffman code is zero
+ p = 0; // grab values in bit order
+ h = -1; // no tables yet--level -1
+ w = -l; // bits decoded == (l * h)
+ u[0] = 0; // just to keep compilers happy
+ q = 0; // ditto
+ z = 0; // ditto
+
+ // go through the bit lengths (k already is bits in shortest code)
+ for (; k <= g; k++)
+ {
+ a = c[k];
+ while (a-- != 0)
+ {
+ // here i is the Huffman code of length k bits for value *p
+ // make tables up to required level
+ while (k > w + l)
+ {
+ h++;
+ w += l; // previous table always l bits
+ // compute minimum size table less than or equal to l bits
+ z = g - w;
+ z = (z > l) ? l : z; // table size upper limit
+ if ((f = 1 << (j = k - w)) > a + 1)
+ { // try a k-w bit table
+ // too few codes for k-w bit table
+ f -= a + 1; // deduct codes from patterns left
+ xp = k;
+ if (j < z)
+ {
+ while (++j < z)
+ { // try smaller tables up to z bits
+ if ((f <<= 1) <= c[++xp])
+ break; // enough codes to use up j bits
+ f -= c[xp]; // else deduct codes from patterns
+ }
+ }
+ }
+ z = 1 << j; // table entries for j-bit table
+
+ // allocate new table
+ if (hn[0] + z > MANY)
+ { // (note: doesn't matter for fixed)
+ return ZLibStatus.Z_DATA_ERROR; // overflow of MANY
+ }
+ u[h] = q = /*hp+*/ hn[0]; // DEBUG
+ hn[0] += z;
+
+ // connect to last table, if there is one
+ if (h != 0)
+ {
+ x[h] = i; // save pattern for backing up
+ r[0] = (byte)j; // bits in this table
+ r[1] = (byte)l; // bits to dump before this table
+ j = i >> (w - l);
+ r[2] = (int)(q - u[h - 1] - j); // offset to this table
+ System.Array.Copy(r, 0, hp, (u[h - 1] + j) * 3, 3); // connect to last table
+ }
+ else
+ {
+ t[0] = q; // first table is returned result
+ }
+ }
+
+ // set up table entry in r
+ r[1] = (byte)(k - w);
+ if (p >= n)
+ {
+ r[0] = 128 + 64; // out of values--invalid code
+ }
+ else if (v[p] < s)
+ {
+ r[0] = (byte)(v[p] < 256 ? 0 : 32 + 64); // 256 is end-of-block
+ r[2] = v[p++]; // simple code is just the value
+ }
+ else
+ {
+ r[0] = (byte)(e[v[p] - s] + 16 + 64); // non-simple--look up in lists
+ r[2] = d[v[p++] - s];
+ }
+
+ // fill code-like entries with r
+ f = 1 << (k - w);
+ for (j = i >> w; j < z; j += f)
+ {
+ System.Array.Copy(r, 0, hp, (q + j) * 3, 3);
+ }
+
+ // backwards increment the k-bit code i
+ for (j = 1 << (k - 1); (i & j) != 0; j >>= 1)
+ {
+ i ^= j;
+ }
+ i ^= j;
+
+ // backup over finished tables
+ mask = (1 << w) - 1; // needed on HP, cc -O bug
+ while ((i & mask) != x[h])
+ {
+ h--; // don't need to update q
+ w -= l;
+ mask = (1 << w) - 1;
+ }
+ }
+ }
+ // Return Z_BUF_ERROR if we were given an incomplete table
+ return y != 0 && g != 1 ? ZLibStatus.Z_BUF_ERROR : ZLibStatus.Z_OK;
+ }
+
+ internal ZLibStatus InflateTreesBits(int[] c, // 19 code lengths
+ int[] bb, // bits tree desired/actual depth
+ int[] tb, // bits tree result
+ int[] hp, // space for trees
+ ZStream z // for messages
+ )
+ {
+ ZLibStatus result;
+ InitWorkArea(19);
+ hn[0] = 0;
+ result = HuftBuild(c, 0, 19, 19, null, null, tb, bb, hp, hn, v);
+
+ if (result == ZLibStatus.Z_DATA_ERROR)
+ {
+ z.msg = "oversubscribed dynamic bit lengths tree";
+ }
+ else if (result == ZLibStatus.Z_BUF_ERROR || bb[0] == 0)
+ {
+ z.msg = "incomplete dynamic bit lengths tree";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ return result;
+ }
+
+ internal ZLibStatus InflateTreesDynamic(int nl, // number of literal/length codes
+ int nd, // number of distance codes
+ int[] c, // that many (total) code lengths
+ int[] bl, // literal desired/actual bit depth
+ int[] bd, // distance desired/actual bit depth
+ int[] tl, // literal/length tree result
+ int[] td, // distance tree result
+ int[] hp, // space for trees
+ ZStream z // for messages
+ )
+ {
+ ZLibStatus result;
+
+ // build literal/length tree
+ InitWorkArea(288);
+ hn[0] = 0;
+ result = HuftBuild(c, 0, nl, 257, cplens, cplext, tl, bl, hp, hn, v);
+ if (result != ZLibStatus.Z_OK || bl[0] == 0)
+ {
+ if (result == ZLibStatus.Z_DATA_ERROR)
+ {
+ z.msg = "oversubscribed literal/length tree";
+ }
+ else if (result != ZLibStatus.Z_MEM_ERROR)
+ {
+ z.msg = "incomplete literal/length tree";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ return result;
+ }
+
+ // build distance tree
+ InitWorkArea(288);
+ result = HuftBuild(c, nl, nd, 0, cpdist, cpdext, td, bd, hp, hn, v);
+
+ if (result != ZLibStatus.Z_OK || (bd[0] == 0 && nl > 257))
+ {
+ if (result == ZLibStatus.Z_DATA_ERROR)
+ {
+ z.msg = "oversubscribed distance tree";
+ }
+ else if (result == ZLibStatus.Z_BUF_ERROR)
+ {
+ z.msg = "incomplete distance tree";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ else if (result != ZLibStatus.Z_MEM_ERROR)
+ {
+ z.msg = "empty distance tree with lengths";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ return result;
+ }
+
+ return ZLibStatus.Z_OK;
+ }
+
+ internal static ZLibStatus InflateTreesFixed(int[] bl, //literal desired/actual bit depth
+ int[] bd, //distance desired/actual bit depth
+ int[][] tl,//literal/length tree result
+ int[][] td,//distance tree result
+ ZStream z //for memory allocation
+ )
+ {
+ bl[0] = fixed_bl;
+ bd[0] = fixed_bd;
+ tl[0] = fixed_tl;
+ td[0] = fixed_td;
+ return ZLibStatus.Z_OK;
+ }
+
+ private void InitWorkArea(int vsize)
+ {
+ if (hn == null)
+ {
+ hn = new int[1];
+ v = new int[vsize];
+ c = new int[BMAX + 1];
+ r = new int[3];
+ u = new int[BMAX];
+ x = new int[BMAX + 1];
+ }
+ if (v.Length < vsize) { v = new int[vsize]; }
+ for (int i = 0; i < vsize; i++) { v[i] = 0; }
+ for (int i = 0; i < BMAX + 1; i++) { c[i] = 0; }
+ for (int i = 0; i < 3; i++) { r[i] = 0; }
+ // for(int i=0; i
+ /// Gets the static tree or null
+ ///
+ ///
+ /// The static_tree.
+ ///
+ public short[] TreeData { get; private set; }
+
+ ///
+ /// Gets the extra bits for each code or null.
+ ///
+ ///
+ /// The extra bits.
+ ///
+ public int[] ExtraBits { get; private set; }
+
+ ///
+ /// Gets the base index for extra_bits.
+ ///
+ ///
+ /// The extra base.
+ ///
+ public int ExtraBase { get; private set; }
+
+ ///
+ /// Gets the max number of elements in the tree.
+ ///
+ ///
+ /// The elements.
+ ///
+ public int Elements { get; private set; }
+
+ ///
+ /// Gets the max bit length for the codes.
+ ///
+ ///
+ /// The length of the max.
+ ///
+ public int MaxLength { get; private set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The tree data.
+ /// The extra bits.
+ /// The extra base.
+ /// The elements.
+ /// Length of the max.
+ public StaticTree(short[] treeData, int[] extraBits, int extraBase, int elements, int maxLength)
+ {
+ this.TreeData = treeData;
+ this.ExtraBits = extraBits;
+ this.ExtraBase = extraBase;
+ this.Elements = elements;
+ this.MaxLength = maxLength;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Version.7/Tree.cs b/Renci.SshNet/Compression/Version.7/Tree.cs
new file mode 100644
index 0000000..d2142c9
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.7/Tree.cs
@@ -0,0 +1,334 @@
+using System;
+/*
+ * $Id: Tree.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+ internal sealed class Tree
+ {
+ private const int MAX_BITS = 15;
+
+ private const int LITERALS = 256;
+
+ private const int LENGTH_CODES = 29;
+
+ private const int L_CODES = (LITERALS + 1 + LENGTH_CODES);
+
+ private const int HEAP_SIZE = (2 * L_CODES + 1);
+
+ private static byte[] _dist_code = {
+ 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8,
+ 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17,
+ 18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
+ 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
+ };
+
+
+ ///
+ /// The corresponding static tree
+ ///
+ private StaticTree _staticTree;
+
+ ///
+ /// The dynamic tree
+ ///
+ private short[] _dynamicTree;
+
+ ///
+ /// Gets the largest code with non zero frequency.
+ ///
+ ///
+ /// The max_code.
+ ///
+ public int LargestCode { get; private set; }
+
+ public void Init(short[] dynamicTree, StaticTree staticTree)
+ {
+ this._staticTree = staticTree;
+ this._dynamicTree = dynamicTree;
+ }
+
+ ///
+ /// Mapping from a distance to a distance code. dist is the distance - 1 and must not have side effects. _dist_code[256] and _dist_code[257] are never used.
+ ///
+ /// The dist.
+ ///
+ public static int DistanceCode(int dist)
+ {
+ // TODO: Under multiple port forward after more then 50K requests gets index out of range
+ return ((dist) < 256 ? _dist_code[dist] : _dist_code[256 + ((dist) >> 7)]);
+ }
+
+ ///
+ /// Construct one Huffman tree and assigns the code bit strings and lengths. Update the total bit length for the current block.
+ ///
+ /// The s.
+ public void BuildTree(Deflate s)
+ {
+ short[] tree = _dynamicTree;
+ short[] stree = _staticTree.TreeData;
+ int elems = _staticTree.Elements;
+ int n, m; // iterate over heap elements
+ int max_code = -1; // largest code with non zero frequency
+ int node; // new node being created
+
+ // Construct the initial heap, with least frequent element in
+ // heap[1]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
+ // heap[0] is not used.
+ s.heap_len = 0;
+ s.heap_max = HEAP_SIZE;
+
+ for (n = 0; n < elems; n++)
+ {
+ if (tree[n * 2] != 0)
+ {
+ s.heap[++s.heap_len] = max_code = n;
+ s.depth[n] = 0;
+ }
+ else
+ {
+ tree[n * 2 + 1] = 0;
+ }
+ }
+
+ // The pkzip format requires that at least one distance code exists,
+ // and that at least one bit should be sent even if there is only one
+ // possible code. So to avoid special checks later on we force at least
+ // two codes of non zero frequency.
+ while (s.heap_len < 2)
+ {
+ node = s.heap[++s.heap_len] = (max_code < 2 ? ++max_code : 0);
+ tree[node * 2] = 1;
+ s.depth[node] = 0;
+ s.opt_len--; if (stree != null) s.static_len -= stree[node * 2 + 1];
+ // node is 0 or 1 so it does not have extra bits
+ }
+ this.LargestCode = max_code;
+
+ // The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
+ // establish sub-heaps of increasing lengths:
+
+ for (n = s.heap_len / 2; n >= 1; n--)
+ s.pqdownheap(tree, n);
+
+ // Construct the Huffman tree by repeatedly combining the least two
+ // frequent nodes.
+
+ node = elems; // next internal node of the tree
+ do
+ {
+ // n = node of least frequency
+ n = s.heap[1];
+ s.heap[1] = s.heap[s.heap_len--];
+ s.pqdownheap(tree, 1);
+ m = s.heap[1]; // m = node of next least frequency
+
+ s.heap[--s.heap_max] = n; // keep the nodes sorted by frequency
+ s.heap[--s.heap_max] = m;
+
+ // Create a new node father of n and m
+ tree[node * 2] = (short)(tree[n * 2] + tree[m * 2]);
+ s.depth[node] = (byte)(System.Math.Max(s.depth[n], s.depth[m]) + 1);
+ tree[n * 2 + 1] = tree[m * 2 + 1] = (short)node;
+
+ // and insert the new node in the heap
+ s.heap[1] = node++;
+ s.pqdownheap(tree, 1);
+ }
+ while (s.heap_len >= 2);
+
+ s.heap[--s.heap_max] = s.heap[1];
+
+ // At this point, the fields freq and dad are set. We can now
+ // generate the bit lengths.
+
+ ComputeBitLength(s);
+
+ // The field len is now set, we can generate the bit codes
+ GenerateCodes(tree, max_code, s.bl_count);
+ }
+
+ ///
+ /// Compute the optimal bit lengths for a tree and update the total bit length for the current block.
+ ///
+ /// The s.
+ private void ComputeBitLength(Deflate s)
+ {
+ short[] tree = _dynamicTree;
+ short[] stree = _staticTree.TreeData;
+ int[] extra = _staticTree.ExtraBits;
+ int based = _staticTree.ExtraBase;
+ int max_length = _staticTree.MaxLength;
+ int h; // heap index
+ int n, m; // iterate over the tree elements
+ int bits; // bit length
+ int xbits; // extra bits
+ short f; // frequency
+ int overflow = 0; // number of elements with bit length too large
+
+ for (bits = 0; bits <= MAX_BITS; bits++) s.bl_count[bits] = 0;
+
+ // In a first pass, compute the optimal bit lengths (which may
+ // overflow in the case of the bit length tree).
+ tree[s.heap[s.heap_max] * 2 + 1] = 0; // root of the heap
+
+ for (h = s.heap_max + 1; h < HEAP_SIZE; h++)
+ {
+ n = s.heap[h];
+ bits = tree[tree[n * 2 + 1] * 2 + 1] + 1;
+ if (bits > max_length) { bits = max_length; overflow++; }
+ tree[n * 2 + 1] = (short)bits;
+ // We overwrite tree[n*2+1] which is no longer needed
+
+ if (n > LargestCode) continue; // not a leaf node
+
+ s.bl_count[bits]++;
+ xbits = 0;
+ if (n >= based) xbits = extra[n - based];
+ f = tree[n * 2];
+ s.opt_len += f * (bits + xbits);
+ if (stree != null) s.static_len += f * (stree[n * 2 + 1] + xbits);
+ }
+ if (overflow == 0) return;
+
+ // This happens for example on obj2 and pic of the Calgary corpus
+ // Find the first bit length which could increase:
+ do
+ {
+ bits = max_length - 1;
+ while (s.bl_count[bits] == 0) bits--;
+ s.bl_count[bits]--; // move one leaf down the tree
+ s.bl_count[bits + 1] += 2; // move one overflow item as its brother
+ s.bl_count[max_length]--;
+ // The brother of the overflow item also moves one step up,
+ // but this does not affect bl_count[max_length]
+ overflow -= 2;
+ }
+ while (overflow > 0);
+
+ for (bits = max_length; bits != 0; bits--)
+ {
+ n = s.bl_count[bits];
+ while (n != 0)
+ {
+ m = s.heap[--h];
+ if (m > LargestCode) continue;
+ if (tree[m * 2 + 1] != bits)
+ {
+ s.opt_len += (int)(((long)bits - (long)tree[m * 2 + 1]) * (long)tree[m * 2]);
+ tree[m * 2 + 1] = (short)bits;
+ }
+ n--;
+ }
+ }
+ }
+
+ ///
+ /// Generate the codes for a given tree and bit counts (which need not be optimal).
+ ///
+ /// The tree to decorate.
+ /// The largest code with non zero frequency.
+ /// The number of codes at each bit length.
+ private static void GenerateCodes(short[] tree, int max_code, short[] bl_count)
+ {
+ short[] next_code = new short[MAX_BITS + 1]; // next code value for each bit length
+ short code = 0; // running code value
+ int bits; // bit index
+ int n; // code index
+
+ // The distribution counts are first used to generate the code values
+ // without bit reversal.
+ for (bits = 1; bits <= MAX_BITS; bits++)
+ {
+ next_code[bits] = code = (short)((code + bl_count[bits - 1]) << 1);
+ }
+
+ // Check that the bit counts in bl_count are consistent. The last code
+ // must be all ones.
+ //Assert (code + bl_count[MAX_BITS]-1 == (1<
+ /// Reverse the first len bits of a code, using straightforward code (a faster method would use a table)
+ ///
+ /// The value to invert.
+ /// The bit length.
+ ///
+ private static int BiReverse(int code, int len)
+ {
+ int res = 0;
+ do
+ {
+ res |= code & 1;
+ code >>= 1;
+ res <<= 1;
+ }
+ while (--len > 0);
+ return res >> 1;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Version.7/ZInputStream.cs b/Renci.SshNet/Compression/Version.7/ZInputStream.cs
new file mode 100644
index 0000000..2e5aaa6
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.7/ZInputStream.cs
@@ -0,0 +1,205 @@
+/*
+Copyright (c) 2001 Lapo Luchini.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS
+OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+/* This file is a port of jzlib v1.0.7, com.jcraft.jzlib.ZInputStream.java
+ */
+
+using Renci.SshNet.Compression;
+using System;
+using System.Diagnostics;
+using System.IO;
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+ public class ZInputStream : Stream
+ {
+ private const int BufferSize = 512;
+ //private ZStream z = new ZStream();
+ private ICompressor _compressor;
+
+ // TODO Allow custom buf
+ private byte[] _buffer = new byte[BufferSize];
+ private CompressionMode _compressionMode;
+ private Stream _input;
+ private bool _isClosed;
+ private bool _noMoreInput = false;
+
+ public FlushType FlushMode { get; private set; }
+
+ public ZInputStream()
+ {
+ this.FlushMode = FlushType.Z_PARTIAL_FLUSH;
+ }
+
+ public ZInputStream(Stream input)
+ : this(input, false)
+ {
+ }
+
+ public ZInputStream(Stream input, bool nowrap)
+ : this()
+ {
+ Debug.Assert(input.CanRead);
+
+ this._input = input;
+ this._compressor = new Inflate(nowrap);
+ //this._compressor.inflateInit(nowrap);
+ this._compressionMode = CompressionMode.Decompress;
+ this._compressor.next_in = _buffer;
+ this._compressor.next_in_index = 0;
+ this._compressor.avail_in = 0;
+ }
+
+ public ZInputStream(Stream input, CompressionLevel level)
+ : this()
+ {
+ Debug.Assert(input.CanRead);
+
+ this._input = input;
+ this._compressor = new Deflate(level);
+ //this._compressor.deflateInit(level);
+ this._compressionMode = CompressionMode.Compress;
+ this._compressor.next_in = _buffer;
+ this._compressor.next_in_index = 0;
+ this._compressor.avail_in = 0;
+ }
+
+ #region Stream implementation
+
+ public sealed override bool CanRead
+ {
+ get { return !_isClosed; }
+ }
+
+ public sealed override bool CanSeek
+ {
+ get { return false; }
+ }
+
+ public sealed override bool CanWrite
+ {
+ get { return false; }
+ }
+
+ public override void Flush()
+ {
+ }
+
+ public override long Length
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ public override long Position
+ {
+ get { throw new NotSupportedException(); }
+ set { throw new NotSupportedException(); }
+ }
+
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ if (count == 0)
+ return 0;
+
+ this._compressor.next_out = buffer;
+ this._compressor.next_out_index = offset;
+ this._compressor.avail_out = count;
+
+ ZLibStatus err = ZLibStatus.Z_OK;
+ do
+ {
+ if (this._compressor.avail_in == 0 && !_noMoreInput)
+ {
+ // if buffer is empty and more input is available, refill it
+ this._compressor.next_in_index = 0;
+ this._compressor.avail_in = _input.Read(_buffer, 0, _buffer.Length); //(bufsize 0 || this._compressor.avail_out == 0);
+ }
+
+ #endregion
+
+ public override void Close()
+ {
+ if (this._isClosed)
+ return;
+
+ try
+ {
+ try
+ {
+ Finish();
+ }
+ catch (IOException)
+ {
+ // Ignore
+ }
+ }
+ finally
+ {
+ this._isClosed = true;
+ End();
+ _output.Close();
+ _output = null;
+ }
+ }
+
+ private void End()
+ {
+ if (this._compressor == null)
+ return;
+ switch (this._compressionMode)
+ {
+ case CompressionMode.Compress:
+ this._compressor.deflateEnd();
+ break;
+ case CompressionMode.Decompress:
+ this._compressor.inflateEnd();
+ break;
+ default:
+ break;
+ }
+
+ this._compressor.free();
+ this._compressor = null;
+ }
+
+ private void Finish()
+ {
+ do
+ {
+ this._compressor.next_out = _buffer;
+ this._compressor.next_out_index = 0;
+ this._compressor.avail_out = _buffer.Length;
+
+ var err = ZLibStatus.Z_OK;
+ switch (this._compressionMode)
+ {
+ case CompressionMode.Compress:
+ err = this._compressor.deflate(FlushType.Z_FINISH);
+ break;
+ case CompressionMode.Decompress:
+ err = this._compressor.inflate(FlushType.Z_FINISH);
+ break;
+ default:
+ break;
+ }
+
+ if (err != ZLibStatus.Z_STREAM_END && err != ZLibStatus.Z_OK)
+ // TODO
+ // throw new ZStreamException((compress?"de":"in")+"flating: "+z.msg);
+ //throw new IOException((_compressionMode ? "de" : "in") + "flating: " + z.msg);
+ throw new IOException(string.Format("{0}ion error: {1}", _compressionMode, this._compressor.msg));
+
+ int count = _buffer.Length - this._compressor.avail_out;
+ if (count > 0)
+ {
+ _output.Write(_buffer, 0, count);
+ }
+ }
+ while (this._compressor.avail_in > 0 || this._compressor.avail_out == 0);
+
+ Flush();
+ }
+ }
+}
diff --git a/Renci.SshNet/Compression/Version.7/ZStream.cs b/Renci.SshNet/Compression/Version.7/ZStream.cs
new file mode 100644
index 0000000..6269735
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.7/ZStream.cs
@@ -0,0 +1,73 @@
+using System;
+using System.IO;
+/*
+ * $Id: ZStream.cs,v 1.1 2006-07-31 13:59:26 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public abstract class ZStream
+ {
+
+ protected const int MAX_WBITS = 15; // 32K LZ77 window
+ protected const int DEF_WBITS = MAX_WBITS;
+
+ private const int MAX_MEM_LEVEL = 9;
+
+ public byte[] next_in { get; set; } // next input byte
+ public int next_in_index { get; set; }
+ public int avail_in { get; set; } // number of bytes available at next_in
+ public long total_in { get; set; } // total nb of input bytes read so far
+
+ public byte[] next_out { get; set; } // next output byte should be put there
+ public int next_out_index { get; set; }
+ public int avail_out { get; set; } // remaining free space at next_out
+ public long total_out { get; set; } // total nb of bytes output so far
+
+ public String msg { get; set; }
+
+ internal BlockType data_type; // best guess about the data type: ascii or binary
+
+ public long adler;
+
+ public void free()
+ {
+ next_in = null;
+ next_out = null;
+ msg = null;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Version.7/Zlib.cs b/Renci.SshNet/Compression/Version.7/Zlib.cs
new file mode 100644
index 0000000..5890675
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.7/Zlib.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Represents "zlib" compression implementation
+ ///
+ internal class Zlib : Compressor
+ {
+ ///
+ /// Gets algorithm name.
+ ///
+ public override string Name
+ {
+ get { return "zlib"; }
+ }
+
+ ///
+ /// Initializes the algorithm
+ ///
+ /// The session.
+ public override void Init(Session session)
+ {
+ base.Init(session);
+ this.IsActive = true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Version.7/ZlibOpenSsh.cs b/Renci.SshNet/Compression/Version.7/ZlibOpenSsh.cs
new file mode 100644
index 0000000..f82a4c0
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.7/ZlibOpenSsh.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Represents "zlib@openssh.org" compression implementation
+ ///
+ public class ZlibOpenSsh : Compressor
+ {
+ ///
+ /// Gets algorithm name.
+ ///
+ public override string Name
+ {
+ get { return "zlib@openssh.org"; }
+ }
+
+ ///
+ /// Initializes the algorithm
+ ///
+ /// The session.
+ public override void Init(Session session)
+ {
+ base.Init(session);
+
+ session.UserAuthenticationSuccessReceived += Session_UserAuthenticationSuccessReceived;
+ }
+
+ private void Session_UserAuthenticationSuccessReceived(object sender, MessageEventArgs e)
+ {
+ this.IsActive = true;
+ this.Session.UserAuthenticationSuccessReceived -= Session_UserAuthenticationSuccessReceived;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Version.7/ZlibStream.cs b/Renci.SshNet/Compression/Version.7/ZlibStream.cs
new file mode 100644
index 0000000..fb5f9d2
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.7/ZlibStream.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.IO;
+using Org.BouncyCastle.Utilities.Zlib;
+
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Implements Zlib compression algorithm.
+ ///
+ public class ZlibStream
+ {
+ private readonly Stream _baseStream;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The stream.
+ /// The mode.
+ public ZlibStream(Stream stream, CompressionMode mode)
+ {
+ switch (mode)
+ {
+ case CompressionMode.Compress:
+ //this._baseStream = new ZOutputStream(stream, CompressionLevel.Z_DEFAULT_COMPRESSION);
+ this._baseStream = new ZOutputStream(stream, CompressionLevel.Z_DEFAULT_COMPRESSION);
+ break;
+ case CompressionMode.Decompress:
+ this._baseStream = new ZOutputStream(stream);
+ break;
+ default:
+ break;
+ }
+
+ //this._baseStream.FlushMode = Ionic.Zlib.FlushType.Partial;
+ }
+
+ ///
+ /// Writes the specified buffer.
+ ///
+ /// The buffer.
+ /// The offset.
+ /// The count.
+ public void Write(byte[] buffer, int offset, int count)
+ {
+ this._baseStream.Write(buffer, offset, count);
+ }
+ }
+}
diff --git a/Renci.SshNet/Compression/Version.8/Adler32.cs b/Renci.SshNet/Compression/Version.8/Adler32.cs
new file mode 100644
index 0000000..c132fa9
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.8/Adler32.cs
@@ -0,0 +1,95 @@
+using System;
+/*
+ * $Id: Adler32.cs,v 1.1 2006-07-31 13:59:25 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ internal static class Adler32
+ {
+
+ // largest prime smaller than 65536
+ private const int BASE = 65521;
+ // NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
+ private const int NMAX = 5552;
+
+ internal static long adler32(long adler, byte[] buf, int index, int len)
+ {
+ if (buf == null) { return 1L; }
+
+ long s1 = adler & 0xffff;
+ long s2 = (adler >> 16) & 0xffff;
+ int k;
+
+ while (len > 0)
+ {
+ k = len < NMAX ? len : NMAX;
+ len -= k;
+ while (k >= 16)
+ {
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ k -= 16;
+ }
+ if (k != 0)
+ {
+ do
+ {
+ s1 += buf[index++] & 0xff; s2 += s1;
+ }
+ while (--k != 0);
+ }
+ s1 %= BASE;
+ s2 %= BASE;
+ }
+ return (s2 << 16) | s1;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Version.8/CompressionMode.cs b/Renci.SshNet/Compression/Version.8/CompressionMode.cs
new file mode 100644
index 0000000..1577e0b
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.8/CompressionMode.cs
@@ -0,0 +1,18 @@
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Specifies compression modes
+ ///
+ public enum CompressionMode
+ {
+ ///
+ /// Specifies that content should be compressed.
+ ///
+ Compress = 0,
+
+ ///
+ /// Specifies that content should be decompressed.
+ ///
+ Decompress = 1,
+ }
+}
diff --git a/Renci.SshNet/Compression/Version.8/Compressor.cs b/Renci.SshNet/Compression/Version.8/Compressor.cs
new file mode 100644
index 0000000..1479bb6
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.8/Compressor.cs
@@ -0,0 +1,151 @@
+using System.Collections.Generic;
+using Renci.SshNet.Security;
+using System.IO;
+using System;
+
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Represents base class for compression algorithm implementation
+ ///
+ public abstract class Compressor : Algorithm, IDisposable
+ {
+ private readonly ZlibStream _compressor;
+ private readonly ZlibStream _decompressor;
+
+ private MemoryStream _compressorStream;
+ private MemoryStream _decompressorStream;
+
+ ///
+ /// Gets or sets a value indicating whether compression is active.
+ ///
+ ///
+ /// true if compression is active; otherwise, false.
+ ///
+ protected bool IsActive { get; set; }
+
+ ///
+ /// Gets the session.
+ ///
+ protected Session Session { get; private set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ 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);
+ }
+
+ ///
+ /// Initializes the algorithm
+ ///
+ /// The session.
+ public virtual void Init(Session session)
+ {
+ this.Session = session;
+ }
+
+ ///
+ /// Compresses the specified data.
+ ///
+ /// Data to compress.
+ /// Compressed 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();
+ }
+
+ ///
+ /// Decompresses the specified data.
+ ///
+ /// Compressed data.
+ /// Decompressed 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;
+
+ ///
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged ResourceMessages.
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Releases unmanaged and - optionally - managed resources
+ ///
+ /// true to release both managed and unmanaged resources; false to release only unmanaged ResourceMessages.
+ 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;
+ }
+ }
+
+ ///
+ /// Releases unmanaged resources and performs other cleanup operations before the
+ /// is reclaimed by garbage collection.
+ ///
+ ~Compressor()
+ {
+ // Do not re-create Dispose clean-up code here.
+ // Calling Dispose(false) is optimal in terms of
+ // readability and maintainability.
+ Dispose(false);
+ }
+
+ #endregion
+ }
+}
diff --git a/Renci.SshNet/Compression/Version.8/Deflate.cs b/Renci.SshNet/Compression/Version.8/Deflate.cs
new file mode 100644
index 0000000..14e76a2
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.8/Deflate.cs
@@ -0,0 +1,2217 @@
+using System;
+using System.Collections.Generic;
+/*
+ * $Id: Deflate.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public enum BlockType : byte
+ {
+ Z_BINARY = 0,
+ Z_ASCII = 1,
+ Z_UNKNOWN = 2
+ }
+
+ public enum DefalteFlavor : int
+ {
+ STORED = 0,
+ FAST = 1,
+ SLOW = 2
+ }
+
+ public sealed class Deflate : ZStream, ICompressor
+ {
+ private const int MAX_MEM_LEVEL = 9;
+
+ private const int Z_DEFAULT_COMPRESSION = -1;
+
+ private const int MAX_WBITS = 15; // 32K LZ77 window
+
+ private const int DEF_MEM_LEVEL = 8;
+
+ ///
+ /// The Bit length codes must not exceed MAX_BL_BITS bits
+ ///
+ private const int MAX_BL_BITS = 7;
+
+ // block not completed, need more input or more output
+ private const int NeedMore = 0;
+
+ // block flush performed
+ private const int BlockDone = 1;
+
+ // finish started, need only more output at next deflate
+ private const int FinishStarted = 2;
+
+ // finish done, accept no more input or output
+ private const int FinishDone = 3;
+
+ // preset dictionary flag in zlib header
+ private const int PRESET_DICT = 0x20;
+
+ private const int Z_VERSION_ERROR = -6;
+
+ private const int INIT_STATE = 42;
+ private const int BUSY_STATE = 113;
+ private const int FINISH_STATE = 666;
+
+ // The deflate compression method
+ private const int Z_DEFLATED = 8;
+
+ private const int STORED_BLOCK = 0;
+ private const int STATIC_TREES = 1;
+ private const int DYN_TREES = 2;
+
+ private const int Buf_size = 8 * 2;
+
+ // repeat previous bit length 3-6 times (2 bits of repeat count)
+ private const int REP_3_6 = 16;
+
+ // repeat a zero length 3-10 times (3 bits of repeat count)
+ private const int REPZ_3_10 = 17;
+
+ // repeat a zero length 11-138 times (7 bits of repeat count)
+ private const int REPZ_11_138 = 18;
+
+ private const int MIN_MATCH = 3;
+ private const int MAX_MATCH = 258;
+ private const int MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1);
+
+ private const int MAX_BITS = 15;
+ private const int D_CODES = 30;
+ private const int BL_CODES = 19;
+ private const int LENGTH_CODES = 29;
+ private const int LITERALS = 256;
+ private const int L_CODES = (LITERALS + 1 + LENGTH_CODES);
+ private const int HEAP_SIZE = (2 * L_CODES + 1);
+
+ private const int END_BLOCK = 256;
+
+ private static readonly IDictionary config_table = new Dictionary() {
+ {(CompressionLevel)0, new Config(0, 0, 0, 0, DefalteFlavor.STORED)},
+ {(CompressionLevel)1, new Config(4, 4, 8, 4, DefalteFlavor.FAST)},
+ {(CompressionLevel)2, new Config(4, 5, 16, 8, DefalteFlavor.FAST)},
+ {(CompressionLevel)3, new Config(4, 6, 32, 32, DefalteFlavor.FAST)},
+
+ {(CompressionLevel)4, new Config(4, 4, 16, 16, DefalteFlavor.SLOW)},
+ {(CompressionLevel)5, new Config(8, 16, 32, 32, DefalteFlavor.SLOW)},
+ {(CompressionLevel)6, new Config(8, 16, 128, 128, DefalteFlavor.SLOW)},
+ {(CompressionLevel)7, new Config(8, 32, 128, 256, DefalteFlavor.SLOW)},
+ {(CompressionLevel)8, new Config(32, 128, 258, 1024, DefalteFlavor.SLOW)},
+ {(CompressionLevel)9, new Config(32, 258, 258, 4096, DefalteFlavor.SLOW)},
+ };
+
+ #region Static definitions
+
+ private static readonly byte[] _length_code ={
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12,
+ 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
+ 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
+ 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
+ };
+
+ private static readonly int[] base_length = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
+ 64, 80, 96, 112, 128, 160, 192, 224, 0
+ };
+
+ private static readonly int[] base_dist = {
+ 0, 1, 2, 3, 4, 6, 8, 12, 16, 24,
+ 32, 48, 64, 96, 128, 192, 256, 384, 512, 768,
+ 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576
+ };
+
+ // extra bits for each length code
+ private static readonly int[] extra_lbits ={
+ 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0
+ };
+
+ // extra bits for each distance code
+ private static readonly int[] extra_dbits ={
+ 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13
+ };
+
+ // extra bits for each bit length code
+ private static readonly int[] extra_blbits ={
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7
+ };
+
+ private static readonly byte[] bl_order ={
+ 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
+
+ private static readonly short[] static_ltree = {
+ 12, 8, 140, 8, 76, 8, 204, 8, 44, 8,
+ 172, 8, 108, 8, 236, 8, 28, 8, 156, 8,
+ 92, 8, 220, 8, 60, 8, 188, 8, 124, 8,
+ 252, 8, 2, 8, 130, 8, 66, 8, 194, 8,
+ 34, 8, 162, 8, 98, 8, 226, 8, 18, 8,
+ 146, 8, 82, 8, 210, 8, 50, 8, 178, 8,
+ 114, 8, 242, 8, 10, 8, 138, 8, 74, 8,
+ 202, 8, 42, 8, 170, 8, 106, 8, 234, 8,
+ 26, 8, 154, 8, 90, 8, 218, 8, 58, 8,
+ 186, 8, 122, 8, 250, 8, 6, 8, 134, 8,
+ 70, 8, 198, 8, 38, 8, 166, 8, 102, 8,
+ 230, 8, 22, 8, 150, 8, 86, 8, 214, 8,
+ 54, 8, 182, 8, 118, 8, 246, 8, 14, 8,
+ 142, 8, 78, 8, 206, 8, 46, 8, 174, 8,
+ 110, 8, 238, 8, 30, 8, 158, 8, 94, 8,
+ 222, 8, 62, 8, 190, 8, 126, 8, 254, 8,
+ 1, 8, 129, 8, 65, 8, 193, 8, 33, 8,
+ 161, 8, 97, 8, 225, 8, 17, 8, 145, 8,
+ 81, 8, 209, 8, 49, 8, 177, 8, 113, 8,
+ 241, 8, 9, 8, 137, 8, 73, 8, 201, 8,
+ 41, 8, 169, 8, 105, 8, 233, 8, 25, 8,
+ 153, 8, 89, 8, 217, 8, 57, 8, 185, 8,
+ 121, 8, 249, 8, 5, 8, 133, 8, 69, 8,
+ 197, 8, 37, 8, 165, 8, 101, 8, 229, 8,
+ 21, 8, 149, 8, 85, 8, 213, 8, 53, 8,
+ 181, 8, 117, 8, 245, 8, 13, 8, 141, 8,
+ 77, 8, 205, 8, 45, 8, 173, 8, 109, 8,
+ 237, 8, 29, 8, 157, 8, 93, 8, 221, 8,
+ 61, 8, 189, 8, 125, 8, 253, 8, 19, 9,
+ 275, 9, 147, 9, 403, 9, 83, 9, 339, 9,
+ 211, 9, 467, 9, 51, 9, 307, 9, 179, 9,
+ 435, 9, 115, 9, 371, 9, 243, 9, 499, 9,
+ 11, 9, 267, 9, 139, 9, 395, 9, 75, 9,
+ 331, 9, 203, 9, 459, 9, 43, 9, 299, 9,
+ 171, 9, 427, 9, 107, 9, 363, 9, 235, 9,
+ 491, 9, 27, 9, 283, 9, 155, 9, 411, 9,
+ 91, 9, 347, 9, 219, 9, 475, 9, 59, 9,
+ 315, 9, 187, 9, 443, 9, 123, 9, 379, 9,
+ 251, 9, 507, 9, 7, 9, 263, 9, 135, 9,
+ 391, 9, 71, 9, 327, 9, 199, 9, 455, 9,
+ 39, 9, 295, 9, 167, 9, 423, 9, 103, 9,
+ 359, 9, 231, 9, 487, 9, 23, 9, 279, 9,
+ 151, 9, 407, 9, 87, 9, 343, 9, 215, 9,
+ 471, 9, 55, 9, 311, 9, 183, 9, 439, 9,
+ 119, 9, 375, 9, 247, 9, 503, 9, 15, 9,
+ 271, 9, 143, 9, 399, 9, 79, 9, 335, 9,
+ 207, 9, 463, 9, 47, 9, 303, 9, 175, 9,
+ 431, 9, 111, 9, 367, 9, 239, 9, 495, 9,
+ 31, 9, 287, 9, 159, 9, 415, 9, 95, 9,
+ 351, 9, 223, 9, 479, 9, 63, 9, 319, 9,
+ 191, 9, 447, 9, 127, 9, 383, 9, 255, 9,
+ 511, 9, 0, 7, 64, 7, 32, 7, 96, 7,
+ 16, 7, 80, 7, 48, 7, 112, 7, 8, 7,
+ 72, 7, 40, 7, 104, 7, 24, 7, 88, 7,
+ 56, 7, 120, 7, 4, 7, 68, 7, 36, 7,
+ 100, 7, 20, 7, 84, 7, 52, 7, 116, 7,
+ 3, 8, 131, 8, 67, 8, 195, 8, 35, 8,
+ 163, 8, 99, 8, 227, 8
+ };
+
+ private static readonly short[] static_dtree = {
+ 0, 5, 16, 5, 8, 5, 24, 5, 4, 5,
+ 20, 5, 12, 5, 28, 5, 2, 5, 18, 5,
+ 10, 5, 26, 5, 6, 5, 22, 5, 14, 5,
+ 30, 5, 1, 5, 17, 5, 9, 5, 25, 5,
+ 5, 5, 21, 5, 13, 5, 29, 5, 3, 5,
+ 19, 5, 11, 5, 27, 5, 7, 5, 23, 5
+ };
+ #endregion
+
+ private static readonly String[] z_errmsg = {
+ "need dictionary", // ZLibStatus.Z_NEED_DICT 2
+ "stream end", // ZLibStatus.Z_STREAM_END 1
+ "", // ZLibStatus.Z_OK 0
+ "file error", // ZLibStatus.Z_ERRNO (-1)
+ "stream error", // ZLibStatus.Z_STREAM_ERROR (-2)
+ "data error", // ZLibStatus.Z_DATA_ERROR (-3)
+ "insufficient memory", // Z_MEM_ERROR (-4)
+ "buffer error", // ZLibStatus.Z_BUF_ERROR (-5)
+ "incompatible version",// Z_VERSION_ERROR (-6)
+ ""
+ };
+
+
+
+ ///
+ /// as the name implies
+ ///
+ private int _status;
+
+ private BlockType _dataType;
+
+ ///
+ /// STORED (for zip only) or DEFLATED
+ ///
+ private byte _method;
+
+ ///
+ /// size of pending_buf
+ ///
+ private int _pendingBufferSize;
+
+ ///
+ /// LZ77 window size (32K by default)
+ ///
+ private int _windowSize;
+
+ ///
+ /// log2(w_size) (8..16)
+ ///
+ private int _windowBits;
+
+ ///
+ /// w_size - 1
+ ///
+ private int _windowMask;
+
+ ///
+ /// Sliding window. Input bytes are read into the second half of the window,
+ /// and move to the first half later to keep a dictionary of at least wSize
+ /// bytes. With this organization, matches are limited to a distance of
+ /// wSize-MAX_MATCH bytes, but this ensures that IO is always
+ /// performed with a length multiple of the block size. Also, it limits
+ /// the window size to 64K, which is quite useful on MSDOS.
+ /// To do: use the user input buffer as sliding window.
+ ///
+ private byte[] _window;
+
+ ///
+ /// Actual size of window: 2*wSize, except when the user input buffer
+ /// is directly used as sliding window.
+ ///
+ private int _windowActualSize;
+
+ ///
+ /// Link to older string with same hash index. To limit the size of this
+ /// array to 64K, this link is maintained only for the last 32K strings.
+ /// An index in this array is thus a window index modulo 32K.
+ ///
+ private short[] _previous;
+
+ ///
+ /// Heads of the hash chains or NIL.
+ ///
+ private short[] _head;
+
+ ///
+ /// hash index of string to be inserted
+ ///
+ private int _insertedHashIndex;
+
+ ///
+ /// number of elements in hash table
+ ///
+ private int _hashSize;
+
+ ///
+ /// log2(hash_size)
+ ///
+ private int _hashBits;
+
+ ///
+ /// hash_size-1
+ ///
+ private int _hashMask;
+
+ ///
+ /// Number of bits by which ins_h must be shifted at each input
+ /// step. It must be such that after MIN_MATCH steps, the oldest
+ /// byte no longer takes part in the hash key, that is:
+ /// hash_shift * MIN_MATCH >= hash_bits
+ ///
+ private int _hashShift;
+
+ ///
+ /// Window position at the beginning of the current output block. Gets
+ /// negative when the window is moved backwards.
+ ///
+ private int _blockStart;
+
+ ///
+ /// length of best match
+ ///
+ private int _matchLength;
+
+ ///
+ /// previous match
+ ///
+ private int _previousMatch;
+
+ ///
+ /// set if previous match exists
+ ///
+ private bool _matchAvailable;
+
+ ///
+ /// start of string to insert
+ ///
+ private int _startInsertString;
+
+ ///
+ /// start of matching string
+ ///
+ private int _startMatchString;
+
+ ///
+ /// number of valid bytes ahead in window
+ ///
+ private int _validBytesAhead;
+
+ ///
+ /// Length of the best match at previous step. Matches not greater than this
+ /// are discarded. This is used in the lazy match evaluation.
+ ///
+ private int _previousLength;
+
+ ///
+ /// To speed up deflation, hash chains are never searched beyond this
+ /// length. A higher limit improves compression ratio but degrades the speed.
+ ///
+ private int _maxChainLength;
+
+ ///
+ /// Attempt to find a better match only when the current match is strictly
+ /// smaller than this value. This mechanism is used only for compression
+ /// levels >= 4.
+ ///
+ private int _maxLazyMatch;
+
+ // Insert new strings in the hash table only if the match length is not
+ // greater than this length. This saves time but degrades compression.
+ // max_insert_length is used only for compression levels <= 3.
+
+ ///
+ /// The compression level (1..9)
+ ///
+ private CompressionLevel level;
+
+ ///
+ /// The favor or force Huffman coding
+ ///
+ private CompressionStrategy strategy;
+
+ ///
+ /// Use a faster search when the previous match is longer than this
+ ///
+ private int good_match;
+
+ ///
+ /// Stop searching when current match exceeds this
+ ///
+ private int nice_match;
+
+ ///
+ /// literal and length tree
+ ///
+ private short[] dyn_ltree;
+
+ ///
+ /// The distance tree
+ ///
+ private short[] dyn_dtree;
+
+ ///
+ /// The Huffman tree for bit lengths
+ ///
+ private short[] bl_tree;
+
+ ///
+ /// The desc for literal tree
+ ///
+ private Tree l_desc = new Tree();
+
+ ///
+ /// The desc for distance tree
+ ///
+ private Tree d_desc = new Tree();
+
+ ///
+ /// The desc for bit length tree
+ ///
+ private Tree bl_desc = new Tree();
+
+ ///
+ /// index for literals or lengths
+ ///
+ private int l_buf;
+
+ ///
+ /// Size of match buffer for literals/lengths. There are 4 reasons for
+ /// limiting lit_bufsize to 64K:
+ /// - frequencies can be kept in 16 bit counters
+ /// - if compression is not successful for the first block, all input
+ /// data is still in the window so we can still emit a stored block even
+ /// when input comes from standard input. (This can also be done for
+ /// all blocks if lit_bufsize is not greater than 32K.)
+ /// - if compression is not successful for a file smaller than 64K, we can
+ /// even emit a stored file instead of a stored block (saving 5 bytes).
+ /// This is applicable only for zip (not gzip or zlib).
+ /// - creating new Huffman trees less frequently may not provide fast
+ /// adaptation to changes in the input data statistics. (Take for
+ /// example a binary file with poorly compressible code followed by
+ /// a highly compressible string table.) Smaller buffer sizes give
+ /// fast adaptation but have of course the overhead of transmitting
+ /// trees more frequently.
+ /// - I can't count above 4
+ ///
+ private int lit_bufsize;
+
+ ///
+ /// running index in l_buf
+ ///
+ private int last_lit;
+
+ // Buffer for distances. To simplify the code, d_buf and l_buf have
+ // the same number of elements. To use different lengths, an extra flag
+ // array would be necessary.
+
+ ///
+ /// The index of pendig_buf
+ ///
+ private int d_buf;
+
+ ///
+ /// The number of string matches in current block
+ ///
+ private int matches;
+
+ ///
+ /// The bit length of EOB code for last block
+ ///
+ private int last_eob_len;
+
+ ///
+ /// Output buffer. bits are inserted starting at the bottom (least
+ /// significant bits).
+ ///
+ private uint bi_buf;
+
+ ///
+ /// Number of valid bits in bi_buf. All bits above the last valid bit
+ /// are always zero.
+ ///
+ private int bi_valid;
+
+ ///
+ /// value of flush param for previous deflate call
+ ///
+ private FlushType last_flush;
+
+ ///
+ /// bit length of current block with optimal trees
+ ///
+ internal int opt_len;
+
+ ///
+ /// bit length of current block with static trees
+ ///
+ internal int static_len;
+
+ ///
+ /// The output still pending
+ ///
+ internal byte[] pending_buf;
+
+ ///
+ /// next pending byte to output to the stream
+ ///
+ internal int pending_out;
+
+ ///
+ /// nb of bytes in the pending buffer
+ ///
+ internal int pending;
+
+ ///
+ /// suppress zlib header and adler32
+ ///
+ internal int noheader;
+
+ ///
+ /// number of codes at each bit length for an optimal tree
+ ///
+ internal short[] bl_count = new short[MAX_BITS + 1];
+
+ ///
+ /// heap used to build the Huffman trees
+ ///
+ internal int[] heap = new int[2 * L_CODES + 1];
+
+ ///
+ /// The number of elements in the heap
+ ///
+ internal int heap_len;
+ ///
+ /// The element of largest frequency
+ ///
+ internal int heap_max;
+
+ // The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+ // The same heap array is used to build all trees.
+
+ ///
+ /// Depth of each subtree used as tie breaker for trees of equal frequency
+ ///
+ internal byte[] depth = new byte[2 * L_CODES + 1];
+
+ public Deflate()
+ {
+ dyn_ltree = new short[HEAP_SIZE * 2];
+ dyn_dtree = new short[(2 * D_CODES + 1) * 2]; // distance tree
+ bl_tree = new short[(2 * BL_CODES + 1) * 2]; // Huffman tree for bit lengths
+ }
+
+ public Deflate(CompressionLevel level)
+ : this()
+ {
+ this.deflateInit(level);
+ }
+
+ public Deflate(CompressionLevel level, bool nowrap)
+ : this()
+ {
+ this.deflateInit(level, nowrap);
+ }
+
+ // Restore the heap property by moving down the tree starting at node k,
+ // exchanging a node with the smallest of its two sons if necessary, stopping
+ // when the heap property is re-established (each father smaller than its
+ // two sons).
+ internal void pqdownheap(short[] tree, // the tree to restore
+ int k // node to move down
+ )
+ {
+ int v = heap[k];
+ int j = k << 1; // left son of k
+ while (j <= heap_len)
+ {
+ // Set j to the smallest of the two sons:
+ if (j < heap_len &&
+ smaller(tree, heap[j + 1], heap[j], depth))
+ {
+ j++;
+ }
+ // Exit if v is smaller than both sons
+ if (smaller(tree, v, heap[j], depth)) break;
+
+ // Exchange v with the smallest son
+ heap[k] = heap[j]; k = j;
+ // And continue down the tree, setting j to the left son of k
+ j <<= 1;
+ }
+ heap[k] = v;
+ }
+
+ public ZLibStatus deflateInit(CompressionLevel level)
+ {
+ return deflateInit(level, MAX_WBITS);
+ }
+ public ZLibStatus deflateInit(CompressionLevel level, bool nowrap)
+ {
+ return deflateInit(level, MAX_WBITS, nowrap);
+ }
+
+ public ZLibStatus deflateInit(CompressionLevel level, int bits, bool nowrap)
+ {
+ return this.deflateInit(level, nowrap ? -bits : bits);
+ }
+
+ internal ZLibStatus deflateInit(CompressionLevel level, int bits)
+ {
+ return deflateInit2(level, Z_DEFLATED, bits, DEF_MEM_LEVEL, CompressionStrategy.Z_DEFAULT_STRATEGY);
+ }
+
+ private ZLibStatus deflateInit2(CompressionLevel level, int method, int windowBits, int memLevel, CompressionStrategy strategy)
+ {
+ int noheader = 0;
+ // byte[] my_version=ZLIB_VERSION;
+
+ //
+ // if (version == null || version[0] != my_version[0]
+ // || stream_size != sizeof(z_stream)) {
+ // return Z_VERSION_ERROR;
+ // }
+
+ base.msg = null;
+
+ if (level == CompressionLevel.Z_DEFAULT_COMPRESSION) level = (CompressionLevel)6;
+
+ if (windowBits < 0)
+ { // undocumented feature: suppress zlib header
+ noheader = 1;
+ windowBits = -windowBits;
+ }
+
+ if (memLevel < 1 || memLevel > MAX_MEM_LEVEL ||
+ method != Z_DEFLATED ||
+ windowBits < 9 || windowBits > 15 || level < 0 || level > (CompressionLevel)9 ||
+ strategy < 0 || strategy > CompressionStrategy.Z_HUFFMAN_ONLY)
+ {
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+
+ this.noheader = noheader;
+ _windowBits = windowBits;
+ _windowSize = 1 << _windowBits;
+ _windowMask = _windowSize - 1;
+
+ _hashBits = memLevel + 7;
+ _hashSize = 1 << _hashBits;
+ _hashMask = _hashSize - 1;
+ _hashShift = ((_hashBits + MIN_MATCH - 1) / MIN_MATCH);
+
+ _window = new byte[_windowSize * 2];
+ _previous = new short[_windowSize];
+ _head = new short[_hashSize];
+
+ lit_bufsize = 1 << (memLevel + 6); // 16K elements by default
+
+ // We overlay pending_buf and d_buf+l_buf. This works since the average
+ // output size for (length,distance) codes is <= 24 bits.
+ pending_buf = new byte[lit_bufsize * 4];
+ _pendingBufferSize = lit_bufsize * 4;
+
+ d_buf = lit_bufsize / 2;
+ l_buf = (1 + 2) * lit_bufsize;
+
+ this.level = level;
+
+ //System.out.println("level="+level);
+
+ this.strategy = strategy;
+ this._method = (byte)method;
+
+ return deflateReset();
+ }
+
+ private ZLibStatus deflateReset()
+ {
+ base.total_in = base.total_out = 0;
+ base.msg = null; //
+ base.data_type = BlockType.Z_UNKNOWN;
+
+ pending = 0;
+ pending_out = 0;
+
+ if (noheader < 0)
+ {
+ noheader = 0; // was set to -1 by deflate(..., FlushType.Z_FINISH);
+ }
+ _status = (noheader != 0) ? BUSY_STATE : INIT_STATE;
+ base.adler = Adler32.adler32(0, null, 0, 0);
+
+ last_flush = FlushType.Z_NO_FLUSH;
+
+ tr_init();
+ lm_init();
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus deflateEnd()
+ {
+ if (_status != INIT_STATE && _status != BUSY_STATE && _status != FINISH_STATE)
+ {
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+ // Deallocate in reverse order of allocations:
+ pending_buf = null;
+ _head = null;
+ _previous = null;
+ _window = null;
+ // free
+ // dstate=null;
+ return _status == BUSY_STATE ? ZLibStatus.Z_DATA_ERROR : ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus deflateParams(CompressionLevel _level, CompressionStrategy _strategy)
+ {
+ ZLibStatus err = ZLibStatus.Z_OK;
+
+ if (_level == CompressionLevel.Z_DEFAULT_COMPRESSION)
+ {
+ _level = (CompressionLevel)6;
+ }
+ if (_level < 0 || _level > (CompressionLevel)9 ||
+ _strategy < 0 || _strategy > CompressionStrategy.Z_HUFFMAN_ONLY)
+ {
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+
+ if (config_table[level].Function != config_table[_level].Function &&
+ base.total_in != 0)
+ {
+ // Flush the last buffer:
+ err = this.deflate(FlushType.Z_PARTIAL_FLUSH);
+ }
+
+ if (level != _level)
+ {
+ level = _level;
+ _maxLazyMatch = config_table[level].MaxLazy;
+ good_match = config_table[level].GoodLength;
+ nice_match = config_table[level].NiceLength;
+ _maxChainLength = config_table[level].MaxChain;
+ }
+ strategy = _strategy;
+ return err;
+ }
+
+ public ZLibStatus deflateSetDictionary(byte[] dictionary, int dictLength)
+ {
+ int length = dictLength;
+ int index = 0;
+
+ if (dictionary == null || _status != INIT_STATE)
+ return ZLibStatus.Z_STREAM_ERROR;
+
+ base.adler = Adler32.adler32(base.adler, dictionary, 0, dictLength);
+
+ if (length < MIN_MATCH) return ZLibStatus.Z_OK;
+ if (length > _windowSize - MIN_LOOKAHEAD)
+ {
+ length = _windowSize - MIN_LOOKAHEAD;
+ index = dictLength - length; // use the tail of the dictionary
+ }
+ System.Array.Copy(dictionary, index, _window, 0, length);
+ _startInsertString = length;
+ _blockStart = length;
+
+ // Insert all strings in the hash table (except for the last two bytes).
+ // s->lookahead stays null, so s->ins_h will be recomputed at the next
+ // call of fill_window.
+
+ _insertedHashIndex = _window[0] & 0xff;
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[1] & 0xff)) & _hashMask;
+
+ for (int n = 0; n <= length - MIN_MATCH; n++)
+ {
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[(n) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+ _previous[n & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)n;
+ }
+ return ZLibStatus.Z_OK;
+ }
+
+ private void lm_init()
+ {
+ _windowActualSize = 2 * _windowSize;
+
+ _head[_hashSize - 1] = 0;
+ for (int i = 0; i < _hashSize - 1; i++)
+ {
+ _head[i] = 0;
+ }
+
+ // Set the default configuration parameters:
+ _maxLazyMatch = Deflate.config_table[level].MaxLazy;
+ good_match = Deflate.config_table[level].GoodLength;
+ nice_match = Deflate.config_table[level].NiceLength;
+ _maxChainLength = Deflate.config_table[level].MaxChain;
+
+ _startInsertString = 0;
+ _blockStart = 0;
+ _validBytesAhead = 0;
+ _matchLength = _previousLength = MIN_MATCH - 1;
+ _matchAvailable = false;
+ _insertedHashIndex = 0;
+ }
+
+ // Initialize the tree data structures for a new zlib stream.
+ private void tr_init()
+ {
+
+ l_desc.Init(dyn_ltree, Deflate.static_l_desc);
+
+ d_desc.Init(dyn_dtree, Deflate.static_d_desc);
+
+ bl_desc.Init(bl_tree, Deflate.static_bl_desc);
+
+
+ bi_buf = 0;
+ bi_valid = 0;
+ last_eob_len = 8; // enough lookahead for inflate
+
+ // Initialize the first block of the first file:
+ init_block();
+ }
+
+ private void init_block()
+ {
+ // Initialize the trees.
+ for (int i = 0; i < L_CODES; i++) dyn_ltree[i * 2] = 0;
+ for (int i = 0; i < D_CODES; i++) dyn_dtree[i * 2] = 0;
+ for (int i = 0; i < BL_CODES; i++) bl_tree[i * 2] = 0;
+
+ dyn_ltree[END_BLOCK * 2] = 1;
+ opt_len = static_len = 0;
+ last_lit = matches = 0;
+ }
+
+ private static bool smaller(short[] tree, int n, int m, byte[] depth)
+ {
+ short tn2 = tree[n * 2];
+ short tm2 = tree[m * 2];
+ return (tn2 < tm2 ||
+ (tn2 == tm2 && depth[n] <= depth[m]));
+ }
+
+ // Scan a literal or distance tree to determine the frequencies of the codes
+ // in the bit length tree.
+ private void scan_tree(short[] tree,// the tree to be scanned
+ int max_code // and its largest code of non zero frequency
+ )
+ {
+ int n; // iterates over all tree elements
+ int prevlen = -1; // last emitted length
+ int curlen; // length of current code
+ int nextlen = tree[0 * 2 + 1]; // length of next code
+ int count = 0; // repeat count of the current code
+ int max_count = 7; // max repeat count
+ int min_count = 4; // min repeat count
+
+ if (nextlen == 0) { max_count = 138; min_count = 3; }
+ tree[(max_code + 1) * 2 + 1] = -1; // guard
+
+ for (n = 0; n <= max_code; n++)
+ {
+ curlen = nextlen; nextlen = tree[(n + 1) * 2 + 1];
+ if (++count < max_count && curlen == nextlen)
+ {
+ continue;
+ }
+ else if (count < min_count)
+ {
+ bl_tree[curlen * 2] += (short)count;
+ }
+ else if (curlen != 0)
+ {
+ if (curlen != prevlen) bl_tree[curlen * 2]++;
+ bl_tree[REP_3_6 * 2]++;
+ }
+ else if (count <= 10)
+ {
+ bl_tree[REPZ_3_10 * 2]++;
+ }
+ else
+ {
+ bl_tree[REPZ_11_138 * 2]++;
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0)
+ {
+ max_count = 138; min_count = 3;
+ }
+ else if (curlen == nextlen)
+ {
+ max_count = 6; min_count = 3;
+ }
+ else
+ {
+ max_count = 7; min_count = 4;
+ }
+ }
+ }
+
+ // Construct the Huffman tree for the bit lengths and return the index in
+ // bl_order of the last bit length code to send.
+ private int build_bl_tree()
+ {
+ int max_blindex; // index of last bit length code of non zero freq
+
+ // Determine the bit length frequencies for literal and distance trees
+ scan_tree(dyn_ltree, l_desc.LargestCode);
+ scan_tree(dyn_dtree, d_desc.LargestCode);
+
+ // Build the bit length tree:
+ bl_desc.BuildTree(this);
+ // opt_len now includes the length of the tree representations, except
+ // the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
+
+ // Determine the number of bit length codes to send. The pkzip format
+ // requires that at least 4 bit length codes be sent. (appnote.txt says
+ // 3 but the actual value used is 4.)
+ for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--)
+ {
+ if (bl_tree[Deflate.bl_order[max_blindex] * 2 + 1] != 0) break;
+ }
+ // Update opt_len to include the bit length tree and counts
+ opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4;
+
+ return max_blindex;
+ }
+
+
+ // Send the header for a block using dynamic Huffman trees: the counts, the
+ // lengths of the bit length codes, the literal tree and the distance tree.
+ // IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
+ private void send_all_trees(int lcodes, int dcodes, int blcodes)
+ {
+ int rank; // index in bl_order
+
+ send_bits(lcodes - 257, 5); // not +255 as stated in appnote.txt
+ send_bits(dcodes - 1, 5);
+ send_bits(blcodes - 4, 4); // not -3 as stated in appnote.txt
+ for (rank = 0; rank < blcodes; rank++)
+ {
+ send_bits(bl_tree[Deflate.bl_order[rank] * 2 + 1], 3);
+ }
+ send_tree(dyn_ltree, lcodes - 1); // literal tree
+ send_tree(dyn_dtree, dcodes - 1); // distance tree
+ }
+
+ // Send a literal or distance tree in compressed form, using the codes in
+ // bl_tree.
+ private void send_tree(short[] tree,// the tree to be sent
+ int max_code // and its largest code of non zero frequency
+ )
+ {
+ int n; // iterates over all tree elements
+ int prevlen = -1; // last emitted length
+ int curlen; // length of current code
+ int nextlen = tree[0 * 2 + 1]; // length of next code
+ int count = 0; // repeat count of the current code
+ int max_count = 7; // max repeat count
+ int min_count = 4; // min repeat count
+
+ if (nextlen == 0) { max_count = 138; min_count = 3; }
+
+ for (n = 0; n <= max_code; n++)
+ {
+ curlen = nextlen; nextlen = tree[(n + 1) * 2 + 1];
+ if (++count < max_count && curlen == nextlen)
+ {
+ continue;
+ }
+ else if (count < min_count)
+ {
+ do { send_code(curlen, bl_tree); } while (--count != 0);
+ }
+ else if (curlen != 0)
+ {
+ if (curlen != prevlen)
+ {
+ send_code(curlen, bl_tree); count--;
+ }
+ send_code(REP_3_6, bl_tree);
+ send_bits(count - 3, 2);
+ }
+ else if (count <= 10)
+ {
+ send_code(REPZ_3_10, bl_tree);
+ send_bits(count - 3, 3);
+ }
+ else
+ {
+ send_code(REPZ_11_138, bl_tree);
+ send_bits(count - 11, 7);
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0)
+ {
+ max_count = 138; min_count = 3;
+ }
+ else if (curlen == nextlen)
+ {
+ max_count = 6; min_count = 3;
+ }
+ else
+ {
+ max_count = 7; min_count = 4;
+ }
+ }
+ }
+
+ // Output a byte on the stream.
+ // IN assertion: there is enough room in pending_buf.
+ private void put_byte(byte[] p, int start, int len)
+ {
+ System.Array.Copy(p, start, pending_buf, pending, len);
+ pending += len;
+ }
+
+ private void put_byte(byte c)
+ {
+ pending_buf[pending++] = c;
+ }
+ private void put_short(int w)
+ {
+ pending_buf[pending++] = (byte)(w/*&0xff*/);
+ pending_buf[pending++] = (byte)(w >> 8);
+ }
+ private void putShortMSB(int b)
+ {
+ pending_buf[pending++] = (byte)(b >> 8);
+ pending_buf[pending++] = (byte)(b/*&0xff*/);
+ }
+
+ private void send_code(int c, short[] tree)
+ {
+ int c2 = c * 2;
+ send_bits((tree[c2] & 0xffff), (tree[c2 + 1] & 0xffff));
+ }
+
+ private void send_bits(int val, int length)
+ {
+ if (bi_valid > Buf_size - length)
+ {
+ bi_buf |= (uint)(val << bi_valid);
+ pending_buf[pending++] = (byte)(bi_buf/*&0xff*/);
+ pending_buf[pending++] = (byte)(bi_buf >> 8);
+ bi_buf = ((uint)val) >> (Buf_size - bi_valid);
+ bi_valid += length - Buf_size;
+ }
+ else
+ {
+ bi_buf |= (uint)(val << bi_valid);
+ bi_valid += length;
+ }
+ // int len = length;
+ // if (bi_valid > (int)Buf_size - len) {
+ // int val = value;
+ // // bi_buf |= (val << bi_valid);
+ // bi_buf = (short)((ushort)bi_buf | (ushort)((val << bi_valid)&0xffff));
+ // put_short(bi_buf);
+ // bi_buf = (short)(((uint)val) >> (Buf_size - bi_valid));
+ // bi_valid += len - Buf_size;
+ // } else {
+ // // bi_buf |= (value) << bi_valid;
+ // bi_buf = (short)((ushort)bi_buf | (ushort)(((value) << bi_valid)&0xffff));
+ // bi_valid += len;
+ // }
+ }
+
+ // Send one empty static block to give enough lookahead for inflate.
+ // This takes 10 bits, of which 7 may remain in the bit buffer.
+ // The current inflate code requires 9 bits of lookahead. If the
+ // last two codes for the previous block (real code plus EOB) were coded
+ // on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
+ // the last real code. In this case we send two empty static blocks instead
+ // of one. (There are no problems if the previous block is stored or fixed.)
+ // To simplify the code, we assume the worst case of last real code encoded
+ // on one bit only.
+ private void _tr_align()
+ {
+ send_bits(STATIC_TREES << 1, 3);
+ send_code(END_BLOCK, Deflate.static_ltree);
+
+ bi_flush();
+
+ // Of the 10 bits for the empty block, we have already sent
+ // (10 - bi_valid) bits. The lookahead for the last real code (before
+ // the EOB of the previous block) was thus at least one plus the length
+ // of the EOB plus what we have just sent of the empty static block.
+ if (1 + last_eob_len + 10 - bi_valid < 9)
+ {
+ send_bits(STATIC_TREES << 1, 3);
+ send_code(END_BLOCK, Deflate.static_ltree);
+ bi_flush();
+ }
+ last_eob_len = 7;
+ }
+
+
+ // Save the match info and tally the frequency counts. Return true if
+ // the current block must be flushed.
+ private bool _tr_tally(int dist, // distance of matched string
+ int lc // match length-MIN_MATCH or unmatched char (if dist==0)
+ )
+ {
+
+ pending_buf[d_buf + last_lit * 2] = (byte)(dist >> 8);
+ pending_buf[d_buf + last_lit * 2 + 1] = (byte)dist;
+
+ pending_buf[l_buf + last_lit] = (byte)lc; last_lit++;
+
+ if (dist == 0)
+ {
+ // lc is the unmatched char
+ dyn_ltree[lc * 2]++;
+ }
+ else
+ {
+ matches++;
+ // Here, lc is the match length - MIN_MATCH
+ dist--; // dist = match distance - 1
+ dyn_ltree[(Deflate._length_code[lc] + LITERALS + 1) * 2]++;
+ dyn_dtree[Tree.DistanceCode(dist) * 2]++;
+ }
+
+ if ((last_lit & 0x1fff) == 0 && level > (CompressionLevel)2)
+ {
+ // Compute an upper bound for the compressed length
+ int out_length = last_lit * 8;
+ int in_length = _startInsertString - _blockStart;
+ int dcode;
+ for (dcode = 0; dcode < D_CODES; dcode++)
+ {
+ out_length += (int)((int)dyn_dtree[dcode * 2] *
+ (5L + Deflate.extra_dbits[dcode]));
+ }
+ out_length >>= 3;
+ if ((matches < (last_lit / 2)) && out_length < in_length / 2) return true;
+ }
+
+ return (last_lit == lit_bufsize - 1);
+ // We avoid equality with lit_bufsize because of wraparound at 64K
+ // on 16 bit machines and because stored blocks are restricted to
+ // 64K-1 bytes.
+ }
+
+ // Send the block data compressed using the given Huffman trees
+ private void compress_block(short[] ltree, short[] dtree)
+ {
+ int dist; // distance of matched string
+ int lc; // match length or unmatched char (if dist == 0)
+ int lx = 0; // running index in l_buf
+ int code; // the code to send
+ int extra; // number of extra bits to send
+
+ if (last_lit != 0)
+ {
+ do
+ {
+ dist = ((pending_buf[d_buf + lx * 2] << 8) & 0xff00) |
+ (pending_buf[d_buf + lx * 2 + 1] & 0xff);
+ lc = (pending_buf[l_buf + lx]) & 0xff; lx++;
+
+ if (dist == 0)
+ {
+ send_code(lc, ltree); // send a literal byte
+ }
+ else
+ {
+ // Here, lc is the match length - MIN_MATCH
+ code = Deflate._length_code[lc];
+
+ send_code(code + LITERALS + 1, ltree); // send the length code
+ extra = Deflate.extra_lbits[code];
+ if (extra != 0)
+ {
+ lc -= Deflate.base_length[code];
+ send_bits(lc, extra); // send the extra length bits
+ }
+ dist--; // dist is now the match distance - 1
+ code = Tree.DistanceCode(dist);
+
+ send_code(code, dtree); // send the distance code
+ extra = Deflate.extra_dbits[code];
+ if (extra != 0)
+ {
+ dist -= Deflate.base_dist[code];
+ send_bits(dist, extra); // send the extra distance bits
+ }
+ } // literal or match pair ?
+
+ // Check that the overlay between pending_buf and d_buf+l_buf is ok:
+ }
+ while (lx < last_lit);
+ }
+
+ send_code(END_BLOCK, ltree);
+ last_eob_len = ltree[END_BLOCK * 2 + 1];
+ }
+
+ // Set the data type to ASCII or BINARY, using a crude approximation:
+ // binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise.
+ // IN assertion: the fields freq of dyn_ltree are set and the total of all
+ // frequencies does not exceed 64K (to fit in an int on 16 bit machines).
+ private void set_data_type()
+ {
+ int n = 0;
+ int ascii_freq = 0;
+ int bin_freq = 0;
+ while (n < 7) { bin_freq += dyn_ltree[n * 2]; n++; }
+ while (n < 128) { ascii_freq += dyn_ltree[n * 2]; n++; }
+ while (n < LITERALS) { bin_freq += dyn_ltree[n * 2]; n++; }
+ this._dataType = (bin_freq > (ascii_freq >> 2) ? BlockType.Z_BINARY : BlockType.Z_ASCII);
+ }
+
+ // Flush the bit buffer, keeping at most 7 bits in it.
+ private void bi_flush()
+ {
+ if (bi_valid == 16)
+ {
+ pending_buf[pending++] = (byte)(bi_buf/*&0xff*/);
+ pending_buf[pending++] = (byte)(bi_buf >> 8);
+ bi_buf = 0;
+ bi_valid = 0;
+ }
+ else if (bi_valid >= 8)
+ {
+ pending_buf[pending++] = (byte)(bi_buf);
+ bi_buf >>= 8;
+ bi_buf &= 0x00ff;
+ bi_valid -= 8;
+ }
+ }
+
+ // Flush the bit buffer and align the output on a byte boundary
+ private void bi_windup()
+ {
+ if (bi_valid > 8)
+ {
+ pending_buf[pending++] = (byte)(bi_buf);
+ pending_buf[pending++] = (byte)(bi_buf >> 8);
+ }
+ else if (bi_valid > 0)
+ {
+ pending_buf[pending++] = (byte)(bi_buf);
+ }
+ bi_buf = 0;
+ bi_valid = 0;
+ }
+
+ // Copy a stored block, storing first the length and its
+ // one's complement if requested.
+ private void copy_block(int buf, // the input data
+ int len, // its length
+ bool header // true if block header must be written
+ )
+ {
+ //int index=0;
+ bi_windup(); // align on byte boundary
+ last_eob_len = 8; // enough lookahead for inflate
+
+ if (header)
+ {
+ put_short((short)len);
+ put_short((short)~len);
+ }
+
+ // while(len--!=0) {
+ // put_byte(window[buf+index]);
+ // index++;
+ // }
+ put_byte(_window, buf, len);
+ }
+
+ private void flush_block_only(bool eof)
+ {
+ _tr_flush_block(_blockStart >= 0 ? _blockStart : -1,
+ _startInsertString - _blockStart,
+ eof);
+ _blockStart = _startInsertString;
+ this.flush_pending();
+ }
+
+ // Copy without compression as much as possible from the input stream, return
+ // the current block state.
+ // This function does not insert new strings in the dictionary since
+ // uncompressible data is probably not useful. This function is used
+ // only for the level=0 compression option.
+ // NOTE: this function should be optimized to avoid extra copying from
+ // window to pending_buf.
+ private int deflate_stored(FlushType flush)
+ {
+ // Stored blocks are limited to 0xffff bytes, pending_buf is limited
+ // to pending_buf_size, and each stored block has a 5 byte header:
+
+ int max_block_size = 0xffff;
+ int max_start;
+
+ if (max_block_size > _pendingBufferSize - 5)
+ {
+ max_block_size = _pendingBufferSize - 5;
+ }
+
+ // Copy as much as possible from input to output:
+ while (true)
+ {
+ // Fill the window as much as possible:
+ if (_validBytesAhead <= 1)
+ {
+ fill_window();
+ if (_validBytesAhead == 0 && flush == FlushType.Z_NO_FLUSH) return NeedMore;
+ if (_validBytesAhead == 0) break; // flush the current block
+ }
+
+ _startInsertString += _validBytesAhead;
+ _validBytesAhead = 0;
+
+ // Emit a stored block if pending_buf will be full:
+ max_start = _blockStart + max_block_size;
+ if (_startInsertString == 0 || _startInsertString >= max_start)
+ {
+ // strstart == 0 is possible when wraparound on 16-bit machine
+ _validBytesAhead = (int)(_startInsertString - max_start);
+ _startInsertString = (int)max_start;
+
+ flush_block_only(false);
+ if (base.avail_out == 0) return NeedMore;
+
+ }
+
+ // Flush if we may have to slide, otherwise block_start may become
+ // negative and the data will be gone:
+ if (_startInsertString - _blockStart >= _windowSize - MIN_LOOKAHEAD)
+ {
+ flush_block_only(false);
+ if (base.avail_out == 0) return NeedMore;
+ }
+ }
+
+ flush_block_only(flush == FlushType.Z_FINISH);
+ if (base.avail_out == 0)
+ return (flush == FlushType.Z_FINISH) ? FinishStarted : NeedMore;
+
+ return flush == FlushType.Z_FINISH ? FinishDone : BlockDone;
+ }
+
+ // Send a stored block
+ private void _tr_stored_block(int buf, // input block
+ int stored_len, // length of input block
+ bool eof // true if this is the last block for a file
+ )
+ {
+ send_bits((STORED_BLOCK << 1) + (eof ? 1 : 0), 3); // send block type
+ copy_block(buf, stored_len, true); // with header
+ }
+
+ // Determine the best encoding for the current block: dynamic trees, static
+ // trees or store, and output the encoded block to the zip file.
+ private void _tr_flush_block(int buf, // input block, or NULL if too old
+ int stored_len, // length of input block
+ bool eof // true if this is the last block for a file
+ )
+ {
+ int opt_lenb, static_lenb;// opt_len and static_len in bytes
+ int max_blindex = 0; // index of last bit length code of non zero freq
+
+ // Build the Huffman trees unless a stored block is forced
+ if (level > 0)
+ {
+ // Check if the file is ascii or binary
+ if (this._dataType == BlockType.Z_UNKNOWN) set_data_type();
+
+ // Construct the literal and distance trees
+ l_desc.BuildTree(this);
+
+ d_desc.BuildTree(this);
+
+ // At this point, opt_len and static_len are the total bit lengths of
+ // the compressed block data, excluding the tree representations.
+
+ // Build the bit length tree for the above two trees, and get the index
+ // in bl_order of the last bit length code to send.
+ max_blindex = build_bl_tree();
+
+ // Determine the best encoding. Compute first the block length in bytes
+ opt_lenb = (opt_len + 3 + 7) >> 3;
+ static_lenb = (static_len + 3 + 7) >> 3;
+
+ if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
+ }
+ else
+ {
+ opt_lenb = static_lenb = stored_len + 5; // force a stored block
+ }
+
+ if (stored_len + 4 <= opt_lenb && buf != -1)
+ {
+ // 4: two words for the lengths
+ // The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
+ // Otherwise we can't have processed more than WSIZE input bytes since
+ // the last block flush, because compression would have been
+ // successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
+ // transform a block into a stored block.
+ _tr_stored_block(buf, stored_len, eof);
+ }
+ else if (static_lenb == opt_lenb)
+ {
+ send_bits((STATIC_TREES << 1) + (eof ? 1 : 0), 3);
+ compress_block(Deflate.static_ltree, Deflate.static_dtree);
+ }
+ else
+ {
+ send_bits((DYN_TREES << 1) + (eof ? 1 : 0), 3);
+ send_all_trees(l_desc.LargestCode + 1, d_desc.LargestCode + 1, max_blindex + 1);
+ compress_block(dyn_ltree, dyn_dtree);
+ }
+
+ // The above check is made mod 2^32, for files larger than 512 MB
+ // and uLong implemented on 32 bits.
+
+ init_block();
+
+ if (eof)
+ {
+ bi_windup();
+ }
+ }
+
+ // Fill the window when the lookahead becomes insufficient.
+ // Updates strstart and lookahead.
+ //
+ // IN assertion: lookahead < MIN_LOOKAHEAD
+ // OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
+ // At least one byte has been read, or avail_in == 0; reads are
+ // performed for at least two bytes (required for the zip translate_eol
+ // option -- not supported here).
+ private void fill_window()
+ {
+ int n, m;
+ int p;
+ int more; // Amount of free space at the end of the window.
+
+ do
+ {
+ more = (_windowActualSize - _validBytesAhead - _startInsertString);
+
+ // Deal with !@#$% 64K limit:
+ if (more == 0 && _startInsertString == 0 && _validBytesAhead == 0)
+ {
+ more = _windowSize;
+ }
+ else if (more == -1)
+ {
+ // Very unlikely, but possible on 16 bit machine if strstart == 0
+ // and lookahead == 1 (input done one byte at time)
+ more--;
+
+ // If the window is almost full and there is insufficient lookahead,
+ // move the upper half to the lower one to make room in the upper half.
+ }
+ else if (_startInsertString >= _windowSize + _windowSize - MIN_LOOKAHEAD)
+ {
+ System.Array.Copy(_window, _windowSize, _window, 0, _windowSize);
+ _startMatchString -= _windowSize;
+ _startInsertString -= _windowSize; // we now have strstart >= MAX_DIST
+ _blockStart -= _windowSize;
+
+ // Slide the hash table (could be avoided with 32 bit values
+ // at the expense of memory usage). We slide even when level == 0
+ // to keep the hash table consistent if we switch back to level > 0
+ // later. (Using level 0 permanently is not an optimal usage of
+ // zlib, so we don't care about this pathological case.)
+
+ n = _hashSize;
+ p = n;
+ do
+ {
+ m = (_head[--p] & 0xffff);
+ _head[p] = (short)(m >= _windowSize ? (m - _windowSize) : 0);
+ }
+ while (--n != 0);
+
+ n = _windowSize;
+ p = n;
+ do
+ {
+ m = (_previous[--p] & 0xffff);
+ _previous[p] = (short)(m >= _windowSize ? (m - _windowSize) : 0);
+ // If n is not on any hash chain, prev[n] is garbage but
+ // its value will never be used.
+ }
+ while (--n != 0);
+ more += _windowSize;
+ }
+
+ if (base.avail_in == 0) return;
+
+ // If there was no sliding:
+ // strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
+ // more == window_size - lookahead - strstart
+ // => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
+ // => more >= window_size - 2*WSIZE + 2
+ // In the BIG_MEM or MMAP case (not yet supported),
+ // window_size == input_size + MIN_LOOKAHEAD &&
+ // strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
+ // Otherwise, window_size == 2*WSIZE so more >= 2.
+ // If there was sliding, more >= WSIZE. So in all cases, more >= 2.
+
+ n = this.read_buf(_window, _startInsertString + _validBytesAhead, more);
+ _validBytesAhead += n;
+
+ // Initialize the hash value now that we have some input:
+ if (_validBytesAhead >= MIN_MATCH)
+ {
+ _insertedHashIndex = _window[_startInsertString] & 0xff;
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[_startInsertString + 1] & 0xff)) & _hashMask;
+ }
+ // If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
+ // but this is not important since only literal bytes will be emitted.
+ }
+ while (_validBytesAhead < MIN_LOOKAHEAD && base.avail_in != 0);
+ }
+
+ // Compress as much as possible from the input stream, return the current
+ // block state.
+ // This function does not perform lazy evaluation of matches and inserts
+ // new strings in the dictionary only for unmatched strings or for short
+ // matches. It is used only for the fast compression options.
+ private int deflate_fast(FlushType flush)
+ {
+ // short hash_head = 0; // head of the hash chain
+ int hash_head = 0; // head of the hash chain
+ bool bflush; // set if current block must be flushed
+
+ while (true)
+ {
+ // Make sure that we always have enough lookahead, except
+ // at the end of the input file. We need MAX_MATCH bytes
+ // for the next match, plus MIN_MATCH bytes to insert the
+ // string following the next match.
+ if (_validBytesAhead < MIN_LOOKAHEAD)
+ {
+ fill_window();
+ if (_validBytesAhead < MIN_LOOKAHEAD && flush == FlushType.Z_NO_FLUSH)
+ {
+ return NeedMore;
+ }
+ if (_validBytesAhead == 0) break; // flush the current block
+ }
+
+ // Insert the string window[strstart .. strstart+2] in the
+ // dictionary, and set hash_head to the head of the hash chain:
+ if (_validBytesAhead >= MIN_MATCH)
+ {
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[(_startInsertString) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+
+ // prev[strstart&w_mask]=hash_head=head[ins_h];
+ hash_head = (_head[_insertedHashIndex] & 0xffff);
+ _previous[_startInsertString & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)_startInsertString;
+ }
+
+ // Find the longest match, discarding those <= prev_length.
+ // At this point we have always match_length < MIN_MATCH
+
+ if (hash_head != 0L &&
+ ((_startInsertString - hash_head) & 0xffff) <= _windowSize - MIN_LOOKAHEAD
+ )
+ {
+ // To simplify the code, we prevent matches with the string
+ // of window index 0 (in particular we have to avoid a match
+ // of the string with itself at the start of the input file).
+ if (strategy != CompressionStrategy.Z_HUFFMAN_ONLY)
+ {
+ _matchLength = longest_match(hash_head);
+ }
+ // longest_match() sets match_start
+ }
+ if (_matchLength >= MIN_MATCH)
+ {
+ // check_match(strstart, match_start, match_length);
+
+ bflush = _tr_tally(_startInsertString - _startMatchString, _matchLength - MIN_MATCH);
+
+ _validBytesAhead -= _matchLength;
+
+ // Insert new strings in the hash table only if the match length
+ // is not too large. This saves time but degrades compression.
+ if (_matchLength <= _maxLazyMatch &&
+ _validBytesAhead >= MIN_MATCH)
+ {
+ _matchLength--; // string at strstart already in hash table
+ do
+ {
+ _startInsertString++;
+
+ _insertedHashIndex = ((_insertedHashIndex << _hashShift) ^ (_window[(_startInsertString) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+ // prev[strstart&w_mask]=hash_head=head[ins_h];
+ hash_head = (_head[_insertedHashIndex] & 0xffff);
+ _previous[_startInsertString & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)_startInsertString;
+
+ // strstart never exceeds WSIZE-MAX_MATCH, so there are
+ // always MIN_MATCH bytes ahead.
+ }
+ while (--_matchLength != 0);
+ _startInsertString++;
+ }
+ else
+ {
+ _startInsertString += _matchLength;
+ _matchLength = 0;
+ _insertedHashIndex = _window[_startInsertString] & 0xff;
+
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[_startInsertString + 1] & 0xff)) & _hashMask;
+ // If lookahead < MIN_MATCH, ins_h is garbage, but it does not
+ // matter since it will be recomputed at next deflate call.
+ }
+ }
+ else
+ {
+ // No match, output a literal byte
+
+ bflush = _tr_tally(0, _window[_startInsertString] & 0xff);
+ _validBytesAhead--;
+ _startInsertString++;
+ }
+ if (bflush)
+ {
+
+ flush_block_only(false);
+ if (base.avail_out == 0) return NeedMore;
+ }
+ }
+
+ flush_block_only(flush == FlushType.Z_FINISH);
+ if (base.avail_out == 0)
+ {
+ if (flush == FlushType.Z_FINISH) return FinishStarted;
+ else return NeedMore;
+ }
+ return flush == FlushType.Z_FINISH ? FinishDone : BlockDone;
+ }
+
+ // Same as above, but achieves better compression. We use a lazy
+ // evaluation for matches: a match is finally adopted only if there is
+ // no better match at the next window position.
+ private int deflate_slow(FlushType flush)
+ {
+ // short hash_head = 0; // head of hash chain
+ int hash_head = 0; // head of hash chain
+ bool bflush; // set if current block must be flushed
+
+ // Process the input block.
+ while (true)
+ {
+ // Make sure that we always have enough lookahead, except
+ // at the end of the input file. We need MAX_MATCH bytes
+ // for the next match, plus MIN_MATCH bytes to insert the
+ // string following the next match.
+
+ if (_validBytesAhead < MIN_LOOKAHEAD)
+ {
+ fill_window();
+ if (_validBytesAhead < MIN_LOOKAHEAD && flush == FlushType.Z_NO_FLUSH)
+ {
+ return NeedMore;
+ }
+ if (_validBytesAhead == 0) break; // flush the current block
+ }
+
+ // Insert the string window[strstart .. strstart+2] in the
+ // dictionary, and set hash_head to the head of the hash chain:
+
+ if (_validBytesAhead >= MIN_MATCH)
+ {
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[(_startInsertString) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+ // prev[strstart&w_mask]=hash_head=head[ins_h];
+ hash_head = (_head[_insertedHashIndex] & 0xffff);
+ _previous[_startInsertString & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)_startInsertString;
+ }
+
+ // Find the longest match, discarding those <= prev_length.
+ _previousLength = _matchLength; _previousMatch = _startMatchString;
+ _matchLength = MIN_MATCH - 1;
+
+ if (hash_head != 0 && _previousLength < _maxLazyMatch &&
+ ((_startInsertString - hash_head) & 0xffff) <= _windowSize - MIN_LOOKAHEAD
+ )
+ {
+ // To simplify the code, we prevent matches with the string
+ // of window index 0 (in particular we have to avoid a match
+ // of the string with itself at the start of the input file).
+
+ if (strategy != CompressionStrategy.Z_HUFFMAN_ONLY)
+ {
+ _matchLength = longest_match(hash_head);
+ }
+ // longest_match() sets match_start
+
+ if (_matchLength <= 5 && (strategy == CompressionStrategy.Z_FILTERED ||
+ (_matchLength == MIN_MATCH &&
+ _startInsertString - _startMatchString > 4096)))
+ {
+
+ // If prev_match is also MIN_MATCH, match_start is garbage
+ // but we will ignore the current match anyway.
+ _matchLength = MIN_MATCH - 1;
+ }
+ }
+
+ // If there was a match at the previous step and the current
+ // match is not better, output the previous match:
+ if (_previousLength >= MIN_MATCH && _matchLength <= _previousLength)
+ {
+ int max_insert = _startInsertString + _validBytesAhead - MIN_MATCH;
+ // Do not insert strings in hash table beyond this.
+
+ // check_match(strstart-1, prev_match, prev_length);
+
+ bflush = _tr_tally(_startInsertString - 1 - _previousMatch, _previousLength - MIN_MATCH);
+
+ // Insert in hash table all strings up to the end of the match.
+ // strstart-1 and strstart are already inserted. If there is not
+ // enough lookahead, the last two strings are not inserted in
+ // the hash table.
+ _validBytesAhead -= _previousLength - 1;
+ _previousLength -= 2;
+ do
+ {
+ if (++_startInsertString <= max_insert)
+ {
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[(_startInsertString) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+ //prev[strstart&w_mask]=hash_head=head[ins_h];
+ hash_head = (_head[_insertedHashIndex] & 0xffff);
+ _previous[_startInsertString & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)_startInsertString;
+ }
+ }
+ while (--_previousLength != 0);
+ _matchAvailable = false;
+ _matchLength = MIN_MATCH - 1;
+ _startInsertString++;
+
+ if (bflush)
+ {
+ flush_block_only(false);
+ if (base.avail_out == 0) return NeedMore;
+ }
+ }
+ else if (_matchAvailable != false)
+ {
+
+ // If there was no match at the previous position, output a
+ // single literal. If there was a match but the current match
+ // is longer, truncate the previous match to a single literal.
+
+ bflush = _tr_tally(0, _window[_startInsertString - 1] & 0xff);
+
+ if (bflush)
+ {
+ flush_block_only(false);
+ }
+ _startInsertString++;
+ _validBytesAhead--;
+ if (base.avail_out == 0) return NeedMore;
+ }
+ else
+ {
+ // There is no previous match to compare with, wait for
+ // the next step to decide.
+
+ _matchAvailable = true;
+ _startInsertString++;
+ _validBytesAhead--;
+ }
+ }
+
+ if (_matchAvailable != false)
+ {
+ bflush = _tr_tally(0, _window[_startInsertString - 1] & 0xff);
+ _matchAvailable = false;
+ }
+ flush_block_only(flush == FlushType.Z_FINISH);
+
+ if (base.avail_out == 0)
+ {
+ if (flush == FlushType.Z_FINISH) return FinishStarted;
+ else return NeedMore;
+ }
+
+ return flush == FlushType.Z_FINISH ? FinishDone : BlockDone;
+ }
+
+ private int longest_match(int cur_match)
+ {
+ int chain_length = _maxChainLength; // max hash chain length
+ int scan = _startInsertString; // current string
+ int match; // matched string
+ int len; // length of current match
+ int best_len = _previousLength; // best match length so far
+ int limit = _startInsertString > (_windowSize - MIN_LOOKAHEAD) ?
+ _startInsertString - (_windowSize - MIN_LOOKAHEAD) : 0;
+ int nice_match = this.nice_match;
+
+ // Stop when cur_match becomes <= limit. To simplify the code,
+ // we prevent matches with the string of window index 0.
+
+ int wmask = _windowMask;
+
+ int strend = _startInsertString + MAX_MATCH;
+ byte scan_end1 = _window[scan + best_len - 1];
+ byte scan_end = _window[scan + best_len];
+
+ // The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+ // It is easy to get rid of this optimization if necessary.
+
+ // Do not waste too much time if we already have a good match:
+ if (_previousLength >= good_match)
+ {
+ chain_length >>= 2;
+ }
+
+ // Do not look for matches beyond the end of the input. This is necessary
+ // to make deflate deterministic.
+ if (nice_match > _validBytesAhead) nice_match = _validBytesAhead;
+
+ do
+ {
+ match = cur_match;
+
+ // Skip to next match if the match length cannot increase
+ // or if the match length is less than 2:
+ if (_window[match + best_len] != scan_end ||
+ _window[match + best_len - 1] != scan_end1 ||
+ _window[match] != _window[scan] ||
+ _window[++match] != _window[scan + 1]) continue;
+
+ // The check at best_len-1 can be removed because it will be made
+ // again later. (This heuristic is not always a win.)
+ // It is not necessary to compare scan[2] and match[2] since they
+ // are always equal when the other bytes match, given that
+ // the hash keys are equal and that HASH_BITS >= 8.
+ scan += 2; match++;
+
+ // We check for insufficient lookahead only every 8th comparison;
+ // the 256th check will be made at strstart+258.
+ do
+ {
+ } while (_window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ scan < strend);
+
+ len = MAX_MATCH - (int)(strend - scan);
+ scan = strend - MAX_MATCH;
+
+ if (len > best_len)
+ {
+ _startMatchString = cur_match;
+ best_len = len;
+ if (len >= nice_match) break;
+ scan_end1 = _window[scan + best_len - 1];
+ scan_end = _window[scan + best_len];
+ }
+
+ } while ((cur_match = (_previous[cur_match & wmask] & 0xffff)) > limit
+ && --chain_length != 0);
+
+ if (best_len <= _validBytesAhead) return best_len;
+ return _validBytesAhead;
+ }
+
+ public ZLibStatus deflate(FlushType flush)
+ {
+ FlushType old_flush;
+
+ if (flush > FlushType.Z_FINISH || flush < 0)
+ {
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+
+ if (base.next_out == null ||
+ (base.next_in == null && base.avail_in != 0) ||
+ (_status == FINISH_STATE && flush != FlushType.Z_FINISH))
+ {
+ base.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_STREAM_ERROR)];
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+ if (base.avail_out == 0)
+ {
+ base.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_BUF_ERROR)];
+ return ZLibStatus.Z_BUF_ERROR;
+ }
+
+ old_flush = last_flush;
+ last_flush = flush;
+
+ // Write the zlib header
+ if (_status == INIT_STATE)
+ {
+ int header = (Z_DEFLATED + ((this._windowBits - 8) << 4)) << 8;
+ int level_flags = (((int)this.level - 1) & 0xff) >> 1;
+
+ if (level_flags > 3) level_flags = 3;
+ header |= (level_flags << 6);
+ if (this._startInsertString != 0) header |= PRESET_DICT;
+ header += 31 - (header % 31);
+
+ _status = BUSY_STATE;
+ putShortMSB(header);
+
+
+ // Save the adler32 of the preset dictionary:
+ if (this._startInsertString != 0)
+ {
+ putShortMSB((int)(base.adler >> 16));
+ putShortMSB((int)(base.adler & 0xffff));
+ }
+ base.adler = Adler32.adler32(0, null, 0, 0);
+ }
+
+ // Flush as much pending output as possible
+ if (pending != 0)
+ {
+ this.flush_pending();
+ if (base.avail_out == 0)
+ {
+ //System.out.println(" avail_out==0");
+ // Since avail_out is 0, deflate will be called again with
+ // more output space, but possibly with both pending and
+ // avail_in equal to zero. There won't be anything to do,
+ // but this is not an error situation so make sure we
+ // return OK instead of BUF_ERROR at next call of deflate:
+ last_flush = (FlushType)(-1);
+ return ZLibStatus.Z_OK;
+ }
+
+ // Make sure there is something to do and avoid duplicate consecutive
+ // flushes. For repeated and useless calls with Z_FINISH, we keep
+ // returning Z_STREAM_END instead of Z_BUFF_ERROR.
+ }
+ else if (base.avail_in == 0 && flush <= old_flush &&
+ flush != FlushType.Z_FINISH)
+ {
+ base.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_BUF_ERROR)];
+ return ZLibStatus.Z_BUF_ERROR;
+ }
+
+ // User must not provide more input after the first FINISH:
+ if (_status == FINISH_STATE && base.avail_in != 0)
+ {
+ base.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_BUF_ERROR)];
+ return ZLibStatus.Z_BUF_ERROR;
+ }
+
+ // Start a new block or continue the current one.
+ if (base.avail_in != 0 || this._validBytesAhead != 0 ||
+ (flush != FlushType.Z_NO_FLUSH && _status != FINISH_STATE))
+ {
+ int bstate = -1;
+ switch (config_table[level].Function)
+ {
+ case DefalteFlavor.STORED:
+ bstate = deflate_stored(flush);
+ break;
+ case DefalteFlavor.FAST:
+ bstate = deflate_fast(flush);
+ break;
+ case DefalteFlavor.SLOW:
+ bstate = deflate_slow(flush);
+ break;
+ default:
+ break;
+ }
+
+ if (bstate == FinishStarted || bstate == FinishDone)
+ {
+ _status = FINISH_STATE;
+ }
+ if (bstate == NeedMore || bstate == FinishStarted)
+ {
+ if (base.avail_out == 0)
+ {
+ last_flush = (FlushType)(-1); // avoid BUF_ERROR next call, see above
+ }
+ return ZLibStatus.Z_OK;
+ // If flush != Z_NO_FLUSH && avail_out == 0, the next call
+ // of deflate should use the same flush parameter to make sure
+ // that the flush is complete. So we don't have to output an
+ // empty block here, this will be done at next call. This also
+ // ensures that for a very small output buffer, we emit at most
+ // one empty block.
+ }
+
+ if (bstate == BlockDone)
+ {
+ if (flush == FlushType.Z_PARTIAL_FLUSH)
+ {
+ _tr_align();
+ }
+ else
+ { // FULL_FLUSH or SYNC_FLUSH
+ _tr_stored_block(0, 0, false);
+ // For a full flush, this empty block will be recognized
+ // as a special marker by inflate_sync().
+ if (flush == FlushType.Z_FULL_FLUSH)
+ {
+ //state.head[s.hash_size-1]=0;
+ for (int i = 0; i < this._hashSize/*-1*/; i++) // forget history
+ this._head[i] = 0;
+ }
+ }
+ this.flush_pending();
+ if (base.avail_out == 0)
+ {
+ last_flush = (FlushType)(-1); // avoid BUF_ERROR at next call, see above
+ return ZLibStatus.Z_OK;
+ }
+ }
+ }
+
+ if (flush != FlushType.Z_FINISH) return ZLibStatus.Z_OK;
+ if (noheader != 0) return ZLibStatus.Z_STREAM_END;
+
+ // Write the zlib trailer (adler32)
+ putShortMSB((int)(base.adler >> 16));
+ putShortMSB((int)(base.adler & 0xffff));
+ this.flush_pending();
+
+ // If avail_out is zero, the application will call deflate again
+ // to flush the rest.
+ noheader = -1; // write the trailer only once!
+ return pending != 0 ? ZLibStatus.Z_OK : ZLibStatus.Z_STREAM_END;
+ }
+
+
+ private static readonly StaticTree static_l_desc = new StaticTree(static_ltree, Deflate.extra_lbits, LITERALS + 1, L_CODES, MAX_BITS);
+
+ private static readonly StaticTree static_d_desc = new StaticTree(static_dtree, Deflate.extra_dbits, 0, D_CODES, MAX_BITS);
+
+ private static readonly StaticTree static_bl_desc = new StaticTree(null, Deflate.extra_blbits, 0, BL_CODES, MAX_BL_BITS);
+
+ private class Config
+ {
+ ///
+ /// Reduce lazy search above this match length
+ ///
+ internal int GoodLength { get; private set; }
+ ///
+ /// Gets or sets whether not to perform lazy search above this match length
+ ///
+ ///
+ /// The max lazy.
+ ///
+ internal int MaxLazy { get; private set; }
+ ///
+ /// Gets or sets whether to quit search above this match length
+ ///
+ ///
+ /// The length of the nice.
+ ///
+ internal int NiceLength { get; private set; }
+ internal int MaxChain { get; private set; }
+ internal DefalteFlavor Function { get; private set; }
+ internal Config(int goodLength, int maxLazy, int niceLength, int maxChain, DefalteFlavor function)
+ {
+ this.GoodLength = goodLength;
+ this.MaxLazy = maxLazy;
+ this.NiceLength = niceLength;
+ this.MaxChain = maxChain;
+ this.Function = function;
+ }
+ }
+
+
+ // Flush as much pending output as possible. All deflate() output goes
+ // through this function so some applications may wish to modify it
+ // to avoid allocating a large strm->next_out buffer and copying into it.
+ // (See also read_buf()).
+ internal void flush_pending()
+ {
+ int len = this.pending;
+
+ if (len > avail_out) len = avail_out;
+ if (len == 0) return;
+
+ if (this.pending_buf.Length <= this.pending_out ||
+ next_out.Length <= next_out_index ||
+ this.pending_buf.Length < (this.pending_out + len) ||
+ next_out.Length < (next_out_index + len))
+ {
+ // System.out.println(this.pending_buf.length+", "+this.pending_out+
+ // ", "+next_out.length+", "+next_out_index+", "+len);
+ // System.out.println("avail_out="+avail_out);
+ }
+
+ System.Array.Copy(this.pending_buf, this.pending_out,
+ next_out, next_out_index, len);
+
+ next_out_index += len;
+ this.pending_out += len;
+ total_out += len;
+ avail_out -= len;
+ this.pending -= len;
+ if (this.pending == 0)
+ {
+ this.pending_out = 0;
+ }
+ }
+
+ // Read a new buffer from the current input stream, update the adler32
+ // and total number of bytes read. All deflate() input goes through
+ // this function so some applications may wish to modify it to avoid
+ // allocating a large strm->next_in buffer and copying from it.
+ // (See also flush_pending()).
+ internal int read_buf(byte[] buf, int start, int size)
+ {
+ int len = avail_in;
+
+ if (len > size) len = size;
+ if (len == 0) return 0;
+
+ avail_in -= len;
+
+ if (this.noheader == 0)
+ {
+ adler = Adler32.adler32(adler, next_in, next_in_index, len);
+ }
+ System.Array.Copy(next_in, next_in_index, buf, start, len);
+ next_in_index += len;
+ total_in += len;
+ return len;
+ }
+
+ public ZLibStatus deflate(byte[] inputBufer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType)
+ {
+ this.next_in = inputBufer;
+ this.next_in_index = inputOffset;
+ this.avail_in = inputCount;
+ this.next_out = outputBuffer;
+ this.next_out_index = outputOffset;
+ this.avail_out = outputCount;
+ return this.deflate(flushType);
+ }
+
+ // TODO: Delete this
+ public ZLibStatus inflateEnd()
+ {
+ throw new NotImplementedException();
+ }
+
+ public ZLibStatus inflate(FlushType flushType)
+ {
+ throw new NotImplementedException();
+ }
+
+ public ZLibStatus inflate(byte[] bufer, int offset, int count, byte[] p1, int p2, int p3, FlushType flushType)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Version.8/Inflate.cs b/Renci.SshNet/Compression/Version.8/Inflate.cs
new file mode 100644
index 0000000..cb31730
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.8/Inflate.cs
@@ -0,0 +1,516 @@
+using System;
+/*
+ * $Id: Inflate.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public enum InflateMode : int
+ {
+ ///
+ ///waiting for method byte
+ ///
+ METHOD = 0,
+ ///
+ /// waiting for flag byte
+ ///
+ FLAG = 1,
+ ///
+ /// four dictionary check bytes to go
+ ///
+ DICT4 = 2,
+ ///
+ /// three dictionary check bytes to go
+ ///
+ DICT3 = 3,
+ ///
+ /// two dictionary check bytes to go
+ ///
+ DICT2 = 4,
+ ///
+ /// one dictionary check byte to go
+ ///
+ DICT1 = 5,
+ ///
+ /// waiting for inflateSetDictionary
+ ///
+ DICT0 = 6,
+ ///
+ /// decompressing blocks
+ ///
+ BLOCKS = 7,
+ ///
+ /// four check bytes to go
+ ///
+ CHECK4 = 8,
+ ///
+ /// three check bytes to go
+ ///
+ CHECK3 = 9,
+ ///
+ /// two check bytes to go
+ ///
+ CHECK2 = 10,
+ ///
+ /// one check byte to go
+ ///
+ CHECK1 = 11,
+ ///
+ /// finished check, done
+ ///
+ DONE = 12,
+ ///
+ /// got an error--stay here
+ ///
+ BAD = 13
+ }
+
+ internal sealed class Inflate : ZStream, ICompressor
+ {
+ // preset dictionary flag in zlib header
+ private const int PRESET_DICT = 0x20;
+
+ private const int Z_DEFLATED = 8;
+
+ private static readonly byte[] mark = { (byte)0, (byte)0, (byte)0xff, (byte)0xff };
+
+ ///
+ /// The current inflate mode
+ ///
+ private InflateMode _mode;
+
+ ///
+ /// if FLAGS, method byte
+ ///
+ private int method;
+
+ ///
+ /// Computed check value
+ ///
+ private long[] _was = new long[1];
+
+ ///
+ /// The stream check value
+ ///
+ private long _need;
+
+ ///
+ /// if BAD, inflateSync's marker bytes count
+ ///
+ private int _marker;
+
+ // mode independent information
+ ///
+ /// Flag for no wrapper
+ ///
+ private int _nowrap;
+
+ ///
+ /// log2(window size) (8..15, defaults to 15)
+ ///
+ private int _wbits;
+
+ ///
+ /// Current inflate_blocks state
+ ///
+ private InflateBlocks _blocks;
+
+ public Inflate()
+ {
+ this.inflateInit();
+ }
+
+ public Inflate(bool nowrap)
+ {
+ this.inflateInit(nowrap);
+ }
+
+ private ZLibStatus InflateReset()
+ {
+ base.total_in = base.total_out = 0;
+ base.msg = null;
+ this._mode = this._nowrap != 0 ? InflateMode.BLOCKS : InflateMode.METHOD;
+ this._blocks.reset(this, null);
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus InflateEnd()
+ {
+ if (_blocks != null)
+ _blocks.free(this);
+ _blocks = null;
+ // ZFREE(z, z->state);
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus InflateInit(int w)
+ {
+ base.msg = null;
+ _blocks = null;
+
+ // handle undocumented nowrap option (no zlib header or check)
+ _nowrap = 0;
+ if (w < 0)
+ {
+ w = -w;
+ _nowrap = 1;
+ }
+
+ // set window size
+ if (w < 8 || w > 15)
+ {
+ InflateEnd();
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+ _wbits = w;
+
+ this._blocks = new InflateBlocks(this, this._nowrap != 0 ? null : this, 1 << w);
+
+ // reset state
+ InflateReset();
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus inflate(FlushType ff)
+ {
+ ZLibStatus r;
+ int b;
+
+ if (base.next_in == null)
+ return ZLibStatus.Z_STREAM_ERROR;
+ var f = ff == FlushType.Z_FINISH ? ZLibStatus.Z_BUF_ERROR : ZLibStatus.Z_OK;
+ r = ZLibStatus.Z_BUF_ERROR;
+ while (true)
+ {
+ //System.out.println("mode: "+this.mode);
+ switch (this._mode)
+ {
+ case InflateMode.METHOD:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ if (((this.method = base.next_in[base.next_in_index++]) & 0xf) != Z_DEFLATED)
+ {
+ this._mode = InflateMode.BAD;
+ base.msg = "unknown compression method";
+ this._marker = 5; // can't try inflateSync
+ break;
+ }
+ if ((this.method >> 4) + 8 > this._wbits)
+ {
+ this._mode = InflateMode.BAD;
+ base.msg = "invalid window size";
+ this._marker = 5; // can't try inflateSync
+ break;
+ }
+ this._mode = InflateMode.FLAG;
+ goto case InflateMode.FLAG;
+ case InflateMode.FLAG:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ b = (base.next_in[base.next_in_index++]) & 0xff;
+
+ if ((((this.method << 8) + b) % 31) != 0)
+ {
+ this._mode = InflateMode.BAD;
+ base.msg = "incorrect header check";
+ this._marker = 5; // can't try inflateSync
+ break;
+ }
+
+ if ((b & PRESET_DICT) == 0)
+ {
+ this._mode = InflateMode.BLOCKS;
+ break;
+ }
+ this._mode = InflateMode.DICT4;
+ goto case InflateMode.DICT4;
+ case InflateMode.DICT4:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need = ((base.next_in[base.next_in_index++] & 0xff) << 24) & 0xff000000L;
+ this._mode = InflateMode.DICT3;
+ goto case InflateMode.DICT3;
+ case InflateMode.DICT3:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += ((base.next_in[base.next_in_index++] & 0xff) << 16) & 0xff0000L;
+ this._mode = InflateMode.DICT2;
+ goto case InflateMode.DICT2;
+ case InflateMode.DICT2:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += ((base.next_in[base.next_in_index++] & 0xff) << 8) & 0xff00L;
+ this._mode = InflateMode.DICT1;
+ goto case InflateMode.DICT1;
+ case InflateMode.DICT1:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += (base.next_in[base.next_in_index++] & 0xffL);
+ base.adler = this._need;
+ this._mode = InflateMode.DICT0;
+ return ZLibStatus.Z_NEED_DICT;
+ case InflateMode.DICT0:
+ this._mode = InflateMode.BAD;
+ base.msg = "need dictionary";
+ this._marker = 0; // can try inflateSync
+ return ZLibStatus.Z_STREAM_ERROR;
+ case InflateMode.BLOCKS:
+
+ r = this._blocks.proc(this, r);
+ if (r == ZLibStatus.Z_DATA_ERROR)
+ {
+ this._mode = InflateMode.BAD;
+ this._marker = 0; // can try inflateSync
+ break;
+ }
+ if (r == ZLibStatus.Z_OK)
+ {
+ r = f;
+ }
+ if (r != ZLibStatus.Z_STREAM_END)
+ {
+ return r;
+ }
+ r = f;
+ this._blocks.reset(this, this._was);
+ if (this._nowrap != 0)
+ {
+ this._mode = InflateMode.DONE;
+ break;
+ }
+ this._mode = InflateMode.CHECK4;
+ goto case InflateMode.CHECK4;
+ case InflateMode.CHECK4:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need = ((base.next_in[base.next_in_index++] & 0xff) << 24) & 0xff000000L;
+ this._mode = InflateMode.CHECK3;
+ goto case InflateMode.CHECK3;
+ case InflateMode.CHECK3:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += ((base.next_in[base.next_in_index++] & 0xff) << 16) & 0xff0000L;
+ this._mode = InflateMode.CHECK2;
+ goto case InflateMode.CHECK2;
+ case InflateMode.CHECK2:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += ((base.next_in[base.next_in_index++] & 0xff) << 8) & 0xff00L;
+ this._mode = InflateMode.CHECK1;
+ goto case InflateMode.CHECK1;
+ case InflateMode.CHECK1:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += (base.next_in[base.next_in_index++] & 0xffL);
+
+ if (((int)(this._was[0])) != ((int)(this._need)))
+ {
+ this._mode = InflateMode.BAD;
+ base.msg = "incorrect data check";
+ this._marker = 5; // can't try inflateSync
+ break;
+ }
+
+ this._mode = InflateMode.DONE;
+ goto case InflateMode.DONE;
+ case InflateMode.DONE:
+ return ZLibStatus.Z_STREAM_END;
+ case InflateMode.BAD:
+ return ZLibStatus.Z_DATA_ERROR;
+ default:
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+ }
+ }
+
+ public ZLibStatus InflateSetDictionary(byte[] dictionary, int dictLength)
+ {
+ int index = 0;
+ int length = dictLength;
+ if (this._mode != InflateMode.DICT0)
+ return ZLibStatus.Z_STREAM_ERROR;
+
+ if (Adler32.adler32(1L, dictionary, 0, dictLength) != base.adler)
+ {
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+
+ base.adler = Adler32.adler32(0, null, 0, 0);
+
+ if (length >= (1 << this._wbits))
+ {
+ length = (1 << this._wbits) - 1;
+ index = dictLength - length;
+ }
+ this._blocks.set_dictionary(dictionary, index, length);
+ this._mode = InflateMode.BLOCKS;
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus InflateSync()
+ {
+ int n; // number of bytes to look at
+ int p; // pointer to bytes
+ int m; // number of marker bytes found in a row
+ long r, w; // temporaries to save total_in and total_out
+
+ // set up
+ if (this._mode != InflateMode.BAD)
+ {
+ this._mode = InflateMode.BAD;
+ this._marker = 0;
+ }
+ if ((n = base.avail_in) == 0)
+ return ZLibStatus.Z_BUF_ERROR;
+ p = base.next_in_index;
+ m = this._marker;
+
+ // search
+ while (n != 0 && m < 4)
+ {
+ if (base.next_in[p] == mark[m])
+ {
+ m++;
+ }
+ else if (base.next_in[p] != 0)
+ {
+ m = 0;
+ }
+ else
+ {
+ m = 4 - m;
+ }
+ p++; n--;
+ }
+
+ // restore
+ base.total_in += p - base.next_in_index;
+ base.next_in_index = p;
+ base.avail_in = n;
+ this._marker = m;
+
+ // return no joy or set up to restart on a new block
+ if (m != 4)
+ {
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ r = base.total_in; w = base.total_out;
+ InflateReset();
+ base.total_in = r; base.total_out = w;
+ this._mode = InflateMode.BLOCKS;
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus inflateInit()
+ {
+ return inflateInit(DEF_WBITS);
+ }
+ public ZLibStatus inflateInit(bool nowrap)
+ {
+ return inflateInit(DEF_WBITS, nowrap);
+ }
+ public ZLibStatus inflateInit(int w)
+ {
+ return inflateInit(w, false);
+ }
+
+ public ZLibStatus inflateInit(int w, bool nowrap)
+ {
+ return this.InflateInit(nowrap ? -w : w);
+ }
+
+ public ZLibStatus inflateEnd()
+ {
+ var ret = this.InflateEnd();
+ return ret;
+ }
+ public ZLibStatus inflateSync()
+ {
+ return this.InflateSync();
+ }
+
+ public ZLibStatus inflateSetDictionary(byte[] dictionary, int dictLength)
+ {
+ return this.InflateSetDictionary(dictionary, dictLength);
+ }
+
+ public ZLibStatus inflate(byte[] inputBufer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType)
+ {
+ this.next_in = inputBufer;
+ this.next_in_index = inputOffset;
+ this.avail_in = inputCount;
+ this.next_out = outputBuffer;
+ this.next_out_index = outputOffset;
+ this.avail_out = outputCount;
+ return this.inflate(flushType);
+ }
+
+ // TODO: Dlete this
+ public ZLibStatus deflate(byte[] bufer, int offset, int count, byte[] p1, int p2, int p3, FlushType flushType)
+ {
+ throw new NotImplementedException();
+ }
+
+ public ZLibStatus deflateEnd()
+ {
+ throw new NotImplementedException();
+ }
+
+ public ZLibStatus deflate(FlushType flushType)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Version.8/InflateBlocks.cs b/Renci.SshNet/Compression/Version.8/InflateBlocks.cs
new file mode 100644
index 0000000..273389f
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.8/InflateBlocks.cs
@@ -0,0 +1,721 @@
+using System;
+/*
+ * $Id: InfBlocks.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public enum InflateBlockMode
+ {
+ ///
+ /// get type bits (3, including end bit)
+ ///
+ TYPE = 0,
+ ///
+ /// get lengths for stored
+ ///
+ LENS = 1,
+ ///
+ /// cessing stored block
+ ///
+ STORED = 2,
+ ///
+ /// get table lengths
+ ///
+ TABLE = 3,
+ ///
+ /// get bit lengths tree for a dynamic block
+ ///
+ BTREE = 4,
+ ///
+ /// get length, distance trees for a dynamic block
+ ///
+ DTREE = 5,
+ ///
+ /// processing fixed or dynamic block
+ ///
+ CODES = 6,
+ ///
+ /// output remaining window bytes
+ ///
+ DRY = 7,
+ ///
+ /// finished last block, done
+ ///
+ DONE = 8,
+ ///
+ /// ot a data error--stuck here
+ ///
+ BAD = 9
+ }
+
+ internal sealed class InflateBlocks : InflateCodes
+ {
+ private const int MANY = 1440;
+
+ // And'ing with mask[n] masks the lower n bits
+ private static readonly int[] inflate_mask = {
+ 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
+ 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
+ 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
+ 0x00007fff, 0x0000ffff
+ };
+
+ // Table for deflate from PKZIP's appnote.txt.
+ static readonly int[] border = { // Order of the bit length code lengths
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
+ };
+
+ internal InflateBlockMode mode; // current inflate_block mode
+
+ internal int left; // if STORED, bytes left to copy
+
+ internal int table; // table lengths (14 bits)
+ internal int index; // index into blens (or border)
+ internal int[] blens; // bit lengths of codes
+ internal int[] bb = new int[1]; // bit length tree depth
+ internal int[] tb = new int[1]; // bit length decoding tree
+
+ //internal InfCodes codes = new InfCodes(); // if CODES, current state
+
+ int last; // true if this block is the last block
+
+ // mode independent information
+ internal int bitk; // bits in bit buffer
+ internal int bitb; // bit buffer
+ internal int[] hufts; // single malloc for tree space
+ internal byte[] window; // sliding window
+ internal int end; // one byte after sliding window
+ internal int read; // window read pointer
+ internal int write; // window write pointer
+ internal Object checkfn; // check function
+ internal long check; // check on output
+
+ internal InflateTree inftree = new InflateTree();
+
+ internal InflateBlocks(ZStream z, Object checkfn, int w)
+ {
+ hufts = new int[MANY * 3];
+ window = new byte[w];
+ end = w;
+ this.checkfn = checkfn;
+ mode = InflateBlockMode.TYPE;
+ reset(z, null);
+ }
+
+ internal void reset(ZStream z, long[] c)
+ {
+ if (c != null) c[0] = check;
+ if (mode == InflateBlockMode.BTREE || mode == InflateBlockMode.DTREE)
+ {
+ }
+ if (mode == InflateBlockMode.CODES)
+ {
+ codesfree(z);
+ }
+ mode = InflateBlockMode.TYPE;
+ bitk = 0;
+ bitb = 0;
+ read = write = 0;
+
+ if (checkfn != null)
+ z.adler = check = Adler32.adler32(0L, null, 0, 0);
+ }
+
+ internal ZLibStatus proc(ZStream z, ZLibStatus r)
+ {
+ int t; // temporary storage
+ ZLibStatus tt;
+ int b; // bit buffer
+ int k; // bits in bit buffer
+ int p; // input data pointer
+ int n; // bytes available there
+ int q; // output window write pointer
+ int m;
+ { // bytes to end of window or read pointer
+
+ // copy input/output information to locals (UPDATE macro restores)
+ p = z.next_in_index; n = z.avail_in; b = bitb; k = bitk;
+ }
+ {
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+ }
+
+ // process input based on current state
+ while (true)
+ {
+ switch (mode)
+ {
+ case InflateBlockMode.TYPE:
+
+ while (k < (3))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+ t = (int)(b & 7);
+ last = t & 1;
+
+ switch (t >> 1)
+ {
+ case 0:
+ { // stored
+ b >>= (3); k -= (3);
+ }
+ t = k & 7;
+ { // go to byte boundary
+
+ b >>= (t); k -= (t);
+ }
+ mode = InflateBlockMode.LENS; // get length of stored block
+ break;
+ case 1:
+ { // fixed
+ int[] bl = new int[1];
+ int[] bd = new int[1];
+ int[][] tl = new int[1][];
+ int[][] td = new int[1][];
+
+ InflateTree.InflateTreesFixed(bl, bd, tl, td, z);
+ codesinit(bl[0], bd[0], tl[0], 0, td[0], 0, z);
+ }
+ {
+
+ b >>= (3); k -= (3);
+ }
+
+ mode = InflateBlockMode.CODES;
+ break;
+ case 2:
+ { // dynamic
+
+ b >>= (3); k -= (3);
+ }
+
+ mode = InflateBlockMode.TABLE;
+ break;
+ case 3:
+ { // illegal
+
+ b >>= (3); k -= (3);
+ }
+ mode = InflateBlockMode.BAD;
+ z.msg = "invalid block type";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ break;
+ case InflateBlockMode.LENS:
+
+ while (k < (32))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ if ((((~b) >> 16) & 0xffff) != (b & 0xffff))
+ {
+ mode = InflateBlockMode.BAD;
+ z.msg = "invalid stored block lengths";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ left = (b & 0xffff);
+ b = k = 0; // dump bits
+ mode = left != 0 ? InflateBlockMode.STORED : (last != 0 ? InflateBlockMode.DRY : InflateBlockMode.TYPE);
+ break;
+ case InflateBlockMode.STORED:
+ if (n == 0)
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+
+ if (m == 0)
+ {
+ if (q == end && read != 0)
+ {
+ q = 0; m = (int)(q < read ? read - q - 1 : end - q);
+ }
+ if (m == 0)
+ {
+ write = q;
+ r = inflate_flush(z, r);
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+ if (q == end && read != 0)
+ {
+ q = 0; m = (int)(q < read ? read - q - 1 : end - q);
+ }
+ if (m == 0)
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ }
+ }
+ r = ZLibStatus.Z_OK;
+
+ t = left;
+ if (t > n) t = n;
+ if (t > m) t = m;
+ System.Array.Copy(z.next_in, p, window, q, t);
+ p += t; n -= t;
+ q += t; m -= t;
+ if ((left -= t) != 0)
+ break;
+ mode = last != 0 ? InflateBlockMode.DRY : InflateBlockMode.TYPE;
+ break;
+ case InflateBlockMode.TABLE:
+
+ while (k < (14))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ table = t = (b & 0x3fff);
+ if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
+ {
+ mode = InflateBlockMode.BAD;
+ z.msg = "too many length or distance symbols";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
+ if (blens == null || blens.Length < t)
+ {
+ blens = new int[t];
+ }
+ else
+ {
+ for (int i = 0; i < t; i++) { blens[i] = 0; }
+ }
+ {
+
+ b >>= (14); k -= (14);
+ }
+
+ index = 0;
+ mode = InflateBlockMode.BTREE;
+ goto case InflateBlockMode.BTREE;
+ case InflateBlockMode.BTREE:
+ while (index < 4 + (table >> 10))
+ {
+ while (k < (3))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ blens[border[index++]] = b & 7;
+ {
+
+ b >>= (3); k -= (3);
+ }
+ }
+
+ while (index < 19)
+ {
+ blens[border[index++]] = 0;
+ }
+
+ bb[0] = 7;
+ tt = inftree.InflateTreesBits(blens, bb, tb, hufts, z);
+ if (tt != ZLibStatus.Z_OK)
+ {
+ r = tt;
+ if (r == ZLibStatus.Z_DATA_ERROR)
+ {
+ blens = null;
+ mode = InflateBlockMode.BAD;
+ }
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+
+ index = 0;
+ mode = InflateBlockMode.DTREE;
+ goto case InflateBlockMode.DTREE;
+ case InflateBlockMode.DTREE:
+ while (true)
+ {
+ t = table;
+ if (!(index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)))
+ {
+ break;
+ }
+
+ int i, j, c;
+
+ t = bb[0];
+
+ while (k < (t))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ if (tb[0] == -1)
+ {
+ //System.err.println("null...");
+ }
+
+ t = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 1];
+ c = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 2];
+
+ if (c < 16)
+ {
+ b >>= (t); k -= (t);
+ blens[index++] = c;
+ }
+ else
+ { // c == 16..18
+ i = c == 18 ? 7 : c - 14;
+ j = c == 18 ? 11 : 3;
+
+ while (k < (t + i))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ b >>= (t); k -= (t);
+
+ j += (b & inflate_mask[i]);
+
+ b >>= (i); k -= (i);
+
+ i = index;
+ t = table;
+ if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
+ (c == 16 && i < 1))
+ {
+ blens = null;
+ mode = InflateBlockMode.BAD;
+ z.msg = "invalid bit length repeat";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+
+ c = c == 16 ? blens[i - 1] : 0;
+ do
+ {
+ blens[i++] = c;
+ }
+ while (--j != 0);
+ index = i;
+ }
+ }
+
+ tb[0] = -1;
+ {
+ int[] bl = new int[1];
+ int[] bd = new int[1];
+ int[] tl = new int[1];
+ int[] td = new int[1];
+ bl[0] = 9; // must be <= 9 for lookahead assumptions
+ bd[0] = 6; // must be <= 9 for lookahead assumptions
+
+ t = table;
+ tt = inftree.InflateTreesDynamic(257 + (t & 0x1f),
+ 1 + ((t >> 5) & 0x1f),
+ blens, bl, bd, tl, td, hufts, z);
+
+ if (tt != ZLibStatus.Z_OK)
+ {
+ if (tt == ZLibStatus.Z_DATA_ERROR)
+ {
+ blens = null;
+ mode = InflateBlockMode.BAD;
+ }
+ r = tt;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ codesinit(bl[0], bd[0], hufts, tl[0], hufts, td[0], z);
+ }
+ mode = InflateBlockMode.CODES;
+ goto case InflateBlockMode.CODES;
+ case InflateBlockMode.CODES:
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+
+ if ((r = codesproc(this, z, r)) != ZLibStatus.Z_STREAM_END)
+ {
+ return inflate_flush(z, r);
+ }
+ r = ZLibStatus.Z_OK;
+ codesfree(z);
+
+ p = z.next_in_index; n = z.avail_in; b = bitb; k = bitk;
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+
+ if (last == 0)
+ {
+ mode = InflateBlockMode.TYPE;
+ break;
+ }
+ mode = InflateBlockMode.DRY;
+ goto case InflateBlockMode.DRY;
+ case InflateBlockMode.DRY:
+ write = q;
+ r = inflate_flush(z, r);
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+ if (read != write)
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ mode = InflateBlockMode.DONE;
+ goto case InflateBlockMode.DONE;
+ case InflateBlockMode.DONE:
+ r = ZLibStatus.Z_STREAM_END;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ case InflateBlockMode.BAD:
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+
+ default:
+ r = ZLibStatus.Z_STREAM_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ }
+ }
+
+ internal void free(ZStream z)
+ {
+ reset(z, null);
+ window = null;
+ hufts = null;
+ //ZFREE(z, s);
+ }
+
+ internal void set_dictionary(byte[] d, int start, int n)
+ {
+ System.Array.Copy(d, start, window, 0, n);
+ read = write = n;
+ }
+
+ // Returns true if inflate is currently at the end of a block generated
+ // by Z_SYNC_FLUSH or FlushType.Z_FULL_FLUSH.
+ internal ZLibStatus sync_point()
+ {
+ return mode == InflateBlockMode.LENS ? ZLibStatus.Z_STREAM_END : ZLibStatus.Z_OK;
+ }
+
+ // copy as much as possible from the sliding window to the output area
+ internal ZLibStatus inflate_flush(ZStream z, ZLibStatus r)
+ {
+ int n;
+ int p;
+ int q;
+
+ // local copies of source and destination pointers
+ p = z.next_out_index;
+ q = read;
+
+ // compute number of bytes to copy as far as end of window
+ n = (int)((q <= write ? write : end) - q);
+ if (n > z.avail_out) n = z.avail_out;
+ if (n != 0 && r == ZLibStatus.Z_BUF_ERROR) r = ZLibStatus.Z_OK;
+
+ // update counters
+ z.avail_out -= n;
+ z.total_out += n;
+
+ // update check information
+ if (checkfn != null)
+ z.adler = check = Adler32.adler32(check, window, q, n);
+
+ // copy as far as end of window
+ System.Array.Copy(window, q, z.next_out, p, n);
+ p += n;
+ q += n;
+
+ // see if more to copy at beginning of window
+ if (q == end)
+ {
+ // wrap pointers
+ q = 0;
+ if (write == end)
+ write = 0;
+
+ // compute bytes to copy
+ n = write - q;
+ if (n > z.avail_out) n = z.avail_out;
+ if (n != 0 && r == ZLibStatus.Z_BUF_ERROR) r = ZLibStatus.Z_OK;
+
+ // update counters
+ z.avail_out -= n;
+ z.total_out += n;
+
+ // update check information
+ if (checkfn != null)
+ z.adler = check = Adler32.adler32(check, window, q, n);
+
+ // copy
+ System.Array.Copy(window, q, z.next_out, p, n);
+ p += n;
+ q += n;
+ }
+
+ // update pointers
+ z.next_out_index = p;
+ read = q;
+
+ // done
+ return r;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Version.8/InflateCodes.cs b/Renci.SshNet/Compression/Version.8/InflateCodes.cs
new file mode 100644
index 0000000..3214e56
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.8/InflateCodes.cs
@@ -0,0 +1,690 @@
+using System;
+/*
+ * $Id: InfCodes.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public enum InflateCodeMode
+ {
+ ///
+ /// x: set up for InflateCodeMode.LEN
+ ///
+ START = 0,
+ ///
+ /// i: get length/literal/eob next
+ ///
+ LEN = 1,
+ ///
+ /// i: getting length extra (have base)
+ ///
+ LENEXT = 2,
+ ///
+ /// i: get distance next
+ ///
+ DIST = 3,
+ ///
+ /// : getting distance extra
+ ///
+ DISTEXT = 4,
+ ///
+ /// o: copying bytes in window, waiting for space
+ ///
+ COPY = 5,
+ ///
+ /// o: got literal, waiting for output space
+ ///
+ LIT = 6,
+ ///
+ /// o: got eob, possibly still output waiting
+ ///
+ WASH = 7,
+ ///
+ /// x: got eob and all data flushed
+ ///
+ END = 8,
+ ///
+ /// x: got error
+ ///
+ BADCODE = 9
+ }
+
+ internal abstract class InflateCodes// : ZStream
+ {
+ private static readonly int[] inflate_mask = {
+ 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
+ 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
+ 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
+ 0x00007fff, 0x0000ffff
+ };
+
+ InflateCodeMode mode; // current inflate_codes mode
+
+ // mode dependent information
+ int len;
+
+ int[] tree; // pointer into tree
+ int tree_index = 0;
+ int need; // bits needed
+
+ int lit;
+
+ // if EXT or COPY, where and how much
+ int get; // bits to get for extra
+ int dist; // distance back to copy from
+
+ byte lbits; // ltree bits decoded per branch
+ byte dbits; // dtree bits decoder per branch
+ int[] ltree; // literal/length/eob tree
+ int ltree_index; // literal/length/eob tree
+ int[] dtree; // distance tree
+ int dtree_index; // distance tree
+
+ internal InflateCodes()
+ {
+ }
+ internal void codesinit(int bl, int bd,
+ int[] tl, int tl_index,
+ int[] td, int td_index, ZStream z)
+ {
+ mode = InflateCodeMode.START;
+ lbits = (byte)bl;
+ dbits = (byte)bd;
+ ltree = tl;
+ ltree_index = tl_index;
+ dtree = td;
+ dtree_index = td_index;
+ tree = null;
+ }
+
+ internal ZLibStatus codesproc(InflateBlocks s, ZStream z, ZLibStatus r)
+ {
+ int j; // temporary storage
+ int tindex; // temporary pointer
+ int e; // extra bits or operation
+ int b = 0; // bit buffer
+ int k = 0; // bits in bit buffer
+ int p = 0; // input data pointer
+ int n; // bytes available there
+ int q; // output window write pointer
+ int m; // bytes to end of window or read pointer
+ int f; // pointer to copy strings from
+
+ // copy input/output information to locals (UPDATE macro restores)
+ p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk;
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ // process input and output based on current state
+ while (true)
+ {
+ switch (mode)
+ {
+ // waiting for "i:"=input, "o:"=output, "x:"=nothing
+ case InflateCodeMode.START: // x: set up for LEN
+ if (m >= 258 && n >= 10)
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ r = inflate_fast(lbits, dbits,
+ ltree, ltree_index,
+ dtree, dtree_index,
+ s, z);
+
+ p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk;
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (r != ZLibStatus.Z_OK)
+ {
+ mode = r == ZLibStatus.Z_STREAM_END ? InflateCodeMode.WASH : InflateCodeMode.BADCODE;
+ break;
+ }
+ }
+ need = lbits;
+ tree = ltree;
+ tree_index = ltree_index;
+
+ mode = InflateCodeMode.LEN;
+ goto case InflateCodeMode.LEN;
+ case InflateCodeMode.LEN: // i: get length/literal/eob next
+ j = need;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ tindex = (tree_index + (b & inflate_mask[j])) * 3;
+
+ b >>= (tree[tindex + 1]);
+ k -= (tree[tindex + 1]);
+
+ e = tree[tindex];
+
+ if (e == 0)
+ { // literal
+ lit = tree[tindex + 2];
+ mode = InflateCodeMode.LIT;
+ break;
+ }
+ if ((e & 16) != 0)
+ { // length
+ get = e & 15;
+ len = tree[tindex + 2];
+ mode = InflateCodeMode.LENEXT;
+ break;
+ }
+ if ((e & 64) == 0)
+ { // next table
+ need = e;
+ tree_index = tindex / 3 + tree[tindex + 2];
+ break;
+ }
+ if ((e & 32) != 0)
+ { // end of block
+ mode = InflateCodeMode.WASH;
+ break;
+ }
+ mode = InflateCodeMode.BADCODE; // invalid code
+ z.msg = "invalid literal/length code";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ case InflateCodeMode.LENEXT: // i: getting length extra (have base)
+ j = get;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--; b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ len += (b & inflate_mask[j]);
+
+ b >>= j;
+ k -= j;
+
+ need = dbits;
+ tree = dtree;
+ tree_index = dtree_index;
+ mode = InflateCodeMode.DIST;
+ goto case InflateCodeMode.DIST;
+ case InflateCodeMode.DIST: // i: get distance next
+ j = need;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--; b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ tindex = (tree_index + (b & inflate_mask[j])) * 3;
+
+ b >>= tree[tindex + 1];
+ k -= tree[tindex + 1];
+
+ e = (tree[tindex]);
+ if ((e & 16) != 0)
+ { // distance
+ get = e & 15;
+ dist = tree[tindex + 2];
+ mode = InflateCodeMode.DISTEXT;
+ break;
+ }
+ if ((e & 64) == 0)
+ { // next table
+ need = e;
+ tree_index = tindex / 3 + tree[tindex + 2];
+ break;
+ }
+ mode = InflateCodeMode.BADCODE; // invalid code
+ z.msg = "invalid distance code";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ case InflateCodeMode.DISTEXT: // i: getting distance extra
+ j = get;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--; b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ dist += (b & inflate_mask[j]);
+
+ b >>= j;
+ k -= j;
+
+ mode = InflateCodeMode.COPY;
+ goto case InflateCodeMode.COPY;
+ case InflateCodeMode.COPY: // o: copying bytes in window, waiting for space
+ f = q - dist;
+ while (f < 0)
+ { // modulo window size-"while" instead
+ f += s.end; // of "if" handles invalid distances
+ }
+ while (len != 0)
+ {
+
+ if (m == 0)
+ {
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+ if (m == 0)
+ {
+ s.write = q; r = s.inflate_flush(z, r);
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+
+ if (m == 0)
+ {
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ }
+ }
+
+ s.window[q++] = s.window[f++]; m--;
+
+ if (f == s.end)
+ f = 0;
+ len--;
+ }
+ mode = InflateCodeMode.START;
+ break;
+ case InflateCodeMode.LIT: // o: got literal, waiting for output space
+ if (m == 0)
+ {
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+ if (m == 0)
+ {
+ s.write = q; r = s.inflate_flush(z, r);
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+ if (m == 0)
+ {
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ }
+ }
+ r = ZLibStatus.Z_OK;
+
+ s.window[q++] = (byte)lit; m--;
+
+ mode = InflateCodeMode.START;
+ break;
+ case InflateCodeMode.WASH: // o: got eob, possibly more output
+ if (k > 7)
+ { // return unused byte, if any
+ k -= 8;
+ n++;
+ p--; // can always return one
+ }
+
+ s.write = q; r = s.inflate_flush(z, r);
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (s.read != s.write)
+ {
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ mode = InflateCodeMode.END;
+ goto case InflateCodeMode.END;
+ case InflateCodeMode.END:
+ r = ZLibStatus.Z_STREAM_END;
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ case InflateCodeMode.BADCODE: // x: got error
+
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ default:
+ r = ZLibStatus.Z_STREAM_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ }
+ }
+
+ internal void codesfree(ZStream z)
+ {
+ // ZFREE(z, c);
+ }
+
+ // Called with number of bytes left to write in window at least 258
+ // (the maximum string length) and number of input bytes available
+ // at least ten. The ten bytes are six bytes for the longest length/
+ // distance pair plus four bytes for overloading the bit buffer.
+
+ internal ZLibStatus inflate_fast(int bl, int bd,
+ int[] tl, int tl_index,
+ int[] td, int td_index,
+ InflateBlocks s, ZStream z)
+ {
+ int t; // temporary pointer
+ int[] tp; // temporary pointer
+ int tp_index; // temporary pointer
+ int e; // extra bits or operation
+ int b; // bit buffer
+ int k; // bits in bit buffer
+ int p; // input data pointer
+ int n; // bytes available there
+ int q; // output window write pointer
+ int m; // bytes to end of window or read pointer
+ int ml; // mask for literal/length tree
+ int md; // mask for distance tree
+ int c; // bytes to copy
+ int d; // distance back to copy from
+ int r; // copy source pointer
+
+ int tp_index_t_3; // (tp_index+t)*3
+
+ // load input, output, bit values
+ p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk;
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ // initialize masks
+ ml = inflate_mask[bl];
+ md = inflate_mask[bd];
+
+ // do until not enough input or output space for fast loop
+ do
+ { // assume called with m >= 258 && n >= 10
+ // get literal/length code
+ while (k < (20))
+ { // max bits for literal/length code
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k; k += 8;
+ }
+
+ t = b & ml;
+ tp = tl;
+ tp_index = tl_index;
+ tp_index_t_3 = (tp_index + t) * 3;
+ if ((e = tp[tp_index_t_3]) == 0)
+ {
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ s.window[q++] = (byte)tp[tp_index_t_3 + 2];
+ m--;
+ continue;
+ }
+ do
+ {
+
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ if ((e & 16) != 0)
+ {
+ e &= 15;
+ c = tp[tp_index_t_3 + 2] + ((int)b & inflate_mask[e]);
+
+ b >>= e; k -= e;
+
+ // decode distance base of block to copy
+ while (k < (15))
+ { // max bits for distance code
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k; k += 8;
+ }
+
+ t = b & md;
+ tp = td;
+ tp_index = td_index;
+ tp_index_t_3 = (tp_index + t) * 3;
+ e = tp[tp_index_t_3];
+
+ do
+ {
+
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ if ((e & 16) != 0)
+ {
+ // get extra bits to add to distance base
+ e &= 15;
+ while (k < (e))
+ { // get extra bits (up to 13)
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k; k += 8;
+ }
+
+ d = tp[tp_index_t_3 + 2] + (b & inflate_mask[e]);
+
+ b >>= (e); k -= (e);
+
+ // do the copy
+ m -= c;
+ if (q >= d)
+ { // offset before dest
+ // just copy
+ r = q - d;
+ if (q - r > 0 && 2 > (q - r))
+ {
+ s.window[q++] = s.window[r++]; // minimum count is three,
+ s.window[q++] = s.window[r++]; // so unroll loop a little
+ c -= 2;
+ }
+ else
+ {
+ System.Array.Copy(s.window, r, s.window, q, 2);
+ q += 2; r += 2; c -= 2;
+ }
+ }
+ else
+ { // else offset after destination
+ r = q - d;
+ do
+ {
+ r += s.end; // force pointer in window
+ } while (r < 0); // covers invalid distances
+ e = s.end - r;
+ if (c > e)
+ { // if source crosses,
+ c -= e; // wrapped copy
+ if (q - r > 0 && e > (q - r))
+ {
+ do { s.window[q++] = s.window[r++]; }
+ while (--e != 0);
+ }
+ else
+ {
+ System.Array.Copy(s.window, r, s.window, q, e);
+ q += e; r += e; e = 0;
+ }
+ r = 0; // copy rest from start of window
+ }
+
+ }
+
+ // copy all or what's left
+ if (q - r > 0 && c > (q - r))
+ {
+ do { s.window[q++] = s.window[r++]; }
+ while (--c != 0);
+ }
+ else
+ {
+ System.Array.Copy(s.window, r, s.window, q, c);
+ q += c; r += c; c = 0;
+ }
+ break;
+ }
+ else if ((e & 64) == 0)
+ {
+ t += tp[tp_index_t_3 + 2];
+ t += (b & inflate_mask[e]);
+ tp_index_t_3 = (tp_index + t) * 3;
+ e = tp[tp_index_t_3];
+ }
+ else
+ {
+ z.msg = "invalid distance code";
+
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ }
+ while (true);
+ break;
+ }
+
+ if ((e & 64) == 0)
+ {
+ t += tp[tp_index_t_3 + 2];
+ t += (b & inflate_mask[e]);
+ tp_index_t_3 = (tp_index + t) * 3;
+ if ((e = tp[tp_index_t_3]) == 0)
+ {
+
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ s.window[q++] = (byte)tp[tp_index_t_3 + 2];
+ m--;
+ break;
+ }
+ }
+ else if ((e & 32) != 0)
+ {
+
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_STREAM_END;
+ }
+ else
+ {
+ z.msg = "invalid literal/length code";
+
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ }
+ while (true);
+ }
+ while (m >= 258 && n >= 10);
+
+ // not enough input or output--restore pointers and return
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_OK;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Version.8/InflateTree.cs b/Renci.SshNet/Compression/Version.8/InflateTree.cs
new file mode 100644
index 0000000..f9da579
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.8/InflateTree.cs
@@ -0,0 +1,555 @@
+using System;
+/*
+ * $Id: InfTree.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ internal sealed class InflateTree
+ {
+ private const int MANY = 1440;
+
+ private const int fixed_bl = 9;
+ private const int fixed_bd = 5;
+
+ static readonly int[] fixed_tl = {
+ 96,7,256, 0,8,80, 0,8,16, 84,8,115,
+ 82,7,31, 0,8,112, 0,8,48, 0,9,192,
+ 80,7,10, 0,8,96, 0,8,32, 0,9,160,
+ 0,8,0, 0,8,128, 0,8,64, 0,9,224,
+ 80,7,6, 0,8,88, 0,8,24, 0,9,144,
+ 83,7,59, 0,8,120, 0,8,56, 0,9,208,
+ 81,7,17, 0,8,104, 0,8,40, 0,9,176,
+ 0,8,8, 0,8,136, 0,8,72, 0,9,240,
+ 80,7,4, 0,8,84, 0,8,20, 85,8,227,
+ 83,7,43, 0,8,116, 0,8,52, 0,9,200,
+ 81,7,13, 0,8,100, 0,8,36, 0,9,168,
+ 0,8,4, 0,8,132, 0,8,68, 0,9,232,
+ 80,7,8, 0,8,92, 0,8,28, 0,9,152,
+ 84,7,83, 0,8,124, 0,8,60, 0,9,216,
+ 82,7,23, 0,8,108, 0,8,44, 0,9,184,
+ 0,8,12, 0,8,140, 0,8,76, 0,9,248,
+ 80,7,3, 0,8,82, 0,8,18, 85,8,163,
+ 83,7,35, 0,8,114, 0,8,50, 0,9,196,
+ 81,7,11, 0,8,98, 0,8,34, 0,9,164,
+ 0,8,2, 0,8,130, 0,8,66, 0,9,228,
+ 80,7,7, 0,8,90, 0,8,26, 0,9,148,
+ 84,7,67, 0,8,122, 0,8,58, 0,9,212,
+ 82,7,19, 0,8,106, 0,8,42, 0,9,180,
+ 0,8,10, 0,8,138, 0,8,74, 0,9,244,
+ 80,7,5, 0,8,86, 0,8,22, 192,8,0,
+ 83,7,51, 0,8,118, 0,8,54, 0,9,204,
+ 81,7,15, 0,8,102, 0,8,38, 0,9,172,
+ 0,8,6, 0,8,134, 0,8,70, 0,9,236,
+ 80,7,9, 0,8,94, 0,8,30, 0,9,156,
+ 84,7,99, 0,8,126, 0,8,62, 0,9,220,
+ 82,7,27, 0,8,110, 0,8,46, 0,9,188,
+ 0,8,14, 0,8,142, 0,8,78, 0,9,252,
+ 96,7,256, 0,8,81, 0,8,17, 85,8,131,
+ 82,7,31, 0,8,113, 0,8,49, 0,9,194,
+ 80,7,10, 0,8,97, 0,8,33, 0,9,162,
+ 0,8,1, 0,8,129, 0,8,65, 0,9,226,
+ 80,7,6, 0,8,89, 0,8,25, 0,9,146,
+ 83,7,59, 0,8,121, 0,8,57, 0,9,210,
+ 81,7,17, 0,8,105, 0,8,41, 0,9,178,
+ 0,8,9, 0,8,137, 0,8,73, 0,9,242,
+ 80,7,4, 0,8,85, 0,8,21, 80,8,258,
+ 83,7,43, 0,8,117, 0,8,53, 0,9,202,
+ 81,7,13, 0,8,101, 0,8,37, 0,9,170,
+ 0,8,5, 0,8,133, 0,8,69, 0,9,234,
+ 80,7,8, 0,8,93, 0,8,29, 0,9,154,
+ 84,7,83, 0,8,125, 0,8,61, 0,9,218,
+ 82,7,23, 0,8,109, 0,8,45, 0,9,186,
+ 0,8,13, 0,8,141, 0,8,77, 0,9,250,
+ 80,7,3, 0,8,83, 0,8,19, 85,8,195,
+ 83,7,35, 0,8,115, 0,8,51, 0,9,198,
+ 81,7,11, 0,8,99, 0,8,35, 0,9,166,
+ 0,8,3, 0,8,131, 0,8,67, 0,9,230,
+ 80,7,7, 0,8,91, 0,8,27, 0,9,150,
+ 84,7,67, 0,8,123, 0,8,59, 0,9,214,
+ 82,7,19, 0,8,107, 0,8,43, 0,9,182,
+ 0,8,11, 0,8,139, 0,8,75, 0,9,246,
+ 80,7,5, 0,8,87, 0,8,23, 192,8,0,
+ 83,7,51, 0,8,119, 0,8,55, 0,9,206,
+ 81,7,15, 0,8,103, 0,8,39, 0,9,174,
+ 0,8,7, 0,8,135, 0,8,71, 0,9,238,
+ 80,7,9, 0,8,95, 0,8,31, 0,9,158,
+ 84,7,99, 0,8,127, 0,8,63, 0,9,222,
+ 82,7,27, 0,8,111, 0,8,47, 0,9,190,
+ 0,8,15, 0,8,143, 0,8,79, 0,9,254,
+ 96,7,256, 0,8,80, 0,8,16, 84,8,115,
+ 82,7,31, 0,8,112, 0,8,48, 0,9,193,
+
+ 80,7,10, 0,8,96, 0,8,32, 0,9,161,
+ 0,8,0, 0,8,128, 0,8,64, 0,9,225,
+ 80,7,6, 0,8,88, 0,8,24, 0,9,145,
+ 83,7,59, 0,8,120, 0,8,56, 0,9,209,
+ 81,7,17, 0,8,104, 0,8,40, 0,9,177,
+ 0,8,8, 0,8,136, 0,8,72, 0,9,241,
+ 80,7,4, 0,8,84, 0,8,20, 85,8,227,
+ 83,7,43, 0,8,116, 0,8,52, 0,9,201,
+ 81,7,13, 0,8,100, 0,8,36, 0,9,169,
+ 0,8,4, 0,8,132, 0,8,68, 0,9,233,
+ 80,7,8, 0,8,92, 0,8,28, 0,9,153,
+ 84,7,83, 0,8,124, 0,8,60, 0,9,217,
+ 82,7,23, 0,8,108, 0,8,44, 0,9,185,
+ 0,8,12, 0,8,140, 0,8,76, 0,9,249,
+ 80,7,3, 0,8,82, 0,8,18, 85,8,163,
+ 83,7,35, 0,8,114, 0,8,50, 0,9,197,
+ 81,7,11, 0,8,98, 0,8,34, 0,9,165,
+ 0,8,2, 0,8,130, 0,8,66, 0,9,229,
+ 80,7,7, 0,8,90, 0,8,26, 0,9,149,
+ 84,7,67, 0,8,122, 0,8,58, 0,9,213,
+ 82,7,19, 0,8,106, 0,8,42, 0,9,181,
+ 0,8,10, 0,8,138, 0,8,74, 0,9,245,
+ 80,7,5, 0,8,86, 0,8,22, 192,8,0,
+ 83,7,51, 0,8,118, 0,8,54, 0,9,205,
+ 81,7,15, 0,8,102, 0,8,38, 0,9,173,
+ 0,8,6, 0,8,134, 0,8,70, 0,9,237,
+ 80,7,9, 0,8,94, 0,8,30, 0,9,157,
+ 84,7,99, 0,8,126, 0,8,62, 0,9,221,
+ 82,7,27, 0,8,110, 0,8,46, 0,9,189,
+ 0,8,14, 0,8,142, 0,8,78, 0,9,253,
+ 96,7,256, 0,8,81, 0,8,17, 85,8,131,
+ 82,7,31, 0,8,113, 0,8,49, 0,9,195,
+ 80,7,10, 0,8,97, 0,8,33, 0,9,163,
+ 0,8,1, 0,8,129, 0,8,65, 0,9,227,
+ 80,7,6, 0,8,89, 0,8,25, 0,9,147,
+ 83,7,59, 0,8,121, 0,8,57, 0,9,211,
+ 81,7,17, 0,8,105, 0,8,41, 0,9,179,
+ 0,8,9, 0,8,137, 0,8,73, 0,9,243,
+ 80,7,4, 0,8,85, 0,8,21, 80,8,258,
+ 83,7,43, 0,8,117, 0,8,53, 0,9,203,
+ 81,7,13, 0,8,101, 0,8,37, 0,9,171,
+ 0,8,5, 0,8,133, 0,8,69, 0,9,235,
+ 80,7,8, 0,8,93, 0,8,29, 0,9,155,
+ 84,7,83, 0,8,125, 0,8,61, 0,9,219,
+ 82,7,23, 0,8,109, 0,8,45, 0,9,187,
+ 0,8,13, 0,8,141, 0,8,77, 0,9,251,
+ 80,7,3, 0,8,83, 0,8,19, 85,8,195,
+ 83,7,35, 0,8,115, 0,8,51, 0,9,199,
+ 81,7,11, 0,8,99, 0,8,35, 0,9,167,
+ 0,8,3, 0,8,131, 0,8,67, 0,9,231,
+ 80,7,7, 0,8,91, 0,8,27, 0,9,151,
+ 84,7,67, 0,8,123, 0,8,59, 0,9,215,
+ 82,7,19, 0,8,107, 0,8,43, 0,9,183,
+ 0,8,11, 0,8,139, 0,8,75, 0,9,247,
+ 80,7,5, 0,8,87, 0,8,23, 192,8,0,
+ 83,7,51, 0,8,119, 0,8,55, 0,9,207,
+ 81,7,15, 0,8,103, 0,8,39, 0,9,175,
+ 0,8,7, 0,8,135, 0,8,71, 0,9,239,
+ 80,7,9, 0,8,95, 0,8,31, 0,9,159,
+ 84,7,99, 0,8,127, 0,8,63, 0,9,223,
+ 82,7,27, 0,8,111, 0,8,47, 0,9,191,
+ 0,8,15, 0,8,143, 0,8,79, 0,9,255
+ };
+ static readonly int[] fixed_td = {
+ 80,5,1, 87,5,257, 83,5,17, 91,5,4097,
+ 81,5,5, 89,5,1025, 85,5,65, 93,5,16385,
+ 80,5,3, 88,5,513, 84,5,33, 92,5,8193,
+ 82,5,9, 90,5,2049, 86,5,129, 192,5,24577,
+ 80,5,2, 87,5,385, 83,5,25, 91,5,6145,
+ 81,5,7, 89,5,1537, 85,5,97, 93,5,24577,
+ 80,5,4, 88,5,769, 84,5,49, 92,5,12289,
+ 82,5,13, 90,5,3073, 86,5,193, 192,5,24577
+ };
+
+ // Tables for deflate from PKZIP's appnote.txt.
+ static readonly int[] cplens = { // Copy lengths for literal codes 257..285
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
+ };
+
+ // see note #13 above about 258
+ static readonly int[] cplext = { // Extra bits for literal codes 257..285
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+ 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112 // 112==invalid
+ };
+
+ static readonly int[] cpdist = { // Copy offsets for distance codes 0..29
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+ 8193, 12289, 16385, 24577
+ };
+
+ static readonly int[] cpdext = { // Extra bits for distance codes
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+ 12, 12, 13, 13};
+
+ // If BMAX needs to be larger than 16, then h and x[] should be uLong.
+ const int BMAX = 15; // maximum bit length of any code
+
+ int[] hn = null; // hufts used in space
+ int[] v = null; // work area for huft_build
+ int[] c = null; // bit length count table
+ int[] r = null; // table entry for structure assignment
+ int[] u = null; // table stack
+ int[] x = null; // bit offsets, then code stack
+
+ private ZLibStatus HuftBuild(int[] b, // code lengths in bits (all assumed <= BMAX)
+ int bindex,
+ int n, // number of codes (assumed <= 288)
+ int s, // number of simple-valued codes (0..s-1)
+ int[] d, // list of base values for non-simple codes
+ int[] e, // list of extra bits for non-simple codes
+ int[] t, // result: starting table
+ int[] m, // maximum lookup bits, returns actual
+ int[] hp,// space for trees
+ int[] hn,// hufts used in space
+ int[] v // working area: values in order of bit length
+ )
+ {
+ // Given a list of code lengths and a maximum table size, make a set of
+ // tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR
+ // if the given code set is incomplete (the tables are still built in this
+ // case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of
+ // lengths), or Z_MEM_ERROR if not enough memory.
+
+ int a; // counter for codes of length k
+ int f; // i repeats in table every f entries
+ int g; // maximum code length
+ int h; // table level
+ int i; // counter, current code
+ int j; // counter
+ int k; // number of bits in current code
+ int l; // bits per table (returned in m)
+ int mask; // (1 << w) - 1, to avoid cc -O bug on HP
+ int p; // pointer into c[], b[], or v[]
+ int q; // points to current table
+ int w; // bits before this table == (l * h)
+ int xp; // pointer into x
+ int y; // number of dummy codes added
+ int z; // number of entries in current table
+
+ // Generate counts for each bit length
+
+ p = 0; i = n;
+ do
+ {
+ c[b[bindex + p]]++; p++; i--; // assume all entries <= BMAX
+ } while (i != 0);
+
+ if (c[0] == n)
+ { // null input--all zero length codes
+ t[0] = -1;
+ m[0] = 0;
+ return ZLibStatus.Z_OK;
+ }
+
+ // Find minimum and maximum length, bound *m by those
+ l = m[0];
+ for (j = 1; j <= BMAX; j++)
+ if (c[j] != 0) break;
+ k = j; // minimum code length
+ if (l < j)
+ {
+ l = j;
+ }
+ for (i = BMAX; i != 0; i--)
+ {
+ if (c[i] != 0) break;
+ }
+ g = i; // maximum code length
+ if (l > i)
+ {
+ l = i;
+ }
+ m[0] = l;
+
+ // Adjust last length count to fill out codes, if needed
+ for (y = 1 << j; j < i; j++, y <<= 1)
+ {
+ if ((y -= c[j]) < 0)
+ {
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ }
+ if ((y -= c[i]) < 0)
+ {
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ c[i] += y;
+
+ // Generate starting offsets into the value table for each length
+ x[1] = j = 0;
+ p = 1; xp = 2;
+ while (--i != 0)
+ { // note that i == g from above
+ x[xp] = (j += c[p]);
+ xp++;
+ p++;
+ }
+
+ // Make a table of values in order of bit lengths
+ i = 0; p = 0;
+ do
+ {
+ if ((j = b[bindex + p]) != 0)
+ {
+ v[x[j]++] = i;
+ }
+ p++;
+ }
+ while (++i < n);
+ n = x[g]; // set n to length of v
+
+ // Generate the Huffman codes and for each, make the table entries
+ x[0] = i = 0; // first Huffman code is zero
+ p = 0; // grab values in bit order
+ h = -1; // no tables yet--level -1
+ w = -l; // bits decoded == (l * h)
+ u[0] = 0; // just to keep compilers happy
+ q = 0; // ditto
+ z = 0; // ditto
+
+ // go through the bit lengths (k already is bits in shortest code)
+ for (; k <= g; k++)
+ {
+ a = c[k];
+ while (a-- != 0)
+ {
+ // here i is the Huffman code of length k bits for value *p
+ // make tables up to required level
+ while (k > w + l)
+ {
+ h++;
+ w += l; // previous table always l bits
+ // compute minimum size table less than or equal to l bits
+ z = g - w;
+ z = (z > l) ? l : z; // table size upper limit
+ if ((f = 1 << (j = k - w)) > a + 1)
+ { // try a k-w bit table
+ // too few codes for k-w bit table
+ f -= a + 1; // deduct codes from patterns left
+ xp = k;
+ if (j < z)
+ {
+ while (++j < z)
+ { // try smaller tables up to z bits
+ if ((f <<= 1) <= c[++xp])
+ break; // enough codes to use up j bits
+ f -= c[xp]; // else deduct codes from patterns
+ }
+ }
+ }
+ z = 1 << j; // table entries for j-bit table
+
+ // allocate new table
+ if (hn[0] + z > MANY)
+ { // (note: doesn't matter for fixed)
+ return ZLibStatus.Z_DATA_ERROR; // overflow of MANY
+ }
+ u[h] = q = /*hp+*/ hn[0]; // DEBUG
+ hn[0] += z;
+
+ // connect to last table, if there is one
+ if (h != 0)
+ {
+ x[h] = i; // save pattern for backing up
+ r[0] = (byte)j; // bits in this table
+ r[1] = (byte)l; // bits to dump before this table
+ j = i >> (w - l);
+ r[2] = (int)(q - u[h - 1] - j); // offset to this table
+ System.Array.Copy(r, 0, hp, (u[h - 1] + j) * 3, 3); // connect to last table
+ }
+ else
+ {
+ t[0] = q; // first table is returned result
+ }
+ }
+
+ // set up table entry in r
+ r[1] = (byte)(k - w);
+ if (p >= n)
+ {
+ r[0] = 128 + 64; // out of values--invalid code
+ }
+ else if (v[p] < s)
+ {
+ r[0] = (byte)(v[p] < 256 ? 0 : 32 + 64); // 256 is end-of-block
+ r[2] = v[p++]; // simple code is just the value
+ }
+ else
+ {
+ r[0] = (byte)(e[v[p] - s] + 16 + 64); // non-simple--look up in lists
+ r[2] = d[v[p++] - s];
+ }
+
+ // fill code-like entries with r
+ f = 1 << (k - w);
+ for (j = i >> w; j < z; j += f)
+ {
+ System.Array.Copy(r, 0, hp, (q + j) * 3, 3);
+ }
+
+ // backwards increment the k-bit code i
+ for (j = 1 << (k - 1); (i & j) != 0; j >>= 1)
+ {
+ i ^= j;
+ }
+ i ^= j;
+
+ // backup over finished tables
+ mask = (1 << w) - 1; // needed on HP, cc -O bug
+ while ((i & mask) != x[h])
+ {
+ h--; // don't need to update q
+ w -= l;
+ mask = (1 << w) - 1;
+ }
+ }
+ }
+ // Return Z_BUF_ERROR if we were given an incomplete table
+ return y != 0 && g != 1 ? ZLibStatus.Z_BUF_ERROR : ZLibStatus.Z_OK;
+ }
+
+ internal ZLibStatus InflateTreesBits(int[] c, // 19 code lengths
+ int[] bb, // bits tree desired/actual depth
+ int[] tb, // bits tree result
+ int[] hp, // space for trees
+ ZStream z // for messages
+ )
+ {
+ ZLibStatus result;
+ InitWorkArea(19);
+ hn[0] = 0;
+ result = HuftBuild(c, 0, 19, 19, null, null, tb, bb, hp, hn, v);
+
+ if (result == ZLibStatus.Z_DATA_ERROR)
+ {
+ z.msg = "oversubscribed dynamic bit lengths tree";
+ }
+ else if (result == ZLibStatus.Z_BUF_ERROR || bb[0] == 0)
+ {
+ z.msg = "incomplete dynamic bit lengths tree";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ return result;
+ }
+
+ internal ZLibStatus InflateTreesDynamic(int nl, // number of literal/length codes
+ int nd, // number of distance codes
+ int[] c, // that many (total) code lengths
+ int[] bl, // literal desired/actual bit depth
+ int[] bd, // distance desired/actual bit depth
+ int[] tl, // literal/length tree result
+ int[] td, // distance tree result
+ int[] hp, // space for trees
+ ZStream z // for messages
+ )
+ {
+ ZLibStatus result;
+
+ // build literal/length tree
+ InitWorkArea(288);
+ hn[0] = 0;
+ result = HuftBuild(c, 0, nl, 257, cplens, cplext, tl, bl, hp, hn, v);
+ if (result != ZLibStatus.Z_OK || bl[0] == 0)
+ {
+ if (result == ZLibStatus.Z_DATA_ERROR)
+ {
+ z.msg = "oversubscribed literal/length tree";
+ }
+ else if (result != ZLibStatus.Z_MEM_ERROR)
+ {
+ z.msg = "incomplete literal/length tree";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ return result;
+ }
+
+ // build distance tree
+ InitWorkArea(288);
+ result = HuftBuild(c, nl, nd, 0, cpdist, cpdext, td, bd, hp, hn, v);
+
+ if (result != ZLibStatus.Z_OK || (bd[0] == 0 && nl > 257))
+ {
+ if (result == ZLibStatus.Z_DATA_ERROR)
+ {
+ z.msg = "oversubscribed distance tree";
+ }
+ else if (result == ZLibStatus.Z_BUF_ERROR)
+ {
+ z.msg = "incomplete distance tree";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ else if (result != ZLibStatus.Z_MEM_ERROR)
+ {
+ z.msg = "empty distance tree with lengths";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ return result;
+ }
+
+ return ZLibStatus.Z_OK;
+ }
+
+ internal static ZLibStatus InflateTreesFixed(int[] bl, //literal desired/actual bit depth
+ int[] bd, //distance desired/actual bit depth
+ int[][] tl,//literal/length tree result
+ int[][] td,//distance tree result
+ ZStream z //for memory allocation
+ )
+ {
+ bl[0] = fixed_bl;
+ bd[0] = fixed_bd;
+ tl[0] = fixed_tl;
+ td[0] = fixed_td;
+ return ZLibStatus.Z_OK;
+ }
+
+ private void InitWorkArea(int vsize)
+ {
+ if (hn == null)
+ {
+ hn = new int[1];
+ v = new int[vsize];
+ c = new int[BMAX + 1];
+ r = new int[3];
+ u = new int[BMAX];
+ x = new int[BMAX + 1];
+ }
+ if (v.Length < vsize) { v = new int[vsize]; }
+ for (int i = 0; i < vsize; i++) { v[i] = 0; }
+ for (int i = 0; i < BMAX + 1; i++) { c[i] = 0; }
+ for (int i = 0; i < 3; i++) { r[i] = 0; }
+ // for(int i=0; i
+ /// Gets the static tree or null
+ ///
+ ///
+ /// The static_tree.
+ ///
+ public short[] TreeData { get; private set; }
+
+ ///
+ /// Gets the extra bits for each code or null.
+ ///
+ ///
+ /// The extra bits.
+ ///
+ public int[] ExtraBits { get; private set; }
+
+ ///
+ /// Gets the base index for extra_bits.
+ ///
+ ///
+ /// The extra base.
+ ///
+ public int ExtraBase { get; private set; }
+
+ ///
+ /// Gets the max number of elements in the tree.
+ ///
+ ///
+ /// The elements.
+ ///
+ public int Elements { get; private set; }
+
+ ///
+ /// Gets the max bit length for the codes.
+ ///
+ ///
+ /// The length of the max.
+ ///
+ public int MaxLength { get; private set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The tree data.
+ /// The extra bits.
+ /// The extra base.
+ /// The elements.
+ /// Length of the max.
+ public StaticTree(short[] treeData, int[] extraBits, int extraBase, int elements, int maxLength)
+ {
+ this.TreeData = treeData;
+ this.ExtraBits = extraBits;
+ this.ExtraBase = extraBase;
+ this.Elements = elements;
+ this.MaxLength = maxLength;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Version.8/Tree.cs b/Renci.SshNet/Compression/Version.8/Tree.cs
new file mode 100644
index 0000000..d2142c9
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.8/Tree.cs
@@ -0,0 +1,334 @@
+using System;
+/*
+ * $Id: Tree.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+ internal sealed class Tree
+ {
+ private const int MAX_BITS = 15;
+
+ private const int LITERALS = 256;
+
+ private const int LENGTH_CODES = 29;
+
+ private const int L_CODES = (LITERALS + 1 + LENGTH_CODES);
+
+ private const int HEAP_SIZE = (2 * L_CODES + 1);
+
+ private static byte[] _dist_code = {
+ 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8,
+ 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17,
+ 18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
+ 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
+ };
+
+
+ ///
+ /// The corresponding static tree
+ ///
+ private StaticTree _staticTree;
+
+ ///
+ /// The dynamic tree
+ ///
+ private short[] _dynamicTree;
+
+ ///
+ /// Gets the largest code with non zero frequency.
+ ///
+ ///
+ /// The max_code.
+ ///
+ public int LargestCode { get; private set; }
+
+ public void Init(short[] dynamicTree, StaticTree staticTree)
+ {
+ this._staticTree = staticTree;
+ this._dynamicTree = dynamicTree;
+ }
+
+ ///
+ /// Mapping from a distance to a distance code. dist is the distance - 1 and must not have side effects. _dist_code[256] and _dist_code[257] are never used.
+ ///
+ /// The dist.
+ ///
+ public static int DistanceCode(int dist)
+ {
+ // TODO: Under multiple port forward after more then 50K requests gets index out of range
+ return ((dist) < 256 ? _dist_code[dist] : _dist_code[256 + ((dist) >> 7)]);
+ }
+
+ ///
+ /// Construct one Huffman tree and assigns the code bit strings and lengths. Update the total bit length for the current block.
+ ///
+ /// The s.
+ public void BuildTree(Deflate s)
+ {
+ short[] tree = _dynamicTree;
+ short[] stree = _staticTree.TreeData;
+ int elems = _staticTree.Elements;
+ int n, m; // iterate over heap elements
+ int max_code = -1; // largest code with non zero frequency
+ int node; // new node being created
+
+ // Construct the initial heap, with least frequent element in
+ // heap[1]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
+ // heap[0] is not used.
+ s.heap_len = 0;
+ s.heap_max = HEAP_SIZE;
+
+ for (n = 0; n < elems; n++)
+ {
+ if (tree[n * 2] != 0)
+ {
+ s.heap[++s.heap_len] = max_code = n;
+ s.depth[n] = 0;
+ }
+ else
+ {
+ tree[n * 2 + 1] = 0;
+ }
+ }
+
+ // The pkzip format requires that at least one distance code exists,
+ // and that at least one bit should be sent even if there is only one
+ // possible code. So to avoid special checks later on we force at least
+ // two codes of non zero frequency.
+ while (s.heap_len < 2)
+ {
+ node = s.heap[++s.heap_len] = (max_code < 2 ? ++max_code : 0);
+ tree[node * 2] = 1;
+ s.depth[node] = 0;
+ s.opt_len--; if (stree != null) s.static_len -= stree[node * 2 + 1];
+ // node is 0 or 1 so it does not have extra bits
+ }
+ this.LargestCode = max_code;
+
+ // The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
+ // establish sub-heaps of increasing lengths:
+
+ for (n = s.heap_len / 2; n >= 1; n--)
+ s.pqdownheap(tree, n);
+
+ // Construct the Huffman tree by repeatedly combining the least two
+ // frequent nodes.
+
+ node = elems; // next internal node of the tree
+ do
+ {
+ // n = node of least frequency
+ n = s.heap[1];
+ s.heap[1] = s.heap[s.heap_len--];
+ s.pqdownheap(tree, 1);
+ m = s.heap[1]; // m = node of next least frequency
+
+ s.heap[--s.heap_max] = n; // keep the nodes sorted by frequency
+ s.heap[--s.heap_max] = m;
+
+ // Create a new node father of n and m
+ tree[node * 2] = (short)(tree[n * 2] + tree[m * 2]);
+ s.depth[node] = (byte)(System.Math.Max(s.depth[n], s.depth[m]) + 1);
+ tree[n * 2 + 1] = tree[m * 2 + 1] = (short)node;
+
+ // and insert the new node in the heap
+ s.heap[1] = node++;
+ s.pqdownheap(tree, 1);
+ }
+ while (s.heap_len >= 2);
+
+ s.heap[--s.heap_max] = s.heap[1];
+
+ // At this point, the fields freq and dad are set. We can now
+ // generate the bit lengths.
+
+ ComputeBitLength(s);
+
+ // The field len is now set, we can generate the bit codes
+ GenerateCodes(tree, max_code, s.bl_count);
+ }
+
+ ///
+ /// Compute the optimal bit lengths for a tree and update the total bit length for the current block.
+ ///
+ /// The s.
+ private void ComputeBitLength(Deflate s)
+ {
+ short[] tree = _dynamicTree;
+ short[] stree = _staticTree.TreeData;
+ int[] extra = _staticTree.ExtraBits;
+ int based = _staticTree.ExtraBase;
+ int max_length = _staticTree.MaxLength;
+ int h; // heap index
+ int n, m; // iterate over the tree elements
+ int bits; // bit length
+ int xbits; // extra bits
+ short f; // frequency
+ int overflow = 0; // number of elements with bit length too large
+
+ for (bits = 0; bits <= MAX_BITS; bits++) s.bl_count[bits] = 0;
+
+ // In a first pass, compute the optimal bit lengths (which may
+ // overflow in the case of the bit length tree).
+ tree[s.heap[s.heap_max] * 2 + 1] = 0; // root of the heap
+
+ for (h = s.heap_max + 1; h < HEAP_SIZE; h++)
+ {
+ n = s.heap[h];
+ bits = tree[tree[n * 2 + 1] * 2 + 1] + 1;
+ if (bits > max_length) { bits = max_length; overflow++; }
+ tree[n * 2 + 1] = (short)bits;
+ // We overwrite tree[n*2+1] which is no longer needed
+
+ if (n > LargestCode) continue; // not a leaf node
+
+ s.bl_count[bits]++;
+ xbits = 0;
+ if (n >= based) xbits = extra[n - based];
+ f = tree[n * 2];
+ s.opt_len += f * (bits + xbits);
+ if (stree != null) s.static_len += f * (stree[n * 2 + 1] + xbits);
+ }
+ if (overflow == 0) return;
+
+ // This happens for example on obj2 and pic of the Calgary corpus
+ // Find the first bit length which could increase:
+ do
+ {
+ bits = max_length - 1;
+ while (s.bl_count[bits] == 0) bits--;
+ s.bl_count[bits]--; // move one leaf down the tree
+ s.bl_count[bits + 1] += 2; // move one overflow item as its brother
+ s.bl_count[max_length]--;
+ // The brother of the overflow item also moves one step up,
+ // but this does not affect bl_count[max_length]
+ overflow -= 2;
+ }
+ while (overflow > 0);
+
+ for (bits = max_length; bits != 0; bits--)
+ {
+ n = s.bl_count[bits];
+ while (n != 0)
+ {
+ m = s.heap[--h];
+ if (m > LargestCode) continue;
+ if (tree[m * 2 + 1] != bits)
+ {
+ s.opt_len += (int)(((long)bits - (long)tree[m * 2 + 1]) * (long)tree[m * 2]);
+ tree[m * 2 + 1] = (short)bits;
+ }
+ n--;
+ }
+ }
+ }
+
+ ///
+ /// Generate the codes for a given tree and bit counts (which need not be optimal).
+ ///
+ /// The tree to decorate.
+ /// The largest code with non zero frequency.
+ /// The number of codes at each bit length.
+ private static void GenerateCodes(short[] tree, int max_code, short[] bl_count)
+ {
+ short[] next_code = new short[MAX_BITS + 1]; // next code value for each bit length
+ short code = 0; // running code value
+ int bits; // bit index
+ int n; // code index
+
+ // The distribution counts are first used to generate the code values
+ // without bit reversal.
+ for (bits = 1; bits <= MAX_BITS; bits++)
+ {
+ next_code[bits] = code = (short)((code + bl_count[bits - 1]) << 1);
+ }
+
+ // Check that the bit counts in bl_count are consistent. The last code
+ // must be all ones.
+ //Assert (code + bl_count[MAX_BITS]-1 == (1<
+ /// Reverse the first len bits of a code, using straightforward code (a faster method would use a table)
+ ///
+ /// The value to invert.
+ /// The bit length.
+ ///
+ private static int BiReverse(int code, int len)
+ {
+ int res = 0;
+ do
+ {
+ res |= code & 1;
+ code >>= 1;
+ res <<= 1;
+ }
+ while (--len > 0);
+ return res >> 1;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Version.8/ZInputStream.cs b/Renci.SshNet/Compression/Version.8/ZInputStream.cs
new file mode 100644
index 0000000..a491d99
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.8/ZInputStream.cs
@@ -0,0 +1,202 @@
+/*
+Copyright (c) 2001 Lapo Luchini.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS
+OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+/* This file is a port of jzlib v1.0.7, com.jcraft.jzlib.ZInputStream.java
+ */
+
+using Renci.SshNet.Compression;
+using System;
+using System.Diagnostics;
+using System.IO;
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+ public class ZInputStream : Stream
+ {
+ private const int BufferSize = 512;
+ //private ZStream z = new ZStream();
+ private ICompressor _compressor;
+
+ // TODO Allow custom buf
+ private byte[] _buffer = new byte[BufferSize];
+ private CompressionMode _compressionMode;
+ private Stream _input;
+ private bool _isClosed;
+ private bool _noMoreInput = false;
+
+ public FlushType FlushMode { get; private set; }
+
+ public ZInputStream()
+ {
+ this.FlushMode = FlushType.Z_PARTIAL_FLUSH;
+ }
+
+ public ZInputStream(Stream input)
+ : this(input, false)
+ {
+ }
+
+ public ZInputStream(Stream input, bool nowrap)
+ : this()
+ {
+ Debug.Assert(input.CanRead);
+
+ this._input = input;
+ this._compressor = new Inflate(nowrap);
+ //this._compressor.inflateInit(nowrap);
+ this._compressionMode = CompressionMode.Decompress;
+ this._compressor.next_in = _buffer;
+ this._compressor.next_in_index = 0;
+ this._compressor.avail_in = 0;
+ }
+
+ public ZInputStream(Stream input, CompressionLevel level)
+ : this()
+ {
+ Debug.Assert(input.CanRead);
+
+ this._input = input;
+ this._compressor = new Deflate(level);
+ //this._compressor.deflateInit(level);
+ this._compressionMode = CompressionMode.Compress;
+ this._compressor.next_in = _buffer;
+ this._compressor.next_in_index = 0;
+ this._compressor.avail_in = 0;
+ }
+
+ #region Stream implementation
+
+ public sealed override bool CanRead
+ {
+ get { return !_isClosed; }
+ }
+
+ public sealed override bool CanSeek
+ {
+ get { return false; }
+ }
+
+ public sealed override bool CanWrite
+ {
+ get { return false; }
+ }
+
+ public override void Flush()
+ {
+ }
+
+ public override long Length
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ public override long Position
+ {
+ get { throw new NotSupportedException(); }
+ set { throw new NotSupportedException(); }
+ }
+
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ if (count == 0)
+ return 0;
+
+ this._compressor.next_out = buffer;
+ this._compressor.next_out_index = offset;
+ this._compressor.avail_out = count;
+
+ ZLibStatus err = ZLibStatus.Z_OK;
+ do
+ {
+ if (this._compressor.avail_in == 0 && !_noMoreInput)
+ {
+ // if buffer is empty and more input is available, refill it
+ this._compressor.next_in_index = 0;
+ this._compressor.avail_in = _input.Read(_buffer, 0, _buffer.Length); //(bufsize 0 || this._compressor.avail_out == 0);
+ }
+
+ #endregion
+
+ public override void Close()
+ {
+ if (this._isClosed)
+ return;
+
+ try
+ {
+ try
+ {
+ Finish();
+ }
+ catch (IOException)
+ {
+ // Ignore
+ }
+ }
+ finally
+ {
+ this._isClosed = true;
+ End();
+ _output.Close();
+ _output = null;
+ }
+ }
+
+ private void End()
+ {
+ if (this._compressor == null)
+ return;
+ switch (this._compressionMode)
+ {
+ case CompressionMode.Compress:
+ this._compressor.deflateEnd();
+ break;
+ case CompressionMode.Decompress:
+ this._compressor.inflateEnd();
+ break;
+ default:
+ break;
+ }
+
+ //this._compressor.free();
+ this._compressor = null;
+ }
+
+ private void Finish()
+ {
+ do
+ {
+ this._compressor.next_out = _buffer;
+ this._compressor.next_out_index = 0;
+ this._compressor.avail_out = _buffer.Length;
+
+ var err = ZLibStatus.Z_OK;
+ switch (this._compressionMode)
+ {
+ case CompressionMode.Compress:
+ err = this._compressor.deflate(FlushType.Z_FINISH);
+ break;
+ case CompressionMode.Decompress:
+ err = this._compressor.inflate(FlushType.Z_FINISH);
+ break;
+ default:
+ break;
+ }
+
+ if (err != ZLibStatus.Z_STREAM_END && err != ZLibStatus.Z_OK)
+ // TODO
+ // throw new ZStreamException((compress?"de":"in")+"flating: "+z.msg);
+ //throw new IOException((_compressionMode ? "de" : "in") + "flating: " + z.msg);
+ throw new IOException(string.Format("{0}ion error: {1}", _compressionMode, err));
+
+ int count = _buffer.Length - this._compressor.avail_out;
+ if (count > 0)
+ {
+ _output.Write(_buffer, 0, count);
+ }
+ }
+ while (this._compressor.avail_in > 0 || this._compressor.avail_out == 0);
+
+ Flush();
+ }
+ }
+}
diff --git a/Renci.SshNet/Compression/Version.8/ZStream.cs b/Renci.SshNet/Compression/Version.8/ZStream.cs
new file mode 100644
index 0000000..1ee045e
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.8/ZStream.cs
@@ -0,0 +1,94 @@
+using System;
+using System.IO;
+/*
+ * $Id: ZStream.cs,v 1.1 2006-07-31 13:59:26 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public interface ICompressor
+ {
+ ZLibStatus deflate(FlushType flushType);
+
+ ZLibStatus deflate(byte[] bufer, int offset, int count, byte[] p1, int p2, int p3, FlushType flushType);
+
+ ZLibStatus deflateEnd();
+
+ ZLibStatus inflate(byte[] bufer, int offset, int count, byte[] p1, int p2, int p3, FlushType flushType);
+
+ ZLibStatus inflateEnd();
+
+ ZLibStatus inflate(FlushType flushType);
+
+ int avail_out { get; set; }
+
+ int avail_in { get; set; }
+
+ int next_out_index { get; set; }
+
+ byte[] next_out { get; set; }
+
+ byte[] next_in { get; set; }
+
+ int next_in_index { get; set; }
+ }
+
+
+ public abstract class ZStream
+ {
+
+ protected const int MAX_WBITS = 15; // 32K LZ77 window
+ protected const int DEF_WBITS = MAX_WBITS;
+
+ private const int MAX_MEM_LEVEL = 9;
+
+ public byte[] next_in { get; set; } // next input byte
+ public int next_in_index { get; set; }
+ public int avail_in { get; set; } // number of bytes available at next_in
+ public long total_in { get; set; } // total nb of input bytes read so far
+
+ public byte[] next_out { get; set; } // next output byte should be put there
+ public int next_out_index { get; set; }
+ public int avail_out { get; set; } // remaining free space at next_out
+ public long total_out { get; set; } // total nb of bytes output so far
+
+ public String msg { get; set; }
+
+ internal BlockType data_type; // best guess about the data type: ascii or binary
+
+ public long adler;
+
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Version.8/Zlib.cs b/Renci.SshNet/Compression/Version.8/Zlib.cs
new file mode 100644
index 0000000..5890675
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.8/Zlib.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Represents "zlib" compression implementation
+ ///
+ internal class Zlib : Compressor
+ {
+ ///
+ /// Gets algorithm name.
+ ///
+ public override string Name
+ {
+ get { return "zlib"; }
+ }
+
+ ///
+ /// Initializes the algorithm
+ ///
+ /// The session.
+ public override void Init(Session session)
+ {
+ base.Init(session);
+ this.IsActive = true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Version.8/ZlibOpenSsh.cs b/Renci.SshNet/Compression/Version.8/ZlibOpenSsh.cs
new file mode 100644
index 0000000..f82a4c0
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.8/ZlibOpenSsh.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Represents "zlib@openssh.org" compression implementation
+ ///
+ public class ZlibOpenSsh : Compressor
+ {
+ ///
+ /// Gets algorithm name.
+ ///
+ public override string Name
+ {
+ get { return "zlib@openssh.org"; }
+ }
+
+ ///
+ /// Initializes the algorithm
+ ///
+ /// The session.
+ public override void Init(Session session)
+ {
+ base.Init(session);
+
+ session.UserAuthenticationSuccessReceived += Session_UserAuthenticationSuccessReceived;
+ }
+
+ private void Session_UserAuthenticationSuccessReceived(object sender, MessageEventArgs e)
+ {
+ this.IsActive = true;
+ this.Session.UserAuthenticationSuccessReceived -= Session_UserAuthenticationSuccessReceived;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Version.8/ZlibStream.cs b/Renci.SshNet/Compression/Version.8/ZlibStream.cs
new file mode 100644
index 0000000..fb5f9d2
--- /dev/null
+++ b/Renci.SshNet/Compression/Version.8/ZlibStream.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.IO;
+using Org.BouncyCastle.Utilities.Zlib;
+
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Implements Zlib compression algorithm.
+ ///
+ public class ZlibStream
+ {
+ private readonly Stream _baseStream;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The stream.
+ /// The mode.
+ public ZlibStream(Stream stream, CompressionMode mode)
+ {
+ switch (mode)
+ {
+ case CompressionMode.Compress:
+ //this._baseStream = new ZOutputStream(stream, CompressionLevel.Z_DEFAULT_COMPRESSION);
+ this._baseStream = new ZOutputStream(stream, CompressionLevel.Z_DEFAULT_COMPRESSION);
+ break;
+ case CompressionMode.Decompress:
+ this._baseStream = new ZOutputStream(stream);
+ break;
+ default:
+ break;
+ }
+
+ //this._baseStream.FlushMode = Ionic.Zlib.FlushType.Partial;
+ }
+
+ ///
+ /// Writes the specified buffer.
+ ///
+ /// The buffer.
+ /// The offset.
+ /// The count.
+ public void Write(byte[] buffer, int offset, int count)
+ {
+ this._baseStream.Write(buffer, offset, count);
+ }
+ }
+}
diff --git a/Renci.SshNet/Compression/Working.1/CompressionMode.cs b/Renci.SshNet/Compression/Working.1/CompressionMode.cs
new file mode 100644
index 0000000..1577e0b
--- /dev/null
+++ b/Renci.SshNet/Compression/Working.1/CompressionMode.cs
@@ -0,0 +1,18 @@
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Specifies compression modes
+ ///
+ public enum CompressionMode
+ {
+ ///
+ /// Specifies that content should be compressed.
+ ///
+ Compress = 0,
+
+ ///
+ /// Specifies that content should be decompressed.
+ ///
+ Decompress = 1,
+ }
+}
diff --git a/Renci.SshNet/Compression/Working.1/Compressor.cs b/Renci.SshNet/Compression/Working.1/Compressor.cs
new file mode 100644
index 0000000..1479bb6
--- /dev/null
+++ b/Renci.SshNet/Compression/Working.1/Compressor.cs
@@ -0,0 +1,151 @@
+using System.Collections.Generic;
+using Renci.SshNet.Security;
+using System.IO;
+using System;
+
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Represents base class for compression algorithm implementation
+ ///
+ public abstract class Compressor : Algorithm, IDisposable
+ {
+ private readonly ZlibStream _compressor;
+ private readonly ZlibStream _decompressor;
+
+ private MemoryStream _compressorStream;
+ private MemoryStream _decompressorStream;
+
+ ///
+ /// Gets or sets a value indicating whether compression is active.
+ ///
+ ///
+ /// true if compression is active; otherwise, false.
+ ///
+ protected bool IsActive { get; set; }
+
+ ///
+ /// Gets the session.
+ ///
+ protected Session Session { get; private set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ 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);
+ }
+
+ ///
+ /// Initializes the algorithm
+ ///
+ /// The session.
+ public virtual void Init(Session session)
+ {
+ this.Session = session;
+ }
+
+ ///
+ /// Compresses the specified data.
+ ///
+ /// Data to compress.
+ /// Compressed 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();
+ }
+
+ ///
+ /// Decompresses the specified data.
+ ///
+ /// Compressed data.
+ /// Decompressed 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;
+
+ ///
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged ResourceMessages.
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Releases unmanaged and - optionally - managed resources
+ ///
+ /// true to release both managed and unmanaged resources; false to release only unmanaged ResourceMessages.
+ 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;
+ }
+ }
+
+ ///
+ /// Releases unmanaged resources and performs other cleanup operations before the
+ /// is reclaimed by garbage collection.
+ ///
+ ~Compressor()
+ {
+ // Do not re-create Dispose clean-up code here.
+ // Calling Dispose(false) is optimal in terms of
+ // readability and maintainability.
+ Dispose(false);
+ }
+
+ #endregion
+ }
+}
diff --git a/Renci.SshNet/Compression/Working.1/Deflate.cs b/Renci.SshNet/Compression/Working.1/Deflate.cs
new file mode 100644
index 0000000..fe7a62a
--- /dev/null
+++ b/Renci.SshNet/Compression/Working.1/Deflate.cs
@@ -0,0 +1,2185 @@
+using System;
+using System.Collections.Generic;
+/*
+ * $Id: Deflate.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public enum BlockType : byte
+ {
+ Z_BINARY = 0,
+ Z_ASCII = 1,
+ Z_UNKNOWN = 2
+ }
+
+ public sealed class Deflate
+ {
+ ///
+ /// The Bit length codes must not exceed MAX_BL_BITS bits
+ ///
+ private const int MAX_BL_BITS = 7;
+
+ private const int MAX_MEM_LEVEL = 9;
+
+ #region Private static declarations
+
+ private static readonly byte[] _lengthCode ={
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12,
+ 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
+ 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
+ 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
+ };
+
+ private static readonly int[] _baseLength = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
+ 64, 80, 96, 112, 128, 160, 192, 224, 0
+ };
+
+ private static readonly int[] _baseDistance = {
+ 0, 1, 2, 3, 4, 6, 8, 12, 16, 24,
+ 32, 48, 64, 96, 128, 192, 256, 384, 512, 768,
+ 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576
+ };
+
+ private static readonly short[] static_ltree = {
+ 12, 8, 140, 8, 76, 8, 204, 8, 44, 8,
+ 172, 8, 108, 8, 236, 8, 28, 8, 156, 8,
+ 92, 8, 220, 8, 60, 8, 188, 8, 124, 8,
+ 252, 8, 2, 8, 130, 8, 66, 8, 194, 8,
+ 34, 8, 162, 8, 98, 8, 226, 8, 18, 8,
+ 146, 8, 82, 8, 210, 8, 50, 8, 178, 8,
+ 114, 8, 242, 8, 10, 8, 138, 8, 74, 8,
+ 202, 8, 42, 8, 170, 8, 106, 8, 234, 8,
+ 26, 8, 154, 8, 90, 8, 218, 8, 58, 8,
+ 186, 8, 122, 8, 250, 8, 6, 8, 134, 8,
+ 70, 8, 198, 8, 38, 8, 166, 8, 102, 8,
+ 230, 8, 22, 8, 150, 8, 86, 8, 214, 8,
+ 54, 8, 182, 8, 118, 8, 246, 8, 14, 8,
+ 142, 8, 78, 8, 206, 8, 46, 8, 174, 8,
+ 110, 8, 238, 8, 30, 8, 158, 8, 94, 8,
+ 222, 8, 62, 8, 190, 8, 126, 8, 254, 8,
+ 1, 8, 129, 8, 65, 8, 193, 8, 33, 8,
+ 161, 8, 97, 8, 225, 8, 17, 8, 145, 8,
+ 81, 8, 209, 8, 49, 8, 177, 8, 113, 8,
+ 241, 8, 9, 8, 137, 8, 73, 8, 201, 8,
+ 41, 8, 169, 8, 105, 8, 233, 8, 25, 8,
+ 153, 8, 89, 8, 217, 8, 57, 8, 185, 8,
+ 121, 8, 249, 8, 5, 8, 133, 8, 69, 8,
+ 197, 8, 37, 8, 165, 8, 101, 8, 229, 8,
+ 21, 8, 149, 8, 85, 8, 213, 8, 53, 8,
+ 181, 8, 117, 8, 245, 8, 13, 8, 141, 8,
+ 77, 8, 205, 8, 45, 8, 173, 8, 109, 8,
+ 237, 8, 29, 8, 157, 8, 93, 8, 221, 8,
+ 61, 8, 189, 8, 125, 8, 253, 8, 19, 9,
+ 275, 9, 147, 9, 403, 9, 83, 9, 339, 9,
+ 211, 9, 467, 9, 51, 9, 307, 9, 179, 9,
+ 435, 9, 115, 9, 371, 9, 243, 9, 499, 9,
+ 11, 9, 267, 9, 139, 9, 395, 9, 75, 9,
+ 331, 9, 203, 9, 459, 9, 43, 9, 299, 9,
+ 171, 9, 427, 9, 107, 9, 363, 9, 235, 9,
+ 491, 9, 27, 9, 283, 9, 155, 9, 411, 9,
+ 91, 9, 347, 9, 219, 9, 475, 9, 59, 9,
+ 315, 9, 187, 9, 443, 9, 123, 9, 379, 9,
+ 251, 9, 507, 9, 7, 9, 263, 9, 135, 9,
+ 391, 9, 71, 9, 327, 9, 199, 9, 455, 9,
+ 39, 9, 295, 9, 167, 9, 423, 9, 103, 9,
+ 359, 9, 231, 9, 487, 9, 23, 9, 279, 9,
+ 151, 9, 407, 9, 87, 9, 343, 9, 215, 9,
+ 471, 9, 55, 9, 311, 9, 183, 9, 439, 9,
+ 119, 9, 375, 9, 247, 9, 503, 9, 15, 9,
+ 271, 9, 143, 9, 399, 9, 79, 9, 335, 9,
+ 207, 9, 463, 9, 47, 9, 303, 9, 175, 9,
+ 431, 9, 111, 9, 367, 9, 239, 9, 495, 9,
+ 31, 9, 287, 9, 159, 9, 415, 9, 95, 9,
+ 351, 9, 223, 9, 479, 9, 63, 9, 319, 9,
+ 191, 9, 447, 9, 127, 9, 383, 9, 255, 9,
+ 511, 9, 0, 7, 64, 7, 32, 7, 96, 7,
+ 16, 7, 80, 7, 48, 7, 112, 7, 8, 7,
+ 72, 7, 40, 7, 104, 7, 24, 7, 88, 7,
+ 56, 7, 120, 7, 4, 7, 68, 7, 36, 7,
+ 100, 7, 20, 7, 84, 7, 52, 7, 116, 7,
+ 3, 8, 131, 8, 67, 8, 195, 8, 35, 8,
+ 163, 8, 99, 8, 227, 8
+ };
+
+ private static readonly short[] static_dtree = {
+ 0, 5, 16, 5, 8, 5, 24, 5, 4, 5,
+ 20, 5, 12, 5, 28, 5, 2, 5, 18, 5,
+ 10, 5, 26, 5, 6, 5, 22, 5, 14, 5,
+ 30, 5, 1, 5, 17, 5, 9, 5, 25, 5,
+ 5, 5, 21, 5, 13, 5, 29, 5, 3, 5,
+ 19, 5, 11, 5, 27, 5, 7, 5, 23, 5
+ };
+
+
+ ///
+ /// The extra bits for each length code
+ ///
+ private static int[] ExtraLBits = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0 };
+
+ ///
+ /// The extra bits for each distance code
+ ///
+ private static int[] ExtraDBits = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 };
+
+ ///
+ /// The extra bits for each bit length code
+ ///
+ private static int[] ExtraBLBits = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 7 };
+
+
+ private static byte[] BLOrder = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
+
+ #endregion
+
+ private const int MAX_WBITS = 15; // 32K LZ77 window
+ private const int DEF_MEM_LEVEL = 8;
+
+ private const int STORED = 0;
+ private const int FAST = 1;
+ private const int SLOW = 2;
+
+ private static readonly IDictionary _configurationTable;
+
+ static Deflate()
+ {
+ //config_table = new Config[10];
+ _configurationTable = new Dictionary();
+ // TODO: Improve array initialization
+ // good lazy nice chain
+ _configurationTable[(CompressionLevel)0] = new Config(0, 0, 0, 0, STORED);
+ _configurationTable[(CompressionLevel)1] = new Config(4, 4, 8, 4, FAST);
+ _configurationTable[(CompressionLevel)2] = new Config(4, 5, 16, 8, FAST);
+ _configurationTable[(CompressionLevel)3] = new Config(4, 6, 32, 32, FAST);
+
+ _configurationTable[(CompressionLevel)4] = new Config(4, 4, 16, 16, SLOW);
+ _configurationTable[(CompressionLevel)5] = new Config(8, 16, 32, 32, SLOW);
+ _configurationTable[(CompressionLevel)6] = new Config(8, 16, 128, 128, SLOW);
+ _configurationTable[(CompressionLevel)7] = new Config(8, 32, 128, 256, SLOW);
+ _configurationTable[(CompressionLevel)8] = new Config(32, 128, 258, 1024, SLOW);
+ _configurationTable[(CompressionLevel)9] = new Config(32, 258, 258, 4096, SLOW);
+ }
+
+ private static readonly String[] z_errmsg = {
+ "need dictionary", // ZLibStatus.Z_NEED_DICT 2
+ "stream end", // ZLibStatus.Z_STREAM_END 1
+ "", // ZLibStatus.Z_OK 0
+ "file error", // ZLibStatus.Z_ERRNO (-1)
+ "stream error", // ZLibStatus.Z_STREAM_ERROR (-2)
+ "data error", // ZLibStatus.Z_DATA_ERROR (-3)
+ "insufficient memory", // ZLibStatus.Z_MEM_ERROR (-4)
+ "buffer error", // ZLibStatus.Z_BUF_ERROR (-5)
+ "incompatible version",// ZLibStatus.Z_VERSION_ERROR (-6)
+ ""
+ };
+
+
+ private static readonly StaticTree static_l_desc = new StaticTree(static_ltree, Deflate.ExtraLBits, LITERALS + 1, L_CODES, MAX_BITS);
+
+ private static readonly StaticTree static_d_desc = new StaticTree(static_dtree, Deflate.ExtraDBits, 0, D_CODES, MAX_BITS);
+
+ private static readonly StaticTree static_bl_desc = new StaticTree(null, Deflate.ExtraBLBits, 0, BL_CODES, MAX_BL_BITS);
+
+
+ ///
+ /// block not completed, need more input or more output
+ ///
+ private const int NeedMore = 0;
+
+ ///
+ // The block flush performed
+ ///
+ private const int BlockDone = 1;
+
+ ///
+ /// finish started, need only more output at next deflate
+ ///
+ private const int FinishStarted = 2;
+
+ ///
+ /// finish done, accept no more input or output
+ ///
+ private const int FinishDone = 3;
+
+ ///
+ /// preset dictionary flag in zlib header
+ ///
+ private const int PRESET_DICT = 0x20;
+
+ private const int INIT_STATE = 42;
+ private const int BUSY_STATE = 113;
+ private const int FINISH_STATE = 666;
+
+ ///
+ /// The deflate compression method
+ ///
+ private const int Z_DEFLATED = 8;
+
+ private const int STORED_BLOCK = 0;
+ private const int STATIC_TREES = 1;
+ private const int DYN_TREES = 2;
+
+ private const int Buf_size = 8 * 2;
+
+ ///
+ /// The repeat previous bit length 3-6 times (2 bits of repeat count)
+ ///
+ private const int REP_3_6 = 16;
+
+ ///
+ /// repeat a zero length 3-10 times (3 bits of repeat count)
+ ///
+ private const int REPZ_3_10 = 17;
+
+ ///
+ /// repeat a zero length 11-138 times (7 bits of repeat count)
+ ///
+ private const int REPZ_11_138 = 18;
+
+ private const int MIN_MATCH = 3;
+ private const int MAX_MATCH = 258;
+ private const int MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1);
+
+ private const int MAX_BITS = 15;
+ private const int D_CODES = 30;
+ private const int BL_CODES = 19;
+ private const int LENGTH_CODES = 29;
+ private const int LITERALS = 256;
+ private const int L_CODES = (LITERALS + 1 + LENGTH_CODES);
+ private const int HEAP_SIZE = (2 * L_CODES + 1);
+
+ private const int END_BLOCK = 256;
+
+ ///
+ /// pointer back to this zlib stream
+ ///
+ private ZStream strm;
+
+ ///
+ /// as the name implies
+ ///
+ private int status;
+
+ private BlockType _dataType;
+
+ ///
+ /// STORED (for zip only) or DEFLATED
+ ///
+ private byte method;
+
+ ///
+ /// size of pending_buf
+ ///
+ private int pending_buf_size;
+
+ ///
+ /// LZ77 window size (32K by default)
+ ///
+ private int w_size;
+
+ ///
+ /// log2(w_size) (8..16)
+ ///
+ private int w_bits;
+
+ ///
+ /// w_size - 1
+ ///
+ private int w_mask;
+
+ ///
+ /// Sliding window. Input bytes are read into the second half of the window,
+ /// and move to the first half later to keep a dictionary of at least wSize
+ /// bytes. With this organization, matches are limited to a distance of
+ /// wSize-MAX_MATCH bytes, but this ensures that IO is always
+ /// performed with a length multiple of the block size. Also, it limits
+ /// the window size to 64K, which is quite useful on MSDOS.
+ /// To do: use the user input buffer as sliding window.
+ ///
+ private byte[] window;
+
+ ///
+ /// Actual size of window: 2*wSize, except when the user input buffer
+ /// is directly used as sliding window.
+ ///
+ private int window_size;
+
+ ///
+ /// Link to older string with same hash index. To limit the size of this
+ /// array to 64K, this link is maintained only for the last 32K strings.
+ /// An index in this array is thus a window index modulo 32K.
+ ///
+ private short[] prev;
+
+ ///
+ /// Heads of the hash chains or NIL.
+ ///
+ private short[] head;
+
+ ///
+ /// hash index of string to be inserted
+ ///
+ private int ins_h;
+
+ ///
+ /// number of elements in hash table
+ ///
+ private int hash_size;
+
+ ///
+ /// log2(hash_size)
+ ///
+ private int hash_bits;
+
+ ///
+ /// hash_size-1
+ ///
+ private int hash_mask;
+
+ ///
+ /// Number of bits by which ins_h must be shifted at each input
+ /// step. It must be such that after MIN_MATCH steps, the oldest
+ /// byte no longer takes part in the hash key, that is:
+ /// hash_shift * MIN_MATCH >= hash_bits
+ ///
+ private int hash_shift;
+
+ ///
+ /// Window position at the beginning of the current output block. Gets
+ /// negative when the window is moved backwards.
+ ///
+ private int block_start;
+
+ ///
+ /// length of best match
+ ///
+ private int match_length;
+
+ ///
+ /// previous match
+ ///
+ private int prev_match;
+
+ ///
+ /// set if previous match exists
+ ///
+ private int match_available;
+
+ ///
+ /// start of string to insert
+ ///
+ private int strstart;
+
+ ///
+ /// start of matching string
+ ///
+ private int match_start;
+
+ ///
+ /// number of valid bytes ahead in window
+ ///
+ private int lookahead;
+
+ ///
+ /// Length of the best match at previous step. Matches not greater than this
+ /// are discarded. This is used in the lazy match evaluation.
+ ///
+ private int prev_length;
+
+ ///
+ /// To speed up deflation, hash chains are never searched beyond this
+ /// length. A higher limit improves compression ratio but degrades the speed.
+ ///
+ private int max_chain_length;
+
+ ///
+ /// Attempt to find a better match only when the current match is strictly
+ /// smaller than this value. This mechanism is used only for compression
+ /// levels >= 4.
+ ///
+ private int max_lazy_match;
+
+ // Insert new strings in the hash table only if the match length is not
+ // greater than this length. This saves time but degrades compression.
+ // max_insert_length is used only for compression levels <= 3.
+
+ ///
+ /// The compression level (1..9)
+ ///
+ private CompressionLevel level;
+
+ ///
+ /// The favor or force Huffman coding
+ ///
+ private CompressionStrategy strategy;
+
+ ///
+ /// Use a faster search when the previous match is longer than this
+ ///
+ private int good_match;
+
+ ///
+ /// Stop searching when current match exceeds this
+ ///
+ private int nice_match;
+
+ ///
+ /// literal and length tree
+ ///
+ private short[] dyn_ltree;
+
+ ///
+ /// The distance tree
+ ///
+ private short[] dyn_dtree;
+
+ ///
+ /// The Huffman tree for bit lengths
+ ///
+ private short[] bl_tree;
+
+ ///
+ /// The desc for literal tree
+ ///
+ private Tree l_desc = new Tree();
+
+ ///
+ /// The desc for distance tree
+ ///
+ private Tree d_desc = new Tree();
+
+ ///
+ /// The desc for bit length tree
+ ///
+ private Tree bl_desc = new Tree();
+
+ ///
+ /// index for literals or lengths
+ ///
+ private int l_buf;
+
+ ///
+ /// Size of match buffer for literals/lengths. There are 4 reasons for
+ /// limiting lit_bufsize to 64K:
+ /// - frequencies can be kept in 16 bit counters
+ /// - if compression is not successful for the first block, all input
+ /// data is still in the window so we can still emit a stored block even
+ /// when input comes from standard input. (This can also be done for
+ /// all blocks if lit_bufsize is not greater than 32K.)
+ /// - if compression is not successful for a file smaller than 64K, we can
+ /// even emit a stored file instead of a stored block (saving 5 bytes).
+ /// This is applicable only for zip (not gzip or zlib).
+ /// - creating new Huffman trees less frequently may not provide fast
+ /// adaptation to changes in the input data statistics. (Take for
+ /// example a binary file with poorly compressible code followed by
+ /// a highly compressible string table.) Smaller buffer sizes give
+ /// fast adaptation but have of course the overhead of transmitting
+ /// trees more frequently.
+ /// - I can't count above 4
+ ///
+ private int lit_bufsize;
+
+ ///
+ /// running index in l_buf
+ ///
+ private int last_lit;
+
+ // Buffer for distances. To simplify the code, d_buf and l_buf have
+ // the same number of elements. To use different lengths, an extra flag
+ // array would be necessary.
+
+ ///
+ /// The index of pendig_buf
+ ///
+ private int d_buf;
+
+ ///
+ /// The number of string matches in current block
+ ///
+ private int matches;
+
+ ///
+ /// The bit length of EOB code for last block
+ ///
+ private int last_eob_len;
+
+ ///
+ /// Output buffer. bits are inserted starting at the bottom (least
+ /// significant bits).
+ ///
+ private uint bi_buf;
+
+ ///
+ /// Number of valid bits in bi_buf. All bits above the last valid bit
+ /// are always zero.
+ ///
+ private int bi_valid;
+
+ ///
+ /// value of flush param for previous deflate call
+ ///
+ private FlushType last_flush;
+
+ ///
+ /// bit length of current block with optimal trees
+ ///
+ internal int opt_len;
+
+ ///
+ /// bit length of current block with static trees
+ ///
+ internal int static_len;
+
+ ///
+ /// The output still pending
+ ///
+ internal byte[] pending_buf;
+
+ ///
+ /// next pending byte to output to the stream
+ ///
+ internal int pending_out;
+
+ ///
+ /// nb of bytes in the pending buffer
+ ///
+ internal int pending;
+
+ ///
+ /// suppress zlib header and adler32
+ ///
+ internal int noheader;
+
+ ///
+ /// number of codes at each bit length for an optimal tree
+ ///
+ internal short[] bl_count = new short[MAX_BITS + 1];
+
+ ///
+ /// heap used to build the Huffman trees
+ ///
+ internal int[] heap = new int[2 * L_CODES + 1];
+
+ ///
+ /// The number of elements in the heap
+ ///
+ internal int heap_len;
+ ///
+ /// The element of largest frequency
+ ///
+ internal int heap_max;
+
+ // The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+ // The same heap array is used to build all trees.
+
+ ///
+ /// Depth of each subtree used as tie breaker for trees of equal frequency
+ ///
+ internal byte[] depth = new byte[2 * L_CODES + 1];
+
+ public Deflate()
+ {
+ dyn_ltree = new short[HEAP_SIZE * 2];
+ dyn_dtree = new short[(2 * D_CODES + 1) * 2]; // distance tree
+ bl_tree = new short[(2 * BL_CODES + 1) * 2]; // Huffman tree for bit lengths
+ }
+
+ public ZLibStatus deflateInit(ZStream strm, CompressionLevel level, int bits)
+ {
+ return deflateInit2(strm, level, Z_DEFLATED, bits, DEF_MEM_LEVEL,
+ CompressionStrategy.Z_DEFAULT_STRATEGY);
+ }
+
+ public ZLibStatus deflateEnd()
+ {
+ if (status != INIT_STATE && status != BUSY_STATE && status != FINISH_STATE)
+ {
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+ // Deallocate in reverse order of allocations:
+ pending_buf = null;
+ head = null;
+ prev = null;
+ window = null;
+ // free
+ // dstate=null;
+ return status == BUSY_STATE ? ZLibStatus.Z_DATA_ERROR : ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus deflateParams(ZStream strm, CompressionLevel _level, CompressionStrategy _strategy)
+ {
+ var err = ZLibStatus.Z_OK;
+
+ if (_level == CompressionLevel.Z_DEFAULT_COMPRESSION)
+ {
+ _level = (CompressionLevel)6;
+ }
+ if (_level < 0 || _level > (CompressionLevel)9 ||
+ _strategy < 0 || _strategy > CompressionStrategy.Z_HUFFMAN_ONLY)
+ {
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+
+ if (_configurationTable[level].Function != _configurationTable[_level].Function &&
+ strm.total_in != 0)
+ {
+ // Flush the last buffer:
+ err = strm.deflate(FlushType.Z_PARTIAL_FLUSH);
+ }
+
+ if (level != _level)
+ {
+ level = _level;
+ max_lazy_match = _configurationTable[level].MaxLazy;
+ good_match = _configurationTable[level].GoodLength;
+ nice_match = _configurationTable[level].NiceLength;
+ max_chain_length = _configurationTable[level].MaxChain;
+ }
+ strategy = _strategy;
+ return err;
+ }
+
+ public ZLibStatus deflateSetDictionary(ZStream strm, byte[] dictionary, int dictLength)
+ {
+ int length = dictLength;
+ int index = 0;
+
+ if (dictionary == null || status != INIT_STATE)
+ return ZLibStatus.Z_STREAM_ERROR;
+
+ //strm.adler = strm.Adler32(strm.adler, dictionary, 0, dictLength);
+ strm.UpdateAdler(dictionary, 0, dictLength);
+
+
+ if (length < MIN_MATCH) return ZLibStatus.Z_OK;
+ if (length > w_size - MIN_LOOKAHEAD)
+ {
+ length = w_size - MIN_LOOKAHEAD;
+ index = dictLength - length; // use the tail of the dictionary
+ }
+ System.Array.Copy(dictionary, index, window, 0, length);
+ strstart = length;
+ block_start = length;
+
+ // Insert all strings in the hash table (except for the last two bytes).
+ // s->lookahead stays null, so s->ins_h will be recomputed at the next
+ // call of fill_window.
+
+ ins_h = window[0] & 0xff;
+ ins_h = (((ins_h) << hash_shift) ^ (window[1] & 0xff)) & hash_mask;
+
+ for (int n = 0; n <= length - MIN_MATCH; n++)
+ {
+ ins_h = (((ins_h) << hash_shift) ^ (window[(n) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;
+ prev[n & w_mask] = head[ins_h];
+ head[ins_h] = (short)n;
+ }
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus deflate(ZStream strm, FlushType flush)
+ {
+ FlushType old_flush;
+
+ if (flush > FlushType.Z_FINISH || flush < 0)
+ {
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+
+ if (strm.next_out == null ||
+ (strm.next_in == null && strm.avail_in != 0) ||
+ (status == FINISH_STATE && flush != FlushType.Z_FINISH))
+ {
+ strm.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_STREAM_ERROR)];
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+ if (strm.avail_out == 0)
+ {
+ strm.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_BUF_ERROR)];
+ return ZLibStatus.Z_BUF_ERROR;
+ }
+
+ this.strm = strm; // just in case
+ old_flush = last_flush;
+ last_flush = flush;
+
+ // Write the zlib header
+ if (status == INIT_STATE)
+ {
+ int header = (Z_DEFLATED + ((w_bits - 8) << 4)) << 8;
+ int level_flags = (((int)level - 1) & 0xff) >> 1;
+
+ if (level_flags > 3) level_flags = 3;
+ header |= (level_flags << 6);
+ if (strstart != 0) header |= PRESET_DICT;
+ header += 31 - (header % 31);
+
+ status = BUSY_STATE;
+ putShortMSB(header);
+
+
+ // Save the adler32 of the preset dictionary:
+ if (strstart != 0)
+ {
+ putShortMSB((int)(strm.Adler >> 16));
+ putShortMSB((int)(strm.Adler & 0xffff));
+ }
+ //strm.adler = strm.Adler32(0, null, 0, 0);
+ strm.UpdateAdler(0, null, 0, 0);
+ }
+
+ // Flush as much pending output as possible
+ if (pending != 0)
+ {
+ strm.flush_pending();
+ if (strm.avail_out == 0)
+ {
+ //System.out.println(" avail_out==0");
+ // Since avail_out is 0, deflate will be called again with
+ // more output space, but possibly with both pending and
+ // avail_in equal to zero. There won't be anything to do,
+ // but this is not an error situation so make sure we
+ // return OK instead of BUF_ERROR at next call of deflate:
+ last_flush = (FlushType)(-1);
+ return ZLibStatus.Z_OK;
+ }
+
+ // Make sure there is something to do and avoid duplicate consecutive
+ // flushes. For repeated and useless calls with FlushType.Z_FINISH, we keep
+ // returning ZLibStatus.Z_STREAM_END instead of Z_BUFF_ERROR.
+ }
+ else if (strm.avail_in == 0 && flush <= old_flush &&
+ flush != FlushType.Z_FINISH)
+ {
+ strm.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_BUF_ERROR)];
+ return ZLibStatus.Z_BUF_ERROR;
+ }
+
+ // User must not provide more input after the first FINISH:
+ if (status == FINISH_STATE && strm.avail_in != 0)
+ {
+ strm.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_BUF_ERROR)];
+ return ZLibStatus.Z_BUF_ERROR;
+ }
+
+ // Start a new block or continue the current one.
+ if (strm.avail_in != 0 || lookahead != 0 ||
+ (flush != FlushType.Z_NO_FLUSH && status != FINISH_STATE))
+ {
+ int bstate = -1;
+ switch (_configurationTable[level].Function)
+ {
+ case STORED:
+ bstate = deflate_stored(flush);
+ break;
+ case FAST:
+ bstate = deflate_fast(flush);
+ break;
+ case SLOW:
+ bstate = deflate_slow(flush);
+ break;
+ default:
+ break;
+ }
+
+ if (bstate == FinishStarted || bstate == FinishDone)
+ {
+ status = FINISH_STATE;
+ }
+ if (bstate == NeedMore || bstate == FinishStarted)
+ {
+ if (strm.avail_out == 0)
+ {
+ last_flush = (FlushType)(-1); // avoid BUF_ERROR next call, see above
+ }
+ return ZLibStatus.Z_OK;
+ // If flush != FlushType.Z_NO_FLUSH && avail_out == 0, the next call
+ // of deflate should use the same flush parameter to make sure
+ // that the flush is complete. So we don't have to output an
+ // empty block here, this will be done at next call. This also
+ // ensures that for a very small output buffer, we emit at most
+ // one empty block.
+ }
+
+ if (bstate == BlockDone)
+ {
+ if (flush == FlushType.Z_PARTIAL_FLUSH)
+ {
+ _tr_align();
+ }
+ else
+ { // FULL_FLUSH or SYNC_FLUSH
+ _tr_stored_block(0, 0, false);
+ // For a full flush, this empty block will be recognized
+ // as a special marker by inflate_sync().
+ if (flush == FlushType.Z_FULL_FLUSH)
+ {
+ //state.head[s.hash_size-1]=0;
+ for (int i = 0; i < hash_size/*-1*/; i++) // forget history
+ head[i] = 0;
+ }
+ }
+ strm.flush_pending();
+ if (strm.avail_out == 0)
+ {
+ last_flush = (FlushType)(-1); // avoid BUF_ERROR at next call, see above
+ return ZLibStatus.Z_OK;
+ }
+ }
+ }
+
+ if (flush != FlushType.Z_FINISH) return ZLibStatus.Z_OK;
+ if (noheader != 0) return ZLibStatus.Z_STREAM_END;
+
+ // Write the zlib trailer (adler32)
+ putShortMSB((int)(strm.Adler >> 16));
+ putShortMSB((int)(strm.Adler & 0xffff));
+ strm.flush_pending();
+
+ // If avail_out is zero, the application will call deflate again
+ // to flush the rest.
+ noheader = -1; // write the trailer only once!
+ return pending != 0 ? ZLibStatus.Z_OK : ZLibStatus.Z_STREAM_END;
+ }
+
+ private void lm_init()
+ {
+ window_size = 2 * w_size;
+
+ head[hash_size - 1] = 0;
+ for (int i = 0; i < hash_size - 1; i++)
+ {
+ head[i] = 0;
+ }
+
+ // Set the default configuration parameters:
+ max_lazy_match = Deflate._configurationTable[level].MaxLazy;
+ good_match = Deflate._configurationTable[level].GoodLength;
+ nice_match = Deflate._configurationTable[level].NiceLength;
+ max_chain_length = Deflate._configurationTable[level].MaxChain;
+
+ strstart = 0;
+ block_start = 0;
+ lookahead = 0;
+ match_length = prev_length = MIN_MATCH - 1;
+ match_available = 0;
+ ins_h = 0;
+ }
+
+ ///
+ /// Initialize the tree data structures for a new zlib stream.
+ ///
+ private void tr_init()
+ {
+
+ //l_desc.dyn_tree = dyn_ltree;
+ //l_desc.stat_desc = Deflate.static_l_desc;
+ l_desc.Init(dyn_ltree, Deflate.static_l_desc);
+
+ //d_desc.dyn_tree = dyn_dtree;
+ //d_desc.stat_desc = Deflate.static_d_desc;
+ d_desc.Init(dyn_ltree, Deflate.static_l_desc);
+
+ //bl_desc.dyn_tree = bl_tree;
+ //bl_desc.stat_desc = Deflate.static_bl_desc;
+ bl_desc.Init(dyn_ltree, Deflate.static_l_desc);
+
+ bi_buf = 0;
+ bi_valid = 0;
+ last_eob_len = 8; // enough lookahead for inflate
+
+ // Initialize the first block of the first file:
+ init_block();
+ }
+
+ private void init_block()
+ {
+ // Initialize the trees.
+ for (int i = 0; i < L_CODES; i++) dyn_ltree[i * 2] = 0;
+ for (int i = 0; i < D_CODES; i++) dyn_dtree[i * 2] = 0;
+ for (int i = 0; i < BL_CODES; i++) bl_tree[i * 2] = 0;
+
+ dyn_ltree[END_BLOCK * 2] = 1;
+ opt_len = static_len = 0;
+ last_lit = matches = 0;
+ }
+
+ ///
+ /// Restore the heap property by moving down the tree starting at node k,
+ /// exchanging a node with the smallest of its two sons if necessary, stopping
+ /// when the heap property is re-established (each father smaller than its
+ /// two sons).
+ ///
+ /// The tree to restore.
+ /// The node to move down.
+ public void pqdownheap(short[] tree, int k)
+ {
+ int v = heap[k];
+ int j = k << 1; // left son of k
+ while (j <= heap_len)
+ {
+ // Set j to the smallest of the two sons:
+ if (j < heap_len &&
+ smaller(tree, heap[j + 1], heap[j], depth))
+ {
+ j++;
+ }
+ // Exit if v is smaller than both sons
+ if (smaller(tree, v, heap[j], depth)) break;
+
+ // Exchange v with the smallest son
+ heap[k] = heap[j]; k = j;
+ // And continue down the tree, setting j to the left son of k
+ j <<= 1;
+ }
+ heap[k] = v;
+ }
+
+ private static bool smaller(short[] tree, int n, int m, byte[] depth)
+ {
+ short tn2 = tree[n * 2];
+ short tm2 = tree[m * 2];
+ return (tn2 < tm2 ||
+ (tn2 == tm2 && depth[n] <= depth[m]));
+ }
+
+ ///
+ /// Scan a literal or distance tree to determine the frequencies of the codes
+ /// in the bit length tree.
+ ///
+ /// The tree to be scanned.
+ /// The largest code of non zero frequency.
+ private void scan_tree(short[] tree, int max_code)
+ {
+ int n; // iterates over all tree elements
+ int prevlen = -1; // last emitted length
+ int curlen; // length of current code
+ int nextlen = tree[0 * 2 + 1]; // length of next code
+ int count = 0; // repeat count of the current code
+ int max_count = 7; // max repeat count
+ int min_count = 4; // min repeat count
+
+ if (nextlen == 0) { max_count = 138; min_count = 3; }
+ tree[(max_code + 1) * 2 + 1] = -1; // guard
+
+ for (n = 0; n <= max_code; n++)
+ {
+ curlen = nextlen; nextlen = tree[(n + 1) * 2 + 1];
+ if (++count < max_count && curlen == nextlen)
+ {
+ continue;
+ }
+ else if (count < min_count)
+ {
+ bl_tree[curlen * 2] += (short)count;
+ }
+ else if (curlen != 0)
+ {
+ if (curlen != prevlen) bl_tree[curlen * 2]++;
+ bl_tree[REP_3_6 * 2]++;
+ }
+ else if (count <= 10)
+ {
+ bl_tree[REPZ_3_10 * 2]++;
+ }
+ else
+ {
+ bl_tree[REPZ_11_138 * 2]++;
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0)
+ {
+ max_count = 138; min_count = 3;
+ }
+ else if (curlen == nextlen)
+ {
+ max_count = 6; min_count = 3;
+ }
+ else
+ {
+ max_count = 7; min_count = 4;
+ }
+ }
+ }
+
+ ///
+ /// Construct the Huffman tree for the bit lengths and return the index in
+ /// bl_order of the last bit length code to send.
+ ///
+ ///
+ private int build_bl_tree()
+ {
+ int max_blindex; // index of last bit length code of non zero freq
+
+ // Determine the bit length frequencies for literal and distance trees
+ scan_tree(dyn_ltree, l_desc.LargestCode);
+ scan_tree(dyn_dtree, d_desc.LargestCode);
+
+ // Build the bit length tree:
+ bl_desc.BuildTree(this);
+ // opt_len now includes the length of the tree representations, except
+ // the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
+
+ // Determine the number of bit length codes to send. The pkzip format
+ // requires that at least 4 bit length codes be sent. (appnote.txt says
+ // 3 but the actual value used is 4.)
+ for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--)
+ {
+ if (bl_tree[Deflate.BLOrder[max_blindex] * 2 + 1] != 0) break;
+ }
+ // Update opt_len to include the bit length tree and counts
+ opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4;
+
+ return max_blindex;
+ }
+
+ ///
+ /// Send the header for a block using dynamic Huffman trees: the counts, the
+ /// lengths of the bit length codes, the literal tree and the distance tree.
+ ///
+ /// The lcodes.
+ /// The dcodes.
+ /// The blcodes.
+ private void send_all_trees(int lcodes, int dcodes, int blcodes)
+ {
+ int rank; // index in bl_order
+
+ send_bits(lcodes - 257, 5); // not +255 as stated in appnote.txt
+ send_bits(dcodes - 1, 5);
+ send_bits(blcodes - 4, 4); // not -3 as stated in appnote.txt
+ for (rank = 0; rank < blcodes; rank++)
+ {
+ send_bits(bl_tree[Deflate.BLOrder[rank] * 2 + 1], 3);
+ }
+ send_tree(dyn_ltree, lcodes - 1); // literal tree
+ send_tree(dyn_dtree, dcodes - 1); // distance tree
+ }
+
+ ///
+ /// Send a literal or distance tree in compressed form, using the codes in
+ /// bl_tree.
+ ///
+ /// The tree to be sent.
+ /// The largest code of non zero frequency.
+ private void send_tree(short[] tree, int max_code)
+ {
+ int n; // iterates over all tree elements
+ int prevlen = -1; // last emitted length
+ int curlen; // length of current code
+ int nextlen = tree[0 * 2 + 1]; // length of next code
+ int count = 0; // repeat count of the current code
+ int max_count = 7; // max repeat count
+ int min_count = 4; // min repeat count
+
+ if (nextlen == 0) { max_count = 138; min_count = 3; }
+
+ for (n = 0; n <= max_code; n++)
+ {
+ curlen = nextlen; nextlen = tree[(n + 1) * 2 + 1];
+ if (++count < max_count && curlen == nextlen)
+ {
+ continue;
+ }
+ else if (count < min_count)
+ {
+ do { send_code(curlen, bl_tree); } while (--count != 0);
+ }
+ else if (curlen != 0)
+ {
+ if (curlen != prevlen)
+ {
+ send_code(curlen, bl_tree); count--;
+ }
+ send_code(REP_3_6, bl_tree);
+ send_bits(count - 3, 2);
+ }
+ else if (count <= 10)
+ {
+ send_code(REPZ_3_10, bl_tree);
+ send_bits(count - 3, 3);
+ }
+ else
+ {
+ send_code(REPZ_11_138, bl_tree);
+ send_bits(count - 11, 7);
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0)
+ {
+ max_count = 138; min_count = 3;
+ }
+ else if (curlen == nextlen)
+ {
+ max_count = 6; min_count = 3;
+ }
+ else
+ {
+ max_count = 7; min_count = 4;
+ }
+ }
+ }
+
+ ///
+ /// Output a byte on the stream.
+ ///
+ /// The p.
+ /// The start.
+ /// The len.
+ private void put_byte(byte[] p, int start, int len)
+ {
+ System.Array.Copy(p, start, pending_buf, pending, len);
+ pending += len;
+ }
+
+ private void put_short(int w)
+ {
+ pending_buf[pending++] = (byte)(w/*&0xff*/);
+ pending_buf[pending++] = (byte)(w >> 8);
+ }
+
+ private void putShortMSB(int b)
+ {
+ pending_buf[pending++] = (byte)(b >> 8);
+ pending_buf[pending++] = (byte)(b/*&0xff*/);
+ }
+
+ private void send_code(int c, short[] tree)
+ {
+ int c2 = c * 2;
+ send_bits((tree[c2] & 0xffff), (tree[c2 + 1] & 0xffff));
+ }
+
+ private void send_bits(int val, int length)
+ {
+ if (bi_valid > Buf_size - length)
+ {
+ bi_buf |= (uint)(val << bi_valid);
+ pending_buf[pending++] = (byte)(bi_buf/*&0xff*/);
+ pending_buf[pending++] = (byte)(bi_buf >> 8);
+ bi_buf = ((uint)val) >> (Buf_size - bi_valid);
+ bi_valid += length - Buf_size;
+ }
+ else
+ {
+ bi_buf |= (uint)(val << bi_valid);
+ bi_valid += length;
+ }
+ // int len = length;
+ // if (bi_valid > (int)Buf_size - len) {
+ // int val = value;
+ // // bi_buf |= (val << bi_valid);
+ // bi_buf = (short)((ushort)bi_buf | (ushort)((val << bi_valid)&0xffff));
+ // put_short(bi_buf);
+ // bi_buf = (short)(((uint)val) >> (Buf_size - bi_valid));
+ // bi_valid += len - Buf_size;
+ // } else {
+ // // bi_buf |= (value) << bi_valid;
+ // bi_buf = (short)((ushort)bi_buf | (ushort)(((value) << bi_valid)&0xffff));
+ // bi_valid += len;
+ // }
+ }
+
+ ///
+ /// Send one empty static block to give enough lookahead for inflate.
+ /// This takes 10 bits, of which 7 may remain in the bit buffer.
+ /// The current inflate code requires 9 bits of lookahead. If the
+ /// last two codes for the previous block (real code plus EOB) were coded
+ /// on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
+ /// the last real code. In this case we send two empty static blocks instead
+ /// of one. (There are no problems if the previous block is stored or fixed.)
+ /// To simplify the code, we assume the worst case of last real code encoded
+ /// on one bit only.
+ ///
+ private void _tr_align()
+ {
+ send_bits(STATIC_TREES << 1, 3);
+ send_code(END_BLOCK, Deflate.static_ltree);
+
+ bi_flush();
+
+ // Of the 10 bits for the empty block, we have already sent
+ // (10 - bi_valid) bits. The lookahead for the last real code (before
+ // the EOB of the previous block) was thus at least one plus the length
+ // of the EOB plus what we have just sent of the empty static block.
+ if (1 + last_eob_len + 10 - bi_valid < 9)
+ {
+ send_bits(STATIC_TREES << 1, 3);
+ send_code(END_BLOCK, Deflate.static_ltree);
+ bi_flush();
+ }
+ last_eob_len = 7;
+ }
+
+ ///
+ /// Save the match info and tally the frequency counts. Return true if
+ /// the current block must be flushed.
+ ///
+ /// The distance of matched string.
+ /// The match length-MIN_MATCH or unmatched char (if dist==0).
+ ///
+ private bool _tr_tally(int dist, int lc)
+ {
+
+ pending_buf[d_buf + last_lit * 2] = (byte)(dist >> 8);
+ pending_buf[d_buf + last_lit * 2 + 1] = (byte)dist;
+
+ pending_buf[l_buf + last_lit] = (byte)lc; last_lit++;
+
+ if (dist == 0)
+ {
+ // lc is the unmatched char
+ dyn_ltree[lc * 2]++;
+ }
+ else
+ {
+ matches++;
+ // Here, lc is the match length - MIN_MATCH
+ dist--; // dist = match distance - 1
+ dyn_ltree[(_lengthCode[lc] + LITERALS + 1) * 2]++;
+ dyn_dtree[Tree.DistanceCode(dist) * 2]++;
+ }
+
+ if ((last_lit & 0x1fff) == 0 && level > (CompressionLevel)2)
+ {
+ // Compute an upper bound for the compressed length
+ int out_length = last_lit * 8;
+ int in_length = strstart - block_start;
+ int dcode;
+ for (dcode = 0; dcode < D_CODES; dcode++)
+ {
+ out_length += (int)((int)dyn_dtree[dcode * 2] *
+ (5L + Deflate.ExtraDBits[dcode]));
+ }
+ out_length >>= 3;
+ if ((matches < (last_lit / 2)) && out_length < in_length / 2) return true;
+ }
+
+ return (last_lit == lit_bufsize - 1);
+ // We avoid equality with lit_bufsize because of wraparound at 64K
+ // on 16 bit machines and because stored blocks are restricted to
+ // 64K-1 bytes.
+ }
+
+ ///
+ /// Send the block data compressed using the given Huffman trees
+ ///
+ /// The ltree.
+ /// The dtree.
+ private void compress_block(short[] ltree, short[] dtree)
+ {
+ int dist; // distance of matched string
+ int lc; // match length or unmatched char (if dist == 0)
+ int lx = 0; // running index in l_buf
+ int code; // the code to send
+ int extra; // number of extra bits to send
+
+ if (last_lit != 0)
+ {
+ do
+ {
+ dist = ((pending_buf[d_buf + lx * 2] << 8) & 0xff00) |
+ (pending_buf[d_buf + lx * 2 + 1] & 0xff);
+ lc = (pending_buf[l_buf + lx]) & 0xff; lx++;
+
+ if (dist == 0)
+ {
+ send_code(lc, ltree); // send a literal byte
+ }
+ else
+ {
+ // Here, lc is the match length - MIN_MATCH
+ code = _lengthCode[lc];
+
+ send_code(code + LITERALS + 1, ltree); // send the length code
+ extra = Deflate.ExtraLBits[code];
+ if (extra != 0)
+ {
+ lc -= _baseLength[code];
+ send_bits(lc, extra); // send the extra length bits
+ }
+ dist--; // dist is now the match distance - 1
+ code = Tree.DistanceCode(dist);
+
+ send_code(code, dtree); // send the distance code
+ extra = Deflate.ExtraDBits[code];
+ if (extra != 0)
+ {
+ dist -= _baseDistance[code];
+ send_bits(dist, extra); // send the extra distance bits
+ }
+ } // literal or match pair ?
+
+ // Check that the overlay between pending_buf and d_buf+l_buf is ok:
+ }
+ while (lx < last_lit);
+ }
+
+ send_code(END_BLOCK, ltree);
+ last_eob_len = ltree[END_BLOCK * 2 + 1];
+ }
+
+ ///
+ /// Set the data type to ASCII or BINARY, using a crude approximation:
+ /// binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise.
+ /// IN assertion: the fields freq of dyn_ltree are set and the total of all
+ /// frequencies does not exceed 64K (to fit in an int on 16 bit machines).
+ ///
+ private void set_data_type()
+ {
+ int n = 0;
+ int ascii_freq = 0;
+ int bin_freq = 0;
+ while (n < 7) { bin_freq += dyn_ltree[n * 2]; n++; }
+ while (n < 128) { ascii_freq += dyn_ltree[n * 2]; n++; }
+ while (n < LITERALS) { bin_freq += dyn_ltree[n * 2]; n++; }
+ _dataType = (bin_freq > (ascii_freq >> 2) ? BlockType.Z_BINARY : BlockType.Z_ASCII);
+ }
+
+ ///
+ /// Flush the bit buffer, keeping at most 7 bits in it.
+ ///
+ private void bi_flush()
+ {
+ if (bi_valid == 16)
+ {
+ pending_buf[pending++] = (byte)(bi_buf/*&0xff*/);
+ pending_buf[pending++] = (byte)(bi_buf >> 8);
+ bi_buf = 0;
+ bi_valid = 0;
+ }
+ else if (bi_valid >= 8)
+ {
+ pending_buf[pending++] = (byte)(bi_buf);
+ bi_buf >>= 8;
+ bi_buf &= 0x00ff;
+ bi_valid -= 8;
+ }
+ }
+
+ ///
+ /// Flush the bit buffer and align the output on a byte boundary
+ ///
+ private void bi_windup()
+ {
+ if (bi_valid > 8)
+ {
+ pending_buf[pending++] = (byte)(bi_buf);
+ pending_buf[pending++] = (byte)(bi_buf >> 8);
+ }
+ else if (bi_valid > 0)
+ {
+ pending_buf[pending++] = (byte)(bi_buf);
+ }
+ bi_buf = 0;
+ bi_valid = 0;
+ }
+
+ ///
+ /// Copy a stored block, storing first the length and its
+ /// one's complement if requested.
+ ///
+ /// The input data.
+ /// The length.
+ /// if set to true block header must be written.
+ private void copy_block(int buf, int len, bool header)
+ {
+ //int index=0;
+ bi_windup(); // align on byte boundary
+ last_eob_len = 8; // enough lookahead for inflate
+
+ if (header)
+ {
+ put_short((short)len);
+ put_short((short)~len);
+ }
+
+ // while(len--!=0) {
+ // put_byte(window[buf+index]);
+ // index++;
+ // }
+ put_byte(window, buf, len);
+ }
+
+ private void flush_block_only(bool eof)
+ {
+ _tr_flush_block(block_start >= 0 ? block_start : -1,
+ strstart - block_start,
+ eof);
+ block_start = strstart;
+ strm.flush_pending();
+ }
+
+ ///
+ /// Copy without compression as much as possible from the input stream, return
+ /// the current block state.
+ /// This function does not insert new strings in the dictionary since
+ /// uncompressible data is probably not useful. This function is used
+ /// only for the level=0 compression option.
+ ///
+ /// The flush.
+ ///
+ private int deflate_stored(FlushType flush)
+ {
+ // TODO: this function should be optimized to avoid extra copying from window to pending_buf.
+
+ // Stored blocks are limited to 0xffff bytes, pending_buf is limited
+ // to pending_buf_size, and each stored block has a 5 byte header:
+
+ int max_block_size = 0xffff;
+ int max_start;
+
+ if (max_block_size > pending_buf_size - 5)
+ {
+ max_block_size = pending_buf_size - 5;
+ }
+
+ // Copy as much as possible from input to output:
+ while (true)
+ {
+ // Fill the window as much as possible:
+ if (lookahead <= 1)
+ {
+ fill_window();
+ if (lookahead == 0 && flush == FlushType.Z_NO_FLUSH) return NeedMore;
+ if (lookahead == 0) break; // flush the current block
+ }
+
+ strstart += lookahead;
+ lookahead = 0;
+
+ // Emit a stored block if pending_buf will be full:
+ max_start = block_start + max_block_size;
+ if (strstart == 0 || strstart >= max_start)
+ {
+ // strstart == 0 is possible when wraparound on 16-bit machine
+ lookahead = (int)(strstart - max_start);
+ strstart = (int)max_start;
+
+ flush_block_only(false);
+ if (strm.avail_out == 0) return NeedMore;
+
+ }
+
+ // Flush if we may have to slide, otherwise block_start may become
+ // negative and the data will be gone:
+ if (strstart - block_start >= w_size - MIN_LOOKAHEAD)
+ {
+ flush_block_only(false);
+ if (strm.avail_out == 0) return NeedMore;
+ }
+ }
+
+ flush_block_only(flush == FlushType.Z_FINISH);
+ if (strm.avail_out == 0)
+ return (flush == FlushType.Z_FINISH) ? FinishStarted : NeedMore;
+
+ return flush == FlushType.Z_FINISH ? FinishDone : BlockDone;
+ }
+
+ ///
+ /// Send a stored block
+ ///
+ /// The input block.
+ /// The length of input block.
+ /// if set to true last block for a file.
+ private void _tr_stored_block(int buf, int stored_len, bool eof)
+ {
+ send_bits((STORED_BLOCK << 1) + (eof ? 1 : 0), 3); // send block type
+ copy_block(buf, stored_len, true); // with header
+ }
+
+ ///
+ /// Determine the best encoding for the current block: dynamic trees, static
+ /// trees or store, and output the encoded block to the zip file.
+ ///
+ /// The input block, or NULL if too old.
+ /// The length of input block.
+ /// if set to true the last block for a file.
+ private void _tr_flush_block(int buf, int stored_len, bool eof)
+ {
+ int opt_lenb, static_lenb;// opt_len and static_len in bytes
+ int max_blindex = 0; // index of last bit length code of non zero freq
+
+ // Build the Huffman trees unless a stored block is forced
+ if (level > 0)
+ {
+ // Check if the file is ascii or binary
+ if (_dataType == BlockType.Z_UNKNOWN) set_data_type();
+
+ // Construct the literal and distance trees
+ l_desc.BuildTree(this);
+
+ d_desc.BuildTree(this);
+
+ // At this point, opt_len and static_len are the total bit lengths of
+ // the compressed block data, excluding the tree representations.
+
+ // Build the bit length tree for the above two trees, and get the index
+ // in bl_order of the last bit length code to send.
+ max_blindex = build_bl_tree();
+
+ // Determine the best encoding. Compute first the block length in bytes
+ opt_lenb = (opt_len + 3 + 7) >> 3;
+ static_lenb = (static_len + 3 + 7) >> 3;
+
+ if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
+ }
+ else
+ {
+ opt_lenb = static_lenb = stored_len + 5; // force a stored block
+ }
+
+ if (stored_len + 4 <= opt_lenb && buf != -1)
+ {
+ // 4: two words for the lengths
+ // The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
+ // Otherwise we can't have processed more than WSIZE input bytes since
+ // the last block flush, because compression would have been
+ // successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
+ // transform a block into a stored block.
+ _tr_stored_block(buf, stored_len, eof);
+ }
+ else if (static_lenb == opt_lenb)
+ {
+ send_bits((STATIC_TREES << 1) + (eof ? 1 : 0), 3);
+ compress_block(Deflate.static_ltree, Deflate.static_dtree);
+ }
+ else
+ {
+ send_bits((DYN_TREES << 1) + (eof ? 1 : 0), 3);
+ send_all_trees(l_desc.LargestCode + 1, d_desc.LargestCode + 1, max_blindex + 1);
+ compress_block(dyn_ltree, dyn_dtree);
+ }
+
+ // The above check is made mod 2^32, for files larger than 512 MB
+ // and uLong implemented on 32 bits.
+
+ init_block();
+
+ if (eof)
+ {
+ bi_windup();
+ }
+ }
+
+ ///
+ /// Fill the window when the lookahead becomes insufficient.
+ /// Updates strstart and lookahead.
+ ///
+ private void fill_window()
+ {
+ int n, m;
+ int p;
+ int more; // Amount of free space at the end of the window.
+
+ do
+ {
+ more = (window_size - lookahead - strstart);
+
+ // Deal with !@#$% 64K limit:
+ if (more == 0 && strstart == 0 && lookahead == 0)
+ {
+ more = w_size;
+ }
+ else if (more == -1)
+ {
+ // Very unlikely, but possible on 16 bit machine if strstart == 0
+ // and lookahead == 1 (input done one byte at time)
+ more--;
+
+ // If the window is almost full and there is insufficient lookahead,
+ // move the upper half to the lower one to make room in the upper half.
+ }
+ else if (strstart >= w_size + w_size - MIN_LOOKAHEAD)
+ {
+ System.Array.Copy(window, w_size, window, 0, w_size);
+ match_start -= w_size;
+ strstart -= w_size; // we now have strstart >= MAX_DIST
+ block_start -= w_size;
+
+ // Slide the hash table (could be avoided with 32 bit values
+ // at the expense of memory usage). We slide even when level == 0
+ // to keep the hash table consistent if we switch back to level > 0
+ // later. (Using level 0 permanently is not an optimal usage of
+ // zlib, so we don't care about this pathological case.)
+
+ n = hash_size;
+ p = n;
+ do
+ {
+ m = (head[--p] & 0xffff);
+ head[p] = (short)(m >= w_size ? (m - w_size) : 0);
+ }
+ while (--n != 0);
+
+ n = w_size;
+ p = n;
+ do
+ {
+ m = (prev[--p] & 0xffff);
+ prev[p] = (short)(m >= w_size ? (m - w_size) : 0);
+ // If n is not on any hash chain, prev[n] is garbage but
+ // its value will never be used.
+ }
+ while (--n != 0);
+ more += w_size;
+ }
+
+ if (strm.avail_in == 0) return;
+
+ // If there was no sliding:
+ // strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
+ // more == window_size - lookahead - strstart
+ // => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
+ // => more >= window_size - 2*WSIZE + 2
+ // In the BIG_MEM or MMAP case (not yet supported),
+ // window_size == input_size + MIN_LOOKAHEAD &&
+ // strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
+ // Otherwise, window_size == 2*WSIZE so more >= 2.
+ // If there was sliding, more >= WSIZE. So in all cases, more >= 2.
+
+ n = strm.read_buf(window, strstart + lookahead, more);
+ lookahead += n;
+
+ // Initialize the hash value now that we have some input:
+ if (lookahead >= MIN_MATCH)
+ {
+ ins_h = window[strstart] & 0xff;
+ ins_h = (((ins_h) << hash_shift) ^ (window[strstart + 1] & 0xff)) & hash_mask;
+ }
+ // If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
+ // but this is not important since only literal bytes will be emitted.
+ }
+ while (lookahead < MIN_LOOKAHEAD && strm.avail_in != 0);
+ }
+
+ ///
+ /// Compress as much as possible from the input stream, return the current
+ /// block state.
+ /// This function does not perform lazy evaluation of matches and inserts
+ /// new strings in the dictionary only for unmatched strings or for short
+ /// matches. It is used only for the fast compression options.
+ ///
+ /// The flush.
+ ///
+ private int deflate_fast(FlushType flush)
+ {
+ // short hash_head = 0; // head of the hash chain
+ int hash_head = 0; // head of the hash chain
+ bool bflush; // set if current block must be flushed
+
+ while (true)
+ {
+ // Make sure that we always have enough lookahead, except
+ // at the end of the input file. We need MAX_MATCH bytes
+ // for the next match, plus MIN_MATCH bytes to insert the
+ // string following the next match.
+ if (lookahead < MIN_LOOKAHEAD)
+ {
+ fill_window();
+ if (lookahead < MIN_LOOKAHEAD && flush == FlushType.Z_NO_FLUSH)
+ {
+ return NeedMore;
+ }
+ if (lookahead == 0) break; // flush the current block
+ }
+
+ // Insert the string window[strstart .. strstart+2] in the
+ // dictionary, and set hash_head to the head of the hash chain:
+ if (lookahead >= MIN_MATCH)
+ {
+ ins_h = (((ins_h) << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;
+
+ // prev[strstart&w_mask]=hash_head=head[ins_h];
+ hash_head = (head[ins_h] & 0xffff);
+ prev[strstart & w_mask] = head[ins_h];
+ head[ins_h] = (short)strstart;
+ }
+
+ // Find the longest match, discarding those <= prev_length.
+ // At this point we have always match_length < MIN_MATCH
+
+ if (hash_head != 0L &&
+ ((strstart - hash_head) & 0xffff) <= w_size - MIN_LOOKAHEAD
+ )
+ {
+ // To simplify the code, we prevent matches with the string
+ // of window index 0 (in particular we have to avoid a match
+ // of the string with itself at the start of the input file).
+ if (strategy != CompressionStrategy.Z_HUFFMAN_ONLY)
+ {
+ match_length = longest_match(hash_head);
+ }
+ // longest_match() sets match_start
+ }
+ if (match_length >= MIN_MATCH)
+ {
+ // check_match(strstart, match_start, match_length);
+
+ bflush = _tr_tally(strstart - match_start, match_length - MIN_MATCH);
+
+ lookahead -= match_length;
+
+ // Insert new strings in the hash table only if the match length
+ // is not too large. This saves time but degrades compression.
+ if (match_length <= max_lazy_match &&
+ lookahead >= MIN_MATCH)
+ {
+ match_length--; // string at strstart already in hash table
+ do
+ {
+ strstart++;
+
+ ins_h = ((ins_h << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;
+ // prev[strstart&w_mask]=hash_head=head[ins_h];
+ hash_head = (head[ins_h] & 0xffff);
+ prev[strstart & w_mask] = head[ins_h];
+ head[ins_h] = (short)strstart;
+
+ // strstart never exceeds WSIZE-MAX_MATCH, so there are
+ // always MIN_MATCH bytes ahead.
+ }
+ while (--match_length != 0);
+ strstart++;
+ }
+ else
+ {
+ strstart += match_length;
+ match_length = 0;
+ ins_h = window[strstart] & 0xff;
+
+ ins_h = (((ins_h) << hash_shift) ^ (window[strstart + 1] & 0xff)) & hash_mask;
+ // If lookahead < MIN_MATCH, ins_h is garbage, but it does not
+ // matter since it will be recomputed at next deflate call.
+ }
+ }
+ else
+ {
+ // No match, output a literal byte
+
+ bflush = _tr_tally(0, window[strstart] & 0xff);
+ lookahead--;
+ strstart++;
+ }
+ if (bflush)
+ {
+
+ flush_block_only(false);
+ if (strm.avail_out == 0) return NeedMore;
+ }
+ }
+
+ flush_block_only(flush == FlushType.Z_FINISH);
+ if (strm.avail_out == 0)
+ {
+ if (flush == FlushType.Z_FINISH) return FinishStarted;
+ else return NeedMore;
+ }
+ return flush == FlushType.Z_FINISH ? FinishDone : BlockDone;
+ }
+
+ ///
+ /// Same as above, but achieves better compression. We use a lazy
+ /// evaluation for matches: a match is finally adopted only if there is
+ /// no better match at the next window position.
+ ///
+ /// The flush.
+ ///
+ private int deflate_slow(FlushType flush)
+ {
+ // short hash_head = 0; // head of hash chain
+ int hash_head = 0; // head of hash chain
+ bool bflush; // set if current block must be flushed
+
+ // Process the input block.
+ while (true)
+ {
+ // Make sure that we always have enough lookahead, except
+ // at the end of the input file. We need MAX_MATCH bytes
+ // for the next match, plus MIN_MATCH bytes to insert the
+ // string following the next match.
+
+ if (lookahead < MIN_LOOKAHEAD)
+ {
+ fill_window();
+ if (lookahead < MIN_LOOKAHEAD && flush == FlushType.Z_NO_FLUSH)
+ {
+ return NeedMore;
+ }
+ if (lookahead == 0) break; // flush the current block
+ }
+
+ // Insert the string window[strstart .. strstart+2] in the
+ // dictionary, and set hash_head to the head of the hash chain:
+
+ if (lookahead >= MIN_MATCH)
+ {
+ ins_h = (((ins_h) << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;
+ // prev[strstart&w_mask]=hash_head=head[ins_h];
+ hash_head = (head[ins_h] & 0xffff);
+ prev[strstart & w_mask] = head[ins_h];
+ head[ins_h] = (short)strstart;
+ }
+
+ // Find the longest match, discarding those <= prev_length.
+ prev_length = match_length; prev_match = match_start;
+ match_length = MIN_MATCH - 1;
+
+ if (hash_head != 0 && prev_length < max_lazy_match &&
+ ((strstart - hash_head) & 0xffff) <= w_size - MIN_LOOKAHEAD
+ )
+ {
+ // To simplify the code, we prevent matches with the string
+ // of window index 0 (in particular we have to avoid a match
+ // of the string with itself at the start of the input file).
+
+ if (strategy != CompressionStrategy.Z_HUFFMAN_ONLY)
+ {
+ match_length = longest_match(hash_head);
+ }
+ // longest_match() sets match_start
+
+ if (match_length <= 5 && (strategy == CompressionStrategy.Z_FILTERED ||
+ (match_length == MIN_MATCH &&
+ strstart - match_start > 4096)))
+ {
+
+ // If prev_match is also MIN_MATCH, match_start is garbage
+ // but we will ignore the current match anyway.
+ match_length = MIN_MATCH - 1;
+ }
+ }
+
+ // If there was a match at the previous step and the current
+ // match is not better, output the previous match:
+ if (prev_length >= MIN_MATCH && match_length <= prev_length)
+ {
+ int max_insert = strstart + lookahead - MIN_MATCH;
+ // Do not insert strings in hash table beyond this.
+
+ // check_match(strstart-1, prev_match, prev_length);
+
+ bflush = _tr_tally(strstart - 1 - prev_match, prev_length - MIN_MATCH);
+
+ // Insert in hash table all strings up to the end of the match.
+ // strstart-1 and strstart are already inserted. If there is not
+ // enough lookahead, the last two strings are not inserted in
+ // the hash table.
+ lookahead -= prev_length - 1;
+ prev_length -= 2;
+ do
+ {
+ if (++strstart <= max_insert)
+ {
+ ins_h = (((ins_h) << hash_shift) ^ (window[(strstart) + (MIN_MATCH - 1)] & 0xff)) & hash_mask;
+ //prev[strstart&w_mask]=hash_head=head[ins_h];
+ hash_head = (head[ins_h] & 0xffff);
+ prev[strstart & w_mask] = head[ins_h];
+ head[ins_h] = (short)strstart;
+ }
+ }
+ while (--prev_length != 0);
+ match_available = 0;
+ match_length = MIN_MATCH - 1;
+ strstart++;
+
+ if (bflush)
+ {
+ flush_block_only(false);
+ if (strm.avail_out == 0) return NeedMore;
+ }
+ }
+ else if (match_available != 0)
+ {
+
+ // If there was no match at the previous position, output a
+ // single literal. If there was a match but the current match
+ // is longer, truncate the previous match to a single literal.
+
+ bflush = _tr_tally(0, window[strstart - 1] & 0xff);
+
+ if (bflush)
+ {
+ flush_block_only(false);
+ }
+ strstart++;
+ lookahead--;
+ if (strm.avail_out == 0) return NeedMore;
+ }
+ else
+ {
+ // There is no previous match to compare with, wait for
+ // the next step to decide.
+
+ match_available = 1;
+ strstart++;
+ lookahead--;
+ }
+ }
+
+ if (match_available != 0)
+ {
+ bflush = _tr_tally(0, window[strstart - 1] & 0xff);
+ match_available = 0;
+ }
+ flush_block_only(flush == FlushType.Z_FINISH);
+
+ if (strm.avail_out == 0)
+ {
+ if (flush == FlushType.Z_FINISH) return FinishStarted;
+ else return NeedMore;
+ }
+
+ return flush == FlushType.Z_FINISH ? FinishDone : BlockDone;
+ }
+
+ private int longest_match(int cur_match)
+ {
+ int chain_length = max_chain_length; // max hash chain length
+ int scan = strstart; // current string
+ int match; // matched string
+ int len; // length of current match
+ int best_len = prev_length; // best match length so far
+ int limit = strstart > (w_size - MIN_LOOKAHEAD) ?
+ strstart - (w_size - MIN_LOOKAHEAD) : 0;
+ int nice_match = this.nice_match;
+
+ // Stop when cur_match becomes <= limit. To simplify the code,
+ // we prevent matches with the string of window index 0.
+
+ int wmask = w_mask;
+
+ int strend = strstart + MAX_MATCH;
+ byte scan_end1 = window[scan + best_len - 1];
+ byte scan_end = window[scan + best_len];
+
+ // The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+ // It is easy to get rid of this optimization if necessary.
+
+ // Do not waste too much time if we already have a good match:
+ if (prev_length >= good_match)
+ {
+ chain_length >>= 2;
+ }
+
+ // Do not look for matches beyond the end of the input. This is necessary
+ // to make deflate deterministic.
+ if (nice_match > lookahead) nice_match = lookahead;
+
+ do
+ {
+ match = cur_match;
+
+ // Skip to next match if the match length cannot increase
+ // or if the match length is less than 2:
+ if (window[match + best_len] != scan_end ||
+ window[match + best_len - 1] != scan_end1 ||
+ window[match] != window[scan] ||
+ window[++match] != window[scan + 1]) continue;
+
+ // The check at best_len-1 can be removed because it will be made
+ // again later. (This heuristic is not always a win.)
+ // It is not necessary to compare scan[2] and match[2] since they
+ // are always equal when the other bytes match, given that
+ // the hash keys are equal and that HASH_BITS >= 8.
+ scan += 2; match++;
+
+ // We check for insufficient lookahead only every 8th comparison;
+ // the 256th check will be made at strstart+258.
+ do
+ {
+ } while (window[++scan] == window[++match] &&
+ window[++scan] == window[++match] &&
+ window[++scan] == window[++match] &&
+ window[++scan] == window[++match] &&
+ window[++scan] == window[++match] &&
+ window[++scan] == window[++match] &&
+ window[++scan] == window[++match] &&
+ window[++scan] == window[++match] &&
+ scan < strend);
+
+ len = MAX_MATCH - (int)(strend - scan);
+ scan = strend - MAX_MATCH;
+
+ if (len > best_len)
+ {
+ match_start = cur_match;
+ best_len = len;
+ if (len >= nice_match) break;
+ scan_end1 = window[scan + best_len - 1];
+ scan_end = window[scan + best_len];
+ }
+
+ } while ((cur_match = (prev[cur_match & wmask] & 0xffff)) > limit
+ && --chain_length != 0);
+
+ if (best_len <= lookahead) return best_len;
+ return lookahead;
+ }
+
+ private ZLibStatus deflateInit2(ZStream strm, CompressionLevel level, int method, int windowBits, int memLevel, CompressionStrategy strategy)
+ {
+ int noheader = 0;
+ // byte[] my_version=ZLIB_VERSION;
+
+ //
+ // if (version == null || version[0] != my_version[0]
+ // || stream_size != sizeof(z_stream)) {
+ // return ZLibStatus.Z_VERSION_ERROR;
+ // }
+
+ strm.msg = null;
+
+ if (level == CompressionLevel.Z_DEFAULT_COMPRESSION) level = (CompressionLevel)6;
+
+ if (windowBits < 0)
+ { // undocumented feature: suppress zlib header
+ noheader = 1;
+ windowBits = -windowBits;
+ }
+
+ if (memLevel < 1 || memLevel > MAX_MEM_LEVEL ||
+ method != Z_DEFLATED ||
+ windowBits < 9 || windowBits > 15 || level < 0 || level > (CompressionLevel)9 ||
+ strategy < 0 || strategy > CompressionStrategy.Z_HUFFMAN_ONLY)
+ {
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+
+ strm.dstate = (Deflate)this;
+
+ this.noheader = noheader;
+ w_bits = windowBits;
+ w_size = 1 << w_bits;
+ w_mask = w_size - 1;
+
+ hash_bits = memLevel + 7;
+ hash_size = 1 << hash_bits;
+ hash_mask = hash_size - 1;
+ hash_shift = ((hash_bits + MIN_MATCH - 1) / MIN_MATCH);
+
+ window = new byte[w_size * 2];
+ prev = new short[w_size];
+ head = new short[hash_size];
+
+ lit_bufsize = 1 << (memLevel + 6); // 16K elements by default
+
+ // We overlay pending_buf and d_buf+l_buf. This works since the average
+ // output size for (length,distance) codes is <= 24 bits.
+ pending_buf = new byte[lit_bufsize * 4];
+ pending_buf_size = lit_bufsize * 4;
+
+ d_buf = lit_bufsize / 2;
+ l_buf = (1 + 2) * lit_bufsize;
+
+ this.level = level;
+
+ //System.out.println("level="+level);
+
+ this.strategy = strategy;
+ this.method = (byte)method;
+
+ return deflateReset(strm);
+ }
+
+ private ZLibStatus deflateReset(ZStream strm)
+ {
+ strm.total_in = strm.total_out = 0;
+ strm.msg = null; //
+ //strm.data_type = Z_UNKNOWN;
+
+ pending = 0;
+ pending_out = 0;
+
+ if (noheader < 0)
+ {
+ noheader = 0; // was set to -1 by deflate(..., FlushType.Z_FINISH);
+ }
+ status = (noheader != 0) ? BUSY_STATE : INIT_STATE;
+ //strm.adler = strm.Adler32(0, null, 0, 0);
+ strm.UpdateAdler(0L, null, 0, 0);
+
+
+ last_flush = FlushType.Z_NO_FLUSH;
+
+ tr_init();
+ lm_init();
+ return ZLibStatus.Z_OK;
+ }
+
+ private class Config
+ {
+ ///
+ /// Reduce lazy search above this match length
+ ///
+ internal int GoodLength { get; private set; }
+ ///
+ /// Gets or sets whether not to perform lazy search above this match length
+ ///
+ ///
+ /// The max lazy.
+ ///
+ internal int MaxLazy { get; private set; }
+ ///
+ /// Gets or sets whether to quit search above this match length
+ ///
+ ///
+ /// The length of the nice.
+ ///
+ internal int NiceLength { get; private set; }
+ internal int MaxChain { get; private set; }
+ internal int Function { get; private set; }
+ internal Config(int goodLength, int maxLazy, int niceLength, int maxChain, int function)
+ {
+ this.GoodLength = goodLength;
+ this.MaxLazy = maxLazy;
+ this.NiceLength = niceLength;
+ this.MaxChain = maxChain;
+ this.Function = function;
+ }
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Working.1/InfBlocks.cs b/Renci.SshNet/Compression/Working.1/InfBlocks.cs
new file mode 100644
index 0000000..190c4ef
--- /dev/null
+++ b/Renci.SshNet/Compression/Working.1/InfBlocks.cs
@@ -0,0 +1,1375 @@
+using System;
+/*
+ * $Id: InfBlocks.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public enum InflateBlockMode
+ {
+ ///
+ /// get type bits (3, including end bit)
+ ///
+ TYPE = 0,
+ ///
+ /// get lengths for stored
+ ///
+ LENS = 1,
+ ///
+ /// cessing stored block
+ ///
+ STORED = 2,
+ ///
+ /// get table lengths
+ ///
+ TABLE = 3,
+ ///
+ /// get bit lengths tree for a dynamic block
+ ///
+ BTREE = 4,
+ ///
+ /// get length, distance trees for a dynamic block
+ ///
+ DTREE = 5,
+ ///
+ /// processing fixed or dynamic block
+ ///
+ CODES = 6,
+ ///
+ /// output remaining window bytes
+ ///
+ DRY = 7,
+ ///
+ /// finished last block, done
+ ///
+ DONE = 8,
+ ///
+ /// ot a data error--stuck here
+ ///
+ BAD = 9
+ }
+
+ public enum InflateCodeMode
+ {
+ ///
+ /// x: set up for InflateCodeMode.LEN
+ ///
+ START = 0,
+ ///
+ /// i: get length/literal/eob next
+ ///
+ LEN = 1,
+ ///
+ /// i: getting length extra (have base)
+ ///
+ LENEXT = 2,
+ ///
+ /// i: get distance next
+ ///
+ DIST = 3,
+ ///
+ /// : getting distance extra
+ ///
+ DISTEXT = 4,
+ ///
+ /// o: copying bytes in window, waiting for space
+ ///
+ COPY = 5,
+ ///
+ /// o: got literal, waiting for output space
+ ///
+ LIT = 6,
+ ///
+ /// o: got eob, possibly still output waiting
+ ///
+ WASH = 7,
+ ///
+ /// x: got eob and all data flushed
+ ///
+ END = 8,
+ ///
+ /// x: got error
+ ///
+ BADCODE = 9
+ }
+
+ internal class InfBlocks : InfTree
+ {
+ private const int MANY = 1440;
+
+ // And'ing with mask[n] masks the lower n bits
+ private static readonly int[] inflate_mask = {
+ 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
+ 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
+ 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
+ 0x00007fff, 0x0000ffff
+ };
+
+ ///
+ /// Table for deflate from PKZIP's appnote.txt.
+ ///
+ static readonly int[] border = { // Order of the bit length code lengths
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
+ };
+
+ internal InflateBlockMode mode; // current inflate_block mode
+
+ private int left; // if STORED, bytes left to copy
+
+ private int table; // table lengths (14 bits)
+ private int index; // index into blens (or border)
+ private int[] blens; // bit lengths of codes
+ private int[] bb = new int[1]; // bit length tree depth
+ private int[] tb = new int[1]; // bit length decoding tree
+
+ private bool _isLastBlock; // true if this block is the last block
+
+ // mode independent information
+ private int bitk; // bits in bit buffer
+ private int bitb; // bit buffer
+ private int[] hufts; // single malloc for tree space
+ private byte[] window; // sliding window
+ private int end; // one byte after sliding window
+ private int read; // window read pointer
+ private int write; // window write pointer
+ private Object checkfn; // check function
+ private long check; // check on output
+
+ ///
+ /// Current inflate_codes mode
+ ///
+ private InflateCodeMode _mode;
+
+ // mode dependent information
+ private int _len;
+
+ private int[] _tree; // pointer into tree
+ private int _treeIndex = 0;
+ private int _need; // bits needed
+
+ private int _lit;
+
+ // if EXT or InflateCodeMode.COPY, where and how much
+ private int _get; // bits to get for extra
+ private int _dist; // distance back to copy from
+
+ private byte _lbits; // ltree bits decoded per branch
+ private byte _dbits; // dtree bits decoder per branch
+ private int[] _ltree; // literal/length/eob tree
+ private int _ltreeIndex; // literal/length/eob tree
+ private int[] _dtree; // distance tree
+ ///
+ /// The distance tree index
+ ///
+ private int _dtreeIndex;
+
+
+
+ //private InfTree inftree = new InfTree();
+
+ public InfBlocks(ZStream z, Object checkfn, int w)
+ {
+ hufts = new int[MANY * 3];
+ window = new byte[w];
+ end = w;
+ this.checkfn = checkfn;
+ mode = InflateBlockMode.TYPE;
+ Reset(z, null);
+ }
+
+ public void Reset(ZStream z, long[] c)
+ {
+ if (c != null) c[0] = check;
+ if (mode == InflateBlockMode.BTREE || mode == InflateBlockMode.DTREE)
+ {
+ }
+ //if (mode == InflateBlockMode.CODES)
+ //{
+ // codes.free(z);
+ //}
+ mode = InflateBlockMode.TYPE;
+ bitk = 0;
+ bitb = 0;
+ read = write = 0;
+
+ if (checkfn != null)
+ {
+ //z.adler = check = z.Adler32(0L, null, 0, 0);
+ z.UpdateAdler(0L, null, 0, 0);
+ check = z.Adler;
+ }
+ }
+
+ public ZLibStatus ProcessBlocks(ZStream z, ZLibStatus r)
+ {
+ int t; // temporary storage
+ ZLibStatus t1; // temporary storage
+ int b; // bit buffer
+ int k; // bits in bit buffer
+ int p; // input data pointer
+ int n; // bytes available there
+ int q; // output window write pointer
+ int m;
+ { // bytes to end of window or read pointer
+
+ // copy input/output information to locals (UPDATE macro restores)
+ p = z.next_in_index; n = z.avail_in; b = bitb; k = bitk;
+ }
+ {
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+ }
+
+ // process input based on current state
+ while (true)
+ {
+ switch (mode)
+ {
+ case InflateBlockMode.TYPE:
+
+ while (k < (3))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index;
+ z.next_in_index = p;
+ write = q;
+ return InflateFlush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+ t = (int)(b & 7);
+ this._isLastBlock = (t & 1) == 1;
+
+ switch (t >> 1)
+ {
+ case 0:
+ { // stored
+ b >>= (3); k -= (3);
+ }
+ t = k & 7;
+ { // go to byte boundary
+
+ b >>= (t); k -= (t);
+ }
+ mode = InflateBlockMode.LENS; // get length of stored block
+ break;
+ case 1:
+ { // fixed
+ int[] bl = new int[1];
+ int[] bd = new int[1];
+ int[][] tl = new int[1][];
+ int[][] td = new int[1][];
+
+ InfTree.InflateTreesFixed(bl, bd, tl, td, z);
+ this.InitCodes(bl[0], bd[0], tl[0], 0, td[0], 0, z);
+ }
+ {
+
+ b >>= (3); k -= (3);
+ }
+
+ mode = InflateBlockMode.CODES;
+ break;
+ case 2:
+ { // dynamic
+
+ b >>= (3); k -= (3);
+ }
+
+ mode = InflateBlockMode.TABLE;
+ break;
+ case 3:
+ { // illegal
+
+ b >>= (3); k -= (3);
+ }
+ mode = InflateBlockMode.BAD;
+ z.msg = "invalid block type";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return InflateFlush(z, r);
+ }
+ break;
+ case InflateBlockMode.LENS:
+
+ while (k < (32))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return InflateFlush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ if ((((~b) >> 16) & 0xffff) != (b & 0xffff))
+ {
+ mode = InflateBlockMode.BAD;
+ z.msg = "invalid stored block lengths";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return InflateFlush(z, r);
+ }
+ left = (b & 0xffff);
+ b = k = 0; // dump bits
+ mode = left != 0 ? InflateBlockMode.STORED : (this._isLastBlock ? InflateBlockMode.DRY : InflateBlockMode.TYPE);
+ break;
+ case InflateBlockMode.STORED:
+ if (n == 0)
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return InflateFlush(z, r);
+ }
+
+ if (m == 0)
+ {
+ if (q == end && read != 0)
+ {
+ q = 0; m = (int)(q < read ? read - q - 1 : end - q);
+ }
+ if (m == 0)
+ {
+ write = q;
+ r = InflateFlush(z, r);
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+ if (q == end && read != 0)
+ {
+ q = 0; m = (int)(q < read ? read - q - 1 : end - q);
+ }
+ if (m == 0)
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return InflateFlush(z, r);
+ }
+ }
+ }
+ r = ZLibStatus.Z_OK;
+
+ t = left;
+ if (t > n) t = n;
+ if (t > m) t = m;
+ System.Array.Copy(z.next_in, p, window, q, t);
+ p += t; n -= t;
+ q += t; m -= t;
+ if ((left -= t) != 0)
+ break;
+ mode = this._isLastBlock ? InflateBlockMode.DRY : InflateBlockMode.TYPE;
+ break;
+ case InflateBlockMode.TABLE:
+
+ while (k < (14))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return InflateFlush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ table = t = (b & 0x3fff);
+ if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
+ {
+ mode = InflateBlockMode.BAD;
+ z.msg = "too many length or distance symbols";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return InflateFlush(z, r);
+ }
+ t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
+ if (blens == null || blens.Length < t)
+ {
+ blens = new int[t];
+ }
+ else
+ {
+ for (int i = 0; i < t; i++) { blens[i] = 0; }
+ }
+ {
+
+ b >>= (14); k -= (14);
+ }
+
+ index = 0;
+ mode = InflateBlockMode.BTREE;
+ goto case InflateBlockMode.BTREE;
+ case InflateBlockMode.BTREE:
+ while (index < 4 + (table >> 10))
+ {
+ while (k < (3))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return InflateFlush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ blens[border[index++]] = b & 7;
+ {
+
+ b >>= (3); k -= (3);
+ }
+ }
+
+ while (index < 19)
+ {
+ blens[border[index++]] = 0;
+ }
+
+ bb[0] = 7;
+ t1 = this.InflateTeesBits(blens, bb, tb, hufts, z);
+ if (t1 != ZLibStatus.Z_OK)
+ {
+ r = t1;
+ if (r == ZLibStatus.Z_DATA_ERROR)
+ {
+ blens = null;
+ mode = InflateBlockMode.BAD;
+ }
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return InflateFlush(z, r);
+ }
+
+ index = 0;
+ mode = InflateBlockMode.DTREE;
+ goto case InflateBlockMode.DTREE;
+ case InflateBlockMode.DTREE:
+ while (true)
+ {
+ t = table;
+ if (!(index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)))
+ {
+ break;
+ }
+
+ int i, j, c;
+
+ t = bb[0];
+
+ while (k < (t))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return InflateFlush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ if (tb[0] == -1)
+ {
+ //System.err.println("null...");
+ }
+
+ t = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 1];
+ c = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 2];
+
+ if (c < 16)
+ {
+ b >>= (t); k -= (t);
+ blens[index++] = c;
+ }
+ else
+ { // c == 16..18
+ i = c == 18 ? 7 : c - 14;
+ j = c == 18 ? 11 : 3;
+
+ while (k < (t + i))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return InflateFlush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ b >>= (t); k -= (t);
+
+ j += (b & inflate_mask[i]);
+
+ b >>= (i); k -= (i);
+
+ i = index;
+ t = table;
+ if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
+ (c == 16 && i < 1))
+ {
+ blens = null;
+ mode = InflateBlockMode.BAD;
+ z.msg = "invalid bit length repeat";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return InflateFlush(z, r);
+ }
+
+ c = c == 16 ? blens[i - 1] : 0;
+ do
+ {
+ blens[i++] = c;
+ }
+ while (--j != 0);
+ index = i;
+ }
+ }
+
+ tb[0] = -1;
+ {
+ int[] bl = new int[1];
+ int[] bd = new int[1];
+ int[] tl = new int[1];
+ int[] td = new int[1];
+ bl[0] = 9; // must be <= 9 for lookahead assumptions
+ bd[0] = 6; // must be <= 9 for lookahead assumptions
+
+ //t = table;
+ t1 = this.InflateTreesDynamic(257 + (table & 0x1f),
+ 1 + ((t >> 5) & 0x1f),
+ blens, bl, bd, tl, td, hufts, z);
+
+ if (t1 != ZLibStatus.Z_OK)
+ {
+ if (t1 == ZLibStatus.Z_DATA_ERROR)
+ {
+ blens = null;
+ mode = InflateBlockMode.BAD;
+ }
+ r = t1;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return InflateFlush(z, r);
+ }
+ this.InitCodes(bl[0], bd[0], hufts, tl[0], hufts, td[0], z);
+ }
+ mode = InflateBlockMode.CODES;
+ goto case InflateBlockMode.CODES;
+ case InflateBlockMode.CODES:
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+
+ if ((r = ProcessCodes(this, z, r)) != ZLibStatus.Z_STREAM_END)
+ {
+ return InflateFlush(z, r);
+ }
+ r = ZLibStatus.Z_OK;
+ //codes.free(z);
+
+ p = z.next_in_index; n = z.avail_in; b = bitb; k = bitk;
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+
+ if (this._isLastBlock == false)
+ {
+ mode = InflateBlockMode.TYPE;
+ break;
+ }
+ mode = InflateBlockMode.DRY;
+ goto case InflateBlockMode.DRY;
+ case InflateBlockMode.DRY:
+ write = q;
+ r = InflateFlush(z, r);
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+ if (read != write)
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return InflateFlush(z, r);
+ }
+ mode = InflateBlockMode.DONE;
+ goto case InflateBlockMode.DONE;
+ case InflateBlockMode.DONE:
+ r = ZLibStatus.Z_STREAM_END;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return InflateFlush(z, r);
+ case InflateBlockMode.BAD:
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return InflateFlush(z, r);
+
+ default:
+ r = ZLibStatus.Z_STREAM_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return InflateFlush(z, r);
+ }
+ }
+ }
+
+ public void free(ZStream z)
+ {
+ this.Reset(z, null);
+ window = null;
+ hufts = null;
+ //ZFREE(z, s);
+ }
+
+ ///
+ /// copy as much as possible from the sliding window to the output area
+ ///
+ /// The z.
+ /// The r.
+ ///
+ public ZLibStatus InflateFlush(ZStream z, ZLibStatus r)
+ {
+ int n;
+ int p;
+ int q;
+
+ // local copies of source and destination pointers
+ p = z.next_out_index;
+ q = read;
+
+ // compute number of bytes to copy as far as end of window
+ n = (int)((q <= write ? write : end) - q);
+ if (n > z.avail_out) n = z.avail_out;
+ if (n != 0 && r == ZLibStatus.Z_BUF_ERROR)
+ r = ZLibStatus.Z_OK;
+
+ // update counters
+ z.avail_out -= n;
+ z.total_out += n;
+
+ // update check information
+ if (checkfn != null)
+ {
+ //z.adler = check = z.Adler32(check, window, q, n);
+ z.UpdateAdler(check, window, q, n);
+ check = z.Adler;
+ }
+
+ // copy as far as end of window
+ System.Array.Copy(window, q, z.next_out, p, n);
+ p += n;
+ q += n;
+
+ // see if more to copy at beginning of window
+ if (q == end)
+ {
+ // wrap pointers
+ q = 0;
+ if (write == end)
+ write = 0;
+
+ // compute bytes to copy
+ n = write - q;
+ if (n > z.avail_out) n = z.avail_out;
+ if (n != 0 && r == ZLibStatus.Z_BUF_ERROR)
+ r = ZLibStatus.Z_OK;
+
+ // update counters
+ z.avail_out -= n;
+ z.total_out += n;
+
+ // update check information
+ if (checkfn != null)
+ {
+ //z.adler = check = z.Adler32(check, window, q, n);
+ z.UpdateAdler(check, window, q, n);
+ check = z.Adler;
+ }
+
+ // copy
+ System.Array.Copy(window, q, z.next_out, p, n);
+ p += n;
+ q += n;
+ }
+
+ // update pointers
+ z.next_out_index = p;
+ read = q;
+
+ // done
+ return r;
+ }
+
+ private void InitCodes(int bl, int bd, int[] tl, int tl_index, int[] td, int td_index, ZStream z)
+ {
+ this._mode = InflateCodeMode.START;
+ this._lbits = (byte)bl;
+ this._dbits = (byte)bd;
+ this._ltree = tl;
+ this._ltreeIndex = tl_index;
+ this._dtree = td;
+ this._dtreeIndex = td_index;
+ this._tree = null;
+ }
+
+ private ZLibStatus ProcessCodes(InfBlocks s, ZStream z, ZLibStatus r)
+ {
+ int j; // temporary storage
+ int tindex; // temporary pointer
+ int e; // extra bits or operation
+ int b = 0; // bit buffer
+ int k = 0; // bits in bit buffer
+ int p = 0; // input data pointer
+ int n; // bytes available there
+ int q; // output window write pointer
+ int m; // bytes to end of window or read pointer
+ int f; // pointer to copy strings from
+
+ // copy input/output information to locals (UPDATE macro restores)
+ p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk;
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ // process input and output based on current state
+ while (true)
+ {
+ switch (this._mode)
+ {
+ // waiting for "i:"=input, "o:"=output, "x:"=nothing
+ case InflateCodeMode.START: // x: set up for InflateCodeMode.LEN
+ if (m >= 258 && n >= 10)
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ r = this.InflateFast(this._lbits, this._dbits, this._ltree, this._ltreeIndex, this._dtree, this._dtreeIndex, s, z);
+
+ p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk;
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (r != ZLibStatus.Z_OK)
+ {
+ this._mode = r == ZLibStatus.Z_STREAM_END ? InflateCodeMode.WASH : InflateCodeMode.BADCODE;
+ break;
+ }
+ }
+ this._need = this._lbits;
+ this._tree = this._ltree;
+ this._treeIndex = this._ltreeIndex;
+
+ this._mode = InflateCodeMode.LEN;
+ goto case InflateCodeMode.LEN;
+ case InflateCodeMode.LEN: // i: get length/literal/eob next
+ j = this._need;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.InflateFlush(z, r);
+ }
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ tindex = (this._treeIndex + (b & inflate_mask[j])) * 3;
+
+ b >>= (this._tree[tindex + 1]);
+ k -= (this._tree[tindex + 1]);
+
+ e = this._tree[tindex];
+
+ if (e == 0)
+ { // literal
+ this._lit = this._tree[tindex + 2];
+ this._mode = InflateCodeMode.LIT;
+ break;
+ }
+ if ((e & 16) != 0)
+ { // length
+ this._get = e & 15;
+ this._len = this._tree[tindex + 2];
+ this._mode = InflateCodeMode.LENEXT;
+ break;
+ }
+ if ((e & 64) == 0)
+ { // next table
+ this._need = e;
+ this._treeIndex = tindex / 3 + this._tree[tindex + 2];
+ break;
+ }
+ if ((e & 32) != 0)
+ { // end of block
+ this._mode = InflateCodeMode.WASH;
+ break;
+ }
+ this._mode = InflateCodeMode.BADCODE; // invalid code
+ z.msg = "invalid literal/length code";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.InflateFlush(z, r);
+
+ case InflateCodeMode.LENEXT: // i: getting length extra (have base)
+ j = this._get;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.InflateFlush(z, r);
+ }
+ n--; b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ this._len += (b & inflate_mask[j]);
+
+ b >>= j;
+ k -= j;
+
+ this._need = this._dbits;
+ this._tree = this._dtree;
+ this._treeIndex = this._dtreeIndex;
+ this._mode = InflateCodeMode.DIST;
+ goto case InflateCodeMode.DIST;
+ case InflateCodeMode.DIST: // i: get distance next
+ j = this._need;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.InflateFlush(z, r);
+ }
+ n--; b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ tindex = (this._treeIndex + (b & inflate_mask[j])) * 3;
+
+ b >>= this._tree[tindex + 1];
+ k -= this._tree[tindex + 1];
+
+ e = (this._tree[tindex]);
+ if ((e & 16) != 0)
+ { // distance
+ this._get = e & 15;
+ this._dist = this._tree[tindex + 2];
+ this._mode = InflateCodeMode.DISTEXT;
+ break;
+ }
+ if ((e & 64) == 0)
+ { // next table
+ this._need = e;
+ this._treeIndex = tindex / 3 + this._tree[tindex + 2];
+ break;
+ }
+ this._mode = InflateCodeMode.BADCODE; // invalid code
+ z.msg = "invalid distance code";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.InflateFlush(z, r);
+
+ case InflateCodeMode.DISTEXT: // i: getting distance extra
+ j = this._get;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.InflateFlush(z, r);
+ }
+ n--; b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ this._dist += (b & inflate_mask[j]);
+
+ b >>= j;
+ k -= j;
+
+ this._mode = InflateCodeMode.COPY;
+ goto case InflateCodeMode.COPY;
+ case InflateCodeMode.COPY: // o: copying bytes in window, waiting for space
+ f = q - this._dist;
+ while (f < 0)
+ { // modulo window size-"while" instead
+ f += s.end; // of "if" handles invalid distances
+ }
+ while (this._len != 0)
+ {
+
+ if (m == 0)
+ {
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+ if (m == 0)
+ {
+ s.write = q; r = s.InflateFlush(z, r);
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+
+ if (m == 0)
+ {
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.InflateFlush(z, r);
+ }
+ }
+ }
+
+ s.window[q++] = s.window[f++]; m--;
+
+ if (f == s.end)
+ f = 0;
+ this._len--;
+ }
+ this._mode = InflateCodeMode.START;
+ break;
+ case InflateCodeMode.LIT: // o: got literal, waiting for output space
+ if (m == 0)
+ {
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+ if (m == 0)
+ {
+ s.write = q; r = s.InflateFlush(z, r);
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+ if (m == 0)
+ {
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.InflateFlush(z, r);
+ }
+ }
+ }
+ r = ZLibStatus.Z_OK;
+
+ s.window[q++] = (byte)this._lit; m--;
+
+ this._mode = InflateCodeMode.START;
+ break;
+ case InflateCodeMode.WASH: // o: got eob, possibly more output
+ if (k > 7)
+ { // return unused byte, if any
+ k -= 8;
+ n++;
+ p--; // can always return one
+ }
+
+ s.write = q; r = s.InflateFlush(z, r);
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (s.read != s.write)
+ {
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.InflateFlush(z, r);
+ }
+ this._mode = InflateCodeMode.END;
+ goto case InflateCodeMode.END;
+ case InflateCodeMode.END:
+ r = ZLibStatus.Z_STREAM_END;
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.InflateFlush(z, r);
+
+ case InflateCodeMode.BADCODE: // x: got error
+
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.InflateFlush(z, r);
+
+ default:
+ r = ZLibStatus.Z_STREAM_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.InflateFlush(z, r);
+ }
+ }
+ }
+
+ ///
+ /// Inflates the fast.
+ ///
+ /// The bl.
+ /// The bd.
+ /// The tl.
+ /// The tl_index.
+ /// The td.
+ /// The td_index.
+ /// The s.
+ /// The z.
+ ///
+ ///
+ /// Called with number of bytes left to write in window at least 258
+ /// (the maximum string length) and number of input bytes available
+ /// at least ten. The ten bytes are six bytes for the longest length/
+ /// distance pair plus four bytes for overloading the bit buffer.
+ ///
+ private ZLibStatus InflateFast(int bl, int bd, int[] tl, int tl_index, int[] td, int td_index, InfBlocks s, ZStream z)
+ {
+ int t; // temporary pointer
+ int[] tp; // temporary pointer
+ int tp_index; // temporary pointer
+ int e; // extra bits or operation
+ int b; // bit buffer
+ int k; // bits in bit buffer
+ int p; // input data pointer
+ int n; // bytes available there
+ int q; // output window write pointer
+ int m; // bytes to end of window or read pointer
+ int ml; // mask for literal/length tree
+ int md; // mask for distance tree
+ int c; // bytes to copy
+ int d; // distance back to copy from
+ int r; // copy source pointer
+
+ int tp_index_t_3; // (tp_index+t)*3
+
+ // load input, output, bit values
+ p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk;
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ // initialize masks
+ ml = inflate_mask[bl];
+ md = inflate_mask[bd];
+
+ // do until not enough input or output space for fast loop
+ do
+ { // assume called with m >= 258 && n >= 10
+ // get literal/length code
+ while (k < (20))
+ { // max bits for literal/length code
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k; k += 8;
+ }
+
+ t = b & ml;
+ tp = tl;
+ tp_index = tl_index;
+ tp_index_t_3 = (tp_index + t) * 3;
+ if ((e = tp[tp_index_t_3]) == 0)
+ {
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ s.window[q++] = (byte)tp[tp_index_t_3 + 2];
+ m--;
+ continue;
+ }
+ do
+ {
+
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ if ((e & 16) != 0)
+ {
+ e &= 15;
+ c = tp[tp_index_t_3 + 2] + ((int)b & inflate_mask[e]);
+
+ b >>= e; k -= e;
+
+ // decode distance base of block to copy
+ while (k < (15))
+ { // max bits for distance code
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k; k += 8;
+ }
+
+ t = b & md;
+ tp = td;
+ tp_index = td_index;
+ tp_index_t_3 = (tp_index + t) * 3;
+ e = tp[tp_index_t_3];
+
+ do
+ {
+
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ if ((e & 16) != 0)
+ {
+ // get extra bits to add to distance base
+ e &= 15;
+ while (k < (e))
+ { // get extra bits (up to 13)
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k; k += 8;
+ }
+
+ d = tp[tp_index_t_3 + 2] + (b & inflate_mask[e]);
+
+ b >>= (e); k -= (e);
+
+ // do the copy
+ m -= c;
+ if (q >= d)
+ { // offset before dest
+ // just copy
+ r = q - d;
+ if (q - r > 0 && 2 > (q - r))
+ {
+ s.window[q++] = s.window[r++]; // minimum count is three,
+ s.window[q++] = s.window[r++]; // so unroll loop a little
+ c -= 2;
+ }
+ else
+ {
+ System.Array.Copy(s.window, r, s.window, q, 2);
+ q += 2; r += 2; c -= 2;
+ }
+ }
+ else
+ { // else offset after destination
+ r = q - d;
+ do
+ {
+ r += s.end; // force pointer in window
+ } while (r < 0); // covers invalid distances
+ e = s.end - r;
+ if (c > e)
+ { // if source crosses,
+ c -= e; // wrapped copy
+ if (q - r > 0 && e > (q - r))
+ {
+ do { s.window[q++] = s.window[r++]; }
+ while (--e != 0);
+ }
+ else
+ {
+ System.Array.Copy(s.window, r, s.window, q, e);
+ q += e; r += e; e = 0;
+ }
+ r = 0; // copy rest from start of window
+ }
+
+ }
+
+ // copy all or what's left
+ if (q - r > 0 && c > (q - r))
+ {
+ do { s.window[q++] = s.window[r++]; }
+ while (--c != 0);
+ }
+ else
+ {
+ System.Array.Copy(s.window, r, s.window, q, c);
+ q += c; r += c; c = 0;
+ }
+ break;
+ }
+ else if ((e & 64) == 0)
+ {
+ t += tp[tp_index_t_3 + 2];
+ t += (b & inflate_mask[e]);
+ tp_index_t_3 = (tp_index + t) * 3;
+ e = tp[tp_index_t_3];
+ }
+ else
+ {
+ z.msg = "invalid distance code";
+
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ }
+ while (true);
+ break;
+ }
+
+ if ((e & 64) == 0)
+ {
+ t += tp[tp_index_t_3 + 2];
+ t += (b & inflate_mask[e]);
+ tp_index_t_3 = (tp_index + t) * 3;
+ if ((e = tp[tp_index_t_3]) == 0)
+ {
+
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ s.window[q++] = (byte)tp[tp_index_t_3 + 2];
+ m--;
+ break;
+ }
+ }
+ else if ((e & 32) != 0)
+ {
+
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_STREAM_END;
+ }
+ else
+ {
+ z.msg = "invalid literal/length code";
+
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ }
+ while (true);
+ }
+ while (m >= 258 && n >= 10);
+
+ // not enough input or output--restore pointers and return
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_OK;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Working.1/InfCodes.cs b/Renci.SshNet/Compression/Working.1/InfCodes.cs
new file mode 100644
index 0000000..be7fe62
--- /dev/null
+++ b/Renci.SshNet/Compression/Working.1/InfCodes.cs
@@ -0,0 +1,696 @@
+using System;
+/*
+ * $Id: InfCodes.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+ public enum InflateCodeMode
+ {
+ ///
+ /// x: set up for InflateCodeMode.LEN
+ ///
+ START = 0,
+ ///
+ /// i: get length/literal/eob next
+ ///
+ LEN = 1,
+ ///
+ /// i: getting length extra (have base)
+ ///
+ LENEXT = 2,
+ ///
+ /// i: get distance next
+ ///
+ DIST = 3,
+ ///
+ /// : getting distance extra
+ ///
+ DISTEXT = 4,
+ ///
+ /// o: copying bytes in window, waiting for space
+ ///
+ COPY = 5,
+ ///
+ /// o: got literal, waiting for output space
+ ///
+ LIT = 6,
+ ///
+ /// o: got eob, possibly still output waiting
+ ///
+ WASH = 7,
+ ///
+ /// x: got eob and all data flushed
+ ///
+ END = 8,
+ ///
+ /// x: got error
+ ///
+ BADCODE = 9
+ }
+
+ internal abstract class InfCodes
+ {
+
+ private static readonly int[] inflate_mask = {
+ 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
+ 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
+ 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
+ 0x00007fff, 0x0000ffff
+ };
+
+ // waiting for "i:"=input,
+ // "o:"=output,
+ // "x:"=nothing
+ ///
+ /// Current inflate_codes mode
+ ///
+ private InflateCodeMode _mode;
+
+ // mode dependent information
+ private int _len;
+
+ private int[] _tree; // pointer into tree
+ private int _treeIndex = 0;
+ private int _need; // bits needed
+
+ private int _lit;
+
+ // if EXT or InflateCodeMode.COPY, where and how much
+ private int _get; // bits to get for extra
+ private int _dist; // distance back to copy from
+
+ private byte _lbits; // ltree bits decoded per branch
+ private byte _dbits; // dtree bits decoder per branch
+ private int[] _ltree; // literal/length/eob tree
+ private int _ltreeIndex; // literal/length/eob tree
+ private int[] _dtree; // distance tree
+ private int _dtreeIndex; // distance tree
+
+ internal void InitCodes(int bl, int bd, int[] tl, int tl_index, int[] td, int td_index, ZStream z)
+ {
+ this._mode = InflateCodeMode.START;
+ this._lbits = (byte)bl;
+ this._dbits = (byte)bd;
+ this._ltree = tl;
+ this._ltreeIndex = tl_index;
+ this._dtree = td;
+ this._dtreeIndex = td_index;
+ this._tree = null;
+ }
+
+ internal ZLibStatus ProcessCodes(InfBlocks s, ZStream z, ZLibStatus r)
+ {
+ int j; // temporary storage
+ int tindex; // temporary pointer
+ int e; // extra bits or operation
+ int b = 0; // bit buffer
+ int k = 0; // bits in bit buffer
+ int p = 0; // input data pointer
+ int n; // bytes available there
+ int q; // output window write pointer
+ int m; // bytes to end of window or read pointer
+ int f; // pointer to copy strings from
+
+ // copy input/output information to locals (UPDATE macro restores)
+ p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk;
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ // process input and output based on current state
+ while (true)
+ {
+ switch (this._mode)
+ {
+ // waiting for "i:"=input, "o:"=output, "x:"=nothing
+ case InflateCodeMode.START: // x: set up for InflateCodeMode.LEN
+ if (m >= 258 && n >= 10)
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ r = InflateFast(this._lbits, this._dbits,
+ this._ltree, this._ltreeIndex,
+ this._dtree, _dtreeIndex,
+ s, z);
+
+ p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk;
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (r != ZLibStatus.Z_OK)
+ {
+ this._mode = r == ZLibStatus.Z_STREAM_END ? InflateCodeMode.WASH : InflateCodeMode.BADCODE;
+ break;
+ }
+ }
+ this._need = this._lbits;
+ this._tree = this._ltree;
+ this._treeIndex = this._ltreeIndex;
+
+ this._mode = InflateCodeMode.LEN;
+ goto case InflateCodeMode.LEN;
+ case InflateCodeMode.LEN: // i: get length/literal/eob next
+ j = this._need;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ tindex = (this._treeIndex + (b & inflate_mask[j])) * 3;
+
+ b >>= (this._tree[tindex + 1]);
+ k -= (this._tree[tindex + 1]);
+
+ e = this._tree[tindex];
+
+ if (e == 0)
+ { // literal
+ this._lit = this._tree[tindex + 2];
+ this._mode = InflateCodeMode.LIT;
+ break;
+ }
+ if ((e & 16) != 0)
+ { // length
+ this._get = e & 15;
+ this._len = this._tree[tindex + 2];
+ this._mode = InflateCodeMode.LENEXT;
+ break;
+ }
+ if ((e & 64) == 0)
+ { // next table
+ this._need = e;
+ this._treeIndex = tindex / 3 + this._tree[tindex + 2];
+ break;
+ }
+ if ((e & 32) != 0)
+ { // end of block
+ this._mode = InflateCodeMode.WASH;
+ break;
+ }
+ this._mode = InflateCodeMode.BADCODE; // invalid code
+ z.msg = "invalid literal/length code";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ case InflateCodeMode.LENEXT: // i: getting length extra (have base)
+ j = this._get;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--; b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ this._len += (b & inflate_mask[j]);
+
+ b >>= j;
+ k -= j;
+
+ this._need = this._dbits;
+ this._tree = this._dtree;
+ this._treeIndex = _dtreeIndex;
+ this._mode = InflateCodeMode.DIST;
+ goto case InflateCodeMode.DIST;
+ case InflateCodeMode.DIST: // i: get distance next
+ j = this._need;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--; b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ tindex = (this._treeIndex + (b & inflate_mask[j])) * 3;
+
+ b >>= this._tree[tindex + 1];
+ k -= this._tree[tindex + 1];
+
+ e = (this._tree[tindex]);
+ if ((e & 16) != 0)
+ { // distance
+ this._get = e & 15;
+ this._dist = this._tree[tindex + 2];
+ this._mode = InflateCodeMode.DISTEXT;
+ break;
+ }
+ if ((e & 64) == 0)
+ { // next table
+ this._need = e;
+ this._treeIndex = tindex / 3 + this._tree[tindex + 2];
+ break;
+ }
+ this._mode = InflateCodeMode.BADCODE; // invalid code
+ z.msg = "invalid distance code";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ case InflateCodeMode.DISTEXT: // i: getting distance extra
+ j = this._get;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--; b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ this._dist += (b & inflate_mask[j]);
+
+ b >>= j;
+ k -= j;
+
+ this._mode = InflateCodeMode.COPY;
+ goto case InflateCodeMode.COPY;
+ case InflateCodeMode.COPY: // o: copying bytes in window, waiting for space
+ f = q - this._dist;
+ while (f < 0)
+ { // modulo window size-"while" instead
+ f += s.end; // of "if" handles invalid distances
+ }
+ while (this._len != 0)
+ {
+
+ if (m == 0)
+ {
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+ if (m == 0)
+ {
+ s.write = q; r = s.inflate_flush(z, r);
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+
+ if (m == 0)
+ {
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ }
+ }
+
+ s.window[q++] = s.window[f++]; m--;
+
+ if (f == s.end)
+ f = 0;
+ this._len--;
+ }
+ this._mode = InflateCodeMode.START;
+ break;
+ case InflateCodeMode.LIT: // o: got literal, waiting for output space
+ if (m == 0)
+ {
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+ if (m == 0)
+ {
+ s.write = q; r = s.inflate_flush(z, r);
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+ if (m == 0)
+ {
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ }
+ }
+ r = ZLibStatus.Z_OK;
+
+ s.window[q++] = (byte)this._lit; m--;
+
+ this._mode = InflateCodeMode.START;
+ break;
+ case InflateCodeMode.WASH: // o: got eob, possibly more output
+ if (k > 7)
+ { // return unused byte, if any
+ k -= 8;
+ n++;
+ p--; // can always return one
+ }
+
+ s.write = q; r = s.inflate_flush(z, r);
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (s.read != s.write)
+ {
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ this._mode = InflateCodeMode.END;
+ goto case InflateCodeMode.END;
+ case InflateCodeMode.END:
+ r = ZLibStatus.Z_STREAM_END;
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ case InflateCodeMode.BADCODE: // x: got error
+
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ default:
+ r = ZLibStatus.Z_STREAM_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ }
+ }
+
+ ///
+ /// Inflates the fast.
+ ///
+ /// The bl.
+ /// The bd.
+ /// The tl.
+ /// The tl_index.
+ /// The td.
+ /// The td_index.
+ /// The s.
+ /// The z.
+ ///
+ ///
+ /// Called with number of bytes left to write in window at least 258
+ /// (the maximum string length) and number of input bytes available
+ /// at least ten. The ten bytes are six bytes for the longest length/
+ /// distance pair plus four bytes for overloading the bit buffer.
+ ///
+ private ZLibStatus InflateFast(int bl, int bd, int[] tl, int tl_index, int[] td, int td_index, InfBlocks s, ZStream z)
+ {
+ int t; // temporary pointer
+ int[] tp; // temporary pointer
+ int tp_index; // temporary pointer
+ int e; // extra bits or operation
+ int b; // bit buffer
+ int k; // bits in bit buffer
+ int p; // input data pointer
+ int n; // bytes available there
+ int q; // output window write pointer
+ int m; // bytes to end of window or read pointer
+ int ml; // mask for literal/length tree
+ int md; // mask for distance tree
+ int c; // bytes to copy
+ int d; // distance back to copy from
+ int r; // copy source pointer
+
+ int tp_index_t_3; // (tp_index+t)*3
+
+ // load input, output, bit values
+ p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk;
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ // initialize masks
+ ml = inflate_mask[bl];
+ md = inflate_mask[bd];
+
+ // do until not enough input or output space for fast loop
+ do
+ { // assume called with m >= 258 && n >= 10
+ // get literal/length code
+ while (k < (20))
+ { // max bits for literal/length code
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k; k += 8;
+ }
+
+ t = b & ml;
+ tp = tl;
+ tp_index = tl_index;
+ tp_index_t_3 = (tp_index + t) * 3;
+ if ((e = tp[tp_index_t_3]) == 0)
+ {
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ s.window[q++] = (byte)tp[tp_index_t_3 + 2];
+ m--;
+ continue;
+ }
+ do
+ {
+
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ if ((e & 16) != 0)
+ {
+ e &= 15;
+ c = tp[tp_index_t_3 + 2] + ((int)b & inflate_mask[e]);
+
+ b >>= e; k -= e;
+
+ // decode distance base of block to copy
+ while (k < (15))
+ { // max bits for distance code
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k; k += 8;
+ }
+
+ t = b & md;
+ tp = td;
+ tp_index = td_index;
+ tp_index_t_3 = (tp_index + t) * 3;
+ e = tp[tp_index_t_3];
+
+ do
+ {
+
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ if ((e & 16) != 0)
+ {
+ // get extra bits to add to distance base
+ e &= 15;
+ while (k < (e))
+ { // get extra bits (up to 13)
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k; k += 8;
+ }
+
+ d = tp[tp_index_t_3 + 2] + (b & inflate_mask[e]);
+
+ b >>= (e); k -= (e);
+
+ // do the copy
+ m -= c;
+ if (q >= d)
+ { // offset before dest
+ // just copy
+ r = q - d;
+ if (q - r > 0 && 2 > (q - r))
+ {
+ s.window[q++] = s.window[r++]; // minimum count is three,
+ s.window[q++] = s.window[r++]; // so unroll loop a little
+ c -= 2;
+ }
+ else
+ {
+ System.Array.Copy(s.window, r, s.window, q, 2);
+ q += 2; r += 2; c -= 2;
+ }
+ }
+ else
+ { // else offset after destination
+ r = q - d;
+ do
+ {
+ r += s.end; // force pointer in window
+ } while (r < 0); // covers invalid distances
+ e = s.end - r;
+ if (c > e)
+ { // if source crosses,
+ c -= e; // wrapped copy
+ if (q - r > 0 && e > (q - r))
+ {
+ do { s.window[q++] = s.window[r++]; }
+ while (--e != 0);
+ }
+ else
+ {
+ System.Array.Copy(s.window, r, s.window, q, e);
+ q += e; r += e; e = 0;
+ }
+ r = 0; // copy rest from start of window
+ }
+
+ }
+
+ // copy all or what's left
+ if (q - r > 0 && c > (q - r))
+ {
+ do { s.window[q++] = s.window[r++]; }
+ while (--c != 0);
+ }
+ else
+ {
+ System.Array.Copy(s.window, r, s.window, q, c);
+ q += c; r += c; c = 0;
+ }
+ break;
+ }
+ else if ((e & 64) == 0)
+ {
+ t += tp[tp_index_t_3 + 2];
+ t += (b & inflate_mask[e]);
+ tp_index_t_3 = (tp_index + t) * 3;
+ e = tp[tp_index_t_3];
+ }
+ else
+ {
+ z.msg = "invalid distance code";
+
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ }
+ while (true);
+ break;
+ }
+
+ if ((e & 64) == 0)
+ {
+ t += tp[tp_index_t_3 + 2];
+ t += (b & inflate_mask[e]);
+ tp_index_t_3 = (tp_index + t) * 3;
+ if ((e = tp[tp_index_t_3]) == 0)
+ {
+
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ s.window[q++] = (byte)tp[tp_index_t_3 + 2];
+ m--;
+ break;
+ }
+ }
+ else if ((e & 32) != 0)
+ {
+
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_STREAM_END;
+ }
+ else
+ {
+ z.msg = "invalid literal/length code";
+
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ }
+ while (true);
+ }
+ while (m >= 258 && n >= 10);
+
+ // not enough input or output--restore pointers and return
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_OK;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Working.1/InfTree.cs b/Renci.SshNet/Compression/Working.1/InfTree.cs
new file mode 100644
index 0000000..798ee7f
--- /dev/null
+++ b/Renci.SshNet/Compression/Working.1/InfTree.cs
@@ -0,0 +1,603 @@
+using System;
+/*
+ * $Id: InfTree.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ internal class InfTree
+ {
+ private const int MANY = 1440;
+
+ private const int fixed_bl = 9;
+
+ private const int fixed_bd = 5;
+
+ static readonly int[] fixed_tl = {
+ 96,7,256, 0,8,80, 0,8,16, 84,8,115,
+ 82,7,31, 0,8,112, 0,8,48, 0,9,192,
+ 80,7,10, 0,8,96, 0,8,32, 0,9,160,
+ 0,8,0, 0,8,128, 0,8,64, 0,9,224,
+ 80,7,6, 0,8,88, 0,8,24, 0,9,144,
+ 83,7,59, 0,8,120, 0,8,56, 0,9,208,
+ 81,7,17, 0,8,104, 0,8,40, 0,9,176,
+ 0,8,8, 0,8,136, 0,8,72, 0,9,240,
+ 80,7,4, 0,8,84, 0,8,20, 85,8,227,
+ 83,7,43, 0,8,116, 0,8,52, 0,9,200,
+ 81,7,13, 0,8,100, 0,8,36, 0,9,168,
+ 0,8,4, 0,8,132, 0,8,68, 0,9,232,
+ 80,7,8, 0,8,92, 0,8,28, 0,9,152,
+ 84,7,83, 0,8,124, 0,8,60, 0,9,216,
+ 82,7,23, 0,8,108, 0,8,44, 0,9,184,
+ 0,8,12, 0,8,140, 0,8,76, 0,9,248,
+ 80,7,3, 0,8,82, 0,8,18, 85,8,163,
+ 83,7,35, 0,8,114, 0,8,50, 0,9,196,
+ 81,7,11, 0,8,98, 0,8,34, 0,9,164,
+ 0,8,2, 0,8,130, 0,8,66, 0,9,228,
+ 80,7,7, 0,8,90, 0,8,26, 0,9,148,
+ 84,7,67, 0,8,122, 0,8,58, 0,9,212,
+ 82,7,19, 0,8,106, 0,8,42, 0,9,180,
+ 0,8,10, 0,8,138, 0,8,74, 0,9,244,
+ 80,7,5, 0,8,86, 0,8,22, 192,8,0,
+ 83,7,51, 0,8,118, 0,8,54, 0,9,204,
+ 81,7,15, 0,8,102, 0,8,38, 0,9,172,
+ 0,8,6, 0,8,134, 0,8,70, 0,9,236,
+ 80,7,9, 0,8,94, 0,8,30, 0,9,156,
+ 84,7,99, 0,8,126, 0,8,62, 0,9,220,
+ 82,7,27, 0,8,110, 0,8,46, 0,9,188,
+ 0,8,14, 0,8,142, 0,8,78, 0,9,252,
+ 96,7,256, 0,8,81, 0,8,17, 85,8,131,
+ 82,7,31, 0,8,113, 0,8,49, 0,9,194,
+ 80,7,10, 0,8,97, 0,8,33, 0,9,162,
+ 0,8,1, 0,8,129, 0,8,65, 0,9,226,
+ 80,7,6, 0,8,89, 0,8,25, 0,9,146,
+ 83,7,59, 0,8,121, 0,8,57, 0,9,210,
+ 81,7,17, 0,8,105, 0,8,41, 0,9,178,
+ 0,8,9, 0,8,137, 0,8,73, 0,9,242,
+ 80,7,4, 0,8,85, 0,8,21, 80,8,258,
+ 83,7,43, 0,8,117, 0,8,53, 0,9,202,
+ 81,7,13, 0,8,101, 0,8,37, 0,9,170,
+ 0,8,5, 0,8,133, 0,8,69, 0,9,234,
+ 80,7,8, 0,8,93, 0,8,29, 0,9,154,
+ 84,7,83, 0,8,125, 0,8,61, 0,9,218,
+ 82,7,23, 0,8,109, 0,8,45, 0,9,186,
+ 0,8,13, 0,8,141, 0,8,77, 0,9,250,
+ 80,7,3, 0,8,83, 0,8,19, 85,8,195,
+ 83,7,35, 0,8,115, 0,8,51, 0,9,198,
+ 81,7,11, 0,8,99, 0,8,35, 0,9,166,
+ 0,8,3, 0,8,131, 0,8,67, 0,9,230,
+ 80,7,7, 0,8,91, 0,8,27, 0,9,150,
+ 84,7,67, 0,8,123, 0,8,59, 0,9,214,
+ 82,7,19, 0,8,107, 0,8,43, 0,9,182,
+ 0,8,11, 0,8,139, 0,8,75, 0,9,246,
+ 80,7,5, 0,8,87, 0,8,23, 192,8,0,
+ 83,7,51, 0,8,119, 0,8,55, 0,9,206,
+ 81,7,15, 0,8,103, 0,8,39, 0,9,174,
+ 0,8,7, 0,8,135, 0,8,71, 0,9,238,
+ 80,7,9, 0,8,95, 0,8,31, 0,9,158,
+ 84,7,99, 0,8,127, 0,8,63, 0,9,222,
+ 82,7,27, 0,8,111, 0,8,47, 0,9,190,
+ 0,8,15, 0,8,143, 0,8,79, 0,9,254,
+ 96,7,256, 0,8,80, 0,8,16, 84,8,115,
+ 82,7,31, 0,8,112, 0,8,48, 0,9,193,
+
+ 80,7,10, 0,8,96, 0,8,32, 0,9,161,
+ 0,8,0, 0,8,128, 0,8,64, 0,9,225,
+ 80,7,6, 0,8,88, 0,8,24, 0,9,145,
+ 83,7,59, 0,8,120, 0,8,56, 0,9,209,
+ 81,7,17, 0,8,104, 0,8,40, 0,9,177,
+ 0,8,8, 0,8,136, 0,8,72, 0,9,241,
+ 80,7,4, 0,8,84, 0,8,20, 85,8,227,
+ 83,7,43, 0,8,116, 0,8,52, 0,9,201,
+ 81,7,13, 0,8,100, 0,8,36, 0,9,169,
+ 0,8,4, 0,8,132, 0,8,68, 0,9,233,
+ 80,7,8, 0,8,92, 0,8,28, 0,9,153,
+ 84,7,83, 0,8,124, 0,8,60, 0,9,217,
+ 82,7,23, 0,8,108, 0,8,44, 0,9,185,
+ 0,8,12, 0,8,140, 0,8,76, 0,9,249,
+ 80,7,3, 0,8,82, 0,8,18, 85,8,163,
+ 83,7,35, 0,8,114, 0,8,50, 0,9,197,
+ 81,7,11, 0,8,98, 0,8,34, 0,9,165,
+ 0,8,2, 0,8,130, 0,8,66, 0,9,229,
+ 80,7,7, 0,8,90, 0,8,26, 0,9,149,
+ 84,7,67, 0,8,122, 0,8,58, 0,9,213,
+ 82,7,19, 0,8,106, 0,8,42, 0,9,181,
+ 0,8,10, 0,8,138, 0,8,74, 0,9,245,
+ 80,7,5, 0,8,86, 0,8,22, 192,8,0,
+ 83,7,51, 0,8,118, 0,8,54, 0,9,205,
+ 81,7,15, 0,8,102, 0,8,38, 0,9,173,
+ 0,8,6, 0,8,134, 0,8,70, 0,9,237,
+ 80,7,9, 0,8,94, 0,8,30, 0,9,157,
+ 84,7,99, 0,8,126, 0,8,62, 0,9,221,
+ 82,7,27, 0,8,110, 0,8,46, 0,9,189,
+ 0,8,14, 0,8,142, 0,8,78, 0,9,253,
+ 96,7,256, 0,8,81, 0,8,17, 85,8,131,
+ 82,7,31, 0,8,113, 0,8,49, 0,9,195,
+ 80,7,10, 0,8,97, 0,8,33, 0,9,163,
+ 0,8,1, 0,8,129, 0,8,65, 0,9,227,
+ 80,7,6, 0,8,89, 0,8,25, 0,9,147,
+ 83,7,59, 0,8,121, 0,8,57, 0,9,211,
+ 81,7,17, 0,8,105, 0,8,41, 0,9,179,
+ 0,8,9, 0,8,137, 0,8,73, 0,9,243,
+ 80,7,4, 0,8,85, 0,8,21, 80,8,258,
+ 83,7,43, 0,8,117, 0,8,53, 0,9,203,
+ 81,7,13, 0,8,101, 0,8,37, 0,9,171,
+ 0,8,5, 0,8,133, 0,8,69, 0,9,235,
+ 80,7,8, 0,8,93, 0,8,29, 0,9,155,
+ 84,7,83, 0,8,125, 0,8,61, 0,9,219,
+ 82,7,23, 0,8,109, 0,8,45, 0,9,187,
+ 0,8,13, 0,8,141, 0,8,77, 0,9,251,
+ 80,7,3, 0,8,83, 0,8,19, 85,8,195,
+ 83,7,35, 0,8,115, 0,8,51, 0,9,199,
+ 81,7,11, 0,8,99, 0,8,35, 0,9,167,
+ 0,8,3, 0,8,131, 0,8,67, 0,9,231,
+ 80,7,7, 0,8,91, 0,8,27, 0,9,151,
+ 84,7,67, 0,8,123, 0,8,59, 0,9,215,
+ 82,7,19, 0,8,107, 0,8,43, 0,9,183,
+ 0,8,11, 0,8,139, 0,8,75, 0,9,247,
+ 80,7,5, 0,8,87, 0,8,23, 192,8,0,
+ 83,7,51, 0,8,119, 0,8,55, 0,9,207,
+ 81,7,15, 0,8,103, 0,8,39, 0,9,175,
+ 0,8,7, 0,8,135, 0,8,71, 0,9,239,
+ 80,7,9, 0,8,95, 0,8,31, 0,9,159,
+ 84,7,99, 0,8,127, 0,8,63, 0,9,223,
+ 82,7,27, 0,8,111, 0,8,47, 0,9,191,
+ 0,8,15, 0,8,143, 0,8,79, 0,9,255
+ };
+ static readonly int[] fixed_td = {
+ 80,5,1, 87,5,257, 83,5,17, 91,5,4097,
+ 81,5,5, 89,5,1025, 85,5,65, 93,5,16385,
+ 80,5,3, 88,5,513, 84,5,33, 92,5,8193,
+ 82,5,9, 90,5,2049, 86,5,129, 192,5,24577,
+ 80,5,2, 87,5,385, 83,5,25, 91,5,6145,
+ 81,5,7, 89,5,1537, 85,5,97, 93,5,24577,
+ 80,5,4, 88,5,769, 84,5,49, 92,5,12289,
+ 82,5,13, 90,5,3073, 86,5,193, 192,5,24577
+ };
+
+ // Tables for deflate from PKZIP's appnote.txt.
+ static readonly int[] cplens = { // Copy lengths for literal codes 257..285
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
+ };
+
+ // see note #13 above about 258
+ static readonly int[] cplext = { // Extra bits for literal codes 257..285
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+ 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112 // 112==invalid
+ };
+
+ static readonly int[] cpdist = { // Copy offsets for distance codes 0..29
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+ 8193, 12289, 16385, 24577
+ };
+
+ static readonly int[] cpdext = { // Extra bits for distance codes
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+ 12, 12, 13, 13};
+
+ ///
+ /// Maximum bit length of any code
+ ///
+ ///
+ /// If BMAX needs to be larger than 16, then h and x[] should be uLong.
+ ///
+ private const int BMAX = 15;
+
+ ///
+ /// hufts used in space
+ ///
+ private int[] _usedHufts = null;
+
+ ///
+ /// The work area for huft_build
+ ///
+ private int[] v = null;
+
+ ///
+ /// The bit length count table
+ ///
+ private int[] c = null;
+
+ ///
+ /// The table entry for structure assignment
+ ///
+ private int[] r = null;
+
+ ///
+ /// The table stack
+ ///
+ private int[] u = null;
+
+ ///
+ /// The bit offsets, then code stack
+ ///
+ private int[] x = null;
+
+ ///
+ /// Inflate_trees_bitses the specified c.
+ ///
+ /// The 19 code lengths.
+ /// The bits tree desired/actual depth.
+ /// The bits tree result.
+ /// The space for trees.
+ /// The for messages.
+ ///
+ protected ZLibStatus InflateTeesBits(int[] c, int[] bb, int[] tb, int[] hp, ZStream z)
+ {
+ ZLibStatus result;
+ InitWorkArea(19);
+ this._usedHufts[0] = 0;
+ result = HuftBuild(c, 0, 19, 19, null, null, tb, bb, hp, this._usedHufts, v);
+
+ if (result == ZLibStatus.Z_DATA_ERROR)
+ {
+ z.msg = "oversubscribed dynamic bit lengths tree";
+ }
+ else if (result == ZLibStatus.Z_BUF_ERROR || bb[0] == 0)
+ {
+ z.msg = "incomplete dynamic bit lengths tree";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ return result;
+ }
+
+ ///
+ /// Inflate_trees_dynamics the specified nl.
+ ///
+ /// The number of literal/length codes.
+ /// The number of distance codes.
+ /// The that many (total) code lengths.
+ /// The literal desired/actual bit depth.
+ /// The distance desired/actual bit depth .
+ /// The literal/length tree result.
+ /// The distance tree result.
+ /// The space for trees.
+ /// The for messages.
+ ///
+ protected ZLibStatus InflateTreesDynamic(int nl, int nd, int[] c, int[] bl, int[] bd, int[] tl, int[] td, int[] hp, ZStream z)
+ {
+ ZLibStatus result;
+
+ // build literal/length tree
+ InitWorkArea(288);
+ this._usedHufts[0] = 0;
+ result = HuftBuild(c, 0, nl, 257, cplens, cplext, tl, bl, hp, this._usedHufts, v);
+ if (result != ZLibStatus.Z_OK || bl[0] == 0)
+ {
+ if (result == ZLibStatus.Z_DATA_ERROR)
+ {
+ z.msg = "oversubscribed literal/length tree";
+ }
+ else if (result != ZLibStatus.Z_MEM_ERROR)
+ {
+ z.msg = "incomplete literal/length tree";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ return result;
+ }
+
+ // build distance tree
+ InitWorkArea(288);
+ result = HuftBuild(c, nl, nd, 0, cpdist, cpdext, td, bd, hp, this._usedHufts, v);
+
+ if (result != ZLibStatus.Z_OK || (bd[0] == 0 && nl > 257))
+ {
+ if (result == ZLibStatus.Z_DATA_ERROR)
+ {
+ z.msg = "oversubscribed distance tree";
+ }
+ else if (result == ZLibStatus.Z_BUF_ERROR)
+ {
+ z.msg = "incomplete distance tree";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ else if (result != ZLibStatus.Z_MEM_ERROR)
+ {
+ z.msg = "empty distance tree with lengths";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ return result;
+ }
+
+ return ZLibStatus.Z_OK;
+ }
+
+ ///
+ /// Inflate_trees_fixeds the specified bl.
+ ///
+ /// The literal desired/actual bit depth.
+ /// The distance desired/actual bit depth.
+ /// The literal/length tree result.
+ /// The distance tree result .
+ /// The for memory allocation.
+ ///
+ protected static ZLibStatus InflateTreesFixed(int[] bl, int[] bd, int[][] tl, int[][] td, ZStream z)
+ {
+ bl[0] = fixed_bl;
+ bd[0] = fixed_bd;
+ tl[0] = fixed_tl;
+ td[0] = fixed_td;
+ return ZLibStatus.Z_OK;
+ }
+
+ ///
+ /// Huft_builds the specified b.
+ ///
+ /// code lengths in bits (all assumed <= BMAX)
+ /// The bindex.
+ /// The number of codes (assumed <= 288).
+ /// The number of simple-valued codes (0..s-1).
+ /// The list of base values for non-simple codes.
+ /// The list of extra bits for non-simple codes.
+ /// The result: starting table.
+ /// The maximum lookup bits, returns actual.
+ /// The space for trees.
+ /// The hufts used in space.
+ /// The working area: values in order of bit length.
+ ///
+ private ZLibStatus HuftBuild(int[] b, int bindex, int n, int s, int[] d, int[] e, int[] t, int[] m, int[] hp, int[] hn, int[] v)
+ {
+ // Given a list of code lengths and a maximum table size, make a set of
+ // tables to decode that set of codes. Return ZLibStatus.Z_OK on success, ZLibStatus.Z_BUF_ERROR
+ // if the given code set is incomplete (the tables are still built in this
+ // case), ZLibStatus.Z_DATA_ERROR if the input is invalid (an over-subscribed set of
+ // lengths), or ZLibStatus.Z_MEM_ERROR if not enough memory.
+
+ int a; // counter for codes of length k
+ int f; // i repeats in table every f entries
+ int g; // maximum code length
+ int h; // table level
+ int i; // counter, current code
+ int j; // counter
+ int k; // number of bits in current code
+ int l; // bits per table (returned in m)
+ int mask; // (1 << w) - 1, to avoid cc -O bug on HP
+ int p; // pointer into c[], b[], or v[]
+ int q; // points to current table
+ int w; // bits before this table == (l * h)
+ int xp; // pointer into x
+ int y; // number of dummy codes added
+ int z; // number of entries in current table
+
+ // Generate counts for each bit length
+
+ p = 0; i = n;
+ do
+ {
+ c[b[bindex + p]]++; p++; i--; // assume all entries <= BMAX
+ } while (i != 0);
+
+ if (c[0] == n)
+ { // null input--all zero length codes
+ t[0] = -1;
+ m[0] = 0;
+ return ZLibStatus.Z_OK;
+ }
+
+ // Find minimum and maximum length, bound *m by those
+ l = m[0];
+ for (j = 1; j <= BMAX; j++)
+ if (c[j] != 0) break;
+ k = j; // minimum code length
+ if (l < j)
+ {
+ l = j;
+ }
+ for (i = BMAX; i != 0; i--)
+ {
+ if (c[i] != 0) break;
+ }
+ g = i; // maximum code length
+ if (l > i)
+ {
+ l = i;
+ }
+ m[0] = l;
+
+ // Adjust last length count to fill out codes, if needed
+ for (y = 1 << j; j < i; j++, y <<= 1)
+ {
+ if ((y -= c[j]) < 0)
+ {
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ }
+ if ((y -= c[i]) < 0)
+ {
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ c[i] += y;
+
+ // Generate starting offsets into the value table for each length
+ x[1] = j = 0;
+ p = 1; xp = 2;
+ while (--i != 0)
+ { // note that i == g from above
+ x[xp] = (j += c[p]);
+ xp++;
+ p++;
+ }
+
+ // Make a table of values in order of bit lengths
+ i = 0; p = 0;
+ do
+ {
+ if ((j = b[bindex + p]) != 0)
+ {
+ v[x[j]++] = i;
+ }
+ p++;
+ }
+ while (++i < n);
+ n = x[g]; // set n to length of v
+
+ // Generate the Huffman codes and for each, make the table entries
+ x[0] = i = 0; // first Huffman code is zero
+ p = 0; // grab values in bit order
+ h = -1; // no tables yet--level -1
+ w = -l; // bits decoded == (l * h)
+ u[0] = 0; // just to keep compilers happy
+ q = 0; // ditto
+ z = 0; // ditto
+
+ // go through the bit lengths (k already is bits in shortest code)
+ for (; k <= g; k++)
+ {
+ a = c[k];
+ while (a-- != 0)
+ {
+ // here i is the Huffman code of length k bits for value *p
+ // make tables up to required level
+ while (k > w + l)
+ {
+ h++;
+ w += l; // previous table always l bits
+ // compute minimum size table less than or equal to l bits
+ z = g - w;
+ z = (z > l) ? l : z; // table size upper limit
+ if ((f = 1 << (j = k - w)) > a + 1)
+ { // try a k-w bit table
+ // too few codes for k-w bit table
+ f -= a + 1; // deduct codes from patterns left
+ xp = k;
+ if (j < z)
+ {
+ while (++j < z)
+ { // try smaller tables up to z bits
+ if ((f <<= 1) <= c[++xp])
+ break; // enough codes to use up j bits
+ f -= c[xp]; // else deduct codes from patterns
+ }
+ }
+ }
+ z = 1 << j; // table entries for j-bit table
+
+ // allocate new table
+ if (hn[0] + z > MANY)
+ { // (note: doesn't matter for fixed)
+ return ZLibStatus.Z_DATA_ERROR; // overflow of MANY
+ }
+ u[h] = q = /*hp+*/ hn[0]; // DEBUG
+ hn[0] += z;
+
+ // connect to last table, if there is one
+ if (h != 0)
+ {
+ x[h] = i; // save pattern for backing up
+ r[0] = (byte)j; // bits in this table
+ r[1] = (byte)l; // bits to dump before this table
+ j = i >> (w - l);
+ r[2] = (int)(q - u[h - 1] - j); // offset to this table
+ System.Array.Copy(r, 0, hp, (u[h - 1] + j) * 3, 3); // connect to last table
+ }
+ else
+ {
+ t[0] = q; // first table is returned result
+ }
+ }
+
+ // set up table entry in r
+ r[1] = (byte)(k - w);
+ if (p >= n)
+ {
+ r[0] = 128 + 64; // out of values--invalid code
+ }
+ else if (v[p] < s)
+ {
+ r[0] = (byte)(v[p] < 256 ? 0 : 32 + 64); // 256 is end-of-block
+ r[2] = v[p++]; // simple code is just the value
+ }
+ else
+ {
+ r[0] = (byte)(e[v[p] - s] + 16 + 64); // non-simple--look up in lists
+ r[2] = d[v[p++] - s];
+ }
+
+ // fill code-like entries with r
+ f = 1 << (k - w);
+ for (j = i >> w; j < z; j += f)
+ {
+ System.Array.Copy(r, 0, hp, (q + j) * 3, 3);
+ }
+
+ // backwards increment the k-bit code i
+ for (j = 1 << (k - 1); (i & j) != 0; j >>= 1)
+ {
+ i ^= j;
+ }
+ i ^= j;
+
+ // backup over finished tables
+ mask = (1 << w) - 1; // needed on HP, cc -O bug
+ while ((i & mask) != x[h])
+ {
+ h--; // don't need to update q
+ w -= l;
+ mask = (1 << w) - 1;
+ }
+ }
+ }
+ // Return ZLibStatus.Z_BUF_ERROR if we were given an incomplete table
+ return y != 0 && g != 1 ? ZLibStatus.Z_BUF_ERROR : ZLibStatus.Z_OK;
+ }
+
+ private void InitWorkArea(int vsize)
+ {
+ if (this._usedHufts == null)
+ {
+ this._usedHufts = new int[1];
+ v = new int[vsize];
+ c = new int[BMAX + 1];
+ r = new int[3];
+ u = new int[BMAX];
+ x = new int[BMAX + 1];
+ }
+ if (v.Length < vsize)
+ {
+ v = new int[vsize];
+ }
+ for (int i = 0; i < vsize; i++) { v[i] = 0; }
+ for (int i = 0; i < BMAX + 1; i++) { c[i] = 0; }
+ for (int i = 0; i < 3; i++) { r[i] = 0; }
+ // for(int i=0; i
+ ///waiting for method byte
+ ///
+ METHOD = 0,
+ ///
+ /// waiting for flag byte
+ ///
+ FLAG = 1,
+ ///
+ /// four dictionary check bytes to go
+ ///
+ DICT4 = 2,
+ ///
+ /// three dictionary check bytes to go
+ ///
+ DICT3 = 3,
+ ///
+ /// two dictionary check bytes to go
+ ///
+ DICT2 = 4,
+ ///
+ /// one dictionary check byte to go
+ ///
+ DICT1 = 5,
+ ///
+ /// waiting for inflateSetDictionary
+ ///
+ DICT0 = 6,
+ ///
+ /// decompressing blocks
+ ///
+ BLOCKS = 7,
+ ///
+ /// four check bytes to go
+ ///
+ CHECK4 = 8,
+ ///
+ /// three check bytes to go
+ ///
+ CHECK3 = 9,
+ ///
+ /// two check bytes to go
+ ///
+ CHECK2 = 10,
+ ///
+ /// one check byte to go
+ ///
+ CHECK1 = 11,
+ ///
+ /// finished check, done
+ ///
+ DONE = 12,
+ ///
+ /// got an error--stay here
+ ///
+ BAD = 13
+ }
+
+ internal sealed class Inflate
+ {
+ ///
+ /// 32K LZ77 window
+ ///
+ private const int MAX_WBITS = 15;
+
+ ///
+ /// Preset dictionary flag in zlib header
+ ///
+ private const int PRESET_DICT = 0x20;
+
+ private const int Z_DEFLATED = 8;
+
+ private static readonly byte[] mark = { (byte)0, (byte)0, (byte)0xff, (byte)0xff };
+
+ ///
+ /// if FLAGS, method byte
+ ///
+ private int method;
+
+ ///
+ /// Computed check value
+ ///
+ private long[] was = new long[1];
+
+ ///
+ /// The stream check value
+ ///
+ private long need;
+
+ ///
+ /// if BAD, inflateSync's marker bytes count
+ ///
+ private int marker;
+
+ // mode independent information
+ ///
+ /// Flag for no wrapper
+ ///
+ private int nowrap;
+
+ ///
+ /// log2(window size) (8..15, defaults to 15)
+ ///
+ private int wbits;
+
+ ///
+ /// Current inflate_blocks state
+ ///
+ private InfBlocks blocks;
+
+ ///
+ /// Gets the current inflate mode.
+ ///
+ ///
+ /// The mode.
+ ///
+ internal InflateMode Mode { get; private set; }
+
+ internal ZLibStatus InflateReset(ZStream z)
+ {
+ if (z == null || z.istate == null) return ZLibStatus.Z_STREAM_ERROR;
+
+ z.total_in = z.total_out = 0;
+ z.msg = null;
+ z.istate.Mode = z.istate.nowrap != 0 ? InflateMode.BLOCKS : InflateMode.METHOD;
+ z.istate.blocks.Reset(z, null);
+ return ZLibStatus.Z_OK;
+ }
+
+ internal ZLibStatus InflateEnd(ZStream z)
+ {
+ if (blocks != null)
+ blocks.free(z);
+ blocks = null;
+ // ZFREE(z, z->state);
+ return ZLibStatus.Z_OK;
+ }
+
+ internal ZLibStatus InflateInit(ZStream z, int w)
+ {
+ z.msg = null;
+ blocks = null;
+
+ // handle undocumented nowrap option (no zlib header or check)
+ nowrap = 0;
+ if (w < 0)
+ {
+ w = -w;
+ nowrap = 1;
+ }
+
+ // set window size
+ if (w < 8 || w > 15)
+ {
+ InflateEnd(z);
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+ wbits = w;
+
+ z.istate.blocks = new InfBlocks(z,
+ z.istate.nowrap != 0 ? null : this,
+ 1 << w);
+
+ // reset state
+ InflateReset(z);
+ return ZLibStatus.Z_OK;
+ }
+
+ internal ZLibStatus inflate(ZStream z, FlushType ff)
+ {
+ ZLibStatus r;
+ int b;
+
+ if (z == null || z.istate == null || z.next_in == null)
+ return ZLibStatus.Z_STREAM_ERROR;
+ var f = ff == FlushType.Z_FINISH ? ZLibStatus.Z_BUF_ERROR : ZLibStatus.Z_OK;
+ r = ZLibStatus.Z_BUF_ERROR;
+ while (true)
+ {
+ //System.out.println("mode: "+z.istate.mode);
+ switch (z.istate.Mode)
+ {
+ case InflateMode.METHOD:
+
+ if (z.avail_in == 0) return r; r = f;
+
+ z.avail_in--; z.total_in++;
+ if (((z.istate.method = z.next_in[z.next_in_index++]) & 0xf) != Z_DEFLATED)
+ {
+ z.istate.Mode = InflateMode.BAD;
+ z.msg = "unknown compression method";
+ z.istate.marker = 5; // can't try inflateSync
+ break;
+ }
+ if ((z.istate.method >> 4) + 8 > z.istate.wbits)
+ {
+ z.istate.Mode = InflateMode.BAD;
+ z.msg = "invalid window size";
+ z.istate.marker = 5; // can't try inflateSync
+ break;
+ }
+ z.istate.Mode = InflateMode.FLAG;
+ goto case InflateMode.FLAG;
+ case InflateMode.FLAG:
+
+ if (z.avail_in == 0) return r; r = f;
+
+ z.avail_in--; z.total_in++;
+ b = (z.next_in[z.next_in_index++]) & 0xff;
+
+ if ((((z.istate.method << 8) + b) % 31) != 0)
+ {
+ z.istate.Mode = InflateMode.BAD;
+ z.msg = "incorrect header check";
+ z.istate.marker = 5; // can't try inflateSync
+ break;
+ }
+
+ if ((b & PRESET_DICT) == 0)
+ {
+ z.istate.Mode = InflateMode.BLOCKS;
+ break;
+ }
+ z.istate.Mode = InflateMode.DICT4;
+ goto case InflateMode.DICT4;
+ case InflateMode.DICT4:
+
+ if (z.avail_in == 0) return r; r = f;
+
+ z.avail_in--; z.total_in++;
+ z.istate.need = ((z.next_in[z.next_in_index++] & 0xff) << 24) & 0xff000000L;
+ z.istate.Mode = InflateMode.DICT3;
+ goto case InflateMode.DICT3;
+ case InflateMode.DICT3:
+
+ if (z.avail_in == 0) return r; r = f;
+
+ z.avail_in--; z.total_in++;
+ z.istate.need += ((z.next_in[z.next_in_index++] & 0xff) << 16) & 0xff0000L;
+ z.istate.Mode = InflateMode.DICT2;
+ goto case InflateMode.DICT2;
+ case InflateMode.DICT2:
+
+ if (z.avail_in == 0) return r; r = f;
+
+ z.avail_in--; z.total_in++;
+ z.istate.need += ((z.next_in[z.next_in_index++] & 0xff) << 8) & 0xff00L;
+ z.istate.Mode = InflateMode.DICT1;
+ goto case InflateMode.DICT1;
+ case InflateMode.DICT1:
+
+ if (z.avail_in == 0) return r; r = f;
+
+ z.avail_in--; z.total_in++;
+ z.istate.need += (z.next_in[z.next_in_index++] & 0xffL);
+ z.Adler = z.istate.need;
+ z.istate.Mode = InflateMode.DICT0;
+ return ZLibStatus.Z_NEED_DICT;
+ case InflateMode.DICT0:
+ z.istate.Mode = InflateMode.BAD;
+ z.msg = "need dictionary";
+ z.istate.marker = 0; // can try inflateSync
+ return ZLibStatus.Z_STREAM_ERROR;
+ case InflateMode.BLOCKS:
+
+ r = z.istate.blocks.ProcessBlocks(z, r);
+ if (r == ZLibStatus.Z_DATA_ERROR)
+ {
+ z.istate.Mode = InflateMode.BAD;
+ z.istate.marker = 0; // can try inflateSync
+ break;
+ }
+ if (r == ZLibStatus.Z_OK)
+ {
+ r = f;
+ }
+ if (r != ZLibStatus.Z_STREAM_END)
+ {
+ return r;
+ }
+ r = f;
+ z.istate.blocks.Reset(z, z.istate.was);
+ if (z.istate.nowrap != 0)
+ {
+ z.istate.Mode = InflateMode.DONE;
+ break;
+ }
+ z.istate.Mode = InflateMode.CHECK4;
+ goto case InflateMode.CHECK4;
+ case InflateMode.CHECK4:
+
+ if (z.avail_in == 0) return r; r = f;
+
+ z.avail_in--; z.total_in++;
+ z.istate.need = ((z.next_in[z.next_in_index++] & 0xff) << 24) & 0xff000000L;
+ z.istate.Mode = InflateMode.CHECK3;
+ goto case InflateMode.CHECK3;
+ case InflateMode.CHECK3:
+
+ if (z.avail_in == 0) return r; r = f;
+
+ z.avail_in--; z.total_in++;
+ z.istate.need += ((z.next_in[z.next_in_index++] & 0xff) << 16) & 0xff0000L;
+ z.istate.Mode = InflateMode.CHECK2;
+ goto case InflateMode.CHECK2;
+ case InflateMode.CHECK2:
+
+ if (z.avail_in == 0) return r; r = f;
+
+ z.avail_in--; z.total_in++;
+ z.istate.need += ((z.next_in[z.next_in_index++] & 0xff) << 8) & 0xff00L;
+ z.istate.Mode = InflateMode.CHECK1;
+ goto case InflateMode.CHECK1;
+ case InflateMode.CHECK1:
+
+ if (z.avail_in == 0) return r; r = f;
+
+ z.avail_in--; z.total_in++;
+ z.istate.need += (z.next_in[z.next_in_index++] & 0xffL);
+
+ if (((int)(z.istate.was[0])) != ((int)(z.istate.need)))
+ {
+ z.istate.Mode = InflateMode.BAD;
+ z.msg = "incorrect data check";
+ z.istate.marker = 5; // can't try inflateSync
+ break;
+ }
+
+ z.istate.Mode = InflateMode.DONE;
+ goto case InflateMode.DONE;
+ case InflateMode.DONE:
+ return ZLibStatus.Z_STREAM_END;
+ case InflateMode.BAD:
+ return ZLibStatus.Z_DATA_ERROR;
+ default:
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+ }
+ }
+
+ //internal ZLibStatus InflateSetDictionary(ZStream z, byte[] dictionary, int dictLength)
+ //{
+ // int index = 0;
+ // int length = dictLength;
+ // if (z == null || z.istate == null || z.istate.Mode != InflateMode.DICT0)
+ // return ZLibStatus.Z_STREAM_ERROR;
+
+ // if (z.Adler32(1L, dictionary, 0, dictLength) != z.Adler)
+ // {
+ // return ZLibStatus.Z_DATA_ERROR;
+ // }
+
+ // //z.adler = z.Adler32(0, null, 0, 0);
+ // z.UpdateAdler(0, null, 0, 0);
+
+ // if (length >= (1 << z.istate.wbits))
+ // {
+ // length = (1 << z.istate.wbits) - 1;
+ // index = dictLength - length;
+ // }
+ // z.istate.blocks.set_dictionary(dictionary, index, length);
+ // z.istate.Mode = InflateMode.BLOCKS;
+ // return ZLibStatus.Z_OK;
+ //}
+
+ internal ZLibStatus InflateSync(ZStream z)
+ {
+ int n; // number of bytes to look at
+ int p; // pointer to bytes
+ int m; // number of marker bytes found in a row
+ long r, w; // temporaries to save total_in and total_out
+
+ // set up
+ if (z == null || z.istate == null)
+ return ZLibStatus.Z_STREAM_ERROR;
+ if (z.istate.Mode != InflateMode.BAD)
+ {
+ z.istate.Mode = InflateMode.BAD;
+ z.istate.marker = 0;
+ }
+ if ((n = z.avail_in) == 0)
+ return ZLibStatus.Z_BUF_ERROR;
+ p = z.next_in_index;
+ m = z.istate.marker;
+
+ // search
+ while (n != 0 && m < 4)
+ {
+ if (z.next_in[p] == mark[m])
+ {
+ m++;
+ }
+ else if (z.next_in[p] != 0)
+ {
+ m = 0;
+ }
+ else
+ {
+ m = 4 - m;
+ }
+ p++; n--;
+ }
+
+ // restore
+ z.total_in += p - z.next_in_index;
+ z.next_in_index = p;
+ z.avail_in = n;
+ z.istate.marker = m;
+
+ // return no joy or set up to restart on a new block
+ if (m != 4)
+ {
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ r = z.total_in; w = z.total_out;
+ InflateReset(z);
+ z.total_in = r; z.total_out = w;
+ z.istate.Mode = InflateMode.BLOCKS;
+ return ZLibStatus.Z_OK;
+ }
+
+ // Returns true if inflate is currently at the end of a block generated
+ // by FlushType.Z_SYNC_FLUSH or FlushType.Z_FULL_FLUSH. This function is used by one PPP
+ // implementation to provide an additional safety check. PPP uses FlushType.Z_SYNC_FLUSH
+ // but removes the length bytes of the resulting empty stored block. When
+ // decompressing, PPP checks that at the end of input packet, inflate is
+ // waiting for these length bytes.
+ //internal ZLibStatus InflateSyncPoint(ZStream z)
+ //{
+ // if (z == null || z.istate == null || z.istate.blocks == null)
+ // return ZLibStatus.Z_STREAM_ERROR;
+ // return z.istate.blocks.sync_point();
+ //}
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Working.1/JZlib.cs b/Renci.SshNet/Compression/Working.1/JZlib.cs
new file mode 100644
index 0000000..1e6d7d8
--- /dev/null
+++ b/Renci.SshNet/Compression/Working.1/JZlib.cs
@@ -0,0 +1,111 @@
+using System;
+/*
+ * $Id: JZlib.cs,v 1.3 2011-02-15 05:46:04 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ // TODO: Double posat her, fix array initialization where it is now dictionary
+ public enum CompressionLevel : int
+ {
+ Z_NO_COMPRESSION = 0,
+ Z_BEST_SPEED = 1,
+ Z_BEST_COMPRESSION = 9,
+ Z_DEFAULT_COMPRESSION = -1
+ }
+ public enum FlushType
+ {
+ Z_NO_FLUSH = 0,
+ Z_PARTIAL_FLUSH = 1,
+ Z_SYNC_FLUSH = 2,
+ Z_FULL_FLUSH = 3,
+ Z_FINISH = 4
+ }
+ public enum CompressionStrategy
+ {
+ Z_FILTERED = 1,
+ Z_HUFFMAN_ONLY = 2,
+ Z_DEFAULT_STRATEGY = 0
+ }
+
+ public enum ZLibStatus
+ {
+ Z_OK = 0,
+ Z_STREAM_END = 1,
+ Z_NEED_DICT = 2,
+ Z_ERRNO = -1,
+ Z_STREAM_ERROR = -2,
+ Z_DATA_ERROR = -3,
+ Z_MEM_ERROR = -4,
+ Z_BUF_ERROR = -5,
+ Z_VERSION_ERROR = -6
+
+ }
+ public sealed class JZlib
+ {
+ private const String _version = "1.0.7";
+ public static String version()
+ {
+ return _version;
+ }
+
+ // compression levels
+ //public const int Z_NO_COMPRESSION = 0;
+ //public const int Z_BEST_SPEED = 1;
+ //public const int Z_BEST_COMPRESSION = 9;
+ //public const int Z_DEFAULT_COMPRESSION = -1;
+
+ // compression strategy
+ //public const int CompressionStrategy.Z_FILTERED = 1;
+ //public const int CompressionStrategy.Z_HUFFMAN_ONLY = 2;
+ //public const int CompressionStrategy.Z_DEFAULT_STRATEGY = 0;
+
+ //public const int FlushType.Z_NO_FLUSH = 0;
+ //public const int FlushType.Z_PARTIAL_FLUSH = 1;
+ //public const int FlushType.Z_SYNC_FLUSH = 2;
+ //public const int FlushType.Z_FULL_FLUSH = 3;
+ //public const int FlushType.Z_FINISH = 4;
+
+ //public const int ZLibStatus.Z_OK = 0;
+ //public const int ZLibStatus.Z_STREAM_END = 1;
+ //public const int ZLibStatus.Z_NEED_DICT = 2;
+ //public const int ZLibStatus.Z_ERRNO = -1;
+ //public const int ZLibStatus.Z_STREAM_ERROR = -2;
+ //public const int ZLibStatus.Z_DATA_ERROR = -3;
+ //public const int ZLibStatus.Z_MEM_ERROR = -4;
+ //public const int ZLibStatus.Z_BUF_ERROR = -5;
+ //public const int ZLibStatus.Z_VERSION_ERROR = -6;
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Working.1/StaticTree.cs b/Renci.SshNet/Compression/Working.1/StaticTree.cs
new file mode 100644
index 0000000..1ee3d35
--- /dev/null
+++ b/Renci.SshNet/Compression/Working.1/StaticTree.cs
@@ -0,0 +1,98 @@
+using System;
+/*
+ * $Id: StaticTree.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+ internal sealed class StaticTree
+ {
+ ///
+ /// Gets the static tree or null
+ ///
+ ///
+ /// The static_tree.
+ ///
+ public short[] TreeData { get; private set; }
+
+ ///
+ /// Gets the extra bits for each code or null.
+ ///
+ ///
+ /// The extra bits.
+ ///
+ public int[] ExtraBits { get; private set; }
+
+ ///
+ /// Gets the base index for extra_bits.
+ ///
+ ///
+ /// The extra base.
+ ///
+ public int ExtraBase { get; private set; }
+
+ ///
+ /// Gets the max number of elements in the tree.
+ ///
+ ///
+ /// The elements.
+ ///
+ public int Elements { get; private set; }
+
+ ///
+ /// Gets the max bit length for the codes.
+ ///
+ ///
+ /// The length of the max.
+ ///
+ public int MaxLength { get; private set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The tree data.
+ /// The extra bits.
+ /// The extra base.
+ /// The elements.
+ /// Length of the max.
+ public StaticTree(short[] treeData, int[] extraBits, int extraBase, int elements, int maxLength)
+ {
+ this.TreeData = treeData;
+ this.ExtraBits = extraBits;
+ this.ExtraBase = extraBase;
+ this.Elements = elements;
+ this.MaxLength = maxLength;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Working.1/Tree.cs b/Renci.SshNet/Compression/Working.1/Tree.cs
new file mode 100644
index 0000000..33849c8
--- /dev/null
+++ b/Renci.SshNet/Compression/Working.1/Tree.cs
@@ -0,0 +1,333 @@
+using System;
+/*
+ * $Id: Tree.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+ internal sealed class Tree
+ {
+ private const int MAX_BITS = 15;
+
+ private const int LITERALS = 256;
+
+ private const int LENGTH_CODES = 29;
+
+ private const int L_CODES = (LITERALS + 1 + LENGTH_CODES);
+
+ private const int HEAP_SIZE = (2 * L_CODES + 1);
+
+ private static byte[] _dist_code = {
+ 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8,
+ 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17,
+ 18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
+ 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
+ };
+
+
+ ///
+ /// The corresponding static tree
+ ///
+ private StaticTree _staticTree;
+
+ ///
+ /// The dynamic tree
+ ///
+ private short[] _dynamicTree;
+
+ ///
+ /// Gets the largest code with non zero frequency.
+ ///
+ ///
+ /// The max_code.
+ ///
+ public int LargestCode { get; private set; }
+
+ public void Init(short[] dynamicTree, StaticTree staticTree)
+ {
+ this._staticTree = staticTree;
+ this._dynamicTree = dynamicTree;
+ }
+
+ ///
+ /// Mapping from a distance to a distance code. dist is the distance - 1 and must not have side effects. _dist_code[256] and _dist_code[257] are never used.
+ ///
+ /// The dist.
+ ///
+ public static int DistanceCode(int dist)
+ {
+ return ((dist) < 256 ? _dist_code[dist] : _dist_code[256 + ((dist) >> 7)]);
+ }
+
+ ///
+ /// Construct one Huffman tree and assigns the code bit strings and lengths. Update the total bit length for the current block.
+ ///
+ /// The s.
+ public void BuildTree(Deflate s)
+ {
+ short[] tree = _dynamicTree;
+ short[] stree = _staticTree.TreeData;
+ int elems = _staticTree.Elements;
+ int n, m; // iterate over heap elements
+ int max_code = -1; // largest code with non zero frequency
+ int node; // new node being created
+
+ // Construct the initial heap, with least frequent element in
+ // heap[1]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
+ // heap[0] is not used.
+ s.heap_len = 0;
+ s.heap_max = HEAP_SIZE;
+
+ for (n = 0; n < elems; n++)
+ {
+ if (tree[n * 2] != 0)
+ {
+ s.heap[++s.heap_len] = max_code = n;
+ s.depth[n] = 0;
+ }
+ else
+ {
+ tree[n * 2 + 1] = 0;
+ }
+ }
+
+ // The pkzip format requires that at least one distance code exists,
+ // and that at least one bit should be sent even if there is only one
+ // possible code. So to avoid special checks later on we force at least
+ // two codes of non zero frequency.
+ while (s.heap_len < 2)
+ {
+ node = s.heap[++s.heap_len] = (max_code < 2 ? ++max_code : 0);
+ tree[node * 2] = 1;
+ s.depth[node] = 0;
+ s.opt_len--; if (stree != null) s.static_len -= stree[node * 2 + 1];
+ // node is 0 or 1 so it does not have extra bits
+ }
+ this.LargestCode = max_code;
+
+ // The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
+ // establish sub-heaps of increasing lengths:
+
+ for (n = s.heap_len / 2; n >= 1; n--)
+ s.pqdownheap(tree, n);
+
+ // Construct the Huffman tree by repeatedly combining the least two
+ // frequent nodes.
+
+ node = elems; // next internal node of the tree
+ do
+ {
+ // n = node of least frequency
+ n = s.heap[1];
+ s.heap[1] = s.heap[s.heap_len--];
+ s.pqdownheap(tree, 1);
+ m = s.heap[1]; // m = node of next least frequency
+
+ s.heap[--s.heap_max] = n; // keep the nodes sorted by frequency
+ s.heap[--s.heap_max] = m;
+
+ // Create a new node father of n and m
+ tree[node * 2] = (short)(tree[n * 2] + tree[m * 2]);
+ s.depth[node] = (byte)(System.Math.Max(s.depth[n], s.depth[m]) + 1);
+ tree[n * 2 + 1] = tree[m * 2 + 1] = (short)node;
+
+ // and insert the new node in the heap
+ s.heap[1] = node++;
+ s.pqdownheap(tree, 1);
+ }
+ while (s.heap_len >= 2);
+
+ s.heap[--s.heap_max] = s.heap[1];
+
+ // At this point, the fields freq and dad are set. We can now
+ // generate the bit lengths.
+
+ ComputeBitLength(s);
+
+ // The field len is now set, we can generate the bit codes
+ GenerateCodes(tree, max_code, s.bl_count);
+ }
+
+ ///
+ /// Compute the optimal bit lengths for a tree and update the total bit length for the current block.
+ ///
+ /// The s.
+ private void ComputeBitLength(Deflate s)
+ {
+ short[] tree = _dynamicTree;
+ short[] stree = _staticTree.TreeData;
+ int[] extra = _staticTree.ExtraBits;
+ int based = _staticTree.ExtraBase;
+ int max_length = _staticTree.MaxLength;
+ int h; // heap index
+ int n, m; // iterate over the tree elements
+ int bits; // bit length
+ int xbits; // extra bits
+ short f; // frequency
+ int overflow = 0; // number of elements with bit length too large
+
+ for (bits = 0; bits <= MAX_BITS; bits++) s.bl_count[bits] = 0;
+
+ // In a first pass, compute the optimal bit lengths (which may
+ // overflow in the case of the bit length tree).
+ tree[s.heap[s.heap_max] * 2 + 1] = 0; // root of the heap
+
+ for (h = s.heap_max + 1; h < HEAP_SIZE; h++)
+ {
+ n = s.heap[h];
+ bits = tree[tree[n * 2 + 1] * 2 + 1] + 1;
+ if (bits > max_length) { bits = max_length; overflow++; }
+ tree[n * 2 + 1] = (short)bits;
+ // We overwrite tree[n*2+1] which is no longer needed
+
+ if (n > LargestCode) continue; // not a leaf node
+
+ s.bl_count[bits]++;
+ xbits = 0;
+ if (n >= based) xbits = extra[n - based];
+ f = tree[n * 2];
+ s.opt_len += f * (bits + xbits);
+ if (stree != null) s.static_len += f * (stree[n * 2 + 1] + xbits);
+ }
+ if (overflow == 0) return;
+
+ // This happens for example on obj2 and pic of the Calgary corpus
+ // Find the first bit length which could increase:
+ do
+ {
+ bits = max_length - 1;
+ while (s.bl_count[bits] == 0) bits--;
+ s.bl_count[bits]--; // move one leaf down the tree
+ s.bl_count[bits + 1] += 2; // move one overflow item as its brother
+ s.bl_count[max_length]--;
+ // The brother of the overflow item also moves one step up,
+ // but this does not affect bl_count[max_length]
+ overflow -= 2;
+ }
+ while (overflow > 0);
+
+ for (bits = max_length; bits != 0; bits--)
+ {
+ n = s.bl_count[bits];
+ while (n != 0)
+ {
+ m = s.heap[--h];
+ if (m > LargestCode) continue;
+ if (tree[m * 2 + 1] != bits)
+ {
+ s.opt_len += (int)(((long)bits - (long)tree[m * 2 + 1]) * (long)tree[m * 2]);
+ tree[m * 2 + 1] = (short)bits;
+ }
+ n--;
+ }
+ }
+ }
+
+ ///
+ /// Generate the codes for a given tree and bit counts (which need not be optimal).
+ ///
+ /// The tree to decorate.
+ /// The largest code with non zero frequency.
+ /// The number of codes at each bit length.
+ private static void GenerateCodes(short[] tree, int max_code, short[] bl_count)
+ {
+ short[] next_code = new short[MAX_BITS + 1]; // next code value for each bit length
+ short code = 0; // running code value
+ int bits; // bit index
+ int n; // code index
+
+ // The distribution counts are first used to generate the code values
+ // without bit reversal.
+ for (bits = 1; bits <= MAX_BITS; bits++)
+ {
+ next_code[bits] = code = (short)((code + bl_count[bits - 1]) << 1);
+ }
+
+ // Check that the bit counts in bl_count are consistent. The last code
+ // must be all ones.
+ //Assert (code + bl_count[MAX_BITS]-1 == (1<
+ /// Reverse the first len bits of a code, using straightforward code (a faster method would use a table)
+ ///
+ /// The value to invert.
+ /// The bit length.
+ ///
+ private static int BiReverse(int code, int len)
+ {
+ int res = 0;
+ do
+ {
+ res |= code & 1;
+ code >>= 1;
+ res <<= 1;
+ }
+ while (--len > 0);
+ return res >> 1;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Working.1/ZInputStream.cs b/Renci.SshNet/Compression/Working.1/ZInputStream.cs
new file mode 100644
index 0000000..2a2722e
--- /dev/null
+++ b/Renci.SshNet/Compression/Working.1/ZInputStream.cs
@@ -0,0 +1,192 @@
+/*
+Copyright (c) 2001 Lapo Luchini.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS
+OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+/* This file is a port of jzlib v1.0.7, com.jcraft.jzlib.ZInputStream.java
+ */
+
+using System;
+using System.Diagnostics;
+using System.IO;
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+ public class ZInputStream : ZStream
+ {
+ private const int BufferSize = 512;
+
+ //protected ZStream z = new ZStream();
+ protected FlushType flushLevel = FlushType.Z_NO_FLUSH;
+ // TODO Allow custom buf
+ protected byte[] buf = new byte[BufferSize];
+ protected byte[] buf1 = new byte[1];
+ protected bool compress;
+
+ protected Stream input;
+ protected bool closed;
+
+ private bool nomoreinput = false;
+
+ public ZInputStream(Stream input)
+ : this(input, false)
+ {
+ }
+
+ public ZInputStream(Stream input, bool nowrap)
+ {
+ Debug.Assert(input.CanRead);
+
+ this.input = input;
+ this.inflateInit(nowrap);
+ this.compress = false;
+ this.next_in = buf;
+ this.next_in_index = 0;
+ this.avail_in = 0;
+ }
+
+ public ZInputStream(Stream input, CompressionLevel level)
+ {
+ Debug.Assert(input.CanRead);
+
+ this.input = input;
+ this.deflateInit(level);
+ this.compress = true;
+ this.next_in = buf;
+ this.next_in_index = 0;
+ this.avail_in = 0;
+ }
+
+ /*public int available() throws IOException {
+ return inf.finished() ? 0 : 1;
+ }*/
+
+ public sealed override bool CanRead { get { return !closed; } }
+ public sealed override bool CanSeek { get { return false; } }
+ public sealed override bool CanWrite { get { return false; } }
+
+ public override void Close()
+ {
+ if (!closed)
+ {
+ closed = true;
+ input.Close();
+ }
+ }
+
+ public sealed override void Flush() {}
+
+ public virtual FlushType FlushMode
+ {
+ get { return flushLevel; }
+ set { this.flushLevel = value; }
+ }
+
+ public sealed override long Length { get { throw new NotSupportedException(); } }
+ public sealed override long Position
+ {
+ get { throw new NotSupportedException(); }
+ set { throw new NotSupportedException(); }
+ }
+
+ public override int Read(byte[] b, int off, int len)
+ {
+ if (len==0)
+ return 0;
+
+ this.next_out = b;
+ this.next_out_index = off;
+ this.avail_out = len;
+
+ ZLibStatus err;
+ do
+ {
+ if (this.avail_in == 0 && !nomoreinput)
+ {
+ // if buffer is empty and more input is available, refill it
+ this.next_in_index = 0;
+ this.avail_in = input.Read(buf, 0, buf.Length); //(bufsize 0 || this.avail_out == 0);
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ base.Dispose(disposing);
+
+ if (this._isDisposed)
+ return;
+
+ try
+ {
+ do
+ {
+ this.next_out = this._bufffer;
+ this.next_out_index = 0;
+ this.avail_out = this._bufffer.Length;
+
+ var err = compress? this.deflate(FlushType.Z_FINISH) : this.inflate(FlushType.Z_FINISH);
+
+ if (err != ZLibStatus.Z_STREAM_END && err != ZLibStatus.Z_OK)
+ throw new IOException((compress ? "de" : "in") + "flating: " + this.msg);
+
+ int count = this._bufffer.Length - this.avail_out;
+ if (count > 0)
+ {
+ this._output.Write(this._bufffer, 0, count);
+ }
+ }
+ while (this.avail_in > 0 || this.avail_out == 0);
+
+ this.Flush();
+ }
+ finally
+ {
+ this._isDisposed = true;
+ if (compress)
+ this.deflateEnd();
+ else
+ this.inflateEnd();
+ this._output.Close();
+ this._output = null;
+ }
+ }
+ }
+}
diff --git a/Renci.SshNet/Compression/Working.1/ZStream.cs b/Renci.SshNet/Compression/Working.1/ZStream.cs
new file mode 100644
index 0000000..bebfebc
--- /dev/null
+++ b/Renci.SshNet/Compression/Working.1/ZStream.cs
@@ -0,0 +1,274 @@
+using System;
+using System.IO;
+/*
+ * $Id: ZStream.cs,v 1.1 2006-07-31 13:59:26 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public abstract class ZStream : Stream
+ {
+ private const int MAX_WBITS = 15; // 32K LZ77 window
+ private const int DEF_WBITS = MAX_WBITS;
+ private const int MAX_MEM_LEVEL = 9;
+
+ public byte[] next_in; // next input byte
+ public int next_in_index;
+ public int avail_in; // number of bytes available at next_in
+ public long total_in; // total nb of input bytes read so far
+
+ public byte[] next_out; // next output byte should be put there
+ public int next_out_index;
+ public int avail_out; // remaining free space at next_out
+ public long total_out; // total nb of bytes output so far
+
+ public String msg;
+
+ internal Deflate dstate;
+ internal Inflate istate;
+
+ //internal int data_type; // best guess about the data type: ascii or binary
+
+ // TODO: Make setter private
+ public long Adler { get; set; }
+ //internal Adler32 _adler = new Adler32();
+
+ // largest prime smaller than 65536
+ private const int ADLER32_BASE = 65521;
+ // NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
+ private const int ADLER32_NMAX = 5552;
+
+ internal long Adler32(long adler, byte[] buf, int index, int len)
+ {
+ if (buf == null) { return 1L; }
+
+ long s1 = adler & 0xffff;
+ long s2 = (adler >> 16) & 0xffff;
+ int k;
+
+ while (len > 0)
+ {
+ k = len < ADLER32_NMAX ? len : ADLER32_NMAX;
+ len -= k;
+ while (k >= 16)
+ {
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ k -= 16;
+ }
+ if (k != 0)
+ {
+ do
+ {
+ s1 += buf[index++] & 0xff; s2 += s1;
+ }
+ while (--k != 0);
+ }
+ s1 %= ADLER32_BASE;
+ s2 %= ADLER32_BASE;
+ }
+ return (s2 << 16) | s1;
+ }
+
+ internal void UpdateAdler(long adler, byte[] buf, int index, int len)
+ {
+ this.Adler = this.Adler32(adler, buf, index, len);
+ }
+ internal void UpdateAdler(byte[] buf, int index, int len)
+ {
+ this.Adler = this.Adler32(this.Adler, buf, index, len);
+ }
+
+
+ protected ZLibStatus inflateInit()
+ {
+ return inflateInit(DEF_WBITS);
+ }
+ protected ZLibStatus inflateInit(bool nowrap)
+ {
+ return inflateInit(DEF_WBITS, nowrap);
+ }
+ protected ZLibStatus inflateInit(int w)
+ {
+ return inflateInit(w, false);
+ }
+ protected ZLibStatus inflateInit(int w, bool nowrap)
+ {
+ istate = new Inflate();
+ return istate.InflateInit(this, nowrap ? -w : w);
+ }
+ protected ZLibStatus inflate(FlushType f)
+ {
+ if (istate == null) return ZLibStatus.Z_STREAM_ERROR;
+ return istate.inflate(this, f);
+ }
+ protected ZLibStatus inflateEnd()
+ {
+ if (istate == null) return ZLibStatus.Z_STREAM_ERROR;
+ var ret = istate.InflateEnd(this);
+ istate = null;
+ return ret;
+ }
+ protected ZLibStatus inflateSync()
+ {
+ if (istate == null)
+ return ZLibStatus.Z_STREAM_ERROR;
+ return istate.InflateSync(this);
+ }
+ //protected ZLibStatus inflateSetDictionary(byte[] dictionary, int dictLength)
+ //{
+ // if (istate == null)
+ // return ZLibStatus.Z_STREAM_ERROR;
+ // return istate.InflateSetDictionary(this, dictionary, dictLength);
+ //}
+
+ protected ZLibStatus deflateInit(CompressionLevel level)
+ {
+ return deflateInit(level, MAX_WBITS);
+ }
+ protected ZLibStatus deflateInit(CompressionLevel level, bool nowrap)
+ {
+ return deflateInit(level, MAX_WBITS, nowrap);
+ }
+ protected ZLibStatus deflateInit(CompressionLevel level, int bits)
+ {
+ return deflateInit(level, bits, false);
+ }
+ protected ZLibStatus deflateInit(CompressionLevel level, int bits, bool nowrap)
+ {
+ dstate = new Deflate();
+ return dstate.deflateInit(this, level, nowrap ? -bits : bits);
+ }
+ public ZLibStatus deflate(FlushType flush)
+ {
+ if (dstate == null)
+ {
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+ return dstate.deflate(this, flush);
+ }
+ protected ZLibStatus deflateEnd()
+ {
+ if (dstate == null) return ZLibStatus.Z_STREAM_ERROR;
+ var ret = dstate.deflateEnd();
+ dstate = null;
+ return ret;
+ }
+ protected ZLibStatus deflateParams(CompressionLevel level, CompressionStrategy strategy)
+ {
+ if (dstate == null) return ZLibStatus.Z_STREAM_ERROR;
+ return dstate.deflateParams(this, level, strategy);
+ }
+ protected ZLibStatus deflateSetDictionary(byte[] dictionary, int dictLength)
+ {
+ if (dstate == null)
+ return ZLibStatus.Z_STREAM_ERROR;
+ return dstate.deflateSetDictionary(this, dictionary, dictLength);
+ }
+
+ // Flush as much pending output as possible. All deflate() output goes
+ // through this function so some applications may wish to modify it
+ // to avoid allocating a large strm->next_out buffer and copying into it.
+ // (See also read_buf()).
+ internal void flush_pending()
+ {
+ int len = dstate.pending;
+
+ if (len > avail_out) len = avail_out;
+ if (len == 0) return;
+
+ if (dstate.pending_buf.Length <= dstate.pending_out ||
+ next_out.Length <= next_out_index ||
+ dstate.pending_buf.Length < (dstate.pending_out + len) ||
+ next_out.Length < (next_out_index + len))
+ {
+ // System.out.println(dstate.pending_buf.length+", "+dstate.pending_out+
+ // ", "+next_out.length+", "+next_out_index+", "+len);
+ // System.out.println("avail_out="+avail_out);
+ }
+
+ System.Array.Copy(dstate.pending_buf, dstate.pending_out,
+ next_out, next_out_index, len);
+
+ next_out_index += len;
+ dstate.pending_out += len;
+ total_out += len;
+ avail_out -= len;
+ dstate.pending -= len;
+ if (dstate.pending == 0)
+ {
+ dstate.pending_out = 0;
+ }
+ }
+
+ // Read a new buffer from the current input stream, update the adler32
+ // and total number of bytes read. All deflate() input goes through
+ // this function so some applications may wish to modify it to avoid
+ // allocating a large strm->next_in buffer and copying from it.
+ // (See also flush_pending()).
+ internal int read_buf(byte[] buf, int start, int size)
+ {
+ int len = avail_in;
+
+ if (len > size) len = size;
+ if (len == 0) return 0;
+
+ avail_in -= len;
+
+ if (dstate.noheader == 0)
+ {
+ Adler = this.Adler32(Adler, next_in, next_in_index, len);
+ }
+ System.Array.Copy(next_in, next_in_index, buf, start, len);
+ next_in_index += len;
+ total_in += len;
+ return len;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Working.1/Zlib.cs b/Renci.SshNet/Compression/Working.1/Zlib.cs
new file mode 100644
index 0000000..5890675
--- /dev/null
+++ b/Renci.SshNet/Compression/Working.1/Zlib.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Represents "zlib" compression implementation
+ ///
+ internal class Zlib : Compressor
+ {
+ ///
+ /// Gets algorithm name.
+ ///
+ public override string Name
+ {
+ get { return "zlib"; }
+ }
+
+ ///
+ /// Initializes the algorithm
+ ///
+ /// The session.
+ public override void Init(Session session)
+ {
+ base.Init(session);
+ this.IsActive = true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Working.1/ZlibOpenSsh.cs b/Renci.SshNet/Compression/Working.1/ZlibOpenSsh.cs
new file mode 100644
index 0000000..f82a4c0
--- /dev/null
+++ b/Renci.SshNet/Compression/Working.1/ZlibOpenSsh.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Represents "zlib@openssh.org" compression implementation
+ ///
+ public class ZlibOpenSsh : Compressor
+ {
+ ///
+ /// Gets algorithm name.
+ ///
+ public override string Name
+ {
+ get { return "zlib@openssh.org"; }
+ }
+
+ ///
+ /// Initializes the algorithm
+ ///
+ /// The session.
+ public override void Init(Session session)
+ {
+ base.Init(session);
+
+ session.UserAuthenticationSuccessReceived += Session_UserAuthenticationSuccessReceived;
+ }
+
+ private void Session_UserAuthenticationSuccessReceived(object sender, MessageEventArgs e)
+ {
+ this.IsActive = true;
+ this.Session.UserAuthenticationSuccessReceived -= Session_UserAuthenticationSuccessReceived;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Working.1/ZlibStream.cs b/Renci.SshNet/Compression/Working.1/ZlibStream.cs
new file mode 100644
index 0000000..31833e8
--- /dev/null
+++ b/Renci.SshNet/Compression/Working.1/ZlibStream.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.IO;
+using Org.BouncyCastle.Utilities.Zlib;
+
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Implements Zlib compression algorithm.
+ ///
+ public class ZlibStream
+ {
+ private readonly Stream _baseStream;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The stream.
+ /// The mode.
+ public ZlibStream(Stream stream, CompressionMode mode)
+ {
+ switch (mode)
+ {
+ case CompressionMode.Compress:
+ this._baseStream = new ZOutputStream(stream, CompressionLevel.Z_DEFAULT_COMPRESSION);
+ break;
+ case CompressionMode.Decompress:
+ this._baseStream = new ZOutputStream(stream);
+ break;
+ default:
+ break;
+ }
+
+ //this._baseStream.FlushMode = Ionic.Zlib.FlushType.Partial;
+ }
+
+ ///
+ /// Writes the specified buffer.
+ ///
+ /// The buffer.
+ /// The offset.
+ /// The count.
+ public void Write(byte[] buffer, int offset, int count)
+ {
+ this._baseStream.Write(buffer, offset, count);
+ }
+ }
+}
diff --git a/Renci.SshNet/Compression/ZDeflaterOutputStream.cs b/Renci.SshNet/Compression/ZDeflaterOutputStream.cs
new file mode 100644
index 0000000..1d88847
--- /dev/null
+++ b/Renci.SshNet/Compression/ZDeflaterOutputStream.cs
@@ -0,0 +1,151 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Utilities.Zlib {
+ ///
+ /// Summary description for DeflaterOutputStream.
+ ///
+ [Obsolete("Use 'ZOutputStream' instead")]
+ public class ZDeflaterOutputStream : Stream {
+ protected ZStream z=new ZStream();
+ protected int flushLevel=JZlib.Z_NO_FLUSH;
+ private const int BUFSIZE = 4192;
+ protected byte[] buf=new byte[BUFSIZE];
+ private byte[] buf1=new byte[1];
+
+ protected Stream outp;
+
+ public ZDeflaterOutputStream(Stream outp) : this(outp, 6, false) {
+ }
+
+ public ZDeflaterOutputStream(Stream outp, int level) : this(outp, level, false) {
+ }
+
+ public ZDeflaterOutputStream(Stream outp, int level, bool nowrap) {
+ this.outp=outp;
+ z.deflateInit(level, nowrap);
+ }
+
+
+ public override bool CanRead {
+ get {
+ // TODO: Add DeflaterOutputStream.CanRead getter implementation
+ return false;
+ }
+ }
+
+ public override bool CanSeek {
+ get {
+ // TODO: Add DeflaterOutputStream.CanSeek getter implementation
+ return false;
+ }
+ }
+
+ public override bool CanWrite {
+ get {
+ // TODO: Add DeflaterOutputStream.CanWrite getter implementation
+ return true;
+ }
+ }
+
+ public override long Length {
+ get {
+ // TODO: Add DeflaterOutputStream.Length getter implementation
+ return 0;
+ }
+ }
+
+ public override long Position {
+ get {
+ // TODO: Add DeflaterOutputStream.Position getter implementation
+ return 0;
+ }
+ set {
+ // TODO: Add DeflaterOutputStream.Position setter implementation
+ }
+ }
+
+ public override void Write(byte[] b, int off, int len) {
+ if(len==0)
+ return;
+ int err;
+ z.next_in=b;
+ z.next_in_index=off;
+ z.avail_in=len;
+ do{
+ z.next_out=buf;
+ z.next_out_index=0;
+ z.avail_out=BUFSIZE;
+ err=z.deflate(flushLevel);
+ if(err!=JZlib.Z_OK)
+ throw new IOException("deflating: "+z.msg);
+ if (z.avail_out < BUFSIZE)
+ {
+ outp.Write(buf, 0, BUFSIZE-z.avail_out);
+ }
+ }
+ while(z.avail_in>0 || z.avail_out==0);
+ }
+
+ public override long Seek(long offset, SeekOrigin origin) {
+ // TODO: Add DeflaterOutputStream.Seek implementation
+ return 0;
+ }
+
+ public override void SetLength(long value) {
+ // TODO: Add DeflaterOutputStream.SetLength implementation
+
+ }
+
+ public override int Read(byte[] buffer, int offset, int count) {
+ // TODO: Add DeflaterOutputStream.Read implementation
+ return 0;
+ }
+
+ public override void Flush() {
+ outp.Flush();
+ }
+
+ public override void WriteByte(byte b) {
+ buf1[0]=(byte)b;
+ Write(buf1, 0, 1);
+ }
+
+ public void Finish() {
+ int err;
+ do{
+ z.next_out=buf;
+ z.next_out_index=0;
+ z.avail_out=BUFSIZE;
+ err=z.deflate(JZlib.Z_FINISH);
+ if(err!=JZlib.Z_STREAM_END && err != JZlib.Z_OK)
+ throw new IOException("deflating: "+z.msg);
+ if(BUFSIZE-z.avail_out>0){
+ outp.Write(buf, 0, BUFSIZE-z.avail_out);
+ }
+ }
+ while(z.avail_in>0 || z.avail_out==0);
+ Flush();
+ }
+
+ public void End() {
+ if(z==null)
+ return;
+ z.deflateEnd();
+ z.free();
+ z=null;
+ }
+
+ public override void Close() {
+ try{
+ try{Finish();}
+ catch (IOException) {}
+ }
+ finally{
+ End();
+ outp.Close();
+ outp=null;
+ }
+ }
+ }
+}
diff --git a/Renci.SshNet/Compression/ZInflaterInputStream.cs b/Renci.SshNet/Compression/ZInflaterInputStream.cs
new file mode 100644
index 0000000..5a3ff5a
--- /dev/null
+++ b/Renci.SshNet/Compression/ZInflaterInputStream.cs
@@ -0,0 +1,127 @@
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Utilities.Zlib {
+ ///
+ /// Summary description for DeflaterOutputStream.
+ ///
+ [Obsolete("Use 'ZInputStream' instead")]
+ public class ZInflaterInputStream : Stream {
+ protected ZStream z=new ZStream();
+ protected int flushLevel=JZlib.Z_NO_FLUSH;
+ private const int BUFSIZE = 4192;
+ protected byte[] buf=new byte[BUFSIZE];
+ private byte[] buf1=new byte[1];
+
+ protected Stream inp=null;
+ private bool nomoreinput=false;
+
+ public ZInflaterInputStream(Stream inp) : this(inp, false) {
+ }
+
+ public ZInflaterInputStream(Stream inp, bool nowrap) {
+ this.inp=inp;
+ z.inflateInit(nowrap);
+ z.next_in=buf;
+ z.next_in_index=0;
+ z.avail_in=0;
+ }
+
+ public override bool CanRead {
+ get {
+ // TODO: Add DeflaterOutputStream.CanRead getter implementation
+ return true;
+ }
+ }
+
+ public override bool CanSeek {
+ get {
+ // TODO: Add DeflaterOutputStream.CanSeek getter implementation
+ return false;
+ }
+ }
+
+ public override bool CanWrite {
+ get {
+ // TODO: Add DeflaterOutputStream.CanWrite getter implementation
+ return false;
+ }
+ }
+
+ public override long Length {
+ get {
+ // TODO: Add DeflaterOutputStream.Length getter implementation
+ return 0;
+ }
+ }
+
+ public override long Position {
+ get {
+ // TODO: Add DeflaterOutputStream.Position getter implementation
+ return 0;
+ }
+ set {
+ // TODO: Add DeflaterOutputStream.Position setter implementation
+ }
+ }
+
+ public override void Write(byte[] b, int off, int len) {
+ }
+
+ public override long Seek(long offset, SeekOrigin origin) {
+ // TODO: Add DeflaterOutputStream.Seek implementation
+ return 0;
+ }
+
+ public override void SetLength(long value) {
+ // TODO: Add DeflaterOutputStream.SetLength implementation
+
+ }
+
+ public override int Read(byte[] b, int off, int len) {
+ if(len==0)
+ return(0);
+ int err;
+ z.next_out=b;
+ z.next_out_index=off;
+ z.avail_out=len;
+ do {
+ if((z.avail_in==0)&&(!nomoreinput)) { // if buffer is empty and more input is avaiable, refill it
+ z.next_in_index=0;
+ z.avail_in=inp.Read(buf, 0, BUFSIZE);//(BUFSIZE 0)
+ {
+ output.Write(buf, 0, count);
+ }
+ }
+ while (z.avail_in > 0 || z.avail_out == 0);
+
+ Flush();
+ }
+
+ public override void Flush()
+ {
+ output.Flush();
+ }
+
+ public virtual int FlushMode
+ {
+ get { return flushLevel; }
+ set { this.flushLevel = value; }
+ }
+
+ public sealed override long Length { get { throw new NotSupportedException(); } }
+ public sealed override long Position
+ {
+ get { throw new NotSupportedException(); }
+ set { throw new NotSupportedException(); }
+ }
+ public sealed override int Read(byte[] buffer, int offset, int count) { throw new NotSupportedException(); }
+ public sealed override long Seek(long offset, SeekOrigin origin) { throw new NotSupportedException(); }
+ public sealed override void SetLength(long value) { throw new NotSupportedException(); }
+
+ public virtual long TotalIn
+ {
+ get { return z.total_in; }
+ }
+
+ public virtual long TotalOut
+ {
+ get { return z.total_out; }
+ }
+
+ public override void Write(byte[] b, int off, int len)
+ {
+ if (len == 0)
+ return;
+
+ z.next_in = b;
+ z.next_in_index = off;
+ z.avail_in = len;
+
+ do
+ {
+ z.next_out = buf;
+ z.next_out_index = 0;
+ z.avail_out = buf.Length;
+
+ int err = compress
+ ? z.deflate(flushLevel)
+ : z.inflate(flushLevel);
+
+ if (err != JZlib.Z_OK)
+ // TODO
+// throw new ZStreamException((compress ? "de" : "in") + "flating: " + z.msg);
+ throw new IOException((compress ? "de" : "in") + "flating: " + z.msg);
+
+ output.Write(buf, 0, buf.Length - z.avail_out);
+ }
+ while (z.avail_in > 0 || z.avail_out == 0);
+ }
+
+ public override void WriteByte(byte b)
+ {
+ buf1[0] = b;
+ Write(buf1, 0, 1);
+ }
+ }
+}
diff --git a/Renci.SshNet/Compression/ZStream.cs b/Renci.SshNet/Compression/ZStream.cs
new file mode 100644
index 0000000..7ff9614
--- /dev/null
+++ b/Renci.SshNet/Compression/ZStream.cs
@@ -0,0 +1,214 @@
+using System;
+/*
+ * $Id: ZStream.cs,v 1.1 2006-07-31 13:59:26 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib {
+
+ public sealed class ZStream{
+
+ private const int MAX_WBITS=15; // 32K LZ77 window
+ private const int DEF_WBITS=MAX_WBITS;
+
+ private const int Z_NO_FLUSH=0;
+ private const int Z_PARTIAL_FLUSH=1;
+ private const int Z_SYNC_FLUSH=2;
+ private const int Z_FULL_FLUSH=3;
+ private const int Z_FINISH=4;
+
+ private const int MAX_MEM_LEVEL=9;
+
+ private const int Z_OK=0;
+ private const int Z_STREAM_END=1;
+ private const int Z_NEED_DICT=2;
+ private const int Z_ERRNO=-1;
+ private const int Z_STREAM_ERROR=-2;
+ private const int Z_DATA_ERROR=-3;
+ private const int Z_MEM_ERROR=-4;
+ private const int Z_BUF_ERROR=-5;
+ private const int Z_VERSION_ERROR=-6;
+
+ public byte[] next_in; // next input byte
+ public int next_in_index;
+ public int avail_in; // number of bytes available at next_in
+ public long total_in; // total nb of input bytes read so far
+
+ public byte[] next_out; // next output byte should be put there
+ public int next_out_index;
+ public int avail_out; // remaining free space at next_out
+ public long total_out; // total nb of bytes output so far
+
+ public String msg;
+
+ internal Deflate dstate;
+ internal Inflate istate;
+
+ internal int data_type; // best guess about the data type: ascii or binary
+
+ public long adler;
+ internal Adler32 _adler=new Adler32();
+
+ public int inflateInit(){
+ return inflateInit(DEF_WBITS);
+ }
+ public int inflateInit(bool nowrap){
+ return inflateInit(DEF_WBITS, nowrap);
+ }
+ public int inflateInit(int w){
+ return inflateInit(w, false);
+ }
+
+ public int inflateInit(int w, bool nowrap){
+ istate=new Inflate();
+ return istate.inflateInit(this, nowrap?-w:w);
+ }
+
+ public int inflate(int f){
+ if(istate==null) return Z_STREAM_ERROR;
+ return istate.inflate(this, f);
+ }
+ public int inflateEnd(){
+ if(istate==null) return Z_STREAM_ERROR;
+ int ret=istate.inflateEnd(this);
+ istate = null;
+ return ret;
+ }
+ public int inflateSync(){
+ if(istate == null)
+ return Z_STREAM_ERROR;
+ return istate.inflateSync(this);
+ }
+ public int inflateSetDictionary(byte[] dictionary, int dictLength){
+ if(istate == null)
+ return Z_STREAM_ERROR;
+ return istate.inflateSetDictionary(this, dictionary, dictLength);
+ }
+
+ public int deflateInit(int level){
+ return deflateInit(level, MAX_WBITS);
+ }
+ public int deflateInit(int level, bool nowrap){
+ return deflateInit(level, MAX_WBITS, nowrap);
+ }
+ public int deflateInit(int level, int bits){
+ return deflateInit(level, bits, false);
+ }
+ public int deflateInit(int level, int bits, bool nowrap){
+ dstate=new Deflate();
+ return dstate.deflateInit(this, level, nowrap?-bits:bits);
+ }
+ public int deflate(int flush){
+ if(dstate==null){
+ return Z_STREAM_ERROR;
+ }
+ return dstate.deflate(this, flush);
+ }
+ public int deflateEnd(){
+ if(dstate==null) return Z_STREAM_ERROR;
+ int ret=dstate.deflateEnd();
+ dstate=null;
+ return ret;
+ }
+ public int deflateParams(int level, int strategy){
+ if(dstate==null) return Z_STREAM_ERROR;
+ return dstate.deflateParams(this, level, strategy);
+ }
+ public int deflateSetDictionary (byte[] dictionary, int dictLength){
+ if(dstate == null)
+ return Z_STREAM_ERROR;
+ return dstate.deflateSetDictionary(this, dictionary, dictLength);
+ }
+
+ // Flush as much pending output as possible. All deflate() output goes
+ // through this function so some applications may wish to modify it
+ // to avoid allocating a large strm->next_out buffer and copying into it.
+ // (See also read_buf()).
+ internal void flush_pending(){
+ int len=dstate.pending;
+
+ if(len>avail_out) len=avail_out;
+ if(len==0) return;
+
+ if(dstate.pending_buf.Length<=dstate.pending_out ||
+ next_out.Length<=next_out_index ||
+ dstate.pending_buf.Length<(dstate.pending_out+len) ||
+ next_out.Length<(next_out_index+len)){
+ // System.out.println(dstate.pending_buf.length+", "+dstate.pending_out+
+ // ", "+next_out.length+", "+next_out_index+", "+len);
+ // System.out.println("avail_out="+avail_out);
+ }
+
+ System.Array.Copy(dstate.pending_buf, dstate.pending_out,
+ next_out, next_out_index, len);
+
+ next_out_index+=len;
+ dstate.pending_out+=len;
+ total_out+=len;
+ avail_out-=len;
+ dstate.pending-=len;
+ if(dstate.pending==0){
+ dstate.pending_out=0;
+ }
+ }
+
+ // Read a new buffer from the current input stream, update the adler32
+ // and total number of bytes read. All deflate() input goes through
+ // this function so some applications may wish to modify it to avoid
+ // allocating a large strm->next_in buffer and copying from it.
+ // (See also flush_pending()).
+ internal int read_buf(byte[] buf, int start, int size) {
+ int len=avail_in;
+
+ if(len>size) len=size;
+ if(len==0) return 0;
+
+ avail_in-=len;
+
+ if(dstate.noheader==0) {
+ adler=_adler.adler32(adler, next_in, next_in_index, len);
+ }
+ System.Array.Copy(next_in, next_in_index, buf, start, len);
+ next_in_index += len;
+ total_in += len;
+ return len;
+ }
+
+ public void free(){
+ next_in=null;
+ next_out=null;
+ msg=null;
+ _adler=null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/Zlib.cs b/Renci.SshNet/Compression/Zlib.cs
index 3921df7..5890675 100644
--- a/Renci.SshNet/Compression/Zlib.cs
+++ b/Renci.SshNet/Compression/Zlib.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.IO;
namespace Renci.SshNet.Compression
{
@@ -8,8 +9,6 @@ namespace Renci.SshNet.Compression
///
internal class Zlib : Compressor
{
- private bool _active;
-
///
/// Gets algorithm name.
///
@@ -25,48 +24,7 @@ public override string Name
public override void Init(Session session)
{
base.Init(session);
-
- session.UserAuthenticationSuccessReceived += Session_UserAuthenticationSuccessReceived;
- }
-
- private void Session_UserAuthenticationSuccessReceived(object sender, MessageEventArgs e)
- {
- this._active = true;
- this.Session.UserAuthenticationSuccessReceived -= Session_UserAuthenticationSuccessReceived;
- }
-
- ///
- /// Compresses the specified data.
- ///
- /// Data to compress.
- ///
- /// Compressed data
- ///
- public override byte[] Compress(byte[] data)
- {
- if (!this._active)
- {
- return data;
- }
-
- throw new NotImplementedException();
- }
-
- ///
- /// Decompresses the specified data.
- ///
- /// Compressed data.
- ///
- /// Decompressed data.
- ///
- public override byte[] Decompress(byte[] data)
- {
- if (!this._active)
- {
- return data;
- }
-
- throw new NotImplementedException();
+ this.IsActive = true;
}
}
}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/ZlibOpenSsh.cs b/Renci.SshNet/Compression/ZlibOpenSsh.cs
index 73dea13..f82a4c0 100644
--- a/Renci.SshNet/Compression/ZlibOpenSsh.cs
+++ b/Renci.SshNet/Compression/ZlibOpenSsh.cs
@@ -1,15 +1,14 @@
using System;
using System.Collections.Generic;
+using System.IO;
namespace Renci.SshNet.Compression
{
///
/// Represents "zlib@openssh.org" compression implementation
///
- internal class ZlibOpenSsh : Compressor
+ public class ZlibOpenSsh : Compressor
{
- private bool _active;
-
///
/// Gets algorithm name.
///
@@ -31,80 +30,8 @@ public override void Init(Session session)
private void Session_UserAuthenticationSuccessReceived(object sender, MessageEventArgs e)
{
- this._active = true;
+ this.IsActive = true;
this.Session.UserAuthenticationSuccessReceived -= Session_UserAuthenticationSuccessReceived;
}
-
- ///
- /// Compresses the specified data.
- ///
- /// Data to compress.
- ///
- /// Compressed data
- ///
- public override byte[] Compress(byte[] data)
- {
- if (!this._active)
- {
- return data;
- }
- throw new NotImplementedException();
-
- //using (var output = new MemoryStream())
- //{
- // using (var input = new MemoryStream(data.ToArray()))
- // using (var compress = new DeflateStream(output, CompressionMode.Compress))
- // {
- // compress.FlushMode = FlushType.Partial;
-
- // input.CopyTo(compress);
-
- // var result = new List();
-
- // result.Add(0x78);
- // result.Add(0x9c);
-
- // result.AddRange(output.ToArray());
-
- // return result;
- // }
- //}
- }
-
- ///
- /// Decompresses the specified data.
- ///
- /// Compressed data.
- ///
- /// Decompressed data.
- ///
- public override byte[] Decompress(byte[] data)
- {
- if (!this._active)
- {
- return data;
- }
-
- throw new NotImplementedException();
-
- //Create the decompressed file.
- //using (var output = new MemoryStream())
- //{
- // using (var input = new MemoryStream(data.ToArray()))
- // {
- // input.ReadByte();
- // input.ReadByte();
-
- // using (var decompress = new DeflateStream(input, CompressionMode.Decompress))
- // {
- // // Copy the decompression stream
- // // into the output file.
- // decompress.CopyTo(output);
- // }
- // }
-
- // return output.ToArray();
- //}
- }
}
}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/ZlibStream.cs b/Renci.SshNet/Compression/ZlibStream.cs
new file mode 100644
index 0000000..f3b6f32
--- /dev/null
+++ b/Renci.SshNet/Compression/ZlibStream.cs
@@ -0,0 +1,49 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.IO;
+
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Implements Zlib compression algorithm.
+ ///
+ public class ZlibStream
+ {
+ //private readonly Ionic.Zlib.ZlibStream _baseStream;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The stream.
+ /// The mode.
+ public ZlibStream(Stream stream, CompressionMode mode)
+ {
+ //switch (mode)
+ //{
+ // case CompressionMode.Compress:
+ // this._baseStream = new Ionic.Zlib.ZlibStream(stream, Ionic.Zlib.CompressionMode.Compress, Ionic.Zlib.CompressionLevel.Default);
+ // break;
+ // case CompressionMode.Decompress:
+ // this._baseStream = new Ionic.Zlib.ZlibStream(stream, Ionic.Zlib.CompressionMode.Decompress, Ionic.Zlib.CompressionLevel.Default);
+ // break;
+ // default:
+ // break;
+ //}
+
+ //this._baseStream.FlushMode = Ionic.Zlib.FlushType.Partial;
+ }
+
+ ///
+ /// Writes the specified buffer.
+ ///
+ /// The buffer.
+ /// The offset.
+ /// The count.
+ public void Write(byte[] buffer, int offset, int count)
+ {
+ //this._baseStream.Write(buffer, offset, count);
+ }
+ }
+}
diff --git a/Renci.SshNet/Compression/v10/Adler32.cs b/Renci.SshNet/Compression/v10/Adler32.cs
new file mode 100644
index 0000000..c132fa9
--- /dev/null
+++ b/Renci.SshNet/Compression/v10/Adler32.cs
@@ -0,0 +1,95 @@
+using System;
+/*
+ * $Id: Adler32.cs,v 1.1 2006-07-31 13:59:25 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ internal static class Adler32
+ {
+
+ // largest prime smaller than 65536
+ private const int BASE = 65521;
+ // NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
+ private const int NMAX = 5552;
+
+ internal static long adler32(long adler, byte[] buf, int index, int len)
+ {
+ if (buf == null) { return 1L; }
+
+ long s1 = adler & 0xffff;
+ long s2 = (adler >> 16) & 0xffff;
+ int k;
+
+ while (len > 0)
+ {
+ k = len < NMAX ? len : NMAX;
+ len -= k;
+ while (k >= 16)
+ {
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ k -= 16;
+ }
+ if (k != 0)
+ {
+ do
+ {
+ s1 += buf[index++] & 0xff; s2 += s1;
+ }
+ while (--k != 0);
+ }
+ s1 %= BASE;
+ s2 %= BASE;
+ }
+ return (s2 << 16) | s1;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v10/CompressionMode.cs b/Renci.SshNet/Compression/v10/CompressionMode.cs
new file mode 100644
index 0000000..1577e0b
--- /dev/null
+++ b/Renci.SshNet/Compression/v10/CompressionMode.cs
@@ -0,0 +1,18 @@
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Specifies compression modes
+ ///
+ public enum CompressionMode
+ {
+ ///
+ /// Specifies that content should be compressed.
+ ///
+ Compress = 0,
+
+ ///
+ /// Specifies that content should be decompressed.
+ ///
+ Decompress = 1,
+ }
+}
diff --git a/Renci.SshNet/Compression/v10/Compressor.cs b/Renci.SshNet/Compression/v10/Compressor.cs
new file mode 100644
index 0000000..1479bb6
--- /dev/null
+++ b/Renci.SshNet/Compression/v10/Compressor.cs
@@ -0,0 +1,151 @@
+using System.Collections.Generic;
+using Renci.SshNet.Security;
+using System.IO;
+using System;
+
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Represents base class for compression algorithm implementation
+ ///
+ public abstract class Compressor : Algorithm, IDisposable
+ {
+ private readonly ZlibStream _compressor;
+ private readonly ZlibStream _decompressor;
+
+ private MemoryStream _compressorStream;
+ private MemoryStream _decompressorStream;
+
+ ///
+ /// Gets or sets a value indicating whether compression is active.
+ ///
+ ///
+ /// true if compression is active; otherwise, false.
+ ///
+ protected bool IsActive { get; set; }
+
+ ///
+ /// Gets the session.
+ ///
+ protected Session Session { get; private set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ 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);
+ }
+
+ ///
+ /// Initializes the algorithm
+ ///
+ /// The session.
+ public virtual void Init(Session session)
+ {
+ this.Session = session;
+ }
+
+ ///
+ /// Compresses the specified data.
+ ///
+ /// Data to compress.
+ /// Compressed 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();
+ }
+
+ ///
+ /// Decompresses the specified data.
+ ///
+ /// Compressed data.
+ /// Decompressed 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;
+
+ ///
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged ResourceMessages.
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Releases unmanaged and - optionally - managed resources
+ ///
+ /// true to release both managed and unmanaged resources; false to release only unmanaged ResourceMessages.
+ 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;
+ }
+ }
+
+ ///
+ /// Releases unmanaged resources and performs other cleanup operations before the
+ /// is reclaimed by garbage collection.
+ ///
+ ~Compressor()
+ {
+ // Do not re-create Dispose clean-up code here.
+ // Calling Dispose(false) is optimal in terms of
+ // readability and maintainability.
+ Dispose(false);
+ }
+
+ #endregion
+ }
+}
diff --git a/Renci.SshNet/Compression/v10/Deflate.cs b/Renci.SshNet/Compression/v10/Deflate.cs
new file mode 100644
index 0000000..fe69f52
--- /dev/null
+++ b/Renci.SshNet/Compression/v10/Deflate.cs
@@ -0,0 +1,2290 @@
+using System;
+using System.Collections.Generic;
+/*
+ * $Id: Deflate.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public enum BlockType : byte
+ {
+ Z_BINARY = 0,
+ Z_ASCII = 1,
+ Z_UNKNOWN = 2
+ }
+
+ public enum DefalteFlavor : int
+ {
+ STORED = 0,
+ FAST = 1,
+ SLOW = 2
+ }
+
+ public sealed class Deflate : ZStream, ICompressor
+ {
+ private const int MAX_MEM_LEVEL = 9;
+
+ private const int Z_DEFAULT_COMPRESSION = -1;
+
+ private const int MAX_WBITS = 15; // 32K LZ77 window
+
+ private const int DEF_MEM_LEVEL = 8;
+
+ ///
+ /// The Bit length codes must not exceed MAX_BL_BITS bits
+ ///
+ private const int MAX_BL_BITS = 7;
+
+ // block not completed, need more input or more output
+ private const int NeedMore = 0;
+
+ // block flush performed
+ private const int BlockDone = 1;
+
+ // finish started, need only more output at next deflate
+ private const int FinishStarted = 2;
+
+ // finish done, accept no more input or output
+ private const int FinishDone = 3;
+
+ // preset dictionary flag in zlib header
+ private const int PRESET_DICT = 0x20;
+
+ private const int Z_VERSION_ERROR = -6;
+
+ private const int INIT_STATE = 42;
+ private const int BUSY_STATE = 113;
+ private const int FINISH_STATE = 666;
+
+ // The deflate compression method
+ private const int Z_DEFLATED = 8;
+
+ private const int STORED_BLOCK = 0;
+ private const int STATIC_TREES = 1;
+ private const int DYN_TREES = 2;
+
+ private const int Buf_size = 8 * 2;
+
+ // repeat previous bit length 3-6 times (2 bits of repeat count)
+ private const int REP_3_6 = 16;
+
+ // repeat a zero length 3-10 times (3 bits of repeat count)
+ private const int REPZ_3_10 = 17;
+
+ // repeat a zero length 11-138 times (7 bits of repeat count)
+ private const int REPZ_11_138 = 18;
+
+ private const int MIN_MATCH = 3;
+ private const int MAX_MATCH = 258;
+ private const int MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1);
+
+ private const int MAX_BITS = 15;
+ private const int D_CODES = 30;
+ private const int BL_CODES = 19;
+ private const int LENGTH_CODES = 29;
+ private const int LITERALS = 256;
+ private const int L_CODES = (LITERALS + 1 + LENGTH_CODES);
+ private const int HEAP_SIZE = (2 * L_CODES + 1);
+
+ private const int END_BLOCK = 256;
+
+ private static readonly IDictionary config_table = new Dictionary() {
+ {(CompressionLevel)0, new Config(0, 0, 0, 0, DefalteFlavor.STORED)},
+ {(CompressionLevel)1, new Config(4, 4, 8, 4, DefalteFlavor.FAST)},
+ {(CompressionLevel)2, new Config(4, 5, 16, 8, DefalteFlavor.FAST)},
+ {(CompressionLevel)3, new Config(4, 6, 32, 32, DefalteFlavor.FAST)},
+
+ {(CompressionLevel)4, new Config(4, 4, 16, 16, DefalteFlavor.SLOW)},
+ {(CompressionLevel)5, new Config(8, 16, 32, 32, DefalteFlavor.SLOW)},
+ {(CompressionLevel)6, new Config(8, 16, 128, 128, DefalteFlavor.SLOW)},
+ {(CompressionLevel)7, new Config(8, 32, 128, 256, DefalteFlavor.SLOW)},
+ {(CompressionLevel)8, new Config(32, 128, 258, 1024, DefalteFlavor.SLOW)},
+ {(CompressionLevel)9, new Config(32, 258, 258, 4096, DefalteFlavor.SLOW)},
+ };
+
+ private static readonly StaticTree static_l_desc = new StaticTree(static_ltree, Deflate.extra_lbits, LITERALS + 1, L_CODES, MAX_BITS);
+
+ private static readonly StaticTree static_d_desc = new StaticTree(static_dtree, Deflate.extra_dbits, 0, D_CODES, MAX_BITS);
+
+ private static readonly StaticTree static_bl_desc = new StaticTree(null, Deflate.extra_blbits, 0, BL_CODES, MAX_BL_BITS);
+
+ #region Static definitions
+
+ private static readonly byte[] _length_code ={
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12,
+ 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
+ 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
+ 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
+ };
+
+ private static readonly int[] base_length = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
+ 64, 80, 96, 112, 128, 160, 192, 224, 0
+ };
+
+ private static readonly int[] base_dist = {
+ 0, 1, 2, 3, 4, 6, 8, 12, 16, 24,
+ 32, 48, 64, 96, 128, 192, 256, 384, 512, 768,
+ 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576
+ };
+
+ // extra bits for each length code
+ private static readonly int[] extra_lbits ={
+ 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0
+ };
+
+ // extra bits for each distance code
+ private static readonly int[] extra_dbits ={
+ 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13
+ };
+
+ // extra bits for each bit length code
+ private static readonly int[] extra_blbits ={
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7
+ };
+
+ private static readonly byte[] bl_order ={
+ 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
+
+ private static readonly short[] static_ltree = {
+ 12, 8, 140, 8, 76, 8, 204, 8, 44, 8,
+ 172, 8, 108, 8, 236, 8, 28, 8, 156, 8,
+ 92, 8, 220, 8, 60, 8, 188, 8, 124, 8,
+ 252, 8, 2, 8, 130, 8, 66, 8, 194, 8,
+ 34, 8, 162, 8, 98, 8, 226, 8, 18, 8,
+ 146, 8, 82, 8, 210, 8, 50, 8, 178, 8,
+ 114, 8, 242, 8, 10, 8, 138, 8, 74, 8,
+ 202, 8, 42, 8, 170, 8, 106, 8, 234, 8,
+ 26, 8, 154, 8, 90, 8, 218, 8, 58, 8,
+ 186, 8, 122, 8, 250, 8, 6, 8, 134, 8,
+ 70, 8, 198, 8, 38, 8, 166, 8, 102, 8,
+ 230, 8, 22, 8, 150, 8, 86, 8, 214, 8,
+ 54, 8, 182, 8, 118, 8, 246, 8, 14, 8,
+ 142, 8, 78, 8, 206, 8, 46, 8, 174, 8,
+ 110, 8, 238, 8, 30, 8, 158, 8, 94, 8,
+ 222, 8, 62, 8, 190, 8, 126, 8, 254, 8,
+ 1, 8, 129, 8, 65, 8, 193, 8, 33, 8,
+ 161, 8, 97, 8, 225, 8, 17, 8, 145, 8,
+ 81, 8, 209, 8, 49, 8, 177, 8, 113, 8,
+ 241, 8, 9, 8, 137, 8, 73, 8, 201, 8,
+ 41, 8, 169, 8, 105, 8, 233, 8, 25, 8,
+ 153, 8, 89, 8, 217, 8, 57, 8, 185, 8,
+ 121, 8, 249, 8, 5, 8, 133, 8, 69, 8,
+ 197, 8, 37, 8, 165, 8, 101, 8, 229, 8,
+ 21, 8, 149, 8, 85, 8, 213, 8, 53, 8,
+ 181, 8, 117, 8, 245, 8, 13, 8, 141, 8,
+ 77, 8, 205, 8, 45, 8, 173, 8, 109, 8,
+ 237, 8, 29, 8, 157, 8, 93, 8, 221, 8,
+ 61, 8, 189, 8, 125, 8, 253, 8, 19, 9,
+ 275, 9, 147, 9, 403, 9, 83, 9, 339, 9,
+ 211, 9, 467, 9, 51, 9, 307, 9, 179, 9,
+ 435, 9, 115, 9, 371, 9, 243, 9, 499, 9,
+ 11, 9, 267, 9, 139, 9, 395, 9, 75, 9,
+ 331, 9, 203, 9, 459, 9, 43, 9, 299, 9,
+ 171, 9, 427, 9, 107, 9, 363, 9, 235, 9,
+ 491, 9, 27, 9, 283, 9, 155, 9, 411, 9,
+ 91, 9, 347, 9, 219, 9, 475, 9, 59, 9,
+ 315, 9, 187, 9, 443, 9, 123, 9, 379, 9,
+ 251, 9, 507, 9, 7, 9, 263, 9, 135, 9,
+ 391, 9, 71, 9, 327, 9, 199, 9, 455, 9,
+ 39, 9, 295, 9, 167, 9, 423, 9, 103, 9,
+ 359, 9, 231, 9, 487, 9, 23, 9, 279, 9,
+ 151, 9, 407, 9, 87, 9, 343, 9, 215, 9,
+ 471, 9, 55, 9, 311, 9, 183, 9, 439, 9,
+ 119, 9, 375, 9, 247, 9, 503, 9, 15, 9,
+ 271, 9, 143, 9, 399, 9, 79, 9, 335, 9,
+ 207, 9, 463, 9, 47, 9, 303, 9, 175, 9,
+ 431, 9, 111, 9, 367, 9, 239, 9, 495, 9,
+ 31, 9, 287, 9, 159, 9, 415, 9, 95, 9,
+ 351, 9, 223, 9, 479, 9, 63, 9, 319, 9,
+ 191, 9, 447, 9, 127, 9, 383, 9, 255, 9,
+ 511, 9, 0, 7, 64, 7, 32, 7, 96, 7,
+ 16, 7, 80, 7, 48, 7, 112, 7, 8, 7,
+ 72, 7, 40, 7, 104, 7, 24, 7, 88, 7,
+ 56, 7, 120, 7, 4, 7, 68, 7, 36, 7,
+ 100, 7, 20, 7, 84, 7, 52, 7, 116, 7,
+ 3, 8, 131, 8, 67, 8, 195, 8, 35, 8,
+ 163, 8, 99, 8, 227, 8
+ };
+
+ private static readonly short[] static_dtree = {
+ 0, 5, 16, 5, 8, 5, 24, 5, 4, 5,
+ 20, 5, 12, 5, 28, 5, 2, 5, 18, 5,
+ 10, 5, 26, 5, 6, 5, 22, 5, 14, 5,
+ 30, 5, 1, 5, 17, 5, 9, 5, 25, 5,
+ 5, 5, 21, 5, 13, 5, 29, 5, 3, 5,
+ 19, 5, 11, 5, 27, 5, 7, 5, 23, 5
+ };
+ #endregion
+
+ private static readonly String[] z_errmsg = {
+ "need dictionary", // ZLibStatus.Z_NEED_DICT 2
+ "stream end", // ZLibStatus.Z_STREAM_END 1
+ "", // ZLibStatus.Z_OK 0
+ "file error", // ZLibStatus.Z_ERRNO (-1)
+ "stream error", // ZLibStatus.Z_STREAM_ERROR (-2)
+ "data error", // ZLibStatus.Z_DATA_ERROR (-3)
+ "insufficient memory", // Z_MEM_ERROR (-4)
+ "buffer error", // ZLibStatus.Z_BUF_ERROR (-5)
+ "incompatible version",// Z_VERSION_ERROR (-6)
+ ""
+ };
+
+
+
+ ///
+ /// as the name implies
+ ///
+ private int _status;
+
+ private BlockType _dataType;
+
+ ///
+ /// STORED (for zip only) or DEFLATED
+ ///
+ private byte _method;
+
+ ///
+ /// size of pending_buf
+ ///
+ private int _pendingBufferSize;
+
+ ///
+ /// LZ77 window size (32K by default)
+ ///
+ private int _windowSize;
+
+ ///
+ /// log2(w_size) (8..16)
+ ///
+ private int _windowBits;
+
+ ///
+ /// w_size - 1
+ ///
+ private int _windowMask;
+
+ ///
+ /// Sliding window. Input bytes are read into the second half of the window,
+ /// and move to the first half later to keep a dictionary of at least wSize
+ /// bytes. With this organization, matches are limited to a distance of
+ /// wSize-MAX_MATCH bytes, but this ensures that IO is always
+ /// performed with a length multiple of the block size. Also, it limits
+ /// the window size to 64K, which is quite useful on MSDOS.
+ /// To do: use the user input buffer as sliding window.
+ ///
+ private byte[] _window;
+
+ ///
+ /// Actual size of window: 2*wSize, except when the user input buffer
+ /// is directly used as sliding window.
+ ///
+ private int _windowActualSize;
+
+ ///
+ /// Link to older string with same hash index. To limit the size of this
+ /// array to 64K, this link is maintained only for the last 32K strings.
+ /// An index in this array is thus a window index modulo 32K.
+ ///
+ private short[] _previous;
+
+ ///
+ /// Heads of the hash chains or NIL.
+ ///
+ private short[] _head;
+
+ ///
+ /// hash index of string to be inserted
+ ///
+ private int _insertedHashIndex;
+
+ ///
+ /// number of elements in hash table
+ ///
+ private int _hashSize;
+
+ ///
+ /// log2(hash_size)
+ ///
+ private int _hashBits;
+
+ ///
+ /// hash_size-1
+ ///
+ private int _hashMask;
+
+ ///
+ /// Number of bits by which ins_h must be shifted at each input
+ /// step. It must be such that after MIN_MATCH steps, the oldest
+ /// byte no longer takes part in the hash key, that is:
+ /// hash_shift * MIN_MATCH >= hash_bits
+ ///
+ private int _hashShift;
+
+ ///
+ /// Window position at the beginning of the current output block. Gets
+ /// negative when the window is moved backwards.
+ ///
+ private int _blockStart;
+
+ ///
+ /// length of best match
+ ///
+ private int _matchLength;
+
+ ///
+ /// previous match
+ ///
+ private int _previousMatch;
+
+ ///
+ /// set if previous match exists
+ ///
+ private bool _matchAvailable;
+
+ ///
+ /// start of string to insert
+ ///
+ private int _startInsertString;
+
+ ///
+ /// start of matching string
+ ///
+ private int _startMatchString;
+
+ ///
+ /// number of valid bytes ahead in window
+ ///
+ private int _validBytesAhead;
+
+ ///
+ /// Length of the best match at previous step. Matches not greater than this
+ /// are discarded. This is used in the lazy match evaluation.
+ ///
+ private int _previousLength;
+
+ ///
+ /// To speed up deflation, hash chains are never searched beyond this
+ /// length. A higher limit improves compression ratio but degrades the speed.
+ ///
+ private int _maxChainLength;
+
+ ///
+ /// Attempt to find a better match only when the current match is strictly
+ /// smaller than this value. This mechanism is used only for compression
+ /// levels >= 4.
+ ///
+ private int _maxLazyMatch;
+
+ // Insert new strings in the hash table only if the match length is not
+ // greater than this length. This saves time but degrades compression.
+ // max_insert_length is used only for compression levels <= 3.
+
+ ///
+ /// The compression level (1..9)
+ ///
+ private CompressionLevel level;
+
+ ///
+ /// The favor or force Huffman coding
+ ///
+ private CompressionStrategy strategy;
+
+ ///
+ /// Use a faster search when the previous match is longer than this
+ ///
+ private int good_match;
+
+ ///
+ /// Stop searching when current match exceeds this
+ ///
+ private int nice_match;
+
+ ///
+ /// literal and length tree
+ ///
+ private short[] dyn_ltree;
+
+ ///
+ /// The distance tree
+ ///
+ private short[] dyn_dtree;
+
+ ///
+ /// The Huffman tree for bit lengths
+ ///
+ private short[] bl_tree;
+
+ ///
+ /// The desc for literal tree
+ ///
+ private Tree l_desc = new Tree();
+
+ ///
+ /// The desc for distance tree
+ ///
+ private Tree d_desc = new Tree();
+
+ ///
+ /// The desc for bit length tree
+ ///
+ private Tree bl_desc = new Tree();
+
+ ///
+ /// index for literals or lengths
+ ///
+ private int l_buf;
+
+ ///
+ /// Size of match buffer for literals/lengths. There are 4 reasons for
+ /// limiting lit_bufsize to 64K:
+ /// - frequencies can be kept in 16 bit counters
+ /// - if compression is not successful for the first block, all input
+ /// data is still in the window so we can still emit a stored block even
+ /// when input comes from standard input. (This can also be done for
+ /// all blocks if lit_bufsize is not greater than 32K.)
+ /// - if compression is not successful for a file smaller than 64K, we can
+ /// even emit a stored file instead of a stored block (saving 5 bytes).
+ /// This is applicable only for zip (not gzip or zlib).
+ /// - creating new Huffman trees less frequently may not provide fast
+ /// adaptation to changes in the input data statistics. (Take for
+ /// example a binary file with poorly compressible code followed by
+ /// a highly compressible string table.) Smaller buffer sizes give
+ /// fast adaptation but have of course the overhead of transmitting
+ /// trees more frequently.
+ /// - I can't count above 4
+ ///
+ private int lit_bufsize;
+
+ ///
+ /// running index in l_buf
+ ///
+ private int last_lit;
+
+ // Buffer for distances. To simplify the code, d_buf and l_buf have
+ // the same number of elements. To use different lengths, an extra flag
+ // array would be necessary.
+
+ ///
+ /// The index of pendig_buf
+ ///
+ private int d_buf;
+
+ ///
+ /// The number of string matches in current block
+ ///
+ private int matches;
+
+ ///
+ /// The bit length of EOB code for last block
+ ///
+ private int last_eob_len;
+
+ ///
+ /// Output buffer. bits are inserted starting at the bottom (least
+ /// significant bits).
+ ///
+ private uint _bitBuffer;
+
+ ///
+ /// Number of valid bits in bi_buf. All bits above the last valid bit
+ /// are always zero.
+ ///
+ private int bi_valid;
+
+ ///
+ /// value of flush param for previous deflate call
+ ///
+ private FlushType last_flush;
+
+ ///
+ /// bit length of current block with optimal trees
+ ///
+ internal int opt_len;
+
+ ///
+ /// bit length of current block with static trees
+ ///
+ internal int static_len;
+
+ ///
+ /// The output still pending
+ ///
+ internal byte[] pending_buf;
+
+ ///
+ /// next pending byte to output to the stream
+ ///
+ internal int pending_out;
+
+ ///
+ /// nb of bytes in the pending buffer
+ ///
+ internal int pending;
+
+ ///
+ /// suppress zlib header and adler32
+ ///
+ internal int noheader;
+
+ ///
+ /// number of codes at each bit length for an optimal tree
+ ///
+ internal short[] bl_count = new short[MAX_BITS + 1];
+
+ ///
+ /// heap used to build the Huffman trees
+ ///
+ internal int[] heap = new int[2 * L_CODES + 1];
+
+ ///
+ /// The number of elements in the heap
+ ///
+ internal int heap_len;
+
+ ///
+ /// The element of largest frequency
+ ///
+ internal int heap_max;
+
+ // The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+ // The same heap array is used to build all trees.
+
+ ///
+ /// Depth of each subtree used as tie breaker for trees of equal frequency
+ ///
+ internal byte[] depth = new byte[2 * L_CODES + 1];
+
+ public Deflate()
+ {
+ dyn_ltree = new short[HEAP_SIZE * 2];
+ dyn_dtree = new short[(2 * D_CODES + 1) * 2]; // distance tree
+ bl_tree = new short[(2 * BL_CODES + 1) * 2]; // Huffman tree for bit lengths
+ }
+
+ public Deflate(CompressionLevel level)
+ : this()
+ {
+ this.deflateInit(level);
+ }
+
+ public Deflate(CompressionLevel level, bool nowrap)
+ : this()
+ {
+ this.deflateInit(level, nowrap);
+ }
+
+
+ public ZLibStatus deflate(byte[] inputBufer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType)
+ {
+ base.next_in = inputBufer;
+ base.next_in_index = inputOffset;
+ base.avail_in = inputCount;
+ base.next_out = outputBuffer;
+ base.next_out_index = outputOffset;
+ base.avail_out = outputCount;
+ return this.deflate(flushType);
+ }
+
+ public ZLibStatus deflate(byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType)
+ {
+ this.next_out = outputBuffer;
+ this.next_out_index = outputOffset;
+ this.avail_out = outputCount;
+ return this.deflate(flushType);
+ }
+
+ public ZLibStatus deflateEnd()
+ {
+ if (_status != INIT_STATE && _status != BUSY_STATE && _status != FINISH_STATE)
+ {
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+ // Deallocate in reverse order of allocations:
+ pending_buf = null;
+ _head = null;
+ _previous = null;
+ _window = null;
+ // free
+ // dstate=null;
+ return _status == BUSY_STATE ? ZLibStatus.Z_DATA_ERROR : ZLibStatus.Z_OK;
+ }
+
+ private ZLibStatus deflate(FlushType flush)
+ {
+ FlushType old_flush;
+
+ if (flush > FlushType.Z_FINISH || flush < 0)
+ {
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+
+ if (base.next_out == null ||
+ (base.next_in == null && base.avail_in != 0) ||
+ (_status == FINISH_STATE && flush != FlushType.Z_FINISH))
+ {
+ base.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_STREAM_ERROR)];
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+ if (base.avail_out == 0)
+ {
+ base.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_BUF_ERROR)];
+ return ZLibStatus.Z_BUF_ERROR;
+ }
+
+ old_flush = last_flush;
+ last_flush = flush;
+
+ // Write the zlib header
+ if (_status == INIT_STATE)
+ {
+ int header = (Z_DEFLATED + ((this._windowBits - 8) << 4)) << 8;
+ int level_flags = (((int)this.level - 1) & 0xff) >> 1;
+
+ if (level_flags > 3) level_flags = 3;
+ header |= (level_flags << 6);
+ if (this._startInsertString != 0) header |= PRESET_DICT;
+ header += 31 - (header % 31);
+
+ _status = BUSY_STATE;
+ PutShortMSB(header);
+
+
+ // Save the adler32 of the preset dictionary:
+ if (this._startInsertString != 0)
+ {
+ PutShortMSB((int)(base.adler >> 16));
+ PutShortMSB((int)(base.adler & 0xffff));
+ }
+ base.adler = Adler32.adler32(0, null, 0, 0);
+ }
+
+ // Flush as much pending output as possible
+ if (pending != 0)
+ {
+ this.FlushPending();
+ if (base.avail_out == 0)
+ {
+ //System.out.println(" avail_out==0");
+ // Since avail_out is 0, deflate will be called again with
+ // more output space, but possibly with both pending and
+ // avail_in equal to zero. There won't be anything to do,
+ // but this is not an error situation so make sure we
+ // return OK instead of BUF_ERROR at next call of deflate:
+ last_flush = (FlushType)(-1);
+ return ZLibStatus.Z_OK;
+ }
+
+ // Make sure there is something to do and avoid duplicate consecutive
+ // flushes. For repeated and useless calls with Z_FINISH, we keep
+ // returning Z_STREAM_END instead of Z_BUFF_ERROR.
+ }
+ else if (base.avail_in == 0 && flush <= old_flush &&
+ flush != FlushType.Z_FINISH)
+ {
+ base.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_BUF_ERROR)];
+ return ZLibStatus.Z_BUF_ERROR;
+ }
+
+ // User must not provide more input after the first FINISH:
+ if (_status == FINISH_STATE && base.avail_in != 0)
+ {
+ base.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_BUF_ERROR)];
+ return ZLibStatus.Z_BUF_ERROR;
+ }
+
+ // Start a new block or continue the current one.
+ if (base.avail_in != 0 || this._validBytesAhead != 0 ||
+ (flush != FlushType.Z_NO_FLUSH && _status != FINISH_STATE))
+ {
+ int bstate = -1;
+ switch (config_table[level].Function)
+ {
+ case DefalteFlavor.STORED:
+ bstate = DeflateStored(flush);
+ break;
+ case DefalteFlavor.FAST:
+ bstate = DeflateFast(flush);
+ break;
+ case DefalteFlavor.SLOW:
+ bstate = DeflateSlow(flush);
+ break;
+ default:
+ break;
+ }
+
+ if (bstate == FinishStarted || bstate == FinishDone)
+ {
+ _status = FINISH_STATE;
+ }
+ if (bstate == NeedMore || bstate == FinishStarted)
+ {
+ if (base.avail_out == 0)
+ {
+ last_flush = (FlushType)(-1); // avoid BUF_ERROR next call, see above
+ }
+ return ZLibStatus.Z_OK;
+ // If flush != Z_NO_FLUSH && avail_out == 0, the next call
+ // of deflate should use the same flush parameter to make sure
+ // that the flush is complete. So we don't have to output an
+ // empty block here, this will be done at next call. This also
+ // ensures that for a very small output buffer, we emit at most
+ // one empty block.
+ }
+
+ if (bstate == BlockDone)
+ {
+ if (flush == FlushType.Z_PARTIAL_FLUSH)
+ {
+ _tr_align();
+ }
+ else
+ { // FULL_FLUSH or SYNC_FLUSH
+ SendStoredBlock(0, 0, false);
+ // For a full flush, this empty block will be recognized
+ // as a special marker by inflate_sync().
+ if (flush == FlushType.Z_FULL_FLUSH)
+ {
+ //state.head[s.hash_size-1]=0;
+ for (int i = 0; i < this._hashSize/*-1*/; i++) // forget history
+ this._head[i] = 0;
+ }
+ }
+ this.FlushPending();
+ if (base.avail_out == 0)
+ {
+ last_flush = (FlushType)(-1); // avoid BUF_ERROR at next call, see above
+ return ZLibStatus.Z_OK;
+ }
+ }
+ }
+
+ if (flush != FlushType.Z_FINISH) return ZLibStatus.Z_OK;
+ if (noheader != 0) return ZLibStatus.Z_STREAM_END;
+
+ // Write the zlib trailer (adler32)
+ PutShortMSB((int)(base.adler >> 16));
+ PutShortMSB((int)(base.adler & 0xffff));
+ this.FlushPending();
+
+ // If avail_out is zero, the application will call deflate again
+ // to flush the rest.
+ noheader = -1; // write the trailer only once!
+ return pending != 0 ? ZLibStatus.Z_OK : ZLibStatus.Z_STREAM_END;
+ }
+
+ ///
+ /// Restore the heap property by moving down the tree starting at node k,
+ /// exchanging a node with the smallest of its two sons if necessary, stopping
+ /// when the heap property is re-established (each father smaller than its
+ /// two sons).
+ ///
+ /// The tree to restore.
+ /// The node to move down.
+ internal void RestoreHeap(short[] tree, int k)
+ {
+ int v = heap[k];
+ int j = k << 1; // left son of k
+ while (j <= heap_len)
+ {
+ // Set j to the smallest of the two sons:
+ if (j < heap_len &&
+ Smaller(tree, heap[j + 1], heap[j], depth))
+ {
+ j++;
+ }
+ // Exit if v is smaller than both sons
+ if (Smaller(tree, v, heap[j], depth)) break;
+
+ // Exchange v with the smallest son
+ heap[k] = heap[j]; k = j;
+ // And continue down the tree, setting j to the left son of k
+ j <<= 1;
+ }
+ heap[k] = v;
+ }
+
+ private ZLibStatus deflateInit(CompressionLevel level)
+ {
+ return deflateInit(level, MAX_WBITS);
+ }
+
+ private ZLibStatus deflateInit(CompressionLevel level, bool nowrap)
+ {
+ return deflateInit(level, MAX_WBITS, nowrap);
+ }
+
+ private ZLibStatus deflateInit(CompressionLevel level, int bits, bool nowrap)
+ {
+ return this.deflateInit(level, nowrap ? -bits : bits);
+ }
+
+ private ZLibStatus deflateInit(CompressionLevel level, int bits)
+ {
+ return deflateInit2(level, Z_DEFLATED, bits, DEF_MEM_LEVEL, CompressionStrategy.Z_DEFAULT_STRATEGY);
+ }
+
+ private ZLibStatus deflateInit2(CompressionLevel level, int method, int windowBits, int memLevel, CompressionStrategy strategy)
+ {
+ int noheader = 0;
+ // byte[] my_version=ZLIB_VERSION;
+
+ //
+ // if (version == null || version[0] != my_version[0]
+ // || stream_size != sizeof(z_stream)) {
+ // return Z_VERSION_ERROR;
+ // }
+
+ base.msg = null;
+
+ if (level == CompressionLevel.Z_DEFAULT_COMPRESSION) level = (CompressionLevel)6;
+
+ if (windowBits < 0)
+ { // undocumented feature: suppress zlib header
+ noheader = 1;
+ windowBits = -windowBits;
+ }
+
+ if (memLevel < 1 || memLevel > MAX_MEM_LEVEL ||
+ method != Z_DEFLATED ||
+ windowBits < 9 || windowBits > 15 || level < 0 || level > (CompressionLevel)9 ||
+ strategy < 0 || strategy > CompressionStrategy.Z_HUFFMAN_ONLY)
+ {
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+
+ this.noheader = noheader;
+ _windowBits = windowBits;
+ _windowSize = 1 << _windowBits;
+ _windowMask = _windowSize - 1;
+
+ _hashBits = memLevel + 7;
+ _hashSize = 1 << _hashBits;
+ _hashMask = _hashSize - 1;
+ _hashShift = ((_hashBits + MIN_MATCH - 1) / MIN_MATCH);
+
+ _window = new byte[_windowSize * 2];
+ _previous = new short[_windowSize];
+ _head = new short[_hashSize];
+
+ lit_bufsize = 1 << (memLevel + 6); // 16K elements by default
+
+ // We overlay pending_buf and d_buf+l_buf. This works since the average
+ // output size for (length,distance) codes is <= 24 bits.
+ pending_buf = new byte[lit_bufsize * 4];
+ _pendingBufferSize = lit_bufsize * 4;
+
+ d_buf = lit_bufsize / 2;
+ l_buf = (1 + 2) * lit_bufsize;
+
+ this.level = level;
+
+ //System.out.println("level="+level);
+
+ this.strategy = strategy;
+ this._method = (byte)method;
+
+ return deflateReset();
+ }
+
+ private ZLibStatus deflateReset()
+ {
+ base.total_in = base.total_out = 0;
+ base.msg = null; //
+ base.data_type = BlockType.Z_UNKNOWN;
+
+ pending = 0;
+ pending_out = 0;
+
+ if (noheader < 0)
+ {
+ noheader = 0; // was set to -1 by deflate(..., FlushType.Z_FINISH);
+ }
+ _status = (noheader != 0) ? BUSY_STATE : INIT_STATE;
+ base.adler = Adler32.adler32(0, null, 0, 0);
+
+ last_flush = FlushType.Z_NO_FLUSH;
+
+ InitializeTreeData();
+ lm_init();
+ return ZLibStatus.Z_OK;
+ }
+
+ private ZLibStatus deflateParams(CompressionLevel _level, CompressionStrategy _strategy)
+ {
+ ZLibStatus err = ZLibStatus.Z_OK;
+
+ if (_level == CompressionLevel.Z_DEFAULT_COMPRESSION)
+ {
+ _level = (CompressionLevel)6;
+ }
+ if (_level < 0 || _level > (CompressionLevel)9 ||
+ _strategy < 0 || _strategy > CompressionStrategy.Z_HUFFMAN_ONLY)
+ {
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+
+ if (config_table[level].Function != config_table[_level].Function &&
+ base.total_in != 0)
+ {
+ // Flush the last buffer:
+ err = this.deflate(FlushType.Z_PARTIAL_FLUSH);
+ }
+
+ if (level != _level)
+ {
+ level = _level;
+ _maxLazyMatch = config_table[level].MaxLazy;
+ good_match = config_table[level].GoodLength;
+ nice_match = config_table[level].NiceLength;
+ _maxChainLength = config_table[level].MaxChain;
+ }
+ strategy = _strategy;
+ return err;
+ }
+
+ private ZLibStatus deflateSetDictionary(byte[] dictionary, int dictLength)
+ {
+ int length = dictLength;
+ int index = 0;
+
+ if (dictionary == null || _status != INIT_STATE)
+ return ZLibStatus.Z_STREAM_ERROR;
+
+ base.adler = Adler32.adler32(base.adler, dictionary, 0, dictLength);
+
+ if (length < MIN_MATCH) return ZLibStatus.Z_OK;
+ if (length > _windowSize - MIN_LOOKAHEAD)
+ {
+ length = _windowSize - MIN_LOOKAHEAD;
+ index = dictLength - length; // use the tail of the dictionary
+ }
+ System.Array.Copy(dictionary, index, _window, 0, length);
+ _startInsertString = length;
+ _blockStart = length;
+
+ // Insert all strings in the hash table (except for the last two bytes).
+ // s->lookahead stays null, so s->ins_h will be recomputed at the next
+ // call of fill_window.
+
+ _insertedHashIndex = _window[0] & 0xff;
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[1] & 0xff)) & _hashMask;
+
+ for (int n = 0; n <= length - MIN_MATCH; n++)
+ {
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[(n) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+ _previous[n & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)n;
+ }
+ return ZLibStatus.Z_OK;
+ }
+
+ private void lm_init()
+ {
+ _windowActualSize = 2 * _windowSize;
+
+ _head[_hashSize - 1] = 0;
+ for (int i = 0; i < _hashSize - 1; i++)
+ {
+ _head[i] = 0;
+ }
+
+ // Set the default configuration parameters:
+ _maxLazyMatch = Deflate.config_table[level].MaxLazy;
+ good_match = Deflate.config_table[level].GoodLength;
+ nice_match = Deflate.config_table[level].NiceLength;
+ _maxChainLength = Deflate.config_table[level].MaxChain;
+
+ _startInsertString = 0;
+ _blockStart = 0;
+ _validBytesAhead = 0;
+ _matchLength = _previousLength = MIN_MATCH - 1;
+ _matchAvailable = false;
+ _insertedHashIndex = 0;
+ }
+
+ ///
+ /// Initialize the tree data structures for a new zlib stream.
+ ///
+ private void InitializeTreeData()
+ {
+
+ l_desc.Init(dyn_ltree, Deflate.static_l_desc);
+
+ d_desc.Init(dyn_dtree, Deflate.static_d_desc);
+
+ bl_desc.Init(bl_tree, Deflate.static_bl_desc);
+
+
+ _bitBuffer = 0;
+ bi_valid = 0;
+ last_eob_len = 8; // enough lookahead for inflate
+
+ // Initialize the first block of the first file:
+ InitializeBlock();
+ }
+
+ private void InitializeBlock()
+ {
+ // Initialize the trees.
+ for (int i = 0; i < L_CODES; i++) dyn_ltree[i * 2] = 0;
+ for (int i = 0; i < D_CODES; i++) dyn_dtree[i * 2] = 0;
+ for (int i = 0; i < BL_CODES; i++) bl_tree[i * 2] = 0;
+
+ dyn_ltree[END_BLOCK * 2] = 1;
+ opt_len = static_len = 0;
+ last_lit = matches = 0;
+ }
+
+ private static bool Smaller(short[] tree, int n, int m, byte[] depth)
+ {
+ short tn2 = tree[n * 2];
+ short tm2 = tree[m * 2];
+ return (tn2 < tm2 ||
+ (tn2 == tm2 && depth[n] <= depth[m]));
+ }
+
+ ///
+ /// Scan a literal or distance tree to determine the frequencies of the codes
+ /// in the bit length tree.
+ ///
+ /// The tree to be scanned.
+ /// The tree's largest code of non zero frequency.
+ private void ScanTree(short[] tree, int max_code)
+ {
+ int n; // iterates over all tree elements
+ int prevlen = -1; // last emitted length
+ int curlen; // length of current code
+ int nextlen = tree[0 * 2 + 1]; // length of next code
+ int count = 0; // repeat count of the current code
+ int max_count = 7; // max repeat count
+ int min_count = 4; // min repeat count
+
+ if (nextlen == 0) { max_count = 138; min_count = 3; }
+ tree[(max_code + 1) * 2 + 1] = -1; // guard
+
+ for (n = 0; n <= max_code; n++)
+ {
+ curlen = nextlen; nextlen = tree[(n + 1) * 2 + 1];
+ if (++count < max_count && curlen == nextlen)
+ {
+ continue;
+ }
+ else if (count < min_count)
+ {
+ bl_tree[curlen * 2] += (short)count;
+ }
+ else if (curlen != 0)
+ {
+ if (curlen != prevlen) bl_tree[curlen * 2]++;
+ bl_tree[REP_3_6 * 2]++;
+ }
+ else if (count <= 10)
+ {
+ bl_tree[REPZ_3_10 * 2]++;
+ }
+ else
+ {
+ bl_tree[REPZ_11_138 * 2]++;
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0)
+ {
+ max_count = 138; min_count = 3;
+ }
+ else if (curlen == nextlen)
+ {
+ max_count = 6; min_count = 3;
+ }
+ else
+ {
+ max_count = 7; min_count = 4;
+ }
+ }
+ }
+
+ ///
+ /// Construct the Huffman tree for the bit lengths and return the index in bl_order of the last bit length code to send.
+ ///
+ ///
+ private int BuildBlTree()
+ {
+ int max_blindex; // index of last bit length code of non zero freq
+
+ // Determine the bit length frequencies for literal and distance trees
+ ScanTree(dyn_ltree, l_desc.LargestCode);
+ ScanTree(dyn_dtree, d_desc.LargestCode);
+
+ // Build the bit length tree:
+ bl_desc.BuildTree(this);
+ // opt_len now includes the length of the tree representations, except
+ // the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
+
+ // Determine the number of bit length codes to send. The pkzip format
+ // requires that at least 4 bit length codes be sent. (appnote.txt says
+ // 3 but the actual value used is 4.)
+ for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--)
+ {
+ if (bl_tree[Deflate.bl_order[max_blindex] * 2 + 1] != 0) break;
+ }
+ // Update opt_len to include the bit length tree and counts
+ opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4;
+
+ return max_blindex;
+ }
+
+ ///
+ /// Send the header for a block using dynamic Huffman trees: the counts, the lengths of the bit length codes, the literal tree and the distance tree.
+ ///
+ /// The lcodes.
+ /// The dcodes.
+ /// The blcodes.
+ private void SendAllTrees(int lcodes, int dcodes, int blcodes)
+ {
+ int rank; // index in bl_order
+
+ SendBits(lcodes - 257, 5); // not +255 as stated in appnote.txt
+ SendBits(dcodes - 1, 5);
+ SendBits(blcodes - 4, 4); // not -3 as stated in appnote.txt
+ for (rank = 0; rank < blcodes; rank++)
+ {
+ SendBits(bl_tree[Deflate.bl_order[rank] * 2 + 1], 3);
+ }
+ SendTree(dyn_ltree, lcodes - 1); // literal tree
+ SendTree(dyn_dtree, dcodes - 1); // distance tree
+ }
+
+ ///
+ /// Send a literal or distance tree in compressed form, using the codes in bl_tree.
+ ///
+ /// The tree to be sent.
+ /// The tree's largest code of non zero frequency.
+ private void SendTree(short[] tree, int max_code)
+ {
+ int n; // iterates over all tree elements
+ int prevlen = -1; // last emitted length
+ int curlen; // length of current code
+ int nextlen = tree[0 * 2 + 1]; // length of next code
+ int count = 0; // repeat count of the current code
+ int max_count = 7; // max repeat count
+ int min_count = 4; // min repeat count
+
+ if (nextlen == 0) { max_count = 138; min_count = 3; }
+
+ for (n = 0; n <= max_code; n++)
+ {
+ curlen = nextlen; nextlen = tree[(n + 1) * 2 + 1];
+ if (++count < max_count && curlen == nextlen)
+ {
+ continue;
+ }
+ else if (count < min_count)
+ {
+ do { SendCode(curlen, bl_tree); } while (--count != 0);
+ }
+ else if (curlen != 0)
+ {
+ if (curlen != prevlen)
+ {
+ SendCode(curlen, bl_tree); count--;
+ }
+ SendCode(REP_3_6, bl_tree);
+ SendBits(count - 3, 2);
+ }
+ else if (count <= 10)
+ {
+ SendCode(REPZ_3_10, bl_tree);
+ SendBits(count - 3, 3);
+ }
+ else
+ {
+ SendCode(REPZ_11_138, bl_tree);
+ SendBits(count - 11, 7);
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0)
+ {
+ max_count = 138; min_count = 3;
+ }
+ else if (curlen == nextlen)
+ {
+ max_count = 6; min_count = 3;
+ }
+ else
+ {
+ max_count = 7; min_count = 4;
+ }
+ }
+ }
+
+ ///
+ /// Puts a bytes into the stream.
+ ///
+ /// The p.
+ /// The start.
+ /// The len.
+ private void PutByte(byte[] p, int start, int len)
+ {
+ System.Array.Copy(p, start, pending_buf, pending, len);
+ pending += len;
+ }
+
+ ///
+ /// Puts a byte into the stream.
+ ///
+ /// The c.
+ private void PutByte(byte c)
+ {
+ pending_buf[pending++] = c;
+ }
+
+ ///
+ /// Puts a short into the stream.
+ ///
+ /// The w.
+ private void PutShort(int w)
+ {
+ pending_buf[pending++] = (byte)(w/*&0xff*/);
+ pending_buf[pending++] = (byte)(w >> 8);
+ }
+
+ ///
+ /// Puts the short MSB.
+ ///
+ /// The b.
+ private void PutShortMSB(int b)
+ {
+ pending_buf[pending++] = (byte)(b >> 8);
+ pending_buf[pending++] = (byte)(b/*&0xff*/);
+ }
+
+ private void SendCode(int code, short[] tree)
+ {
+ int c2 = code * 2;
+ SendBits((tree[c2] & 0xffff), (tree[c2 + 1] & 0xffff));
+ }
+
+ private void SendBits(int bits, int length)
+ {
+ if (bi_valid > Buf_size - length)
+ {
+ _bitBuffer |= (uint)(bits << bi_valid);
+ pending_buf[pending++] = (byte)(_bitBuffer/*&0xff*/);
+ pending_buf[pending++] = (byte)(_bitBuffer >> 8);
+ _bitBuffer = ((uint)bits) >> (Buf_size - bi_valid);
+ bi_valid += length - Buf_size;
+ }
+ else
+ {
+ _bitBuffer |= (uint)(bits << bi_valid);
+ bi_valid += length;
+ }
+ // int len = length;
+ // if (bi_valid > (int)Buf_size - len) {
+ // int val = value;
+ // // bi_buf |= (val << bi_valid);
+ // bi_buf = (short)((ushort)bi_buf | (ushort)((val << bi_valid)&0xffff));
+ // put_short(bi_buf);
+ // bi_buf = (short)(((uint)val) >> (Buf_size - bi_valid));
+ // bi_valid += len - Buf_size;
+ // } else {
+ // // bi_buf |= (value) << bi_valid;
+ // bi_buf = (short)((ushort)bi_buf | (ushort)(((value) << bi_valid)&0xffff));
+ // bi_valid += len;
+ // }
+ }
+
+ ///
+ /// Send one empty static block to give enough lookahead for inflate.
+ /// This takes 10 bits, of which 7 may remain in the bit buffer.
+ /// The current inflate code requires 9 bits of lookahead. If the
+ /// last two codes for the previous block (real code plus EOB) were coded
+ /// on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
+ /// the last real code. In this case we send two empty static blocks instead
+ /// of one. (There are no problems if the previous block is stored or fixed.)
+ /// To simplify the code, we assume the worst case of last real code encoded
+ /// on one bit only.
+ ///
+ private void _tr_align()
+ {
+ SendBits(STATIC_TREES << 1, 3);
+ SendCode(END_BLOCK, Deflate.static_ltree);
+
+ FlushBitBuffer();
+
+ // Of the 10 bits for the empty block, we have already sent
+ // (10 - bi_valid) bits. The lookahead for the last real code (before
+ // the EOB of the previous block) was thus at least one plus the length
+ // of the EOB plus what we have just sent of the empty static block.
+ if (1 + last_eob_len + 10 - bi_valid < 9)
+ {
+ SendBits(STATIC_TREES << 1, 3);
+ SendCode(END_BLOCK, Deflate.static_ltree);
+ FlushBitBuffer();
+ }
+ last_eob_len = 7;
+ }
+
+ ///
+ /// Save the match info and tally the frequency counts. Return true if
+ /// the current block must be flushed.
+ ///
+ /// The distance of matched string.
+ /// The match length-MIN_MATCH or unmatched char (if dist==0).
+ ///
+ private bool _tr_tally(int dist, int lc)
+ {
+
+ pending_buf[d_buf + last_lit * 2] = (byte)(dist >> 8);
+ pending_buf[d_buf + last_lit * 2 + 1] = (byte)dist;
+
+ pending_buf[l_buf + last_lit] = (byte)lc; last_lit++;
+
+ if (dist == 0)
+ {
+ // lc is the unmatched char
+ dyn_ltree[lc * 2]++;
+ }
+ else
+ {
+ matches++;
+ // Here, lc is the match length - MIN_MATCH
+ dist--; // dist = match distance - 1
+ dyn_ltree[(Deflate._length_code[lc] + LITERALS + 1) * 2]++;
+ dyn_dtree[Tree.DistanceCode(dist) * 2]++;
+ }
+
+ if ((last_lit & 0x1fff) == 0 && level > (CompressionLevel)2)
+ {
+ // Compute an upper bound for the compressed length
+ int out_length = last_lit * 8;
+ int in_length = _startInsertString - _blockStart;
+ int dcode;
+ for (dcode = 0; dcode < D_CODES; dcode++)
+ {
+ out_length += (int)((int)dyn_dtree[dcode * 2] *
+ (5L + Deflate.extra_dbits[dcode]));
+ }
+ out_length >>= 3;
+ if ((matches < (last_lit / 2)) && out_length < in_length / 2) return true;
+ }
+
+ return (last_lit == lit_bufsize - 1);
+ // We avoid equality with lit_bufsize because of wraparound at 64K
+ // on 16 bit machines and because stored blocks are restricted to
+ // 64K-1 bytes.
+ }
+
+ ///
+ /// Send the block data compressed using the given Huffman trees
+ ///
+ /// The ltree.
+ /// The dtree.
+ private void CompressBlock(short[] ltree, short[] dtree)
+ {
+ int dist; // distance of matched string
+ int lc; // match length or unmatched char (if dist == 0)
+ int lx = 0; // running index in l_buf
+ int code; // the code to send
+ int extra; // number of extra bits to send
+
+ if (last_lit != 0)
+ {
+ do
+ {
+ dist = ((pending_buf[d_buf + lx * 2] << 8) & 0xff00) |
+ (pending_buf[d_buf + lx * 2 + 1] & 0xff);
+ lc = (pending_buf[l_buf + lx]) & 0xff; lx++;
+
+ if (dist == 0)
+ {
+ SendCode(lc, ltree); // send a literal byte
+ }
+ else
+ {
+ // Here, lc is the match length - MIN_MATCH
+ code = Deflate._length_code[lc];
+
+ SendCode(code + LITERALS + 1, ltree); // send the length code
+ extra = Deflate.extra_lbits[code];
+ if (extra != 0)
+ {
+ lc -= Deflate.base_length[code];
+ SendBits(lc, extra); // send the extra length bits
+ }
+ dist--; // dist is now the match distance - 1
+ code = Tree.DistanceCode(dist);
+
+ SendCode(code, dtree); // send the distance code
+ extra = Deflate.extra_dbits[code];
+ if (extra != 0)
+ {
+ dist -= Deflate.base_dist[code];
+ SendBits(dist, extra); // send the extra distance bits
+ }
+ } // literal or match pair ?
+
+ // Check that the overlay between pending_buf and d_buf+l_buf is ok:
+ }
+ while (lx < last_lit);
+ }
+
+ SendCode(END_BLOCK, ltree);
+ last_eob_len = ltree[END_BLOCK * 2 + 1];
+ }
+
+ ///
+ /// Set the data type to ASCII or BINARY, using a crude approximation:
+ /// binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise.
+ /// IN assertion: the fields freq of dyn_ltree are set and the total of all
+ /// frequencies does not exceed 64K (to fit in an int on 16 bit machines).
+ ///
+ private void SetDataType()
+ {
+ int n = 0;
+ int ascii_freq = 0;
+ int bin_freq = 0;
+ while (n < 7) { bin_freq += dyn_ltree[n * 2]; n++; }
+ while (n < 128) { ascii_freq += dyn_ltree[n * 2]; n++; }
+ while (n < LITERALS) { bin_freq += dyn_ltree[n * 2]; n++; }
+ this._dataType = (bin_freq > (ascii_freq >> 2) ? BlockType.Z_BINARY : BlockType.Z_ASCII);
+ }
+
+ ///
+ /// Flush the bit buffer, keeping at most 7 bits in it.
+ ///
+ private void FlushBitBuffer()
+ {
+ if (bi_valid == 16)
+ {
+ pending_buf[pending++] = (byte)(_bitBuffer/*&0xff*/);
+ pending_buf[pending++] = (byte)(_bitBuffer >> 8);
+ _bitBuffer = 0;
+ bi_valid = 0;
+ }
+ else if (bi_valid >= 8)
+ {
+ pending_buf[pending++] = (byte)(_bitBuffer);
+ _bitBuffer >>= 8;
+ _bitBuffer &= 0x00ff;
+ bi_valid -= 8;
+ }
+ }
+
+ ///
+ /// Flush the bit buffer and align the output on a byte boundary
+ ///
+ private void bi_windup()
+ {
+ if (bi_valid > 8)
+ {
+ pending_buf[pending++] = (byte)(_bitBuffer);
+ pending_buf[pending++] = (byte)(_bitBuffer >> 8);
+ }
+ else if (bi_valid > 0)
+ {
+ pending_buf[pending++] = (byte)(_bitBuffer);
+ }
+ _bitBuffer = 0;
+ bi_valid = 0;
+ }
+
+ ///
+ /// Copy a stored block, storing first the length and its one's complement if requested.
+ ///
+ /// The input data.
+ /// The length.
+ /// if set to true block header must be written.
+ private void CopyBlock(int buf, int len, bool header)
+ {
+ //int index=0;
+ bi_windup(); // align on byte boundary
+ last_eob_len = 8; // enough lookahead for inflate
+
+ if (header)
+ {
+ PutShort((short)len);
+ PutShort((short)~len);
+ }
+
+ // while(len--!=0) {
+ // put_byte(window[buf+index]);
+ // index++;
+ // }
+ PutByte(_window, buf, len);
+ }
+
+ private void FlushBlockOnly(bool eof)
+ {
+ FlushBlock(_blockStart >= 0 ? _blockStart : -1,
+ _startInsertString - _blockStart,
+ eof);
+ _blockStart = _startInsertString;
+ this.FlushPending();
+ }
+
+ ///
+ /// Copy without compression as much as possible from the input stream, return
+ /// the current block state.
+ /// This function does not insert new strings in the dictionary since
+ /// uncompressible data is probably not useful. This function is used
+ /// only for the level=0 compression option.
+ ///
+ /// The flush.
+ ///
+ private int DeflateStored(FlushType flush)
+ {
+ // TODO: this function should be optimized to avoid extra copying from window to pending_buf.
+
+ // Stored blocks are limited to 0xffff bytes, pending_buf is limited
+ // to pending_buf_size, and each stored block has a 5 byte header:
+
+ int max_block_size = 0xffff;
+ int max_start;
+
+ if (max_block_size > _pendingBufferSize - 5)
+ {
+ max_block_size = _pendingBufferSize - 5;
+ }
+
+ // Copy as much as possible from input to output:
+ while (true)
+ {
+ // Fill the window as much as possible:
+ if (_validBytesAhead <= 1)
+ {
+ FillWindow();
+ if (_validBytesAhead == 0 && flush == FlushType.Z_NO_FLUSH) return NeedMore;
+ if (_validBytesAhead == 0) break; // flush the current block
+ }
+
+ _startInsertString += _validBytesAhead;
+ _validBytesAhead = 0;
+
+ // Emit a stored block if pending_buf will be full:
+ max_start = _blockStart + max_block_size;
+ if (_startInsertString == 0 || _startInsertString >= max_start)
+ {
+ // strstart == 0 is possible when wraparound on 16-bit machine
+ _validBytesAhead = (int)(_startInsertString - max_start);
+ _startInsertString = (int)max_start;
+
+ FlushBlockOnly(false);
+ if (base.avail_out == 0) return NeedMore;
+
+ }
+
+ // Flush if we may have to slide, otherwise block_start may become
+ // negative and the data will be gone:
+ if (_startInsertString - _blockStart >= _windowSize - MIN_LOOKAHEAD)
+ {
+ FlushBlockOnly(false);
+ if (base.avail_out == 0) return NeedMore;
+ }
+ }
+
+ FlushBlockOnly(flush == FlushType.Z_FINISH);
+ if (base.avail_out == 0)
+ return (flush == FlushType.Z_FINISH) ? FinishStarted : NeedMore;
+
+ return flush == FlushType.Z_FINISH ? FinishDone : BlockDone;
+ }
+
+ ///
+ /// Send a stored block
+ ///
+ /// The input block.
+ /// The length of input block.
+ /// if set to true then this is the last block for a file.
+ private void SendStoredBlock(int buf, int stored_len, bool eof)
+ {
+ SendBits((STORED_BLOCK << 1) + (eof ? 1 : 0), 3); // send block type
+ CopyBlock(buf, stored_len, true); // with header
+ }
+
+ ///
+ /// Determine the best encoding for the current block: dynamic trees, static
+ /// trees or store, and output the encoded block to the zip file.
+ ///
+ /// The input block, or NULL if too old.
+ /// The length of input block.
+ /// if set to true then this is the last block for a file.
+ private void FlushBlock(int buf, int stored_len, bool eof)
+ {
+ int opt_lenb, static_lenb;// opt_len and static_len in bytes
+ int max_blindex = 0; // index of last bit length code of non zero freq
+
+ // Build the Huffman trees unless a stored block is forced
+ if (level > 0)
+ {
+ // Check if the file is ascii or binary
+ if (this._dataType == BlockType.Z_UNKNOWN) SetDataType();
+
+ // Construct the literal and distance trees
+ l_desc.BuildTree(this);
+
+ d_desc.BuildTree(this);
+
+ // At this point, opt_len and static_len are the total bit lengths of
+ // the compressed block data, excluding the tree representations.
+
+ // Build the bit length tree for the above two trees, and get the index
+ // in bl_order of the last bit length code to send.
+ max_blindex = BuildBlTree();
+
+ // Determine the best encoding. Compute first the block length in bytes
+ opt_lenb = (opt_len + 3 + 7) >> 3;
+ static_lenb = (static_len + 3 + 7) >> 3;
+
+ if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
+ }
+ else
+ {
+ opt_lenb = static_lenb = stored_len + 5; // force a stored block
+ }
+
+ if (stored_len + 4 <= opt_lenb && buf != -1)
+ {
+ // 4: two words for the lengths
+ // The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
+ // Otherwise we can't have processed more than WSIZE input bytes since
+ // the last block flush, because compression would have been
+ // successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
+ // transform a block into a stored block.
+ SendStoredBlock(buf, stored_len, eof);
+ }
+ else if (static_lenb == opt_lenb)
+ {
+ SendBits((STATIC_TREES << 1) + (eof ? 1 : 0), 3);
+ CompressBlock(Deflate.static_ltree, Deflate.static_dtree);
+ }
+ else
+ {
+ SendBits((DYN_TREES << 1) + (eof ? 1 : 0), 3);
+ SendAllTrees(l_desc.LargestCode + 1, d_desc.LargestCode + 1, max_blindex + 1);
+ CompressBlock(dyn_ltree, dyn_dtree);
+ }
+
+ // The above check is made mod 2^32, for files larger than 512 MB
+ // and uLong implemented on 32 bits.
+
+ InitializeBlock();
+
+ if (eof)
+ {
+ bi_windup();
+ }
+ }
+
+ ///
+ /// Fill the window when the lookahead becomes insufficient.
+ /// Updates strstart and lookahead.
+ ///
+ private void FillWindow()
+ {
+ int n, m;
+ int p;
+ int more; // Amount of free space at the end of the window.
+
+ do
+ {
+ more = (_windowActualSize - _validBytesAhead - _startInsertString);
+
+ // Deal with !@#$% 64K limit:
+ if (more == 0 && _startInsertString == 0 && _validBytesAhead == 0)
+ {
+ more = _windowSize;
+ }
+ else if (more == -1)
+ {
+ // Very unlikely, but possible on 16 bit machine if strstart == 0
+ // and lookahead == 1 (input done one byte at time)
+ more--;
+
+ // If the window is almost full and there is insufficient lookahead,
+ // move the upper half to the lower one to make room in the upper half.
+ }
+ else if (_startInsertString >= _windowSize + _windowSize - MIN_LOOKAHEAD)
+ {
+ System.Array.Copy(_window, _windowSize, _window, 0, _windowSize);
+ _startMatchString -= _windowSize;
+ _startInsertString -= _windowSize; // we now have strstart >= MAX_DIST
+ _blockStart -= _windowSize;
+
+ // Slide the hash table (could be avoided with 32 bit values
+ // at the expense of memory usage). We slide even when level == 0
+ // to keep the hash table consistent if we switch back to level > 0
+ // later. (Using level 0 permanently is not an optimal usage of
+ // zlib, so we don't care about this pathological case.)
+
+ n = _hashSize;
+ p = n;
+ do
+ {
+ m = (_head[--p] & 0xffff);
+ _head[p] = (short)(m >= _windowSize ? (m - _windowSize) : 0);
+ }
+ while (--n != 0);
+
+ n = _windowSize;
+ p = n;
+ do
+ {
+ m = (_previous[--p] & 0xffff);
+ _previous[p] = (short)(m >= _windowSize ? (m - _windowSize) : 0);
+ // If n is not on any hash chain, prev[n] is garbage but
+ // its value will never be used.
+ }
+ while (--n != 0);
+ more += _windowSize;
+ }
+
+ if (base.avail_in == 0) return;
+
+ // If there was no sliding:
+ // strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
+ // more == window_size - lookahead - strstart
+ // => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
+ // => more >= window_size - 2*WSIZE + 2
+ // In the BIG_MEM or MMAP case (not yet supported),
+ // window_size == input_size + MIN_LOOKAHEAD &&
+ // strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
+ // Otherwise, window_size == 2*WSIZE so more >= 2.
+ // If there was sliding, more >= WSIZE. So in all cases, more >= 2.
+
+ n = this.ReadBuffer(_window, _startInsertString + _validBytesAhead, more);
+ _validBytesAhead += n;
+
+ // Initialize the hash value now that we have some input:
+ if (_validBytesAhead >= MIN_MATCH)
+ {
+ _insertedHashIndex = _window[_startInsertString] & 0xff;
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[_startInsertString + 1] & 0xff)) & _hashMask;
+ }
+ // If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
+ // but this is not important since only literal bytes will be emitted.
+ }
+ while (_validBytesAhead < MIN_LOOKAHEAD && base.avail_in != 0);
+ }
+
+ ///
+ /// Compress as much as possible from the input stream, return the current
+ /// block state.
+ /// This function does not perform lazy evaluation of matches and inserts
+ /// new strings in the dictionary only for unmatched strings or for short
+ /// matches. It is used only for the fast compression options.
+ ///
+ /// The flush.
+ ///
+ private int DeflateFast(FlushType flush)
+ {
+ // short hash_head = 0; // head of the hash chain
+ int hash_head = 0; // head of the hash chain
+ bool bflush; // set if current block must be flushed
+
+ while (true)
+ {
+ // Make sure that we always have enough lookahead, except
+ // at the end of the input file. We need MAX_MATCH bytes
+ // for the next match, plus MIN_MATCH bytes to insert the
+ // string following the next match.
+ if (_validBytesAhead < MIN_LOOKAHEAD)
+ {
+ FillWindow();
+ if (_validBytesAhead < MIN_LOOKAHEAD && flush == FlushType.Z_NO_FLUSH)
+ {
+ return NeedMore;
+ }
+ if (_validBytesAhead == 0) break; // flush the current block
+ }
+
+ // Insert the string window[strstart .. strstart+2] in the
+ // dictionary, and set hash_head to the head of the hash chain:
+ if (_validBytesAhead >= MIN_MATCH)
+ {
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[(_startInsertString) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+
+ // prev[strstart&w_mask]=hash_head=head[ins_h];
+ hash_head = (_head[_insertedHashIndex] & 0xffff);
+ _previous[_startInsertString & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)_startInsertString;
+ }
+
+ // Find the longest match, discarding those <= prev_length.
+ // At this point we have always match_length < MIN_MATCH
+
+ if (hash_head != 0L &&
+ ((_startInsertString - hash_head) & 0xffff) <= _windowSize - MIN_LOOKAHEAD
+ )
+ {
+ // To simplify the code, we prevent matches with the string
+ // of window index 0 (in particular we have to avoid a match
+ // of the string with itself at the start of the input file).
+ if (strategy != CompressionStrategy.Z_HUFFMAN_ONLY)
+ {
+ _matchLength = LongestMatch(hash_head);
+ }
+ // longest_match() sets match_start
+ }
+ if (_matchLength >= MIN_MATCH)
+ {
+ // check_match(strstart, match_start, match_length);
+
+ bflush = _tr_tally(_startInsertString - _startMatchString, _matchLength - MIN_MATCH);
+
+ _validBytesAhead -= _matchLength;
+
+ // Insert new strings in the hash table only if the match length
+ // is not too large. This saves time but degrades compression.
+ if (_matchLength <= _maxLazyMatch &&
+ _validBytesAhead >= MIN_MATCH)
+ {
+ _matchLength--; // string at strstart already in hash table
+ do
+ {
+ _startInsertString++;
+
+ _insertedHashIndex = ((_insertedHashIndex << _hashShift) ^ (_window[(_startInsertString) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+ // prev[strstart&w_mask]=hash_head=head[ins_h];
+ hash_head = (_head[_insertedHashIndex] & 0xffff);
+ _previous[_startInsertString & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)_startInsertString;
+
+ // strstart never exceeds WSIZE-MAX_MATCH, so there are
+ // always MIN_MATCH bytes ahead.
+ }
+ while (--_matchLength != 0);
+ _startInsertString++;
+ }
+ else
+ {
+ _startInsertString += _matchLength;
+ _matchLength = 0;
+ _insertedHashIndex = _window[_startInsertString] & 0xff;
+
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[_startInsertString + 1] & 0xff)) & _hashMask;
+ // If lookahead < MIN_MATCH, ins_h is garbage, but it does not
+ // matter since it will be recomputed at next deflate call.
+ }
+ }
+ else
+ {
+ // No match, output a literal byte
+
+ bflush = _tr_tally(0, _window[_startInsertString] & 0xff);
+ _validBytesAhead--;
+ _startInsertString++;
+ }
+ if (bflush)
+ {
+
+ FlushBlockOnly(false);
+ if (base.avail_out == 0) return NeedMore;
+ }
+ }
+
+ FlushBlockOnly(flush == FlushType.Z_FINISH);
+ if (base.avail_out == 0)
+ {
+ if (flush == FlushType.Z_FINISH) return FinishStarted;
+ else return NeedMore;
+ }
+ return flush == FlushType.Z_FINISH ? FinishDone : BlockDone;
+ }
+
+ ///
+ /// Same as above, but achieves better compression. We use a lazy
+ /// evaluation for matches: a match is finally adopted only if there is
+ /// no better match at the next window position.
+ ///
+ /// The flush.
+ ///
+ private int DeflateSlow(FlushType flush)
+ {
+ // short hash_head = 0; // head of hash chain
+ int hash_head = 0; // head of hash chain
+ bool bflush; // set if current block must be flushed
+
+ // Process the input block.
+ while (true)
+ {
+ // Make sure that we always have enough lookahead, except
+ // at the end of the input file. We need MAX_MATCH bytes
+ // for the next match, plus MIN_MATCH bytes to insert the
+ // string following the next match.
+
+ if (_validBytesAhead < MIN_LOOKAHEAD)
+ {
+ FillWindow();
+ if (_validBytesAhead < MIN_LOOKAHEAD && flush == FlushType.Z_NO_FLUSH)
+ {
+ return NeedMore;
+ }
+ if (_validBytesAhead == 0) break; // flush the current block
+ }
+
+ // Insert the string window[strstart .. strstart+2] in the
+ // dictionary, and set hash_head to the head of the hash chain:
+
+ if (_validBytesAhead >= MIN_MATCH)
+ {
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[(_startInsertString) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+ // prev[strstart&w_mask]=hash_head=head[ins_h];
+ hash_head = (_head[_insertedHashIndex] & 0xffff);
+ _previous[_startInsertString & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)_startInsertString;
+ }
+
+ // Find the longest match, discarding those <= prev_length.
+ _previousLength = _matchLength; _previousMatch = _startMatchString;
+ _matchLength = MIN_MATCH - 1;
+
+ if (hash_head != 0 && _previousLength < _maxLazyMatch &&
+ ((_startInsertString - hash_head) & 0xffff) <= _windowSize - MIN_LOOKAHEAD
+ )
+ {
+ // To simplify the code, we prevent matches with the string
+ // of window index 0 (in particular we have to avoid a match
+ // of the string with itself at the start of the input file).
+
+ if (strategy != CompressionStrategy.Z_HUFFMAN_ONLY)
+ {
+ _matchLength = LongestMatch(hash_head);
+ }
+ // longest_match() sets match_start
+
+ if (_matchLength <= 5 && (strategy == CompressionStrategy.Z_FILTERED ||
+ (_matchLength == MIN_MATCH &&
+ _startInsertString - _startMatchString > 4096)))
+ {
+
+ // If prev_match is also MIN_MATCH, match_start is garbage
+ // but we will ignore the current match anyway.
+ _matchLength = MIN_MATCH - 1;
+ }
+ }
+
+ // If there was a match at the previous step and the current
+ // match is not better, output the previous match:
+ if (_previousLength >= MIN_MATCH && _matchLength <= _previousLength)
+ {
+ int max_insert = _startInsertString + _validBytesAhead - MIN_MATCH;
+ // Do not insert strings in hash table beyond this.
+
+ // check_match(strstart-1, prev_match, prev_length);
+
+ bflush = _tr_tally(_startInsertString - 1 - _previousMatch, _previousLength - MIN_MATCH);
+
+ // Insert in hash table all strings up to the end of the match.
+ // strstart-1 and strstart are already inserted. If there is not
+ // enough lookahead, the last two strings are not inserted in
+ // the hash table.
+ _validBytesAhead -= _previousLength - 1;
+ _previousLength -= 2;
+ do
+ {
+ if (++_startInsertString <= max_insert)
+ {
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[(_startInsertString) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+ //prev[strstart&w_mask]=hash_head=head[ins_h];
+ hash_head = (_head[_insertedHashIndex] & 0xffff);
+ _previous[_startInsertString & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)_startInsertString;
+ }
+ }
+ while (--_previousLength != 0);
+ _matchAvailable = false;
+ _matchLength = MIN_MATCH - 1;
+ _startInsertString++;
+
+ if (bflush)
+ {
+ FlushBlockOnly(false);
+ if (base.avail_out == 0) return NeedMore;
+ }
+ }
+ else if (_matchAvailable != false)
+ {
+
+ // If there was no match at the previous position, output a
+ // single literal. If there was a match but the current match
+ // is longer, truncate the previous match to a single literal.
+
+ bflush = _tr_tally(0, _window[_startInsertString - 1] & 0xff);
+
+ if (bflush)
+ {
+ FlushBlockOnly(false);
+ }
+ _startInsertString++;
+ _validBytesAhead--;
+ if (base.avail_out == 0) return NeedMore;
+ }
+ else
+ {
+ // There is no previous match to compare with, wait for
+ // the next step to decide.
+
+ _matchAvailable = true;
+ _startInsertString++;
+ _validBytesAhead--;
+ }
+ }
+
+ if (_matchAvailable != false)
+ {
+ bflush = _tr_tally(0, _window[_startInsertString - 1] & 0xff);
+ _matchAvailable = false;
+ }
+ FlushBlockOnly(flush == FlushType.Z_FINISH);
+
+ if (base.avail_out == 0)
+ {
+ if (flush == FlushType.Z_FINISH) return FinishStarted;
+ else return NeedMore;
+ }
+
+ return flush == FlushType.Z_FINISH ? FinishDone : BlockDone;
+ }
+
+ private int LongestMatch(int cur_match)
+ {
+ int chain_length = _maxChainLength; // max hash chain length
+ int scan = _startInsertString; // current string
+ int match; // matched string
+ int len; // length of current match
+ int best_len = _previousLength; // best match length so far
+ int limit = _startInsertString > (_windowSize - MIN_LOOKAHEAD) ?
+ _startInsertString - (_windowSize - MIN_LOOKAHEAD) : 0;
+ int nice_match = this.nice_match;
+
+ // Stop when cur_match becomes <= limit. To simplify the code,
+ // we prevent matches with the string of window index 0.
+
+ int wmask = _windowMask;
+
+ int strend = _startInsertString + MAX_MATCH;
+ byte scan_end1 = _window[scan + best_len - 1];
+ byte scan_end = _window[scan + best_len];
+
+ // The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+ // It is easy to get rid of this optimization if necessary.
+
+ // Do not waste too much time if we already have a good match:
+ if (_previousLength >= good_match)
+ {
+ chain_length >>= 2;
+ }
+
+ // Do not look for matches beyond the end of the input. This is necessary
+ // to make deflate deterministic.
+ if (nice_match > _validBytesAhead) nice_match = _validBytesAhead;
+
+ do
+ {
+ match = cur_match;
+
+ // Skip to next match if the match length cannot increase
+ // or if the match length is less than 2:
+ if (_window[match + best_len] != scan_end ||
+ _window[match + best_len - 1] != scan_end1 ||
+ _window[match] != _window[scan] ||
+ _window[++match] != _window[scan + 1]) continue;
+
+ // The check at best_len-1 can be removed because it will be made
+ // again later. (This heuristic is not always a win.)
+ // It is not necessary to compare scan[2] and match[2] since they
+ // are always equal when the other bytes match, given that
+ // the hash keys are equal and that HASH_BITS >= 8.
+ scan += 2; match++;
+
+ // We check for insufficient lookahead only every 8th comparison;
+ // the 256th check will be made at strstart+258.
+ do
+ {
+ } while (_window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ scan < strend);
+
+ len = MAX_MATCH - (int)(strend - scan);
+ scan = strend - MAX_MATCH;
+
+ if (len > best_len)
+ {
+ _startMatchString = cur_match;
+ best_len = len;
+ if (len >= nice_match) break;
+ scan_end1 = _window[scan + best_len - 1];
+ scan_end = _window[scan + best_len];
+ }
+
+ } while ((cur_match = (_previous[cur_match & wmask] & 0xffff)) > limit
+ && --chain_length != 0);
+
+ if (best_len <= _validBytesAhead) return best_len;
+ return _validBytesAhead;
+ }
+
+ private class Config
+ {
+ ///
+ /// Reduce lazy search above this match length
+ ///
+ internal int GoodLength { get; private set; }
+ ///
+ /// Gets or sets whether not to perform lazy search above this match length
+ ///
+ ///
+ /// The max lazy.
+ ///
+ internal int MaxLazy { get; private set; }
+ ///
+ /// Gets or sets whether to quit search above this match length
+ ///
+ ///
+ /// The length of the nice.
+ ///
+ internal int NiceLength { get; private set; }
+ internal int MaxChain { get; private set; }
+ internal DefalteFlavor Function { get; private set; }
+ internal Config(int goodLength, int maxLazy, int niceLength, int maxChain, DefalteFlavor function)
+ {
+ this.GoodLength = goodLength;
+ this.MaxLazy = maxLazy;
+ this.NiceLength = niceLength;
+ this.MaxChain = maxChain;
+ this.Function = function;
+ }
+ }
+
+ ///
+ /// Flush as much pending output as possible. All deflate() output goes
+ /// through this function so some applications may wish to modify it
+ /// to avoid allocating a large strm->next_out buffer and copying into it.
+ /// (See also ReadBuffer()).
+ ///
+ private void FlushPending()
+ {
+ int len = this.pending;
+
+ if (len > avail_out) len = avail_out;
+ if (len == 0) return;
+
+ if (this.pending_buf.Length <= this.pending_out ||
+ next_out.Length <= next_out_index ||
+ this.pending_buf.Length < (this.pending_out + len) ||
+ next_out.Length < (next_out_index + len))
+ {
+ // System.out.println(this.pending_buf.length+", "+this.pending_out+
+ // ", "+next_out.length+", "+next_out_index+", "+len);
+ // System.out.println("avail_out="+avail_out);
+ }
+
+ System.Array.Copy(this.pending_buf, this.pending_out,
+ next_out, next_out_index, len);
+
+ next_out_index += len;
+ this.pending_out += len;
+ total_out += len;
+ avail_out -= len;
+ this.pending -= len;
+ if (this.pending == 0)
+ {
+ this.pending_out = 0;
+ }
+ }
+
+ ///
+ /// Reads a new buffer from the current input stream, update the adler32
+ /// and total number of bytes read. All deflate() input goes through
+ /// this function so some applications may wish to modify it to avoid
+ /// allocating a large strm->next_in buffer and copying from it.
+ /// (See also FlushPending()).
+ ///
+ /// The buf.
+ /// The start.
+ /// The size.
+ ///
+ private int ReadBuffer(byte[] buf, int start, int size)
+ {
+ int len = avail_in;
+
+ if (len > size) len = size;
+ if (len == 0) return 0;
+
+ avail_in -= len;
+
+ if (this.noheader == 0)
+ {
+ adler = Adler32.adler32(adler, next_in, next_in_index, len);
+ }
+ System.Array.Copy(next_in, next_in_index, buf, start, len);
+ next_in_index += len;
+ total_in += len;
+ return len;
+ }
+
+ // TODO: Delete this
+ public ZLibStatus inflateEnd()
+ {
+ throw new NotImplementedException();
+ }
+
+ public ZLibStatus inflate(byte[] bufer, int offset, int count, byte[] p1, int p2, int p3, FlushType flushType)
+ {
+ throw new NotImplementedException();
+ }
+
+ public ZLibStatus inflate(byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v10/Inflate.cs b/Renci.SshNet/Compression/v10/Inflate.cs
new file mode 100644
index 0000000..c05e2d8
--- /dev/null
+++ b/Renci.SshNet/Compression/v10/Inflate.cs
@@ -0,0 +1,524 @@
+using System;
+/*
+ * $Id: Inflate.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public enum InflateMode : int
+ {
+ ///
+ ///waiting for method byte
+ ///
+ METHOD = 0,
+ ///
+ /// waiting for flag byte
+ ///
+ FLAG = 1,
+ ///
+ /// four dictionary check bytes to go
+ ///
+ DICT4 = 2,
+ ///
+ /// three dictionary check bytes to go
+ ///
+ DICT3 = 3,
+ ///
+ /// two dictionary check bytes to go
+ ///
+ DICT2 = 4,
+ ///
+ /// one dictionary check byte to go
+ ///
+ DICT1 = 5,
+ ///
+ /// waiting for inflateSetDictionary
+ ///
+ DICT0 = 6,
+ ///
+ /// decompressing blocks
+ ///
+ BLOCKS = 7,
+ ///
+ /// four check bytes to go
+ ///
+ CHECK4 = 8,
+ ///
+ /// three check bytes to go
+ ///
+ CHECK3 = 9,
+ ///
+ /// two check bytes to go
+ ///
+ CHECK2 = 10,
+ ///
+ /// one check byte to go
+ ///
+ CHECK1 = 11,
+ ///
+ /// finished check, done
+ ///
+ DONE = 12,
+ ///
+ /// got an error--stay here
+ ///
+ BAD = 13
+ }
+
+ internal sealed class Inflate : ZStream, ICompressor
+ {
+ // preset dictionary flag in zlib header
+ private const int PRESET_DICT = 0x20;
+
+ private const int Z_DEFLATED = 8;
+
+ private static readonly byte[] mark = { (byte)0, (byte)0, (byte)0xff, (byte)0xff };
+
+ ///
+ /// The current inflate mode
+ ///
+ private InflateMode _mode;
+
+ ///
+ /// if FLAGS, method byte
+ ///
+ private int method;
+
+ ///
+ /// Computed check value
+ ///
+ private long[] _was = new long[1];
+
+ ///
+ /// The stream check value
+ ///
+ private long _need;
+
+ ///
+ /// if BAD, inflateSync's marker bytes count
+ ///
+ private int _marker;
+
+ // mode independent information
+ ///
+ /// Flag for no wrapper
+ ///
+ private int _nowrap;
+
+ ///
+ /// log2(window size) (8..15, defaults to 15)
+ ///
+ private int _wbits;
+
+ ///
+ /// Current inflate_blocks state
+ ///
+ private InflateBlocks _blocks;
+
+ public Inflate()
+ {
+ this.inflateInit();
+ }
+
+ public Inflate(bool nowrap)
+ {
+ this.inflateInit(nowrap);
+ }
+
+ private ZLibStatus InflateReset()
+ {
+ base.total_in = base.total_out = 0;
+ base.msg = null;
+ this._mode = this._nowrap != 0 ? InflateMode.BLOCKS : InflateMode.METHOD;
+ this._blocks.reset(this, null);
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus InflateEnd()
+ {
+ if (_blocks != null)
+ _blocks.free(this);
+ _blocks = null;
+ // ZFREE(z, z->state);
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus InflateInit(int w)
+ {
+ base.msg = null;
+ _blocks = null;
+
+ // handle undocumented nowrap option (no zlib header or check)
+ _nowrap = 0;
+ if (w < 0)
+ {
+ w = -w;
+ _nowrap = 1;
+ }
+
+ // set window size
+ if (w < 8 || w > 15)
+ {
+ InflateEnd();
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+ _wbits = w;
+
+ this._blocks = new InflateBlocks(this, this._nowrap != 0 ? null : this, 1 << w);
+
+ // reset state
+ InflateReset();
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus inflate(FlushType ff)
+ {
+ ZLibStatus r;
+ int b;
+
+ if (base.next_in == null)
+ return ZLibStatus.Z_STREAM_ERROR;
+ var f = ff == FlushType.Z_FINISH ? ZLibStatus.Z_BUF_ERROR : ZLibStatus.Z_OK;
+ r = ZLibStatus.Z_BUF_ERROR;
+ while (true)
+ {
+ //System.out.println("mode: "+this.mode);
+ switch (this._mode)
+ {
+ case InflateMode.METHOD:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ if (((this.method = base.next_in[base.next_in_index++]) & 0xf) != Z_DEFLATED)
+ {
+ this._mode = InflateMode.BAD;
+ base.msg = "unknown compression method";
+ this._marker = 5; // can't try inflateSync
+ break;
+ }
+ if ((this.method >> 4) + 8 > this._wbits)
+ {
+ this._mode = InflateMode.BAD;
+ base.msg = "invalid window size";
+ this._marker = 5; // can't try inflateSync
+ break;
+ }
+ this._mode = InflateMode.FLAG;
+ goto case InflateMode.FLAG;
+ case InflateMode.FLAG:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ b = (base.next_in[base.next_in_index++]) & 0xff;
+
+ if ((((this.method << 8) + b) % 31) != 0)
+ {
+ this._mode = InflateMode.BAD;
+ base.msg = "incorrect header check";
+ this._marker = 5; // can't try inflateSync
+ break;
+ }
+
+ if ((b & PRESET_DICT) == 0)
+ {
+ this._mode = InflateMode.BLOCKS;
+ break;
+ }
+ this._mode = InflateMode.DICT4;
+ goto case InflateMode.DICT4;
+ case InflateMode.DICT4:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need = ((base.next_in[base.next_in_index++] & 0xff) << 24) & 0xff000000L;
+ this._mode = InflateMode.DICT3;
+ goto case InflateMode.DICT3;
+ case InflateMode.DICT3:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += ((base.next_in[base.next_in_index++] & 0xff) << 16) & 0xff0000L;
+ this._mode = InflateMode.DICT2;
+ goto case InflateMode.DICT2;
+ case InflateMode.DICT2:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += ((base.next_in[base.next_in_index++] & 0xff) << 8) & 0xff00L;
+ this._mode = InflateMode.DICT1;
+ goto case InflateMode.DICT1;
+ case InflateMode.DICT1:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += (base.next_in[base.next_in_index++] & 0xffL);
+ base.adler = this._need;
+ this._mode = InflateMode.DICT0;
+ return ZLibStatus.Z_NEED_DICT;
+ case InflateMode.DICT0:
+ this._mode = InflateMode.BAD;
+ base.msg = "need dictionary";
+ this._marker = 0; // can try inflateSync
+ return ZLibStatus.Z_STREAM_ERROR;
+ case InflateMode.BLOCKS:
+
+ r = this._blocks.proc(this, r);
+ if (r == ZLibStatus.Z_DATA_ERROR)
+ {
+ this._mode = InflateMode.BAD;
+ this._marker = 0; // can try inflateSync
+ break;
+ }
+ if (r == ZLibStatus.Z_OK)
+ {
+ r = f;
+ }
+ if (r != ZLibStatus.Z_STREAM_END)
+ {
+ return r;
+ }
+ r = f;
+ this._blocks.reset(this, this._was);
+ if (this._nowrap != 0)
+ {
+ this._mode = InflateMode.DONE;
+ break;
+ }
+ this._mode = InflateMode.CHECK4;
+ goto case InflateMode.CHECK4;
+ case InflateMode.CHECK4:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need = ((base.next_in[base.next_in_index++] & 0xff) << 24) & 0xff000000L;
+ this._mode = InflateMode.CHECK3;
+ goto case InflateMode.CHECK3;
+ case InflateMode.CHECK3:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += ((base.next_in[base.next_in_index++] & 0xff) << 16) & 0xff0000L;
+ this._mode = InflateMode.CHECK2;
+ goto case InflateMode.CHECK2;
+ case InflateMode.CHECK2:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += ((base.next_in[base.next_in_index++] & 0xff) << 8) & 0xff00L;
+ this._mode = InflateMode.CHECK1;
+ goto case InflateMode.CHECK1;
+ case InflateMode.CHECK1:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += (base.next_in[base.next_in_index++] & 0xffL);
+
+ if (((int)(this._was[0])) != ((int)(this._need)))
+ {
+ this._mode = InflateMode.BAD;
+ base.msg = "incorrect data check";
+ this._marker = 5; // can't try inflateSync
+ break;
+ }
+
+ this._mode = InflateMode.DONE;
+ goto case InflateMode.DONE;
+ case InflateMode.DONE:
+ return ZLibStatus.Z_STREAM_END;
+ case InflateMode.BAD:
+ return ZLibStatus.Z_DATA_ERROR;
+ default:
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+ }
+ }
+
+ public ZLibStatus InflateSetDictionary(byte[] dictionary, int dictLength)
+ {
+ int index = 0;
+ int length = dictLength;
+ if (this._mode != InflateMode.DICT0)
+ return ZLibStatus.Z_STREAM_ERROR;
+
+ if (Adler32.adler32(1L, dictionary, 0, dictLength) != base.adler)
+ {
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+
+ base.adler = Adler32.adler32(0, null, 0, 0);
+
+ if (length >= (1 << this._wbits))
+ {
+ length = (1 << this._wbits) - 1;
+ index = dictLength - length;
+ }
+ this._blocks.set_dictionary(dictionary, index, length);
+ this._mode = InflateMode.BLOCKS;
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus InflateSync()
+ {
+ int n; // number of bytes to look at
+ int p; // pointer to bytes
+ int m; // number of marker bytes found in a row
+ long r, w; // temporaries to save total_in and total_out
+
+ // set up
+ if (this._mode != InflateMode.BAD)
+ {
+ this._mode = InflateMode.BAD;
+ this._marker = 0;
+ }
+ if ((n = base.avail_in) == 0)
+ return ZLibStatus.Z_BUF_ERROR;
+ p = base.next_in_index;
+ m = this._marker;
+
+ // search
+ while (n != 0 && m < 4)
+ {
+ if (base.next_in[p] == mark[m])
+ {
+ m++;
+ }
+ else if (base.next_in[p] != 0)
+ {
+ m = 0;
+ }
+ else
+ {
+ m = 4 - m;
+ }
+ p++; n--;
+ }
+
+ // restore
+ base.total_in += p - base.next_in_index;
+ base.next_in_index = p;
+ base.avail_in = n;
+ this._marker = m;
+
+ // return no joy or set up to restart on a new block
+ if (m != 4)
+ {
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ r = base.total_in; w = base.total_out;
+ InflateReset();
+ base.total_in = r; base.total_out = w;
+ this._mode = InflateMode.BLOCKS;
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus inflateInit()
+ {
+ return inflateInit(DEF_WBITS);
+ }
+ public ZLibStatus inflateInit(bool nowrap)
+ {
+ return inflateInit(DEF_WBITS, nowrap);
+ }
+ public ZLibStatus inflateInit(int w)
+ {
+ return inflateInit(w, false);
+ }
+
+ public ZLibStatus inflateInit(int w, bool nowrap)
+ {
+ return this.InflateInit(nowrap ? -w : w);
+ }
+
+ public ZLibStatus inflateEnd()
+ {
+ var ret = this.InflateEnd();
+ return ret;
+ }
+ public ZLibStatus inflateSync()
+ {
+ return this.InflateSync();
+ }
+
+ public ZLibStatus inflateSetDictionary(byte[] dictionary, int dictLength)
+ {
+ return this.InflateSetDictionary(dictionary, dictLength);
+ }
+
+ public ZLibStatus inflate(byte[] inputBufer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType)
+ {
+ this.next_in = inputBufer;
+ this.next_in_index = inputOffset;
+ this.avail_in = inputCount;
+ this.next_out = outputBuffer;
+ this.next_out_index = outputOffset;
+ this.avail_out = outputCount;
+ return this.inflate(flushType);
+ }
+
+ public ZLibStatus inflate(byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType)
+ {
+ this.next_out = outputBuffer;
+ this.next_out_index = outputOffset;
+ this.avail_out = outputCount;
+ return this.inflate(flushType);
+ }
+
+ // TODO: Dlete this
+ public ZLibStatus deflate(byte[] bufer, int offset, int count, byte[] p1, int p2, int p3, FlushType flushType)
+ {
+ throw new NotImplementedException();
+ }
+
+ public ZLibStatus deflateEnd()
+ {
+ throw new NotImplementedException();
+ }
+
+ public ZLibStatus deflate(byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v10/InflateBlocks.cs b/Renci.SshNet/Compression/v10/InflateBlocks.cs
new file mode 100644
index 0000000..273389f
--- /dev/null
+++ b/Renci.SshNet/Compression/v10/InflateBlocks.cs
@@ -0,0 +1,721 @@
+using System;
+/*
+ * $Id: InfBlocks.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public enum InflateBlockMode
+ {
+ ///
+ /// get type bits (3, including end bit)
+ ///
+ TYPE = 0,
+ ///
+ /// get lengths for stored
+ ///
+ LENS = 1,
+ ///
+ /// cessing stored block
+ ///
+ STORED = 2,
+ ///
+ /// get table lengths
+ ///
+ TABLE = 3,
+ ///
+ /// get bit lengths tree for a dynamic block
+ ///
+ BTREE = 4,
+ ///
+ /// get length, distance trees for a dynamic block
+ ///
+ DTREE = 5,
+ ///
+ /// processing fixed or dynamic block
+ ///
+ CODES = 6,
+ ///
+ /// output remaining window bytes
+ ///
+ DRY = 7,
+ ///
+ /// finished last block, done
+ ///
+ DONE = 8,
+ ///
+ /// ot a data error--stuck here
+ ///
+ BAD = 9
+ }
+
+ internal sealed class InflateBlocks : InflateCodes
+ {
+ private const int MANY = 1440;
+
+ // And'ing with mask[n] masks the lower n bits
+ private static readonly int[] inflate_mask = {
+ 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
+ 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
+ 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
+ 0x00007fff, 0x0000ffff
+ };
+
+ // Table for deflate from PKZIP's appnote.txt.
+ static readonly int[] border = { // Order of the bit length code lengths
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
+ };
+
+ internal InflateBlockMode mode; // current inflate_block mode
+
+ internal int left; // if STORED, bytes left to copy
+
+ internal int table; // table lengths (14 bits)
+ internal int index; // index into blens (or border)
+ internal int[] blens; // bit lengths of codes
+ internal int[] bb = new int[1]; // bit length tree depth
+ internal int[] tb = new int[1]; // bit length decoding tree
+
+ //internal InfCodes codes = new InfCodes(); // if CODES, current state
+
+ int last; // true if this block is the last block
+
+ // mode independent information
+ internal int bitk; // bits in bit buffer
+ internal int bitb; // bit buffer
+ internal int[] hufts; // single malloc for tree space
+ internal byte[] window; // sliding window
+ internal int end; // one byte after sliding window
+ internal int read; // window read pointer
+ internal int write; // window write pointer
+ internal Object checkfn; // check function
+ internal long check; // check on output
+
+ internal InflateTree inftree = new InflateTree();
+
+ internal InflateBlocks(ZStream z, Object checkfn, int w)
+ {
+ hufts = new int[MANY * 3];
+ window = new byte[w];
+ end = w;
+ this.checkfn = checkfn;
+ mode = InflateBlockMode.TYPE;
+ reset(z, null);
+ }
+
+ internal void reset(ZStream z, long[] c)
+ {
+ if (c != null) c[0] = check;
+ if (mode == InflateBlockMode.BTREE || mode == InflateBlockMode.DTREE)
+ {
+ }
+ if (mode == InflateBlockMode.CODES)
+ {
+ codesfree(z);
+ }
+ mode = InflateBlockMode.TYPE;
+ bitk = 0;
+ bitb = 0;
+ read = write = 0;
+
+ if (checkfn != null)
+ z.adler = check = Adler32.adler32(0L, null, 0, 0);
+ }
+
+ internal ZLibStatus proc(ZStream z, ZLibStatus r)
+ {
+ int t; // temporary storage
+ ZLibStatus tt;
+ int b; // bit buffer
+ int k; // bits in bit buffer
+ int p; // input data pointer
+ int n; // bytes available there
+ int q; // output window write pointer
+ int m;
+ { // bytes to end of window or read pointer
+
+ // copy input/output information to locals (UPDATE macro restores)
+ p = z.next_in_index; n = z.avail_in; b = bitb; k = bitk;
+ }
+ {
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+ }
+
+ // process input based on current state
+ while (true)
+ {
+ switch (mode)
+ {
+ case InflateBlockMode.TYPE:
+
+ while (k < (3))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+ t = (int)(b & 7);
+ last = t & 1;
+
+ switch (t >> 1)
+ {
+ case 0:
+ { // stored
+ b >>= (3); k -= (3);
+ }
+ t = k & 7;
+ { // go to byte boundary
+
+ b >>= (t); k -= (t);
+ }
+ mode = InflateBlockMode.LENS; // get length of stored block
+ break;
+ case 1:
+ { // fixed
+ int[] bl = new int[1];
+ int[] bd = new int[1];
+ int[][] tl = new int[1][];
+ int[][] td = new int[1][];
+
+ InflateTree.InflateTreesFixed(bl, bd, tl, td, z);
+ codesinit(bl[0], bd[0], tl[0], 0, td[0], 0, z);
+ }
+ {
+
+ b >>= (3); k -= (3);
+ }
+
+ mode = InflateBlockMode.CODES;
+ break;
+ case 2:
+ { // dynamic
+
+ b >>= (3); k -= (3);
+ }
+
+ mode = InflateBlockMode.TABLE;
+ break;
+ case 3:
+ { // illegal
+
+ b >>= (3); k -= (3);
+ }
+ mode = InflateBlockMode.BAD;
+ z.msg = "invalid block type";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ break;
+ case InflateBlockMode.LENS:
+
+ while (k < (32))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ if ((((~b) >> 16) & 0xffff) != (b & 0xffff))
+ {
+ mode = InflateBlockMode.BAD;
+ z.msg = "invalid stored block lengths";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ left = (b & 0xffff);
+ b = k = 0; // dump bits
+ mode = left != 0 ? InflateBlockMode.STORED : (last != 0 ? InflateBlockMode.DRY : InflateBlockMode.TYPE);
+ break;
+ case InflateBlockMode.STORED:
+ if (n == 0)
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+
+ if (m == 0)
+ {
+ if (q == end && read != 0)
+ {
+ q = 0; m = (int)(q < read ? read - q - 1 : end - q);
+ }
+ if (m == 0)
+ {
+ write = q;
+ r = inflate_flush(z, r);
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+ if (q == end && read != 0)
+ {
+ q = 0; m = (int)(q < read ? read - q - 1 : end - q);
+ }
+ if (m == 0)
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ }
+ }
+ r = ZLibStatus.Z_OK;
+
+ t = left;
+ if (t > n) t = n;
+ if (t > m) t = m;
+ System.Array.Copy(z.next_in, p, window, q, t);
+ p += t; n -= t;
+ q += t; m -= t;
+ if ((left -= t) != 0)
+ break;
+ mode = last != 0 ? InflateBlockMode.DRY : InflateBlockMode.TYPE;
+ break;
+ case InflateBlockMode.TABLE:
+
+ while (k < (14))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ table = t = (b & 0x3fff);
+ if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
+ {
+ mode = InflateBlockMode.BAD;
+ z.msg = "too many length or distance symbols";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
+ if (blens == null || blens.Length < t)
+ {
+ blens = new int[t];
+ }
+ else
+ {
+ for (int i = 0; i < t; i++) { blens[i] = 0; }
+ }
+ {
+
+ b >>= (14); k -= (14);
+ }
+
+ index = 0;
+ mode = InflateBlockMode.BTREE;
+ goto case InflateBlockMode.BTREE;
+ case InflateBlockMode.BTREE:
+ while (index < 4 + (table >> 10))
+ {
+ while (k < (3))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ blens[border[index++]] = b & 7;
+ {
+
+ b >>= (3); k -= (3);
+ }
+ }
+
+ while (index < 19)
+ {
+ blens[border[index++]] = 0;
+ }
+
+ bb[0] = 7;
+ tt = inftree.InflateTreesBits(blens, bb, tb, hufts, z);
+ if (tt != ZLibStatus.Z_OK)
+ {
+ r = tt;
+ if (r == ZLibStatus.Z_DATA_ERROR)
+ {
+ blens = null;
+ mode = InflateBlockMode.BAD;
+ }
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+
+ index = 0;
+ mode = InflateBlockMode.DTREE;
+ goto case InflateBlockMode.DTREE;
+ case InflateBlockMode.DTREE:
+ while (true)
+ {
+ t = table;
+ if (!(index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)))
+ {
+ break;
+ }
+
+ int i, j, c;
+
+ t = bb[0];
+
+ while (k < (t))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ if (tb[0] == -1)
+ {
+ //System.err.println("null...");
+ }
+
+ t = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 1];
+ c = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 2];
+
+ if (c < 16)
+ {
+ b >>= (t); k -= (t);
+ blens[index++] = c;
+ }
+ else
+ { // c == 16..18
+ i = c == 18 ? 7 : c - 14;
+ j = c == 18 ? 11 : 3;
+
+ while (k < (t + i))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ b >>= (t); k -= (t);
+
+ j += (b & inflate_mask[i]);
+
+ b >>= (i); k -= (i);
+
+ i = index;
+ t = table;
+ if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
+ (c == 16 && i < 1))
+ {
+ blens = null;
+ mode = InflateBlockMode.BAD;
+ z.msg = "invalid bit length repeat";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+
+ c = c == 16 ? blens[i - 1] : 0;
+ do
+ {
+ blens[i++] = c;
+ }
+ while (--j != 0);
+ index = i;
+ }
+ }
+
+ tb[0] = -1;
+ {
+ int[] bl = new int[1];
+ int[] bd = new int[1];
+ int[] tl = new int[1];
+ int[] td = new int[1];
+ bl[0] = 9; // must be <= 9 for lookahead assumptions
+ bd[0] = 6; // must be <= 9 for lookahead assumptions
+
+ t = table;
+ tt = inftree.InflateTreesDynamic(257 + (t & 0x1f),
+ 1 + ((t >> 5) & 0x1f),
+ blens, bl, bd, tl, td, hufts, z);
+
+ if (tt != ZLibStatus.Z_OK)
+ {
+ if (tt == ZLibStatus.Z_DATA_ERROR)
+ {
+ blens = null;
+ mode = InflateBlockMode.BAD;
+ }
+ r = tt;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ codesinit(bl[0], bd[0], hufts, tl[0], hufts, td[0], z);
+ }
+ mode = InflateBlockMode.CODES;
+ goto case InflateBlockMode.CODES;
+ case InflateBlockMode.CODES:
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+
+ if ((r = codesproc(this, z, r)) != ZLibStatus.Z_STREAM_END)
+ {
+ return inflate_flush(z, r);
+ }
+ r = ZLibStatus.Z_OK;
+ codesfree(z);
+
+ p = z.next_in_index; n = z.avail_in; b = bitb; k = bitk;
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+
+ if (last == 0)
+ {
+ mode = InflateBlockMode.TYPE;
+ break;
+ }
+ mode = InflateBlockMode.DRY;
+ goto case InflateBlockMode.DRY;
+ case InflateBlockMode.DRY:
+ write = q;
+ r = inflate_flush(z, r);
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+ if (read != write)
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ mode = InflateBlockMode.DONE;
+ goto case InflateBlockMode.DONE;
+ case InflateBlockMode.DONE:
+ r = ZLibStatus.Z_STREAM_END;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ case InflateBlockMode.BAD:
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+
+ default:
+ r = ZLibStatus.Z_STREAM_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ }
+ }
+
+ internal void free(ZStream z)
+ {
+ reset(z, null);
+ window = null;
+ hufts = null;
+ //ZFREE(z, s);
+ }
+
+ internal void set_dictionary(byte[] d, int start, int n)
+ {
+ System.Array.Copy(d, start, window, 0, n);
+ read = write = n;
+ }
+
+ // Returns true if inflate is currently at the end of a block generated
+ // by Z_SYNC_FLUSH or FlushType.Z_FULL_FLUSH.
+ internal ZLibStatus sync_point()
+ {
+ return mode == InflateBlockMode.LENS ? ZLibStatus.Z_STREAM_END : ZLibStatus.Z_OK;
+ }
+
+ // copy as much as possible from the sliding window to the output area
+ internal ZLibStatus inflate_flush(ZStream z, ZLibStatus r)
+ {
+ int n;
+ int p;
+ int q;
+
+ // local copies of source and destination pointers
+ p = z.next_out_index;
+ q = read;
+
+ // compute number of bytes to copy as far as end of window
+ n = (int)((q <= write ? write : end) - q);
+ if (n > z.avail_out) n = z.avail_out;
+ if (n != 0 && r == ZLibStatus.Z_BUF_ERROR) r = ZLibStatus.Z_OK;
+
+ // update counters
+ z.avail_out -= n;
+ z.total_out += n;
+
+ // update check information
+ if (checkfn != null)
+ z.adler = check = Adler32.adler32(check, window, q, n);
+
+ // copy as far as end of window
+ System.Array.Copy(window, q, z.next_out, p, n);
+ p += n;
+ q += n;
+
+ // see if more to copy at beginning of window
+ if (q == end)
+ {
+ // wrap pointers
+ q = 0;
+ if (write == end)
+ write = 0;
+
+ // compute bytes to copy
+ n = write - q;
+ if (n > z.avail_out) n = z.avail_out;
+ if (n != 0 && r == ZLibStatus.Z_BUF_ERROR) r = ZLibStatus.Z_OK;
+
+ // update counters
+ z.avail_out -= n;
+ z.total_out += n;
+
+ // update check information
+ if (checkfn != null)
+ z.adler = check = Adler32.adler32(check, window, q, n);
+
+ // copy
+ System.Array.Copy(window, q, z.next_out, p, n);
+ p += n;
+ q += n;
+ }
+
+ // update pointers
+ z.next_out_index = p;
+ read = q;
+
+ // done
+ return r;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v10/InflateCodes.cs b/Renci.SshNet/Compression/v10/InflateCodes.cs
new file mode 100644
index 0000000..3214e56
--- /dev/null
+++ b/Renci.SshNet/Compression/v10/InflateCodes.cs
@@ -0,0 +1,690 @@
+using System;
+/*
+ * $Id: InfCodes.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public enum InflateCodeMode
+ {
+ ///
+ /// x: set up for InflateCodeMode.LEN
+ ///
+ START = 0,
+ ///
+ /// i: get length/literal/eob next
+ ///
+ LEN = 1,
+ ///
+ /// i: getting length extra (have base)
+ ///
+ LENEXT = 2,
+ ///
+ /// i: get distance next
+ ///
+ DIST = 3,
+ ///
+ /// : getting distance extra
+ ///
+ DISTEXT = 4,
+ ///
+ /// o: copying bytes in window, waiting for space
+ ///
+ COPY = 5,
+ ///
+ /// o: got literal, waiting for output space
+ ///
+ LIT = 6,
+ ///
+ /// o: got eob, possibly still output waiting
+ ///
+ WASH = 7,
+ ///
+ /// x: got eob and all data flushed
+ ///
+ END = 8,
+ ///
+ /// x: got error
+ ///
+ BADCODE = 9
+ }
+
+ internal abstract class InflateCodes// : ZStream
+ {
+ private static readonly int[] inflate_mask = {
+ 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
+ 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
+ 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
+ 0x00007fff, 0x0000ffff
+ };
+
+ InflateCodeMode mode; // current inflate_codes mode
+
+ // mode dependent information
+ int len;
+
+ int[] tree; // pointer into tree
+ int tree_index = 0;
+ int need; // bits needed
+
+ int lit;
+
+ // if EXT or COPY, where and how much
+ int get; // bits to get for extra
+ int dist; // distance back to copy from
+
+ byte lbits; // ltree bits decoded per branch
+ byte dbits; // dtree bits decoder per branch
+ int[] ltree; // literal/length/eob tree
+ int ltree_index; // literal/length/eob tree
+ int[] dtree; // distance tree
+ int dtree_index; // distance tree
+
+ internal InflateCodes()
+ {
+ }
+ internal void codesinit(int bl, int bd,
+ int[] tl, int tl_index,
+ int[] td, int td_index, ZStream z)
+ {
+ mode = InflateCodeMode.START;
+ lbits = (byte)bl;
+ dbits = (byte)bd;
+ ltree = tl;
+ ltree_index = tl_index;
+ dtree = td;
+ dtree_index = td_index;
+ tree = null;
+ }
+
+ internal ZLibStatus codesproc(InflateBlocks s, ZStream z, ZLibStatus r)
+ {
+ int j; // temporary storage
+ int tindex; // temporary pointer
+ int e; // extra bits or operation
+ int b = 0; // bit buffer
+ int k = 0; // bits in bit buffer
+ int p = 0; // input data pointer
+ int n; // bytes available there
+ int q; // output window write pointer
+ int m; // bytes to end of window or read pointer
+ int f; // pointer to copy strings from
+
+ // copy input/output information to locals (UPDATE macro restores)
+ p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk;
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ // process input and output based on current state
+ while (true)
+ {
+ switch (mode)
+ {
+ // waiting for "i:"=input, "o:"=output, "x:"=nothing
+ case InflateCodeMode.START: // x: set up for LEN
+ if (m >= 258 && n >= 10)
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ r = inflate_fast(lbits, dbits,
+ ltree, ltree_index,
+ dtree, dtree_index,
+ s, z);
+
+ p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk;
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (r != ZLibStatus.Z_OK)
+ {
+ mode = r == ZLibStatus.Z_STREAM_END ? InflateCodeMode.WASH : InflateCodeMode.BADCODE;
+ break;
+ }
+ }
+ need = lbits;
+ tree = ltree;
+ tree_index = ltree_index;
+
+ mode = InflateCodeMode.LEN;
+ goto case InflateCodeMode.LEN;
+ case InflateCodeMode.LEN: // i: get length/literal/eob next
+ j = need;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ tindex = (tree_index + (b & inflate_mask[j])) * 3;
+
+ b >>= (tree[tindex + 1]);
+ k -= (tree[tindex + 1]);
+
+ e = tree[tindex];
+
+ if (e == 0)
+ { // literal
+ lit = tree[tindex + 2];
+ mode = InflateCodeMode.LIT;
+ break;
+ }
+ if ((e & 16) != 0)
+ { // length
+ get = e & 15;
+ len = tree[tindex + 2];
+ mode = InflateCodeMode.LENEXT;
+ break;
+ }
+ if ((e & 64) == 0)
+ { // next table
+ need = e;
+ tree_index = tindex / 3 + tree[tindex + 2];
+ break;
+ }
+ if ((e & 32) != 0)
+ { // end of block
+ mode = InflateCodeMode.WASH;
+ break;
+ }
+ mode = InflateCodeMode.BADCODE; // invalid code
+ z.msg = "invalid literal/length code";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ case InflateCodeMode.LENEXT: // i: getting length extra (have base)
+ j = get;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--; b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ len += (b & inflate_mask[j]);
+
+ b >>= j;
+ k -= j;
+
+ need = dbits;
+ tree = dtree;
+ tree_index = dtree_index;
+ mode = InflateCodeMode.DIST;
+ goto case InflateCodeMode.DIST;
+ case InflateCodeMode.DIST: // i: get distance next
+ j = need;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--; b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ tindex = (tree_index + (b & inflate_mask[j])) * 3;
+
+ b >>= tree[tindex + 1];
+ k -= tree[tindex + 1];
+
+ e = (tree[tindex]);
+ if ((e & 16) != 0)
+ { // distance
+ get = e & 15;
+ dist = tree[tindex + 2];
+ mode = InflateCodeMode.DISTEXT;
+ break;
+ }
+ if ((e & 64) == 0)
+ { // next table
+ need = e;
+ tree_index = tindex / 3 + tree[tindex + 2];
+ break;
+ }
+ mode = InflateCodeMode.BADCODE; // invalid code
+ z.msg = "invalid distance code";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ case InflateCodeMode.DISTEXT: // i: getting distance extra
+ j = get;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--; b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ dist += (b & inflate_mask[j]);
+
+ b >>= j;
+ k -= j;
+
+ mode = InflateCodeMode.COPY;
+ goto case InflateCodeMode.COPY;
+ case InflateCodeMode.COPY: // o: copying bytes in window, waiting for space
+ f = q - dist;
+ while (f < 0)
+ { // modulo window size-"while" instead
+ f += s.end; // of "if" handles invalid distances
+ }
+ while (len != 0)
+ {
+
+ if (m == 0)
+ {
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+ if (m == 0)
+ {
+ s.write = q; r = s.inflate_flush(z, r);
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+
+ if (m == 0)
+ {
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ }
+ }
+
+ s.window[q++] = s.window[f++]; m--;
+
+ if (f == s.end)
+ f = 0;
+ len--;
+ }
+ mode = InflateCodeMode.START;
+ break;
+ case InflateCodeMode.LIT: // o: got literal, waiting for output space
+ if (m == 0)
+ {
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+ if (m == 0)
+ {
+ s.write = q; r = s.inflate_flush(z, r);
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+ if (m == 0)
+ {
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ }
+ }
+ r = ZLibStatus.Z_OK;
+
+ s.window[q++] = (byte)lit; m--;
+
+ mode = InflateCodeMode.START;
+ break;
+ case InflateCodeMode.WASH: // o: got eob, possibly more output
+ if (k > 7)
+ { // return unused byte, if any
+ k -= 8;
+ n++;
+ p--; // can always return one
+ }
+
+ s.write = q; r = s.inflate_flush(z, r);
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (s.read != s.write)
+ {
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ mode = InflateCodeMode.END;
+ goto case InflateCodeMode.END;
+ case InflateCodeMode.END:
+ r = ZLibStatus.Z_STREAM_END;
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ case InflateCodeMode.BADCODE: // x: got error
+
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ default:
+ r = ZLibStatus.Z_STREAM_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ }
+ }
+
+ internal void codesfree(ZStream z)
+ {
+ // ZFREE(z, c);
+ }
+
+ // Called with number of bytes left to write in window at least 258
+ // (the maximum string length) and number of input bytes available
+ // at least ten. The ten bytes are six bytes for the longest length/
+ // distance pair plus four bytes for overloading the bit buffer.
+
+ internal ZLibStatus inflate_fast(int bl, int bd,
+ int[] tl, int tl_index,
+ int[] td, int td_index,
+ InflateBlocks s, ZStream z)
+ {
+ int t; // temporary pointer
+ int[] tp; // temporary pointer
+ int tp_index; // temporary pointer
+ int e; // extra bits or operation
+ int b; // bit buffer
+ int k; // bits in bit buffer
+ int p; // input data pointer
+ int n; // bytes available there
+ int q; // output window write pointer
+ int m; // bytes to end of window or read pointer
+ int ml; // mask for literal/length tree
+ int md; // mask for distance tree
+ int c; // bytes to copy
+ int d; // distance back to copy from
+ int r; // copy source pointer
+
+ int tp_index_t_3; // (tp_index+t)*3
+
+ // load input, output, bit values
+ p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk;
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ // initialize masks
+ ml = inflate_mask[bl];
+ md = inflate_mask[bd];
+
+ // do until not enough input or output space for fast loop
+ do
+ { // assume called with m >= 258 && n >= 10
+ // get literal/length code
+ while (k < (20))
+ { // max bits for literal/length code
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k; k += 8;
+ }
+
+ t = b & ml;
+ tp = tl;
+ tp_index = tl_index;
+ tp_index_t_3 = (tp_index + t) * 3;
+ if ((e = tp[tp_index_t_3]) == 0)
+ {
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ s.window[q++] = (byte)tp[tp_index_t_3 + 2];
+ m--;
+ continue;
+ }
+ do
+ {
+
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ if ((e & 16) != 0)
+ {
+ e &= 15;
+ c = tp[tp_index_t_3 + 2] + ((int)b & inflate_mask[e]);
+
+ b >>= e; k -= e;
+
+ // decode distance base of block to copy
+ while (k < (15))
+ { // max bits for distance code
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k; k += 8;
+ }
+
+ t = b & md;
+ tp = td;
+ tp_index = td_index;
+ tp_index_t_3 = (tp_index + t) * 3;
+ e = tp[tp_index_t_3];
+
+ do
+ {
+
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ if ((e & 16) != 0)
+ {
+ // get extra bits to add to distance base
+ e &= 15;
+ while (k < (e))
+ { // get extra bits (up to 13)
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k; k += 8;
+ }
+
+ d = tp[tp_index_t_3 + 2] + (b & inflate_mask[e]);
+
+ b >>= (e); k -= (e);
+
+ // do the copy
+ m -= c;
+ if (q >= d)
+ { // offset before dest
+ // just copy
+ r = q - d;
+ if (q - r > 0 && 2 > (q - r))
+ {
+ s.window[q++] = s.window[r++]; // minimum count is three,
+ s.window[q++] = s.window[r++]; // so unroll loop a little
+ c -= 2;
+ }
+ else
+ {
+ System.Array.Copy(s.window, r, s.window, q, 2);
+ q += 2; r += 2; c -= 2;
+ }
+ }
+ else
+ { // else offset after destination
+ r = q - d;
+ do
+ {
+ r += s.end; // force pointer in window
+ } while (r < 0); // covers invalid distances
+ e = s.end - r;
+ if (c > e)
+ { // if source crosses,
+ c -= e; // wrapped copy
+ if (q - r > 0 && e > (q - r))
+ {
+ do { s.window[q++] = s.window[r++]; }
+ while (--e != 0);
+ }
+ else
+ {
+ System.Array.Copy(s.window, r, s.window, q, e);
+ q += e; r += e; e = 0;
+ }
+ r = 0; // copy rest from start of window
+ }
+
+ }
+
+ // copy all or what's left
+ if (q - r > 0 && c > (q - r))
+ {
+ do { s.window[q++] = s.window[r++]; }
+ while (--c != 0);
+ }
+ else
+ {
+ System.Array.Copy(s.window, r, s.window, q, c);
+ q += c; r += c; c = 0;
+ }
+ break;
+ }
+ else if ((e & 64) == 0)
+ {
+ t += tp[tp_index_t_3 + 2];
+ t += (b & inflate_mask[e]);
+ tp_index_t_3 = (tp_index + t) * 3;
+ e = tp[tp_index_t_3];
+ }
+ else
+ {
+ z.msg = "invalid distance code";
+
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ }
+ while (true);
+ break;
+ }
+
+ if ((e & 64) == 0)
+ {
+ t += tp[tp_index_t_3 + 2];
+ t += (b & inflate_mask[e]);
+ tp_index_t_3 = (tp_index + t) * 3;
+ if ((e = tp[tp_index_t_3]) == 0)
+ {
+
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ s.window[q++] = (byte)tp[tp_index_t_3 + 2];
+ m--;
+ break;
+ }
+ }
+ else if ((e & 32) != 0)
+ {
+
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_STREAM_END;
+ }
+ else
+ {
+ z.msg = "invalid literal/length code";
+
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ }
+ while (true);
+ }
+ while (m >= 258 && n >= 10);
+
+ // not enough input or output--restore pointers and return
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_OK;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v10/InflateTree.cs b/Renci.SshNet/Compression/v10/InflateTree.cs
new file mode 100644
index 0000000..f9da579
--- /dev/null
+++ b/Renci.SshNet/Compression/v10/InflateTree.cs
@@ -0,0 +1,555 @@
+using System;
+/*
+ * $Id: InfTree.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ internal sealed class InflateTree
+ {
+ private const int MANY = 1440;
+
+ private const int fixed_bl = 9;
+ private const int fixed_bd = 5;
+
+ static readonly int[] fixed_tl = {
+ 96,7,256, 0,8,80, 0,8,16, 84,8,115,
+ 82,7,31, 0,8,112, 0,8,48, 0,9,192,
+ 80,7,10, 0,8,96, 0,8,32, 0,9,160,
+ 0,8,0, 0,8,128, 0,8,64, 0,9,224,
+ 80,7,6, 0,8,88, 0,8,24, 0,9,144,
+ 83,7,59, 0,8,120, 0,8,56, 0,9,208,
+ 81,7,17, 0,8,104, 0,8,40, 0,9,176,
+ 0,8,8, 0,8,136, 0,8,72, 0,9,240,
+ 80,7,4, 0,8,84, 0,8,20, 85,8,227,
+ 83,7,43, 0,8,116, 0,8,52, 0,9,200,
+ 81,7,13, 0,8,100, 0,8,36, 0,9,168,
+ 0,8,4, 0,8,132, 0,8,68, 0,9,232,
+ 80,7,8, 0,8,92, 0,8,28, 0,9,152,
+ 84,7,83, 0,8,124, 0,8,60, 0,9,216,
+ 82,7,23, 0,8,108, 0,8,44, 0,9,184,
+ 0,8,12, 0,8,140, 0,8,76, 0,9,248,
+ 80,7,3, 0,8,82, 0,8,18, 85,8,163,
+ 83,7,35, 0,8,114, 0,8,50, 0,9,196,
+ 81,7,11, 0,8,98, 0,8,34, 0,9,164,
+ 0,8,2, 0,8,130, 0,8,66, 0,9,228,
+ 80,7,7, 0,8,90, 0,8,26, 0,9,148,
+ 84,7,67, 0,8,122, 0,8,58, 0,9,212,
+ 82,7,19, 0,8,106, 0,8,42, 0,9,180,
+ 0,8,10, 0,8,138, 0,8,74, 0,9,244,
+ 80,7,5, 0,8,86, 0,8,22, 192,8,0,
+ 83,7,51, 0,8,118, 0,8,54, 0,9,204,
+ 81,7,15, 0,8,102, 0,8,38, 0,9,172,
+ 0,8,6, 0,8,134, 0,8,70, 0,9,236,
+ 80,7,9, 0,8,94, 0,8,30, 0,9,156,
+ 84,7,99, 0,8,126, 0,8,62, 0,9,220,
+ 82,7,27, 0,8,110, 0,8,46, 0,9,188,
+ 0,8,14, 0,8,142, 0,8,78, 0,9,252,
+ 96,7,256, 0,8,81, 0,8,17, 85,8,131,
+ 82,7,31, 0,8,113, 0,8,49, 0,9,194,
+ 80,7,10, 0,8,97, 0,8,33, 0,9,162,
+ 0,8,1, 0,8,129, 0,8,65, 0,9,226,
+ 80,7,6, 0,8,89, 0,8,25, 0,9,146,
+ 83,7,59, 0,8,121, 0,8,57, 0,9,210,
+ 81,7,17, 0,8,105, 0,8,41, 0,9,178,
+ 0,8,9, 0,8,137, 0,8,73, 0,9,242,
+ 80,7,4, 0,8,85, 0,8,21, 80,8,258,
+ 83,7,43, 0,8,117, 0,8,53, 0,9,202,
+ 81,7,13, 0,8,101, 0,8,37, 0,9,170,
+ 0,8,5, 0,8,133, 0,8,69, 0,9,234,
+ 80,7,8, 0,8,93, 0,8,29, 0,9,154,
+ 84,7,83, 0,8,125, 0,8,61, 0,9,218,
+ 82,7,23, 0,8,109, 0,8,45, 0,9,186,
+ 0,8,13, 0,8,141, 0,8,77, 0,9,250,
+ 80,7,3, 0,8,83, 0,8,19, 85,8,195,
+ 83,7,35, 0,8,115, 0,8,51, 0,9,198,
+ 81,7,11, 0,8,99, 0,8,35, 0,9,166,
+ 0,8,3, 0,8,131, 0,8,67, 0,9,230,
+ 80,7,7, 0,8,91, 0,8,27, 0,9,150,
+ 84,7,67, 0,8,123, 0,8,59, 0,9,214,
+ 82,7,19, 0,8,107, 0,8,43, 0,9,182,
+ 0,8,11, 0,8,139, 0,8,75, 0,9,246,
+ 80,7,5, 0,8,87, 0,8,23, 192,8,0,
+ 83,7,51, 0,8,119, 0,8,55, 0,9,206,
+ 81,7,15, 0,8,103, 0,8,39, 0,9,174,
+ 0,8,7, 0,8,135, 0,8,71, 0,9,238,
+ 80,7,9, 0,8,95, 0,8,31, 0,9,158,
+ 84,7,99, 0,8,127, 0,8,63, 0,9,222,
+ 82,7,27, 0,8,111, 0,8,47, 0,9,190,
+ 0,8,15, 0,8,143, 0,8,79, 0,9,254,
+ 96,7,256, 0,8,80, 0,8,16, 84,8,115,
+ 82,7,31, 0,8,112, 0,8,48, 0,9,193,
+
+ 80,7,10, 0,8,96, 0,8,32, 0,9,161,
+ 0,8,0, 0,8,128, 0,8,64, 0,9,225,
+ 80,7,6, 0,8,88, 0,8,24, 0,9,145,
+ 83,7,59, 0,8,120, 0,8,56, 0,9,209,
+ 81,7,17, 0,8,104, 0,8,40, 0,9,177,
+ 0,8,8, 0,8,136, 0,8,72, 0,9,241,
+ 80,7,4, 0,8,84, 0,8,20, 85,8,227,
+ 83,7,43, 0,8,116, 0,8,52, 0,9,201,
+ 81,7,13, 0,8,100, 0,8,36, 0,9,169,
+ 0,8,4, 0,8,132, 0,8,68, 0,9,233,
+ 80,7,8, 0,8,92, 0,8,28, 0,9,153,
+ 84,7,83, 0,8,124, 0,8,60, 0,9,217,
+ 82,7,23, 0,8,108, 0,8,44, 0,9,185,
+ 0,8,12, 0,8,140, 0,8,76, 0,9,249,
+ 80,7,3, 0,8,82, 0,8,18, 85,8,163,
+ 83,7,35, 0,8,114, 0,8,50, 0,9,197,
+ 81,7,11, 0,8,98, 0,8,34, 0,9,165,
+ 0,8,2, 0,8,130, 0,8,66, 0,9,229,
+ 80,7,7, 0,8,90, 0,8,26, 0,9,149,
+ 84,7,67, 0,8,122, 0,8,58, 0,9,213,
+ 82,7,19, 0,8,106, 0,8,42, 0,9,181,
+ 0,8,10, 0,8,138, 0,8,74, 0,9,245,
+ 80,7,5, 0,8,86, 0,8,22, 192,8,0,
+ 83,7,51, 0,8,118, 0,8,54, 0,9,205,
+ 81,7,15, 0,8,102, 0,8,38, 0,9,173,
+ 0,8,6, 0,8,134, 0,8,70, 0,9,237,
+ 80,7,9, 0,8,94, 0,8,30, 0,9,157,
+ 84,7,99, 0,8,126, 0,8,62, 0,9,221,
+ 82,7,27, 0,8,110, 0,8,46, 0,9,189,
+ 0,8,14, 0,8,142, 0,8,78, 0,9,253,
+ 96,7,256, 0,8,81, 0,8,17, 85,8,131,
+ 82,7,31, 0,8,113, 0,8,49, 0,9,195,
+ 80,7,10, 0,8,97, 0,8,33, 0,9,163,
+ 0,8,1, 0,8,129, 0,8,65, 0,9,227,
+ 80,7,6, 0,8,89, 0,8,25, 0,9,147,
+ 83,7,59, 0,8,121, 0,8,57, 0,9,211,
+ 81,7,17, 0,8,105, 0,8,41, 0,9,179,
+ 0,8,9, 0,8,137, 0,8,73, 0,9,243,
+ 80,7,4, 0,8,85, 0,8,21, 80,8,258,
+ 83,7,43, 0,8,117, 0,8,53, 0,9,203,
+ 81,7,13, 0,8,101, 0,8,37, 0,9,171,
+ 0,8,5, 0,8,133, 0,8,69, 0,9,235,
+ 80,7,8, 0,8,93, 0,8,29, 0,9,155,
+ 84,7,83, 0,8,125, 0,8,61, 0,9,219,
+ 82,7,23, 0,8,109, 0,8,45, 0,9,187,
+ 0,8,13, 0,8,141, 0,8,77, 0,9,251,
+ 80,7,3, 0,8,83, 0,8,19, 85,8,195,
+ 83,7,35, 0,8,115, 0,8,51, 0,9,199,
+ 81,7,11, 0,8,99, 0,8,35, 0,9,167,
+ 0,8,3, 0,8,131, 0,8,67, 0,9,231,
+ 80,7,7, 0,8,91, 0,8,27, 0,9,151,
+ 84,7,67, 0,8,123, 0,8,59, 0,9,215,
+ 82,7,19, 0,8,107, 0,8,43, 0,9,183,
+ 0,8,11, 0,8,139, 0,8,75, 0,9,247,
+ 80,7,5, 0,8,87, 0,8,23, 192,8,0,
+ 83,7,51, 0,8,119, 0,8,55, 0,9,207,
+ 81,7,15, 0,8,103, 0,8,39, 0,9,175,
+ 0,8,7, 0,8,135, 0,8,71, 0,9,239,
+ 80,7,9, 0,8,95, 0,8,31, 0,9,159,
+ 84,7,99, 0,8,127, 0,8,63, 0,9,223,
+ 82,7,27, 0,8,111, 0,8,47, 0,9,191,
+ 0,8,15, 0,8,143, 0,8,79, 0,9,255
+ };
+ static readonly int[] fixed_td = {
+ 80,5,1, 87,5,257, 83,5,17, 91,5,4097,
+ 81,5,5, 89,5,1025, 85,5,65, 93,5,16385,
+ 80,5,3, 88,5,513, 84,5,33, 92,5,8193,
+ 82,5,9, 90,5,2049, 86,5,129, 192,5,24577,
+ 80,5,2, 87,5,385, 83,5,25, 91,5,6145,
+ 81,5,7, 89,5,1537, 85,5,97, 93,5,24577,
+ 80,5,4, 88,5,769, 84,5,49, 92,5,12289,
+ 82,5,13, 90,5,3073, 86,5,193, 192,5,24577
+ };
+
+ // Tables for deflate from PKZIP's appnote.txt.
+ static readonly int[] cplens = { // Copy lengths for literal codes 257..285
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
+ };
+
+ // see note #13 above about 258
+ static readonly int[] cplext = { // Extra bits for literal codes 257..285
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+ 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112 // 112==invalid
+ };
+
+ static readonly int[] cpdist = { // Copy offsets for distance codes 0..29
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+ 8193, 12289, 16385, 24577
+ };
+
+ static readonly int[] cpdext = { // Extra bits for distance codes
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+ 12, 12, 13, 13};
+
+ // If BMAX needs to be larger than 16, then h and x[] should be uLong.
+ const int BMAX = 15; // maximum bit length of any code
+
+ int[] hn = null; // hufts used in space
+ int[] v = null; // work area for huft_build
+ int[] c = null; // bit length count table
+ int[] r = null; // table entry for structure assignment
+ int[] u = null; // table stack
+ int[] x = null; // bit offsets, then code stack
+
+ private ZLibStatus HuftBuild(int[] b, // code lengths in bits (all assumed <= BMAX)
+ int bindex,
+ int n, // number of codes (assumed <= 288)
+ int s, // number of simple-valued codes (0..s-1)
+ int[] d, // list of base values for non-simple codes
+ int[] e, // list of extra bits for non-simple codes
+ int[] t, // result: starting table
+ int[] m, // maximum lookup bits, returns actual
+ int[] hp,// space for trees
+ int[] hn,// hufts used in space
+ int[] v // working area: values in order of bit length
+ )
+ {
+ // Given a list of code lengths and a maximum table size, make a set of
+ // tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR
+ // if the given code set is incomplete (the tables are still built in this
+ // case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of
+ // lengths), or Z_MEM_ERROR if not enough memory.
+
+ int a; // counter for codes of length k
+ int f; // i repeats in table every f entries
+ int g; // maximum code length
+ int h; // table level
+ int i; // counter, current code
+ int j; // counter
+ int k; // number of bits in current code
+ int l; // bits per table (returned in m)
+ int mask; // (1 << w) - 1, to avoid cc -O bug on HP
+ int p; // pointer into c[], b[], or v[]
+ int q; // points to current table
+ int w; // bits before this table == (l * h)
+ int xp; // pointer into x
+ int y; // number of dummy codes added
+ int z; // number of entries in current table
+
+ // Generate counts for each bit length
+
+ p = 0; i = n;
+ do
+ {
+ c[b[bindex + p]]++; p++; i--; // assume all entries <= BMAX
+ } while (i != 0);
+
+ if (c[0] == n)
+ { // null input--all zero length codes
+ t[0] = -1;
+ m[0] = 0;
+ return ZLibStatus.Z_OK;
+ }
+
+ // Find minimum and maximum length, bound *m by those
+ l = m[0];
+ for (j = 1; j <= BMAX; j++)
+ if (c[j] != 0) break;
+ k = j; // minimum code length
+ if (l < j)
+ {
+ l = j;
+ }
+ for (i = BMAX; i != 0; i--)
+ {
+ if (c[i] != 0) break;
+ }
+ g = i; // maximum code length
+ if (l > i)
+ {
+ l = i;
+ }
+ m[0] = l;
+
+ // Adjust last length count to fill out codes, if needed
+ for (y = 1 << j; j < i; j++, y <<= 1)
+ {
+ if ((y -= c[j]) < 0)
+ {
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ }
+ if ((y -= c[i]) < 0)
+ {
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ c[i] += y;
+
+ // Generate starting offsets into the value table for each length
+ x[1] = j = 0;
+ p = 1; xp = 2;
+ while (--i != 0)
+ { // note that i == g from above
+ x[xp] = (j += c[p]);
+ xp++;
+ p++;
+ }
+
+ // Make a table of values in order of bit lengths
+ i = 0; p = 0;
+ do
+ {
+ if ((j = b[bindex + p]) != 0)
+ {
+ v[x[j]++] = i;
+ }
+ p++;
+ }
+ while (++i < n);
+ n = x[g]; // set n to length of v
+
+ // Generate the Huffman codes and for each, make the table entries
+ x[0] = i = 0; // first Huffman code is zero
+ p = 0; // grab values in bit order
+ h = -1; // no tables yet--level -1
+ w = -l; // bits decoded == (l * h)
+ u[0] = 0; // just to keep compilers happy
+ q = 0; // ditto
+ z = 0; // ditto
+
+ // go through the bit lengths (k already is bits in shortest code)
+ for (; k <= g; k++)
+ {
+ a = c[k];
+ while (a-- != 0)
+ {
+ // here i is the Huffman code of length k bits for value *p
+ // make tables up to required level
+ while (k > w + l)
+ {
+ h++;
+ w += l; // previous table always l bits
+ // compute minimum size table less than or equal to l bits
+ z = g - w;
+ z = (z > l) ? l : z; // table size upper limit
+ if ((f = 1 << (j = k - w)) > a + 1)
+ { // try a k-w bit table
+ // too few codes for k-w bit table
+ f -= a + 1; // deduct codes from patterns left
+ xp = k;
+ if (j < z)
+ {
+ while (++j < z)
+ { // try smaller tables up to z bits
+ if ((f <<= 1) <= c[++xp])
+ break; // enough codes to use up j bits
+ f -= c[xp]; // else deduct codes from patterns
+ }
+ }
+ }
+ z = 1 << j; // table entries for j-bit table
+
+ // allocate new table
+ if (hn[0] + z > MANY)
+ { // (note: doesn't matter for fixed)
+ return ZLibStatus.Z_DATA_ERROR; // overflow of MANY
+ }
+ u[h] = q = /*hp+*/ hn[0]; // DEBUG
+ hn[0] += z;
+
+ // connect to last table, if there is one
+ if (h != 0)
+ {
+ x[h] = i; // save pattern for backing up
+ r[0] = (byte)j; // bits in this table
+ r[1] = (byte)l; // bits to dump before this table
+ j = i >> (w - l);
+ r[2] = (int)(q - u[h - 1] - j); // offset to this table
+ System.Array.Copy(r, 0, hp, (u[h - 1] + j) * 3, 3); // connect to last table
+ }
+ else
+ {
+ t[0] = q; // first table is returned result
+ }
+ }
+
+ // set up table entry in r
+ r[1] = (byte)(k - w);
+ if (p >= n)
+ {
+ r[0] = 128 + 64; // out of values--invalid code
+ }
+ else if (v[p] < s)
+ {
+ r[0] = (byte)(v[p] < 256 ? 0 : 32 + 64); // 256 is end-of-block
+ r[2] = v[p++]; // simple code is just the value
+ }
+ else
+ {
+ r[0] = (byte)(e[v[p] - s] + 16 + 64); // non-simple--look up in lists
+ r[2] = d[v[p++] - s];
+ }
+
+ // fill code-like entries with r
+ f = 1 << (k - w);
+ for (j = i >> w; j < z; j += f)
+ {
+ System.Array.Copy(r, 0, hp, (q + j) * 3, 3);
+ }
+
+ // backwards increment the k-bit code i
+ for (j = 1 << (k - 1); (i & j) != 0; j >>= 1)
+ {
+ i ^= j;
+ }
+ i ^= j;
+
+ // backup over finished tables
+ mask = (1 << w) - 1; // needed on HP, cc -O bug
+ while ((i & mask) != x[h])
+ {
+ h--; // don't need to update q
+ w -= l;
+ mask = (1 << w) - 1;
+ }
+ }
+ }
+ // Return Z_BUF_ERROR if we were given an incomplete table
+ return y != 0 && g != 1 ? ZLibStatus.Z_BUF_ERROR : ZLibStatus.Z_OK;
+ }
+
+ internal ZLibStatus InflateTreesBits(int[] c, // 19 code lengths
+ int[] bb, // bits tree desired/actual depth
+ int[] tb, // bits tree result
+ int[] hp, // space for trees
+ ZStream z // for messages
+ )
+ {
+ ZLibStatus result;
+ InitWorkArea(19);
+ hn[0] = 0;
+ result = HuftBuild(c, 0, 19, 19, null, null, tb, bb, hp, hn, v);
+
+ if (result == ZLibStatus.Z_DATA_ERROR)
+ {
+ z.msg = "oversubscribed dynamic bit lengths tree";
+ }
+ else if (result == ZLibStatus.Z_BUF_ERROR || bb[0] == 0)
+ {
+ z.msg = "incomplete dynamic bit lengths tree";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ return result;
+ }
+
+ internal ZLibStatus InflateTreesDynamic(int nl, // number of literal/length codes
+ int nd, // number of distance codes
+ int[] c, // that many (total) code lengths
+ int[] bl, // literal desired/actual bit depth
+ int[] bd, // distance desired/actual bit depth
+ int[] tl, // literal/length tree result
+ int[] td, // distance tree result
+ int[] hp, // space for trees
+ ZStream z // for messages
+ )
+ {
+ ZLibStatus result;
+
+ // build literal/length tree
+ InitWorkArea(288);
+ hn[0] = 0;
+ result = HuftBuild(c, 0, nl, 257, cplens, cplext, tl, bl, hp, hn, v);
+ if (result != ZLibStatus.Z_OK || bl[0] == 0)
+ {
+ if (result == ZLibStatus.Z_DATA_ERROR)
+ {
+ z.msg = "oversubscribed literal/length tree";
+ }
+ else if (result != ZLibStatus.Z_MEM_ERROR)
+ {
+ z.msg = "incomplete literal/length tree";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ return result;
+ }
+
+ // build distance tree
+ InitWorkArea(288);
+ result = HuftBuild(c, nl, nd, 0, cpdist, cpdext, td, bd, hp, hn, v);
+
+ if (result != ZLibStatus.Z_OK || (bd[0] == 0 && nl > 257))
+ {
+ if (result == ZLibStatus.Z_DATA_ERROR)
+ {
+ z.msg = "oversubscribed distance tree";
+ }
+ else if (result == ZLibStatus.Z_BUF_ERROR)
+ {
+ z.msg = "incomplete distance tree";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ else if (result != ZLibStatus.Z_MEM_ERROR)
+ {
+ z.msg = "empty distance tree with lengths";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ return result;
+ }
+
+ return ZLibStatus.Z_OK;
+ }
+
+ internal static ZLibStatus InflateTreesFixed(int[] bl, //literal desired/actual bit depth
+ int[] bd, //distance desired/actual bit depth
+ int[][] tl,//literal/length tree result
+ int[][] td,//distance tree result
+ ZStream z //for memory allocation
+ )
+ {
+ bl[0] = fixed_bl;
+ bd[0] = fixed_bd;
+ tl[0] = fixed_tl;
+ td[0] = fixed_td;
+ return ZLibStatus.Z_OK;
+ }
+
+ private void InitWorkArea(int vsize)
+ {
+ if (hn == null)
+ {
+ hn = new int[1];
+ v = new int[vsize];
+ c = new int[BMAX + 1];
+ r = new int[3];
+ u = new int[BMAX];
+ x = new int[BMAX + 1];
+ }
+ if (v.Length < vsize) { v = new int[vsize]; }
+ for (int i = 0; i < vsize; i++) { v[i] = 0; }
+ for (int i = 0; i < BMAX + 1; i++) { c[i] = 0; }
+ for (int i = 0; i < 3; i++) { r[i] = 0; }
+ // for(int i=0; i
+ /// Gets the static tree or null
+ ///
+ ///
+ /// The static_tree.
+ ///
+ public short[] TreeData { get; private set; }
+
+ ///
+ /// Gets the extra bits for each code or null.
+ ///
+ ///
+ /// The extra bits.
+ ///
+ public int[] ExtraBits { get; private set; }
+
+ ///
+ /// Gets the base index for extra_bits.
+ ///
+ ///
+ /// The extra base.
+ ///
+ public int ExtraBase { get; private set; }
+
+ ///
+ /// Gets the max number of elements in the tree.
+ ///
+ ///
+ /// The elements.
+ ///
+ public int Elements { get; private set; }
+
+ ///
+ /// Gets the max bit length for the codes.
+ ///
+ ///
+ /// The length of the max.
+ ///
+ public int MaxLength { get; private set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The tree data.
+ /// The extra bits.
+ /// The extra base.
+ /// The elements.
+ /// Length of the max.
+ public StaticTree(short[] treeData, int[] extraBits, int extraBase, int elements, int maxLength)
+ {
+ this.TreeData = treeData;
+ this.ExtraBits = extraBits;
+ this.ExtraBase = extraBase;
+ this.Elements = elements;
+ this.MaxLength = maxLength;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v10/Tree.cs b/Renci.SshNet/Compression/v10/Tree.cs
new file mode 100644
index 0000000..b0978af
--- /dev/null
+++ b/Renci.SshNet/Compression/v10/Tree.cs
@@ -0,0 +1,334 @@
+using System;
+/*
+ * $Id: Tree.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+ internal sealed class Tree
+ {
+ private const int MAX_BITS = 15;
+
+ private const int LITERALS = 256;
+
+ private const int LENGTH_CODES = 29;
+
+ private const int L_CODES = (LITERALS + 1 + LENGTH_CODES);
+
+ private const int HEAP_SIZE = (2 * L_CODES + 1);
+
+ private static byte[] _dist_code = {
+ 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8,
+ 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17,
+ 18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
+ 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
+ };
+
+
+ ///
+ /// The corresponding static tree
+ ///
+ private StaticTree _staticTree;
+
+ ///
+ /// The dynamic tree
+ ///
+ private short[] _dynamicTree;
+
+ ///
+ /// Gets the largest code with non zero frequency.
+ ///
+ ///
+ /// The max_code.
+ ///
+ public int LargestCode { get; private set; }
+
+ public void Init(short[] dynamicTree, StaticTree staticTree)
+ {
+ this._staticTree = staticTree;
+ this._dynamicTree = dynamicTree;
+ }
+
+ ///
+ /// Mapping from a distance to a distance code. dist is the distance - 1 and must not have side effects. _dist_code[256] and _dist_code[257] are never used.
+ ///
+ /// The dist.
+ ///
+ public static int DistanceCode(int dist)
+ {
+ // TODO: Under multiple port forward after more then 50K requests gets index out of range
+ return ((dist) < 256 ? _dist_code[dist] : _dist_code[256 + ((dist) >> 7)]);
+ }
+
+ ///
+ /// Construct one Huffman tree and assigns the code bit strings and lengths. Update the total bit length for the current block.
+ ///
+ /// The s.
+ public void BuildTree(Deflate s)
+ {
+ short[] tree = _dynamicTree;
+ short[] stree = _staticTree.TreeData;
+ int elems = _staticTree.Elements;
+ int n, m; // iterate over heap elements
+ int max_code = -1; // largest code with non zero frequency
+ int node; // new node being created
+
+ // Construct the initial heap, with least frequent element in
+ // heap[1]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
+ // heap[0] is not used.
+ s.heap_len = 0;
+ s.heap_max = HEAP_SIZE;
+
+ for (n = 0; n < elems; n++)
+ {
+ if (tree[n * 2] != 0)
+ {
+ s.heap[++s.heap_len] = max_code = n;
+ s.depth[n] = 0;
+ }
+ else
+ {
+ tree[n * 2 + 1] = 0;
+ }
+ }
+
+ // The pkzip format requires that at least one distance code exists,
+ // and that at least one bit should be sent even if there is only one
+ // possible code. So to avoid special checks later on we force at least
+ // two codes of non zero frequency.
+ while (s.heap_len < 2)
+ {
+ node = s.heap[++s.heap_len] = (max_code < 2 ? ++max_code : 0);
+ tree[node * 2] = 1;
+ s.depth[node] = 0;
+ s.opt_len--; if (stree != null) s.static_len -= stree[node * 2 + 1];
+ // node is 0 or 1 so it does not have extra bits
+ }
+ this.LargestCode = max_code;
+
+ // The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
+ // establish sub-heaps of increasing lengths:
+
+ for (n = s.heap_len / 2; n >= 1; n--)
+ s.RestoreHeap(tree, n);
+
+ // Construct the Huffman tree by repeatedly combining the least two
+ // frequent nodes.
+
+ node = elems; // next internal node of the tree
+ do
+ {
+ // n = node of least frequency
+ n = s.heap[1];
+ s.heap[1] = s.heap[s.heap_len--];
+ s.RestoreHeap(tree, 1);
+ m = s.heap[1]; // m = node of next least frequency
+
+ s.heap[--s.heap_max] = n; // keep the nodes sorted by frequency
+ s.heap[--s.heap_max] = m;
+
+ // Create a new node father of n and m
+ tree[node * 2] = (short)(tree[n * 2] + tree[m * 2]);
+ s.depth[node] = (byte)(System.Math.Max(s.depth[n], s.depth[m]) + 1);
+ tree[n * 2 + 1] = tree[m * 2 + 1] = (short)node;
+
+ // and insert the new node in the heap
+ s.heap[1] = node++;
+ s.RestoreHeap(tree, 1);
+ }
+ while (s.heap_len >= 2);
+
+ s.heap[--s.heap_max] = s.heap[1];
+
+ // At this point, the fields freq and dad are set. We can now
+ // generate the bit lengths.
+
+ ComputeBitLength(s);
+
+ // The field len is now set, we can generate the bit codes
+ GenerateCodes(tree, max_code, s.bl_count);
+ }
+
+ ///
+ /// Compute the optimal bit lengths for a tree and update the total bit length for the current block.
+ ///
+ /// The s.
+ private void ComputeBitLength(Deflate s)
+ {
+ short[] tree = _dynamicTree;
+ short[] stree = _staticTree.TreeData;
+ int[] extra = _staticTree.ExtraBits;
+ int based = _staticTree.ExtraBase;
+ int max_length = _staticTree.MaxLength;
+ int h; // heap index
+ int n, m; // iterate over the tree elements
+ int bits; // bit length
+ int xbits; // extra bits
+ short f; // frequency
+ int overflow = 0; // number of elements with bit length too large
+
+ for (bits = 0; bits <= MAX_BITS; bits++) s.bl_count[bits] = 0;
+
+ // In a first pass, compute the optimal bit lengths (which may
+ // overflow in the case of the bit length tree).
+ tree[s.heap[s.heap_max] * 2 + 1] = 0; // root of the heap
+
+ for (h = s.heap_max + 1; h < HEAP_SIZE; h++)
+ {
+ n = s.heap[h];
+ bits = tree[tree[n * 2 + 1] * 2 + 1] + 1;
+ if (bits > max_length) { bits = max_length; overflow++; }
+ tree[n * 2 + 1] = (short)bits;
+ // We overwrite tree[n*2+1] which is no longer needed
+
+ if (n > LargestCode) continue; // not a leaf node
+
+ s.bl_count[bits]++;
+ xbits = 0;
+ if (n >= based) xbits = extra[n - based];
+ f = tree[n * 2];
+ s.opt_len += f * (bits + xbits);
+ if (stree != null) s.static_len += f * (stree[n * 2 + 1] + xbits);
+ }
+ if (overflow == 0) return;
+
+ // This happens for example on obj2 and pic of the Calgary corpus
+ // Find the first bit length which could increase:
+ do
+ {
+ bits = max_length - 1;
+ while (s.bl_count[bits] == 0) bits--;
+ s.bl_count[bits]--; // move one leaf down the tree
+ s.bl_count[bits + 1] += 2; // move one overflow item as its brother
+ s.bl_count[max_length]--;
+ // The brother of the overflow item also moves one step up,
+ // but this does not affect bl_count[max_length]
+ overflow -= 2;
+ }
+ while (overflow > 0);
+
+ for (bits = max_length; bits != 0; bits--)
+ {
+ n = s.bl_count[bits];
+ while (n != 0)
+ {
+ m = s.heap[--h];
+ if (m > LargestCode) continue;
+ if (tree[m * 2 + 1] != bits)
+ {
+ s.opt_len += (int)(((long)bits - (long)tree[m * 2 + 1]) * (long)tree[m * 2]);
+ tree[m * 2 + 1] = (short)bits;
+ }
+ n--;
+ }
+ }
+ }
+
+ ///
+ /// Generate the codes for a given tree and bit counts (which need not be optimal).
+ ///
+ /// The tree to decorate.
+ /// The largest code with non zero frequency.
+ /// The number of codes at each bit length.
+ private static void GenerateCodes(short[] tree, int max_code, short[] bl_count)
+ {
+ short[] next_code = new short[MAX_BITS + 1]; // next code value for each bit length
+ short code = 0; // running code value
+ int bits; // bit index
+ int n; // code index
+
+ // The distribution counts are first used to generate the code values
+ // without bit reversal.
+ for (bits = 1; bits <= MAX_BITS; bits++)
+ {
+ next_code[bits] = code = (short)((code + bl_count[bits - 1]) << 1);
+ }
+
+ // Check that the bit counts in bl_count are consistent. The last code
+ // must be all ones.
+ //Assert (code + bl_count[MAX_BITS]-1 == (1<
+ /// Reverse the first len bits of a code, using straightforward code (a faster method would use a table)
+ ///
+ /// The value to invert.
+ /// The bit length.
+ ///
+ private static int BiReverse(int code, int len)
+ {
+ int res = 0;
+ do
+ {
+ res |= code & 1;
+ code >>= 1;
+ res <<= 1;
+ }
+ while (--len > 0);
+ return res >> 1;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v10/ZInputStream.cs b/Renci.SshNet/Compression/v10/ZInputStream.cs
new file mode 100644
index 0000000..d316955
--- /dev/null
+++ b/Renci.SshNet/Compression/v10/ZInputStream.cs
@@ -0,0 +1,200 @@
+/*
+Copyright (c) 2001 Lapo Luchini.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS
+OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+/* This file is a port of jzlib v1.0.7, com.jcraft.jzlib.ZInputStream.java
+ */
+
+using Renci.SshNet.Compression;
+using System;
+using System.Diagnostics;
+using System.IO;
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+ public class ZInputStream : Stream
+ {
+ private const int BufferSize = 512;
+ //private ZStream z = new ZStream();
+ private ICompressor _compressor;
+
+ // TODO Allow custom buf
+ private byte[] _buffer = new byte[BufferSize];
+ private CompressionMode _compressionMode;
+ private Stream _input;
+ private bool _isClosed;
+ private bool _noMoreInput = false;
+
+ public FlushType FlushMode { get; private set; }
+
+ public ZInputStream()
+ {
+ this.FlushMode = FlushType.Z_PARTIAL_FLUSH;
+ }
+
+ public ZInputStream(Stream input)
+ : this(input, false)
+ {
+ }
+
+ public ZInputStream(Stream input, bool nowrap)
+ : this()
+ {
+ Debug.Assert(input.CanRead);
+
+ this._input = input;
+ this._compressor = new Inflate(nowrap);
+ this._compressionMode = CompressionMode.Decompress;
+ this._compressor.next_in = _buffer;
+ this._compressor.next_in_index = 0;
+ this._compressor.avail_in = 0;
+ }
+
+ public ZInputStream(Stream input, CompressionLevel level)
+ : this()
+ {
+ Debug.Assert(input.CanRead);
+
+ this._input = input;
+ this._compressor = new Deflate(level);
+ this._compressionMode = CompressionMode.Compress;
+ this._compressor.next_in = _buffer;
+ this._compressor.next_in_index = 0;
+ this._compressor.avail_in = 0;
+ }
+
+ #region Stream implementation
+
+ public sealed override bool CanRead
+ {
+ get { return !_isClosed; }
+ }
+
+ public sealed override bool CanSeek
+ {
+ get { return false; }
+ }
+
+ public sealed override bool CanWrite
+ {
+ get { return false; }
+ }
+
+ public override void Flush()
+ {
+ }
+
+ public override long Length
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ public override long Position
+ {
+ get { throw new NotSupportedException(); }
+ set { throw new NotSupportedException(); }
+ }
+
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ if (count == 0)
+ return 0;
+
+ //this._compressor.next_out = buffer;
+ //this._compressor.next_out_index = offset;
+ //this._compressor.avail_out = count;
+
+ ZLibStatus err = ZLibStatus.Z_OK;
+ do
+ {
+ if (this._compressor.avail_in == 0 && !_noMoreInput)
+ {
+ // if buffer is empty and more input is available, refill it
+ this._compressor.next_in_index = 0;
+ this._compressor.avail_in = _input.Read(_buffer, 0, _buffer.Length); //(bufsize 0 || this._compressor.avail_out == 0);
+ }
+
+ #endregion
+
+ public override void Close()
+ {
+ if (this._isClosed)
+ return;
+
+ try
+ {
+ try
+ {
+ Finish();
+ }
+ catch (IOException)
+ {
+ // Ignore
+ }
+ }
+ finally
+ {
+ this._isClosed = true;
+ End();
+ _output.Close();
+ _output = null;
+ }
+ }
+
+ private void End()
+ {
+ if (this._compressor == null)
+ return;
+ switch (this._compressionMode)
+ {
+ case CompressionMode.Compress:
+ this._compressor.deflateEnd();
+ break;
+ case CompressionMode.Decompress:
+ this._compressor.inflateEnd();
+ break;
+ default:
+ break;
+ }
+
+ //this._compressor.free();
+ this._compressor = null;
+ }
+
+ private void Finish()
+ {
+ do
+ {
+ var err = ZLibStatus.Z_OK;
+ switch (this._compressionMode)
+ {
+ case CompressionMode.Compress:
+ err = this._compressor.deflate(_buffer, 0, _buffer.Length, FlushType.Z_FINISH);
+ break;
+ case CompressionMode.Decompress:
+ err = this._compressor.inflate(_buffer, 0, _buffer.Length, FlushType.Z_FINISH);
+ break;
+ default:
+ break;
+ }
+
+ if (err != ZLibStatus.Z_STREAM_END && err != ZLibStatus.Z_OK)
+ // TODO
+ // throw new ZStreamException((compress?"de":"in")+"flating: "+z.msg);
+ //throw new IOException((_compressionMode ? "de" : "in") + "flating: " + z.msg);
+ throw new IOException(string.Format("{0}ion error: {1}", _compressionMode, err));
+
+ int count = _buffer.Length - this._compressor.avail_out;
+ if (count > 0)
+ {
+ _output.Write(_buffer, 0, count);
+ }
+ }
+ while (this._compressor.avail_in > 0 || this._compressor.avail_out == 0);
+
+ Flush();
+ }
+ }
+}
diff --git a/Renci.SshNet/Compression/v10/ZStream.cs b/Renci.SshNet/Compression/v10/ZStream.cs
new file mode 100644
index 0000000..b151ba1
--- /dev/null
+++ b/Renci.SshNet/Compression/v10/ZStream.cs
@@ -0,0 +1,94 @@
+using System;
+using System.IO;
+/*
+ * $Id: ZStream.cs,v 1.1 2006-07-31 13:59:26 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public interface ICompressor
+ {
+ ZLibStatus deflate(byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType);
+ ZLibStatus deflate(byte[] bufer, int offset, int count, byte[] p1, int p2, int p3, FlushType flushType);
+
+ ZLibStatus deflateEnd();
+
+ ZLibStatus inflate(byte[] bufer, int offset, int count, byte[] p1, int p2, int p3, FlushType flushType);
+ ZLibStatus inflate(byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType);
+
+ ZLibStatus inflateEnd();
+
+ //ZLibStatus inflate(FlushType flushType);
+
+ int avail_out { get; set; }
+
+ int avail_in { get; set; }
+
+ //int next_out_index { get; set; }
+
+ //byte[] next_out { get; set; }
+
+ byte[] next_in { get; set; }
+
+ int next_in_index { get; set; }
+ }
+
+
+ public abstract class ZStream
+ {
+
+ protected const int MAX_WBITS = 15; // 32K LZ77 window
+ protected const int DEF_WBITS = MAX_WBITS;
+
+ private const int MAX_MEM_LEVEL = 9;
+
+ public byte[] next_in { get; set; } // next input byte
+ public int next_in_index { get; set; }
+ public int avail_in { get; set; } // number of bytes available at next_in
+ public long total_in { get; set; } // total nb of input bytes read so far
+
+ public byte[] next_out { get; set; } // next output byte should be put there
+ public int next_out_index { get; set; }
+ public int avail_out { get; set; } // remaining free space at next_out
+ public long total_out { get; set; } // total nb of bytes output so far
+
+ public String msg { get; set; }
+
+ internal BlockType data_type; // best guess about the data type: ascii or binary
+
+ public long adler;
+
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v10/Zlib.cs b/Renci.SshNet/Compression/v10/Zlib.cs
new file mode 100644
index 0000000..5890675
--- /dev/null
+++ b/Renci.SshNet/Compression/v10/Zlib.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Represents "zlib" compression implementation
+ ///
+ internal class Zlib : Compressor
+ {
+ ///
+ /// Gets algorithm name.
+ ///
+ public override string Name
+ {
+ get { return "zlib"; }
+ }
+
+ ///
+ /// Initializes the algorithm
+ ///
+ /// The session.
+ public override void Init(Session session)
+ {
+ base.Init(session);
+ this.IsActive = true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v10/ZlibOpenSsh.cs b/Renci.SshNet/Compression/v10/ZlibOpenSsh.cs
new file mode 100644
index 0000000..f82a4c0
--- /dev/null
+++ b/Renci.SshNet/Compression/v10/ZlibOpenSsh.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Represents "zlib@openssh.org" compression implementation
+ ///
+ public class ZlibOpenSsh : Compressor
+ {
+ ///
+ /// Gets algorithm name.
+ ///
+ public override string Name
+ {
+ get { return "zlib@openssh.org"; }
+ }
+
+ ///
+ /// Initializes the algorithm
+ ///
+ /// The session.
+ public override void Init(Session session)
+ {
+ base.Init(session);
+
+ session.UserAuthenticationSuccessReceived += Session_UserAuthenticationSuccessReceived;
+ }
+
+ private void Session_UserAuthenticationSuccessReceived(object sender, MessageEventArgs e)
+ {
+ this.IsActive = true;
+ this.Session.UserAuthenticationSuccessReceived -= Session_UserAuthenticationSuccessReceived;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v10/ZlibStream.cs b/Renci.SshNet/Compression/v10/ZlibStream.cs
new file mode 100644
index 0000000..fb5f9d2
--- /dev/null
+++ b/Renci.SshNet/Compression/v10/ZlibStream.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.IO;
+using Org.BouncyCastle.Utilities.Zlib;
+
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Implements Zlib compression algorithm.
+ ///
+ public class ZlibStream
+ {
+ private readonly Stream _baseStream;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The stream.
+ /// The mode.
+ public ZlibStream(Stream stream, CompressionMode mode)
+ {
+ switch (mode)
+ {
+ case CompressionMode.Compress:
+ //this._baseStream = new ZOutputStream(stream, CompressionLevel.Z_DEFAULT_COMPRESSION);
+ this._baseStream = new ZOutputStream(stream, CompressionLevel.Z_DEFAULT_COMPRESSION);
+ break;
+ case CompressionMode.Decompress:
+ this._baseStream = new ZOutputStream(stream);
+ break;
+ default:
+ break;
+ }
+
+ //this._baseStream.FlushMode = Ionic.Zlib.FlushType.Partial;
+ }
+
+ ///
+ /// Writes the specified buffer.
+ ///
+ /// The buffer.
+ /// The offset.
+ /// The count.
+ public void Write(byte[] buffer, int offset, int count)
+ {
+ this._baseStream.Write(buffer, offset, count);
+ }
+ }
+}
diff --git a/Renci.SshNet/Compression/v11/Adler32.cs b/Renci.SshNet/Compression/v11/Adler32.cs
new file mode 100644
index 0000000..c132fa9
--- /dev/null
+++ b/Renci.SshNet/Compression/v11/Adler32.cs
@@ -0,0 +1,95 @@
+using System;
+/*
+ * $Id: Adler32.cs,v 1.1 2006-07-31 13:59:25 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ internal static class Adler32
+ {
+
+ // largest prime smaller than 65536
+ private const int BASE = 65521;
+ // NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
+ private const int NMAX = 5552;
+
+ internal static long adler32(long adler, byte[] buf, int index, int len)
+ {
+ if (buf == null) { return 1L; }
+
+ long s1 = adler & 0xffff;
+ long s2 = (adler >> 16) & 0xffff;
+ int k;
+
+ while (len > 0)
+ {
+ k = len < NMAX ? len : NMAX;
+ len -= k;
+ while (k >= 16)
+ {
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ k -= 16;
+ }
+ if (k != 0)
+ {
+ do
+ {
+ s1 += buf[index++] & 0xff; s2 += s1;
+ }
+ while (--k != 0);
+ }
+ s1 %= BASE;
+ s2 %= BASE;
+ }
+ return (s2 << 16) | s1;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v11/CompressionMode.cs b/Renci.SshNet/Compression/v11/CompressionMode.cs
new file mode 100644
index 0000000..1577e0b
--- /dev/null
+++ b/Renci.SshNet/Compression/v11/CompressionMode.cs
@@ -0,0 +1,18 @@
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Specifies compression modes
+ ///
+ public enum CompressionMode
+ {
+ ///
+ /// Specifies that content should be compressed.
+ ///
+ Compress = 0,
+
+ ///
+ /// Specifies that content should be decompressed.
+ ///
+ Decompress = 1,
+ }
+}
diff --git a/Renci.SshNet/Compression/v11/Compressor.cs b/Renci.SshNet/Compression/v11/Compressor.cs
new file mode 100644
index 0000000..1479bb6
--- /dev/null
+++ b/Renci.SshNet/Compression/v11/Compressor.cs
@@ -0,0 +1,151 @@
+using System.Collections.Generic;
+using Renci.SshNet.Security;
+using System.IO;
+using System;
+
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Represents base class for compression algorithm implementation
+ ///
+ public abstract class Compressor : Algorithm, IDisposable
+ {
+ private readonly ZlibStream _compressor;
+ private readonly ZlibStream _decompressor;
+
+ private MemoryStream _compressorStream;
+ private MemoryStream _decompressorStream;
+
+ ///
+ /// Gets or sets a value indicating whether compression is active.
+ ///
+ ///
+ /// true if compression is active; otherwise, false.
+ ///
+ protected bool IsActive { get; set; }
+
+ ///
+ /// Gets the session.
+ ///
+ protected Session Session { get; private set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ 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);
+ }
+
+ ///
+ /// Initializes the algorithm
+ ///
+ /// The session.
+ public virtual void Init(Session session)
+ {
+ this.Session = session;
+ }
+
+ ///
+ /// Compresses the specified data.
+ ///
+ /// Data to compress.
+ /// Compressed 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();
+ }
+
+ ///
+ /// Decompresses the specified data.
+ ///
+ /// Compressed data.
+ /// Decompressed 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;
+
+ ///
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged ResourceMessages.
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Releases unmanaged and - optionally - managed resources
+ ///
+ /// true to release both managed and unmanaged resources; false to release only unmanaged ResourceMessages.
+ 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;
+ }
+ }
+
+ ///
+ /// Releases unmanaged resources and performs other cleanup operations before the
+ /// is reclaimed by garbage collection.
+ ///
+ ~Compressor()
+ {
+ // Do not re-create Dispose clean-up code here.
+ // Calling Dispose(false) is optimal in terms of
+ // readability and maintainability.
+ Dispose(false);
+ }
+
+ #endregion
+ }
+}
diff --git a/Renci.SshNet/Compression/v11/Deflate.cs b/Renci.SshNet/Compression/v11/Deflate.cs
new file mode 100644
index 0000000..cc42021
--- /dev/null
+++ b/Renci.SshNet/Compression/v11/Deflate.cs
@@ -0,0 +1,2225 @@
+using System;
+using System.Collections.Generic;
+/*
+ * $Id: Deflate.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public enum BlockType : byte
+ {
+ Z_BINARY = 0,
+ Z_ASCII = 1,
+ Z_UNKNOWN = 2
+ }
+
+ public enum DefalteFlavor : int
+ {
+ STORED = 0,
+ FAST = 1,
+ SLOW = 2
+ }
+
+ public sealed class Deflate : ZStream, ICompressor
+ {
+ private const int MAX_MEM_LEVEL = 9;
+
+ private const int Z_DEFAULT_COMPRESSION = -1;
+
+ private const int MAX_WBITS = 15; // 32K LZ77 window
+
+ private const int DEF_MEM_LEVEL = 8;
+
+ ///
+ /// The Bit length codes must not exceed MAX_BL_BITS bits
+ ///
+ private const int MAX_BL_BITS = 7;
+
+ // block not completed, need more input or more output
+ private const int NeedMore = 0;
+
+ // block flush performed
+ private const int BlockDone = 1;
+
+ // finish started, need only more output at next deflate
+ private const int FinishStarted = 2;
+
+ // finish done, accept no more input or output
+ private const int FinishDone = 3;
+
+ // preset dictionary flag in zlib header
+ private const int PRESET_DICT = 0x20;
+
+ private const int Z_VERSION_ERROR = -6;
+
+ private const int INIT_STATE = 42;
+ private const int BUSY_STATE = 113;
+ private const int FINISH_STATE = 666;
+
+ // The deflate compression method
+ private const int Z_DEFLATED = 8;
+
+ private const int STORED_BLOCK = 0;
+ private const int STATIC_TREES = 1;
+ private const int DYN_TREES = 2;
+
+ private const int Buf_size = 8 * 2;
+
+ // repeat previous bit length 3-6 times (2 bits of repeat count)
+ private const int REP_3_6 = 16;
+
+ // repeat a zero length 3-10 times (3 bits of repeat count)
+ private const int REPZ_3_10 = 17;
+
+ // repeat a zero length 11-138 times (7 bits of repeat count)
+ private const int REPZ_11_138 = 18;
+
+ private const int MIN_MATCH = 3;
+ private const int MAX_MATCH = 258;
+ private const int MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1);
+
+ private const int MAX_BITS = 15;
+ private const int D_CODES = 30;
+ private const int BL_CODES = 19;
+ private const int LENGTH_CODES = 29;
+ private const int LITERALS = 256;
+ private const int L_CODES = (LITERALS + 1 + LENGTH_CODES);
+ private const int HEAP_SIZE = (2 * L_CODES + 1);
+
+ private const int END_BLOCK = 256;
+
+ private static readonly IDictionary config_table = new Dictionary() {
+ {(CompressionLevel)0, new Config(0, 0, 0, 0, DefalteFlavor.STORED)},
+ {(CompressionLevel)1, new Config(4, 4, 8, 4, DefalteFlavor.FAST)},
+ {(CompressionLevel)2, new Config(4, 5, 16, 8, DefalteFlavor.FAST)},
+ {(CompressionLevel)3, new Config(4, 6, 32, 32, DefalteFlavor.FAST)},
+
+ {(CompressionLevel)4, new Config(4, 4, 16, 16, DefalteFlavor.SLOW)},
+ {(CompressionLevel)5, new Config(8, 16, 32, 32, DefalteFlavor.SLOW)},
+ {(CompressionLevel)6, new Config(8, 16, 128, 128, DefalteFlavor.SLOW)},
+ {(CompressionLevel)7, new Config(8, 32, 128, 256, DefalteFlavor.SLOW)},
+ {(CompressionLevel)8, new Config(32, 128, 258, 1024, DefalteFlavor.SLOW)},
+ {(CompressionLevel)9, new Config(32, 258, 258, 4096, DefalteFlavor.SLOW)},
+ };
+
+ #region Static definitions
+
+ private static readonly byte[] _length_code ={
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12,
+ 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
+ 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
+ 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
+ };
+
+ private static readonly int[] base_length = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
+ 64, 80, 96, 112, 128, 160, 192, 224, 0
+ };
+
+ private static readonly int[] base_dist = {
+ 0, 1, 2, 3, 4, 6, 8, 12, 16, 24,
+ 32, 48, 64, 96, 128, 192, 256, 384, 512, 768,
+ 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576
+ };
+
+ // extra bits for each length code
+ private static readonly int[] extra_lbits ={
+ 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0
+ };
+
+ // extra bits for each distance code
+ private static readonly int[] extra_dbits ={
+ 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13
+ };
+
+ // extra bits for each bit length code
+ private static readonly int[] extra_blbits ={
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7
+ };
+
+ private static readonly byte[] bl_order ={
+ 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
+
+ private static readonly short[] static_ltree = {
+ 12, 8, 140, 8, 76, 8, 204, 8, 44, 8,
+ 172, 8, 108, 8, 236, 8, 28, 8, 156, 8,
+ 92, 8, 220, 8, 60, 8, 188, 8, 124, 8,
+ 252, 8, 2, 8, 130, 8, 66, 8, 194, 8,
+ 34, 8, 162, 8, 98, 8, 226, 8, 18, 8,
+ 146, 8, 82, 8, 210, 8, 50, 8, 178, 8,
+ 114, 8, 242, 8, 10, 8, 138, 8, 74, 8,
+ 202, 8, 42, 8, 170, 8, 106, 8, 234, 8,
+ 26, 8, 154, 8, 90, 8, 218, 8, 58, 8,
+ 186, 8, 122, 8, 250, 8, 6, 8, 134, 8,
+ 70, 8, 198, 8, 38, 8, 166, 8, 102, 8,
+ 230, 8, 22, 8, 150, 8, 86, 8, 214, 8,
+ 54, 8, 182, 8, 118, 8, 246, 8, 14, 8,
+ 142, 8, 78, 8, 206, 8, 46, 8, 174, 8,
+ 110, 8, 238, 8, 30, 8, 158, 8, 94, 8,
+ 222, 8, 62, 8, 190, 8, 126, 8, 254, 8,
+ 1, 8, 129, 8, 65, 8, 193, 8, 33, 8,
+ 161, 8, 97, 8, 225, 8, 17, 8, 145, 8,
+ 81, 8, 209, 8, 49, 8, 177, 8, 113, 8,
+ 241, 8, 9, 8, 137, 8, 73, 8, 201, 8,
+ 41, 8, 169, 8, 105, 8, 233, 8, 25, 8,
+ 153, 8, 89, 8, 217, 8, 57, 8, 185, 8,
+ 121, 8, 249, 8, 5, 8, 133, 8, 69, 8,
+ 197, 8, 37, 8, 165, 8, 101, 8, 229, 8,
+ 21, 8, 149, 8, 85, 8, 213, 8, 53, 8,
+ 181, 8, 117, 8, 245, 8, 13, 8, 141, 8,
+ 77, 8, 205, 8, 45, 8, 173, 8, 109, 8,
+ 237, 8, 29, 8, 157, 8, 93, 8, 221, 8,
+ 61, 8, 189, 8, 125, 8, 253, 8, 19, 9,
+ 275, 9, 147, 9, 403, 9, 83, 9, 339, 9,
+ 211, 9, 467, 9, 51, 9, 307, 9, 179, 9,
+ 435, 9, 115, 9, 371, 9, 243, 9, 499, 9,
+ 11, 9, 267, 9, 139, 9, 395, 9, 75, 9,
+ 331, 9, 203, 9, 459, 9, 43, 9, 299, 9,
+ 171, 9, 427, 9, 107, 9, 363, 9, 235, 9,
+ 491, 9, 27, 9, 283, 9, 155, 9, 411, 9,
+ 91, 9, 347, 9, 219, 9, 475, 9, 59, 9,
+ 315, 9, 187, 9, 443, 9, 123, 9, 379, 9,
+ 251, 9, 507, 9, 7, 9, 263, 9, 135, 9,
+ 391, 9, 71, 9, 327, 9, 199, 9, 455, 9,
+ 39, 9, 295, 9, 167, 9, 423, 9, 103, 9,
+ 359, 9, 231, 9, 487, 9, 23, 9, 279, 9,
+ 151, 9, 407, 9, 87, 9, 343, 9, 215, 9,
+ 471, 9, 55, 9, 311, 9, 183, 9, 439, 9,
+ 119, 9, 375, 9, 247, 9, 503, 9, 15, 9,
+ 271, 9, 143, 9, 399, 9, 79, 9, 335, 9,
+ 207, 9, 463, 9, 47, 9, 303, 9, 175, 9,
+ 431, 9, 111, 9, 367, 9, 239, 9, 495, 9,
+ 31, 9, 287, 9, 159, 9, 415, 9, 95, 9,
+ 351, 9, 223, 9, 479, 9, 63, 9, 319, 9,
+ 191, 9, 447, 9, 127, 9, 383, 9, 255, 9,
+ 511, 9, 0, 7, 64, 7, 32, 7, 96, 7,
+ 16, 7, 80, 7, 48, 7, 112, 7, 8, 7,
+ 72, 7, 40, 7, 104, 7, 24, 7, 88, 7,
+ 56, 7, 120, 7, 4, 7, 68, 7, 36, 7,
+ 100, 7, 20, 7, 84, 7, 52, 7, 116, 7,
+ 3, 8, 131, 8, 67, 8, 195, 8, 35, 8,
+ 163, 8, 99, 8, 227, 8
+ };
+
+ private static readonly short[] static_dtree = {
+ 0, 5, 16, 5, 8, 5, 24, 5, 4, 5,
+ 20, 5, 12, 5, 28, 5, 2, 5, 18, 5,
+ 10, 5, 26, 5, 6, 5, 22, 5, 14, 5,
+ 30, 5, 1, 5, 17, 5, 9, 5, 25, 5,
+ 5, 5, 21, 5, 13, 5, 29, 5, 3, 5,
+ 19, 5, 11, 5, 27, 5, 7, 5, 23, 5
+ };
+ #endregion
+
+ private static readonly String[] z_errmsg = {
+ "need dictionary", // ZLibStatus.Z_NEED_DICT 2
+ "stream end", // ZLibStatus.Z_STREAM_END 1
+ "", // ZLibStatus.Z_OK 0
+ "file error", // ZLibStatus.Z_ERRNO (-1)
+ "stream error", // ZLibStatus.Z_STREAM_ERROR (-2)
+ "data error", // ZLibStatus.Z_DATA_ERROR (-3)
+ "insufficient memory", // Z_MEM_ERROR (-4)
+ "buffer error", // ZLibStatus.Z_BUF_ERROR (-5)
+ "incompatible version",// Z_VERSION_ERROR (-6)
+ ""
+ };
+
+
+
+ ///
+ /// as the name implies
+ ///
+ private int _status;
+
+ private BlockType _dataType;
+
+ ///
+ /// STORED (for zip only) or DEFLATED
+ ///
+ private byte _method;
+
+ ///
+ /// size of pending_buf
+ ///
+ private int _pendingBufferSize;
+
+ ///
+ /// LZ77 window size (32K by default)
+ ///
+ private int _windowSize;
+
+ ///
+ /// log2(w_size) (8..16)
+ ///
+ private int _windowBits;
+
+ ///
+ /// w_size - 1
+ ///
+ private int _windowMask;
+
+ ///
+ /// Sliding window. Input bytes are read into the second half of the window,
+ /// and move to the first half later to keep a dictionary of at least wSize
+ /// bytes. With this organization, matches are limited to a distance of
+ /// wSize-MAX_MATCH bytes, but this ensures that IO is always
+ /// performed with a length multiple of the block size. Also, it limits
+ /// the window size to 64K, which is quite useful on MSDOS.
+ /// To do: use the user input buffer as sliding window.
+ ///
+ private byte[] _window;
+
+ ///
+ /// Actual size of window: 2*wSize, except when the user input buffer
+ /// is directly used as sliding window.
+ ///
+ private int _windowActualSize;
+
+ ///
+ /// Link to older string with same hash index. To limit the size of this
+ /// array to 64K, this link is maintained only for the last 32K strings.
+ /// An index in this array is thus a window index modulo 32K.
+ ///
+ private short[] _previous;
+
+ ///
+ /// Heads of the hash chains or NIL.
+ ///
+ private short[] _head;
+
+ ///
+ /// hash index of string to be inserted
+ ///
+ private int _insertedHashIndex;
+
+ ///
+ /// number of elements in hash table
+ ///
+ private int _hashSize;
+
+ ///
+ /// log2(hash_size)
+ ///
+ private int _hashBits;
+
+ ///
+ /// hash_size-1
+ ///
+ private int _hashMask;
+
+ ///
+ /// Number of bits by which ins_h must be shifted at each input
+ /// step. It must be such that after MIN_MATCH steps, the oldest
+ /// byte no longer takes part in the hash key, that is:
+ /// hash_shift * MIN_MATCH >= hash_bits
+ ///
+ private int _hashShift;
+
+ ///
+ /// Window position at the beginning of the current output block. Gets
+ /// negative when the window is moved backwards.
+ ///
+ private int _blockStart;
+
+ ///
+ /// length of best match
+ ///
+ private int _matchLength;
+
+ ///
+ /// previous match
+ ///
+ private int _previousMatch;
+
+ ///
+ /// set if previous match exists
+ ///
+ private bool _matchAvailable;
+
+ ///
+ /// start of string to insert
+ ///
+ private int _startInsertString;
+
+ ///
+ /// start of matching string
+ ///
+ private int _startMatchString;
+
+ ///
+ /// number of valid bytes ahead in window
+ ///
+ private int _validBytesAhead;
+
+ ///
+ /// Length of the best match at previous step. Matches not greater than this
+ /// are discarded. This is used in the lazy match evaluation.
+ ///
+ private int _previousLength;
+
+ ///
+ /// To speed up deflation, hash chains are never searched beyond this
+ /// length. A higher limit improves compression ratio but degrades the speed.
+ ///
+ private int _maxChainLength;
+
+ ///
+ /// Attempt to find a better match only when the current match is strictly
+ /// smaller than this value. This mechanism is used only for compression
+ /// levels >= 4.
+ ///
+ private int _maxLazyMatch;
+
+ // Insert new strings in the hash table only if the match length is not
+ // greater than this length. This saves time but degrades compression.
+ // max_insert_length is used only for compression levels <= 3.
+
+ ///
+ /// The compression level (1..9)
+ ///
+ private CompressionLevel level;
+
+ ///
+ /// The favor or force Huffman coding
+ ///
+ private CompressionStrategy strategy;
+
+ ///
+ /// Use a faster search when the previous match is longer than this
+ ///
+ private int good_match;
+
+ ///
+ /// Stop searching when current match exceeds this
+ ///
+ private int nice_match;
+
+ ///
+ /// literal and length tree
+ ///
+ private short[] dyn_ltree;
+
+ ///
+ /// The distance tree
+ ///
+ private short[] dyn_dtree;
+
+ ///
+ /// The Huffman tree for bit lengths
+ ///
+ private short[] bl_tree;
+
+ ///
+ /// The desc for literal tree
+ ///
+ private Tree l_desc = new Tree();
+
+ ///
+ /// The desc for distance tree
+ ///
+ private Tree d_desc = new Tree();
+
+ ///
+ /// The desc for bit length tree
+ ///
+ private Tree bl_desc = new Tree();
+
+ ///
+ /// index for literals or lengths
+ ///
+ private int l_buf;
+
+ ///
+ /// Size of match buffer for literals/lengths. There are 4 reasons for
+ /// limiting lit_bufsize to 64K:
+ /// - frequencies can be kept in 16 bit counters
+ /// - if compression is not successful for the first block, all input
+ /// data is still in the window so we can still emit a stored block even
+ /// when input comes from standard input. (This can also be done for
+ /// all blocks if lit_bufsize is not greater than 32K.)
+ /// - if compression is not successful for a file smaller than 64K, we can
+ /// even emit a stored file instead of a stored block (saving 5 bytes).
+ /// This is applicable only for zip (not gzip or zlib).
+ /// - creating new Huffman trees less frequently may not provide fast
+ /// adaptation to changes in the input data statistics. (Take for
+ /// example a binary file with poorly compressible code followed by
+ /// a highly compressible string table.) Smaller buffer sizes give
+ /// fast adaptation but have of course the overhead of transmitting
+ /// trees more frequently.
+ /// - I can't count above 4
+ ///
+ private int lit_bufsize;
+
+ ///
+ /// running index in l_buf
+ ///
+ private int last_lit;
+
+ // Buffer for distances. To simplify the code, d_buf and l_buf have
+ // the same number of elements. To use different lengths, an extra flag
+ // array would be necessary.
+
+ ///
+ /// The index of pendig_buf
+ ///
+ private int d_buf;
+
+ ///
+ /// The number of string matches in current block
+ ///
+ private int matches;
+
+ ///
+ /// The bit length of EOB code for last block
+ ///
+ private int last_eob_len;
+
+ ///
+ /// Output buffer. bits are inserted starting at the bottom (least
+ /// significant bits).
+ ///
+ private uint bi_buf;
+
+ ///
+ /// Number of valid bits in bi_buf. All bits above the last valid bit
+ /// are always zero.
+ ///
+ private int bi_valid;
+
+ ///
+ /// value of flush param for previous deflate call
+ ///
+ private FlushType last_flush;
+
+ ///
+ /// bit length of current block with optimal trees
+ ///
+ internal int opt_len;
+
+ ///
+ /// bit length of current block with static trees
+ ///
+ internal int static_len;
+
+ ///
+ /// The output still pending
+ ///
+ internal byte[] pending_buf;
+
+ ///
+ /// next pending byte to output to the stream
+ ///
+ internal int pending_out;
+
+ ///
+ /// nb of bytes in the pending buffer
+ ///
+ internal int pending;
+
+ ///
+ /// suppress zlib header and adler32
+ ///
+ internal int noheader;
+
+ ///
+ /// number of codes at each bit length for an optimal tree
+ ///
+ internal short[] bl_count = new short[MAX_BITS + 1];
+
+ ///
+ /// heap used to build the Huffman trees
+ ///
+ internal int[] heap = new int[2 * L_CODES + 1];
+
+ ///
+ /// The number of elements in the heap
+ ///
+ internal int heap_len;
+ ///
+ /// The element of largest frequency
+ ///
+ internal int heap_max;
+
+ // The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+ // The same heap array is used to build all trees.
+
+ ///
+ /// Depth of each subtree used as tie breaker for trees of equal frequency
+ ///
+ internal byte[] depth = new byte[2 * L_CODES + 1];
+
+ public Deflate()
+ {
+ dyn_ltree = new short[HEAP_SIZE * 2];
+ dyn_dtree = new short[(2 * D_CODES + 1) * 2]; // distance tree
+ bl_tree = new short[(2 * BL_CODES + 1) * 2]; // Huffman tree for bit lengths
+ }
+
+ public Deflate(CompressionLevel level)
+ : this()
+ {
+ this.deflateInit(level);
+ }
+
+ public Deflate(CompressionLevel level, bool nowrap)
+ : this()
+ {
+ this.deflateInit(level, nowrap);
+ }
+
+ // Restore the heap property by moving down the tree starting at node k,
+ // exchanging a node with the smallest of its two sons if necessary, stopping
+ // when the heap property is re-established (each father smaller than its
+ // two sons).
+ internal void pqdownheap(short[] tree, // the tree to restore
+ int k // node to move down
+ )
+ {
+ int v = heap[k];
+ int j = k << 1; // left son of k
+ while (j <= heap_len)
+ {
+ // Set j to the smallest of the two sons:
+ if (j < heap_len &&
+ smaller(tree, heap[j + 1], heap[j], depth))
+ {
+ j++;
+ }
+ // Exit if v is smaller than both sons
+ if (smaller(tree, v, heap[j], depth)) break;
+
+ // Exchange v with the smallest son
+ heap[k] = heap[j]; k = j;
+ // And continue down the tree, setting j to the left son of k
+ j <<= 1;
+ }
+ heap[k] = v;
+ }
+
+ public ZLibStatus deflateInit(CompressionLevel level)
+ {
+ return deflateInit(level, MAX_WBITS);
+ }
+ public ZLibStatus deflateInit(CompressionLevel level, bool nowrap)
+ {
+ return deflateInit(level, MAX_WBITS, nowrap);
+ }
+ public ZLibStatus deflateInit(CompressionLevel level, int bits, bool nowrap)
+ {
+ return this.deflateInit(level, nowrap ? -bits : bits);
+ }
+
+ internal ZLibStatus deflateInit(CompressionLevel level, int bits)
+ {
+ return deflateInit2(level, Z_DEFLATED, bits, DEF_MEM_LEVEL, CompressionStrategy.Z_DEFAULT_STRATEGY);
+ }
+
+ private ZLibStatus deflateInit2(CompressionLevel level, int method, int windowBits, int memLevel, CompressionStrategy strategy)
+ {
+ int noheader = 0;
+ // byte[] my_version=ZLIB_VERSION;
+
+ //
+ // if (version == null || version[0] != my_version[0]
+ // || stream_size != sizeof(z_stream)) {
+ // return Z_VERSION_ERROR;
+ // }
+
+ base.msg = null;
+
+ if (level == CompressionLevel.Z_DEFAULT_COMPRESSION) level = (CompressionLevel)6;
+
+ if (windowBits < 0)
+ { // undocumented feature: suppress zlib header
+ noheader = 1;
+ windowBits = -windowBits;
+ }
+
+ if (memLevel < 1 || memLevel > MAX_MEM_LEVEL ||
+ method != Z_DEFLATED ||
+ windowBits < 9 || windowBits > 15 || level < 0 || level > (CompressionLevel)9 ||
+ strategy < 0 || strategy > CompressionStrategy.Z_HUFFMAN_ONLY)
+ {
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+
+ this.noheader = noheader;
+ _windowBits = windowBits;
+ _windowSize = 1 << _windowBits;
+ _windowMask = _windowSize - 1;
+
+ _hashBits = memLevel + 7;
+ _hashSize = 1 << _hashBits;
+ _hashMask = _hashSize - 1;
+ _hashShift = ((_hashBits + MIN_MATCH - 1) / MIN_MATCH);
+
+ _window = new byte[_windowSize * 2];
+ _previous = new short[_windowSize];
+ _head = new short[_hashSize];
+
+ lit_bufsize = 1 << (memLevel + 6); // 16K elements by default
+
+ // We overlay pending_buf and d_buf+l_buf. This works since the average
+ // output size for (length,distance) codes is <= 24 bits.
+ pending_buf = new byte[lit_bufsize * 4];
+ _pendingBufferSize = lit_bufsize * 4;
+
+ d_buf = lit_bufsize / 2;
+ l_buf = (1 + 2) * lit_bufsize;
+
+ this.level = level;
+
+ //System.out.println("level="+level);
+
+ this.strategy = strategy;
+ this._method = (byte)method;
+
+ return deflateReset();
+ }
+
+ private ZLibStatus deflateReset()
+ {
+ base.total_in = base.total_out = 0;
+ base.msg = null; //
+ base.data_type = BlockType.Z_UNKNOWN;
+
+ pending = 0;
+ pending_out = 0;
+
+ if (noheader < 0)
+ {
+ noheader = 0; // was set to -1 by deflate(..., FlushType.Z_FINISH);
+ }
+ _status = (noheader != 0) ? BUSY_STATE : INIT_STATE;
+ base.adler = Adler32.adler32(0, null, 0, 0);
+
+ last_flush = FlushType.Z_NO_FLUSH;
+
+ tr_init();
+ lm_init();
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus deflateEnd()
+ {
+ if (_status != INIT_STATE && _status != BUSY_STATE && _status != FINISH_STATE)
+ {
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+ // Deallocate in reverse order of allocations:
+ pending_buf = null;
+ _head = null;
+ _previous = null;
+ _window = null;
+ // free
+ // dstate=null;
+ return _status == BUSY_STATE ? ZLibStatus.Z_DATA_ERROR : ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus deflateParams(CompressionLevel _level, CompressionStrategy _strategy)
+ {
+ ZLibStatus err = ZLibStatus.Z_OK;
+
+ if (_level == CompressionLevel.Z_DEFAULT_COMPRESSION)
+ {
+ _level = (CompressionLevel)6;
+ }
+ if (_level < 0 || _level > (CompressionLevel)9 ||
+ _strategy < 0 || _strategy > CompressionStrategy.Z_HUFFMAN_ONLY)
+ {
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+
+ if (config_table[level].Function != config_table[_level].Function &&
+ base.total_in != 0)
+ {
+ // Flush the last buffer:
+ err = this.deflate(FlushType.Z_PARTIAL_FLUSH);
+ }
+
+ if (level != _level)
+ {
+ level = _level;
+ _maxLazyMatch = config_table[level].MaxLazy;
+ good_match = config_table[level].GoodLength;
+ nice_match = config_table[level].NiceLength;
+ _maxChainLength = config_table[level].MaxChain;
+ }
+ strategy = _strategy;
+ return err;
+ }
+
+ public ZLibStatus deflateSetDictionary(byte[] dictionary, int dictLength)
+ {
+ int length = dictLength;
+ int index = 0;
+
+ if (dictionary == null || _status != INIT_STATE)
+ return ZLibStatus.Z_STREAM_ERROR;
+
+ base.adler = Adler32.adler32(base.adler, dictionary, 0, dictLength);
+
+ if (length < MIN_MATCH) return ZLibStatus.Z_OK;
+ if (length > _windowSize - MIN_LOOKAHEAD)
+ {
+ length = _windowSize - MIN_LOOKAHEAD;
+ index = dictLength - length; // use the tail of the dictionary
+ }
+ System.Array.Copy(dictionary, index, _window, 0, length);
+ _startInsertString = length;
+ _blockStart = length;
+
+ // Insert all strings in the hash table (except for the last two bytes).
+ // s->lookahead stays null, so s->ins_h will be recomputed at the next
+ // call of fill_window.
+
+ _insertedHashIndex = _window[0] & 0xff;
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[1] & 0xff)) & _hashMask;
+
+ for (int n = 0; n <= length - MIN_MATCH; n++)
+ {
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[(n) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+ _previous[n & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)n;
+ }
+ return ZLibStatus.Z_OK;
+ }
+
+ private void lm_init()
+ {
+ _windowActualSize = 2 * _windowSize;
+
+ _head[_hashSize - 1] = 0;
+ for (int i = 0; i < _hashSize - 1; i++)
+ {
+ _head[i] = 0;
+ }
+
+ // Set the default configuration parameters:
+ _maxLazyMatch = Deflate.config_table[level].MaxLazy;
+ good_match = Deflate.config_table[level].GoodLength;
+ nice_match = Deflate.config_table[level].NiceLength;
+ _maxChainLength = Deflate.config_table[level].MaxChain;
+
+ _startInsertString = 0;
+ _blockStart = 0;
+ _validBytesAhead = 0;
+ _matchLength = _previousLength = MIN_MATCH - 1;
+ _matchAvailable = false;
+ _insertedHashIndex = 0;
+ }
+
+ // Initialize the tree data structures for a new zlib stream.
+ private void tr_init()
+ {
+
+ l_desc.Init(dyn_ltree, Deflate.static_l_desc);
+
+ d_desc.Init(dyn_dtree, Deflate.static_d_desc);
+
+ bl_desc.Init(bl_tree, Deflate.static_bl_desc);
+
+
+ bi_buf = 0;
+ bi_valid = 0;
+ last_eob_len = 8; // enough lookahead for inflate
+
+ // Initialize the first block of the first file:
+ init_block();
+ }
+
+ private void init_block()
+ {
+ // Initialize the trees.
+ for (int i = 0; i < L_CODES; i++) dyn_ltree[i * 2] = 0;
+ for (int i = 0; i < D_CODES; i++) dyn_dtree[i * 2] = 0;
+ for (int i = 0; i < BL_CODES; i++) bl_tree[i * 2] = 0;
+
+ dyn_ltree[END_BLOCK * 2] = 1;
+ opt_len = static_len = 0;
+ last_lit = matches = 0;
+ }
+
+ private static bool smaller(short[] tree, int n, int m, byte[] depth)
+ {
+ short tn2 = tree[n * 2];
+ short tm2 = tree[m * 2];
+ return (tn2 < tm2 ||
+ (tn2 == tm2 && depth[n] <= depth[m]));
+ }
+
+ // Scan a literal or distance tree to determine the frequencies of the codes
+ // in the bit length tree.
+ private void scan_tree(short[] tree,// the tree to be scanned
+ int max_code // and its largest code of non zero frequency
+ )
+ {
+ int n; // iterates over all tree elements
+ int prevlen = -1; // last emitted length
+ int curlen; // length of current code
+ int nextlen = tree[0 * 2 + 1]; // length of next code
+ int count = 0; // repeat count of the current code
+ int max_count = 7; // max repeat count
+ int min_count = 4; // min repeat count
+
+ if (nextlen == 0) { max_count = 138; min_count = 3; }
+ tree[(max_code + 1) * 2 + 1] = -1; // guard
+
+ for (n = 0; n <= max_code; n++)
+ {
+ curlen = nextlen; nextlen = tree[(n + 1) * 2 + 1];
+ if (++count < max_count && curlen == nextlen)
+ {
+ continue;
+ }
+ else if (count < min_count)
+ {
+ bl_tree[curlen * 2] += (short)count;
+ }
+ else if (curlen != 0)
+ {
+ if (curlen != prevlen) bl_tree[curlen * 2]++;
+ bl_tree[REP_3_6 * 2]++;
+ }
+ else if (count <= 10)
+ {
+ bl_tree[REPZ_3_10 * 2]++;
+ }
+ else
+ {
+ bl_tree[REPZ_11_138 * 2]++;
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0)
+ {
+ max_count = 138; min_count = 3;
+ }
+ else if (curlen == nextlen)
+ {
+ max_count = 6; min_count = 3;
+ }
+ else
+ {
+ max_count = 7; min_count = 4;
+ }
+ }
+ }
+
+ // Construct the Huffman tree for the bit lengths and return the index in
+ // bl_order of the last bit length code to send.
+ private int build_bl_tree()
+ {
+ int max_blindex; // index of last bit length code of non zero freq
+
+ // Determine the bit length frequencies for literal and distance trees
+ scan_tree(dyn_ltree, l_desc.LargestCode);
+ scan_tree(dyn_dtree, d_desc.LargestCode);
+
+ // Build the bit length tree:
+ bl_desc.BuildTree(this);
+ // opt_len now includes the length of the tree representations, except
+ // the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
+
+ // Determine the number of bit length codes to send. The pkzip format
+ // requires that at least 4 bit length codes be sent. (appnote.txt says
+ // 3 but the actual value used is 4.)
+ for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--)
+ {
+ if (bl_tree[Deflate.bl_order[max_blindex] * 2 + 1] != 0) break;
+ }
+ // Update opt_len to include the bit length tree and counts
+ opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4;
+
+ return max_blindex;
+ }
+
+
+ // Send the header for a block using dynamic Huffman trees: the counts, the
+ // lengths of the bit length codes, the literal tree and the distance tree.
+ // IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
+ private void send_all_trees(int lcodes, int dcodes, int blcodes)
+ {
+ int rank; // index in bl_order
+
+ send_bits(lcodes - 257, 5); // not +255 as stated in appnote.txt
+ send_bits(dcodes - 1, 5);
+ send_bits(blcodes - 4, 4); // not -3 as stated in appnote.txt
+ for (rank = 0; rank < blcodes; rank++)
+ {
+ send_bits(bl_tree[Deflate.bl_order[rank] * 2 + 1], 3);
+ }
+ send_tree(dyn_ltree, lcodes - 1); // literal tree
+ send_tree(dyn_dtree, dcodes - 1); // distance tree
+ }
+
+ // Send a literal or distance tree in compressed form, using the codes in
+ // bl_tree.
+ private void send_tree(short[] tree,// the tree to be sent
+ int max_code // and its largest code of non zero frequency
+ )
+ {
+ int n; // iterates over all tree elements
+ int prevlen = -1; // last emitted length
+ int curlen; // length of current code
+ int nextlen = tree[0 * 2 + 1]; // length of next code
+ int count = 0; // repeat count of the current code
+ int max_count = 7; // max repeat count
+ int min_count = 4; // min repeat count
+
+ if (nextlen == 0) { max_count = 138; min_count = 3; }
+
+ for (n = 0; n <= max_code; n++)
+ {
+ curlen = nextlen; nextlen = tree[(n + 1) * 2 + 1];
+ if (++count < max_count && curlen == nextlen)
+ {
+ continue;
+ }
+ else if (count < min_count)
+ {
+ do { send_code(curlen, bl_tree); } while (--count != 0);
+ }
+ else if (curlen != 0)
+ {
+ if (curlen != prevlen)
+ {
+ send_code(curlen, bl_tree); count--;
+ }
+ send_code(REP_3_6, bl_tree);
+ send_bits(count - 3, 2);
+ }
+ else if (count <= 10)
+ {
+ send_code(REPZ_3_10, bl_tree);
+ send_bits(count - 3, 3);
+ }
+ else
+ {
+ send_code(REPZ_11_138, bl_tree);
+ send_bits(count - 11, 7);
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0)
+ {
+ max_count = 138; min_count = 3;
+ }
+ else if (curlen == nextlen)
+ {
+ max_count = 6; min_count = 3;
+ }
+ else
+ {
+ max_count = 7; min_count = 4;
+ }
+ }
+ }
+
+ // Output a byte on the stream.
+ // IN assertion: there is enough room in pending_buf.
+ private void put_byte(byte[] p, int start, int len)
+ {
+ System.Array.Copy(p, start, pending_buf, pending, len);
+ pending += len;
+ }
+
+ private void put_byte(byte c)
+ {
+ pending_buf[pending++] = c;
+ }
+ private void put_short(int w)
+ {
+ pending_buf[pending++] = (byte)(w/*&0xff*/);
+ pending_buf[pending++] = (byte)(w >> 8);
+ }
+ private void putShortMSB(int b)
+ {
+ pending_buf[pending++] = (byte)(b >> 8);
+ pending_buf[pending++] = (byte)(b/*&0xff*/);
+ }
+
+ private void send_code(int c, short[] tree)
+ {
+ int c2 = c * 2;
+ send_bits((tree[c2] & 0xffff), (tree[c2 + 1] & 0xffff));
+ }
+
+ private void send_bits(int val, int length)
+ {
+ if (bi_valid > Buf_size - length)
+ {
+ bi_buf |= (uint)(val << bi_valid);
+ pending_buf[pending++] = (byte)(bi_buf/*&0xff*/);
+ pending_buf[pending++] = (byte)(bi_buf >> 8);
+ bi_buf = ((uint)val) >> (Buf_size - bi_valid);
+ bi_valid += length - Buf_size;
+ }
+ else
+ {
+ bi_buf |= (uint)(val << bi_valid);
+ bi_valid += length;
+ }
+ // int len = length;
+ // if (bi_valid > (int)Buf_size - len) {
+ // int val = value;
+ // // bi_buf |= (val << bi_valid);
+ // bi_buf = (short)((ushort)bi_buf | (ushort)((val << bi_valid)&0xffff));
+ // put_short(bi_buf);
+ // bi_buf = (short)(((uint)val) >> (Buf_size - bi_valid));
+ // bi_valid += len - Buf_size;
+ // } else {
+ // // bi_buf |= (value) << bi_valid;
+ // bi_buf = (short)((ushort)bi_buf | (ushort)(((value) << bi_valid)&0xffff));
+ // bi_valid += len;
+ // }
+ }
+
+ // Send one empty static block to give enough lookahead for inflate.
+ // This takes 10 bits, of which 7 may remain in the bit buffer.
+ // The current inflate code requires 9 bits of lookahead. If the
+ // last two codes for the previous block (real code plus EOB) were coded
+ // on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
+ // the last real code. In this case we send two empty static blocks instead
+ // of one. (There are no problems if the previous block is stored or fixed.)
+ // To simplify the code, we assume the worst case of last real code encoded
+ // on one bit only.
+ private void _tr_align()
+ {
+ send_bits(STATIC_TREES << 1, 3);
+ send_code(END_BLOCK, Deflate.static_ltree);
+
+ bi_flush();
+
+ // Of the 10 bits for the empty block, we have already sent
+ // (10 - bi_valid) bits. The lookahead for the last real code (before
+ // the EOB of the previous block) was thus at least one plus the length
+ // of the EOB plus what we have just sent of the empty static block.
+ if (1 + last_eob_len + 10 - bi_valid < 9)
+ {
+ send_bits(STATIC_TREES << 1, 3);
+ send_code(END_BLOCK, Deflate.static_ltree);
+ bi_flush();
+ }
+ last_eob_len = 7;
+ }
+
+
+ // Save the match info and tally the frequency counts. Return true if
+ // the current block must be flushed.
+ private bool _tr_tally(int dist, // distance of matched string
+ int lc // match length-MIN_MATCH or unmatched char (if dist==0)
+ )
+ {
+
+ pending_buf[d_buf + last_lit * 2] = (byte)(dist >> 8);
+ pending_buf[d_buf + last_lit * 2 + 1] = (byte)dist;
+
+ pending_buf[l_buf + last_lit] = (byte)lc; last_lit++;
+
+ if (dist == 0)
+ {
+ // lc is the unmatched char
+ dyn_ltree[lc * 2]++;
+ }
+ else
+ {
+ matches++;
+ // Here, lc is the match length - MIN_MATCH
+ dist--; // dist = match distance - 1
+ dyn_ltree[(Deflate._length_code[lc] + LITERALS + 1) * 2]++;
+ dyn_dtree[Tree.DistanceCode(dist) * 2]++;
+ }
+
+ if ((last_lit & 0x1fff) == 0 && level > (CompressionLevel)2)
+ {
+ // Compute an upper bound for the compressed length
+ int out_length = last_lit * 8;
+ int in_length = _startInsertString - _blockStart;
+ int dcode;
+ for (dcode = 0; dcode < D_CODES; dcode++)
+ {
+ out_length += (int)((int)dyn_dtree[dcode * 2] *
+ (5L + Deflate.extra_dbits[dcode]));
+ }
+ out_length >>= 3;
+ if ((matches < (last_lit / 2)) && out_length < in_length / 2) return true;
+ }
+
+ return (last_lit == lit_bufsize - 1);
+ // We avoid equality with lit_bufsize because of wraparound at 64K
+ // on 16 bit machines and because stored blocks are restricted to
+ // 64K-1 bytes.
+ }
+
+ // Send the block data compressed using the given Huffman trees
+ private void compress_block(short[] ltree, short[] dtree)
+ {
+ int dist; // distance of matched string
+ int lc; // match length or unmatched char (if dist == 0)
+ int lx = 0; // running index in l_buf
+ int code; // the code to send
+ int extra; // number of extra bits to send
+
+ if (last_lit != 0)
+ {
+ do
+ {
+ dist = ((pending_buf[d_buf + lx * 2] << 8) & 0xff00) |
+ (pending_buf[d_buf + lx * 2 + 1] & 0xff);
+ lc = (pending_buf[l_buf + lx]) & 0xff; lx++;
+
+ if (dist == 0)
+ {
+ send_code(lc, ltree); // send a literal byte
+ }
+ else
+ {
+ // Here, lc is the match length - MIN_MATCH
+ code = Deflate._length_code[lc];
+
+ send_code(code + LITERALS + 1, ltree); // send the length code
+ extra = Deflate.extra_lbits[code];
+ if (extra != 0)
+ {
+ lc -= Deflate.base_length[code];
+ send_bits(lc, extra); // send the extra length bits
+ }
+ dist--; // dist is now the match distance - 1
+ code = Tree.DistanceCode(dist);
+
+ send_code(code, dtree); // send the distance code
+ extra = Deflate.extra_dbits[code];
+ if (extra != 0)
+ {
+ dist -= Deflate.base_dist[code];
+ send_bits(dist, extra); // send the extra distance bits
+ }
+ } // literal or match pair ?
+
+ // Check that the overlay between pending_buf and d_buf+l_buf is ok:
+ }
+ while (lx < last_lit);
+ }
+
+ send_code(END_BLOCK, ltree);
+ last_eob_len = ltree[END_BLOCK * 2 + 1];
+ }
+
+ // Set the data type to ASCII or BINARY, using a crude approximation:
+ // binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise.
+ // IN assertion: the fields freq of dyn_ltree are set and the total of all
+ // frequencies does not exceed 64K (to fit in an int on 16 bit machines).
+ private void set_data_type()
+ {
+ int n = 0;
+ int ascii_freq = 0;
+ int bin_freq = 0;
+ while (n < 7) { bin_freq += dyn_ltree[n * 2]; n++; }
+ while (n < 128) { ascii_freq += dyn_ltree[n * 2]; n++; }
+ while (n < LITERALS) { bin_freq += dyn_ltree[n * 2]; n++; }
+ this._dataType = (bin_freq > (ascii_freq >> 2) ? BlockType.Z_BINARY : BlockType.Z_ASCII);
+ }
+
+ // Flush the bit buffer, keeping at most 7 bits in it.
+ private void bi_flush()
+ {
+ if (bi_valid == 16)
+ {
+ pending_buf[pending++] = (byte)(bi_buf/*&0xff*/);
+ pending_buf[pending++] = (byte)(bi_buf >> 8);
+ bi_buf = 0;
+ bi_valid = 0;
+ }
+ else if (bi_valid >= 8)
+ {
+ pending_buf[pending++] = (byte)(bi_buf);
+ bi_buf >>= 8;
+ bi_buf &= 0x00ff;
+ bi_valid -= 8;
+ }
+ }
+
+ // Flush the bit buffer and align the output on a byte boundary
+ private void bi_windup()
+ {
+ if (bi_valid > 8)
+ {
+ pending_buf[pending++] = (byte)(bi_buf);
+ pending_buf[pending++] = (byte)(bi_buf >> 8);
+ }
+ else if (bi_valid > 0)
+ {
+ pending_buf[pending++] = (byte)(bi_buf);
+ }
+ bi_buf = 0;
+ bi_valid = 0;
+ }
+
+ // Copy a stored block, storing first the length and its
+ // one's complement if requested.
+ private void copy_block(int buf, // the input data
+ int len, // its length
+ bool header // true if block header must be written
+ )
+ {
+ //int index=0;
+ bi_windup(); // align on byte boundary
+ last_eob_len = 8; // enough lookahead for inflate
+
+ if (header)
+ {
+ put_short((short)len);
+ put_short((short)~len);
+ }
+
+ // while(len--!=0) {
+ // put_byte(window[buf+index]);
+ // index++;
+ // }
+ put_byte(_window, buf, len);
+ }
+
+ private void flush_block_only(bool eof)
+ {
+ _tr_flush_block(_blockStart >= 0 ? _blockStart : -1,
+ _startInsertString - _blockStart,
+ eof);
+ _blockStart = _startInsertString;
+ this.flush_pending();
+ }
+
+ // Copy without compression as much as possible from the input stream, return
+ // the current block state.
+ // This function does not insert new strings in the dictionary since
+ // uncompressible data is probably not useful. This function is used
+ // only for the level=0 compression option.
+ // NOTE: this function should be optimized to avoid extra copying from
+ // window to pending_buf.
+ private int deflate_stored(FlushType flush)
+ {
+ // Stored blocks are limited to 0xffff bytes, pending_buf is limited
+ // to pending_buf_size, and each stored block has a 5 byte header:
+
+ int max_block_size = 0xffff;
+ int max_start;
+
+ if (max_block_size > _pendingBufferSize - 5)
+ {
+ max_block_size = _pendingBufferSize - 5;
+ }
+
+ // Copy as much as possible from input to output:
+ while (true)
+ {
+ // Fill the window as much as possible:
+ if (_validBytesAhead <= 1)
+ {
+ fill_window();
+ if (_validBytesAhead == 0 && flush == FlushType.Z_NO_FLUSH) return NeedMore;
+ if (_validBytesAhead == 0) break; // flush the current block
+ }
+
+ _startInsertString += _validBytesAhead;
+ _validBytesAhead = 0;
+
+ // Emit a stored block if pending_buf will be full:
+ max_start = _blockStart + max_block_size;
+ if (_startInsertString == 0 || _startInsertString >= max_start)
+ {
+ // strstart == 0 is possible when wraparound on 16-bit machine
+ _validBytesAhead = (int)(_startInsertString - max_start);
+ _startInsertString = (int)max_start;
+
+ flush_block_only(false);
+ if (base.avail_out == 0) return NeedMore;
+
+ }
+
+ // Flush if we may have to slide, otherwise block_start may become
+ // negative and the data will be gone:
+ if (_startInsertString - _blockStart >= _windowSize - MIN_LOOKAHEAD)
+ {
+ flush_block_only(false);
+ if (base.avail_out == 0) return NeedMore;
+ }
+ }
+
+ flush_block_only(flush == FlushType.Z_FINISH);
+ if (base.avail_out == 0)
+ return (flush == FlushType.Z_FINISH) ? FinishStarted : NeedMore;
+
+ return flush == FlushType.Z_FINISH ? FinishDone : BlockDone;
+ }
+
+ // Send a stored block
+ private void _tr_stored_block(int buf, // input block
+ int stored_len, // length of input block
+ bool eof // true if this is the last block for a file
+ )
+ {
+ send_bits((STORED_BLOCK << 1) + (eof ? 1 : 0), 3); // send block type
+ copy_block(buf, stored_len, true); // with header
+ }
+
+ // Determine the best encoding for the current block: dynamic trees, static
+ // trees or store, and output the encoded block to the zip file.
+ private void _tr_flush_block(int buf, // input block, or NULL if too old
+ int stored_len, // length of input block
+ bool eof // true if this is the last block for a file
+ )
+ {
+ int opt_lenb, static_lenb;// opt_len and static_len in bytes
+ int max_blindex = 0; // index of last bit length code of non zero freq
+
+ // Build the Huffman trees unless a stored block is forced
+ if (level > 0)
+ {
+ // Check if the file is ascii or binary
+ if (this._dataType == BlockType.Z_UNKNOWN) set_data_type();
+
+ // Construct the literal and distance trees
+ l_desc.BuildTree(this);
+
+ d_desc.BuildTree(this);
+
+ // At this point, opt_len and static_len are the total bit lengths of
+ // the compressed block data, excluding the tree representations.
+
+ // Build the bit length tree for the above two trees, and get the index
+ // in bl_order of the last bit length code to send.
+ max_blindex = build_bl_tree();
+
+ // Determine the best encoding. Compute first the block length in bytes
+ opt_lenb = (opt_len + 3 + 7) >> 3;
+ static_lenb = (static_len + 3 + 7) >> 3;
+
+ if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
+ }
+ else
+ {
+ opt_lenb = static_lenb = stored_len + 5; // force a stored block
+ }
+
+ if (stored_len + 4 <= opt_lenb && buf != -1)
+ {
+ // 4: two words for the lengths
+ // The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
+ // Otherwise we can't have processed more than WSIZE input bytes since
+ // the last block flush, because compression would have been
+ // successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
+ // transform a block into a stored block.
+ _tr_stored_block(buf, stored_len, eof);
+ }
+ else if (static_lenb == opt_lenb)
+ {
+ send_bits((STATIC_TREES << 1) + (eof ? 1 : 0), 3);
+ compress_block(Deflate.static_ltree, Deflate.static_dtree);
+ }
+ else
+ {
+ send_bits((DYN_TREES << 1) + (eof ? 1 : 0), 3);
+ send_all_trees(l_desc.LargestCode + 1, d_desc.LargestCode + 1, max_blindex + 1);
+ compress_block(dyn_ltree, dyn_dtree);
+ }
+
+ // The above check is made mod 2^32, for files larger than 512 MB
+ // and uLong implemented on 32 bits.
+
+ init_block();
+
+ if (eof)
+ {
+ bi_windup();
+ }
+ }
+
+ // Fill the window when the lookahead becomes insufficient.
+ // Updates strstart and lookahead.
+ //
+ // IN assertion: lookahead < MIN_LOOKAHEAD
+ // OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
+ // At least one byte has been read, or avail_in == 0; reads are
+ // performed for at least two bytes (required for the zip translate_eol
+ // option -- not supported here).
+ private void fill_window()
+ {
+ int n, m;
+ int p;
+ int more; // Amount of free space at the end of the window.
+
+ do
+ {
+ more = (_windowActualSize - _validBytesAhead - _startInsertString);
+
+ // Deal with !@#$% 64K limit:
+ if (more == 0 && _startInsertString == 0 && _validBytesAhead == 0)
+ {
+ more = _windowSize;
+ }
+ else if (more == -1)
+ {
+ // Very unlikely, but possible on 16 bit machine if strstart == 0
+ // and lookahead == 1 (input done one byte at time)
+ more--;
+
+ // If the window is almost full and there is insufficient lookahead,
+ // move the upper half to the lower one to make room in the upper half.
+ }
+ else if (_startInsertString >= _windowSize + _windowSize - MIN_LOOKAHEAD)
+ {
+ System.Array.Copy(_window, _windowSize, _window, 0, _windowSize);
+ _startMatchString -= _windowSize;
+ _startInsertString -= _windowSize; // we now have strstart >= MAX_DIST
+ _blockStart -= _windowSize;
+
+ // Slide the hash table (could be avoided with 32 bit values
+ // at the expense of memory usage). We slide even when level == 0
+ // to keep the hash table consistent if we switch back to level > 0
+ // later. (Using level 0 permanently is not an optimal usage of
+ // zlib, so we don't care about this pathological case.)
+
+ n = _hashSize;
+ p = n;
+ do
+ {
+ m = (_head[--p] & 0xffff);
+ _head[p] = (short)(m >= _windowSize ? (m - _windowSize) : 0);
+ }
+ while (--n != 0);
+
+ n = _windowSize;
+ p = n;
+ do
+ {
+ m = (_previous[--p] & 0xffff);
+ _previous[p] = (short)(m >= _windowSize ? (m - _windowSize) : 0);
+ // If n is not on any hash chain, prev[n] is garbage but
+ // its value will never be used.
+ }
+ while (--n != 0);
+ more += _windowSize;
+ }
+
+ if (base.avail_in == 0) return;
+
+ // If there was no sliding:
+ // strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
+ // more == window_size - lookahead - strstart
+ // => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
+ // => more >= window_size - 2*WSIZE + 2
+ // In the BIG_MEM or MMAP case (not yet supported),
+ // window_size == input_size + MIN_LOOKAHEAD &&
+ // strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
+ // Otherwise, window_size == 2*WSIZE so more >= 2.
+ // If there was sliding, more >= WSIZE. So in all cases, more >= 2.
+
+ n = this.read_buf(_window, _startInsertString + _validBytesAhead, more);
+ _validBytesAhead += n;
+
+ // Initialize the hash value now that we have some input:
+ if (_validBytesAhead >= MIN_MATCH)
+ {
+ _insertedHashIndex = _window[_startInsertString] & 0xff;
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[_startInsertString + 1] & 0xff)) & _hashMask;
+ }
+ // If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
+ // but this is not important since only literal bytes will be emitted.
+ }
+ while (_validBytesAhead < MIN_LOOKAHEAD && base.avail_in != 0);
+ }
+
+ // Compress as much as possible from the input stream, return the current
+ // block state.
+ // This function does not perform lazy evaluation of matches and inserts
+ // new strings in the dictionary only for unmatched strings or for short
+ // matches. It is used only for the fast compression options.
+ private int deflate_fast(FlushType flush)
+ {
+ // short hash_head = 0; // head of the hash chain
+ int hash_head = 0; // head of the hash chain
+ bool bflush; // set if current block must be flushed
+
+ while (true)
+ {
+ // Make sure that we always have enough lookahead, except
+ // at the end of the input file. We need MAX_MATCH bytes
+ // for the next match, plus MIN_MATCH bytes to insert the
+ // string following the next match.
+ if (_validBytesAhead < MIN_LOOKAHEAD)
+ {
+ fill_window();
+ if (_validBytesAhead < MIN_LOOKAHEAD && flush == FlushType.Z_NO_FLUSH)
+ {
+ return NeedMore;
+ }
+ if (_validBytesAhead == 0) break; // flush the current block
+ }
+
+ // Insert the string window[strstart .. strstart+2] in the
+ // dictionary, and set hash_head to the head of the hash chain:
+ if (_validBytesAhead >= MIN_MATCH)
+ {
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[(_startInsertString) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+
+ // prev[strstart&w_mask]=hash_head=head[ins_h];
+ hash_head = (_head[_insertedHashIndex] & 0xffff);
+ _previous[_startInsertString & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)_startInsertString;
+ }
+
+ // Find the longest match, discarding those <= prev_length.
+ // At this point we have always match_length < MIN_MATCH
+
+ if (hash_head != 0L &&
+ ((_startInsertString - hash_head) & 0xffff) <= _windowSize - MIN_LOOKAHEAD
+ )
+ {
+ // To simplify the code, we prevent matches with the string
+ // of window index 0 (in particular we have to avoid a match
+ // of the string with itself at the start of the input file).
+ if (strategy != CompressionStrategy.Z_HUFFMAN_ONLY)
+ {
+ _matchLength = longest_match(hash_head);
+ }
+ // longest_match() sets match_start
+ }
+ if (_matchLength >= MIN_MATCH)
+ {
+ // check_match(strstart, match_start, match_length);
+
+ bflush = _tr_tally(_startInsertString - _startMatchString, _matchLength - MIN_MATCH);
+
+ _validBytesAhead -= _matchLength;
+
+ // Insert new strings in the hash table only if the match length
+ // is not too large. This saves time but degrades compression.
+ if (_matchLength <= _maxLazyMatch &&
+ _validBytesAhead >= MIN_MATCH)
+ {
+ _matchLength--; // string at strstart already in hash table
+ do
+ {
+ _startInsertString++;
+
+ _insertedHashIndex = ((_insertedHashIndex << _hashShift) ^ (_window[(_startInsertString) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+ // prev[strstart&w_mask]=hash_head=head[ins_h];
+ hash_head = (_head[_insertedHashIndex] & 0xffff);
+ _previous[_startInsertString & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)_startInsertString;
+
+ // strstart never exceeds WSIZE-MAX_MATCH, so there are
+ // always MIN_MATCH bytes ahead.
+ }
+ while (--_matchLength != 0);
+ _startInsertString++;
+ }
+ else
+ {
+ _startInsertString += _matchLength;
+ _matchLength = 0;
+ _insertedHashIndex = _window[_startInsertString] & 0xff;
+
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[_startInsertString + 1] & 0xff)) & _hashMask;
+ // If lookahead < MIN_MATCH, ins_h is garbage, but it does not
+ // matter since it will be recomputed at next deflate call.
+ }
+ }
+ else
+ {
+ // No match, output a literal byte
+
+ bflush = _tr_tally(0, _window[_startInsertString] & 0xff);
+ _validBytesAhead--;
+ _startInsertString++;
+ }
+ if (bflush)
+ {
+
+ flush_block_only(false);
+ if (base.avail_out == 0) return NeedMore;
+ }
+ }
+
+ flush_block_only(flush == FlushType.Z_FINISH);
+ if (base.avail_out == 0)
+ {
+ if (flush == FlushType.Z_FINISH) return FinishStarted;
+ else return NeedMore;
+ }
+ return flush == FlushType.Z_FINISH ? FinishDone : BlockDone;
+ }
+
+ // Same as above, but achieves better compression. We use a lazy
+ // evaluation for matches: a match is finally adopted only if there is
+ // no better match at the next window position.
+ private int deflate_slow(FlushType flush)
+ {
+ // short hash_head = 0; // head of hash chain
+ int hash_head = 0; // head of hash chain
+ bool bflush; // set if current block must be flushed
+
+ // Process the input block.
+ while (true)
+ {
+ // Make sure that we always have enough lookahead, except
+ // at the end of the input file. We need MAX_MATCH bytes
+ // for the next match, plus MIN_MATCH bytes to insert the
+ // string following the next match.
+
+ if (_validBytesAhead < MIN_LOOKAHEAD)
+ {
+ fill_window();
+ if (_validBytesAhead < MIN_LOOKAHEAD && flush == FlushType.Z_NO_FLUSH)
+ {
+ return NeedMore;
+ }
+ if (_validBytesAhead == 0) break; // flush the current block
+ }
+
+ // Insert the string window[strstart .. strstart+2] in the
+ // dictionary, and set hash_head to the head of the hash chain:
+
+ if (_validBytesAhead >= MIN_MATCH)
+ {
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[(_startInsertString) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+ // prev[strstart&w_mask]=hash_head=head[ins_h];
+ hash_head = (_head[_insertedHashIndex] & 0xffff);
+ _previous[_startInsertString & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)_startInsertString;
+ }
+
+ // Find the longest match, discarding those <= prev_length.
+ _previousLength = _matchLength; _previousMatch = _startMatchString;
+ _matchLength = MIN_MATCH - 1;
+
+ if (hash_head != 0 && _previousLength < _maxLazyMatch &&
+ ((_startInsertString - hash_head) & 0xffff) <= _windowSize - MIN_LOOKAHEAD
+ )
+ {
+ // To simplify the code, we prevent matches with the string
+ // of window index 0 (in particular we have to avoid a match
+ // of the string with itself at the start of the input file).
+
+ if (strategy != CompressionStrategy.Z_HUFFMAN_ONLY)
+ {
+ _matchLength = longest_match(hash_head);
+ }
+ // longest_match() sets match_start
+
+ if (_matchLength <= 5 && (strategy == CompressionStrategy.Z_FILTERED ||
+ (_matchLength == MIN_MATCH &&
+ _startInsertString - _startMatchString > 4096)))
+ {
+
+ // If prev_match is also MIN_MATCH, match_start is garbage
+ // but we will ignore the current match anyway.
+ _matchLength = MIN_MATCH - 1;
+ }
+ }
+
+ // If there was a match at the previous step and the current
+ // match is not better, output the previous match:
+ if (_previousLength >= MIN_MATCH && _matchLength <= _previousLength)
+ {
+ int max_insert = _startInsertString + _validBytesAhead - MIN_MATCH;
+ // Do not insert strings in hash table beyond this.
+
+ // check_match(strstart-1, prev_match, prev_length);
+
+ bflush = _tr_tally(_startInsertString - 1 - _previousMatch, _previousLength - MIN_MATCH);
+
+ // Insert in hash table all strings up to the end of the match.
+ // strstart-1 and strstart are already inserted. If there is not
+ // enough lookahead, the last two strings are not inserted in
+ // the hash table.
+ _validBytesAhead -= _previousLength - 1;
+ _previousLength -= 2;
+ do
+ {
+ if (++_startInsertString <= max_insert)
+ {
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[(_startInsertString) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+ //prev[strstart&w_mask]=hash_head=head[ins_h];
+ hash_head = (_head[_insertedHashIndex] & 0xffff);
+ _previous[_startInsertString & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)_startInsertString;
+ }
+ }
+ while (--_previousLength != 0);
+ _matchAvailable = false;
+ _matchLength = MIN_MATCH - 1;
+ _startInsertString++;
+
+ if (bflush)
+ {
+ flush_block_only(false);
+ if (base.avail_out == 0) return NeedMore;
+ }
+ }
+ else if (_matchAvailable != false)
+ {
+
+ // If there was no match at the previous position, output a
+ // single literal. If there was a match but the current match
+ // is longer, truncate the previous match to a single literal.
+
+ bflush = _tr_tally(0, _window[_startInsertString - 1] & 0xff);
+
+ if (bflush)
+ {
+ flush_block_only(false);
+ }
+ _startInsertString++;
+ _validBytesAhead--;
+ if (base.avail_out == 0) return NeedMore;
+ }
+ else
+ {
+ // There is no previous match to compare with, wait for
+ // the next step to decide.
+
+ _matchAvailable = true;
+ _startInsertString++;
+ _validBytesAhead--;
+ }
+ }
+
+ if (_matchAvailable != false)
+ {
+ bflush = _tr_tally(0, _window[_startInsertString - 1] & 0xff);
+ _matchAvailable = false;
+ }
+ flush_block_only(flush == FlushType.Z_FINISH);
+
+ if (base.avail_out == 0)
+ {
+ if (flush == FlushType.Z_FINISH) return FinishStarted;
+ else return NeedMore;
+ }
+
+ return flush == FlushType.Z_FINISH ? FinishDone : BlockDone;
+ }
+
+ private int longest_match(int cur_match)
+ {
+ int chain_length = _maxChainLength; // max hash chain length
+ int scan = _startInsertString; // current string
+ int match; // matched string
+ int len; // length of current match
+ int best_len = _previousLength; // best match length so far
+ int limit = _startInsertString > (_windowSize - MIN_LOOKAHEAD) ?
+ _startInsertString - (_windowSize - MIN_LOOKAHEAD) : 0;
+ int nice_match = this.nice_match;
+
+ // Stop when cur_match becomes <= limit. To simplify the code,
+ // we prevent matches with the string of window index 0.
+
+ int wmask = _windowMask;
+
+ int strend = _startInsertString + MAX_MATCH;
+ byte scan_end1 = _window[scan + best_len - 1];
+ byte scan_end = _window[scan + best_len];
+
+ // The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+ // It is easy to get rid of this optimization if necessary.
+
+ // Do not waste too much time if we already have a good match:
+ if (_previousLength >= good_match)
+ {
+ chain_length >>= 2;
+ }
+
+ // Do not look for matches beyond the end of the input. This is necessary
+ // to make deflate deterministic.
+ if (nice_match > _validBytesAhead) nice_match = _validBytesAhead;
+
+ do
+ {
+ match = cur_match;
+
+ // Skip to next match if the match length cannot increase
+ // or if the match length is less than 2:
+ if (_window[match + best_len] != scan_end ||
+ _window[match + best_len - 1] != scan_end1 ||
+ _window[match] != _window[scan] ||
+ _window[++match] != _window[scan + 1]) continue;
+
+ // The check at best_len-1 can be removed because it will be made
+ // again later. (This heuristic is not always a win.)
+ // It is not necessary to compare scan[2] and match[2] since they
+ // are always equal when the other bytes match, given that
+ // the hash keys are equal and that HASH_BITS >= 8.
+ scan += 2; match++;
+
+ // We check for insufficient lookahead only every 8th comparison;
+ // the 256th check will be made at strstart+258.
+ do
+ {
+ } while (_window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ scan < strend);
+
+ len = MAX_MATCH - (int)(strend - scan);
+ scan = strend - MAX_MATCH;
+
+ if (len > best_len)
+ {
+ _startMatchString = cur_match;
+ best_len = len;
+ if (len >= nice_match) break;
+ scan_end1 = _window[scan + best_len - 1];
+ scan_end = _window[scan + best_len];
+ }
+
+ } while ((cur_match = (_previous[cur_match & wmask] & 0xffff)) > limit
+ && --chain_length != 0);
+
+ if (best_len <= _validBytesAhead) return best_len;
+ return _validBytesAhead;
+ }
+
+ public ZLibStatus deflate(FlushType flush)
+ {
+ FlushType old_flush;
+
+ if (flush > FlushType.Z_FINISH || flush < 0)
+ {
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+
+ if (base.next_out == null ||
+ (base.next_in == null && base.avail_in != 0) ||
+ (_status == FINISH_STATE && flush != FlushType.Z_FINISH))
+ {
+ base.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_STREAM_ERROR)];
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+ if (base.avail_out == 0)
+ {
+ base.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_BUF_ERROR)];
+ return ZLibStatus.Z_BUF_ERROR;
+ }
+
+ old_flush = last_flush;
+ last_flush = flush;
+
+ // Write the zlib header
+ if (_status == INIT_STATE)
+ {
+ int header = (Z_DEFLATED + ((this._windowBits - 8) << 4)) << 8;
+ int level_flags = (((int)this.level - 1) & 0xff) >> 1;
+
+ if (level_flags > 3) level_flags = 3;
+ header |= (level_flags << 6);
+ if (this._startInsertString != 0) header |= PRESET_DICT;
+ header += 31 - (header % 31);
+
+ _status = BUSY_STATE;
+ putShortMSB(header);
+
+
+ // Save the adler32 of the preset dictionary:
+ if (this._startInsertString != 0)
+ {
+ putShortMSB((int)(base.adler >> 16));
+ putShortMSB((int)(base.adler & 0xffff));
+ }
+ base.adler = Adler32.adler32(0, null, 0, 0);
+ }
+
+ // Flush as much pending output as possible
+ if (pending != 0)
+ {
+ this.flush_pending();
+ if (base.avail_out == 0)
+ {
+ //System.out.println(" avail_out==0");
+ // Since avail_out is 0, deflate will be called again with
+ // more output space, but possibly with both pending and
+ // avail_in equal to zero. There won't be anything to do,
+ // but this is not an error situation so make sure we
+ // return OK instead of BUF_ERROR at next call of deflate:
+ last_flush = (FlushType)(-1);
+ return ZLibStatus.Z_OK;
+ }
+
+ // Make sure there is something to do and avoid duplicate consecutive
+ // flushes. For repeated and useless calls with Z_FINISH, we keep
+ // returning Z_STREAM_END instead of Z_BUFF_ERROR.
+ }
+ else if (base.avail_in == 0 && flush <= old_flush &&
+ flush != FlushType.Z_FINISH)
+ {
+ base.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_BUF_ERROR)];
+ return ZLibStatus.Z_BUF_ERROR;
+ }
+
+ // User must not provide more input after the first FINISH:
+ if (_status == FINISH_STATE && base.avail_in != 0)
+ {
+ base.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_BUF_ERROR)];
+ return ZLibStatus.Z_BUF_ERROR;
+ }
+
+ // Start a new block or continue the current one.
+ if (base.avail_in != 0 || this._validBytesAhead != 0 ||
+ (flush != FlushType.Z_NO_FLUSH && _status != FINISH_STATE))
+ {
+ int bstate = -1;
+ switch (config_table[level].Function)
+ {
+ case DefalteFlavor.STORED:
+ bstate = deflate_stored(flush);
+ break;
+ case DefalteFlavor.FAST:
+ bstate = deflate_fast(flush);
+ break;
+ case DefalteFlavor.SLOW:
+ bstate = deflate_slow(flush);
+ break;
+ default:
+ break;
+ }
+
+ if (bstate == FinishStarted || bstate == FinishDone)
+ {
+ _status = FINISH_STATE;
+ }
+ if (bstate == NeedMore || bstate == FinishStarted)
+ {
+ if (base.avail_out == 0)
+ {
+ last_flush = (FlushType)(-1); // avoid BUF_ERROR next call, see above
+ }
+ return ZLibStatus.Z_OK;
+ // If flush != Z_NO_FLUSH && avail_out == 0, the next call
+ // of deflate should use the same flush parameter to make sure
+ // that the flush is complete. So we don't have to output an
+ // empty block here, this will be done at next call. This also
+ // ensures that for a very small output buffer, we emit at most
+ // one empty block.
+ }
+
+ if (bstate == BlockDone)
+ {
+ if (flush == FlushType.Z_PARTIAL_FLUSH)
+ {
+ _tr_align();
+ }
+ else
+ { // FULL_FLUSH or SYNC_FLUSH
+ _tr_stored_block(0, 0, false);
+ // For a full flush, this empty block will be recognized
+ // as a special marker by inflate_sync().
+ if (flush == FlushType.Z_FULL_FLUSH)
+ {
+ //state.head[s.hash_size-1]=0;
+ for (int i = 0; i < this._hashSize/*-1*/; i++) // forget history
+ this._head[i] = 0;
+ }
+ }
+ this.flush_pending();
+ if (base.avail_out == 0)
+ {
+ last_flush = (FlushType)(-1); // avoid BUF_ERROR at next call, see above
+ return ZLibStatus.Z_OK;
+ }
+ }
+ }
+
+ if (flush != FlushType.Z_FINISH) return ZLibStatus.Z_OK;
+ if (noheader != 0) return ZLibStatus.Z_STREAM_END;
+
+ // Write the zlib trailer (adler32)
+ putShortMSB((int)(base.adler >> 16));
+ putShortMSB((int)(base.adler & 0xffff));
+ this.flush_pending();
+
+ // If avail_out is zero, the application will call deflate again
+ // to flush the rest.
+ noheader = -1; // write the trailer only once!
+ return pending != 0 ? ZLibStatus.Z_OK : ZLibStatus.Z_STREAM_END;
+ }
+
+
+ private static readonly StaticTree static_l_desc = new StaticTree(static_ltree, Deflate.extra_lbits, LITERALS + 1, L_CODES, MAX_BITS);
+
+ private static readonly StaticTree static_d_desc = new StaticTree(static_dtree, Deflate.extra_dbits, 0, D_CODES, MAX_BITS);
+
+ private static readonly StaticTree static_bl_desc = new StaticTree(null, Deflate.extra_blbits, 0, BL_CODES, MAX_BL_BITS);
+
+ private class Config
+ {
+ ///
+ /// Reduce lazy search above this match length
+ ///
+ internal int GoodLength { get; private set; }
+ ///
+ /// Gets or sets whether not to perform lazy search above this match length
+ ///
+ ///
+ /// The max lazy.
+ ///
+ internal int MaxLazy { get; private set; }
+ ///
+ /// Gets or sets whether to quit search above this match length
+ ///
+ ///
+ /// The length of the nice.
+ ///
+ internal int NiceLength { get; private set; }
+ internal int MaxChain { get; private set; }
+ internal DefalteFlavor Function { get; private set; }
+ internal Config(int goodLength, int maxLazy, int niceLength, int maxChain, DefalteFlavor function)
+ {
+ this.GoodLength = goodLength;
+ this.MaxLazy = maxLazy;
+ this.NiceLength = niceLength;
+ this.MaxChain = maxChain;
+ this.Function = function;
+ }
+ }
+
+
+ // Flush as much pending output as possible. All deflate() output goes
+ // through this function so some applications may wish to modify it
+ // to avoid allocating a large strm->next_out buffer and copying into it.
+ // (See also read_buf()).
+ internal void flush_pending()
+ {
+ int len = this.pending;
+
+ if (len > avail_out) len = avail_out;
+ if (len == 0) return;
+
+ if (this.pending_buf.Length <= this.pending_out ||
+ next_out.Length <= next_out_index ||
+ this.pending_buf.Length < (this.pending_out + len) ||
+ next_out.Length < (next_out_index + len))
+ {
+ // System.out.println(this.pending_buf.length+", "+this.pending_out+
+ // ", "+next_out.length+", "+next_out_index+", "+len);
+ // System.out.println("avail_out="+avail_out);
+ }
+
+ System.Array.Copy(this.pending_buf, this.pending_out,
+ next_out, next_out_index, len);
+
+ next_out_index += len;
+ this.pending_out += len;
+ total_out += len;
+ avail_out -= len;
+ this.pending -= len;
+ if (this.pending == 0)
+ {
+ this.pending_out = 0;
+ }
+ }
+
+ // Read a new buffer from the current input stream, update the adler32
+ // and total number of bytes read. All deflate() input goes through
+ // this function so some applications may wish to modify it to avoid
+ // allocating a large strm->next_in buffer and copying from it.
+ // (See also flush_pending()).
+ internal int read_buf(byte[] buf, int start, int size)
+ {
+ int len = avail_in;
+
+ if (len > size) len = size;
+ if (len == 0) return 0;
+
+ avail_in -= len;
+
+ if (this.noheader == 0)
+ {
+ adler = Adler32.adler32(adler, next_in, next_in_index, len);
+ }
+ System.Array.Copy(next_in, next_in_index, buf, start, len);
+ next_in_index += len;
+ total_in += len;
+ return len;
+ }
+
+ public ZLibStatus deflate(byte[] inputBufer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType)
+ {
+ this.next_in = inputBufer;
+ this.next_in_index = inputOffset;
+ this.avail_in = inputCount;
+ this.next_out = outputBuffer;
+ this.next_out_index = outputOffset;
+ this.avail_out = outputCount;
+ return this.deflate(flushType);
+ }
+
+ public ZLibStatus deflate(byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType)
+ {
+ this.next_out = outputBuffer;
+ this.next_out_index = outputOffset;
+ this.avail_out = outputCount;
+ return this.deflate(flushType);
+ }
+
+
+ // TODO: Delete this
+ public ZLibStatus inflateEnd()
+ {
+ throw new NotImplementedException();
+ }
+
+ public ZLibStatus inflate(byte[] bufer, int offset, int count, byte[] p1, int p2, int p3, FlushType flushType)
+ {
+ throw new NotImplementedException();
+ }
+
+ public ZLibStatus inflate(byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v11/Inflate.cs b/Renci.SshNet/Compression/v11/Inflate.cs
new file mode 100644
index 0000000..c05e2d8
--- /dev/null
+++ b/Renci.SshNet/Compression/v11/Inflate.cs
@@ -0,0 +1,524 @@
+using System;
+/*
+ * $Id: Inflate.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public enum InflateMode : int
+ {
+ ///
+ ///waiting for method byte
+ ///
+ METHOD = 0,
+ ///
+ /// waiting for flag byte
+ ///
+ FLAG = 1,
+ ///
+ /// four dictionary check bytes to go
+ ///
+ DICT4 = 2,
+ ///
+ /// three dictionary check bytes to go
+ ///
+ DICT3 = 3,
+ ///
+ /// two dictionary check bytes to go
+ ///
+ DICT2 = 4,
+ ///
+ /// one dictionary check byte to go
+ ///
+ DICT1 = 5,
+ ///
+ /// waiting for inflateSetDictionary
+ ///
+ DICT0 = 6,
+ ///
+ /// decompressing blocks
+ ///
+ BLOCKS = 7,
+ ///
+ /// four check bytes to go
+ ///
+ CHECK4 = 8,
+ ///
+ /// three check bytes to go
+ ///
+ CHECK3 = 9,
+ ///
+ /// two check bytes to go
+ ///
+ CHECK2 = 10,
+ ///
+ /// one check byte to go
+ ///
+ CHECK1 = 11,
+ ///
+ /// finished check, done
+ ///
+ DONE = 12,
+ ///
+ /// got an error--stay here
+ ///
+ BAD = 13
+ }
+
+ internal sealed class Inflate : ZStream, ICompressor
+ {
+ // preset dictionary flag in zlib header
+ private const int PRESET_DICT = 0x20;
+
+ private const int Z_DEFLATED = 8;
+
+ private static readonly byte[] mark = { (byte)0, (byte)0, (byte)0xff, (byte)0xff };
+
+ ///
+ /// The current inflate mode
+ ///
+ private InflateMode _mode;
+
+ ///
+ /// if FLAGS, method byte
+ ///
+ private int method;
+
+ ///
+ /// Computed check value
+ ///
+ private long[] _was = new long[1];
+
+ ///
+ /// The stream check value
+ ///
+ private long _need;
+
+ ///
+ /// if BAD, inflateSync's marker bytes count
+ ///
+ private int _marker;
+
+ // mode independent information
+ ///
+ /// Flag for no wrapper
+ ///
+ private int _nowrap;
+
+ ///
+ /// log2(window size) (8..15, defaults to 15)
+ ///
+ private int _wbits;
+
+ ///
+ /// Current inflate_blocks state
+ ///
+ private InflateBlocks _blocks;
+
+ public Inflate()
+ {
+ this.inflateInit();
+ }
+
+ public Inflate(bool nowrap)
+ {
+ this.inflateInit(nowrap);
+ }
+
+ private ZLibStatus InflateReset()
+ {
+ base.total_in = base.total_out = 0;
+ base.msg = null;
+ this._mode = this._nowrap != 0 ? InflateMode.BLOCKS : InflateMode.METHOD;
+ this._blocks.reset(this, null);
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus InflateEnd()
+ {
+ if (_blocks != null)
+ _blocks.free(this);
+ _blocks = null;
+ // ZFREE(z, z->state);
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus InflateInit(int w)
+ {
+ base.msg = null;
+ _blocks = null;
+
+ // handle undocumented nowrap option (no zlib header or check)
+ _nowrap = 0;
+ if (w < 0)
+ {
+ w = -w;
+ _nowrap = 1;
+ }
+
+ // set window size
+ if (w < 8 || w > 15)
+ {
+ InflateEnd();
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+ _wbits = w;
+
+ this._blocks = new InflateBlocks(this, this._nowrap != 0 ? null : this, 1 << w);
+
+ // reset state
+ InflateReset();
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus inflate(FlushType ff)
+ {
+ ZLibStatus r;
+ int b;
+
+ if (base.next_in == null)
+ return ZLibStatus.Z_STREAM_ERROR;
+ var f = ff == FlushType.Z_FINISH ? ZLibStatus.Z_BUF_ERROR : ZLibStatus.Z_OK;
+ r = ZLibStatus.Z_BUF_ERROR;
+ while (true)
+ {
+ //System.out.println("mode: "+this.mode);
+ switch (this._mode)
+ {
+ case InflateMode.METHOD:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ if (((this.method = base.next_in[base.next_in_index++]) & 0xf) != Z_DEFLATED)
+ {
+ this._mode = InflateMode.BAD;
+ base.msg = "unknown compression method";
+ this._marker = 5; // can't try inflateSync
+ break;
+ }
+ if ((this.method >> 4) + 8 > this._wbits)
+ {
+ this._mode = InflateMode.BAD;
+ base.msg = "invalid window size";
+ this._marker = 5; // can't try inflateSync
+ break;
+ }
+ this._mode = InflateMode.FLAG;
+ goto case InflateMode.FLAG;
+ case InflateMode.FLAG:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ b = (base.next_in[base.next_in_index++]) & 0xff;
+
+ if ((((this.method << 8) + b) % 31) != 0)
+ {
+ this._mode = InflateMode.BAD;
+ base.msg = "incorrect header check";
+ this._marker = 5; // can't try inflateSync
+ break;
+ }
+
+ if ((b & PRESET_DICT) == 0)
+ {
+ this._mode = InflateMode.BLOCKS;
+ break;
+ }
+ this._mode = InflateMode.DICT4;
+ goto case InflateMode.DICT4;
+ case InflateMode.DICT4:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need = ((base.next_in[base.next_in_index++] & 0xff) << 24) & 0xff000000L;
+ this._mode = InflateMode.DICT3;
+ goto case InflateMode.DICT3;
+ case InflateMode.DICT3:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += ((base.next_in[base.next_in_index++] & 0xff) << 16) & 0xff0000L;
+ this._mode = InflateMode.DICT2;
+ goto case InflateMode.DICT2;
+ case InflateMode.DICT2:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += ((base.next_in[base.next_in_index++] & 0xff) << 8) & 0xff00L;
+ this._mode = InflateMode.DICT1;
+ goto case InflateMode.DICT1;
+ case InflateMode.DICT1:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += (base.next_in[base.next_in_index++] & 0xffL);
+ base.adler = this._need;
+ this._mode = InflateMode.DICT0;
+ return ZLibStatus.Z_NEED_DICT;
+ case InflateMode.DICT0:
+ this._mode = InflateMode.BAD;
+ base.msg = "need dictionary";
+ this._marker = 0; // can try inflateSync
+ return ZLibStatus.Z_STREAM_ERROR;
+ case InflateMode.BLOCKS:
+
+ r = this._blocks.proc(this, r);
+ if (r == ZLibStatus.Z_DATA_ERROR)
+ {
+ this._mode = InflateMode.BAD;
+ this._marker = 0; // can try inflateSync
+ break;
+ }
+ if (r == ZLibStatus.Z_OK)
+ {
+ r = f;
+ }
+ if (r != ZLibStatus.Z_STREAM_END)
+ {
+ return r;
+ }
+ r = f;
+ this._blocks.reset(this, this._was);
+ if (this._nowrap != 0)
+ {
+ this._mode = InflateMode.DONE;
+ break;
+ }
+ this._mode = InflateMode.CHECK4;
+ goto case InflateMode.CHECK4;
+ case InflateMode.CHECK4:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need = ((base.next_in[base.next_in_index++] & 0xff) << 24) & 0xff000000L;
+ this._mode = InflateMode.CHECK3;
+ goto case InflateMode.CHECK3;
+ case InflateMode.CHECK3:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += ((base.next_in[base.next_in_index++] & 0xff) << 16) & 0xff0000L;
+ this._mode = InflateMode.CHECK2;
+ goto case InflateMode.CHECK2;
+ case InflateMode.CHECK2:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += ((base.next_in[base.next_in_index++] & 0xff) << 8) & 0xff00L;
+ this._mode = InflateMode.CHECK1;
+ goto case InflateMode.CHECK1;
+ case InflateMode.CHECK1:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += (base.next_in[base.next_in_index++] & 0xffL);
+
+ if (((int)(this._was[0])) != ((int)(this._need)))
+ {
+ this._mode = InflateMode.BAD;
+ base.msg = "incorrect data check";
+ this._marker = 5; // can't try inflateSync
+ break;
+ }
+
+ this._mode = InflateMode.DONE;
+ goto case InflateMode.DONE;
+ case InflateMode.DONE:
+ return ZLibStatus.Z_STREAM_END;
+ case InflateMode.BAD:
+ return ZLibStatus.Z_DATA_ERROR;
+ default:
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+ }
+ }
+
+ public ZLibStatus InflateSetDictionary(byte[] dictionary, int dictLength)
+ {
+ int index = 0;
+ int length = dictLength;
+ if (this._mode != InflateMode.DICT0)
+ return ZLibStatus.Z_STREAM_ERROR;
+
+ if (Adler32.adler32(1L, dictionary, 0, dictLength) != base.adler)
+ {
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+
+ base.adler = Adler32.adler32(0, null, 0, 0);
+
+ if (length >= (1 << this._wbits))
+ {
+ length = (1 << this._wbits) - 1;
+ index = dictLength - length;
+ }
+ this._blocks.set_dictionary(dictionary, index, length);
+ this._mode = InflateMode.BLOCKS;
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus InflateSync()
+ {
+ int n; // number of bytes to look at
+ int p; // pointer to bytes
+ int m; // number of marker bytes found in a row
+ long r, w; // temporaries to save total_in and total_out
+
+ // set up
+ if (this._mode != InflateMode.BAD)
+ {
+ this._mode = InflateMode.BAD;
+ this._marker = 0;
+ }
+ if ((n = base.avail_in) == 0)
+ return ZLibStatus.Z_BUF_ERROR;
+ p = base.next_in_index;
+ m = this._marker;
+
+ // search
+ while (n != 0 && m < 4)
+ {
+ if (base.next_in[p] == mark[m])
+ {
+ m++;
+ }
+ else if (base.next_in[p] != 0)
+ {
+ m = 0;
+ }
+ else
+ {
+ m = 4 - m;
+ }
+ p++; n--;
+ }
+
+ // restore
+ base.total_in += p - base.next_in_index;
+ base.next_in_index = p;
+ base.avail_in = n;
+ this._marker = m;
+
+ // return no joy or set up to restart on a new block
+ if (m != 4)
+ {
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ r = base.total_in; w = base.total_out;
+ InflateReset();
+ base.total_in = r; base.total_out = w;
+ this._mode = InflateMode.BLOCKS;
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus inflateInit()
+ {
+ return inflateInit(DEF_WBITS);
+ }
+ public ZLibStatus inflateInit(bool nowrap)
+ {
+ return inflateInit(DEF_WBITS, nowrap);
+ }
+ public ZLibStatus inflateInit(int w)
+ {
+ return inflateInit(w, false);
+ }
+
+ public ZLibStatus inflateInit(int w, bool nowrap)
+ {
+ return this.InflateInit(nowrap ? -w : w);
+ }
+
+ public ZLibStatus inflateEnd()
+ {
+ var ret = this.InflateEnd();
+ return ret;
+ }
+ public ZLibStatus inflateSync()
+ {
+ return this.InflateSync();
+ }
+
+ public ZLibStatus inflateSetDictionary(byte[] dictionary, int dictLength)
+ {
+ return this.InflateSetDictionary(dictionary, dictLength);
+ }
+
+ public ZLibStatus inflate(byte[] inputBufer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType)
+ {
+ this.next_in = inputBufer;
+ this.next_in_index = inputOffset;
+ this.avail_in = inputCount;
+ this.next_out = outputBuffer;
+ this.next_out_index = outputOffset;
+ this.avail_out = outputCount;
+ return this.inflate(flushType);
+ }
+
+ public ZLibStatus inflate(byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType)
+ {
+ this.next_out = outputBuffer;
+ this.next_out_index = outputOffset;
+ this.avail_out = outputCount;
+ return this.inflate(flushType);
+ }
+
+ // TODO: Dlete this
+ public ZLibStatus deflate(byte[] bufer, int offset, int count, byte[] p1, int p2, int p3, FlushType flushType)
+ {
+ throw new NotImplementedException();
+ }
+
+ public ZLibStatus deflateEnd()
+ {
+ throw new NotImplementedException();
+ }
+
+ public ZLibStatus deflate(byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v11/InflateBlocks.cs b/Renci.SshNet/Compression/v11/InflateBlocks.cs
new file mode 100644
index 0000000..273389f
--- /dev/null
+++ b/Renci.SshNet/Compression/v11/InflateBlocks.cs
@@ -0,0 +1,721 @@
+using System;
+/*
+ * $Id: InfBlocks.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public enum InflateBlockMode
+ {
+ ///
+ /// get type bits (3, including end bit)
+ ///
+ TYPE = 0,
+ ///
+ /// get lengths for stored
+ ///
+ LENS = 1,
+ ///
+ /// cessing stored block
+ ///
+ STORED = 2,
+ ///
+ /// get table lengths
+ ///
+ TABLE = 3,
+ ///
+ /// get bit lengths tree for a dynamic block
+ ///
+ BTREE = 4,
+ ///
+ /// get length, distance trees for a dynamic block
+ ///
+ DTREE = 5,
+ ///
+ /// processing fixed or dynamic block
+ ///
+ CODES = 6,
+ ///
+ /// output remaining window bytes
+ ///
+ DRY = 7,
+ ///
+ /// finished last block, done
+ ///
+ DONE = 8,
+ ///
+ /// ot a data error--stuck here
+ ///
+ BAD = 9
+ }
+
+ internal sealed class InflateBlocks : InflateCodes
+ {
+ private const int MANY = 1440;
+
+ // And'ing with mask[n] masks the lower n bits
+ private static readonly int[] inflate_mask = {
+ 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
+ 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
+ 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
+ 0x00007fff, 0x0000ffff
+ };
+
+ // Table for deflate from PKZIP's appnote.txt.
+ static readonly int[] border = { // Order of the bit length code lengths
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
+ };
+
+ internal InflateBlockMode mode; // current inflate_block mode
+
+ internal int left; // if STORED, bytes left to copy
+
+ internal int table; // table lengths (14 bits)
+ internal int index; // index into blens (or border)
+ internal int[] blens; // bit lengths of codes
+ internal int[] bb = new int[1]; // bit length tree depth
+ internal int[] tb = new int[1]; // bit length decoding tree
+
+ //internal InfCodes codes = new InfCodes(); // if CODES, current state
+
+ int last; // true if this block is the last block
+
+ // mode independent information
+ internal int bitk; // bits in bit buffer
+ internal int bitb; // bit buffer
+ internal int[] hufts; // single malloc for tree space
+ internal byte[] window; // sliding window
+ internal int end; // one byte after sliding window
+ internal int read; // window read pointer
+ internal int write; // window write pointer
+ internal Object checkfn; // check function
+ internal long check; // check on output
+
+ internal InflateTree inftree = new InflateTree();
+
+ internal InflateBlocks(ZStream z, Object checkfn, int w)
+ {
+ hufts = new int[MANY * 3];
+ window = new byte[w];
+ end = w;
+ this.checkfn = checkfn;
+ mode = InflateBlockMode.TYPE;
+ reset(z, null);
+ }
+
+ internal void reset(ZStream z, long[] c)
+ {
+ if (c != null) c[0] = check;
+ if (mode == InflateBlockMode.BTREE || mode == InflateBlockMode.DTREE)
+ {
+ }
+ if (mode == InflateBlockMode.CODES)
+ {
+ codesfree(z);
+ }
+ mode = InflateBlockMode.TYPE;
+ bitk = 0;
+ bitb = 0;
+ read = write = 0;
+
+ if (checkfn != null)
+ z.adler = check = Adler32.adler32(0L, null, 0, 0);
+ }
+
+ internal ZLibStatus proc(ZStream z, ZLibStatus r)
+ {
+ int t; // temporary storage
+ ZLibStatus tt;
+ int b; // bit buffer
+ int k; // bits in bit buffer
+ int p; // input data pointer
+ int n; // bytes available there
+ int q; // output window write pointer
+ int m;
+ { // bytes to end of window or read pointer
+
+ // copy input/output information to locals (UPDATE macro restores)
+ p = z.next_in_index; n = z.avail_in; b = bitb; k = bitk;
+ }
+ {
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+ }
+
+ // process input based on current state
+ while (true)
+ {
+ switch (mode)
+ {
+ case InflateBlockMode.TYPE:
+
+ while (k < (3))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+ t = (int)(b & 7);
+ last = t & 1;
+
+ switch (t >> 1)
+ {
+ case 0:
+ { // stored
+ b >>= (3); k -= (3);
+ }
+ t = k & 7;
+ { // go to byte boundary
+
+ b >>= (t); k -= (t);
+ }
+ mode = InflateBlockMode.LENS; // get length of stored block
+ break;
+ case 1:
+ { // fixed
+ int[] bl = new int[1];
+ int[] bd = new int[1];
+ int[][] tl = new int[1][];
+ int[][] td = new int[1][];
+
+ InflateTree.InflateTreesFixed(bl, bd, tl, td, z);
+ codesinit(bl[0], bd[0], tl[0], 0, td[0], 0, z);
+ }
+ {
+
+ b >>= (3); k -= (3);
+ }
+
+ mode = InflateBlockMode.CODES;
+ break;
+ case 2:
+ { // dynamic
+
+ b >>= (3); k -= (3);
+ }
+
+ mode = InflateBlockMode.TABLE;
+ break;
+ case 3:
+ { // illegal
+
+ b >>= (3); k -= (3);
+ }
+ mode = InflateBlockMode.BAD;
+ z.msg = "invalid block type";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ break;
+ case InflateBlockMode.LENS:
+
+ while (k < (32))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ if ((((~b) >> 16) & 0xffff) != (b & 0xffff))
+ {
+ mode = InflateBlockMode.BAD;
+ z.msg = "invalid stored block lengths";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ left = (b & 0xffff);
+ b = k = 0; // dump bits
+ mode = left != 0 ? InflateBlockMode.STORED : (last != 0 ? InflateBlockMode.DRY : InflateBlockMode.TYPE);
+ break;
+ case InflateBlockMode.STORED:
+ if (n == 0)
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+
+ if (m == 0)
+ {
+ if (q == end && read != 0)
+ {
+ q = 0; m = (int)(q < read ? read - q - 1 : end - q);
+ }
+ if (m == 0)
+ {
+ write = q;
+ r = inflate_flush(z, r);
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+ if (q == end && read != 0)
+ {
+ q = 0; m = (int)(q < read ? read - q - 1 : end - q);
+ }
+ if (m == 0)
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ }
+ }
+ r = ZLibStatus.Z_OK;
+
+ t = left;
+ if (t > n) t = n;
+ if (t > m) t = m;
+ System.Array.Copy(z.next_in, p, window, q, t);
+ p += t; n -= t;
+ q += t; m -= t;
+ if ((left -= t) != 0)
+ break;
+ mode = last != 0 ? InflateBlockMode.DRY : InflateBlockMode.TYPE;
+ break;
+ case InflateBlockMode.TABLE:
+
+ while (k < (14))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ table = t = (b & 0x3fff);
+ if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
+ {
+ mode = InflateBlockMode.BAD;
+ z.msg = "too many length or distance symbols";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
+ if (blens == null || blens.Length < t)
+ {
+ blens = new int[t];
+ }
+ else
+ {
+ for (int i = 0; i < t; i++) { blens[i] = 0; }
+ }
+ {
+
+ b >>= (14); k -= (14);
+ }
+
+ index = 0;
+ mode = InflateBlockMode.BTREE;
+ goto case InflateBlockMode.BTREE;
+ case InflateBlockMode.BTREE:
+ while (index < 4 + (table >> 10))
+ {
+ while (k < (3))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ blens[border[index++]] = b & 7;
+ {
+
+ b >>= (3); k -= (3);
+ }
+ }
+
+ while (index < 19)
+ {
+ blens[border[index++]] = 0;
+ }
+
+ bb[0] = 7;
+ tt = inftree.InflateTreesBits(blens, bb, tb, hufts, z);
+ if (tt != ZLibStatus.Z_OK)
+ {
+ r = tt;
+ if (r == ZLibStatus.Z_DATA_ERROR)
+ {
+ blens = null;
+ mode = InflateBlockMode.BAD;
+ }
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+
+ index = 0;
+ mode = InflateBlockMode.DTREE;
+ goto case InflateBlockMode.DTREE;
+ case InflateBlockMode.DTREE:
+ while (true)
+ {
+ t = table;
+ if (!(index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)))
+ {
+ break;
+ }
+
+ int i, j, c;
+
+ t = bb[0];
+
+ while (k < (t))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ if (tb[0] == -1)
+ {
+ //System.err.println("null...");
+ }
+
+ t = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 1];
+ c = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 2];
+
+ if (c < 16)
+ {
+ b >>= (t); k -= (t);
+ blens[index++] = c;
+ }
+ else
+ { // c == 16..18
+ i = c == 18 ? 7 : c - 14;
+ j = c == 18 ? 11 : 3;
+
+ while (k < (t + i))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ b >>= (t); k -= (t);
+
+ j += (b & inflate_mask[i]);
+
+ b >>= (i); k -= (i);
+
+ i = index;
+ t = table;
+ if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
+ (c == 16 && i < 1))
+ {
+ blens = null;
+ mode = InflateBlockMode.BAD;
+ z.msg = "invalid bit length repeat";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+
+ c = c == 16 ? blens[i - 1] : 0;
+ do
+ {
+ blens[i++] = c;
+ }
+ while (--j != 0);
+ index = i;
+ }
+ }
+
+ tb[0] = -1;
+ {
+ int[] bl = new int[1];
+ int[] bd = new int[1];
+ int[] tl = new int[1];
+ int[] td = new int[1];
+ bl[0] = 9; // must be <= 9 for lookahead assumptions
+ bd[0] = 6; // must be <= 9 for lookahead assumptions
+
+ t = table;
+ tt = inftree.InflateTreesDynamic(257 + (t & 0x1f),
+ 1 + ((t >> 5) & 0x1f),
+ blens, bl, bd, tl, td, hufts, z);
+
+ if (tt != ZLibStatus.Z_OK)
+ {
+ if (tt == ZLibStatus.Z_DATA_ERROR)
+ {
+ blens = null;
+ mode = InflateBlockMode.BAD;
+ }
+ r = tt;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ codesinit(bl[0], bd[0], hufts, tl[0], hufts, td[0], z);
+ }
+ mode = InflateBlockMode.CODES;
+ goto case InflateBlockMode.CODES;
+ case InflateBlockMode.CODES:
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+
+ if ((r = codesproc(this, z, r)) != ZLibStatus.Z_STREAM_END)
+ {
+ return inflate_flush(z, r);
+ }
+ r = ZLibStatus.Z_OK;
+ codesfree(z);
+
+ p = z.next_in_index; n = z.avail_in; b = bitb; k = bitk;
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+
+ if (last == 0)
+ {
+ mode = InflateBlockMode.TYPE;
+ break;
+ }
+ mode = InflateBlockMode.DRY;
+ goto case InflateBlockMode.DRY;
+ case InflateBlockMode.DRY:
+ write = q;
+ r = inflate_flush(z, r);
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+ if (read != write)
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ mode = InflateBlockMode.DONE;
+ goto case InflateBlockMode.DONE;
+ case InflateBlockMode.DONE:
+ r = ZLibStatus.Z_STREAM_END;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ case InflateBlockMode.BAD:
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+
+ default:
+ r = ZLibStatus.Z_STREAM_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ }
+ }
+
+ internal void free(ZStream z)
+ {
+ reset(z, null);
+ window = null;
+ hufts = null;
+ //ZFREE(z, s);
+ }
+
+ internal void set_dictionary(byte[] d, int start, int n)
+ {
+ System.Array.Copy(d, start, window, 0, n);
+ read = write = n;
+ }
+
+ // Returns true if inflate is currently at the end of a block generated
+ // by Z_SYNC_FLUSH or FlushType.Z_FULL_FLUSH.
+ internal ZLibStatus sync_point()
+ {
+ return mode == InflateBlockMode.LENS ? ZLibStatus.Z_STREAM_END : ZLibStatus.Z_OK;
+ }
+
+ // copy as much as possible from the sliding window to the output area
+ internal ZLibStatus inflate_flush(ZStream z, ZLibStatus r)
+ {
+ int n;
+ int p;
+ int q;
+
+ // local copies of source and destination pointers
+ p = z.next_out_index;
+ q = read;
+
+ // compute number of bytes to copy as far as end of window
+ n = (int)((q <= write ? write : end) - q);
+ if (n > z.avail_out) n = z.avail_out;
+ if (n != 0 && r == ZLibStatus.Z_BUF_ERROR) r = ZLibStatus.Z_OK;
+
+ // update counters
+ z.avail_out -= n;
+ z.total_out += n;
+
+ // update check information
+ if (checkfn != null)
+ z.adler = check = Adler32.adler32(check, window, q, n);
+
+ // copy as far as end of window
+ System.Array.Copy(window, q, z.next_out, p, n);
+ p += n;
+ q += n;
+
+ // see if more to copy at beginning of window
+ if (q == end)
+ {
+ // wrap pointers
+ q = 0;
+ if (write == end)
+ write = 0;
+
+ // compute bytes to copy
+ n = write - q;
+ if (n > z.avail_out) n = z.avail_out;
+ if (n != 0 && r == ZLibStatus.Z_BUF_ERROR) r = ZLibStatus.Z_OK;
+
+ // update counters
+ z.avail_out -= n;
+ z.total_out += n;
+
+ // update check information
+ if (checkfn != null)
+ z.adler = check = Adler32.adler32(check, window, q, n);
+
+ // copy
+ System.Array.Copy(window, q, z.next_out, p, n);
+ p += n;
+ q += n;
+ }
+
+ // update pointers
+ z.next_out_index = p;
+ read = q;
+
+ // done
+ return r;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v11/InflateCodes.cs b/Renci.SshNet/Compression/v11/InflateCodes.cs
new file mode 100644
index 0000000..3214e56
--- /dev/null
+++ b/Renci.SshNet/Compression/v11/InflateCodes.cs
@@ -0,0 +1,690 @@
+using System;
+/*
+ * $Id: InfCodes.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public enum InflateCodeMode
+ {
+ ///
+ /// x: set up for InflateCodeMode.LEN
+ ///
+ START = 0,
+ ///
+ /// i: get length/literal/eob next
+ ///
+ LEN = 1,
+ ///
+ /// i: getting length extra (have base)
+ ///
+ LENEXT = 2,
+ ///
+ /// i: get distance next
+ ///
+ DIST = 3,
+ ///
+ /// : getting distance extra
+ ///
+ DISTEXT = 4,
+ ///
+ /// o: copying bytes in window, waiting for space
+ ///
+ COPY = 5,
+ ///
+ /// o: got literal, waiting for output space
+ ///
+ LIT = 6,
+ ///
+ /// o: got eob, possibly still output waiting
+ ///
+ WASH = 7,
+ ///
+ /// x: got eob and all data flushed
+ ///
+ END = 8,
+ ///
+ /// x: got error
+ ///
+ BADCODE = 9
+ }
+
+ internal abstract class InflateCodes// : ZStream
+ {
+ private static readonly int[] inflate_mask = {
+ 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
+ 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
+ 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
+ 0x00007fff, 0x0000ffff
+ };
+
+ InflateCodeMode mode; // current inflate_codes mode
+
+ // mode dependent information
+ int len;
+
+ int[] tree; // pointer into tree
+ int tree_index = 0;
+ int need; // bits needed
+
+ int lit;
+
+ // if EXT or COPY, where and how much
+ int get; // bits to get for extra
+ int dist; // distance back to copy from
+
+ byte lbits; // ltree bits decoded per branch
+ byte dbits; // dtree bits decoder per branch
+ int[] ltree; // literal/length/eob tree
+ int ltree_index; // literal/length/eob tree
+ int[] dtree; // distance tree
+ int dtree_index; // distance tree
+
+ internal InflateCodes()
+ {
+ }
+ internal void codesinit(int bl, int bd,
+ int[] tl, int tl_index,
+ int[] td, int td_index, ZStream z)
+ {
+ mode = InflateCodeMode.START;
+ lbits = (byte)bl;
+ dbits = (byte)bd;
+ ltree = tl;
+ ltree_index = tl_index;
+ dtree = td;
+ dtree_index = td_index;
+ tree = null;
+ }
+
+ internal ZLibStatus codesproc(InflateBlocks s, ZStream z, ZLibStatus r)
+ {
+ int j; // temporary storage
+ int tindex; // temporary pointer
+ int e; // extra bits or operation
+ int b = 0; // bit buffer
+ int k = 0; // bits in bit buffer
+ int p = 0; // input data pointer
+ int n; // bytes available there
+ int q; // output window write pointer
+ int m; // bytes to end of window or read pointer
+ int f; // pointer to copy strings from
+
+ // copy input/output information to locals (UPDATE macro restores)
+ p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk;
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ // process input and output based on current state
+ while (true)
+ {
+ switch (mode)
+ {
+ // waiting for "i:"=input, "o:"=output, "x:"=nothing
+ case InflateCodeMode.START: // x: set up for LEN
+ if (m >= 258 && n >= 10)
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ r = inflate_fast(lbits, dbits,
+ ltree, ltree_index,
+ dtree, dtree_index,
+ s, z);
+
+ p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk;
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (r != ZLibStatus.Z_OK)
+ {
+ mode = r == ZLibStatus.Z_STREAM_END ? InflateCodeMode.WASH : InflateCodeMode.BADCODE;
+ break;
+ }
+ }
+ need = lbits;
+ tree = ltree;
+ tree_index = ltree_index;
+
+ mode = InflateCodeMode.LEN;
+ goto case InflateCodeMode.LEN;
+ case InflateCodeMode.LEN: // i: get length/literal/eob next
+ j = need;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ tindex = (tree_index + (b & inflate_mask[j])) * 3;
+
+ b >>= (tree[tindex + 1]);
+ k -= (tree[tindex + 1]);
+
+ e = tree[tindex];
+
+ if (e == 0)
+ { // literal
+ lit = tree[tindex + 2];
+ mode = InflateCodeMode.LIT;
+ break;
+ }
+ if ((e & 16) != 0)
+ { // length
+ get = e & 15;
+ len = tree[tindex + 2];
+ mode = InflateCodeMode.LENEXT;
+ break;
+ }
+ if ((e & 64) == 0)
+ { // next table
+ need = e;
+ tree_index = tindex / 3 + tree[tindex + 2];
+ break;
+ }
+ if ((e & 32) != 0)
+ { // end of block
+ mode = InflateCodeMode.WASH;
+ break;
+ }
+ mode = InflateCodeMode.BADCODE; // invalid code
+ z.msg = "invalid literal/length code";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ case InflateCodeMode.LENEXT: // i: getting length extra (have base)
+ j = get;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--; b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ len += (b & inflate_mask[j]);
+
+ b >>= j;
+ k -= j;
+
+ need = dbits;
+ tree = dtree;
+ tree_index = dtree_index;
+ mode = InflateCodeMode.DIST;
+ goto case InflateCodeMode.DIST;
+ case InflateCodeMode.DIST: // i: get distance next
+ j = need;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--; b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ tindex = (tree_index + (b & inflate_mask[j])) * 3;
+
+ b >>= tree[tindex + 1];
+ k -= tree[tindex + 1];
+
+ e = (tree[tindex]);
+ if ((e & 16) != 0)
+ { // distance
+ get = e & 15;
+ dist = tree[tindex + 2];
+ mode = InflateCodeMode.DISTEXT;
+ break;
+ }
+ if ((e & 64) == 0)
+ { // next table
+ need = e;
+ tree_index = tindex / 3 + tree[tindex + 2];
+ break;
+ }
+ mode = InflateCodeMode.BADCODE; // invalid code
+ z.msg = "invalid distance code";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ case InflateCodeMode.DISTEXT: // i: getting distance extra
+ j = get;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--; b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ dist += (b & inflate_mask[j]);
+
+ b >>= j;
+ k -= j;
+
+ mode = InflateCodeMode.COPY;
+ goto case InflateCodeMode.COPY;
+ case InflateCodeMode.COPY: // o: copying bytes in window, waiting for space
+ f = q - dist;
+ while (f < 0)
+ { // modulo window size-"while" instead
+ f += s.end; // of "if" handles invalid distances
+ }
+ while (len != 0)
+ {
+
+ if (m == 0)
+ {
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+ if (m == 0)
+ {
+ s.write = q; r = s.inflate_flush(z, r);
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+
+ if (m == 0)
+ {
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ }
+ }
+
+ s.window[q++] = s.window[f++]; m--;
+
+ if (f == s.end)
+ f = 0;
+ len--;
+ }
+ mode = InflateCodeMode.START;
+ break;
+ case InflateCodeMode.LIT: // o: got literal, waiting for output space
+ if (m == 0)
+ {
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+ if (m == 0)
+ {
+ s.write = q; r = s.inflate_flush(z, r);
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+ if (m == 0)
+ {
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ }
+ }
+ r = ZLibStatus.Z_OK;
+
+ s.window[q++] = (byte)lit; m--;
+
+ mode = InflateCodeMode.START;
+ break;
+ case InflateCodeMode.WASH: // o: got eob, possibly more output
+ if (k > 7)
+ { // return unused byte, if any
+ k -= 8;
+ n++;
+ p--; // can always return one
+ }
+
+ s.write = q; r = s.inflate_flush(z, r);
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (s.read != s.write)
+ {
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ mode = InflateCodeMode.END;
+ goto case InflateCodeMode.END;
+ case InflateCodeMode.END:
+ r = ZLibStatus.Z_STREAM_END;
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ case InflateCodeMode.BADCODE: // x: got error
+
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ default:
+ r = ZLibStatus.Z_STREAM_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ }
+ }
+
+ internal void codesfree(ZStream z)
+ {
+ // ZFREE(z, c);
+ }
+
+ // Called with number of bytes left to write in window at least 258
+ // (the maximum string length) and number of input bytes available
+ // at least ten. The ten bytes are six bytes for the longest length/
+ // distance pair plus four bytes for overloading the bit buffer.
+
+ internal ZLibStatus inflate_fast(int bl, int bd,
+ int[] tl, int tl_index,
+ int[] td, int td_index,
+ InflateBlocks s, ZStream z)
+ {
+ int t; // temporary pointer
+ int[] tp; // temporary pointer
+ int tp_index; // temporary pointer
+ int e; // extra bits or operation
+ int b; // bit buffer
+ int k; // bits in bit buffer
+ int p; // input data pointer
+ int n; // bytes available there
+ int q; // output window write pointer
+ int m; // bytes to end of window or read pointer
+ int ml; // mask for literal/length tree
+ int md; // mask for distance tree
+ int c; // bytes to copy
+ int d; // distance back to copy from
+ int r; // copy source pointer
+
+ int tp_index_t_3; // (tp_index+t)*3
+
+ // load input, output, bit values
+ p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk;
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ // initialize masks
+ ml = inflate_mask[bl];
+ md = inflate_mask[bd];
+
+ // do until not enough input or output space for fast loop
+ do
+ { // assume called with m >= 258 && n >= 10
+ // get literal/length code
+ while (k < (20))
+ { // max bits for literal/length code
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k; k += 8;
+ }
+
+ t = b & ml;
+ tp = tl;
+ tp_index = tl_index;
+ tp_index_t_3 = (tp_index + t) * 3;
+ if ((e = tp[tp_index_t_3]) == 0)
+ {
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ s.window[q++] = (byte)tp[tp_index_t_3 + 2];
+ m--;
+ continue;
+ }
+ do
+ {
+
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ if ((e & 16) != 0)
+ {
+ e &= 15;
+ c = tp[tp_index_t_3 + 2] + ((int)b & inflate_mask[e]);
+
+ b >>= e; k -= e;
+
+ // decode distance base of block to copy
+ while (k < (15))
+ { // max bits for distance code
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k; k += 8;
+ }
+
+ t = b & md;
+ tp = td;
+ tp_index = td_index;
+ tp_index_t_3 = (tp_index + t) * 3;
+ e = tp[tp_index_t_3];
+
+ do
+ {
+
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ if ((e & 16) != 0)
+ {
+ // get extra bits to add to distance base
+ e &= 15;
+ while (k < (e))
+ { // get extra bits (up to 13)
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k; k += 8;
+ }
+
+ d = tp[tp_index_t_3 + 2] + (b & inflate_mask[e]);
+
+ b >>= (e); k -= (e);
+
+ // do the copy
+ m -= c;
+ if (q >= d)
+ { // offset before dest
+ // just copy
+ r = q - d;
+ if (q - r > 0 && 2 > (q - r))
+ {
+ s.window[q++] = s.window[r++]; // minimum count is three,
+ s.window[q++] = s.window[r++]; // so unroll loop a little
+ c -= 2;
+ }
+ else
+ {
+ System.Array.Copy(s.window, r, s.window, q, 2);
+ q += 2; r += 2; c -= 2;
+ }
+ }
+ else
+ { // else offset after destination
+ r = q - d;
+ do
+ {
+ r += s.end; // force pointer in window
+ } while (r < 0); // covers invalid distances
+ e = s.end - r;
+ if (c > e)
+ { // if source crosses,
+ c -= e; // wrapped copy
+ if (q - r > 0 && e > (q - r))
+ {
+ do { s.window[q++] = s.window[r++]; }
+ while (--e != 0);
+ }
+ else
+ {
+ System.Array.Copy(s.window, r, s.window, q, e);
+ q += e; r += e; e = 0;
+ }
+ r = 0; // copy rest from start of window
+ }
+
+ }
+
+ // copy all or what's left
+ if (q - r > 0 && c > (q - r))
+ {
+ do { s.window[q++] = s.window[r++]; }
+ while (--c != 0);
+ }
+ else
+ {
+ System.Array.Copy(s.window, r, s.window, q, c);
+ q += c; r += c; c = 0;
+ }
+ break;
+ }
+ else if ((e & 64) == 0)
+ {
+ t += tp[tp_index_t_3 + 2];
+ t += (b & inflate_mask[e]);
+ tp_index_t_3 = (tp_index + t) * 3;
+ e = tp[tp_index_t_3];
+ }
+ else
+ {
+ z.msg = "invalid distance code";
+
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ }
+ while (true);
+ break;
+ }
+
+ if ((e & 64) == 0)
+ {
+ t += tp[tp_index_t_3 + 2];
+ t += (b & inflate_mask[e]);
+ tp_index_t_3 = (tp_index + t) * 3;
+ if ((e = tp[tp_index_t_3]) == 0)
+ {
+
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ s.window[q++] = (byte)tp[tp_index_t_3 + 2];
+ m--;
+ break;
+ }
+ }
+ else if ((e & 32) != 0)
+ {
+
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_STREAM_END;
+ }
+ else
+ {
+ z.msg = "invalid literal/length code";
+
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ }
+ while (true);
+ }
+ while (m >= 258 && n >= 10);
+
+ // not enough input or output--restore pointers and return
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_OK;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v11/InflateTree.cs b/Renci.SshNet/Compression/v11/InflateTree.cs
new file mode 100644
index 0000000..f9da579
--- /dev/null
+++ b/Renci.SshNet/Compression/v11/InflateTree.cs
@@ -0,0 +1,555 @@
+using System;
+/*
+ * $Id: InfTree.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ internal sealed class InflateTree
+ {
+ private const int MANY = 1440;
+
+ private const int fixed_bl = 9;
+ private const int fixed_bd = 5;
+
+ static readonly int[] fixed_tl = {
+ 96,7,256, 0,8,80, 0,8,16, 84,8,115,
+ 82,7,31, 0,8,112, 0,8,48, 0,9,192,
+ 80,7,10, 0,8,96, 0,8,32, 0,9,160,
+ 0,8,0, 0,8,128, 0,8,64, 0,9,224,
+ 80,7,6, 0,8,88, 0,8,24, 0,9,144,
+ 83,7,59, 0,8,120, 0,8,56, 0,9,208,
+ 81,7,17, 0,8,104, 0,8,40, 0,9,176,
+ 0,8,8, 0,8,136, 0,8,72, 0,9,240,
+ 80,7,4, 0,8,84, 0,8,20, 85,8,227,
+ 83,7,43, 0,8,116, 0,8,52, 0,9,200,
+ 81,7,13, 0,8,100, 0,8,36, 0,9,168,
+ 0,8,4, 0,8,132, 0,8,68, 0,9,232,
+ 80,7,8, 0,8,92, 0,8,28, 0,9,152,
+ 84,7,83, 0,8,124, 0,8,60, 0,9,216,
+ 82,7,23, 0,8,108, 0,8,44, 0,9,184,
+ 0,8,12, 0,8,140, 0,8,76, 0,9,248,
+ 80,7,3, 0,8,82, 0,8,18, 85,8,163,
+ 83,7,35, 0,8,114, 0,8,50, 0,9,196,
+ 81,7,11, 0,8,98, 0,8,34, 0,9,164,
+ 0,8,2, 0,8,130, 0,8,66, 0,9,228,
+ 80,7,7, 0,8,90, 0,8,26, 0,9,148,
+ 84,7,67, 0,8,122, 0,8,58, 0,9,212,
+ 82,7,19, 0,8,106, 0,8,42, 0,9,180,
+ 0,8,10, 0,8,138, 0,8,74, 0,9,244,
+ 80,7,5, 0,8,86, 0,8,22, 192,8,0,
+ 83,7,51, 0,8,118, 0,8,54, 0,9,204,
+ 81,7,15, 0,8,102, 0,8,38, 0,9,172,
+ 0,8,6, 0,8,134, 0,8,70, 0,9,236,
+ 80,7,9, 0,8,94, 0,8,30, 0,9,156,
+ 84,7,99, 0,8,126, 0,8,62, 0,9,220,
+ 82,7,27, 0,8,110, 0,8,46, 0,9,188,
+ 0,8,14, 0,8,142, 0,8,78, 0,9,252,
+ 96,7,256, 0,8,81, 0,8,17, 85,8,131,
+ 82,7,31, 0,8,113, 0,8,49, 0,9,194,
+ 80,7,10, 0,8,97, 0,8,33, 0,9,162,
+ 0,8,1, 0,8,129, 0,8,65, 0,9,226,
+ 80,7,6, 0,8,89, 0,8,25, 0,9,146,
+ 83,7,59, 0,8,121, 0,8,57, 0,9,210,
+ 81,7,17, 0,8,105, 0,8,41, 0,9,178,
+ 0,8,9, 0,8,137, 0,8,73, 0,9,242,
+ 80,7,4, 0,8,85, 0,8,21, 80,8,258,
+ 83,7,43, 0,8,117, 0,8,53, 0,9,202,
+ 81,7,13, 0,8,101, 0,8,37, 0,9,170,
+ 0,8,5, 0,8,133, 0,8,69, 0,9,234,
+ 80,7,8, 0,8,93, 0,8,29, 0,9,154,
+ 84,7,83, 0,8,125, 0,8,61, 0,9,218,
+ 82,7,23, 0,8,109, 0,8,45, 0,9,186,
+ 0,8,13, 0,8,141, 0,8,77, 0,9,250,
+ 80,7,3, 0,8,83, 0,8,19, 85,8,195,
+ 83,7,35, 0,8,115, 0,8,51, 0,9,198,
+ 81,7,11, 0,8,99, 0,8,35, 0,9,166,
+ 0,8,3, 0,8,131, 0,8,67, 0,9,230,
+ 80,7,7, 0,8,91, 0,8,27, 0,9,150,
+ 84,7,67, 0,8,123, 0,8,59, 0,9,214,
+ 82,7,19, 0,8,107, 0,8,43, 0,9,182,
+ 0,8,11, 0,8,139, 0,8,75, 0,9,246,
+ 80,7,5, 0,8,87, 0,8,23, 192,8,0,
+ 83,7,51, 0,8,119, 0,8,55, 0,9,206,
+ 81,7,15, 0,8,103, 0,8,39, 0,9,174,
+ 0,8,7, 0,8,135, 0,8,71, 0,9,238,
+ 80,7,9, 0,8,95, 0,8,31, 0,9,158,
+ 84,7,99, 0,8,127, 0,8,63, 0,9,222,
+ 82,7,27, 0,8,111, 0,8,47, 0,9,190,
+ 0,8,15, 0,8,143, 0,8,79, 0,9,254,
+ 96,7,256, 0,8,80, 0,8,16, 84,8,115,
+ 82,7,31, 0,8,112, 0,8,48, 0,9,193,
+
+ 80,7,10, 0,8,96, 0,8,32, 0,9,161,
+ 0,8,0, 0,8,128, 0,8,64, 0,9,225,
+ 80,7,6, 0,8,88, 0,8,24, 0,9,145,
+ 83,7,59, 0,8,120, 0,8,56, 0,9,209,
+ 81,7,17, 0,8,104, 0,8,40, 0,9,177,
+ 0,8,8, 0,8,136, 0,8,72, 0,9,241,
+ 80,7,4, 0,8,84, 0,8,20, 85,8,227,
+ 83,7,43, 0,8,116, 0,8,52, 0,9,201,
+ 81,7,13, 0,8,100, 0,8,36, 0,9,169,
+ 0,8,4, 0,8,132, 0,8,68, 0,9,233,
+ 80,7,8, 0,8,92, 0,8,28, 0,9,153,
+ 84,7,83, 0,8,124, 0,8,60, 0,9,217,
+ 82,7,23, 0,8,108, 0,8,44, 0,9,185,
+ 0,8,12, 0,8,140, 0,8,76, 0,9,249,
+ 80,7,3, 0,8,82, 0,8,18, 85,8,163,
+ 83,7,35, 0,8,114, 0,8,50, 0,9,197,
+ 81,7,11, 0,8,98, 0,8,34, 0,9,165,
+ 0,8,2, 0,8,130, 0,8,66, 0,9,229,
+ 80,7,7, 0,8,90, 0,8,26, 0,9,149,
+ 84,7,67, 0,8,122, 0,8,58, 0,9,213,
+ 82,7,19, 0,8,106, 0,8,42, 0,9,181,
+ 0,8,10, 0,8,138, 0,8,74, 0,9,245,
+ 80,7,5, 0,8,86, 0,8,22, 192,8,0,
+ 83,7,51, 0,8,118, 0,8,54, 0,9,205,
+ 81,7,15, 0,8,102, 0,8,38, 0,9,173,
+ 0,8,6, 0,8,134, 0,8,70, 0,9,237,
+ 80,7,9, 0,8,94, 0,8,30, 0,9,157,
+ 84,7,99, 0,8,126, 0,8,62, 0,9,221,
+ 82,7,27, 0,8,110, 0,8,46, 0,9,189,
+ 0,8,14, 0,8,142, 0,8,78, 0,9,253,
+ 96,7,256, 0,8,81, 0,8,17, 85,8,131,
+ 82,7,31, 0,8,113, 0,8,49, 0,9,195,
+ 80,7,10, 0,8,97, 0,8,33, 0,9,163,
+ 0,8,1, 0,8,129, 0,8,65, 0,9,227,
+ 80,7,6, 0,8,89, 0,8,25, 0,9,147,
+ 83,7,59, 0,8,121, 0,8,57, 0,9,211,
+ 81,7,17, 0,8,105, 0,8,41, 0,9,179,
+ 0,8,9, 0,8,137, 0,8,73, 0,9,243,
+ 80,7,4, 0,8,85, 0,8,21, 80,8,258,
+ 83,7,43, 0,8,117, 0,8,53, 0,9,203,
+ 81,7,13, 0,8,101, 0,8,37, 0,9,171,
+ 0,8,5, 0,8,133, 0,8,69, 0,9,235,
+ 80,7,8, 0,8,93, 0,8,29, 0,9,155,
+ 84,7,83, 0,8,125, 0,8,61, 0,9,219,
+ 82,7,23, 0,8,109, 0,8,45, 0,9,187,
+ 0,8,13, 0,8,141, 0,8,77, 0,9,251,
+ 80,7,3, 0,8,83, 0,8,19, 85,8,195,
+ 83,7,35, 0,8,115, 0,8,51, 0,9,199,
+ 81,7,11, 0,8,99, 0,8,35, 0,9,167,
+ 0,8,3, 0,8,131, 0,8,67, 0,9,231,
+ 80,7,7, 0,8,91, 0,8,27, 0,9,151,
+ 84,7,67, 0,8,123, 0,8,59, 0,9,215,
+ 82,7,19, 0,8,107, 0,8,43, 0,9,183,
+ 0,8,11, 0,8,139, 0,8,75, 0,9,247,
+ 80,7,5, 0,8,87, 0,8,23, 192,8,0,
+ 83,7,51, 0,8,119, 0,8,55, 0,9,207,
+ 81,7,15, 0,8,103, 0,8,39, 0,9,175,
+ 0,8,7, 0,8,135, 0,8,71, 0,9,239,
+ 80,7,9, 0,8,95, 0,8,31, 0,9,159,
+ 84,7,99, 0,8,127, 0,8,63, 0,9,223,
+ 82,7,27, 0,8,111, 0,8,47, 0,9,191,
+ 0,8,15, 0,8,143, 0,8,79, 0,9,255
+ };
+ static readonly int[] fixed_td = {
+ 80,5,1, 87,5,257, 83,5,17, 91,5,4097,
+ 81,5,5, 89,5,1025, 85,5,65, 93,5,16385,
+ 80,5,3, 88,5,513, 84,5,33, 92,5,8193,
+ 82,5,9, 90,5,2049, 86,5,129, 192,5,24577,
+ 80,5,2, 87,5,385, 83,5,25, 91,5,6145,
+ 81,5,7, 89,5,1537, 85,5,97, 93,5,24577,
+ 80,5,4, 88,5,769, 84,5,49, 92,5,12289,
+ 82,5,13, 90,5,3073, 86,5,193, 192,5,24577
+ };
+
+ // Tables for deflate from PKZIP's appnote.txt.
+ static readonly int[] cplens = { // Copy lengths for literal codes 257..285
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
+ };
+
+ // see note #13 above about 258
+ static readonly int[] cplext = { // Extra bits for literal codes 257..285
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+ 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112 // 112==invalid
+ };
+
+ static readonly int[] cpdist = { // Copy offsets for distance codes 0..29
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+ 8193, 12289, 16385, 24577
+ };
+
+ static readonly int[] cpdext = { // Extra bits for distance codes
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+ 12, 12, 13, 13};
+
+ // If BMAX needs to be larger than 16, then h and x[] should be uLong.
+ const int BMAX = 15; // maximum bit length of any code
+
+ int[] hn = null; // hufts used in space
+ int[] v = null; // work area for huft_build
+ int[] c = null; // bit length count table
+ int[] r = null; // table entry for structure assignment
+ int[] u = null; // table stack
+ int[] x = null; // bit offsets, then code stack
+
+ private ZLibStatus HuftBuild(int[] b, // code lengths in bits (all assumed <= BMAX)
+ int bindex,
+ int n, // number of codes (assumed <= 288)
+ int s, // number of simple-valued codes (0..s-1)
+ int[] d, // list of base values for non-simple codes
+ int[] e, // list of extra bits for non-simple codes
+ int[] t, // result: starting table
+ int[] m, // maximum lookup bits, returns actual
+ int[] hp,// space for trees
+ int[] hn,// hufts used in space
+ int[] v // working area: values in order of bit length
+ )
+ {
+ // Given a list of code lengths and a maximum table size, make a set of
+ // tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR
+ // if the given code set is incomplete (the tables are still built in this
+ // case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of
+ // lengths), or Z_MEM_ERROR if not enough memory.
+
+ int a; // counter for codes of length k
+ int f; // i repeats in table every f entries
+ int g; // maximum code length
+ int h; // table level
+ int i; // counter, current code
+ int j; // counter
+ int k; // number of bits in current code
+ int l; // bits per table (returned in m)
+ int mask; // (1 << w) - 1, to avoid cc -O bug on HP
+ int p; // pointer into c[], b[], or v[]
+ int q; // points to current table
+ int w; // bits before this table == (l * h)
+ int xp; // pointer into x
+ int y; // number of dummy codes added
+ int z; // number of entries in current table
+
+ // Generate counts for each bit length
+
+ p = 0; i = n;
+ do
+ {
+ c[b[bindex + p]]++; p++; i--; // assume all entries <= BMAX
+ } while (i != 0);
+
+ if (c[0] == n)
+ { // null input--all zero length codes
+ t[0] = -1;
+ m[0] = 0;
+ return ZLibStatus.Z_OK;
+ }
+
+ // Find minimum and maximum length, bound *m by those
+ l = m[0];
+ for (j = 1; j <= BMAX; j++)
+ if (c[j] != 0) break;
+ k = j; // minimum code length
+ if (l < j)
+ {
+ l = j;
+ }
+ for (i = BMAX; i != 0; i--)
+ {
+ if (c[i] != 0) break;
+ }
+ g = i; // maximum code length
+ if (l > i)
+ {
+ l = i;
+ }
+ m[0] = l;
+
+ // Adjust last length count to fill out codes, if needed
+ for (y = 1 << j; j < i; j++, y <<= 1)
+ {
+ if ((y -= c[j]) < 0)
+ {
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ }
+ if ((y -= c[i]) < 0)
+ {
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ c[i] += y;
+
+ // Generate starting offsets into the value table for each length
+ x[1] = j = 0;
+ p = 1; xp = 2;
+ while (--i != 0)
+ { // note that i == g from above
+ x[xp] = (j += c[p]);
+ xp++;
+ p++;
+ }
+
+ // Make a table of values in order of bit lengths
+ i = 0; p = 0;
+ do
+ {
+ if ((j = b[bindex + p]) != 0)
+ {
+ v[x[j]++] = i;
+ }
+ p++;
+ }
+ while (++i < n);
+ n = x[g]; // set n to length of v
+
+ // Generate the Huffman codes and for each, make the table entries
+ x[0] = i = 0; // first Huffman code is zero
+ p = 0; // grab values in bit order
+ h = -1; // no tables yet--level -1
+ w = -l; // bits decoded == (l * h)
+ u[0] = 0; // just to keep compilers happy
+ q = 0; // ditto
+ z = 0; // ditto
+
+ // go through the bit lengths (k already is bits in shortest code)
+ for (; k <= g; k++)
+ {
+ a = c[k];
+ while (a-- != 0)
+ {
+ // here i is the Huffman code of length k bits for value *p
+ // make tables up to required level
+ while (k > w + l)
+ {
+ h++;
+ w += l; // previous table always l bits
+ // compute minimum size table less than or equal to l bits
+ z = g - w;
+ z = (z > l) ? l : z; // table size upper limit
+ if ((f = 1 << (j = k - w)) > a + 1)
+ { // try a k-w bit table
+ // too few codes for k-w bit table
+ f -= a + 1; // deduct codes from patterns left
+ xp = k;
+ if (j < z)
+ {
+ while (++j < z)
+ { // try smaller tables up to z bits
+ if ((f <<= 1) <= c[++xp])
+ break; // enough codes to use up j bits
+ f -= c[xp]; // else deduct codes from patterns
+ }
+ }
+ }
+ z = 1 << j; // table entries for j-bit table
+
+ // allocate new table
+ if (hn[0] + z > MANY)
+ { // (note: doesn't matter for fixed)
+ return ZLibStatus.Z_DATA_ERROR; // overflow of MANY
+ }
+ u[h] = q = /*hp+*/ hn[0]; // DEBUG
+ hn[0] += z;
+
+ // connect to last table, if there is one
+ if (h != 0)
+ {
+ x[h] = i; // save pattern for backing up
+ r[0] = (byte)j; // bits in this table
+ r[1] = (byte)l; // bits to dump before this table
+ j = i >> (w - l);
+ r[2] = (int)(q - u[h - 1] - j); // offset to this table
+ System.Array.Copy(r, 0, hp, (u[h - 1] + j) * 3, 3); // connect to last table
+ }
+ else
+ {
+ t[0] = q; // first table is returned result
+ }
+ }
+
+ // set up table entry in r
+ r[1] = (byte)(k - w);
+ if (p >= n)
+ {
+ r[0] = 128 + 64; // out of values--invalid code
+ }
+ else if (v[p] < s)
+ {
+ r[0] = (byte)(v[p] < 256 ? 0 : 32 + 64); // 256 is end-of-block
+ r[2] = v[p++]; // simple code is just the value
+ }
+ else
+ {
+ r[0] = (byte)(e[v[p] - s] + 16 + 64); // non-simple--look up in lists
+ r[2] = d[v[p++] - s];
+ }
+
+ // fill code-like entries with r
+ f = 1 << (k - w);
+ for (j = i >> w; j < z; j += f)
+ {
+ System.Array.Copy(r, 0, hp, (q + j) * 3, 3);
+ }
+
+ // backwards increment the k-bit code i
+ for (j = 1 << (k - 1); (i & j) != 0; j >>= 1)
+ {
+ i ^= j;
+ }
+ i ^= j;
+
+ // backup over finished tables
+ mask = (1 << w) - 1; // needed on HP, cc -O bug
+ while ((i & mask) != x[h])
+ {
+ h--; // don't need to update q
+ w -= l;
+ mask = (1 << w) - 1;
+ }
+ }
+ }
+ // Return Z_BUF_ERROR if we were given an incomplete table
+ return y != 0 && g != 1 ? ZLibStatus.Z_BUF_ERROR : ZLibStatus.Z_OK;
+ }
+
+ internal ZLibStatus InflateTreesBits(int[] c, // 19 code lengths
+ int[] bb, // bits tree desired/actual depth
+ int[] tb, // bits tree result
+ int[] hp, // space for trees
+ ZStream z // for messages
+ )
+ {
+ ZLibStatus result;
+ InitWorkArea(19);
+ hn[0] = 0;
+ result = HuftBuild(c, 0, 19, 19, null, null, tb, bb, hp, hn, v);
+
+ if (result == ZLibStatus.Z_DATA_ERROR)
+ {
+ z.msg = "oversubscribed dynamic bit lengths tree";
+ }
+ else if (result == ZLibStatus.Z_BUF_ERROR || bb[0] == 0)
+ {
+ z.msg = "incomplete dynamic bit lengths tree";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ return result;
+ }
+
+ internal ZLibStatus InflateTreesDynamic(int nl, // number of literal/length codes
+ int nd, // number of distance codes
+ int[] c, // that many (total) code lengths
+ int[] bl, // literal desired/actual bit depth
+ int[] bd, // distance desired/actual bit depth
+ int[] tl, // literal/length tree result
+ int[] td, // distance tree result
+ int[] hp, // space for trees
+ ZStream z // for messages
+ )
+ {
+ ZLibStatus result;
+
+ // build literal/length tree
+ InitWorkArea(288);
+ hn[0] = 0;
+ result = HuftBuild(c, 0, nl, 257, cplens, cplext, tl, bl, hp, hn, v);
+ if (result != ZLibStatus.Z_OK || bl[0] == 0)
+ {
+ if (result == ZLibStatus.Z_DATA_ERROR)
+ {
+ z.msg = "oversubscribed literal/length tree";
+ }
+ else if (result != ZLibStatus.Z_MEM_ERROR)
+ {
+ z.msg = "incomplete literal/length tree";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ return result;
+ }
+
+ // build distance tree
+ InitWorkArea(288);
+ result = HuftBuild(c, nl, nd, 0, cpdist, cpdext, td, bd, hp, hn, v);
+
+ if (result != ZLibStatus.Z_OK || (bd[0] == 0 && nl > 257))
+ {
+ if (result == ZLibStatus.Z_DATA_ERROR)
+ {
+ z.msg = "oversubscribed distance tree";
+ }
+ else if (result == ZLibStatus.Z_BUF_ERROR)
+ {
+ z.msg = "incomplete distance tree";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ else if (result != ZLibStatus.Z_MEM_ERROR)
+ {
+ z.msg = "empty distance tree with lengths";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ return result;
+ }
+
+ return ZLibStatus.Z_OK;
+ }
+
+ internal static ZLibStatus InflateTreesFixed(int[] bl, //literal desired/actual bit depth
+ int[] bd, //distance desired/actual bit depth
+ int[][] tl,//literal/length tree result
+ int[][] td,//distance tree result
+ ZStream z //for memory allocation
+ )
+ {
+ bl[0] = fixed_bl;
+ bd[0] = fixed_bd;
+ tl[0] = fixed_tl;
+ td[0] = fixed_td;
+ return ZLibStatus.Z_OK;
+ }
+
+ private void InitWorkArea(int vsize)
+ {
+ if (hn == null)
+ {
+ hn = new int[1];
+ v = new int[vsize];
+ c = new int[BMAX + 1];
+ r = new int[3];
+ u = new int[BMAX];
+ x = new int[BMAX + 1];
+ }
+ if (v.Length < vsize) { v = new int[vsize]; }
+ for (int i = 0; i < vsize; i++) { v[i] = 0; }
+ for (int i = 0; i < BMAX + 1; i++) { c[i] = 0; }
+ for (int i = 0; i < 3; i++) { r[i] = 0; }
+ // for(int i=0; i
+ /// Gets the static tree or null
+ ///
+ ///
+ /// The static_tree.
+ ///
+ public short[] TreeData { get; private set; }
+
+ ///
+ /// Gets the extra bits for each code or null.
+ ///
+ ///
+ /// The extra bits.
+ ///
+ public int[] ExtraBits { get; private set; }
+
+ ///
+ /// Gets the base index for extra_bits.
+ ///
+ ///
+ /// The extra base.
+ ///
+ public int ExtraBase { get; private set; }
+
+ ///
+ /// Gets the max number of elements in the tree.
+ ///
+ ///
+ /// The elements.
+ ///
+ public int Elements { get; private set; }
+
+ ///
+ /// Gets the max bit length for the codes.
+ ///
+ ///
+ /// The length of the max.
+ ///
+ public int MaxLength { get; private set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The tree data.
+ /// The extra bits.
+ /// The extra base.
+ /// The elements.
+ /// Length of the max.
+ public StaticTree(short[] treeData, int[] extraBits, int extraBase, int elements, int maxLength)
+ {
+ this.TreeData = treeData;
+ this.ExtraBits = extraBits;
+ this.ExtraBase = extraBase;
+ this.Elements = elements;
+ this.MaxLength = maxLength;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v11/Tree.cs b/Renci.SshNet/Compression/v11/Tree.cs
new file mode 100644
index 0000000..d2142c9
--- /dev/null
+++ b/Renci.SshNet/Compression/v11/Tree.cs
@@ -0,0 +1,334 @@
+using System;
+/*
+ * $Id: Tree.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+ internal sealed class Tree
+ {
+ private const int MAX_BITS = 15;
+
+ private const int LITERALS = 256;
+
+ private const int LENGTH_CODES = 29;
+
+ private const int L_CODES = (LITERALS + 1 + LENGTH_CODES);
+
+ private const int HEAP_SIZE = (2 * L_CODES + 1);
+
+ private static byte[] _dist_code = {
+ 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8,
+ 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17,
+ 18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
+ 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
+ };
+
+
+ ///
+ /// The corresponding static tree
+ ///
+ private StaticTree _staticTree;
+
+ ///
+ /// The dynamic tree
+ ///
+ private short[] _dynamicTree;
+
+ ///
+ /// Gets the largest code with non zero frequency.
+ ///
+ ///
+ /// The max_code.
+ ///
+ public int LargestCode { get; private set; }
+
+ public void Init(short[] dynamicTree, StaticTree staticTree)
+ {
+ this._staticTree = staticTree;
+ this._dynamicTree = dynamicTree;
+ }
+
+ ///
+ /// Mapping from a distance to a distance code. dist is the distance - 1 and must not have side effects. _dist_code[256] and _dist_code[257] are never used.
+ ///
+ /// The dist.
+ ///
+ public static int DistanceCode(int dist)
+ {
+ // TODO: Under multiple port forward after more then 50K requests gets index out of range
+ return ((dist) < 256 ? _dist_code[dist] : _dist_code[256 + ((dist) >> 7)]);
+ }
+
+ ///
+ /// Construct one Huffman tree and assigns the code bit strings and lengths. Update the total bit length for the current block.
+ ///
+ /// The s.
+ public void BuildTree(Deflate s)
+ {
+ short[] tree = _dynamicTree;
+ short[] stree = _staticTree.TreeData;
+ int elems = _staticTree.Elements;
+ int n, m; // iterate over heap elements
+ int max_code = -1; // largest code with non zero frequency
+ int node; // new node being created
+
+ // Construct the initial heap, with least frequent element in
+ // heap[1]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
+ // heap[0] is not used.
+ s.heap_len = 0;
+ s.heap_max = HEAP_SIZE;
+
+ for (n = 0; n < elems; n++)
+ {
+ if (tree[n * 2] != 0)
+ {
+ s.heap[++s.heap_len] = max_code = n;
+ s.depth[n] = 0;
+ }
+ else
+ {
+ tree[n * 2 + 1] = 0;
+ }
+ }
+
+ // The pkzip format requires that at least one distance code exists,
+ // and that at least one bit should be sent even if there is only one
+ // possible code. So to avoid special checks later on we force at least
+ // two codes of non zero frequency.
+ while (s.heap_len < 2)
+ {
+ node = s.heap[++s.heap_len] = (max_code < 2 ? ++max_code : 0);
+ tree[node * 2] = 1;
+ s.depth[node] = 0;
+ s.opt_len--; if (stree != null) s.static_len -= stree[node * 2 + 1];
+ // node is 0 or 1 so it does not have extra bits
+ }
+ this.LargestCode = max_code;
+
+ // The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
+ // establish sub-heaps of increasing lengths:
+
+ for (n = s.heap_len / 2; n >= 1; n--)
+ s.pqdownheap(tree, n);
+
+ // Construct the Huffman tree by repeatedly combining the least two
+ // frequent nodes.
+
+ node = elems; // next internal node of the tree
+ do
+ {
+ // n = node of least frequency
+ n = s.heap[1];
+ s.heap[1] = s.heap[s.heap_len--];
+ s.pqdownheap(tree, 1);
+ m = s.heap[1]; // m = node of next least frequency
+
+ s.heap[--s.heap_max] = n; // keep the nodes sorted by frequency
+ s.heap[--s.heap_max] = m;
+
+ // Create a new node father of n and m
+ tree[node * 2] = (short)(tree[n * 2] + tree[m * 2]);
+ s.depth[node] = (byte)(System.Math.Max(s.depth[n], s.depth[m]) + 1);
+ tree[n * 2 + 1] = tree[m * 2 + 1] = (short)node;
+
+ // and insert the new node in the heap
+ s.heap[1] = node++;
+ s.pqdownheap(tree, 1);
+ }
+ while (s.heap_len >= 2);
+
+ s.heap[--s.heap_max] = s.heap[1];
+
+ // At this point, the fields freq and dad are set. We can now
+ // generate the bit lengths.
+
+ ComputeBitLength(s);
+
+ // The field len is now set, we can generate the bit codes
+ GenerateCodes(tree, max_code, s.bl_count);
+ }
+
+ ///
+ /// Compute the optimal bit lengths for a tree and update the total bit length for the current block.
+ ///
+ /// The s.
+ private void ComputeBitLength(Deflate s)
+ {
+ short[] tree = _dynamicTree;
+ short[] stree = _staticTree.TreeData;
+ int[] extra = _staticTree.ExtraBits;
+ int based = _staticTree.ExtraBase;
+ int max_length = _staticTree.MaxLength;
+ int h; // heap index
+ int n, m; // iterate over the tree elements
+ int bits; // bit length
+ int xbits; // extra bits
+ short f; // frequency
+ int overflow = 0; // number of elements with bit length too large
+
+ for (bits = 0; bits <= MAX_BITS; bits++) s.bl_count[bits] = 0;
+
+ // In a first pass, compute the optimal bit lengths (which may
+ // overflow in the case of the bit length tree).
+ tree[s.heap[s.heap_max] * 2 + 1] = 0; // root of the heap
+
+ for (h = s.heap_max + 1; h < HEAP_SIZE; h++)
+ {
+ n = s.heap[h];
+ bits = tree[tree[n * 2 + 1] * 2 + 1] + 1;
+ if (bits > max_length) { bits = max_length; overflow++; }
+ tree[n * 2 + 1] = (short)bits;
+ // We overwrite tree[n*2+1] which is no longer needed
+
+ if (n > LargestCode) continue; // not a leaf node
+
+ s.bl_count[bits]++;
+ xbits = 0;
+ if (n >= based) xbits = extra[n - based];
+ f = tree[n * 2];
+ s.opt_len += f * (bits + xbits);
+ if (stree != null) s.static_len += f * (stree[n * 2 + 1] + xbits);
+ }
+ if (overflow == 0) return;
+
+ // This happens for example on obj2 and pic of the Calgary corpus
+ // Find the first bit length which could increase:
+ do
+ {
+ bits = max_length - 1;
+ while (s.bl_count[bits] == 0) bits--;
+ s.bl_count[bits]--; // move one leaf down the tree
+ s.bl_count[bits + 1] += 2; // move one overflow item as its brother
+ s.bl_count[max_length]--;
+ // The brother of the overflow item also moves one step up,
+ // but this does not affect bl_count[max_length]
+ overflow -= 2;
+ }
+ while (overflow > 0);
+
+ for (bits = max_length; bits != 0; bits--)
+ {
+ n = s.bl_count[bits];
+ while (n != 0)
+ {
+ m = s.heap[--h];
+ if (m > LargestCode) continue;
+ if (tree[m * 2 + 1] != bits)
+ {
+ s.opt_len += (int)(((long)bits - (long)tree[m * 2 + 1]) * (long)tree[m * 2]);
+ tree[m * 2 + 1] = (short)bits;
+ }
+ n--;
+ }
+ }
+ }
+
+ ///
+ /// Generate the codes for a given tree and bit counts (which need not be optimal).
+ ///
+ /// The tree to decorate.
+ /// The largest code with non zero frequency.
+ /// The number of codes at each bit length.
+ private static void GenerateCodes(short[] tree, int max_code, short[] bl_count)
+ {
+ short[] next_code = new short[MAX_BITS + 1]; // next code value for each bit length
+ short code = 0; // running code value
+ int bits; // bit index
+ int n; // code index
+
+ // The distribution counts are first used to generate the code values
+ // without bit reversal.
+ for (bits = 1; bits <= MAX_BITS; bits++)
+ {
+ next_code[bits] = code = (short)((code + bl_count[bits - 1]) << 1);
+ }
+
+ // Check that the bit counts in bl_count are consistent. The last code
+ // must be all ones.
+ //Assert (code + bl_count[MAX_BITS]-1 == (1<
+ /// Reverse the first len bits of a code, using straightforward code (a faster method would use a table)
+ ///
+ /// The value to invert.
+ /// The bit length.
+ ///
+ private static int BiReverse(int code, int len)
+ {
+ int res = 0;
+ do
+ {
+ res |= code & 1;
+ code >>= 1;
+ res <<= 1;
+ }
+ while (--len > 0);
+ return res >> 1;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v11/ZInputStream.cs b/Renci.SshNet/Compression/v11/ZInputStream.cs
new file mode 100644
index 0000000..0ef972c
--- /dev/null
+++ b/Renci.SshNet/Compression/v11/ZInputStream.cs
@@ -0,0 +1,202 @@
+/*
+Copyright (c) 2001 Lapo Luchini.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS
+OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+/* This file is a port of jzlib v1.0.7, com.jcraft.jzlib.ZInputStream.java
+ */
+
+using Renci.SshNet.Compression;
+using System;
+using System.Diagnostics;
+using System.IO;
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+ public class ZInputStream : Stream
+ {
+ private const int BufferSize = 512;
+ //private ZStream z = new ZStream();
+ private ICompressor _compressor;
+
+ // TODO Allow custom buf
+ private byte[] _buffer = new byte[BufferSize];
+ private CompressionMode _compressionMode;
+ private Stream _input;
+ private bool _isClosed;
+ private bool _noMoreInput = false;
+
+ public FlushType FlushMode { get; private set; }
+
+ public ZInputStream()
+ {
+ this.FlushMode = FlushType.Z_PARTIAL_FLUSH;
+ }
+
+ public ZInputStream(Stream input)
+ : this(input, false)
+ {
+ }
+
+ public ZInputStream(Stream input, bool nowrap)
+ : this()
+ {
+ Debug.Assert(input.CanRead);
+
+ this._input = input;
+ this._compressor = new Inflate(nowrap);
+ //this._compressor.inflateInit(nowrap);
+ this._compressionMode = CompressionMode.Decompress;
+ this._compressor.next_in = _buffer;
+ this._compressor.next_in_index = 0;
+ this._compressor.avail_in = 0;
+ }
+
+ public ZInputStream(Stream input, CompressionLevel level)
+ : this()
+ {
+ Debug.Assert(input.CanRead);
+
+ this._input = input;
+ this._compressor = new Deflate(level);
+ //this._compressor.deflateInit(level);
+ this._compressionMode = CompressionMode.Compress;
+ this._compressor.next_in = _buffer;
+ this._compressor.next_in_index = 0;
+ this._compressor.avail_in = 0;
+ }
+
+ #region Stream implementation
+
+ public sealed override bool CanRead
+ {
+ get { return !_isClosed; }
+ }
+
+ public sealed override bool CanSeek
+ {
+ get { return false; }
+ }
+
+ public sealed override bool CanWrite
+ {
+ get { return false; }
+ }
+
+ public override void Flush()
+ {
+ }
+
+ public override long Length
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ public override long Position
+ {
+ get { throw new NotSupportedException(); }
+ set { throw new NotSupportedException(); }
+ }
+
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ if (count == 0)
+ return 0;
+
+ //this._compressor.next_out = buffer;
+ //this._compressor.next_out_index = offset;
+ //this._compressor.avail_out = count;
+
+ ZLibStatus err = ZLibStatus.Z_OK;
+ do
+ {
+ if (this._compressor.avail_in == 0 && !_noMoreInput)
+ {
+ // if buffer is empty and more input is available, refill it
+ this._compressor.next_in_index = 0;
+ this._compressor.avail_in = _input.Read(_buffer, 0, _buffer.Length); //(bufsize 0 || this._compressor.avail_out == 0);
+ }
+
+ #endregion
+
+ public override void Close()
+ {
+ if (this._isClosed)
+ return;
+
+ try
+ {
+ try
+ {
+ Finish();
+ }
+ catch (IOException)
+ {
+ // Ignore
+ }
+ }
+ finally
+ {
+ this._isClosed = true;
+ End();
+ _output.Close();
+ _output = null;
+ }
+ }
+
+ private void End()
+ {
+ if (this._compressor == null)
+ return;
+ switch (this._compressionMode)
+ {
+ case CompressionMode.Compress:
+ this._compressor.deflateEnd();
+ break;
+ case CompressionMode.Decompress:
+ this._compressor.inflateEnd();
+ break;
+ default:
+ break;
+ }
+
+ //this._compressor.free();
+ this._compressor = null;
+ }
+
+ private void Finish()
+ {
+ do
+ {
+ var err = ZLibStatus.Z_OK;
+ switch (this._compressionMode)
+ {
+ case CompressionMode.Compress:
+ err = this._compressor.deflate(_buffer, 0, _buffer.Length, FlushType.Z_FINISH);
+ break;
+ case CompressionMode.Decompress:
+ err = this._compressor.inflate(_buffer, 0, _buffer.Length, FlushType.Z_FINISH);
+ break;
+ default:
+ break;
+ }
+
+ if (err != ZLibStatus.Z_STREAM_END && err != ZLibStatus.Z_OK)
+ // TODO
+ // throw new ZStreamException((compress?"de":"in")+"flating: "+z.msg);
+ //throw new IOException((_compressionMode ? "de" : "in") + "flating: " + z.msg);
+ throw new IOException(string.Format("{0}ion error: {1}", _compressionMode, err));
+
+ int count = _buffer.Length - this._compressor.avail_out;
+ if (count > 0)
+ {
+ _output.Write(_buffer, 0, count);
+ }
+ }
+ while (this._compressor.avail_in > 0 || this._compressor.avail_out == 0);
+
+ Flush();
+ }
+ }
+}
diff --git a/Renci.SshNet/Compression/v11/ZStream.cs b/Renci.SshNet/Compression/v11/ZStream.cs
new file mode 100644
index 0000000..b151ba1
--- /dev/null
+++ b/Renci.SshNet/Compression/v11/ZStream.cs
@@ -0,0 +1,94 @@
+using System;
+using System.IO;
+/*
+ * $Id: ZStream.cs,v 1.1 2006-07-31 13:59:26 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public interface ICompressor
+ {
+ ZLibStatus deflate(byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType);
+ ZLibStatus deflate(byte[] bufer, int offset, int count, byte[] p1, int p2, int p3, FlushType flushType);
+
+ ZLibStatus deflateEnd();
+
+ ZLibStatus inflate(byte[] bufer, int offset, int count, byte[] p1, int p2, int p3, FlushType flushType);
+ ZLibStatus inflate(byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType);
+
+ ZLibStatus inflateEnd();
+
+ //ZLibStatus inflate(FlushType flushType);
+
+ int avail_out { get; set; }
+
+ int avail_in { get; set; }
+
+ //int next_out_index { get; set; }
+
+ //byte[] next_out { get; set; }
+
+ byte[] next_in { get; set; }
+
+ int next_in_index { get; set; }
+ }
+
+
+ public abstract class ZStream
+ {
+
+ protected const int MAX_WBITS = 15; // 32K LZ77 window
+ protected const int DEF_WBITS = MAX_WBITS;
+
+ private const int MAX_MEM_LEVEL = 9;
+
+ public byte[] next_in { get; set; } // next input byte
+ public int next_in_index { get; set; }
+ public int avail_in { get; set; } // number of bytes available at next_in
+ public long total_in { get; set; } // total nb of input bytes read so far
+
+ public byte[] next_out { get; set; } // next output byte should be put there
+ public int next_out_index { get; set; }
+ public int avail_out { get; set; } // remaining free space at next_out
+ public long total_out { get; set; } // total nb of bytes output so far
+
+ public String msg { get; set; }
+
+ internal BlockType data_type; // best guess about the data type: ascii or binary
+
+ public long adler;
+
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v11/Zlib.cs b/Renci.SshNet/Compression/v11/Zlib.cs
new file mode 100644
index 0000000..5890675
--- /dev/null
+++ b/Renci.SshNet/Compression/v11/Zlib.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Represents "zlib" compression implementation
+ ///
+ internal class Zlib : Compressor
+ {
+ ///
+ /// Gets algorithm name.
+ ///
+ public override string Name
+ {
+ get { return "zlib"; }
+ }
+
+ ///
+ /// Initializes the algorithm
+ ///
+ /// The session.
+ public override void Init(Session session)
+ {
+ base.Init(session);
+ this.IsActive = true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v11/ZlibOpenSsh.cs b/Renci.SshNet/Compression/v11/ZlibOpenSsh.cs
new file mode 100644
index 0000000..f82a4c0
--- /dev/null
+++ b/Renci.SshNet/Compression/v11/ZlibOpenSsh.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Represents "zlib@openssh.org" compression implementation
+ ///
+ public class ZlibOpenSsh : Compressor
+ {
+ ///
+ /// Gets algorithm name.
+ ///
+ public override string Name
+ {
+ get { return "zlib@openssh.org"; }
+ }
+
+ ///
+ /// Initializes the algorithm
+ ///
+ /// The session.
+ public override void Init(Session session)
+ {
+ base.Init(session);
+
+ session.UserAuthenticationSuccessReceived += Session_UserAuthenticationSuccessReceived;
+ }
+
+ private void Session_UserAuthenticationSuccessReceived(object sender, MessageEventArgs e)
+ {
+ this.IsActive = true;
+ this.Session.UserAuthenticationSuccessReceived -= Session_UserAuthenticationSuccessReceived;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v11/ZlibStream.cs b/Renci.SshNet/Compression/v11/ZlibStream.cs
new file mode 100644
index 0000000..fb5f9d2
--- /dev/null
+++ b/Renci.SshNet/Compression/v11/ZlibStream.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.IO;
+using Org.BouncyCastle.Utilities.Zlib;
+
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Implements Zlib compression algorithm.
+ ///
+ public class ZlibStream
+ {
+ private readonly Stream _baseStream;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The stream.
+ /// The mode.
+ public ZlibStream(Stream stream, CompressionMode mode)
+ {
+ switch (mode)
+ {
+ case CompressionMode.Compress:
+ //this._baseStream = new ZOutputStream(stream, CompressionLevel.Z_DEFAULT_COMPRESSION);
+ this._baseStream = new ZOutputStream(stream, CompressionLevel.Z_DEFAULT_COMPRESSION);
+ break;
+ case CompressionMode.Decompress:
+ this._baseStream = new ZOutputStream(stream);
+ break;
+ default:
+ break;
+ }
+
+ //this._baseStream.FlushMode = Ionic.Zlib.FlushType.Partial;
+ }
+
+ ///
+ /// Writes the specified buffer.
+ ///
+ /// The buffer.
+ /// The offset.
+ /// The count.
+ public void Write(byte[] buffer, int offset, int count)
+ {
+ this._baseStream.Write(buffer, offset, count);
+ }
+ }
+}
diff --git a/Renci.SshNet/Compression/v12/Adler32.cs b/Renci.SshNet/Compression/v12/Adler32.cs
new file mode 100644
index 0000000..c132fa9
--- /dev/null
+++ b/Renci.SshNet/Compression/v12/Adler32.cs
@@ -0,0 +1,95 @@
+using System;
+/*
+ * $Id: Adler32.cs,v 1.1 2006-07-31 13:59:25 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ internal static class Adler32
+ {
+
+ // largest prime smaller than 65536
+ private const int BASE = 65521;
+ // NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
+ private const int NMAX = 5552;
+
+ internal static long adler32(long adler, byte[] buf, int index, int len)
+ {
+ if (buf == null) { return 1L; }
+
+ long s1 = adler & 0xffff;
+ long s2 = (adler >> 16) & 0xffff;
+ int k;
+
+ while (len > 0)
+ {
+ k = len < NMAX ? len : NMAX;
+ len -= k;
+ while (k >= 16)
+ {
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ k -= 16;
+ }
+ if (k != 0)
+ {
+ do
+ {
+ s1 += buf[index++] & 0xff; s2 += s1;
+ }
+ while (--k != 0);
+ }
+ s1 %= BASE;
+ s2 %= BASE;
+ }
+ return (s2 << 16) | s1;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v12/CompressionMode.cs b/Renci.SshNet/Compression/v12/CompressionMode.cs
new file mode 100644
index 0000000..1577e0b
--- /dev/null
+++ b/Renci.SshNet/Compression/v12/CompressionMode.cs
@@ -0,0 +1,18 @@
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Specifies compression modes
+ ///
+ public enum CompressionMode
+ {
+ ///
+ /// Specifies that content should be compressed.
+ ///
+ Compress = 0,
+
+ ///
+ /// Specifies that content should be decompressed.
+ ///
+ Decompress = 1,
+ }
+}
diff --git a/Renci.SshNet/Compression/v12/Compressor.cs b/Renci.SshNet/Compression/v12/Compressor.cs
new file mode 100644
index 0000000..1479bb6
--- /dev/null
+++ b/Renci.SshNet/Compression/v12/Compressor.cs
@@ -0,0 +1,151 @@
+using System.Collections.Generic;
+using Renci.SshNet.Security;
+using System.IO;
+using System;
+
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Represents base class for compression algorithm implementation
+ ///
+ public abstract class Compressor : Algorithm, IDisposable
+ {
+ private readonly ZlibStream _compressor;
+ private readonly ZlibStream _decompressor;
+
+ private MemoryStream _compressorStream;
+ private MemoryStream _decompressorStream;
+
+ ///
+ /// Gets or sets a value indicating whether compression is active.
+ ///
+ ///
+ /// true if compression is active; otherwise, false.
+ ///
+ protected bool IsActive { get; set; }
+
+ ///
+ /// Gets the session.
+ ///
+ protected Session Session { get; private set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ 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);
+ }
+
+ ///
+ /// Initializes the algorithm
+ ///
+ /// The session.
+ public virtual void Init(Session session)
+ {
+ this.Session = session;
+ }
+
+ ///
+ /// Compresses the specified data.
+ ///
+ /// Data to compress.
+ /// Compressed 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();
+ }
+
+ ///
+ /// Decompresses the specified data.
+ ///
+ /// Compressed data.
+ /// Decompressed 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;
+
+ ///
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged ResourceMessages.
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Releases unmanaged and - optionally - managed resources
+ ///
+ /// true to release both managed and unmanaged resources; false to release only unmanaged ResourceMessages.
+ 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;
+ }
+ }
+
+ ///
+ /// Releases unmanaged resources and performs other cleanup operations before the
+ /// is reclaimed by garbage collection.
+ ///
+ ~Compressor()
+ {
+ // Do not re-create Dispose clean-up code here.
+ // Calling Dispose(false) is optimal in terms of
+ // readability and maintainability.
+ Dispose(false);
+ }
+
+ #endregion
+ }
+}
diff --git a/Renci.SshNet/Compression/v12/Deflate.cs b/Renci.SshNet/Compression/v12/Deflate.cs
new file mode 100644
index 0000000..cc42021
--- /dev/null
+++ b/Renci.SshNet/Compression/v12/Deflate.cs
@@ -0,0 +1,2225 @@
+using System;
+using System.Collections.Generic;
+/*
+ * $Id: Deflate.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public enum BlockType : byte
+ {
+ Z_BINARY = 0,
+ Z_ASCII = 1,
+ Z_UNKNOWN = 2
+ }
+
+ public enum DefalteFlavor : int
+ {
+ STORED = 0,
+ FAST = 1,
+ SLOW = 2
+ }
+
+ public sealed class Deflate : ZStream, ICompressor
+ {
+ private const int MAX_MEM_LEVEL = 9;
+
+ private const int Z_DEFAULT_COMPRESSION = -1;
+
+ private const int MAX_WBITS = 15; // 32K LZ77 window
+
+ private const int DEF_MEM_LEVEL = 8;
+
+ ///
+ /// The Bit length codes must not exceed MAX_BL_BITS bits
+ ///
+ private const int MAX_BL_BITS = 7;
+
+ // block not completed, need more input or more output
+ private const int NeedMore = 0;
+
+ // block flush performed
+ private const int BlockDone = 1;
+
+ // finish started, need only more output at next deflate
+ private const int FinishStarted = 2;
+
+ // finish done, accept no more input or output
+ private const int FinishDone = 3;
+
+ // preset dictionary flag in zlib header
+ private const int PRESET_DICT = 0x20;
+
+ private const int Z_VERSION_ERROR = -6;
+
+ private const int INIT_STATE = 42;
+ private const int BUSY_STATE = 113;
+ private const int FINISH_STATE = 666;
+
+ // The deflate compression method
+ private const int Z_DEFLATED = 8;
+
+ private const int STORED_BLOCK = 0;
+ private const int STATIC_TREES = 1;
+ private const int DYN_TREES = 2;
+
+ private const int Buf_size = 8 * 2;
+
+ // repeat previous bit length 3-6 times (2 bits of repeat count)
+ private const int REP_3_6 = 16;
+
+ // repeat a zero length 3-10 times (3 bits of repeat count)
+ private const int REPZ_3_10 = 17;
+
+ // repeat a zero length 11-138 times (7 bits of repeat count)
+ private const int REPZ_11_138 = 18;
+
+ private const int MIN_MATCH = 3;
+ private const int MAX_MATCH = 258;
+ private const int MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1);
+
+ private const int MAX_BITS = 15;
+ private const int D_CODES = 30;
+ private const int BL_CODES = 19;
+ private const int LENGTH_CODES = 29;
+ private const int LITERALS = 256;
+ private const int L_CODES = (LITERALS + 1 + LENGTH_CODES);
+ private const int HEAP_SIZE = (2 * L_CODES + 1);
+
+ private const int END_BLOCK = 256;
+
+ private static readonly IDictionary config_table = new Dictionary() {
+ {(CompressionLevel)0, new Config(0, 0, 0, 0, DefalteFlavor.STORED)},
+ {(CompressionLevel)1, new Config(4, 4, 8, 4, DefalteFlavor.FAST)},
+ {(CompressionLevel)2, new Config(4, 5, 16, 8, DefalteFlavor.FAST)},
+ {(CompressionLevel)3, new Config(4, 6, 32, 32, DefalteFlavor.FAST)},
+
+ {(CompressionLevel)4, new Config(4, 4, 16, 16, DefalteFlavor.SLOW)},
+ {(CompressionLevel)5, new Config(8, 16, 32, 32, DefalteFlavor.SLOW)},
+ {(CompressionLevel)6, new Config(8, 16, 128, 128, DefalteFlavor.SLOW)},
+ {(CompressionLevel)7, new Config(8, 32, 128, 256, DefalteFlavor.SLOW)},
+ {(CompressionLevel)8, new Config(32, 128, 258, 1024, DefalteFlavor.SLOW)},
+ {(CompressionLevel)9, new Config(32, 258, 258, 4096, DefalteFlavor.SLOW)},
+ };
+
+ #region Static definitions
+
+ private static readonly byte[] _length_code ={
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12,
+ 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
+ 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
+ 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
+ };
+
+ private static readonly int[] base_length = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
+ 64, 80, 96, 112, 128, 160, 192, 224, 0
+ };
+
+ private static readonly int[] base_dist = {
+ 0, 1, 2, 3, 4, 6, 8, 12, 16, 24,
+ 32, 48, 64, 96, 128, 192, 256, 384, 512, 768,
+ 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576
+ };
+
+ // extra bits for each length code
+ private static readonly int[] extra_lbits ={
+ 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0
+ };
+
+ // extra bits for each distance code
+ private static readonly int[] extra_dbits ={
+ 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13
+ };
+
+ // extra bits for each bit length code
+ private static readonly int[] extra_blbits ={
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7
+ };
+
+ private static readonly byte[] bl_order ={
+ 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
+
+ private static readonly short[] static_ltree = {
+ 12, 8, 140, 8, 76, 8, 204, 8, 44, 8,
+ 172, 8, 108, 8, 236, 8, 28, 8, 156, 8,
+ 92, 8, 220, 8, 60, 8, 188, 8, 124, 8,
+ 252, 8, 2, 8, 130, 8, 66, 8, 194, 8,
+ 34, 8, 162, 8, 98, 8, 226, 8, 18, 8,
+ 146, 8, 82, 8, 210, 8, 50, 8, 178, 8,
+ 114, 8, 242, 8, 10, 8, 138, 8, 74, 8,
+ 202, 8, 42, 8, 170, 8, 106, 8, 234, 8,
+ 26, 8, 154, 8, 90, 8, 218, 8, 58, 8,
+ 186, 8, 122, 8, 250, 8, 6, 8, 134, 8,
+ 70, 8, 198, 8, 38, 8, 166, 8, 102, 8,
+ 230, 8, 22, 8, 150, 8, 86, 8, 214, 8,
+ 54, 8, 182, 8, 118, 8, 246, 8, 14, 8,
+ 142, 8, 78, 8, 206, 8, 46, 8, 174, 8,
+ 110, 8, 238, 8, 30, 8, 158, 8, 94, 8,
+ 222, 8, 62, 8, 190, 8, 126, 8, 254, 8,
+ 1, 8, 129, 8, 65, 8, 193, 8, 33, 8,
+ 161, 8, 97, 8, 225, 8, 17, 8, 145, 8,
+ 81, 8, 209, 8, 49, 8, 177, 8, 113, 8,
+ 241, 8, 9, 8, 137, 8, 73, 8, 201, 8,
+ 41, 8, 169, 8, 105, 8, 233, 8, 25, 8,
+ 153, 8, 89, 8, 217, 8, 57, 8, 185, 8,
+ 121, 8, 249, 8, 5, 8, 133, 8, 69, 8,
+ 197, 8, 37, 8, 165, 8, 101, 8, 229, 8,
+ 21, 8, 149, 8, 85, 8, 213, 8, 53, 8,
+ 181, 8, 117, 8, 245, 8, 13, 8, 141, 8,
+ 77, 8, 205, 8, 45, 8, 173, 8, 109, 8,
+ 237, 8, 29, 8, 157, 8, 93, 8, 221, 8,
+ 61, 8, 189, 8, 125, 8, 253, 8, 19, 9,
+ 275, 9, 147, 9, 403, 9, 83, 9, 339, 9,
+ 211, 9, 467, 9, 51, 9, 307, 9, 179, 9,
+ 435, 9, 115, 9, 371, 9, 243, 9, 499, 9,
+ 11, 9, 267, 9, 139, 9, 395, 9, 75, 9,
+ 331, 9, 203, 9, 459, 9, 43, 9, 299, 9,
+ 171, 9, 427, 9, 107, 9, 363, 9, 235, 9,
+ 491, 9, 27, 9, 283, 9, 155, 9, 411, 9,
+ 91, 9, 347, 9, 219, 9, 475, 9, 59, 9,
+ 315, 9, 187, 9, 443, 9, 123, 9, 379, 9,
+ 251, 9, 507, 9, 7, 9, 263, 9, 135, 9,
+ 391, 9, 71, 9, 327, 9, 199, 9, 455, 9,
+ 39, 9, 295, 9, 167, 9, 423, 9, 103, 9,
+ 359, 9, 231, 9, 487, 9, 23, 9, 279, 9,
+ 151, 9, 407, 9, 87, 9, 343, 9, 215, 9,
+ 471, 9, 55, 9, 311, 9, 183, 9, 439, 9,
+ 119, 9, 375, 9, 247, 9, 503, 9, 15, 9,
+ 271, 9, 143, 9, 399, 9, 79, 9, 335, 9,
+ 207, 9, 463, 9, 47, 9, 303, 9, 175, 9,
+ 431, 9, 111, 9, 367, 9, 239, 9, 495, 9,
+ 31, 9, 287, 9, 159, 9, 415, 9, 95, 9,
+ 351, 9, 223, 9, 479, 9, 63, 9, 319, 9,
+ 191, 9, 447, 9, 127, 9, 383, 9, 255, 9,
+ 511, 9, 0, 7, 64, 7, 32, 7, 96, 7,
+ 16, 7, 80, 7, 48, 7, 112, 7, 8, 7,
+ 72, 7, 40, 7, 104, 7, 24, 7, 88, 7,
+ 56, 7, 120, 7, 4, 7, 68, 7, 36, 7,
+ 100, 7, 20, 7, 84, 7, 52, 7, 116, 7,
+ 3, 8, 131, 8, 67, 8, 195, 8, 35, 8,
+ 163, 8, 99, 8, 227, 8
+ };
+
+ private static readonly short[] static_dtree = {
+ 0, 5, 16, 5, 8, 5, 24, 5, 4, 5,
+ 20, 5, 12, 5, 28, 5, 2, 5, 18, 5,
+ 10, 5, 26, 5, 6, 5, 22, 5, 14, 5,
+ 30, 5, 1, 5, 17, 5, 9, 5, 25, 5,
+ 5, 5, 21, 5, 13, 5, 29, 5, 3, 5,
+ 19, 5, 11, 5, 27, 5, 7, 5, 23, 5
+ };
+ #endregion
+
+ private static readonly String[] z_errmsg = {
+ "need dictionary", // ZLibStatus.Z_NEED_DICT 2
+ "stream end", // ZLibStatus.Z_STREAM_END 1
+ "", // ZLibStatus.Z_OK 0
+ "file error", // ZLibStatus.Z_ERRNO (-1)
+ "stream error", // ZLibStatus.Z_STREAM_ERROR (-2)
+ "data error", // ZLibStatus.Z_DATA_ERROR (-3)
+ "insufficient memory", // Z_MEM_ERROR (-4)
+ "buffer error", // ZLibStatus.Z_BUF_ERROR (-5)
+ "incompatible version",// Z_VERSION_ERROR (-6)
+ ""
+ };
+
+
+
+ ///
+ /// as the name implies
+ ///
+ private int _status;
+
+ private BlockType _dataType;
+
+ ///
+ /// STORED (for zip only) or DEFLATED
+ ///
+ private byte _method;
+
+ ///
+ /// size of pending_buf
+ ///
+ private int _pendingBufferSize;
+
+ ///
+ /// LZ77 window size (32K by default)
+ ///
+ private int _windowSize;
+
+ ///
+ /// log2(w_size) (8..16)
+ ///
+ private int _windowBits;
+
+ ///
+ /// w_size - 1
+ ///
+ private int _windowMask;
+
+ ///
+ /// Sliding window. Input bytes are read into the second half of the window,
+ /// and move to the first half later to keep a dictionary of at least wSize
+ /// bytes. With this organization, matches are limited to a distance of
+ /// wSize-MAX_MATCH bytes, but this ensures that IO is always
+ /// performed with a length multiple of the block size. Also, it limits
+ /// the window size to 64K, which is quite useful on MSDOS.
+ /// To do: use the user input buffer as sliding window.
+ ///
+ private byte[] _window;
+
+ ///
+ /// Actual size of window: 2*wSize, except when the user input buffer
+ /// is directly used as sliding window.
+ ///
+ private int _windowActualSize;
+
+ ///
+ /// Link to older string with same hash index. To limit the size of this
+ /// array to 64K, this link is maintained only for the last 32K strings.
+ /// An index in this array is thus a window index modulo 32K.
+ ///
+ private short[] _previous;
+
+ ///
+ /// Heads of the hash chains or NIL.
+ ///
+ private short[] _head;
+
+ ///
+ /// hash index of string to be inserted
+ ///
+ private int _insertedHashIndex;
+
+ ///
+ /// number of elements in hash table
+ ///
+ private int _hashSize;
+
+ ///
+ /// log2(hash_size)
+ ///
+ private int _hashBits;
+
+ ///
+ /// hash_size-1
+ ///
+ private int _hashMask;
+
+ ///
+ /// Number of bits by which ins_h must be shifted at each input
+ /// step. It must be such that after MIN_MATCH steps, the oldest
+ /// byte no longer takes part in the hash key, that is:
+ /// hash_shift * MIN_MATCH >= hash_bits
+ ///
+ private int _hashShift;
+
+ ///
+ /// Window position at the beginning of the current output block. Gets
+ /// negative when the window is moved backwards.
+ ///
+ private int _blockStart;
+
+ ///
+ /// length of best match
+ ///
+ private int _matchLength;
+
+ ///
+ /// previous match
+ ///
+ private int _previousMatch;
+
+ ///
+ /// set if previous match exists
+ ///
+ private bool _matchAvailable;
+
+ ///
+ /// start of string to insert
+ ///
+ private int _startInsertString;
+
+ ///
+ /// start of matching string
+ ///
+ private int _startMatchString;
+
+ ///
+ /// number of valid bytes ahead in window
+ ///
+ private int _validBytesAhead;
+
+ ///
+ /// Length of the best match at previous step. Matches not greater than this
+ /// are discarded. This is used in the lazy match evaluation.
+ ///
+ private int _previousLength;
+
+ ///
+ /// To speed up deflation, hash chains are never searched beyond this
+ /// length. A higher limit improves compression ratio but degrades the speed.
+ ///
+ private int _maxChainLength;
+
+ ///
+ /// Attempt to find a better match only when the current match is strictly
+ /// smaller than this value. This mechanism is used only for compression
+ /// levels >= 4.
+ ///
+ private int _maxLazyMatch;
+
+ // Insert new strings in the hash table only if the match length is not
+ // greater than this length. This saves time but degrades compression.
+ // max_insert_length is used only for compression levels <= 3.
+
+ ///
+ /// The compression level (1..9)
+ ///
+ private CompressionLevel level;
+
+ ///
+ /// The favor or force Huffman coding
+ ///
+ private CompressionStrategy strategy;
+
+ ///
+ /// Use a faster search when the previous match is longer than this
+ ///
+ private int good_match;
+
+ ///
+ /// Stop searching when current match exceeds this
+ ///
+ private int nice_match;
+
+ ///
+ /// literal and length tree
+ ///
+ private short[] dyn_ltree;
+
+ ///
+ /// The distance tree
+ ///
+ private short[] dyn_dtree;
+
+ ///
+ /// The Huffman tree for bit lengths
+ ///
+ private short[] bl_tree;
+
+ ///
+ /// The desc for literal tree
+ ///
+ private Tree l_desc = new Tree();
+
+ ///
+ /// The desc for distance tree
+ ///
+ private Tree d_desc = new Tree();
+
+ ///
+ /// The desc for bit length tree
+ ///
+ private Tree bl_desc = new Tree();
+
+ ///
+ /// index for literals or lengths
+ ///
+ private int l_buf;
+
+ ///
+ /// Size of match buffer for literals/lengths. There are 4 reasons for
+ /// limiting lit_bufsize to 64K:
+ /// - frequencies can be kept in 16 bit counters
+ /// - if compression is not successful for the first block, all input
+ /// data is still in the window so we can still emit a stored block even
+ /// when input comes from standard input. (This can also be done for
+ /// all blocks if lit_bufsize is not greater than 32K.)
+ /// - if compression is not successful for a file smaller than 64K, we can
+ /// even emit a stored file instead of a stored block (saving 5 bytes).
+ /// This is applicable only for zip (not gzip or zlib).
+ /// - creating new Huffman trees less frequently may not provide fast
+ /// adaptation to changes in the input data statistics. (Take for
+ /// example a binary file with poorly compressible code followed by
+ /// a highly compressible string table.) Smaller buffer sizes give
+ /// fast adaptation but have of course the overhead of transmitting
+ /// trees more frequently.
+ /// - I can't count above 4
+ ///
+ private int lit_bufsize;
+
+ ///
+ /// running index in l_buf
+ ///
+ private int last_lit;
+
+ // Buffer for distances. To simplify the code, d_buf and l_buf have
+ // the same number of elements. To use different lengths, an extra flag
+ // array would be necessary.
+
+ ///
+ /// The index of pendig_buf
+ ///
+ private int d_buf;
+
+ ///
+ /// The number of string matches in current block
+ ///
+ private int matches;
+
+ ///
+ /// The bit length of EOB code for last block
+ ///
+ private int last_eob_len;
+
+ ///
+ /// Output buffer. bits are inserted starting at the bottom (least
+ /// significant bits).
+ ///
+ private uint bi_buf;
+
+ ///
+ /// Number of valid bits in bi_buf. All bits above the last valid bit
+ /// are always zero.
+ ///
+ private int bi_valid;
+
+ ///
+ /// value of flush param for previous deflate call
+ ///
+ private FlushType last_flush;
+
+ ///
+ /// bit length of current block with optimal trees
+ ///
+ internal int opt_len;
+
+ ///
+ /// bit length of current block with static trees
+ ///
+ internal int static_len;
+
+ ///
+ /// The output still pending
+ ///
+ internal byte[] pending_buf;
+
+ ///
+ /// next pending byte to output to the stream
+ ///
+ internal int pending_out;
+
+ ///
+ /// nb of bytes in the pending buffer
+ ///
+ internal int pending;
+
+ ///
+ /// suppress zlib header and adler32
+ ///
+ internal int noheader;
+
+ ///
+ /// number of codes at each bit length for an optimal tree
+ ///
+ internal short[] bl_count = new short[MAX_BITS + 1];
+
+ ///
+ /// heap used to build the Huffman trees
+ ///
+ internal int[] heap = new int[2 * L_CODES + 1];
+
+ ///
+ /// The number of elements in the heap
+ ///
+ internal int heap_len;
+ ///
+ /// The element of largest frequency
+ ///
+ internal int heap_max;
+
+ // The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+ // The same heap array is used to build all trees.
+
+ ///
+ /// Depth of each subtree used as tie breaker for trees of equal frequency
+ ///
+ internal byte[] depth = new byte[2 * L_CODES + 1];
+
+ public Deflate()
+ {
+ dyn_ltree = new short[HEAP_SIZE * 2];
+ dyn_dtree = new short[(2 * D_CODES + 1) * 2]; // distance tree
+ bl_tree = new short[(2 * BL_CODES + 1) * 2]; // Huffman tree for bit lengths
+ }
+
+ public Deflate(CompressionLevel level)
+ : this()
+ {
+ this.deflateInit(level);
+ }
+
+ public Deflate(CompressionLevel level, bool nowrap)
+ : this()
+ {
+ this.deflateInit(level, nowrap);
+ }
+
+ // Restore the heap property by moving down the tree starting at node k,
+ // exchanging a node with the smallest of its two sons if necessary, stopping
+ // when the heap property is re-established (each father smaller than its
+ // two sons).
+ internal void pqdownheap(short[] tree, // the tree to restore
+ int k // node to move down
+ )
+ {
+ int v = heap[k];
+ int j = k << 1; // left son of k
+ while (j <= heap_len)
+ {
+ // Set j to the smallest of the two sons:
+ if (j < heap_len &&
+ smaller(tree, heap[j + 1], heap[j], depth))
+ {
+ j++;
+ }
+ // Exit if v is smaller than both sons
+ if (smaller(tree, v, heap[j], depth)) break;
+
+ // Exchange v with the smallest son
+ heap[k] = heap[j]; k = j;
+ // And continue down the tree, setting j to the left son of k
+ j <<= 1;
+ }
+ heap[k] = v;
+ }
+
+ public ZLibStatus deflateInit(CompressionLevel level)
+ {
+ return deflateInit(level, MAX_WBITS);
+ }
+ public ZLibStatus deflateInit(CompressionLevel level, bool nowrap)
+ {
+ return deflateInit(level, MAX_WBITS, nowrap);
+ }
+ public ZLibStatus deflateInit(CompressionLevel level, int bits, bool nowrap)
+ {
+ return this.deflateInit(level, nowrap ? -bits : bits);
+ }
+
+ internal ZLibStatus deflateInit(CompressionLevel level, int bits)
+ {
+ return deflateInit2(level, Z_DEFLATED, bits, DEF_MEM_LEVEL, CompressionStrategy.Z_DEFAULT_STRATEGY);
+ }
+
+ private ZLibStatus deflateInit2(CompressionLevel level, int method, int windowBits, int memLevel, CompressionStrategy strategy)
+ {
+ int noheader = 0;
+ // byte[] my_version=ZLIB_VERSION;
+
+ //
+ // if (version == null || version[0] != my_version[0]
+ // || stream_size != sizeof(z_stream)) {
+ // return Z_VERSION_ERROR;
+ // }
+
+ base.msg = null;
+
+ if (level == CompressionLevel.Z_DEFAULT_COMPRESSION) level = (CompressionLevel)6;
+
+ if (windowBits < 0)
+ { // undocumented feature: suppress zlib header
+ noheader = 1;
+ windowBits = -windowBits;
+ }
+
+ if (memLevel < 1 || memLevel > MAX_MEM_LEVEL ||
+ method != Z_DEFLATED ||
+ windowBits < 9 || windowBits > 15 || level < 0 || level > (CompressionLevel)9 ||
+ strategy < 0 || strategy > CompressionStrategy.Z_HUFFMAN_ONLY)
+ {
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+
+ this.noheader = noheader;
+ _windowBits = windowBits;
+ _windowSize = 1 << _windowBits;
+ _windowMask = _windowSize - 1;
+
+ _hashBits = memLevel + 7;
+ _hashSize = 1 << _hashBits;
+ _hashMask = _hashSize - 1;
+ _hashShift = ((_hashBits + MIN_MATCH - 1) / MIN_MATCH);
+
+ _window = new byte[_windowSize * 2];
+ _previous = new short[_windowSize];
+ _head = new short[_hashSize];
+
+ lit_bufsize = 1 << (memLevel + 6); // 16K elements by default
+
+ // We overlay pending_buf and d_buf+l_buf. This works since the average
+ // output size for (length,distance) codes is <= 24 bits.
+ pending_buf = new byte[lit_bufsize * 4];
+ _pendingBufferSize = lit_bufsize * 4;
+
+ d_buf = lit_bufsize / 2;
+ l_buf = (1 + 2) * lit_bufsize;
+
+ this.level = level;
+
+ //System.out.println("level="+level);
+
+ this.strategy = strategy;
+ this._method = (byte)method;
+
+ return deflateReset();
+ }
+
+ private ZLibStatus deflateReset()
+ {
+ base.total_in = base.total_out = 0;
+ base.msg = null; //
+ base.data_type = BlockType.Z_UNKNOWN;
+
+ pending = 0;
+ pending_out = 0;
+
+ if (noheader < 0)
+ {
+ noheader = 0; // was set to -1 by deflate(..., FlushType.Z_FINISH);
+ }
+ _status = (noheader != 0) ? BUSY_STATE : INIT_STATE;
+ base.adler = Adler32.adler32(0, null, 0, 0);
+
+ last_flush = FlushType.Z_NO_FLUSH;
+
+ tr_init();
+ lm_init();
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus deflateEnd()
+ {
+ if (_status != INIT_STATE && _status != BUSY_STATE && _status != FINISH_STATE)
+ {
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+ // Deallocate in reverse order of allocations:
+ pending_buf = null;
+ _head = null;
+ _previous = null;
+ _window = null;
+ // free
+ // dstate=null;
+ return _status == BUSY_STATE ? ZLibStatus.Z_DATA_ERROR : ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus deflateParams(CompressionLevel _level, CompressionStrategy _strategy)
+ {
+ ZLibStatus err = ZLibStatus.Z_OK;
+
+ if (_level == CompressionLevel.Z_DEFAULT_COMPRESSION)
+ {
+ _level = (CompressionLevel)6;
+ }
+ if (_level < 0 || _level > (CompressionLevel)9 ||
+ _strategy < 0 || _strategy > CompressionStrategy.Z_HUFFMAN_ONLY)
+ {
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+
+ if (config_table[level].Function != config_table[_level].Function &&
+ base.total_in != 0)
+ {
+ // Flush the last buffer:
+ err = this.deflate(FlushType.Z_PARTIAL_FLUSH);
+ }
+
+ if (level != _level)
+ {
+ level = _level;
+ _maxLazyMatch = config_table[level].MaxLazy;
+ good_match = config_table[level].GoodLength;
+ nice_match = config_table[level].NiceLength;
+ _maxChainLength = config_table[level].MaxChain;
+ }
+ strategy = _strategy;
+ return err;
+ }
+
+ public ZLibStatus deflateSetDictionary(byte[] dictionary, int dictLength)
+ {
+ int length = dictLength;
+ int index = 0;
+
+ if (dictionary == null || _status != INIT_STATE)
+ return ZLibStatus.Z_STREAM_ERROR;
+
+ base.adler = Adler32.adler32(base.adler, dictionary, 0, dictLength);
+
+ if (length < MIN_MATCH) return ZLibStatus.Z_OK;
+ if (length > _windowSize - MIN_LOOKAHEAD)
+ {
+ length = _windowSize - MIN_LOOKAHEAD;
+ index = dictLength - length; // use the tail of the dictionary
+ }
+ System.Array.Copy(dictionary, index, _window, 0, length);
+ _startInsertString = length;
+ _blockStart = length;
+
+ // Insert all strings in the hash table (except for the last two bytes).
+ // s->lookahead stays null, so s->ins_h will be recomputed at the next
+ // call of fill_window.
+
+ _insertedHashIndex = _window[0] & 0xff;
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[1] & 0xff)) & _hashMask;
+
+ for (int n = 0; n <= length - MIN_MATCH; n++)
+ {
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[(n) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+ _previous[n & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)n;
+ }
+ return ZLibStatus.Z_OK;
+ }
+
+ private void lm_init()
+ {
+ _windowActualSize = 2 * _windowSize;
+
+ _head[_hashSize - 1] = 0;
+ for (int i = 0; i < _hashSize - 1; i++)
+ {
+ _head[i] = 0;
+ }
+
+ // Set the default configuration parameters:
+ _maxLazyMatch = Deflate.config_table[level].MaxLazy;
+ good_match = Deflate.config_table[level].GoodLength;
+ nice_match = Deflate.config_table[level].NiceLength;
+ _maxChainLength = Deflate.config_table[level].MaxChain;
+
+ _startInsertString = 0;
+ _blockStart = 0;
+ _validBytesAhead = 0;
+ _matchLength = _previousLength = MIN_MATCH - 1;
+ _matchAvailable = false;
+ _insertedHashIndex = 0;
+ }
+
+ // Initialize the tree data structures for a new zlib stream.
+ private void tr_init()
+ {
+
+ l_desc.Init(dyn_ltree, Deflate.static_l_desc);
+
+ d_desc.Init(dyn_dtree, Deflate.static_d_desc);
+
+ bl_desc.Init(bl_tree, Deflate.static_bl_desc);
+
+
+ bi_buf = 0;
+ bi_valid = 0;
+ last_eob_len = 8; // enough lookahead for inflate
+
+ // Initialize the first block of the first file:
+ init_block();
+ }
+
+ private void init_block()
+ {
+ // Initialize the trees.
+ for (int i = 0; i < L_CODES; i++) dyn_ltree[i * 2] = 0;
+ for (int i = 0; i < D_CODES; i++) dyn_dtree[i * 2] = 0;
+ for (int i = 0; i < BL_CODES; i++) bl_tree[i * 2] = 0;
+
+ dyn_ltree[END_BLOCK * 2] = 1;
+ opt_len = static_len = 0;
+ last_lit = matches = 0;
+ }
+
+ private static bool smaller(short[] tree, int n, int m, byte[] depth)
+ {
+ short tn2 = tree[n * 2];
+ short tm2 = tree[m * 2];
+ return (tn2 < tm2 ||
+ (tn2 == tm2 && depth[n] <= depth[m]));
+ }
+
+ // Scan a literal or distance tree to determine the frequencies of the codes
+ // in the bit length tree.
+ private void scan_tree(short[] tree,// the tree to be scanned
+ int max_code // and its largest code of non zero frequency
+ )
+ {
+ int n; // iterates over all tree elements
+ int prevlen = -1; // last emitted length
+ int curlen; // length of current code
+ int nextlen = tree[0 * 2 + 1]; // length of next code
+ int count = 0; // repeat count of the current code
+ int max_count = 7; // max repeat count
+ int min_count = 4; // min repeat count
+
+ if (nextlen == 0) { max_count = 138; min_count = 3; }
+ tree[(max_code + 1) * 2 + 1] = -1; // guard
+
+ for (n = 0; n <= max_code; n++)
+ {
+ curlen = nextlen; nextlen = tree[(n + 1) * 2 + 1];
+ if (++count < max_count && curlen == nextlen)
+ {
+ continue;
+ }
+ else if (count < min_count)
+ {
+ bl_tree[curlen * 2] += (short)count;
+ }
+ else if (curlen != 0)
+ {
+ if (curlen != prevlen) bl_tree[curlen * 2]++;
+ bl_tree[REP_3_6 * 2]++;
+ }
+ else if (count <= 10)
+ {
+ bl_tree[REPZ_3_10 * 2]++;
+ }
+ else
+ {
+ bl_tree[REPZ_11_138 * 2]++;
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0)
+ {
+ max_count = 138; min_count = 3;
+ }
+ else if (curlen == nextlen)
+ {
+ max_count = 6; min_count = 3;
+ }
+ else
+ {
+ max_count = 7; min_count = 4;
+ }
+ }
+ }
+
+ // Construct the Huffman tree for the bit lengths and return the index in
+ // bl_order of the last bit length code to send.
+ private int build_bl_tree()
+ {
+ int max_blindex; // index of last bit length code of non zero freq
+
+ // Determine the bit length frequencies for literal and distance trees
+ scan_tree(dyn_ltree, l_desc.LargestCode);
+ scan_tree(dyn_dtree, d_desc.LargestCode);
+
+ // Build the bit length tree:
+ bl_desc.BuildTree(this);
+ // opt_len now includes the length of the tree representations, except
+ // the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
+
+ // Determine the number of bit length codes to send. The pkzip format
+ // requires that at least 4 bit length codes be sent. (appnote.txt says
+ // 3 but the actual value used is 4.)
+ for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--)
+ {
+ if (bl_tree[Deflate.bl_order[max_blindex] * 2 + 1] != 0) break;
+ }
+ // Update opt_len to include the bit length tree and counts
+ opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4;
+
+ return max_blindex;
+ }
+
+
+ // Send the header for a block using dynamic Huffman trees: the counts, the
+ // lengths of the bit length codes, the literal tree and the distance tree.
+ // IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
+ private void send_all_trees(int lcodes, int dcodes, int blcodes)
+ {
+ int rank; // index in bl_order
+
+ send_bits(lcodes - 257, 5); // not +255 as stated in appnote.txt
+ send_bits(dcodes - 1, 5);
+ send_bits(blcodes - 4, 4); // not -3 as stated in appnote.txt
+ for (rank = 0; rank < blcodes; rank++)
+ {
+ send_bits(bl_tree[Deflate.bl_order[rank] * 2 + 1], 3);
+ }
+ send_tree(dyn_ltree, lcodes - 1); // literal tree
+ send_tree(dyn_dtree, dcodes - 1); // distance tree
+ }
+
+ // Send a literal or distance tree in compressed form, using the codes in
+ // bl_tree.
+ private void send_tree(short[] tree,// the tree to be sent
+ int max_code // and its largest code of non zero frequency
+ )
+ {
+ int n; // iterates over all tree elements
+ int prevlen = -1; // last emitted length
+ int curlen; // length of current code
+ int nextlen = tree[0 * 2 + 1]; // length of next code
+ int count = 0; // repeat count of the current code
+ int max_count = 7; // max repeat count
+ int min_count = 4; // min repeat count
+
+ if (nextlen == 0) { max_count = 138; min_count = 3; }
+
+ for (n = 0; n <= max_code; n++)
+ {
+ curlen = nextlen; nextlen = tree[(n + 1) * 2 + 1];
+ if (++count < max_count && curlen == nextlen)
+ {
+ continue;
+ }
+ else if (count < min_count)
+ {
+ do { send_code(curlen, bl_tree); } while (--count != 0);
+ }
+ else if (curlen != 0)
+ {
+ if (curlen != prevlen)
+ {
+ send_code(curlen, bl_tree); count--;
+ }
+ send_code(REP_3_6, bl_tree);
+ send_bits(count - 3, 2);
+ }
+ else if (count <= 10)
+ {
+ send_code(REPZ_3_10, bl_tree);
+ send_bits(count - 3, 3);
+ }
+ else
+ {
+ send_code(REPZ_11_138, bl_tree);
+ send_bits(count - 11, 7);
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0)
+ {
+ max_count = 138; min_count = 3;
+ }
+ else if (curlen == nextlen)
+ {
+ max_count = 6; min_count = 3;
+ }
+ else
+ {
+ max_count = 7; min_count = 4;
+ }
+ }
+ }
+
+ // Output a byte on the stream.
+ // IN assertion: there is enough room in pending_buf.
+ private void put_byte(byte[] p, int start, int len)
+ {
+ System.Array.Copy(p, start, pending_buf, pending, len);
+ pending += len;
+ }
+
+ private void put_byte(byte c)
+ {
+ pending_buf[pending++] = c;
+ }
+ private void put_short(int w)
+ {
+ pending_buf[pending++] = (byte)(w/*&0xff*/);
+ pending_buf[pending++] = (byte)(w >> 8);
+ }
+ private void putShortMSB(int b)
+ {
+ pending_buf[pending++] = (byte)(b >> 8);
+ pending_buf[pending++] = (byte)(b/*&0xff*/);
+ }
+
+ private void send_code(int c, short[] tree)
+ {
+ int c2 = c * 2;
+ send_bits((tree[c2] & 0xffff), (tree[c2 + 1] & 0xffff));
+ }
+
+ private void send_bits(int val, int length)
+ {
+ if (bi_valid > Buf_size - length)
+ {
+ bi_buf |= (uint)(val << bi_valid);
+ pending_buf[pending++] = (byte)(bi_buf/*&0xff*/);
+ pending_buf[pending++] = (byte)(bi_buf >> 8);
+ bi_buf = ((uint)val) >> (Buf_size - bi_valid);
+ bi_valid += length - Buf_size;
+ }
+ else
+ {
+ bi_buf |= (uint)(val << bi_valid);
+ bi_valid += length;
+ }
+ // int len = length;
+ // if (bi_valid > (int)Buf_size - len) {
+ // int val = value;
+ // // bi_buf |= (val << bi_valid);
+ // bi_buf = (short)((ushort)bi_buf | (ushort)((val << bi_valid)&0xffff));
+ // put_short(bi_buf);
+ // bi_buf = (short)(((uint)val) >> (Buf_size - bi_valid));
+ // bi_valid += len - Buf_size;
+ // } else {
+ // // bi_buf |= (value) << bi_valid;
+ // bi_buf = (short)((ushort)bi_buf | (ushort)(((value) << bi_valid)&0xffff));
+ // bi_valid += len;
+ // }
+ }
+
+ // Send one empty static block to give enough lookahead for inflate.
+ // This takes 10 bits, of which 7 may remain in the bit buffer.
+ // The current inflate code requires 9 bits of lookahead. If the
+ // last two codes for the previous block (real code plus EOB) were coded
+ // on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
+ // the last real code. In this case we send two empty static blocks instead
+ // of one. (There are no problems if the previous block is stored or fixed.)
+ // To simplify the code, we assume the worst case of last real code encoded
+ // on one bit only.
+ private void _tr_align()
+ {
+ send_bits(STATIC_TREES << 1, 3);
+ send_code(END_BLOCK, Deflate.static_ltree);
+
+ bi_flush();
+
+ // Of the 10 bits for the empty block, we have already sent
+ // (10 - bi_valid) bits. The lookahead for the last real code (before
+ // the EOB of the previous block) was thus at least one plus the length
+ // of the EOB plus what we have just sent of the empty static block.
+ if (1 + last_eob_len + 10 - bi_valid < 9)
+ {
+ send_bits(STATIC_TREES << 1, 3);
+ send_code(END_BLOCK, Deflate.static_ltree);
+ bi_flush();
+ }
+ last_eob_len = 7;
+ }
+
+
+ // Save the match info and tally the frequency counts. Return true if
+ // the current block must be flushed.
+ private bool _tr_tally(int dist, // distance of matched string
+ int lc // match length-MIN_MATCH or unmatched char (if dist==0)
+ )
+ {
+
+ pending_buf[d_buf + last_lit * 2] = (byte)(dist >> 8);
+ pending_buf[d_buf + last_lit * 2 + 1] = (byte)dist;
+
+ pending_buf[l_buf + last_lit] = (byte)lc; last_lit++;
+
+ if (dist == 0)
+ {
+ // lc is the unmatched char
+ dyn_ltree[lc * 2]++;
+ }
+ else
+ {
+ matches++;
+ // Here, lc is the match length - MIN_MATCH
+ dist--; // dist = match distance - 1
+ dyn_ltree[(Deflate._length_code[lc] + LITERALS + 1) * 2]++;
+ dyn_dtree[Tree.DistanceCode(dist) * 2]++;
+ }
+
+ if ((last_lit & 0x1fff) == 0 && level > (CompressionLevel)2)
+ {
+ // Compute an upper bound for the compressed length
+ int out_length = last_lit * 8;
+ int in_length = _startInsertString - _blockStart;
+ int dcode;
+ for (dcode = 0; dcode < D_CODES; dcode++)
+ {
+ out_length += (int)((int)dyn_dtree[dcode * 2] *
+ (5L + Deflate.extra_dbits[dcode]));
+ }
+ out_length >>= 3;
+ if ((matches < (last_lit / 2)) && out_length < in_length / 2) return true;
+ }
+
+ return (last_lit == lit_bufsize - 1);
+ // We avoid equality with lit_bufsize because of wraparound at 64K
+ // on 16 bit machines and because stored blocks are restricted to
+ // 64K-1 bytes.
+ }
+
+ // Send the block data compressed using the given Huffman trees
+ private void compress_block(short[] ltree, short[] dtree)
+ {
+ int dist; // distance of matched string
+ int lc; // match length or unmatched char (if dist == 0)
+ int lx = 0; // running index in l_buf
+ int code; // the code to send
+ int extra; // number of extra bits to send
+
+ if (last_lit != 0)
+ {
+ do
+ {
+ dist = ((pending_buf[d_buf + lx * 2] << 8) & 0xff00) |
+ (pending_buf[d_buf + lx * 2 + 1] & 0xff);
+ lc = (pending_buf[l_buf + lx]) & 0xff; lx++;
+
+ if (dist == 0)
+ {
+ send_code(lc, ltree); // send a literal byte
+ }
+ else
+ {
+ // Here, lc is the match length - MIN_MATCH
+ code = Deflate._length_code[lc];
+
+ send_code(code + LITERALS + 1, ltree); // send the length code
+ extra = Deflate.extra_lbits[code];
+ if (extra != 0)
+ {
+ lc -= Deflate.base_length[code];
+ send_bits(lc, extra); // send the extra length bits
+ }
+ dist--; // dist is now the match distance - 1
+ code = Tree.DistanceCode(dist);
+
+ send_code(code, dtree); // send the distance code
+ extra = Deflate.extra_dbits[code];
+ if (extra != 0)
+ {
+ dist -= Deflate.base_dist[code];
+ send_bits(dist, extra); // send the extra distance bits
+ }
+ } // literal or match pair ?
+
+ // Check that the overlay between pending_buf and d_buf+l_buf is ok:
+ }
+ while (lx < last_lit);
+ }
+
+ send_code(END_BLOCK, ltree);
+ last_eob_len = ltree[END_BLOCK * 2 + 1];
+ }
+
+ // Set the data type to ASCII or BINARY, using a crude approximation:
+ // binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise.
+ // IN assertion: the fields freq of dyn_ltree are set and the total of all
+ // frequencies does not exceed 64K (to fit in an int on 16 bit machines).
+ private void set_data_type()
+ {
+ int n = 0;
+ int ascii_freq = 0;
+ int bin_freq = 0;
+ while (n < 7) { bin_freq += dyn_ltree[n * 2]; n++; }
+ while (n < 128) { ascii_freq += dyn_ltree[n * 2]; n++; }
+ while (n < LITERALS) { bin_freq += dyn_ltree[n * 2]; n++; }
+ this._dataType = (bin_freq > (ascii_freq >> 2) ? BlockType.Z_BINARY : BlockType.Z_ASCII);
+ }
+
+ // Flush the bit buffer, keeping at most 7 bits in it.
+ private void bi_flush()
+ {
+ if (bi_valid == 16)
+ {
+ pending_buf[pending++] = (byte)(bi_buf/*&0xff*/);
+ pending_buf[pending++] = (byte)(bi_buf >> 8);
+ bi_buf = 0;
+ bi_valid = 0;
+ }
+ else if (bi_valid >= 8)
+ {
+ pending_buf[pending++] = (byte)(bi_buf);
+ bi_buf >>= 8;
+ bi_buf &= 0x00ff;
+ bi_valid -= 8;
+ }
+ }
+
+ // Flush the bit buffer and align the output on a byte boundary
+ private void bi_windup()
+ {
+ if (bi_valid > 8)
+ {
+ pending_buf[pending++] = (byte)(bi_buf);
+ pending_buf[pending++] = (byte)(bi_buf >> 8);
+ }
+ else if (bi_valid > 0)
+ {
+ pending_buf[pending++] = (byte)(bi_buf);
+ }
+ bi_buf = 0;
+ bi_valid = 0;
+ }
+
+ // Copy a stored block, storing first the length and its
+ // one's complement if requested.
+ private void copy_block(int buf, // the input data
+ int len, // its length
+ bool header // true if block header must be written
+ )
+ {
+ //int index=0;
+ bi_windup(); // align on byte boundary
+ last_eob_len = 8; // enough lookahead for inflate
+
+ if (header)
+ {
+ put_short((short)len);
+ put_short((short)~len);
+ }
+
+ // while(len--!=0) {
+ // put_byte(window[buf+index]);
+ // index++;
+ // }
+ put_byte(_window, buf, len);
+ }
+
+ private void flush_block_only(bool eof)
+ {
+ _tr_flush_block(_blockStart >= 0 ? _blockStart : -1,
+ _startInsertString - _blockStart,
+ eof);
+ _blockStart = _startInsertString;
+ this.flush_pending();
+ }
+
+ // Copy without compression as much as possible from the input stream, return
+ // the current block state.
+ // This function does not insert new strings in the dictionary since
+ // uncompressible data is probably not useful. This function is used
+ // only for the level=0 compression option.
+ // NOTE: this function should be optimized to avoid extra copying from
+ // window to pending_buf.
+ private int deflate_stored(FlushType flush)
+ {
+ // Stored blocks are limited to 0xffff bytes, pending_buf is limited
+ // to pending_buf_size, and each stored block has a 5 byte header:
+
+ int max_block_size = 0xffff;
+ int max_start;
+
+ if (max_block_size > _pendingBufferSize - 5)
+ {
+ max_block_size = _pendingBufferSize - 5;
+ }
+
+ // Copy as much as possible from input to output:
+ while (true)
+ {
+ // Fill the window as much as possible:
+ if (_validBytesAhead <= 1)
+ {
+ fill_window();
+ if (_validBytesAhead == 0 && flush == FlushType.Z_NO_FLUSH) return NeedMore;
+ if (_validBytesAhead == 0) break; // flush the current block
+ }
+
+ _startInsertString += _validBytesAhead;
+ _validBytesAhead = 0;
+
+ // Emit a stored block if pending_buf will be full:
+ max_start = _blockStart + max_block_size;
+ if (_startInsertString == 0 || _startInsertString >= max_start)
+ {
+ // strstart == 0 is possible when wraparound on 16-bit machine
+ _validBytesAhead = (int)(_startInsertString - max_start);
+ _startInsertString = (int)max_start;
+
+ flush_block_only(false);
+ if (base.avail_out == 0) return NeedMore;
+
+ }
+
+ // Flush if we may have to slide, otherwise block_start may become
+ // negative and the data will be gone:
+ if (_startInsertString - _blockStart >= _windowSize - MIN_LOOKAHEAD)
+ {
+ flush_block_only(false);
+ if (base.avail_out == 0) return NeedMore;
+ }
+ }
+
+ flush_block_only(flush == FlushType.Z_FINISH);
+ if (base.avail_out == 0)
+ return (flush == FlushType.Z_FINISH) ? FinishStarted : NeedMore;
+
+ return flush == FlushType.Z_FINISH ? FinishDone : BlockDone;
+ }
+
+ // Send a stored block
+ private void _tr_stored_block(int buf, // input block
+ int stored_len, // length of input block
+ bool eof // true if this is the last block for a file
+ )
+ {
+ send_bits((STORED_BLOCK << 1) + (eof ? 1 : 0), 3); // send block type
+ copy_block(buf, stored_len, true); // with header
+ }
+
+ // Determine the best encoding for the current block: dynamic trees, static
+ // trees or store, and output the encoded block to the zip file.
+ private void _tr_flush_block(int buf, // input block, or NULL if too old
+ int stored_len, // length of input block
+ bool eof // true if this is the last block for a file
+ )
+ {
+ int opt_lenb, static_lenb;// opt_len and static_len in bytes
+ int max_blindex = 0; // index of last bit length code of non zero freq
+
+ // Build the Huffman trees unless a stored block is forced
+ if (level > 0)
+ {
+ // Check if the file is ascii or binary
+ if (this._dataType == BlockType.Z_UNKNOWN) set_data_type();
+
+ // Construct the literal and distance trees
+ l_desc.BuildTree(this);
+
+ d_desc.BuildTree(this);
+
+ // At this point, opt_len and static_len are the total bit lengths of
+ // the compressed block data, excluding the tree representations.
+
+ // Build the bit length tree for the above two trees, and get the index
+ // in bl_order of the last bit length code to send.
+ max_blindex = build_bl_tree();
+
+ // Determine the best encoding. Compute first the block length in bytes
+ opt_lenb = (opt_len + 3 + 7) >> 3;
+ static_lenb = (static_len + 3 + 7) >> 3;
+
+ if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
+ }
+ else
+ {
+ opt_lenb = static_lenb = stored_len + 5; // force a stored block
+ }
+
+ if (stored_len + 4 <= opt_lenb && buf != -1)
+ {
+ // 4: two words for the lengths
+ // The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
+ // Otherwise we can't have processed more than WSIZE input bytes since
+ // the last block flush, because compression would have been
+ // successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
+ // transform a block into a stored block.
+ _tr_stored_block(buf, stored_len, eof);
+ }
+ else if (static_lenb == opt_lenb)
+ {
+ send_bits((STATIC_TREES << 1) + (eof ? 1 : 0), 3);
+ compress_block(Deflate.static_ltree, Deflate.static_dtree);
+ }
+ else
+ {
+ send_bits((DYN_TREES << 1) + (eof ? 1 : 0), 3);
+ send_all_trees(l_desc.LargestCode + 1, d_desc.LargestCode + 1, max_blindex + 1);
+ compress_block(dyn_ltree, dyn_dtree);
+ }
+
+ // The above check is made mod 2^32, for files larger than 512 MB
+ // and uLong implemented on 32 bits.
+
+ init_block();
+
+ if (eof)
+ {
+ bi_windup();
+ }
+ }
+
+ // Fill the window when the lookahead becomes insufficient.
+ // Updates strstart and lookahead.
+ //
+ // IN assertion: lookahead < MIN_LOOKAHEAD
+ // OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
+ // At least one byte has been read, or avail_in == 0; reads are
+ // performed for at least two bytes (required for the zip translate_eol
+ // option -- not supported here).
+ private void fill_window()
+ {
+ int n, m;
+ int p;
+ int more; // Amount of free space at the end of the window.
+
+ do
+ {
+ more = (_windowActualSize - _validBytesAhead - _startInsertString);
+
+ // Deal with !@#$% 64K limit:
+ if (more == 0 && _startInsertString == 0 && _validBytesAhead == 0)
+ {
+ more = _windowSize;
+ }
+ else if (more == -1)
+ {
+ // Very unlikely, but possible on 16 bit machine if strstart == 0
+ // and lookahead == 1 (input done one byte at time)
+ more--;
+
+ // If the window is almost full and there is insufficient lookahead,
+ // move the upper half to the lower one to make room in the upper half.
+ }
+ else if (_startInsertString >= _windowSize + _windowSize - MIN_LOOKAHEAD)
+ {
+ System.Array.Copy(_window, _windowSize, _window, 0, _windowSize);
+ _startMatchString -= _windowSize;
+ _startInsertString -= _windowSize; // we now have strstart >= MAX_DIST
+ _blockStart -= _windowSize;
+
+ // Slide the hash table (could be avoided with 32 bit values
+ // at the expense of memory usage). We slide even when level == 0
+ // to keep the hash table consistent if we switch back to level > 0
+ // later. (Using level 0 permanently is not an optimal usage of
+ // zlib, so we don't care about this pathological case.)
+
+ n = _hashSize;
+ p = n;
+ do
+ {
+ m = (_head[--p] & 0xffff);
+ _head[p] = (short)(m >= _windowSize ? (m - _windowSize) : 0);
+ }
+ while (--n != 0);
+
+ n = _windowSize;
+ p = n;
+ do
+ {
+ m = (_previous[--p] & 0xffff);
+ _previous[p] = (short)(m >= _windowSize ? (m - _windowSize) : 0);
+ // If n is not on any hash chain, prev[n] is garbage but
+ // its value will never be used.
+ }
+ while (--n != 0);
+ more += _windowSize;
+ }
+
+ if (base.avail_in == 0) return;
+
+ // If there was no sliding:
+ // strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
+ // more == window_size - lookahead - strstart
+ // => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
+ // => more >= window_size - 2*WSIZE + 2
+ // In the BIG_MEM or MMAP case (not yet supported),
+ // window_size == input_size + MIN_LOOKAHEAD &&
+ // strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
+ // Otherwise, window_size == 2*WSIZE so more >= 2.
+ // If there was sliding, more >= WSIZE. So in all cases, more >= 2.
+
+ n = this.read_buf(_window, _startInsertString + _validBytesAhead, more);
+ _validBytesAhead += n;
+
+ // Initialize the hash value now that we have some input:
+ if (_validBytesAhead >= MIN_MATCH)
+ {
+ _insertedHashIndex = _window[_startInsertString] & 0xff;
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[_startInsertString + 1] & 0xff)) & _hashMask;
+ }
+ // If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
+ // but this is not important since only literal bytes will be emitted.
+ }
+ while (_validBytesAhead < MIN_LOOKAHEAD && base.avail_in != 0);
+ }
+
+ // Compress as much as possible from the input stream, return the current
+ // block state.
+ // This function does not perform lazy evaluation of matches and inserts
+ // new strings in the dictionary only for unmatched strings or for short
+ // matches. It is used only for the fast compression options.
+ private int deflate_fast(FlushType flush)
+ {
+ // short hash_head = 0; // head of the hash chain
+ int hash_head = 0; // head of the hash chain
+ bool bflush; // set if current block must be flushed
+
+ while (true)
+ {
+ // Make sure that we always have enough lookahead, except
+ // at the end of the input file. We need MAX_MATCH bytes
+ // for the next match, plus MIN_MATCH bytes to insert the
+ // string following the next match.
+ if (_validBytesAhead < MIN_LOOKAHEAD)
+ {
+ fill_window();
+ if (_validBytesAhead < MIN_LOOKAHEAD && flush == FlushType.Z_NO_FLUSH)
+ {
+ return NeedMore;
+ }
+ if (_validBytesAhead == 0) break; // flush the current block
+ }
+
+ // Insert the string window[strstart .. strstart+2] in the
+ // dictionary, and set hash_head to the head of the hash chain:
+ if (_validBytesAhead >= MIN_MATCH)
+ {
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[(_startInsertString) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+
+ // prev[strstart&w_mask]=hash_head=head[ins_h];
+ hash_head = (_head[_insertedHashIndex] & 0xffff);
+ _previous[_startInsertString & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)_startInsertString;
+ }
+
+ // Find the longest match, discarding those <= prev_length.
+ // At this point we have always match_length < MIN_MATCH
+
+ if (hash_head != 0L &&
+ ((_startInsertString - hash_head) & 0xffff) <= _windowSize - MIN_LOOKAHEAD
+ )
+ {
+ // To simplify the code, we prevent matches with the string
+ // of window index 0 (in particular we have to avoid a match
+ // of the string with itself at the start of the input file).
+ if (strategy != CompressionStrategy.Z_HUFFMAN_ONLY)
+ {
+ _matchLength = longest_match(hash_head);
+ }
+ // longest_match() sets match_start
+ }
+ if (_matchLength >= MIN_MATCH)
+ {
+ // check_match(strstart, match_start, match_length);
+
+ bflush = _tr_tally(_startInsertString - _startMatchString, _matchLength - MIN_MATCH);
+
+ _validBytesAhead -= _matchLength;
+
+ // Insert new strings in the hash table only if the match length
+ // is not too large. This saves time but degrades compression.
+ if (_matchLength <= _maxLazyMatch &&
+ _validBytesAhead >= MIN_MATCH)
+ {
+ _matchLength--; // string at strstart already in hash table
+ do
+ {
+ _startInsertString++;
+
+ _insertedHashIndex = ((_insertedHashIndex << _hashShift) ^ (_window[(_startInsertString) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+ // prev[strstart&w_mask]=hash_head=head[ins_h];
+ hash_head = (_head[_insertedHashIndex] & 0xffff);
+ _previous[_startInsertString & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)_startInsertString;
+
+ // strstart never exceeds WSIZE-MAX_MATCH, so there are
+ // always MIN_MATCH bytes ahead.
+ }
+ while (--_matchLength != 0);
+ _startInsertString++;
+ }
+ else
+ {
+ _startInsertString += _matchLength;
+ _matchLength = 0;
+ _insertedHashIndex = _window[_startInsertString] & 0xff;
+
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[_startInsertString + 1] & 0xff)) & _hashMask;
+ // If lookahead < MIN_MATCH, ins_h is garbage, but it does not
+ // matter since it will be recomputed at next deflate call.
+ }
+ }
+ else
+ {
+ // No match, output a literal byte
+
+ bflush = _tr_tally(0, _window[_startInsertString] & 0xff);
+ _validBytesAhead--;
+ _startInsertString++;
+ }
+ if (bflush)
+ {
+
+ flush_block_only(false);
+ if (base.avail_out == 0) return NeedMore;
+ }
+ }
+
+ flush_block_only(flush == FlushType.Z_FINISH);
+ if (base.avail_out == 0)
+ {
+ if (flush == FlushType.Z_FINISH) return FinishStarted;
+ else return NeedMore;
+ }
+ return flush == FlushType.Z_FINISH ? FinishDone : BlockDone;
+ }
+
+ // Same as above, but achieves better compression. We use a lazy
+ // evaluation for matches: a match is finally adopted only if there is
+ // no better match at the next window position.
+ private int deflate_slow(FlushType flush)
+ {
+ // short hash_head = 0; // head of hash chain
+ int hash_head = 0; // head of hash chain
+ bool bflush; // set if current block must be flushed
+
+ // Process the input block.
+ while (true)
+ {
+ // Make sure that we always have enough lookahead, except
+ // at the end of the input file. We need MAX_MATCH bytes
+ // for the next match, plus MIN_MATCH bytes to insert the
+ // string following the next match.
+
+ if (_validBytesAhead < MIN_LOOKAHEAD)
+ {
+ fill_window();
+ if (_validBytesAhead < MIN_LOOKAHEAD && flush == FlushType.Z_NO_FLUSH)
+ {
+ return NeedMore;
+ }
+ if (_validBytesAhead == 0) break; // flush the current block
+ }
+
+ // Insert the string window[strstart .. strstart+2] in the
+ // dictionary, and set hash_head to the head of the hash chain:
+
+ if (_validBytesAhead >= MIN_MATCH)
+ {
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[(_startInsertString) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+ // prev[strstart&w_mask]=hash_head=head[ins_h];
+ hash_head = (_head[_insertedHashIndex] & 0xffff);
+ _previous[_startInsertString & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)_startInsertString;
+ }
+
+ // Find the longest match, discarding those <= prev_length.
+ _previousLength = _matchLength; _previousMatch = _startMatchString;
+ _matchLength = MIN_MATCH - 1;
+
+ if (hash_head != 0 && _previousLength < _maxLazyMatch &&
+ ((_startInsertString - hash_head) & 0xffff) <= _windowSize - MIN_LOOKAHEAD
+ )
+ {
+ // To simplify the code, we prevent matches with the string
+ // of window index 0 (in particular we have to avoid a match
+ // of the string with itself at the start of the input file).
+
+ if (strategy != CompressionStrategy.Z_HUFFMAN_ONLY)
+ {
+ _matchLength = longest_match(hash_head);
+ }
+ // longest_match() sets match_start
+
+ if (_matchLength <= 5 && (strategy == CompressionStrategy.Z_FILTERED ||
+ (_matchLength == MIN_MATCH &&
+ _startInsertString - _startMatchString > 4096)))
+ {
+
+ // If prev_match is also MIN_MATCH, match_start is garbage
+ // but we will ignore the current match anyway.
+ _matchLength = MIN_MATCH - 1;
+ }
+ }
+
+ // If there was a match at the previous step and the current
+ // match is not better, output the previous match:
+ if (_previousLength >= MIN_MATCH && _matchLength <= _previousLength)
+ {
+ int max_insert = _startInsertString + _validBytesAhead - MIN_MATCH;
+ // Do not insert strings in hash table beyond this.
+
+ // check_match(strstart-1, prev_match, prev_length);
+
+ bflush = _tr_tally(_startInsertString - 1 - _previousMatch, _previousLength - MIN_MATCH);
+
+ // Insert in hash table all strings up to the end of the match.
+ // strstart-1 and strstart are already inserted. If there is not
+ // enough lookahead, the last two strings are not inserted in
+ // the hash table.
+ _validBytesAhead -= _previousLength - 1;
+ _previousLength -= 2;
+ do
+ {
+ if (++_startInsertString <= max_insert)
+ {
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[(_startInsertString) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+ //prev[strstart&w_mask]=hash_head=head[ins_h];
+ hash_head = (_head[_insertedHashIndex] & 0xffff);
+ _previous[_startInsertString & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)_startInsertString;
+ }
+ }
+ while (--_previousLength != 0);
+ _matchAvailable = false;
+ _matchLength = MIN_MATCH - 1;
+ _startInsertString++;
+
+ if (bflush)
+ {
+ flush_block_only(false);
+ if (base.avail_out == 0) return NeedMore;
+ }
+ }
+ else if (_matchAvailable != false)
+ {
+
+ // If there was no match at the previous position, output a
+ // single literal. If there was a match but the current match
+ // is longer, truncate the previous match to a single literal.
+
+ bflush = _tr_tally(0, _window[_startInsertString - 1] & 0xff);
+
+ if (bflush)
+ {
+ flush_block_only(false);
+ }
+ _startInsertString++;
+ _validBytesAhead--;
+ if (base.avail_out == 0) return NeedMore;
+ }
+ else
+ {
+ // There is no previous match to compare with, wait for
+ // the next step to decide.
+
+ _matchAvailable = true;
+ _startInsertString++;
+ _validBytesAhead--;
+ }
+ }
+
+ if (_matchAvailable != false)
+ {
+ bflush = _tr_tally(0, _window[_startInsertString - 1] & 0xff);
+ _matchAvailable = false;
+ }
+ flush_block_only(flush == FlushType.Z_FINISH);
+
+ if (base.avail_out == 0)
+ {
+ if (flush == FlushType.Z_FINISH) return FinishStarted;
+ else return NeedMore;
+ }
+
+ return flush == FlushType.Z_FINISH ? FinishDone : BlockDone;
+ }
+
+ private int longest_match(int cur_match)
+ {
+ int chain_length = _maxChainLength; // max hash chain length
+ int scan = _startInsertString; // current string
+ int match; // matched string
+ int len; // length of current match
+ int best_len = _previousLength; // best match length so far
+ int limit = _startInsertString > (_windowSize - MIN_LOOKAHEAD) ?
+ _startInsertString - (_windowSize - MIN_LOOKAHEAD) : 0;
+ int nice_match = this.nice_match;
+
+ // Stop when cur_match becomes <= limit. To simplify the code,
+ // we prevent matches with the string of window index 0.
+
+ int wmask = _windowMask;
+
+ int strend = _startInsertString + MAX_MATCH;
+ byte scan_end1 = _window[scan + best_len - 1];
+ byte scan_end = _window[scan + best_len];
+
+ // The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+ // It is easy to get rid of this optimization if necessary.
+
+ // Do not waste too much time if we already have a good match:
+ if (_previousLength >= good_match)
+ {
+ chain_length >>= 2;
+ }
+
+ // Do not look for matches beyond the end of the input. This is necessary
+ // to make deflate deterministic.
+ if (nice_match > _validBytesAhead) nice_match = _validBytesAhead;
+
+ do
+ {
+ match = cur_match;
+
+ // Skip to next match if the match length cannot increase
+ // or if the match length is less than 2:
+ if (_window[match + best_len] != scan_end ||
+ _window[match + best_len - 1] != scan_end1 ||
+ _window[match] != _window[scan] ||
+ _window[++match] != _window[scan + 1]) continue;
+
+ // The check at best_len-1 can be removed because it will be made
+ // again later. (This heuristic is not always a win.)
+ // It is not necessary to compare scan[2] and match[2] since they
+ // are always equal when the other bytes match, given that
+ // the hash keys are equal and that HASH_BITS >= 8.
+ scan += 2; match++;
+
+ // We check for insufficient lookahead only every 8th comparison;
+ // the 256th check will be made at strstart+258.
+ do
+ {
+ } while (_window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ scan < strend);
+
+ len = MAX_MATCH - (int)(strend - scan);
+ scan = strend - MAX_MATCH;
+
+ if (len > best_len)
+ {
+ _startMatchString = cur_match;
+ best_len = len;
+ if (len >= nice_match) break;
+ scan_end1 = _window[scan + best_len - 1];
+ scan_end = _window[scan + best_len];
+ }
+
+ } while ((cur_match = (_previous[cur_match & wmask] & 0xffff)) > limit
+ && --chain_length != 0);
+
+ if (best_len <= _validBytesAhead) return best_len;
+ return _validBytesAhead;
+ }
+
+ public ZLibStatus deflate(FlushType flush)
+ {
+ FlushType old_flush;
+
+ if (flush > FlushType.Z_FINISH || flush < 0)
+ {
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+
+ if (base.next_out == null ||
+ (base.next_in == null && base.avail_in != 0) ||
+ (_status == FINISH_STATE && flush != FlushType.Z_FINISH))
+ {
+ base.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_STREAM_ERROR)];
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+ if (base.avail_out == 0)
+ {
+ base.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_BUF_ERROR)];
+ return ZLibStatus.Z_BUF_ERROR;
+ }
+
+ old_flush = last_flush;
+ last_flush = flush;
+
+ // Write the zlib header
+ if (_status == INIT_STATE)
+ {
+ int header = (Z_DEFLATED + ((this._windowBits - 8) << 4)) << 8;
+ int level_flags = (((int)this.level - 1) & 0xff) >> 1;
+
+ if (level_flags > 3) level_flags = 3;
+ header |= (level_flags << 6);
+ if (this._startInsertString != 0) header |= PRESET_DICT;
+ header += 31 - (header % 31);
+
+ _status = BUSY_STATE;
+ putShortMSB(header);
+
+
+ // Save the adler32 of the preset dictionary:
+ if (this._startInsertString != 0)
+ {
+ putShortMSB((int)(base.adler >> 16));
+ putShortMSB((int)(base.adler & 0xffff));
+ }
+ base.adler = Adler32.adler32(0, null, 0, 0);
+ }
+
+ // Flush as much pending output as possible
+ if (pending != 0)
+ {
+ this.flush_pending();
+ if (base.avail_out == 0)
+ {
+ //System.out.println(" avail_out==0");
+ // Since avail_out is 0, deflate will be called again with
+ // more output space, but possibly with both pending and
+ // avail_in equal to zero. There won't be anything to do,
+ // but this is not an error situation so make sure we
+ // return OK instead of BUF_ERROR at next call of deflate:
+ last_flush = (FlushType)(-1);
+ return ZLibStatus.Z_OK;
+ }
+
+ // Make sure there is something to do and avoid duplicate consecutive
+ // flushes. For repeated and useless calls with Z_FINISH, we keep
+ // returning Z_STREAM_END instead of Z_BUFF_ERROR.
+ }
+ else if (base.avail_in == 0 && flush <= old_flush &&
+ flush != FlushType.Z_FINISH)
+ {
+ base.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_BUF_ERROR)];
+ return ZLibStatus.Z_BUF_ERROR;
+ }
+
+ // User must not provide more input after the first FINISH:
+ if (_status == FINISH_STATE && base.avail_in != 0)
+ {
+ base.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_BUF_ERROR)];
+ return ZLibStatus.Z_BUF_ERROR;
+ }
+
+ // Start a new block or continue the current one.
+ if (base.avail_in != 0 || this._validBytesAhead != 0 ||
+ (flush != FlushType.Z_NO_FLUSH && _status != FINISH_STATE))
+ {
+ int bstate = -1;
+ switch (config_table[level].Function)
+ {
+ case DefalteFlavor.STORED:
+ bstate = deflate_stored(flush);
+ break;
+ case DefalteFlavor.FAST:
+ bstate = deflate_fast(flush);
+ break;
+ case DefalteFlavor.SLOW:
+ bstate = deflate_slow(flush);
+ break;
+ default:
+ break;
+ }
+
+ if (bstate == FinishStarted || bstate == FinishDone)
+ {
+ _status = FINISH_STATE;
+ }
+ if (bstate == NeedMore || bstate == FinishStarted)
+ {
+ if (base.avail_out == 0)
+ {
+ last_flush = (FlushType)(-1); // avoid BUF_ERROR next call, see above
+ }
+ return ZLibStatus.Z_OK;
+ // If flush != Z_NO_FLUSH && avail_out == 0, the next call
+ // of deflate should use the same flush parameter to make sure
+ // that the flush is complete. So we don't have to output an
+ // empty block here, this will be done at next call. This also
+ // ensures that for a very small output buffer, we emit at most
+ // one empty block.
+ }
+
+ if (bstate == BlockDone)
+ {
+ if (flush == FlushType.Z_PARTIAL_FLUSH)
+ {
+ _tr_align();
+ }
+ else
+ { // FULL_FLUSH or SYNC_FLUSH
+ _tr_stored_block(0, 0, false);
+ // For a full flush, this empty block will be recognized
+ // as a special marker by inflate_sync().
+ if (flush == FlushType.Z_FULL_FLUSH)
+ {
+ //state.head[s.hash_size-1]=0;
+ for (int i = 0; i < this._hashSize/*-1*/; i++) // forget history
+ this._head[i] = 0;
+ }
+ }
+ this.flush_pending();
+ if (base.avail_out == 0)
+ {
+ last_flush = (FlushType)(-1); // avoid BUF_ERROR at next call, see above
+ return ZLibStatus.Z_OK;
+ }
+ }
+ }
+
+ if (flush != FlushType.Z_FINISH) return ZLibStatus.Z_OK;
+ if (noheader != 0) return ZLibStatus.Z_STREAM_END;
+
+ // Write the zlib trailer (adler32)
+ putShortMSB((int)(base.adler >> 16));
+ putShortMSB((int)(base.adler & 0xffff));
+ this.flush_pending();
+
+ // If avail_out is zero, the application will call deflate again
+ // to flush the rest.
+ noheader = -1; // write the trailer only once!
+ return pending != 0 ? ZLibStatus.Z_OK : ZLibStatus.Z_STREAM_END;
+ }
+
+
+ private static readonly StaticTree static_l_desc = new StaticTree(static_ltree, Deflate.extra_lbits, LITERALS + 1, L_CODES, MAX_BITS);
+
+ private static readonly StaticTree static_d_desc = new StaticTree(static_dtree, Deflate.extra_dbits, 0, D_CODES, MAX_BITS);
+
+ private static readonly StaticTree static_bl_desc = new StaticTree(null, Deflate.extra_blbits, 0, BL_CODES, MAX_BL_BITS);
+
+ private class Config
+ {
+ ///
+ /// Reduce lazy search above this match length
+ ///
+ internal int GoodLength { get; private set; }
+ ///
+ /// Gets or sets whether not to perform lazy search above this match length
+ ///
+ ///
+ /// The max lazy.
+ ///
+ internal int MaxLazy { get; private set; }
+ ///
+ /// Gets or sets whether to quit search above this match length
+ ///
+ ///
+ /// The length of the nice.
+ ///
+ internal int NiceLength { get; private set; }
+ internal int MaxChain { get; private set; }
+ internal DefalteFlavor Function { get; private set; }
+ internal Config(int goodLength, int maxLazy, int niceLength, int maxChain, DefalteFlavor function)
+ {
+ this.GoodLength = goodLength;
+ this.MaxLazy = maxLazy;
+ this.NiceLength = niceLength;
+ this.MaxChain = maxChain;
+ this.Function = function;
+ }
+ }
+
+
+ // Flush as much pending output as possible. All deflate() output goes
+ // through this function so some applications may wish to modify it
+ // to avoid allocating a large strm->next_out buffer and copying into it.
+ // (See also read_buf()).
+ internal void flush_pending()
+ {
+ int len = this.pending;
+
+ if (len > avail_out) len = avail_out;
+ if (len == 0) return;
+
+ if (this.pending_buf.Length <= this.pending_out ||
+ next_out.Length <= next_out_index ||
+ this.pending_buf.Length < (this.pending_out + len) ||
+ next_out.Length < (next_out_index + len))
+ {
+ // System.out.println(this.pending_buf.length+", "+this.pending_out+
+ // ", "+next_out.length+", "+next_out_index+", "+len);
+ // System.out.println("avail_out="+avail_out);
+ }
+
+ System.Array.Copy(this.pending_buf, this.pending_out,
+ next_out, next_out_index, len);
+
+ next_out_index += len;
+ this.pending_out += len;
+ total_out += len;
+ avail_out -= len;
+ this.pending -= len;
+ if (this.pending == 0)
+ {
+ this.pending_out = 0;
+ }
+ }
+
+ // Read a new buffer from the current input stream, update the adler32
+ // and total number of bytes read. All deflate() input goes through
+ // this function so some applications may wish to modify it to avoid
+ // allocating a large strm->next_in buffer and copying from it.
+ // (See also flush_pending()).
+ internal int read_buf(byte[] buf, int start, int size)
+ {
+ int len = avail_in;
+
+ if (len > size) len = size;
+ if (len == 0) return 0;
+
+ avail_in -= len;
+
+ if (this.noheader == 0)
+ {
+ adler = Adler32.adler32(adler, next_in, next_in_index, len);
+ }
+ System.Array.Copy(next_in, next_in_index, buf, start, len);
+ next_in_index += len;
+ total_in += len;
+ return len;
+ }
+
+ public ZLibStatus deflate(byte[] inputBufer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType)
+ {
+ this.next_in = inputBufer;
+ this.next_in_index = inputOffset;
+ this.avail_in = inputCount;
+ this.next_out = outputBuffer;
+ this.next_out_index = outputOffset;
+ this.avail_out = outputCount;
+ return this.deflate(flushType);
+ }
+
+ public ZLibStatus deflate(byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType)
+ {
+ this.next_out = outputBuffer;
+ this.next_out_index = outputOffset;
+ this.avail_out = outputCount;
+ return this.deflate(flushType);
+ }
+
+
+ // TODO: Delete this
+ public ZLibStatus inflateEnd()
+ {
+ throw new NotImplementedException();
+ }
+
+ public ZLibStatus inflate(byte[] bufer, int offset, int count, byte[] p1, int p2, int p3, FlushType flushType)
+ {
+ throw new NotImplementedException();
+ }
+
+ public ZLibStatus inflate(byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v12/Inflate.cs b/Renci.SshNet/Compression/v12/Inflate.cs
new file mode 100644
index 0000000..c05e2d8
--- /dev/null
+++ b/Renci.SshNet/Compression/v12/Inflate.cs
@@ -0,0 +1,524 @@
+using System;
+/*
+ * $Id: Inflate.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public enum InflateMode : int
+ {
+ ///
+ ///waiting for method byte
+ ///
+ METHOD = 0,
+ ///
+ /// waiting for flag byte
+ ///
+ FLAG = 1,
+ ///
+ /// four dictionary check bytes to go
+ ///
+ DICT4 = 2,
+ ///
+ /// three dictionary check bytes to go
+ ///
+ DICT3 = 3,
+ ///
+ /// two dictionary check bytes to go
+ ///
+ DICT2 = 4,
+ ///
+ /// one dictionary check byte to go
+ ///
+ DICT1 = 5,
+ ///
+ /// waiting for inflateSetDictionary
+ ///
+ DICT0 = 6,
+ ///
+ /// decompressing blocks
+ ///
+ BLOCKS = 7,
+ ///
+ /// four check bytes to go
+ ///
+ CHECK4 = 8,
+ ///
+ /// three check bytes to go
+ ///
+ CHECK3 = 9,
+ ///
+ /// two check bytes to go
+ ///
+ CHECK2 = 10,
+ ///
+ /// one check byte to go
+ ///
+ CHECK1 = 11,
+ ///
+ /// finished check, done
+ ///
+ DONE = 12,
+ ///
+ /// got an error--stay here
+ ///
+ BAD = 13
+ }
+
+ internal sealed class Inflate : ZStream, ICompressor
+ {
+ // preset dictionary flag in zlib header
+ private const int PRESET_DICT = 0x20;
+
+ private const int Z_DEFLATED = 8;
+
+ private static readonly byte[] mark = { (byte)0, (byte)0, (byte)0xff, (byte)0xff };
+
+ ///
+ /// The current inflate mode
+ ///
+ private InflateMode _mode;
+
+ ///
+ /// if FLAGS, method byte
+ ///
+ private int method;
+
+ ///
+ /// Computed check value
+ ///
+ private long[] _was = new long[1];
+
+ ///
+ /// The stream check value
+ ///
+ private long _need;
+
+ ///
+ /// if BAD, inflateSync's marker bytes count
+ ///
+ private int _marker;
+
+ // mode independent information
+ ///
+ /// Flag for no wrapper
+ ///
+ private int _nowrap;
+
+ ///
+ /// log2(window size) (8..15, defaults to 15)
+ ///
+ private int _wbits;
+
+ ///
+ /// Current inflate_blocks state
+ ///
+ private InflateBlocks _blocks;
+
+ public Inflate()
+ {
+ this.inflateInit();
+ }
+
+ public Inflate(bool nowrap)
+ {
+ this.inflateInit(nowrap);
+ }
+
+ private ZLibStatus InflateReset()
+ {
+ base.total_in = base.total_out = 0;
+ base.msg = null;
+ this._mode = this._nowrap != 0 ? InflateMode.BLOCKS : InflateMode.METHOD;
+ this._blocks.reset(this, null);
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus InflateEnd()
+ {
+ if (_blocks != null)
+ _blocks.free(this);
+ _blocks = null;
+ // ZFREE(z, z->state);
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus InflateInit(int w)
+ {
+ base.msg = null;
+ _blocks = null;
+
+ // handle undocumented nowrap option (no zlib header or check)
+ _nowrap = 0;
+ if (w < 0)
+ {
+ w = -w;
+ _nowrap = 1;
+ }
+
+ // set window size
+ if (w < 8 || w > 15)
+ {
+ InflateEnd();
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+ _wbits = w;
+
+ this._blocks = new InflateBlocks(this, this._nowrap != 0 ? null : this, 1 << w);
+
+ // reset state
+ InflateReset();
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus inflate(FlushType ff)
+ {
+ ZLibStatus r;
+ int b;
+
+ if (base.next_in == null)
+ return ZLibStatus.Z_STREAM_ERROR;
+ var f = ff == FlushType.Z_FINISH ? ZLibStatus.Z_BUF_ERROR : ZLibStatus.Z_OK;
+ r = ZLibStatus.Z_BUF_ERROR;
+ while (true)
+ {
+ //System.out.println("mode: "+this.mode);
+ switch (this._mode)
+ {
+ case InflateMode.METHOD:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ if (((this.method = base.next_in[base.next_in_index++]) & 0xf) != Z_DEFLATED)
+ {
+ this._mode = InflateMode.BAD;
+ base.msg = "unknown compression method";
+ this._marker = 5; // can't try inflateSync
+ break;
+ }
+ if ((this.method >> 4) + 8 > this._wbits)
+ {
+ this._mode = InflateMode.BAD;
+ base.msg = "invalid window size";
+ this._marker = 5; // can't try inflateSync
+ break;
+ }
+ this._mode = InflateMode.FLAG;
+ goto case InflateMode.FLAG;
+ case InflateMode.FLAG:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ b = (base.next_in[base.next_in_index++]) & 0xff;
+
+ if ((((this.method << 8) + b) % 31) != 0)
+ {
+ this._mode = InflateMode.BAD;
+ base.msg = "incorrect header check";
+ this._marker = 5; // can't try inflateSync
+ break;
+ }
+
+ if ((b & PRESET_DICT) == 0)
+ {
+ this._mode = InflateMode.BLOCKS;
+ break;
+ }
+ this._mode = InflateMode.DICT4;
+ goto case InflateMode.DICT4;
+ case InflateMode.DICT4:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need = ((base.next_in[base.next_in_index++] & 0xff) << 24) & 0xff000000L;
+ this._mode = InflateMode.DICT3;
+ goto case InflateMode.DICT3;
+ case InflateMode.DICT3:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += ((base.next_in[base.next_in_index++] & 0xff) << 16) & 0xff0000L;
+ this._mode = InflateMode.DICT2;
+ goto case InflateMode.DICT2;
+ case InflateMode.DICT2:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += ((base.next_in[base.next_in_index++] & 0xff) << 8) & 0xff00L;
+ this._mode = InflateMode.DICT1;
+ goto case InflateMode.DICT1;
+ case InflateMode.DICT1:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += (base.next_in[base.next_in_index++] & 0xffL);
+ base.adler = this._need;
+ this._mode = InflateMode.DICT0;
+ return ZLibStatus.Z_NEED_DICT;
+ case InflateMode.DICT0:
+ this._mode = InflateMode.BAD;
+ base.msg = "need dictionary";
+ this._marker = 0; // can try inflateSync
+ return ZLibStatus.Z_STREAM_ERROR;
+ case InflateMode.BLOCKS:
+
+ r = this._blocks.proc(this, r);
+ if (r == ZLibStatus.Z_DATA_ERROR)
+ {
+ this._mode = InflateMode.BAD;
+ this._marker = 0; // can try inflateSync
+ break;
+ }
+ if (r == ZLibStatus.Z_OK)
+ {
+ r = f;
+ }
+ if (r != ZLibStatus.Z_STREAM_END)
+ {
+ return r;
+ }
+ r = f;
+ this._blocks.reset(this, this._was);
+ if (this._nowrap != 0)
+ {
+ this._mode = InflateMode.DONE;
+ break;
+ }
+ this._mode = InflateMode.CHECK4;
+ goto case InflateMode.CHECK4;
+ case InflateMode.CHECK4:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need = ((base.next_in[base.next_in_index++] & 0xff) << 24) & 0xff000000L;
+ this._mode = InflateMode.CHECK3;
+ goto case InflateMode.CHECK3;
+ case InflateMode.CHECK3:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += ((base.next_in[base.next_in_index++] & 0xff) << 16) & 0xff0000L;
+ this._mode = InflateMode.CHECK2;
+ goto case InflateMode.CHECK2;
+ case InflateMode.CHECK2:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += ((base.next_in[base.next_in_index++] & 0xff) << 8) & 0xff00L;
+ this._mode = InflateMode.CHECK1;
+ goto case InflateMode.CHECK1;
+ case InflateMode.CHECK1:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += (base.next_in[base.next_in_index++] & 0xffL);
+
+ if (((int)(this._was[0])) != ((int)(this._need)))
+ {
+ this._mode = InflateMode.BAD;
+ base.msg = "incorrect data check";
+ this._marker = 5; // can't try inflateSync
+ break;
+ }
+
+ this._mode = InflateMode.DONE;
+ goto case InflateMode.DONE;
+ case InflateMode.DONE:
+ return ZLibStatus.Z_STREAM_END;
+ case InflateMode.BAD:
+ return ZLibStatus.Z_DATA_ERROR;
+ default:
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+ }
+ }
+
+ public ZLibStatus InflateSetDictionary(byte[] dictionary, int dictLength)
+ {
+ int index = 0;
+ int length = dictLength;
+ if (this._mode != InflateMode.DICT0)
+ return ZLibStatus.Z_STREAM_ERROR;
+
+ if (Adler32.adler32(1L, dictionary, 0, dictLength) != base.adler)
+ {
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+
+ base.adler = Adler32.adler32(0, null, 0, 0);
+
+ if (length >= (1 << this._wbits))
+ {
+ length = (1 << this._wbits) - 1;
+ index = dictLength - length;
+ }
+ this._blocks.set_dictionary(dictionary, index, length);
+ this._mode = InflateMode.BLOCKS;
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus InflateSync()
+ {
+ int n; // number of bytes to look at
+ int p; // pointer to bytes
+ int m; // number of marker bytes found in a row
+ long r, w; // temporaries to save total_in and total_out
+
+ // set up
+ if (this._mode != InflateMode.BAD)
+ {
+ this._mode = InflateMode.BAD;
+ this._marker = 0;
+ }
+ if ((n = base.avail_in) == 0)
+ return ZLibStatus.Z_BUF_ERROR;
+ p = base.next_in_index;
+ m = this._marker;
+
+ // search
+ while (n != 0 && m < 4)
+ {
+ if (base.next_in[p] == mark[m])
+ {
+ m++;
+ }
+ else if (base.next_in[p] != 0)
+ {
+ m = 0;
+ }
+ else
+ {
+ m = 4 - m;
+ }
+ p++; n--;
+ }
+
+ // restore
+ base.total_in += p - base.next_in_index;
+ base.next_in_index = p;
+ base.avail_in = n;
+ this._marker = m;
+
+ // return no joy or set up to restart on a new block
+ if (m != 4)
+ {
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ r = base.total_in; w = base.total_out;
+ InflateReset();
+ base.total_in = r; base.total_out = w;
+ this._mode = InflateMode.BLOCKS;
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus inflateInit()
+ {
+ return inflateInit(DEF_WBITS);
+ }
+ public ZLibStatus inflateInit(bool nowrap)
+ {
+ return inflateInit(DEF_WBITS, nowrap);
+ }
+ public ZLibStatus inflateInit(int w)
+ {
+ return inflateInit(w, false);
+ }
+
+ public ZLibStatus inflateInit(int w, bool nowrap)
+ {
+ return this.InflateInit(nowrap ? -w : w);
+ }
+
+ public ZLibStatus inflateEnd()
+ {
+ var ret = this.InflateEnd();
+ return ret;
+ }
+ public ZLibStatus inflateSync()
+ {
+ return this.InflateSync();
+ }
+
+ public ZLibStatus inflateSetDictionary(byte[] dictionary, int dictLength)
+ {
+ return this.InflateSetDictionary(dictionary, dictLength);
+ }
+
+ public ZLibStatus inflate(byte[] inputBufer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType)
+ {
+ this.next_in = inputBufer;
+ this.next_in_index = inputOffset;
+ this.avail_in = inputCount;
+ this.next_out = outputBuffer;
+ this.next_out_index = outputOffset;
+ this.avail_out = outputCount;
+ return this.inflate(flushType);
+ }
+
+ public ZLibStatus inflate(byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType)
+ {
+ this.next_out = outputBuffer;
+ this.next_out_index = outputOffset;
+ this.avail_out = outputCount;
+ return this.inflate(flushType);
+ }
+
+ // TODO: Dlete this
+ public ZLibStatus deflate(byte[] bufer, int offset, int count, byte[] p1, int p2, int p3, FlushType flushType)
+ {
+ throw new NotImplementedException();
+ }
+
+ public ZLibStatus deflateEnd()
+ {
+ throw new NotImplementedException();
+ }
+
+ public ZLibStatus deflate(byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v12/InflateBlocks.cs b/Renci.SshNet/Compression/v12/InflateBlocks.cs
new file mode 100644
index 0000000..dde3654
--- /dev/null
+++ b/Renci.SshNet/Compression/v12/InflateBlocks.cs
@@ -0,0 +1,721 @@
+using System;
+/*
+ * $Id: InfBlocks.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public enum InflateBlockMode
+ {
+ ///
+ /// get type bits (3, including end bit)
+ ///
+ TYPE = 0,
+ ///
+ /// get lengths for stored
+ ///
+ LENS = 1,
+ ///
+ /// cessing stored block
+ ///
+ STORED = 2,
+ ///
+ /// get table lengths
+ ///
+ TABLE = 3,
+ ///
+ /// get bit lengths tree for a dynamic block
+ ///
+ BTREE = 4,
+ ///
+ /// get length, distance trees for a dynamic block
+ ///
+ DTREE = 5,
+ ///
+ /// processing fixed or dynamic block
+ ///
+ CODES = 6,
+ ///
+ /// output remaining window bytes
+ ///
+ DRY = 7,
+ ///
+ /// finished last block, done
+ ///
+ DONE = 8,
+ ///
+ /// ot a data error--stuck here
+ ///
+ BAD = 9
+ }
+
+ internal sealed class InflateBlocks : InflateCodes
+ {
+ private const int MANY = 1440;
+
+ // And'ing with mask[n] masks the lower n bits
+ private static readonly int[] inflate_mask = {
+ 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
+ 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
+ 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
+ 0x00007fff, 0x0000ffff
+ };
+
+ // Table for deflate from PKZIP's appnote.txt.
+ static readonly int[] border = { // Order of the bit length code lengths
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
+ };
+
+ internal InflateBlockMode mode; // current inflate_block mode
+
+ internal int left; // if STORED, bytes left to copy
+
+ internal int table; // table lengths (14 bits)
+ internal int index; // index into blens (or border)
+ internal int[] blens; // bit lengths of codes
+ internal int[] bb = new int[1]; // bit length tree depth
+ internal int[] tb = new int[1]; // bit length decoding tree
+
+ //internal InfCodes codes = new InfCodes(); // if CODES, current state
+
+ int last; // true if this block is the last block
+
+ // mode independent information
+ internal int bitk; // bits in bit buffer
+ internal int bitb; // bit buffer
+ internal int[] hufts; // single malloc for tree space
+ internal byte[] window; // sliding window
+ internal int end; // one byte after sliding window
+ internal int read; // window read pointer
+ internal int write; // window write pointer
+ internal Object checkfn; // check function
+ internal long check; // check on output
+
+ internal InflateTree inftree = new InflateTree();
+
+ internal InflateBlocks(ICompressor z, Object checkfn, int w)
+ {
+ hufts = new int[MANY * 3];
+ window = new byte[w];
+ end = w;
+ this.checkfn = checkfn;
+ mode = InflateBlockMode.TYPE;
+ reset(z, null);
+ }
+
+ internal void reset(ICompressor z, long[] c)
+ {
+ if (c != null) c[0] = check;
+ if (mode == InflateBlockMode.BTREE || mode == InflateBlockMode.DTREE)
+ {
+ }
+ if (mode == InflateBlockMode.CODES)
+ {
+ codesfree(z);
+ }
+ mode = InflateBlockMode.TYPE;
+ bitk = 0;
+ bitb = 0;
+ read = write = 0;
+
+ if (checkfn != null)
+ z.adler = check = Adler32.adler32(0L, null, 0, 0);
+ }
+
+ internal ZLibStatus proc(ICompressor z, ZLibStatus r)
+ {
+ int t; // temporary storage
+ ZLibStatus tt;
+ int b; // bit buffer
+ int k; // bits in bit buffer
+ int p; // input data pointer
+ int n; // bytes available there
+ int q; // output window write pointer
+ int m;
+ { // bytes to end of window or read pointer
+
+ // copy input/output information to locals (UPDATE macro restores)
+ p = z.next_in_index; n = z.avail_in; b = bitb; k = bitk;
+ }
+ {
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+ }
+
+ // process input based on current state
+ while (true)
+ {
+ switch (mode)
+ {
+ case InflateBlockMode.TYPE:
+
+ while (k < (3))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+ t = (int)(b & 7);
+ last = t & 1;
+
+ switch (t >> 1)
+ {
+ case 0:
+ { // stored
+ b >>= (3); k -= (3);
+ }
+ t = k & 7;
+ { // go to byte boundary
+
+ b >>= (t); k -= (t);
+ }
+ mode = InflateBlockMode.LENS; // get length of stored block
+ break;
+ case 1:
+ { // fixed
+ int[] bl = new int[1];
+ int[] bd = new int[1];
+ int[][] tl = new int[1][];
+ int[][] td = new int[1][];
+
+ InflateTree.InflateTreesFixed(bl, bd, tl, td, z);
+ codesinit(bl[0], bd[0], tl[0], 0, td[0], 0, z);
+ }
+ {
+
+ b >>= (3); k -= (3);
+ }
+
+ mode = InflateBlockMode.CODES;
+ break;
+ case 2:
+ { // dynamic
+
+ b >>= (3); k -= (3);
+ }
+
+ mode = InflateBlockMode.TABLE;
+ break;
+ case 3:
+ { // illegal
+
+ b >>= (3); k -= (3);
+ }
+ mode = InflateBlockMode.BAD;
+ z.msg = "invalid block type";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ break;
+ case InflateBlockMode.LENS:
+
+ while (k < (32))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ if ((((~b) >> 16) & 0xffff) != (b & 0xffff))
+ {
+ mode = InflateBlockMode.BAD;
+ z.msg = "invalid stored block lengths";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ left = (b & 0xffff);
+ b = k = 0; // dump bits
+ mode = left != 0 ? InflateBlockMode.STORED : (last != 0 ? InflateBlockMode.DRY : InflateBlockMode.TYPE);
+ break;
+ case InflateBlockMode.STORED:
+ if (n == 0)
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+
+ if (m == 0)
+ {
+ if (q == end && read != 0)
+ {
+ q = 0; m = (int)(q < read ? read - q - 1 : end - q);
+ }
+ if (m == 0)
+ {
+ write = q;
+ r = inflate_flush(z, r);
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+ if (q == end && read != 0)
+ {
+ q = 0; m = (int)(q < read ? read - q - 1 : end - q);
+ }
+ if (m == 0)
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ }
+ }
+ r = ZLibStatus.Z_OK;
+
+ t = left;
+ if (t > n) t = n;
+ if (t > m) t = m;
+ System.Array.Copy(z.next_in, p, window, q, t);
+ p += t; n -= t;
+ q += t; m -= t;
+ if ((left -= t) != 0)
+ break;
+ mode = last != 0 ? InflateBlockMode.DRY : InflateBlockMode.TYPE;
+ break;
+ case InflateBlockMode.TABLE:
+
+ while (k < (14))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ table = t = (b & 0x3fff);
+ if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
+ {
+ mode = InflateBlockMode.BAD;
+ z.msg = "too many length or distance symbols";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
+ if (blens == null || blens.Length < t)
+ {
+ blens = new int[t];
+ }
+ else
+ {
+ for (int i = 0; i < t; i++) { blens[i] = 0; }
+ }
+ {
+
+ b >>= (14); k -= (14);
+ }
+
+ index = 0;
+ mode = InflateBlockMode.BTREE;
+ goto case InflateBlockMode.BTREE;
+ case InflateBlockMode.BTREE:
+ while (index < 4 + (table >> 10))
+ {
+ while (k < (3))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ blens[border[index++]] = b & 7;
+ {
+
+ b >>= (3); k -= (3);
+ }
+ }
+
+ while (index < 19)
+ {
+ blens[border[index++]] = 0;
+ }
+
+ bb[0] = 7;
+ tt = inftree.InflateTreesBits(blens, bb, tb, hufts, z);
+ if (tt != ZLibStatus.Z_OK)
+ {
+ r = tt;
+ if (r == ZLibStatus.Z_DATA_ERROR)
+ {
+ blens = null;
+ mode = InflateBlockMode.BAD;
+ }
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+
+ index = 0;
+ mode = InflateBlockMode.DTREE;
+ goto case InflateBlockMode.DTREE;
+ case InflateBlockMode.DTREE:
+ while (true)
+ {
+ t = table;
+ if (!(index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)))
+ {
+ break;
+ }
+
+ int i, j, c;
+
+ t = bb[0];
+
+ while (k < (t))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ if (tb[0] == -1)
+ {
+ //System.err.println("null...");
+ }
+
+ t = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 1];
+ c = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 2];
+
+ if (c < 16)
+ {
+ b >>= (t); k -= (t);
+ blens[index++] = c;
+ }
+ else
+ { // c == 16..18
+ i = c == 18 ? 7 : c - 14;
+ j = c == 18 ? 11 : 3;
+
+ while (k < (t + i))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ b >>= (t); k -= (t);
+
+ j += (b & inflate_mask[i]);
+
+ b >>= (i); k -= (i);
+
+ i = index;
+ t = table;
+ if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
+ (c == 16 && i < 1))
+ {
+ blens = null;
+ mode = InflateBlockMode.BAD;
+ z.msg = "invalid bit length repeat";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+
+ c = c == 16 ? blens[i - 1] : 0;
+ do
+ {
+ blens[i++] = c;
+ }
+ while (--j != 0);
+ index = i;
+ }
+ }
+
+ tb[0] = -1;
+ {
+ int[] bl = new int[1];
+ int[] bd = new int[1];
+ int[] tl = new int[1];
+ int[] td = new int[1];
+ bl[0] = 9; // must be <= 9 for lookahead assumptions
+ bd[0] = 6; // must be <= 9 for lookahead assumptions
+
+ t = table;
+ tt = inftree.InflateTreesDynamic(257 + (t & 0x1f),
+ 1 + ((t >> 5) & 0x1f),
+ blens, bl, bd, tl, td, hufts, z);
+
+ if (tt != ZLibStatus.Z_OK)
+ {
+ if (tt == ZLibStatus.Z_DATA_ERROR)
+ {
+ blens = null;
+ mode = InflateBlockMode.BAD;
+ }
+ r = tt;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ codesinit(bl[0], bd[0], hufts, tl[0], hufts, td[0], z);
+ }
+ mode = InflateBlockMode.CODES;
+ goto case InflateBlockMode.CODES;
+ case InflateBlockMode.CODES:
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+
+ if ((r = codesproc(this, z, r)) != ZLibStatus.Z_STREAM_END)
+ {
+ return inflate_flush(z, r);
+ }
+ r = ZLibStatus.Z_OK;
+ codesfree(z);
+
+ p = z.next_in_index; n = z.avail_in; b = bitb; k = bitk;
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+
+ if (last == 0)
+ {
+ mode = InflateBlockMode.TYPE;
+ break;
+ }
+ mode = InflateBlockMode.DRY;
+ goto case InflateBlockMode.DRY;
+ case InflateBlockMode.DRY:
+ write = q;
+ r = inflate_flush(z, r);
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+ if (read != write)
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ mode = InflateBlockMode.DONE;
+ goto case InflateBlockMode.DONE;
+ case InflateBlockMode.DONE:
+ r = ZLibStatus.Z_STREAM_END;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ case InflateBlockMode.BAD:
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+
+ default:
+ r = ZLibStatus.Z_STREAM_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ }
+ }
+
+ internal void free(ICompressor z)
+ {
+ reset(z, null);
+ window = null;
+ hufts = null;
+ //ZFREE(z, s);
+ }
+
+ internal void set_dictionary(byte[] d, int start, int n)
+ {
+ System.Array.Copy(d, start, window, 0, n);
+ read = write = n;
+ }
+
+ // Returns true if inflate is currently at the end of a block generated
+ // by Z_SYNC_FLUSH or FlushType.Z_FULL_FLUSH.
+ internal ZLibStatus sync_point()
+ {
+ return mode == InflateBlockMode.LENS ? ZLibStatus.Z_STREAM_END : ZLibStatus.Z_OK;
+ }
+
+ // copy as much as possible from the sliding window to the output area
+ internal ZLibStatus inflate_flush(ICompressor z, ZLibStatus r)
+ {
+ int n;
+ int p;
+ int q;
+
+ // local copies of source and destination pointers
+ p = z.next_out_index;
+ q = read;
+
+ // compute number of bytes to copy as far as end of window
+ n = (int)((q <= write ? write : end) - q);
+ if (n > z.avail_out) n = z.avail_out;
+ if (n != 0 && r == ZLibStatus.Z_BUF_ERROR) r = ZLibStatus.Z_OK;
+
+ // update counters
+ z.avail_out -= n;
+ z.total_out += n;
+
+ // update check information
+ if (checkfn != null)
+ z.adler = check = Adler32.adler32(check, window, q, n);
+
+ // copy as far as end of window
+ System.Array.Copy(window, q, z.next_out, p, n);
+ p += n;
+ q += n;
+
+ // see if more to copy at beginning of window
+ if (q == end)
+ {
+ // wrap pointers
+ q = 0;
+ if (write == end)
+ write = 0;
+
+ // compute bytes to copy
+ n = write - q;
+ if (n > z.avail_out) n = z.avail_out;
+ if (n != 0 && r == ZLibStatus.Z_BUF_ERROR) r = ZLibStatus.Z_OK;
+
+ // update counters
+ z.avail_out -= n;
+ z.total_out += n;
+
+ // update check information
+ if (checkfn != null)
+ z.adler = check = Adler32.adler32(check, window, q, n);
+
+ // copy
+ System.Array.Copy(window, q, z.next_out, p, n);
+ p += n;
+ q += n;
+ }
+
+ // update pointers
+ z.next_out_index = p;
+ read = q;
+
+ // done
+ return r;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v12/InflateCodes.cs b/Renci.SshNet/Compression/v12/InflateCodes.cs
new file mode 100644
index 0000000..5edecb7
--- /dev/null
+++ b/Renci.SshNet/Compression/v12/InflateCodes.cs
@@ -0,0 +1,690 @@
+using System;
+/*
+ * $Id: InfCodes.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public enum InflateCodeMode
+ {
+ ///
+ /// x: set up for InflateCodeMode.LEN
+ ///
+ START = 0,
+ ///
+ /// i: get length/literal/eob next
+ ///
+ LEN = 1,
+ ///
+ /// i: getting length extra (have base)
+ ///
+ LENEXT = 2,
+ ///
+ /// i: get distance next
+ ///
+ DIST = 3,
+ ///
+ /// : getting distance extra
+ ///
+ DISTEXT = 4,
+ ///
+ /// o: copying bytes in window, waiting for space
+ ///
+ COPY = 5,
+ ///
+ /// o: got literal, waiting for output space
+ ///
+ LIT = 6,
+ ///
+ /// o: got eob, possibly still output waiting
+ ///
+ WASH = 7,
+ ///
+ /// x: got eob and all data flushed
+ ///
+ END = 8,
+ ///
+ /// x: got error
+ ///
+ BADCODE = 9
+ }
+
+ internal abstract class InflateCodes// : ZStream
+ {
+ private static readonly int[] inflate_mask = {
+ 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
+ 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
+ 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
+ 0x00007fff, 0x0000ffff
+ };
+
+ InflateCodeMode mode; // current inflate_codes mode
+
+ // mode dependent information
+ int len;
+
+ int[] tree; // pointer into tree
+ int tree_index = 0;
+ int need; // bits needed
+
+ int lit;
+
+ // if EXT or COPY, where and how much
+ int get; // bits to get for extra
+ int dist; // distance back to copy from
+
+ byte lbits; // ltree bits decoded per branch
+ byte dbits; // dtree bits decoder per branch
+ int[] ltree; // literal/length/eob tree
+ int ltree_index; // literal/length/eob tree
+ int[] dtree; // distance tree
+ int dtree_index; // distance tree
+
+ internal InflateCodes()
+ {
+ }
+ internal void codesinit(int bl, int bd,
+ int[] tl, int tl_index,
+ int[] td, int td_index, ICompressor z)
+ {
+ mode = InflateCodeMode.START;
+ lbits = (byte)bl;
+ dbits = (byte)bd;
+ ltree = tl;
+ ltree_index = tl_index;
+ dtree = td;
+ dtree_index = td_index;
+ tree = null;
+ }
+
+ internal ZLibStatus codesproc(InflateBlocks s, ICompressor z, ZLibStatus r)
+ {
+ int j; // temporary storage
+ int tindex; // temporary pointer
+ int e; // extra bits or operation
+ int b = 0; // bit buffer
+ int k = 0; // bits in bit buffer
+ int p = 0; // input data pointer
+ int n; // bytes available there
+ int q; // output window write pointer
+ int m; // bytes to end of window or read pointer
+ int f; // pointer to copy strings from
+
+ // copy input/output information to locals (UPDATE macro restores)
+ p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk;
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ // process input and output based on current state
+ while (true)
+ {
+ switch (mode)
+ {
+ // waiting for "i:"=input, "o:"=output, "x:"=nothing
+ case InflateCodeMode.START: // x: set up for LEN
+ if (m >= 258 && n >= 10)
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ r = inflate_fast(lbits, dbits,
+ ltree, ltree_index,
+ dtree, dtree_index,
+ s, z);
+
+ p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk;
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (r != ZLibStatus.Z_OK)
+ {
+ mode = r == ZLibStatus.Z_STREAM_END ? InflateCodeMode.WASH : InflateCodeMode.BADCODE;
+ break;
+ }
+ }
+ need = lbits;
+ tree = ltree;
+ tree_index = ltree_index;
+
+ mode = InflateCodeMode.LEN;
+ goto case InflateCodeMode.LEN;
+ case InflateCodeMode.LEN: // i: get length/literal/eob next
+ j = need;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ tindex = (tree_index + (b & inflate_mask[j])) * 3;
+
+ b >>= (tree[tindex + 1]);
+ k -= (tree[tindex + 1]);
+
+ e = tree[tindex];
+
+ if (e == 0)
+ { // literal
+ lit = tree[tindex + 2];
+ mode = InflateCodeMode.LIT;
+ break;
+ }
+ if ((e & 16) != 0)
+ { // length
+ get = e & 15;
+ len = tree[tindex + 2];
+ mode = InflateCodeMode.LENEXT;
+ break;
+ }
+ if ((e & 64) == 0)
+ { // next table
+ need = e;
+ tree_index = tindex / 3 + tree[tindex + 2];
+ break;
+ }
+ if ((e & 32) != 0)
+ { // end of block
+ mode = InflateCodeMode.WASH;
+ break;
+ }
+ mode = InflateCodeMode.BADCODE; // invalid code
+ z.msg = "invalid literal/length code";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ case InflateCodeMode.LENEXT: // i: getting length extra (have base)
+ j = get;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--; b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ len += (b & inflate_mask[j]);
+
+ b >>= j;
+ k -= j;
+
+ need = dbits;
+ tree = dtree;
+ tree_index = dtree_index;
+ mode = InflateCodeMode.DIST;
+ goto case InflateCodeMode.DIST;
+ case InflateCodeMode.DIST: // i: get distance next
+ j = need;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--; b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ tindex = (tree_index + (b & inflate_mask[j])) * 3;
+
+ b >>= tree[tindex + 1];
+ k -= tree[tindex + 1];
+
+ e = (tree[tindex]);
+ if ((e & 16) != 0)
+ { // distance
+ get = e & 15;
+ dist = tree[tindex + 2];
+ mode = InflateCodeMode.DISTEXT;
+ break;
+ }
+ if ((e & 64) == 0)
+ { // next table
+ need = e;
+ tree_index = tindex / 3 + tree[tindex + 2];
+ break;
+ }
+ mode = InflateCodeMode.BADCODE; // invalid code
+ z.msg = "invalid distance code";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ case InflateCodeMode.DISTEXT: // i: getting distance extra
+ j = get;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--; b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ dist += (b & inflate_mask[j]);
+
+ b >>= j;
+ k -= j;
+
+ mode = InflateCodeMode.COPY;
+ goto case InflateCodeMode.COPY;
+ case InflateCodeMode.COPY: // o: copying bytes in window, waiting for space
+ f = q - dist;
+ while (f < 0)
+ { // modulo window size-"while" instead
+ f += s.end; // of "if" handles invalid distances
+ }
+ while (len != 0)
+ {
+
+ if (m == 0)
+ {
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+ if (m == 0)
+ {
+ s.write = q; r = s.inflate_flush(z, r);
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+
+ if (m == 0)
+ {
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ }
+ }
+
+ s.window[q++] = s.window[f++]; m--;
+
+ if (f == s.end)
+ f = 0;
+ len--;
+ }
+ mode = InflateCodeMode.START;
+ break;
+ case InflateCodeMode.LIT: // o: got literal, waiting for output space
+ if (m == 0)
+ {
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+ if (m == 0)
+ {
+ s.write = q; r = s.inflate_flush(z, r);
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+ if (m == 0)
+ {
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ }
+ }
+ r = ZLibStatus.Z_OK;
+
+ s.window[q++] = (byte)lit; m--;
+
+ mode = InflateCodeMode.START;
+ break;
+ case InflateCodeMode.WASH: // o: got eob, possibly more output
+ if (k > 7)
+ { // return unused byte, if any
+ k -= 8;
+ n++;
+ p--; // can always return one
+ }
+
+ s.write = q; r = s.inflate_flush(z, r);
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (s.read != s.write)
+ {
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ mode = InflateCodeMode.END;
+ goto case InflateCodeMode.END;
+ case InflateCodeMode.END:
+ r = ZLibStatus.Z_STREAM_END;
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ case InflateCodeMode.BADCODE: // x: got error
+
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ default:
+ r = ZLibStatus.Z_STREAM_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ }
+ }
+
+ internal void codesfree(ICompressor z)
+ {
+ // ZFREE(z, c);
+ }
+
+ // Called with number of bytes left to write in window at least 258
+ // (the maximum string length) and number of input bytes available
+ // at least ten. The ten bytes are six bytes for the longest length/
+ // distance pair plus four bytes for overloading the bit buffer.
+
+ internal ZLibStatus inflate_fast(int bl, int bd,
+ int[] tl, int tl_index,
+ int[] td, int td_index,
+ InflateBlocks s, ICompressor z)
+ {
+ int t; // temporary pointer
+ int[] tp; // temporary pointer
+ int tp_index; // temporary pointer
+ int e; // extra bits or operation
+ int b; // bit buffer
+ int k; // bits in bit buffer
+ int p; // input data pointer
+ int n; // bytes available there
+ int q; // output window write pointer
+ int m; // bytes to end of window or read pointer
+ int ml; // mask for literal/length tree
+ int md; // mask for distance tree
+ int c; // bytes to copy
+ int d; // distance back to copy from
+ int r; // copy source pointer
+
+ int tp_index_t_3; // (tp_index+t)*3
+
+ // load input, output, bit values
+ p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk;
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ // initialize masks
+ ml = inflate_mask[bl];
+ md = inflate_mask[bd];
+
+ // do until not enough input or output space for fast loop
+ do
+ { // assume called with m >= 258 && n >= 10
+ // get literal/length code
+ while (k < (20))
+ { // max bits for literal/length code
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k; k += 8;
+ }
+
+ t = b & ml;
+ tp = tl;
+ tp_index = tl_index;
+ tp_index_t_3 = (tp_index + t) * 3;
+ if ((e = tp[tp_index_t_3]) == 0)
+ {
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ s.window[q++] = (byte)tp[tp_index_t_3 + 2];
+ m--;
+ continue;
+ }
+ do
+ {
+
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ if ((e & 16) != 0)
+ {
+ e &= 15;
+ c = tp[tp_index_t_3 + 2] + ((int)b & inflate_mask[e]);
+
+ b >>= e; k -= e;
+
+ // decode distance base of block to copy
+ while (k < (15))
+ { // max bits for distance code
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k; k += 8;
+ }
+
+ t = b & md;
+ tp = td;
+ tp_index = td_index;
+ tp_index_t_3 = (tp_index + t) * 3;
+ e = tp[tp_index_t_3];
+
+ do
+ {
+
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ if ((e & 16) != 0)
+ {
+ // get extra bits to add to distance base
+ e &= 15;
+ while (k < (e))
+ { // get extra bits (up to 13)
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k; k += 8;
+ }
+
+ d = tp[tp_index_t_3 + 2] + (b & inflate_mask[e]);
+
+ b >>= (e); k -= (e);
+
+ // do the copy
+ m -= c;
+ if (q >= d)
+ { // offset before dest
+ // just copy
+ r = q - d;
+ if (q - r > 0 && 2 > (q - r))
+ {
+ s.window[q++] = s.window[r++]; // minimum count is three,
+ s.window[q++] = s.window[r++]; // so unroll loop a little
+ c -= 2;
+ }
+ else
+ {
+ System.Array.Copy(s.window, r, s.window, q, 2);
+ q += 2; r += 2; c -= 2;
+ }
+ }
+ else
+ { // else offset after destination
+ r = q - d;
+ do
+ {
+ r += s.end; // force pointer in window
+ } while (r < 0); // covers invalid distances
+ e = s.end - r;
+ if (c > e)
+ { // if source crosses,
+ c -= e; // wrapped copy
+ if (q - r > 0 && e > (q - r))
+ {
+ do { s.window[q++] = s.window[r++]; }
+ while (--e != 0);
+ }
+ else
+ {
+ System.Array.Copy(s.window, r, s.window, q, e);
+ q += e; r += e; e = 0;
+ }
+ r = 0; // copy rest from start of window
+ }
+
+ }
+
+ // copy all or what's left
+ if (q - r > 0 && c > (q - r))
+ {
+ do { s.window[q++] = s.window[r++]; }
+ while (--c != 0);
+ }
+ else
+ {
+ System.Array.Copy(s.window, r, s.window, q, c);
+ q += c; r += c; c = 0;
+ }
+ break;
+ }
+ else if ((e & 64) == 0)
+ {
+ t += tp[tp_index_t_3 + 2];
+ t += (b & inflate_mask[e]);
+ tp_index_t_3 = (tp_index + t) * 3;
+ e = tp[tp_index_t_3];
+ }
+ else
+ {
+ z.msg = "invalid distance code";
+
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ }
+ while (true);
+ break;
+ }
+
+ if ((e & 64) == 0)
+ {
+ t += tp[tp_index_t_3 + 2];
+ t += (b & inflate_mask[e]);
+ tp_index_t_3 = (tp_index + t) * 3;
+ if ((e = tp[tp_index_t_3]) == 0)
+ {
+
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ s.window[q++] = (byte)tp[tp_index_t_3 + 2];
+ m--;
+ break;
+ }
+ }
+ else if ((e & 32) != 0)
+ {
+
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_STREAM_END;
+ }
+ else
+ {
+ z.msg = "invalid literal/length code";
+
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ }
+ while (true);
+ }
+ while (m >= 258 && n >= 10);
+
+ // not enough input or output--restore pointers and return
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_OK;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v12/InflateTree.cs b/Renci.SshNet/Compression/v12/InflateTree.cs
new file mode 100644
index 0000000..a97d4cb
--- /dev/null
+++ b/Renci.SshNet/Compression/v12/InflateTree.cs
@@ -0,0 +1,555 @@
+using System;
+/*
+ * $Id: InfTree.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ internal sealed class InflateTree
+ {
+ private const int MANY = 1440;
+
+ private const int fixed_bl = 9;
+ private const int fixed_bd = 5;
+
+ static readonly int[] fixed_tl = {
+ 96,7,256, 0,8,80, 0,8,16, 84,8,115,
+ 82,7,31, 0,8,112, 0,8,48, 0,9,192,
+ 80,7,10, 0,8,96, 0,8,32, 0,9,160,
+ 0,8,0, 0,8,128, 0,8,64, 0,9,224,
+ 80,7,6, 0,8,88, 0,8,24, 0,9,144,
+ 83,7,59, 0,8,120, 0,8,56, 0,9,208,
+ 81,7,17, 0,8,104, 0,8,40, 0,9,176,
+ 0,8,8, 0,8,136, 0,8,72, 0,9,240,
+ 80,7,4, 0,8,84, 0,8,20, 85,8,227,
+ 83,7,43, 0,8,116, 0,8,52, 0,9,200,
+ 81,7,13, 0,8,100, 0,8,36, 0,9,168,
+ 0,8,4, 0,8,132, 0,8,68, 0,9,232,
+ 80,7,8, 0,8,92, 0,8,28, 0,9,152,
+ 84,7,83, 0,8,124, 0,8,60, 0,9,216,
+ 82,7,23, 0,8,108, 0,8,44, 0,9,184,
+ 0,8,12, 0,8,140, 0,8,76, 0,9,248,
+ 80,7,3, 0,8,82, 0,8,18, 85,8,163,
+ 83,7,35, 0,8,114, 0,8,50, 0,9,196,
+ 81,7,11, 0,8,98, 0,8,34, 0,9,164,
+ 0,8,2, 0,8,130, 0,8,66, 0,9,228,
+ 80,7,7, 0,8,90, 0,8,26, 0,9,148,
+ 84,7,67, 0,8,122, 0,8,58, 0,9,212,
+ 82,7,19, 0,8,106, 0,8,42, 0,9,180,
+ 0,8,10, 0,8,138, 0,8,74, 0,9,244,
+ 80,7,5, 0,8,86, 0,8,22, 192,8,0,
+ 83,7,51, 0,8,118, 0,8,54, 0,9,204,
+ 81,7,15, 0,8,102, 0,8,38, 0,9,172,
+ 0,8,6, 0,8,134, 0,8,70, 0,9,236,
+ 80,7,9, 0,8,94, 0,8,30, 0,9,156,
+ 84,7,99, 0,8,126, 0,8,62, 0,9,220,
+ 82,7,27, 0,8,110, 0,8,46, 0,9,188,
+ 0,8,14, 0,8,142, 0,8,78, 0,9,252,
+ 96,7,256, 0,8,81, 0,8,17, 85,8,131,
+ 82,7,31, 0,8,113, 0,8,49, 0,9,194,
+ 80,7,10, 0,8,97, 0,8,33, 0,9,162,
+ 0,8,1, 0,8,129, 0,8,65, 0,9,226,
+ 80,7,6, 0,8,89, 0,8,25, 0,9,146,
+ 83,7,59, 0,8,121, 0,8,57, 0,9,210,
+ 81,7,17, 0,8,105, 0,8,41, 0,9,178,
+ 0,8,9, 0,8,137, 0,8,73, 0,9,242,
+ 80,7,4, 0,8,85, 0,8,21, 80,8,258,
+ 83,7,43, 0,8,117, 0,8,53, 0,9,202,
+ 81,7,13, 0,8,101, 0,8,37, 0,9,170,
+ 0,8,5, 0,8,133, 0,8,69, 0,9,234,
+ 80,7,8, 0,8,93, 0,8,29, 0,9,154,
+ 84,7,83, 0,8,125, 0,8,61, 0,9,218,
+ 82,7,23, 0,8,109, 0,8,45, 0,9,186,
+ 0,8,13, 0,8,141, 0,8,77, 0,9,250,
+ 80,7,3, 0,8,83, 0,8,19, 85,8,195,
+ 83,7,35, 0,8,115, 0,8,51, 0,9,198,
+ 81,7,11, 0,8,99, 0,8,35, 0,9,166,
+ 0,8,3, 0,8,131, 0,8,67, 0,9,230,
+ 80,7,7, 0,8,91, 0,8,27, 0,9,150,
+ 84,7,67, 0,8,123, 0,8,59, 0,9,214,
+ 82,7,19, 0,8,107, 0,8,43, 0,9,182,
+ 0,8,11, 0,8,139, 0,8,75, 0,9,246,
+ 80,7,5, 0,8,87, 0,8,23, 192,8,0,
+ 83,7,51, 0,8,119, 0,8,55, 0,9,206,
+ 81,7,15, 0,8,103, 0,8,39, 0,9,174,
+ 0,8,7, 0,8,135, 0,8,71, 0,9,238,
+ 80,7,9, 0,8,95, 0,8,31, 0,9,158,
+ 84,7,99, 0,8,127, 0,8,63, 0,9,222,
+ 82,7,27, 0,8,111, 0,8,47, 0,9,190,
+ 0,8,15, 0,8,143, 0,8,79, 0,9,254,
+ 96,7,256, 0,8,80, 0,8,16, 84,8,115,
+ 82,7,31, 0,8,112, 0,8,48, 0,9,193,
+
+ 80,7,10, 0,8,96, 0,8,32, 0,9,161,
+ 0,8,0, 0,8,128, 0,8,64, 0,9,225,
+ 80,7,6, 0,8,88, 0,8,24, 0,9,145,
+ 83,7,59, 0,8,120, 0,8,56, 0,9,209,
+ 81,7,17, 0,8,104, 0,8,40, 0,9,177,
+ 0,8,8, 0,8,136, 0,8,72, 0,9,241,
+ 80,7,4, 0,8,84, 0,8,20, 85,8,227,
+ 83,7,43, 0,8,116, 0,8,52, 0,9,201,
+ 81,7,13, 0,8,100, 0,8,36, 0,9,169,
+ 0,8,4, 0,8,132, 0,8,68, 0,9,233,
+ 80,7,8, 0,8,92, 0,8,28, 0,9,153,
+ 84,7,83, 0,8,124, 0,8,60, 0,9,217,
+ 82,7,23, 0,8,108, 0,8,44, 0,9,185,
+ 0,8,12, 0,8,140, 0,8,76, 0,9,249,
+ 80,7,3, 0,8,82, 0,8,18, 85,8,163,
+ 83,7,35, 0,8,114, 0,8,50, 0,9,197,
+ 81,7,11, 0,8,98, 0,8,34, 0,9,165,
+ 0,8,2, 0,8,130, 0,8,66, 0,9,229,
+ 80,7,7, 0,8,90, 0,8,26, 0,9,149,
+ 84,7,67, 0,8,122, 0,8,58, 0,9,213,
+ 82,7,19, 0,8,106, 0,8,42, 0,9,181,
+ 0,8,10, 0,8,138, 0,8,74, 0,9,245,
+ 80,7,5, 0,8,86, 0,8,22, 192,8,0,
+ 83,7,51, 0,8,118, 0,8,54, 0,9,205,
+ 81,7,15, 0,8,102, 0,8,38, 0,9,173,
+ 0,8,6, 0,8,134, 0,8,70, 0,9,237,
+ 80,7,9, 0,8,94, 0,8,30, 0,9,157,
+ 84,7,99, 0,8,126, 0,8,62, 0,9,221,
+ 82,7,27, 0,8,110, 0,8,46, 0,9,189,
+ 0,8,14, 0,8,142, 0,8,78, 0,9,253,
+ 96,7,256, 0,8,81, 0,8,17, 85,8,131,
+ 82,7,31, 0,8,113, 0,8,49, 0,9,195,
+ 80,7,10, 0,8,97, 0,8,33, 0,9,163,
+ 0,8,1, 0,8,129, 0,8,65, 0,9,227,
+ 80,7,6, 0,8,89, 0,8,25, 0,9,147,
+ 83,7,59, 0,8,121, 0,8,57, 0,9,211,
+ 81,7,17, 0,8,105, 0,8,41, 0,9,179,
+ 0,8,9, 0,8,137, 0,8,73, 0,9,243,
+ 80,7,4, 0,8,85, 0,8,21, 80,8,258,
+ 83,7,43, 0,8,117, 0,8,53, 0,9,203,
+ 81,7,13, 0,8,101, 0,8,37, 0,9,171,
+ 0,8,5, 0,8,133, 0,8,69, 0,9,235,
+ 80,7,8, 0,8,93, 0,8,29, 0,9,155,
+ 84,7,83, 0,8,125, 0,8,61, 0,9,219,
+ 82,7,23, 0,8,109, 0,8,45, 0,9,187,
+ 0,8,13, 0,8,141, 0,8,77, 0,9,251,
+ 80,7,3, 0,8,83, 0,8,19, 85,8,195,
+ 83,7,35, 0,8,115, 0,8,51, 0,9,199,
+ 81,7,11, 0,8,99, 0,8,35, 0,9,167,
+ 0,8,3, 0,8,131, 0,8,67, 0,9,231,
+ 80,7,7, 0,8,91, 0,8,27, 0,9,151,
+ 84,7,67, 0,8,123, 0,8,59, 0,9,215,
+ 82,7,19, 0,8,107, 0,8,43, 0,9,183,
+ 0,8,11, 0,8,139, 0,8,75, 0,9,247,
+ 80,7,5, 0,8,87, 0,8,23, 192,8,0,
+ 83,7,51, 0,8,119, 0,8,55, 0,9,207,
+ 81,7,15, 0,8,103, 0,8,39, 0,9,175,
+ 0,8,7, 0,8,135, 0,8,71, 0,9,239,
+ 80,7,9, 0,8,95, 0,8,31, 0,9,159,
+ 84,7,99, 0,8,127, 0,8,63, 0,9,223,
+ 82,7,27, 0,8,111, 0,8,47, 0,9,191,
+ 0,8,15, 0,8,143, 0,8,79, 0,9,255
+ };
+ static readonly int[] fixed_td = {
+ 80,5,1, 87,5,257, 83,5,17, 91,5,4097,
+ 81,5,5, 89,5,1025, 85,5,65, 93,5,16385,
+ 80,5,3, 88,5,513, 84,5,33, 92,5,8193,
+ 82,5,9, 90,5,2049, 86,5,129, 192,5,24577,
+ 80,5,2, 87,5,385, 83,5,25, 91,5,6145,
+ 81,5,7, 89,5,1537, 85,5,97, 93,5,24577,
+ 80,5,4, 88,5,769, 84,5,49, 92,5,12289,
+ 82,5,13, 90,5,3073, 86,5,193, 192,5,24577
+ };
+
+ // Tables for deflate from PKZIP's appnote.txt.
+ static readonly int[] cplens = { // Copy lengths for literal codes 257..285
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
+ };
+
+ // see note #13 above about 258
+ static readonly int[] cplext = { // Extra bits for literal codes 257..285
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+ 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112 // 112==invalid
+ };
+
+ static readonly int[] cpdist = { // Copy offsets for distance codes 0..29
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+ 8193, 12289, 16385, 24577
+ };
+
+ static readonly int[] cpdext = { // Extra bits for distance codes
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+ 12, 12, 13, 13};
+
+ // If BMAX needs to be larger than 16, then h and x[] should be uLong.
+ const int BMAX = 15; // maximum bit length of any code
+
+ int[] hn = null; // hufts used in space
+ int[] v = null; // work area for huft_build
+ int[] c = null; // bit length count table
+ int[] r = null; // table entry for structure assignment
+ int[] u = null; // table stack
+ int[] x = null; // bit offsets, then code stack
+
+ private ZLibStatus HuftBuild(int[] b, // code lengths in bits (all assumed <= BMAX)
+ int bindex,
+ int n, // number of codes (assumed <= 288)
+ int s, // number of simple-valued codes (0..s-1)
+ int[] d, // list of base values for non-simple codes
+ int[] e, // list of extra bits for non-simple codes
+ int[] t, // result: starting table
+ int[] m, // maximum lookup bits, returns actual
+ int[] hp,// space for trees
+ int[] hn,// hufts used in space
+ int[] v // working area: values in order of bit length
+ )
+ {
+ // Given a list of code lengths and a maximum table size, make a set of
+ // tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR
+ // if the given code set is incomplete (the tables are still built in this
+ // case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of
+ // lengths), or Z_MEM_ERROR if not enough memory.
+
+ int a; // counter for codes of length k
+ int f; // i repeats in table every f entries
+ int g; // maximum code length
+ int h; // table level
+ int i; // counter, current code
+ int j; // counter
+ int k; // number of bits in current code
+ int l; // bits per table (returned in m)
+ int mask; // (1 << w) - 1, to avoid cc -O bug on HP
+ int p; // pointer into c[], b[], or v[]
+ int q; // points to current table
+ int w; // bits before this table == (l * h)
+ int xp; // pointer into x
+ int y; // number of dummy codes added
+ int z; // number of entries in current table
+
+ // Generate counts for each bit length
+
+ p = 0; i = n;
+ do
+ {
+ c[b[bindex + p]]++; p++; i--; // assume all entries <= BMAX
+ } while (i != 0);
+
+ if (c[0] == n)
+ { // null input--all zero length codes
+ t[0] = -1;
+ m[0] = 0;
+ return ZLibStatus.Z_OK;
+ }
+
+ // Find minimum and maximum length, bound *m by those
+ l = m[0];
+ for (j = 1; j <= BMAX; j++)
+ if (c[j] != 0) break;
+ k = j; // minimum code length
+ if (l < j)
+ {
+ l = j;
+ }
+ for (i = BMAX; i != 0; i--)
+ {
+ if (c[i] != 0) break;
+ }
+ g = i; // maximum code length
+ if (l > i)
+ {
+ l = i;
+ }
+ m[0] = l;
+
+ // Adjust last length count to fill out codes, if needed
+ for (y = 1 << j; j < i; j++, y <<= 1)
+ {
+ if ((y -= c[j]) < 0)
+ {
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ }
+ if ((y -= c[i]) < 0)
+ {
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ c[i] += y;
+
+ // Generate starting offsets into the value table for each length
+ x[1] = j = 0;
+ p = 1; xp = 2;
+ while (--i != 0)
+ { // note that i == g from above
+ x[xp] = (j += c[p]);
+ xp++;
+ p++;
+ }
+
+ // Make a table of values in order of bit lengths
+ i = 0; p = 0;
+ do
+ {
+ if ((j = b[bindex + p]) != 0)
+ {
+ v[x[j]++] = i;
+ }
+ p++;
+ }
+ while (++i < n);
+ n = x[g]; // set n to length of v
+
+ // Generate the Huffman codes and for each, make the table entries
+ x[0] = i = 0; // first Huffman code is zero
+ p = 0; // grab values in bit order
+ h = -1; // no tables yet--level -1
+ w = -l; // bits decoded == (l * h)
+ u[0] = 0; // just to keep compilers happy
+ q = 0; // ditto
+ z = 0; // ditto
+
+ // go through the bit lengths (k already is bits in shortest code)
+ for (; k <= g; k++)
+ {
+ a = c[k];
+ while (a-- != 0)
+ {
+ // here i is the Huffman code of length k bits for value *p
+ // make tables up to required level
+ while (k > w + l)
+ {
+ h++;
+ w += l; // previous table always l bits
+ // compute minimum size table less than or equal to l bits
+ z = g - w;
+ z = (z > l) ? l : z; // table size upper limit
+ if ((f = 1 << (j = k - w)) > a + 1)
+ { // try a k-w bit table
+ // too few codes for k-w bit table
+ f -= a + 1; // deduct codes from patterns left
+ xp = k;
+ if (j < z)
+ {
+ while (++j < z)
+ { // try smaller tables up to z bits
+ if ((f <<= 1) <= c[++xp])
+ break; // enough codes to use up j bits
+ f -= c[xp]; // else deduct codes from patterns
+ }
+ }
+ }
+ z = 1 << j; // table entries for j-bit table
+
+ // allocate new table
+ if (hn[0] + z > MANY)
+ { // (note: doesn't matter for fixed)
+ return ZLibStatus.Z_DATA_ERROR; // overflow of MANY
+ }
+ u[h] = q = /*hp+*/ hn[0]; // DEBUG
+ hn[0] += z;
+
+ // connect to last table, if there is one
+ if (h != 0)
+ {
+ x[h] = i; // save pattern for backing up
+ r[0] = (byte)j; // bits in this table
+ r[1] = (byte)l; // bits to dump before this table
+ j = i >> (w - l);
+ r[2] = (int)(q - u[h - 1] - j); // offset to this table
+ System.Array.Copy(r, 0, hp, (u[h - 1] + j) * 3, 3); // connect to last table
+ }
+ else
+ {
+ t[0] = q; // first table is returned result
+ }
+ }
+
+ // set up table entry in r
+ r[1] = (byte)(k - w);
+ if (p >= n)
+ {
+ r[0] = 128 + 64; // out of values--invalid code
+ }
+ else if (v[p] < s)
+ {
+ r[0] = (byte)(v[p] < 256 ? 0 : 32 + 64); // 256 is end-of-block
+ r[2] = v[p++]; // simple code is just the value
+ }
+ else
+ {
+ r[0] = (byte)(e[v[p] - s] + 16 + 64); // non-simple--look up in lists
+ r[2] = d[v[p++] - s];
+ }
+
+ // fill code-like entries with r
+ f = 1 << (k - w);
+ for (j = i >> w; j < z; j += f)
+ {
+ System.Array.Copy(r, 0, hp, (q + j) * 3, 3);
+ }
+
+ // backwards increment the k-bit code i
+ for (j = 1 << (k - 1); (i & j) != 0; j >>= 1)
+ {
+ i ^= j;
+ }
+ i ^= j;
+
+ // backup over finished tables
+ mask = (1 << w) - 1; // needed on HP, cc -O bug
+ while ((i & mask) != x[h])
+ {
+ h--; // don't need to update q
+ w -= l;
+ mask = (1 << w) - 1;
+ }
+ }
+ }
+ // Return Z_BUF_ERROR if we were given an incomplete table
+ return y != 0 && g != 1 ? ZLibStatus.Z_BUF_ERROR : ZLibStatus.Z_OK;
+ }
+
+ internal ZLibStatus InflateTreesBits(int[] c, // 19 code lengths
+ int[] bb, // bits tree desired/actual depth
+ int[] tb, // bits tree result
+ int[] hp, // space for trees
+ ICompressor z // for messages
+ )
+ {
+ ZLibStatus result;
+ InitWorkArea(19);
+ hn[0] = 0;
+ result = HuftBuild(c, 0, 19, 19, null, null, tb, bb, hp, hn, v);
+
+ if (result == ZLibStatus.Z_DATA_ERROR)
+ {
+ z.msg = "oversubscribed dynamic bit lengths tree";
+ }
+ else if (result == ZLibStatus.Z_BUF_ERROR || bb[0] == 0)
+ {
+ z.msg = "incomplete dynamic bit lengths tree";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ return result;
+ }
+
+ internal ZLibStatus InflateTreesDynamic(int nl, // number of literal/length codes
+ int nd, // number of distance codes
+ int[] c, // that many (total) code lengths
+ int[] bl, // literal desired/actual bit depth
+ int[] bd, // distance desired/actual bit depth
+ int[] tl, // literal/length tree result
+ int[] td, // distance tree result
+ int[] hp, // space for trees
+ ICompressor z // for messages
+ )
+ {
+ ZLibStatus result;
+
+ // build literal/length tree
+ InitWorkArea(288);
+ hn[0] = 0;
+ result = HuftBuild(c, 0, nl, 257, cplens, cplext, tl, bl, hp, hn, v);
+ if (result != ZLibStatus.Z_OK || bl[0] == 0)
+ {
+ if (result == ZLibStatus.Z_DATA_ERROR)
+ {
+ z.msg = "oversubscribed literal/length tree";
+ }
+ else if (result != ZLibStatus.Z_MEM_ERROR)
+ {
+ z.msg = "incomplete literal/length tree";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ return result;
+ }
+
+ // build distance tree
+ InitWorkArea(288);
+ result = HuftBuild(c, nl, nd, 0, cpdist, cpdext, td, bd, hp, hn, v);
+
+ if (result != ZLibStatus.Z_OK || (bd[0] == 0 && nl > 257))
+ {
+ if (result == ZLibStatus.Z_DATA_ERROR)
+ {
+ z.msg = "oversubscribed distance tree";
+ }
+ else if (result == ZLibStatus.Z_BUF_ERROR)
+ {
+ z.msg = "incomplete distance tree";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ else if (result != ZLibStatus.Z_MEM_ERROR)
+ {
+ z.msg = "empty distance tree with lengths";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ return result;
+ }
+
+ return ZLibStatus.Z_OK;
+ }
+
+ internal static ZLibStatus InflateTreesFixed(int[] bl, //literal desired/actual bit depth
+ int[] bd, //distance desired/actual bit depth
+ int[][] tl,//literal/length tree result
+ int[][] td,//distance tree result
+ ICompressor z //for memory allocation
+ )
+ {
+ bl[0] = fixed_bl;
+ bd[0] = fixed_bd;
+ tl[0] = fixed_tl;
+ td[0] = fixed_td;
+ return ZLibStatus.Z_OK;
+ }
+
+ private void InitWorkArea(int vsize)
+ {
+ if (hn == null)
+ {
+ hn = new int[1];
+ v = new int[vsize];
+ c = new int[BMAX + 1];
+ r = new int[3];
+ u = new int[BMAX];
+ x = new int[BMAX + 1];
+ }
+ if (v.Length < vsize) { v = new int[vsize]; }
+ for (int i = 0; i < vsize; i++) { v[i] = 0; }
+ for (int i = 0; i < BMAX + 1; i++) { c[i] = 0; }
+ for (int i = 0; i < 3; i++) { r[i] = 0; }
+ // for(int i=0; i
+ /// Gets the static tree or null
+ ///
+ ///
+ /// The static_tree.
+ ///
+ public short[] TreeData { get; private set; }
+
+ ///
+ /// Gets the extra bits for each code or null.
+ ///
+ ///
+ /// The extra bits.
+ ///
+ public int[] ExtraBits { get; private set; }
+
+ ///
+ /// Gets the base index for extra_bits.
+ ///
+ ///
+ /// The extra base.
+ ///
+ public int ExtraBase { get; private set; }
+
+ ///
+ /// Gets the max number of elements in the tree.
+ ///
+ ///
+ /// The elements.
+ ///
+ public int Elements { get; private set; }
+
+ ///
+ /// Gets the max bit length for the codes.
+ ///
+ ///
+ /// The length of the max.
+ ///
+ public int MaxLength { get; private set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The tree data.
+ /// The extra bits.
+ /// The extra base.
+ /// The elements.
+ /// Length of the max.
+ public StaticTree(short[] treeData, int[] extraBits, int extraBase, int elements, int maxLength)
+ {
+ this.TreeData = treeData;
+ this.ExtraBits = extraBits;
+ this.ExtraBase = extraBase;
+ this.Elements = elements;
+ this.MaxLength = maxLength;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v12/Tree.cs b/Renci.SshNet/Compression/v12/Tree.cs
new file mode 100644
index 0000000..d2142c9
--- /dev/null
+++ b/Renci.SshNet/Compression/v12/Tree.cs
@@ -0,0 +1,334 @@
+using System;
+/*
+ * $Id: Tree.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+ internal sealed class Tree
+ {
+ private const int MAX_BITS = 15;
+
+ private const int LITERALS = 256;
+
+ private const int LENGTH_CODES = 29;
+
+ private const int L_CODES = (LITERALS + 1 + LENGTH_CODES);
+
+ private const int HEAP_SIZE = (2 * L_CODES + 1);
+
+ private static byte[] _dist_code = {
+ 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8,
+ 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17,
+ 18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
+ 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
+ };
+
+
+ ///
+ /// The corresponding static tree
+ ///
+ private StaticTree _staticTree;
+
+ ///
+ /// The dynamic tree
+ ///
+ private short[] _dynamicTree;
+
+ ///
+ /// Gets the largest code with non zero frequency.
+ ///
+ ///
+ /// The max_code.
+ ///
+ public int LargestCode { get; private set; }
+
+ public void Init(short[] dynamicTree, StaticTree staticTree)
+ {
+ this._staticTree = staticTree;
+ this._dynamicTree = dynamicTree;
+ }
+
+ ///
+ /// Mapping from a distance to a distance code. dist is the distance - 1 and must not have side effects. _dist_code[256] and _dist_code[257] are never used.
+ ///
+ /// The dist.
+ ///
+ public static int DistanceCode(int dist)
+ {
+ // TODO: Under multiple port forward after more then 50K requests gets index out of range
+ return ((dist) < 256 ? _dist_code[dist] : _dist_code[256 + ((dist) >> 7)]);
+ }
+
+ ///
+ /// Construct one Huffman tree and assigns the code bit strings and lengths. Update the total bit length for the current block.
+ ///
+ /// The s.
+ public void BuildTree(Deflate s)
+ {
+ short[] tree = _dynamicTree;
+ short[] stree = _staticTree.TreeData;
+ int elems = _staticTree.Elements;
+ int n, m; // iterate over heap elements
+ int max_code = -1; // largest code with non zero frequency
+ int node; // new node being created
+
+ // Construct the initial heap, with least frequent element in
+ // heap[1]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
+ // heap[0] is not used.
+ s.heap_len = 0;
+ s.heap_max = HEAP_SIZE;
+
+ for (n = 0; n < elems; n++)
+ {
+ if (tree[n * 2] != 0)
+ {
+ s.heap[++s.heap_len] = max_code = n;
+ s.depth[n] = 0;
+ }
+ else
+ {
+ tree[n * 2 + 1] = 0;
+ }
+ }
+
+ // The pkzip format requires that at least one distance code exists,
+ // and that at least one bit should be sent even if there is only one
+ // possible code. So to avoid special checks later on we force at least
+ // two codes of non zero frequency.
+ while (s.heap_len < 2)
+ {
+ node = s.heap[++s.heap_len] = (max_code < 2 ? ++max_code : 0);
+ tree[node * 2] = 1;
+ s.depth[node] = 0;
+ s.opt_len--; if (stree != null) s.static_len -= stree[node * 2 + 1];
+ // node is 0 or 1 so it does not have extra bits
+ }
+ this.LargestCode = max_code;
+
+ // The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
+ // establish sub-heaps of increasing lengths:
+
+ for (n = s.heap_len / 2; n >= 1; n--)
+ s.pqdownheap(tree, n);
+
+ // Construct the Huffman tree by repeatedly combining the least two
+ // frequent nodes.
+
+ node = elems; // next internal node of the tree
+ do
+ {
+ // n = node of least frequency
+ n = s.heap[1];
+ s.heap[1] = s.heap[s.heap_len--];
+ s.pqdownheap(tree, 1);
+ m = s.heap[1]; // m = node of next least frequency
+
+ s.heap[--s.heap_max] = n; // keep the nodes sorted by frequency
+ s.heap[--s.heap_max] = m;
+
+ // Create a new node father of n and m
+ tree[node * 2] = (short)(tree[n * 2] + tree[m * 2]);
+ s.depth[node] = (byte)(System.Math.Max(s.depth[n], s.depth[m]) + 1);
+ tree[n * 2 + 1] = tree[m * 2 + 1] = (short)node;
+
+ // and insert the new node in the heap
+ s.heap[1] = node++;
+ s.pqdownheap(tree, 1);
+ }
+ while (s.heap_len >= 2);
+
+ s.heap[--s.heap_max] = s.heap[1];
+
+ // At this point, the fields freq and dad are set. We can now
+ // generate the bit lengths.
+
+ ComputeBitLength(s);
+
+ // The field len is now set, we can generate the bit codes
+ GenerateCodes(tree, max_code, s.bl_count);
+ }
+
+ ///
+ /// Compute the optimal bit lengths for a tree and update the total bit length for the current block.
+ ///
+ /// The s.
+ private void ComputeBitLength(Deflate s)
+ {
+ short[] tree = _dynamicTree;
+ short[] stree = _staticTree.TreeData;
+ int[] extra = _staticTree.ExtraBits;
+ int based = _staticTree.ExtraBase;
+ int max_length = _staticTree.MaxLength;
+ int h; // heap index
+ int n, m; // iterate over the tree elements
+ int bits; // bit length
+ int xbits; // extra bits
+ short f; // frequency
+ int overflow = 0; // number of elements with bit length too large
+
+ for (bits = 0; bits <= MAX_BITS; bits++) s.bl_count[bits] = 0;
+
+ // In a first pass, compute the optimal bit lengths (which may
+ // overflow in the case of the bit length tree).
+ tree[s.heap[s.heap_max] * 2 + 1] = 0; // root of the heap
+
+ for (h = s.heap_max + 1; h < HEAP_SIZE; h++)
+ {
+ n = s.heap[h];
+ bits = tree[tree[n * 2 + 1] * 2 + 1] + 1;
+ if (bits > max_length) { bits = max_length; overflow++; }
+ tree[n * 2 + 1] = (short)bits;
+ // We overwrite tree[n*2+1] which is no longer needed
+
+ if (n > LargestCode) continue; // not a leaf node
+
+ s.bl_count[bits]++;
+ xbits = 0;
+ if (n >= based) xbits = extra[n - based];
+ f = tree[n * 2];
+ s.opt_len += f * (bits + xbits);
+ if (stree != null) s.static_len += f * (stree[n * 2 + 1] + xbits);
+ }
+ if (overflow == 0) return;
+
+ // This happens for example on obj2 and pic of the Calgary corpus
+ // Find the first bit length which could increase:
+ do
+ {
+ bits = max_length - 1;
+ while (s.bl_count[bits] == 0) bits--;
+ s.bl_count[bits]--; // move one leaf down the tree
+ s.bl_count[bits + 1] += 2; // move one overflow item as its brother
+ s.bl_count[max_length]--;
+ // The brother of the overflow item also moves one step up,
+ // but this does not affect bl_count[max_length]
+ overflow -= 2;
+ }
+ while (overflow > 0);
+
+ for (bits = max_length; bits != 0; bits--)
+ {
+ n = s.bl_count[bits];
+ while (n != 0)
+ {
+ m = s.heap[--h];
+ if (m > LargestCode) continue;
+ if (tree[m * 2 + 1] != bits)
+ {
+ s.opt_len += (int)(((long)bits - (long)tree[m * 2 + 1]) * (long)tree[m * 2]);
+ tree[m * 2 + 1] = (short)bits;
+ }
+ n--;
+ }
+ }
+ }
+
+ ///
+ /// Generate the codes for a given tree and bit counts (which need not be optimal).
+ ///
+ /// The tree to decorate.
+ /// The largest code with non zero frequency.
+ /// The number of codes at each bit length.
+ private static void GenerateCodes(short[] tree, int max_code, short[] bl_count)
+ {
+ short[] next_code = new short[MAX_BITS + 1]; // next code value for each bit length
+ short code = 0; // running code value
+ int bits; // bit index
+ int n; // code index
+
+ // The distribution counts are first used to generate the code values
+ // without bit reversal.
+ for (bits = 1; bits <= MAX_BITS; bits++)
+ {
+ next_code[bits] = code = (short)((code + bl_count[bits - 1]) << 1);
+ }
+
+ // Check that the bit counts in bl_count are consistent. The last code
+ // must be all ones.
+ //Assert (code + bl_count[MAX_BITS]-1 == (1<
+ /// Reverse the first len bits of a code, using straightforward code (a faster method would use a table)
+ ///
+ /// The value to invert.
+ /// The bit length.
+ ///
+ private static int BiReverse(int code, int len)
+ {
+ int res = 0;
+ do
+ {
+ res |= code & 1;
+ code >>= 1;
+ res <<= 1;
+ }
+ while (--len > 0);
+ return res >> 1;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v12/ZInputStream.cs b/Renci.SshNet/Compression/v12/ZInputStream.cs
new file mode 100644
index 0000000..0ef972c
--- /dev/null
+++ b/Renci.SshNet/Compression/v12/ZInputStream.cs
@@ -0,0 +1,202 @@
+/*
+Copyright (c) 2001 Lapo Luchini.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS
+OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+/* This file is a port of jzlib v1.0.7, com.jcraft.jzlib.ZInputStream.java
+ */
+
+using Renci.SshNet.Compression;
+using System;
+using System.Diagnostics;
+using System.IO;
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+ public class ZInputStream : Stream
+ {
+ private const int BufferSize = 512;
+ //private ZStream z = new ZStream();
+ private ICompressor _compressor;
+
+ // TODO Allow custom buf
+ private byte[] _buffer = new byte[BufferSize];
+ private CompressionMode _compressionMode;
+ private Stream _input;
+ private bool _isClosed;
+ private bool _noMoreInput = false;
+
+ public FlushType FlushMode { get; private set; }
+
+ public ZInputStream()
+ {
+ this.FlushMode = FlushType.Z_PARTIAL_FLUSH;
+ }
+
+ public ZInputStream(Stream input)
+ : this(input, false)
+ {
+ }
+
+ public ZInputStream(Stream input, bool nowrap)
+ : this()
+ {
+ Debug.Assert(input.CanRead);
+
+ this._input = input;
+ this._compressor = new Inflate(nowrap);
+ //this._compressor.inflateInit(nowrap);
+ this._compressionMode = CompressionMode.Decompress;
+ this._compressor.next_in = _buffer;
+ this._compressor.next_in_index = 0;
+ this._compressor.avail_in = 0;
+ }
+
+ public ZInputStream(Stream input, CompressionLevel level)
+ : this()
+ {
+ Debug.Assert(input.CanRead);
+
+ this._input = input;
+ this._compressor = new Deflate(level);
+ //this._compressor.deflateInit(level);
+ this._compressionMode = CompressionMode.Compress;
+ this._compressor.next_in = _buffer;
+ this._compressor.next_in_index = 0;
+ this._compressor.avail_in = 0;
+ }
+
+ #region Stream implementation
+
+ public sealed override bool CanRead
+ {
+ get { return !_isClosed; }
+ }
+
+ public sealed override bool CanSeek
+ {
+ get { return false; }
+ }
+
+ public sealed override bool CanWrite
+ {
+ get { return false; }
+ }
+
+ public override void Flush()
+ {
+ }
+
+ public override long Length
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ public override long Position
+ {
+ get { throw new NotSupportedException(); }
+ set { throw new NotSupportedException(); }
+ }
+
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ if (count == 0)
+ return 0;
+
+ //this._compressor.next_out = buffer;
+ //this._compressor.next_out_index = offset;
+ //this._compressor.avail_out = count;
+
+ ZLibStatus err = ZLibStatus.Z_OK;
+ do
+ {
+ if (this._compressor.avail_in == 0 && !_noMoreInput)
+ {
+ // if buffer is empty and more input is available, refill it
+ this._compressor.next_in_index = 0;
+ this._compressor.avail_in = _input.Read(_buffer, 0, _buffer.Length); //(bufsize 0 || this._compressor.avail_out == 0);
+ }
+
+ #endregion
+
+ public override void Close()
+ {
+ if (this._isClosed)
+ return;
+
+ try
+ {
+ try
+ {
+ Finish();
+ }
+ catch (IOException)
+ {
+ // Ignore
+ }
+ }
+ finally
+ {
+ this._isClosed = true;
+ End();
+ _output.Close();
+ _output = null;
+ }
+ }
+
+ private void End()
+ {
+ if (this._compressor == null)
+ return;
+ switch (this._compressionMode)
+ {
+ case CompressionMode.Compress:
+ this._compressor.deflateEnd();
+ break;
+ case CompressionMode.Decompress:
+ this._compressor.inflateEnd();
+ break;
+ default:
+ break;
+ }
+
+ //this._compressor.free();
+ this._compressor = null;
+ }
+
+ private void Finish()
+ {
+ do
+ {
+ var err = ZLibStatus.Z_OK;
+ switch (this._compressionMode)
+ {
+ case CompressionMode.Compress:
+ err = this._compressor.deflate(_buffer, 0, _buffer.Length, FlushType.Z_FINISH);
+ break;
+ case CompressionMode.Decompress:
+ err = this._compressor.inflate(_buffer, 0, _buffer.Length, FlushType.Z_FINISH);
+ break;
+ default:
+ break;
+ }
+
+ if (err != ZLibStatus.Z_STREAM_END && err != ZLibStatus.Z_OK)
+ // TODO
+ // throw new ZStreamException((compress?"de":"in")+"flating: "+z.msg);
+ //throw new IOException((_compressionMode ? "de" : "in") + "flating: " + z.msg);
+ throw new IOException(string.Format("{0}ion error: {1}", _compressionMode, err));
+
+ int count = _buffer.Length - this._compressor.avail_out;
+ if (count > 0)
+ {
+ _output.Write(_buffer, 0, count);
+ }
+ }
+ while (this._compressor.avail_in > 0 || this._compressor.avail_out == 0);
+
+ Flush();
+ }
+ }
+}
diff --git a/Renci.SshNet/Compression/v12/ZStream.cs b/Renci.SshNet/Compression/v12/ZStream.cs
new file mode 100644
index 0000000..3e9d952
--- /dev/null
+++ b/Renci.SshNet/Compression/v12/ZStream.cs
@@ -0,0 +1,102 @@
+using System;
+using System.IO;
+/*
+ * $Id: ZStream.cs,v 1.1 2006-07-31 13:59:26 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public interface ICompressor
+ {
+ ZLibStatus deflate(byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType);
+ ZLibStatus deflate(byte[] bufer, int offset, int count, byte[] p1, int p2, int p3, FlushType flushType);
+
+ ZLibStatus deflateEnd();
+
+ ZLibStatus inflate(byte[] bufer, int offset, int count, byte[] p1, int p2, int p3, FlushType flushType);
+ ZLibStatus inflate(byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType);
+
+ ZLibStatus inflateEnd();
+
+ //ZLibStatus inflate(FlushType flushType);
+
+ int avail_out { get; set; }
+
+ int avail_in { get; set; }
+
+ int next_out_index { get; set; }
+
+ byte[] next_out { get; set; }
+
+ byte[] next_in { get; set; }
+
+ int next_in_index { get; set; }
+
+ String msg { get; set; }
+
+ long adler { get; set; }
+
+ long total_in { get; set; }
+
+ long total_out { get; set; }
+ }
+
+
+ public abstract class ZStream
+ {
+
+ protected const int MAX_WBITS = 15; // 32K LZ77 window
+ protected const int DEF_WBITS = MAX_WBITS;
+
+ private const int MAX_MEM_LEVEL = 9;
+
+ public byte[] next_in { get; set; } // next input byte
+ public int next_in_index { get; set; }
+ public int avail_in { get; set; } // number of bytes available at next_in
+ public long total_in { get; set; } // total nb of input bytes read so far
+
+ public byte[] next_out { get; set; } // next output byte should be put there
+ public int next_out_index { get; set; }
+ public int avail_out { get; set; } // remaining free space at next_out
+ public long total_out { get; set; } // total nb of bytes output so far
+
+ public String msg { get; set; }
+
+ internal BlockType data_type; // best guess about the data type: ascii or binary
+
+ public long adler { get; set; }
+
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v12/Zlib.cs b/Renci.SshNet/Compression/v12/Zlib.cs
new file mode 100644
index 0000000..5890675
--- /dev/null
+++ b/Renci.SshNet/Compression/v12/Zlib.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Represents "zlib" compression implementation
+ ///
+ internal class Zlib : Compressor
+ {
+ ///
+ /// Gets algorithm name.
+ ///
+ public override string Name
+ {
+ get { return "zlib"; }
+ }
+
+ ///
+ /// Initializes the algorithm
+ ///
+ /// The session.
+ public override void Init(Session session)
+ {
+ base.Init(session);
+ this.IsActive = true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v12/ZlibOpenSsh.cs b/Renci.SshNet/Compression/v12/ZlibOpenSsh.cs
new file mode 100644
index 0000000..f82a4c0
--- /dev/null
+++ b/Renci.SshNet/Compression/v12/ZlibOpenSsh.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Represents "zlib@openssh.org" compression implementation
+ ///
+ public class ZlibOpenSsh : Compressor
+ {
+ ///
+ /// Gets algorithm name.
+ ///
+ public override string Name
+ {
+ get { return "zlib@openssh.org"; }
+ }
+
+ ///
+ /// Initializes the algorithm
+ ///
+ /// The session.
+ public override void Init(Session session)
+ {
+ base.Init(session);
+
+ session.UserAuthenticationSuccessReceived += Session_UserAuthenticationSuccessReceived;
+ }
+
+ private void Session_UserAuthenticationSuccessReceived(object sender, MessageEventArgs e)
+ {
+ this.IsActive = true;
+ this.Session.UserAuthenticationSuccessReceived -= Session_UserAuthenticationSuccessReceived;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v12/ZlibStream.cs b/Renci.SshNet/Compression/v12/ZlibStream.cs
new file mode 100644
index 0000000..fb5f9d2
--- /dev/null
+++ b/Renci.SshNet/Compression/v12/ZlibStream.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.IO;
+using Org.BouncyCastle.Utilities.Zlib;
+
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Implements Zlib compression algorithm.
+ ///
+ public class ZlibStream
+ {
+ private readonly Stream _baseStream;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The stream.
+ /// The mode.
+ public ZlibStream(Stream stream, CompressionMode mode)
+ {
+ switch (mode)
+ {
+ case CompressionMode.Compress:
+ //this._baseStream = new ZOutputStream(stream, CompressionLevel.Z_DEFAULT_COMPRESSION);
+ this._baseStream = new ZOutputStream(stream, CompressionLevel.Z_DEFAULT_COMPRESSION);
+ break;
+ case CompressionMode.Decompress:
+ this._baseStream = new ZOutputStream(stream);
+ break;
+ default:
+ break;
+ }
+
+ //this._baseStream.FlushMode = Ionic.Zlib.FlushType.Partial;
+ }
+
+ ///
+ /// Writes the specified buffer.
+ ///
+ /// The buffer.
+ /// The offset.
+ /// The count.
+ public void Write(byte[] buffer, int offset, int count)
+ {
+ this._baseStream.Write(buffer, offset, count);
+ }
+ }
+}
diff --git a/Renci.SshNet/Compression/v13/Adler32.cs b/Renci.SshNet/Compression/v13/Adler32.cs
new file mode 100644
index 0000000..c132fa9
--- /dev/null
+++ b/Renci.SshNet/Compression/v13/Adler32.cs
@@ -0,0 +1,95 @@
+using System;
+/*
+ * $Id: Adler32.cs,v 1.1 2006-07-31 13:59:25 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ internal static class Adler32
+ {
+
+ // largest prime smaller than 65536
+ private const int BASE = 65521;
+ // NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
+ private const int NMAX = 5552;
+
+ internal static long adler32(long adler, byte[] buf, int index, int len)
+ {
+ if (buf == null) { return 1L; }
+
+ long s1 = adler & 0xffff;
+ long s2 = (adler >> 16) & 0xffff;
+ int k;
+
+ while (len > 0)
+ {
+ k = len < NMAX ? len : NMAX;
+ len -= k;
+ while (k >= 16)
+ {
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ k -= 16;
+ }
+ if (k != 0)
+ {
+ do
+ {
+ s1 += buf[index++] & 0xff; s2 += s1;
+ }
+ while (--k != 0);
+ }
+ s1 %= BASE;
+ s2 %= BASE;
+ }
+ return (s2 << 16) | s1;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v13/CompressionMode.cs b/Renci.SshNet/Compression/v13/CompressionMode.cs
new file mode 100644
index 0000000..1577e0b
--- /dev/null
+++ b/Renci.SshNet/Compression/v13/CompressionMode.cs
@@ -0,0 +1,18 @@
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Specifies compression modes
+ ///
+ public enum CompressionMode
+ {
+ ///
+ /// Specifies that content should be compressed.
+ ///
+ Compress = 0,
+
+ ///
+ /// Specifies that content should be decompressed.
+ ///
+ Decompress = 1,
+ }
+}
diff --git a/Renci.SshNet/Compression/v13/Compressor.cs b/Renci.SshNet/Compression/v13/Compressor.cs
new file mode 100644
index 0000000..1479bb6
--- /dev/null
+++ b/Renci.SshNet/Compression/v13/Compressor.cs
@@ -0,0 +1,151 @@
+using System.Collections.Generic;
+using Renci.SshNet.Security;
+using System.IO;
+using System;
+
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Represents base class for compression algorithm implementation
+ ///
+ public abstract class Compressor : Algorithm, IDisposable
+ {
+ private readonly ZlibStream _compressor;
+ private readonly ZlibStream _decompressor;
+
+ private MemoryStream _compressorStream;
+ private MemoryStream _decompressorStream;
+
+ ///
+ /// Gets or sets a value indicating whether compression is active.
+ ///
+ ///
+ /// true if compression is active; otherwise, false.
+ ///
+ protected bool IsActive { get; set; }
+
+ ///
+ /// Gets the session.
+ ///
+ protected Session Session { get; private set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ 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);
+ }
+
+ ///
+ /// Initializes the algorithm
+ ///
+ /// The session.
+ public virtual void Init(Session session)
+ {
+ this.Session = session;
+ }
+
+ ///
+ /// Compresses the specified data.
+ ///
+ /// Data to compress.
+ /// Compressed 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();
+ }
+
+ ///
+ /// Decompresses the specified data.
+ ///
+ /// Compressed data.
+ /// Decompressed 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;
+
+ ///
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged ResourceMessages.
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Releases unmanaged and - optionally - managed resources
+ ///
+ /// true to release both managed and unmanaged resources; false to release only unmanaged ResourceMessages.
+ 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;
+ }
+ }
+
+ ///
+ /// Releases unmanaged resources and performs other cleanup operations before the
+ /// is reclaimed by garbage collection.
+ ///
+ ~Compressor()
+ {
+ // Do not re-create Dispose clean-up code here.
+ // Calling Dispose(false) is optimal in terms of
+ // readability and maintainability.
+ Dispose(false);
+ }
+
+ #endregion
+ }
+}
diff --git a/Renci.SshNet/Compression/v13/Deflate.cs b/Renci.SshNet/Compression/v13/Deflate.cs
new file mode 100644
index 0000000..cc42021
--- /dev/null
+++ b/Renci.SshNet/Compression/v13/Deflate.cs
@@ -0,0 +1,2225 @@
+using System;
+using System.Collections.Generic;
+/*
+ * $Id: Deflate.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public enum BlockType : byte
+ {
+ Z_BINARY = 0,
+ Z_ASCII = 1,
+ Z_UNKNOWN = 2
+ }
+
+ public enum DefalteFlavor : int
+ {
+ STORED = 0,
+ FAST = 1,
+ SLOW = 2
+ }
+
+ public sealed class Deflate : ZStream, ICompressor
+ {
+ private const int MAX_MEM_LEVEL = 9;
+
+ private const int Z_DEFAULT_COMPRESSION = -1;
+
+ private const int MAX_WBITS = 15; // 32K LZ77 window
+
+ private const int DEF_MEM_LEVEL = 8;
+
+ ///
+ /// The Bit length codes must not exceed MAX_BL_BITS bits
+ ///
+ private const int MAX_BL_BITS = 7;
+
+ // block not completed, need more input or more output
+ private const int NeedMore = 0;
+
+ // block flush performed
+ private const int BlockDone = 1;
+
+ // finish started, need only more output at next deflate
+ private const int FinishStarted = 2;
+
+ // finish done, accept no more input or output
+ private const int FinishDone = 3;
+
+ // preset dictionary flag in zlib header
+ private const int PRESET_DICT = 0x20;
+
+ private const int Z_VERSION_ERROR = -6;
+
+ private const int INIT_STATE = 42;
+ private const int BUSY_STATE = 113;
+ private const int FINISH_STATE = 666;
+
+ // The deflate compression method
+ private const int Z_DEFLATED = 8;
+
+ private const int STORED_BLOCK = 0;
+ private const int STATIC_TREES = 1;
+ private const int DYN_TREES = 2;
+
+ private const int Buf_size = 8 * 2;
+
+ // repeat previous bit length 3-6 times (2 bits of repeat count)
+ private const int REP_3_6 = 16;
+
+ // repeat a zero length 3-10 times (3 bits of repeat count)
+ private const int REPZ_3_10 = 17;
+
+ // repeat a zero length 11-138 times (7 bits of repeat count)
+ private const int REPZ_11_138 = 18;
+
+ private const int MIN_MATCH = 3;
+ private const int MAX_MATCH = 258;
+ private const int MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1);
+
+ private const int MAX_BITS = 15;
+ private const int D_CODES = 30;
+ private const int BL_CODES = 19;
+ private const int LENGTH_CODES = 29;
+ private const int LITERALS = 256;
+ private const int L_CODES = (LITERALS + 1 + LENGTH_CODES);
+ private const int HEAP_SIZE = (2 * L_CODES + 1);
+
+ private const int END_BLOCK = 256;
+
+ private static readonly IDictionary config_table = new Dictionary() {
+ {(CompressionLevel)0, new Config(0, 0, 0, 0, DefalteFlavor.STORED)},
+ {(CompressionLevel)1, new Config(4, 4, 8, 4, DefalteFlavor.FAST)},
+ {(CompressionLevel)2, new Config(4, 5, 16, 8, DefalteFlavor.FAST)},
+ {(CompressionLevel)3, new Config(4, 6, 32, 32, DefalteFlavor.FAST)},
+
+ {(CompressionLevel)4, new Config(4, 4, 16, 16, DefalteFlavor.SLOW)},
+ {(CompressionLevel)5, new Config(8, 16, 32, 32, DefalteFlavor.SLOW)},
+ {(CompressionLevel)6, new Config(8, 16, 128, 128, DefalteFlavor.SLOW)},
+ {(CompressionLevel)7, new Config(8, 32, 128, 256, DefalteFlavor.SLOW)},
+ {(CompressionLevel)8, new Config(32, 128, 258, 1024, DefalteFlavor.SLOW)},
+ {(CompressionLevel)9, new Config(32, 258, 258, 4096, DefalteFlavor.SLOW)},
+ };
+
+ #region Static definitions
+
+ private static readonly byte[] _length_code ={
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12,
+ 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
+ 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
+ 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
+ };
+
+ private static readonly int[] base_length = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
+ 64, 80, 96, 112, 128, 160, 192, 224, 0
+ };
+
+ private static readonly int[] base_dist = {
+ 0, 1, 2, 3, 4, 6, 8, 12, 16, 24,
+ 32, 48, 64, 96, 128, 192, 256, 384, 512, 768,
+ 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576
+ };
+
+ // extra bits for each length code
+ private static readonly int[] extra_lbits ={
+ 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0
+ };
+
+ // extra bits for each distance code
+ private static readonly int[] extra_dbits ={
+ 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13
+ };
+
+ // extra bits for each bit length code
+ private static readonly int[] extra_blbits ={
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7
+ };
+
+ private static readonly byte[] bl_order ={
+ 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
+
+ private static readonly short[] static_ltree = {
+ 12, 8, 140, 8, 76, 8, 204, 8, 44, 8,
+ 172, 8, 108, 8, 236, 8, 28, 8, 156, 8,
+ 92, 8, 220, 8, 60, 8, 188, 8, 124, 8,
+ 252, 8, 2, 8, 130, 8, 66, 8, 194, 8,
+ 34, 8, 162, 8, 98, 8, 226, 8, 18, 8,
+ 146, 8, 82, 8, 210, 8, 50, 8, 178, 8,
+ 114, 8, 242, 8, 10, 8, 138, 8, 74, 8,
+ 202, 8, 42, 8, 170, 8, 106, 8, 234, 8,
+ 26, 8, 154, 8, 90, 8, 218, 8, 58, 8,
+ 186, 8, 122, 8, 250, 8, 6, 8, 134, 8,
+ 70, 8, 198, 8, 38, 8, 166, 8, 102, 8,
+ 230, 8, 22, 8, 150, 8, 86, 8, 214, 8,
+ 54, 8, 182, 8, 118, 8, 246, 8, 14, 8,
+ 142, 8, 78, 8, 206, 8, 46, 8, 174, 8,
+ 110, 8, 238, 8, 30, 8, 158, 8, 94, 8,
+ 222, 8, 62, 8, 190, 8, 126, 8, 254, 8,
+ 1, 8, 129, 8, 65, 8, 193, 8, 33, 8,
+ 161, 8, 97, 8, 225, 8, 17, 8, 145, 8,
+ 81, 8, 209, 8, 49, 8, 177, 8, 113, 8,
+ 241, 8, 9, 8, 137, 8, 73, 8, 201, 8,
+ 41, 8, 169, 8, 105, 8, 233, 8, 25, 8,
+ 153, 8, 89, 8, 217, 8, 57, 8, 185, 8,
+ 121, 8, 249, 8, 5, 8, 133, 8, 69, 8,
+ 197, 8, 37, 8, 165, 8, 101, 8, 229, 8,
+ 21, 8, 149, 8, 85, 8, 213, 8, 53, 8,
+ 181, 8, 117, 8, 245, 8, 13, 8, 141, 8,
+ 77, 8, 205, 8, 45, 8, 173, 8, 109, 8,
+ 237, 8, 29, 8, 157, 8, 93, 8, 221, 8,
+ 61, 8, 189, 8, 125, 8, 253, 8, 19, 9,
+ 275, 9, 147, 9, 403, 9, 83, 9, 339, 9,
+ 211, 9, 467, 9, 51, 9, 307, 9, 179, 9,
+ 435, 9, 115, 9, 371, 9, 243, 9, 499, 9,
+ 11, 9, 267, 9, 139, 9, 395, 9, 75, 9,
+ 331, 9, 203, 9, 459, 9, 43, 9, 299, 9,
+ 171, 9, 427, 9, 107, 9, 363, 9, 235, 9,
+ 491, 9, 27, 9, 283, 9, 155, 9, 411, 9,
+ 91, 9, 347, 9, 219, 9, 475, 9, 59, 9,
+ 315, 9, 187, 9, 443, 9, 123, 9, 379, 9,
+ 251, 9, 507, 9, 7, 9, 263, 9, 135, 9,
+ 391, 9, 71, 9, 327, 9, 199, 9, 455, 9,
+ 39, 9, 295, 9, 167, 9, 423, 9, 103, 9,
+ 359, 9, 231, 9, 487, 9, 23, 9, 279, 9,
+ 151, 9, 407, 9, 87, 9, 343, 9, 215, 9,
+ 471, 9, 55, 9, 311, 9, 183, 9, 439, 9,
+ 119, 9, 375, 9, 247, 9, 503, 9, 15, 9,
+ 271, 9, 143, 9, 399, 9, 79, 9, 335, 9,
+ 207, 9, 463, 9, 47, 9, 303, 9, 175, 9,
+ 431, 9, 111, 9, 367, 9, 239, 9, 495, 9,
+ 31, 9, 287, 9, 159, 9, 415, 9, 95, 9,
+ 351, 9, 223, 9, 479, 9, 63, 9, 319, 9,
+ 191, 9, 447, 9, 127, 9, 383, 9, 255, 9,
+ 511, 9, 0, 7, 64, 7, 32, 7, 96, 7,
+ 16, 7, 80, 7, 48, 7, 112, 7, 8, 7,
+ 72, 7, 40, 7, 104, 7, 24, 7, 88, 7,
+ 56, 7, 120, 7, 4, 7, 68, 7, 36, 7,
+ 100, 7, 20, 7, 84, 7, 52, 7, 116, 7,
+ 3, 8, 131, 8, 67, 8, 195, 8, 35, 8,
+ 163, 8, 99, 8, 227, 8
+ };
+
+ private static readonly short[] static_dtree = {
+ 0, 5, 16, 5, 8, 5, 24, 5, 4, 5,
+ 20, 5, 12, 5, 28, 5, 2, 5, 18, 5,
+ 10, 5, 26, 5, 6, 5, 22, 5, 14, 5,
+ 30, 5, 1, 5, 17, 5, 9, 5, 25, 5,
+ 5, 5, 21, 5, 13, 5, 29, 5, 3, 5,
+ 19, 5, 11, 5, 27, 5, 7, 5, 23, 5
+ };
+ #endregion
+
+ private static readonly String[] z_errmsg = {
+ "need dictionary", // ZLibStatus.Z_NEED_DICT 2
+ "stream end", // ZLibStatus.Z_STREAM_END 1
+ "", // ZLibStatus.Z_OK 0
+ "file error", // ZLibStatus.Z_ERRNO (-1)
+ "stream error", // ZLibStatus.Z_STREAM_ERROR (-2)
+ "data error", // ZLibStatus.Z_DATA_ERROR (-3)
+ "insufficient memory", // Z_MEM_ERROR (-4)
+ "buffer error", // ZLibStatus.Z_BUF_ERROR (-5)
+ "incompatible version",// Z_VERSION_ERROR (-6)
+ ""
+ };
+
+
+
+ ///
+ /// as the name implies
+ ///
+ private int _status;
+
+ private BlockType _dataType;
+
+ ///
+ /// STORED (for zip only) or DEFLATED
+ ///
+ private byte _method;
+
+ ///
+ /// size of pending_buf
+ ///
+ private int _pendingBufferSize;
+
+ ///
+ /// LZ77 window size (32K by default)
+ ///
+ private int _windowSize;
+
+ ///
+ /// log2(w_size) (8..16)
+ ///
+ private int _windowBits;
+
+ ///
+ /// w_size - 1
+ ///
+ private int _windowMask;
+
+ ///
+ /// Sliding window. Input bytes are read into the second half of the window,
+ /// and move to the first half later to keep a dictionary of at least wSize
+ /// bytes. With this organization, matches are limited to a distance of
+ /// wSize-MAX_MATCH bytes, but this ensures that IO is always
+ /// performed with a length multiple of the block size. Also, it limits
+ /// the window size to 64K, which is quite useful on MSDOS.
+ /// To do: use the user input buffer as sliding window.
+ ///
+ private byte[] _window;
+
+ ///
+ /// Actual size of window: 2*wSize, except when the user input buffer
+ /// is directly used as sliding window.
+ ///
+ private int _windowActualSize;
+
+ ///
+ /// Link to older string with same hash index. To limit the size of this
+ /// array to 64K, this link is maintained only for the last 32K strings.
+ /// An index in this array is thus a window index modulo 32K.
+ ///
+ private short[] _previous;
+
+ ///
+ /// Heads of the hash chains or NIL.
+ ///
+ private short[] _head;
+
+ ///
+ /// hash index of string to be inserted
+ ///
+ private int _insertedHashIndex;
+
+ ///
+ /// number of elements in hash table
+ ///
+ private int _hashSize;
+
+ ///
+ /// log2(hash_size)
+ ///
+ private int _hashBits;
+
+ ///
+ /// hash_size-1
+ ///
+ private int _hashMask;
+
+ ///
+ /// Number of bits by which ins_h must be shifted at each input
+ /// step. It must be such that after MIN_MATCH steps, the oldest
+ /// byte no longer takes part in the hash key, that is:
+ /// hash_shift * MIN_MATCH >= hash_bits
+ ///
+ private int _hashShift;
+
+ ///
+ /// Window position at the beginning of the current output block. Gets
+ /// negative when the window is moved backwards.
+ ///
+ private int _blockStart;
+
+ ///
+ /// length of best match
+ ///
+ private int _matchLength;
+
+ ///
+ /// previous match
+ ///
+ private int _previousMatch;
+
+ ///
+ /// set if previous match exists
+ ///
+ private bool _matchAvailable;
+
+ ///
+ /// start of string to insert
+ ///
+ private int _startInsertString;
+
+ ///
+ /// start of matching string
+ ///
+ private int _startMatchString;
+
+ ///
+ /// number of valid bytes ahead in window
+ ///
+ private int _validBytesAhead;
+
+ ///
+ /// Length of the best match at previous step. Matches not greater than this
+ /// are discarded. This is used in the lazy match evaluation.
+ ///
+ private int _previousLength;
+
+ ///
+ /// To speed up deflation, hash chains are never searched beyond this
+ /// length. A higher limit improves compression ratio but degrades the speed.
+ ///
+ private int _maxChainLength;
+
+ ///
+ /// Attempt to find a better match only when the current match is strictly
+ /// smaller than this value. This mechanism is used only for compression
+ /// levels >= 4.
+ ///
+ private int _maxLazyMatch;
+
+ // Insert new strings in the hash table only if the match length is not
+ // greater than this length. This saves time but degrades compression.
+ // max_insert_length is used only for compression levels <= 3.
+
+ ///
+ /// The compression level (1..9)
+ ///
+ private CompressionLevel level;
+
+ ///
+ /// The favor or force Huffman coding
+ ///
+ private CompressionStrategy strategy;
+
+ ///
+ /// Use a faster search when the previous match is longer than this
+ ///
+ private int good_match;
+
+ ///
+ /// Stop searching when current match exceeds this
+ ///
+ private int nice_match;
+
+ ///
+ /// literal and length tree
+ ///
+ private short[] dyn_ltree;
+
+ ///
+ /// The distance tree
+ ///
+ private short[] dyn_dtree;
+
+ ///
+ /// The Huffman tree for bit lengths
+ ///
+ private short[] bl_tree;
+
+ ///
+ /// The desc for literal tree
+ ///
+ private Tree l_desc = new Tree();
+
+ ///
+ /// The desc for distance tree
+ ///
+ private Tree d_desc = new Tree();
+
+ ///
+ /// The desc for bit length tree
+ ///
+ private Tree bl_desc = new Tree();
+
+ ///
+ /// index for literals or lengths
+ ///
+ private int l_buf;
+
+ ///
+ /// Size of match buffer for literals/lengths. There are 4 reasons for
+ /// limiting lit_bufsize to 64K:
+ /// - frequencies can be kept in 16 bit counters
+ /// - if compression is not successful for the first block, all input
+ /// data is still in the window so we can still emit a stored block even
+ /// when input comes from standard input. (This can also be done for
+ /// all blocks if lit_bufsize is not greater than 32K.)
+ /// - if compression is not successful for a file smaller than 64K, we can
+ /// even emit a stored file instead of a stored block (saving 5 bytes).
+ /// This is applicable only for zip (not gzip or zlib).
+ /// - creating new Huffman trees less frequently may not provide fast
+ /// adaptation to changes in the input data statistics. (Take for
+ /// example a binary file with poorly compressible code followed by
+ /// a highly compressible string table.) Smaller buffer sizes give
+ /// fast adaptation but have of course the overhead of transmitting
+ /// trees more frequently.
+ /// - I can't count above 4
+ ///
+ private int lit_bufsize;
+
+ ///
+ /// running index in l_buf
+ ///
+ private int last_lit;
+
+ // Buffer for distances. To simplify the code, d_buf and l_buf have
+ // the same number of elements. To use different lengths, an extra flag
+ // array would be necessary.
+
+ ///
+ /// The index of pendig_buf
+ ///
+ private int d_buf;
+
+ ///
+ /// The number of string matches in current block
+ ///
+ private int matches;
+
+ ///
+ /// The bit length of EOB code for last block
+ ///
+ private int last_eob_len;
+
+ ///
+ /// Output buffer. bits are inserted starting at the bottom (least
+ /// significant bits).
+ ///
+ private uint bi_buf;
+
+ ///
+ /// Number of valid bits in bi_buf. All bits above the last valid bit
+ /// are always zero.
+ ///
+ private int bi_valid;
+
+ ///
+ /// value of flush param for previous deflate call
+ ///
+ private FlushType last_flush;
+
+ ///
+ /// bit length of current block with optimal trees
+ ///
+ internal int opt_len;
+
+ ///
+ /// bit length of current block with static trees
+ ///
+ internal int static_len;
+
+ ///
+ /// The output still pending
+ ///
+ internal byte[] pending_buf;
+
+ ///
+ /// next pending byte to output to the stream
+ ///
+ internal int pending_out;
+
+ ///
+ /// nb of bytes in the pending buffer
+ ///
+ internal int pending;
+
+ ///
+ /// suppress zlib header and adler32
+ ///
+ internal int noheader;
+
+ ///
+ /// number of codes at each bit length for an optimal tree
+ ///
+ internal short[] bl_count = new short[MAX_BITS + 1];
+
+ ///
+ /// heap used to build the Huffman trees
+ ///
+ internal int[] heap = new int[2 * L_CODES + 1];
+
+ ///
+ /// The number of elements in the heap
+ ///
+ internal int heap_len;
+ ///
+ /// The element of largest frequency
+ ///
+ internal int heap_max;
+
+ // The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+ // The same heap array is used to build all trees.
+
+ ///
+ /// Depth of each subtree used as tie breaker for trees of equal frequency
+ ///
+ internal byte[] depth = new byte[2 * L_CODES + 1];
+
+ public Deflate()
+ {
+ dyn_ltree = new short[HEAP_SIZE * 2];
+ dyn_dtree = new short[(2 * D_CODES + 1) * 2]; // distance tree
+ bl_tree = new short[(2 * BL_CODES + 1) * 2]; // Huffman tree for bit lengths
+ }
+
+ public Deflate(CompressionLevel level)
+ : this()
+ {
+ this.deflateInit(level);
+ }
+
+ public Deflate(CompressionLevel level, bool nowrap)
+ : this()
+ {
+ this.deflateInit(level, nowrap);
+ }
+
+ // Restore the heap property by moving down the tree starting at node k,
+ // exchanging a node with the smallest of its two sons if necessary, stopping
+ // when the heap property is re-established (each father smaller than its
+ // two sons).
+ internal void pqdownheap(short[] tree, // the tree to restore
+ int k // node to move down
+ )
+ {
+ int v = heap[k];
+ int j = k << 1; // left son of k
+ while (j <= heap_len)
+ {
+ // Set j to the smallest of the two sons:
+ if (j < heap_len &&
+ smaller(tree, heap[j + 1], heap[j], depth))
+ {
+ j++;
+ }
+ // Exit if v is smaller than both sons
+ if (smaller(tree, v, heap[j], depth)) break;
+
+ // Exchange v with the smallest son
+ heap[k] = heap[j]; k = j;
+ // And continue down the tree, setting j to the left son of k
+ j <<= 1;
+ }
+ heap[k] = v;
+ }
+
+ public ZLibStatus deflateInit(CompressionLevel level)
+ {
+ return deflateInit(level, MAX_WBITS);
+ }
+ public ZLibStatus deflateInit(CompressionLevel level, bool nowrap)
+ {
+ return deflateInit(level, MAX_WBITS, nowrap);
+ }
+ public ZLibStatus deflateInit(CompressionLevel level, int bits, bool nowrap)
+ {
+ return this.deflateInit(level, nowrap ? -bits : bits);
+ }
+
+ internal ZLibStatus deflateInit(CompressionLevel level, int bits)
+ {
+ return deflateInit2(level, Z_DEFLATED, bits, DEF_MEM_LEVEL, CompressionStrategy.Z_DEFAULT_STRATEGY);
+ }
+
+ private ZLibStatus deflateInit2(CompressionLevel level, int method, int windowBits, int memLevel, CompressionStrategy strategy)
+ {
+ int noheader = 0;
+ // byte[] my_version=ZLIB_VERSION;
+
+ //
+ // if (version == null || version[0] != my_version[0]
+ // || stream_size != sizeof(z_stream)) {
+ // return Z_VERSION_ERROR;
+ // }
+
+ base.msg = null;
+
+ if (level == CompressionLevel.Z_DEFAULT_COMPRESSION) level = (CompressionLevel)6;
+
+ if (windowBits < 0)
+ { // undocumented feature: suppress zlib header
+ noheader = 1;
+ windowBits = -windowBits;
+ }
+
+ if (memLevel < 1 || memLevel > MAX_MEM_LEVEL ||
+ method != Z_DEFLATED ||
+ windowBits < 9 || windowBits > 15 || level < 0 || level > (CompressionLevel)9 ||
+ strategy < 0 || strategy > CompressionStrategy.Z_HUFFMAN_ONLY)
+ {
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+
+ this.noheader = noheader;
+ _windowBits = windowBits;
+ _windowSize = 1 << _windowBits;
+ _windowMask = _windowSize - 1;
+
+ _hashBits = memLevel + 7;
+ _hashSize = 1 << _hashBits;
+ _hashMask = _hashSize - 1;
+ _hashShift = ((_hashBits + MIN_MATCH - 1) / MIN_MATCH);
+
+ _window = new byte[_windowSize * 2];
+ _previous = new short[_windowSize];
+ _head = new short[_hashSize];
+
+ lit_bufsize = 1 << (memLevel + 6); // 16K elements by default
+
+ // We overlay pending_buf and d_buf+l_buf. This works since the average
+ // output size for (length,distance) codes is <= 24 bits.
+ pending_buf = new byte[lit_bufsize * 4];
+ _pendingBufferSize = lit_bufsize * 4;
+
+ d_buf = lit_bufsize / 2;
+ l_buf = (1 + 2) * lit_bufsize;
+
+ this.level = level;
+
+ //System.out.println("level="+level);
+
+ this.strategy = strategy;
+ this._method = (byte)method;
+
+ return deflateReset();
+ }
+
+ private ZLibStatus deflateReset()
+ {
+ base.total_in = base.total_out = 0;
+ base.msg = null; //
+ base.data_type = BlockType.Z_UNKNOWN;
+
+ pending = 0;
+ pending_out = 0;
+
+ if (noheader < 0)
+ {
+ noheader = 0; // was set to -1 by deflate(..., FlushType.Z_FINISH);
+ }
+ _status = (noheader != 0) ? BUSY_STATE : INIT_STATE;
+ base.adler = Adler32.adler32(0, null, 0, 0);
+
+ last_flush = FlushType.Z_NO_FLUSH;
+
+ tr_init();
+ lm_init();
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus deflateEnd()
+ {
+ if (_status != INIT_STATE && _status != BUSY_STATE && _status != FINISH_STATE)
+ {
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+ // Deallocate in reverse order of allocations:
+ pending_buf = null;
+ _head = null;
+ _previous = null;
+ _window = null;
+ // free
+ // dstate=null;
+ return _status == BUSY_STATE ? ZLibStatus.Z_DATA_ERROR : ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus deflateParams(CompressionLevel _level, CompressionStrategy _strategy)
+ {
+ ZLibStatus err = ZLibStatus.Z_OK;
+
+ if (_level == CompressionLevel.Z_DEFAULT_COMPRESSION)
+ {
+ _level = (CompressionLevel)6;
+ }
+ if (_level < 0 || _level > (CompressionLevel)9 ||
+ _strategy < 0 || _strategy > CompressionStrategy.Z_HUFFMAN_ONLY)
+ {
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+
+ if (config_table[level].Function != config_table[_level].Function &&
+ base.total_in != 0)
+ {
+ // Flush the last buffer:
+ err = this.deflate(FlushType.Z_PARTIAL_FLUSH);
+ }
+
+ if (level != _level)
+ {
+ level = _level;
+ _maxLazyMatch = config_table[level].MaxLazy;
+ good_match = config_table[level].GoodLength;
+ nice_match = config_table[level].NiceLength;
+ _maxChainLength = config_table[level].MaxChain;
+ }
+ strategy = _strategy;
+ return err;
+ }
+
+ public ZLibStatus deflateSetDictionary(byte[] dictionary, int dictLength)
+ {
+ int length = dictLength;
+ int index = 0;
+
+ if (dictionary == null || _status != INIT_STATE)
+ return ZLibStatus.Z_STREAM_ERROR;
+
+ base.adler = Adler32.adler32(base.adler, dictionary, 0, dictLength);
+
+ if (length < MIN_MATCH) return ZLibStatus.Z_OK;
+ if (length > _windowSize - MIN_LOOKAHEAD)
+ {
+ length = _windowSize - MIN_LOOKAHEAD;
+ index = dictLength - length; // use the tail of the dictionary
+ }
+ System.Array.Copy(dictionary, index, _window, 0, length);
+ _startInsertString = length;
+ _blockStart = length;
+
+ // Insert all strings in the hash table (except for the last two bytes).
+ // s->lookahead stays null, so s->ins_h will be recomputed at the next
+ // call of fill_window.
+
+ _insertedHashIndex = _window[0] & 0xff;
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[1] & 0xff)) & _hashMask;
+
+ for (int n = 0; n <= length - MIN_MATCH; n++)
+ {
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[(n) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+ _previous[n & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)n;
+ }
+ return ZLibStatus.Z_OK;
+ }
+
+ private void lm_init()
+ {
+ _windowActualSize = 2 * _windowSize;
+
+ _head[_hashSize - 1] = 0;
+ for (int i = 0; i < _hashSize - 1; i++)
+ {
+ _head[i] = 0;
+ }
+
+ // Set the default configuration parameters:
+ _maxLazyMatch = Deflate.config_table[level].MaxLazy;
+ good_match = Deflate.config_table[level].GoodLength;
+ nice_match = Deflate.config_table[level].NiceLength;
+ _maxChainLength = Deflate.config_table[level].MaxChain;
+
+ _startInsertString = 0;
+ _blockStart = 0;
+ _validBytesAhead = 0;
+ _matchLength = _previousLength = MIN_MATCH - 1;
+ _matchAvailable = false;
+ _insertedHashIndex = 0;
+ }
+
+ // Initialize the tree data structures for a new zlib stream.
+ private void tr_init()
+ {
+
+ l_desc.Init(dyn_ltree, Deflate.static_l_desc);
+
+ d_desc.Init(dyn_dtree, Deflate.static_d_desc);
+
+ bl_desc.Init(bl_tree, Deflate.static_bl_desc);
+
+
+ bi_buf = 0;
+ bi_valid = 0;
+ last_eob_len = 8; // enough lookahead for inflate
+
+ // Initialize the first block of the first file:
+ init_block();
+ }
+
+ private void init_block()
+ {
+ // Initialize the trees.
+ for (int i = 0; i < L_CODES; i++) dyn_ltree[i * 2] = 0;
+ for (int i = 0; i < D_CODES; i++) dyn_dtree[i * 2] = 0;
+ for (int i = 0; i < BL_CODES; i++) bl_tree[i * 2] = 0;
+
+ dyn_ltree[END_BLOCK * 2] = 1;
+ opt_len = static_len = 0;
+ last_lit = matches = 0;
+ }
+
+ private static bool smaller(short[] tree, int n, int m, byte[] depth)
+ {
+ short tn2 = tree[n * 2];
+ short tm2 = tree[m * 2];
+ return (tn2 < tm2 ||
+ (tn2 == tm2 && depth[n] <= depth[m]));
+ }
+
+ // Scan a literal or distance tree to determine the frequencies of the codes
+ // in the bit length tree.
+ private void scan_tree(short[] tree,// the tree to be scanned
+ int max_code // and its largest code of non zero frequency
+ )
+ {
+ int n; // iterates over all tree elements
+ int prevlen = -1; // last emitted length
+ int curlen; // length of current code
+ int nextlen = tree[0 * 2 + 1]; // length of next code
+ int count = 0; // repeat count of the current code
+ int max_count = 7; // max repeat count
+ int min_count = 4; // min repeat count
+
+ if (nextlen == 0) { max_count = 138; min_count = 3; }
+ tree[(max_code + 1) * 2 + 1] = -1; // guard
+
+ for (n = 0; n <= max_code; n++)
+ {
+ curlen = nextlen; nextlen = tree[(n + 1) * 2 + 1];
+ if (++count < max_count && curlen == nextlen)
+ {
+ continue;
+ }
+ else if (count < min_count)
+ {
+ bl_tree[curlen * 2] += (short)count;
+ }
+ else if (curlen != 0)
+ {
+ if (curlen != prevlen) bl_tree[curlen * 2]++;
+ bl_tree[REP_3_6 * 2]++;
+ }
+ else if (count <= 10)
+ {
+ bl_tree[REPZ_3_10 * 2]++;
+ }
+ else
+ {
+ bl_tree[REPZ_11_138 * 2]++;
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0)
+ {
+ max_count = 138; min_count = 3;
+ }
+ else if (curlen == nextlen)
+ {
+ max_count = 6; min_count = 3;
+ }
+ else
+ {
+ max_count = 7; min_count = 4;
+ }
+ }
+ }
+
+ // Construct the Huffman tree for the bit lengths and return the index in
+ // bl_order of the last bit length code to send.
+ private int build_bl_tree()
+ {
+ int max_blindex; // index of last bit length code of non zero freq
+
+ // Determine the bit length frequencies for literal and distance trees
+ scan_tree(dyn_ltree, l_desc.LargestCode);
+ scan_tree(dyn_dtree, d_desc.LargestCode);
+
+ // Build the bit length tree:
+ bl_desc.BuildTree(this);
+ // opt_len now includes the length of the tree representations, except
+ // the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
+
+ // Determine the number of bit length codes to send. The pkzip format
+ // requires that at least 4 bit length codes be sent. (appnote.txt says
+ // 3 but the actual value used is 4.)
+ for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--)
+ {
+ if (bl_tree[Deflate.bl_order[max_blindex] * 2 + 1] != 0) break;
+ }
+ // Update opt_len to include the bit length tree and counts
+ opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4;
+
+ return max_blindex;
+ }
+
+
+ // Send the header for a block using dynamic Huffman trees: the counts, the
+ // lengths of the bit length codes, the literal tree and the distance tree.
+ // IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
+ private void send_all_trees(int lcodes, int dcodes, int blcodes)
+ {
+ int rank; // index in bl_order
+
+ send_bits(lcodes - 257, 5); // not +255 as stated in appnote.txt
+ send_bits(dcodes - 1, 5);
+ send_bits(blcodes - 4, 4); // not -3 as stated in appnote.txt
+ for (rank = 0; rank < blcodes; rank++)
+ {
+ send_bits(bl_tree[Deflate.bl_order[rank] * 2 + 1], 3);
+ }
+ send_tree(dyn_ltree, lcodes - 1); // literal tree
+ send_tree(dyn_dtree, dcodes - 1); // distance tree
+ }
+
+ // Send a literal or distance tree in compressed form, using the codes in
+ // bl_tree.
+ private void send_tree(short[] tree,// the tree to be sent
+ int max_code // and its largest code of non zero frequency
+ )
+ {
+ int n; // iterates over all tree elements
+ int prevlen = -1; // last emitted length
+ int curlen; // length of current code
+ int nextlen = tree[0 * 2 + 1]; // length of next code
+ int count = 0; // repeat count of the current code
+ int max_count = 7; // max repeat count
+ int min_count = 4; // min repeat count
+
+ if (nextlen == 0) { max_count = 138; min_count = 3; }
+
+ for (n = 0; n <= max_code; n++)
+ {
+ curlen = nextlen; nextlen = tree[(n + 1) * 2 + 1];
+ if (++count < max_count && curlen == nextlen)
+ {
+ continue;
+ }
+ else if (count < min_count)
+ {
+ do { send_code(curlen, bl_tree); } while (--count != 0);
+ }
+ else if (curlen != 0)
+ {
+ if (curlen != prevlen)
+ {
+ send_code(curlen, bl_tree); count--;
+ }
+ send_code(REP_3_6, bl_tree);
+ send_bits(count - 3, 2);
+ }
+ else if (count <= 10)
+ {
+ send_code(REPZ_3_10, bl_tree);
+ send_bits(count - 3, 3);
+ }
+ else
+ {
+ send_code(REPZ_11_138, bl_tree);
+ send_bits(count - 11, 7);
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0)
+ {
+ max_count = 138; min_count = 3;
+ }
+ else if (curlen == nextlen)
+ {
+ max_count = 6; min_count = 3;
+ }
+ else
+ {
+ max_count = 7; min_count = 4;
+ }
+ }
+ }
+
+ // Output a byte on the stream.
+ // IN assertion: there is enough room in pending_buf.
+ private void put_byte(byte[] p, int start, int len)
+ {
+ System.Array.Copy(p, start, pending_buf, pending, len);
+ pending += len;
+ }
+
+ private void put_byte(byte c)
+ {
+ pending_buf[pending++] = c;
+ }
+ private void put_short(int w)
+ {
+ pending_buf[pending++] = (byte)(w/*&0xff*/);
+ pending_buf[pending++] = (byte)(w >> 8);
+ }
+ private void putShortMSB(int b)
+ {
+ pending_buf[pending++] = (byte)(b >> 8);
+ pending_buf[pending++] = (byte)(b/*&0xff*/);
+ }
+
+ private void send_code(int c, short[] tree)
+ {
+ int c2 = c * 2;
+ send_bits((tree[c2] & 0xffff), (tree[c2 + 1] & 0xffff));
+ }
+
+ private void send_bits(int val, int length)
+ {
+ if (bi_valid > Buf_size - length)
+ {
+ bi_buf |= (uint)(val << bi_valid);
+ pending_buf[pending++] = (byte)(bi_buf/*&0xff*/);
+ pending_buf[pending++] = (byte)(bi_buf >> 8);
+ bi_buf = ((uint)val) >> (Buf_size - bi_valid);
+ bi_valid += length - Buf_size;
+ }
+ else
+ {
+ bi_buf |= (uint)(val << bi_valid);
+ bi_valid += length;
+ }
+ // int len = length;
+ // if (bi_valid > (int)Buf_size - len) {
+ // int val = value;
+ // // bi_buf |= (val << bi_valid);
+ // bi_buf = (short)((ushort)bi_buf | (ushort)((val << bi_valid)&0xffff));
+ // put_short(bi_buf);
+ // bi_buf = (short)(((uint)val) >> (Buf_size - bi_valid));
+ // bi_valid += len - Buf_size;
+ // } else {
+ // // bi_buf |= (value) << bi_valid;
+ // bi_buf = (short)((ushort)bi_buf | (ushort)(((value) << bi_valid)&0xffff));
+ // bi_valid += len;
+ // }
+ }
+
+ // Send one empty static block to give enough lookahead for inflate.
+ // This takes 10 bits, of which 7 may remain in the bit buffer.
+ // The current inflate code requires 9 bits of lookahead. If the
+ // last two codes for the previous block (real code plus EOB) were coded
+ // on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
+ // the last real code. In this case we send two empty static blocks instead
+ // of one. (There are no problems if the previous block is stored or fixed.)
+ // To simplify the code, we assume the worst case of last real code encoded
+ // on one bit only.
+ private void _tr_align()
+ {
+ send_bits(STATIC_TREES << 1, 3);
+ send_code(END_BLOCK, Deflate.static_ltree);
+
+ bi_flush();
+
+ // Of the 10 bits for the empty block, we have already sent
+ // (10 - bi_valid) bits. The lookahead for the last real code (before
+ // the EOB of the previous block) was thus at least one plus the length
+ // of the EOB plus what we have just sent of the empty static block.
+ if (1 + last_eob_len + 10 - bi_valid < 9)
+ {
+ send_bits(STATIC_TREES << 1, 3);
+ send_code(END_BLOCK, Deflate.static_ltree);
+ bi_flush();
+ }
+ last_eob_len = 7;
+ }
+
+
+ // Save the match info and tally the frequency counts. Return true if
+ // the current block must be flushed.
+ private bool _tr_tally(int dist, // distance of matched string
+ int lc // match length-MIN_MATCH or unmatched char (if dist==0)
+ )
+ {
+
+ pending_buf[d_buf + last_lit * 2] = (byte)(dist >> 8);
+ pending_buf[d_buf + last_lit * 2 + 1] = (byte)dist;
+
+ pending_buf[l_buf + last_lit] = (byte)lc; last_lit++;
+
+ if (dist == 0)
+ {
+ // lc is the unmatched char
+ dyn_ltree[lc * 2]++;
+ }
+ else
+ {
+ matches++;
+ // Here, lc is the match length - MIN_MATCH
+ dist--; // dist = match distance - 1
+ dyn_ltree[(Deflate._length_code[lc] + LITERALS + 1) * 2]++;
+ dyn_dtree[Tree.DistanceCode(dist) * 2]++;
+ }
+
+ if ((last_lit & 0x1fff) == 0 && level > (CompressionLevel)2)
+ {
+ // Compute an upper bound for the compressed length
+ int out_length = last_lit * 8;
+ int in_length = _startInsertString - _blockStart;
+ int dcode;
+ for (dcode = 0; dcode < D_CODES; dcode++)
+ {
+ out_length += (int)((int)dyn_dtree[dcode * 2] *
+ (5L + Deflate.extra_dbits[dcode]));
+ }
+ out_length >>= 3;
+ if ((matches < (last_lit / 2)) && out_length < in_length / 2) return true;
+ }
+
+ return (last_lit == lit_bufsize - 1);
+ // We avoid equality with lit_bufsize because of wraparound at 64K
+ // on 16 bit machines and because stored blocks are restricted to
+ // 64K-1 bytes.
+ }
+
+ // Send the block data compressed using the given Huffman trees
+ private void compress_block(short[] ltree, short[] dtree)
+ {
+ int dist; // distance of matched string
+ int lc; // match length or unmatched char (if dist == 0)
+ int lx = 0; // running index in l_buf
+ int code; // the code to send
+ int extra; // number of extra bits to send
+
+ if (last_lit != 0)
+ {
+ do
+ {
+ dist = ((pending_buf[d_buf + lx * 2] << 8) & 0xff00) |
+ (pending_buf[d_buf + lx * 2 + 1] & 0xff);
+ lc = (pending_buf[l_buf + lx]) & 0xff; lx++;
+
+ if (dist == 0)
+ {
+ send_code(lc, ltree); // send a literal byte
+ }
+ else
+ {
+ // Here, lc is the match length - MIN_MATCH
+ code = Deflate._length_code[lc];
+
+ send_code(code + LITERALS + 1, ltree); // send the length code
+ extra = Deflate.extra_lbits[code];
+ if (extra != 0)
+ {
+ lc -= Deflate.base_length[code];
+ send_bits(lc, extra); // send the extra length bits
+ }
+ dist--; // dist is now the match distance - 1
+ code = Tree.DistanceCode(dist);
+
+ send_code(code, dtree); // send the distance code
+ extra = Deflate.extra_dbits[code];
+ if (extra != 0)
+ {
+ dist -= Deflate.base_dist[code];
+ send_bits(dist, extra); // send the extra distance bits
+ }
+ } // literal or match pair ?
+
+ // Check that the overlay between pending_buf and d_buf+l_buf is ok:
+ }
+ while (lx < last_lit);
+ }
+
+ send_code(END_BLOCK, ltree);
+ last_eob_len = ltree[END_BLOCK * 2 + 1];
+ }
+
+ // Set the data type to ASCII or BINARY, using a crude approximation:
+ // binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise.
+ // IN assertion: the fields freq of dyn_ltree are set and the total of all
+ // frequencies does not exceed 64K (to fit in an int on 16 bit machines).
+ private void set_data_type()
+ {
+ int n = 0;
+ int ascii_freq = 0;
+ int bin_freq = 0;
+ while (n < 7) { bin_freq += dyn_ltree[n * 2]; n++; }
+ while (n < 128) { ascii_freq += dyn_ltree[n * 2]; n++; }
+ while (n < LITERALS) { bin_freq += dyn_ltree[n * 2]; n++; }
+ this._dataType = (bin_freq > (ascii_freq >> 2) ? BlockType.Z_BINARY : BlockType.Z_ASCII);
+ }
+
+ // Flush the bit buffer, keeping at most 7 bits in it.
+ private void bi_flush()
+ {
+ if (bi_valid == 16)
+ {
+ pending_buf[pending++] = (byte)(bi_buf/*&0xff*/);
+ pending_buf[pending++] = (byte)(bi_buf >> 8);
+ bi_buf = 0;
+ bi_valid = 0;
+ }
+ else if (bi_valid >= 8)
+ {
+ pending_buf[pending++] = (byte)(bi_buf);
+ bi_buf >>= 8;
+ bi_buf &= 0x00ff;
+ bi_valid -= 8;
+ }
+ }
+
+ // Flush the bit buffer and align the output on a byte boundary
+ private void bi_windup()
+ {
+ if (bi_valid > 8)
+ {
+ pending_buf[pending++] = (byte)(bi_buf);
+ pending_buf[pending++] = (byte)(bi_buf >> 8);
+ }
+ else if (bi_valid > 0)
+ {
+ pending_buf[pending++] = (byte)(bi_buf);
+ }
+ bi_buf = 0;
+ bi_valid = 0;
+ }
+
+ // Copy a stored block, storing first the length and its
+ // one's complement if requested.
+ private void copy_block(int buf, // the input data
+ int len, // its length
+ bool header // true if block header must be written
+ )
+ {
+ //int index=0;
+ bi_windup(); // align on byte boundary
+ last_eob_len = 8; // enough lookahead for inflate
+
+ if (header)
+ {
+ put_short((short)len);
+ put_short((short)~len);
+ }
+
+ // while(len--!=0) {
+ // put_byte(window[buf+index]);
+ // index++;
+ // }
+ put_byte(_window, buf, len);
+ }
+
+ private void flush_block_only(bool eof)
+ {
+ _tr_flush_block(_blockStart >= 0 ? _blockStart : -1,
+ _startInsertString - _blockStart,
+ eof);
+ _blockStart = _startInsertString;
+ this.flush_pending();
+ }
+
+ // Copy without compression as much as possible from the input stream, return
+ // the current block state.
+ // This function does not insert new strings in the dictionary since
+ // uncompressible data is probably not useful. This function is used
+ // only for the level=0 compression option.
+ // NOTE: this function should be optimized to avoid extra copying from
+ // window to pending_buf.
+ private int deflate_stored(FlushType flush)
+ {
+ // Stored blocks are limited to 0xffff bytes, pending_buf is limited
+ // to pending_buf_size, and each stored block has a 5 byte header:
+
+ int max_block_size = 0xffff;
+ int max_start;
+
+ if (max_block_size > _pendingBufferSize - 5)
+ {
+ max_block_size = _pendingBufferSize - 5;
+ }
+
+ // Copy as much as possible from input to output:
+ while (true)
+ {
+ // Fill the window as much as possible:
+ if (_validBytesAhead <= 1)
+ {
+ fill_window();
+ if (_validBytesAhead == 0 && flush == FlushType.Z_NO_FLUSH) return NeedMore;
+ if (_validBytesAhead == 0) break; // flush the current block
+ }
+
+ _startInsertString += _validBytesAhead;
+ _validBytesAhead = 0;
+
+ // Emit a stored block if pending_buf will be full:
+ max_start = _blockStart + max_block_size;
+ if (_startInsertString == 0 || _startInsertString >= max_start)
+ {
+ // strstart == 0 is possible when wraparound on 16-bit machine
+ _validBytesAhead = (int)(_startInsertString - max_start);
+ _startInsertString = (int)max_start;
+
+ flush_block_only(false);
+ if (base.avail_out == 0) return NeedMore;
+
+ }
+
+ // Flush if we may have to slide, otherwise block_start may become
+ // negative and the data will be gone:
+ if (_startInsertString - _blockStart >= _windowSize - MIN_LOOKAHEAD)
+ {
+ flush_block_only(false);
+ if (base.avail_out == 0) return NeedMore;
+ }
+ }
+
+ flush_block_only(flush == FlushType.Z_FINISH);
+ if (base.avail_out == 0)
+ return (flush == FlushType.Z_FINISH) ? FinishStarted : NeedMore;
+
+ return flush == FlushType.Z_FINISH ? FinishDone : BlockDone;
+ }
+
+ // Send a stored block
+ private void _tr_stored_block(int buf, // input block
+ int stored_len, // length of input block
+ bool eof // true if this is the last block for a file
+ )
+ {
+ send_bits((STORED_BLOCK << 1) + (eof ? 1 : 0), 3); // send block type
+ copy_block(buf, stored_len, true); // with header
+ }
+
+ // Determine the best encoding for the current block: dynamic trees, static
+ // trees or store, and output the encoded block to the zip file.
+ private void _tr_flush_block(int buf, // input block, or NULL if too old
+ int stored_len, // length of input block
+ bool eof // true if this is the last block for a file
+ )
+ {
+ int opt_lenb, static_lenb;// opt_len and static_len in bytes
+ int max_blindex = 0; // index of last bit length code of non zero freq
+
+ // Build the Huffman trees unless a stored block is forced
+ if (level > 0)
+ {
+ // Check if the file is ascii or binary
+ if (this._dataType == BlockType.Z_UNKNOWN) set_data_type();
+
+ // Construct the literal and distance trees
+ l_desc.BuildTree(this);
+
+ d_desc.BuildTree(this);
+
+ // At this point, opt_len and static_len are the total bit lengths of
+ // the compressed block data, excluding the tree representations.
+
+ // Build the bit length tree for the above two trees, and get the index
+ // in bl_order of the last bit length code to send.
+ max_blindex = build_bl_tree();
+
+ // Determine the best encoding. Compute first the block length in bytes
+ opt_lenb = (opt_len + 3 + 7) >> 3;
+ static_lenb = (static_len + 3 + 7) >> 3;
+
+ if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
+ }
+ else
+ {
+ opt_lenb = static_lenb = stored_len + 5; // force a stored block
+ }
+
+ if (stored_len + 4 <= opt_lenb && buf != -1)
+ {
+ // 4: two words for the lengths
+ // The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
+ // Otherwise we can't have processed more than WSIZE input bytes since
+ // the last block flush, because compression would have been
+ // successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
+ // transform a block into a stored block.
+ _tr_stored_block(buf, stored_len, eof);
+ }
+ else if (static_lenb == opt_lenb)
+ {
+ send_bits((STATIC_TREES << 1) + (eof ? 1 : 0), 3);
+ compress_block(Deflate.static_ltree, Deflate.static_dtree);
+ }
+ else
+ {
+ send_bits((DYN_TREES << 1) + (eof ? 1 : 0), 3);
+ send_all_trees(l_desc.LargestCode + 1, d_desc.LargestCode + 1, max_blindex + 1);
+ compress_block(dyn_ltree, dyn_dtree);
+ }
+
+ // The above check is made mod 2^32, for files larger than 512 MB
+ // and uLong implemented on 32 bits.
+
+ init_block();
+
+ if (eof)
+ {
+ bi_windup();
+ }
+ }
+
+ // Fill the window when the lookahead becomes insufficient.
+ // Updates strstart and lookahead.
+ //
+ // IN assertion: lookahead < MIN_LOOKAHEAD
+ // OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
+ // At least one byte has been read, or avail_in == 0; reads are
+ // performed for at least two bytes (required for the zip translate_eol
+ // option -- not supported here).
+ private void fill_window()
+ {
+ int n, m;
+ int p;
+ int more; // Amount of free space at the end of the window.
+
+ do
+ {
+ more = (_windowActualSize - _validBytesAhead - _startInsertString);
+
+ // Deal with !@#$% 64K limit:
+ if (more == 0 && _startInsertString == 0 && _validBytesAhead == 0)
+ {
+ more = _windowSize;
+ }
+ else if (more == -1)
+ {
+ // Very unlikely, but possible on 16 bit machine if strstart == 0
+ // and lookahead == 1 (input done one byte at time)
+ more--;
+
+ // If the window is almost full and there is insufficient lookahead,
+ // move the upper half to the lower one to make room in the upper half.
+ }
+ else if (_startInsertString >= _windowSize + _windowSize - MIN_LOOKAHEAD)
+ {
+ System.Array.Copy(_window, _windowSize, _window, 0, _windowSize);
+ _startMatchString -= _windowSize;
+ _startInsertString -= _windowSize; // we now have strstart >= MAX_DIST
+ _blockStart -= _windowSize;
+
+ // Slide the hash table (could be avoided with 32 bit values
+ // at the expense of memory usage). We slide even when level == 0
+ // to keep the hash table consistent if we switch back to level > 0
+ // later. (Using level 0 permanently is not an optimal usage of
+ // zlib, so we don't care about this pathological case.)
+
+ n = _hashSize;
+ p = n;
+ do
+ {
+ m = (_head[--p] & 0xffff);
+ _head[p] = (short)(m >= _windowSize ? (m - _windowSize) : 0);
+ }
+ while (--n != 0);
+
+ n = _windowSize;
+ p = n;
+ do
+ {
+ m = (_previous[--p] & 0xffff);
+ _previous[p] = (short)(m >= _windowSize ? (m - _windowSize) : 0);
+ // If n is not on any hash chain, prev[n] is garbage but
+ // its value will never be used.
+ }
+ while (--n != 0);
+ more += _windowSize;
+ }
+
+ if (base.avail_in == 0) return;
+
+ // If there was no sliding:
+ // strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
+ // more == window_size - lookahead - strstart
+ // => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
+ // => more >= window_size - 2*WSIZE + 2
+ // In the BIG_MEM or MMAP case (not yet supported),
+ // window_size == input_size + MIN_LOOKAHEAD &&
+ // strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
+ // Otherwise, window_size == 2*WSIZE so more >= 2.
+ // If there was sliding, more >= WSIZE. So in all cases, more >= 2.
+
+ n = this.read_buf(_window, _startInsertString + _validBytesAhead, more);
+ _validBytesAhead += n;
+
+ // Initialize the hash value now that we have some input:
+ if (_validBytesAhead >= MIN_MATCH)
+ {
+ _insertedHashIndex = _window[_startInsertString] & 0xff;
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[_startInsertString + 1] & 0xff)) & _hashMask;
+ }
+ // If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
+ // but this is not important since only literal bytes will be emitted.
+ }
+ while (_validBytesAhead < MIN_LOOKAHEAD && base.avail_in != 0);
+ }
+
+ // Compress as much as possible from the input stream, return the current
+ // block state.
+ // This function does not perform lazy evaluation of matches and inserts
+ // new strings in the dictionary only for unmatched strings or for short
+ // matches. It is used only for the fast compression options.
+ private int deflate_fast(FlushType flush)
+ {
+ // short hash_head = 0; // head of the hash chain
+ int hash_head = 0; // head of the hash chain
+ bool bflush; // set if current block must be flushed
+
+ while (true)
+ {
+ // Make sure that we always have enough lookahead, except
+ // at the end of the input file. We need MAX_MATCH bytes
+ // for the next match, plus MIN_MATCH bytes to insert the
+ // string following the next match.
+ if (_validBytesAhead < MIN_LOOKAHEAD)
+ {
+ fill_window();
+ if (_validBytesAhead < MIN_LOOKAHEAD && flush == FlushType.Z_NO_FLUSH)
+ {
+ return NeedMore;
+ }
+ if (_validBytesAhead == 0) break; // flush the current block
+ }
+
+ // Insert the string window[strstart .. strstart+2] in the
+ // dictionary, and set hash_head to the head of the hash chain:
+ if (_validBytesAhead >= MIN_MATCH)
+ {
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[(_startInsertString) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+
+ // prev[strstart&w_mask]=hash_head=head[ins_h];
+ hash_head = (_head[_insertedHashIndex] & 0xffff);
+ _previous[_startInsertString & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)_startInsertString;
+ }
+
+ // Find the longest match, discarding those <= prev_length.
+ // At this point we have always match_length < MIN_MATCH
+
+ if (hash_head != 0L &&
+ ((_startInsertString - hash_head) & 0xffff) <= _windowSize - MIN_LOOKAHEAD
+ )
+ {
+ // To simplify the code, we prevent matches with the string
+ // of window index 0 (in particular we have to avoid a match
+ // of the string with itself at the start of the input file).
+ if (strategy != CompressionStrategy.Z_HUFFMAN_ONLY)
+ {
+ _matchLength = longest_match(hash_head);
+ }
+ // longest_match() sets match_start
+ }
+ if (_matchLength >= MIN_MATCH)
+ {
+ // check_match(strstart, match_start, match_length);
+
+ bflush = _tr_tally(_startInsertString - _startMatchString, _matchLength - MIN_MATCH);
+
+ _validBytesAhead -= _matchLength;
+
+ // Insert new strings in the hash table only if the match length
+ // is not too large. This saves time but degrades compression.
+ if (_matchLength <= _maxLazyMatch &&
+ _validBytesAhead >= MIN_MATCH)
+ {
+ _matchLength--; // string at strstart already in hash table
+ do
+ {
+ _startInsertString++;
+
+ _insertedHashIndex = ((_insertedHashIndex << _hashShift) ^ (_window[(_startInsertString) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+ // prev[strstart&w_mask]=hash_head=head[ins_h];
+ hash_head = (_head[_insertedHashIndex] & 0xffff);
+ _previous[_startInsertString & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)_startInsertString;
+
+ // strstart never exceeds WSIZE-MAX_MATCH, so there are
+ // always MIN_MATCH bytes ahead.
+ }
+ while (--_matchLength != 0);
+ _startInsertString++;
+ }
+ else
+ {
+ _startInsertString += _matchLength;
+ _matchLength = 0;
+ _insertedHashIndex = _window[_startInsertString] & 0xff;
+
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[_startInsertString + 1] & 0xff)) & _hashMask;
+ // If lookahead < MIN_MATCH, ins_h is garbage, but it does not
+ // matter since it will be recomputed at next deflate call.
+ }
+ }
+ else
+ {
+ // No match, output a literal byte
+
+ bflush = _tr_tally(0, _window[_startInsertString] & 0xff);
+ _validBytesAhead--;
+ _startInsertString++;
+ }
+ if (bflush)
+ {
+
+ flush_block_only(false);
+ if (base.avail_out == 0) return NeedMore;
+ }
+ }
+
+ flush_block_only(flush == FlushType.Z_FINISH);
+ if (base.avail_out == 0)
+ {
+ if (flush == FlushType.Z_FINISH) return FinishStarted;
+ else return NeedMore;
+ }
+ return flush == FlushType.Z_FINISH ? FinishDone : BlockDone;
+ }
+
+ // Same as above, but achieves better compression. We use a lazy
+ // evaluation for matches: a match is finally adopted only if there is
+ // no better match at the next window position.
+ private int deflate_slow(FlushType flush)
+ {
+ // short hash_head = 0; // head of hash chain
+ int hash_head = 0; // head of hash chain
+ bool bflush; // set if current block must be flushed
+
+ // Process the input block.
+ while (true)
+ {
+ // Make sure that we always have enough lookahead, except
+ // at the end of the input file. We need MAX_MATCH bytes
+ // for the next match, plus MIN_MATCH bytes to insert the
+ // string following the next match.
+
+ if (_validBytesAhead < MIN_LOOKAHEAD)
+ {
+ fill_window();
+ if (_validBytesAhead < MIN_LOOKAHEAD && flush == FlushType.Z_NO_FLUSH)
+ {
+ return NeedMore;
+ }
+ if (_validBytesAhead == 0) break; // flush the current block
+ }
+
+ // Insert the string window[strstart .. strstart+2] in the
+ // dictionary, and set hash_head to the head of the hash chain:
+
+ if (_validBytesAhead >= MIN_MATCH)
+ {
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[(_startInsertString) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+ // prev[strstart&w_mask]=hash_head=head[ins_h];
+ hash_head = (_head[_insertedHashIndex] & 0xffff);
+ _previous[_startInsertString & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)_startInsertString;
+ }
+
+ // Find the longest match, discarding those <= prev_length.
+ _previousLength = _matchLength; _previousMatch = _startMatchString;
+ _matchLength = MIN_MATCH - 1;
+
+ if (hash_head != 0 && _previousLength < _maxLazyMatch &&
+ ((_startInsertString - hash_head) & 0xffff) <= _windowSize - MIN_LOOKAHEAD
+ )
+ {
+ // To simplify the code, we prevent matches with the string
+ // of window index 0 (in particular we have to avoid a match
+ // of the string with itself at the start of the input file).
+
+ if (strategy != CompressionStrategy.Z_HUFFMAN_ONLY)
+ {
+ _matchLength = longest_match(hash_head);
+ }
+ // longest_match() sets match_start
+
+ if (_matchLength <= 5 && (strategy == CompressionStrategy.Z_FILTERED ||
+ (_matchLength == MIN_MATCH &&
+ _startInsertString - _startMatchString > 4096)))
+ {
+
+ // If prev_match is also MIN_MATCH, match_start is garbage
+ // but we will ignore the current match anyway.
+ _matchLength = MIN_MATCH - 1;
+ }
+ }
+
+ // If there was a match at the previous step and the current
+ // match is not better, output the previous match:
+ if (_previousLength >= MIN_MATCH && _matchLength <= _previousLength)
+ {
+ int max_insert = _startInsertString + _validBytesAhead - MIN_MATCH;
+ // Do not insert strings in hash table beyond this.
+
+ // check_match(strstart-1, prev_match, prev_length);
+
+ bflush = _tr_tally(_startInsertString - 1 - _previousMatch, _previousLength - MIN_MATCH);
+
+ // Insert in hash table all strings up to the end of the match.
+ // strstart-1 and strstart are already inserted. If there is not
+ // enough lookahead, the last two strings are not inserted in
+ // the hash table.
+ _validBytesAhead -= _previousLength - 1;
+ _previousLength -= 2;
+ do
+ {
+ if (++_startInsertString <= max_insert)
+ {
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[(_startInsertString) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+ //prev[strstart&w_mask]=hash_head=head[ins_h];
+ hash_head = (_head[_insertedHashIndex] & 0xffff);
+ _previous[_startInsertString & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)_startInsertString;
+ }
+ }
+ while (--_previousLength != 0);
+ _matchAvailable = false;
+ _matchLength = MIN_MATCH - 1;
+ _startInsertString++;
+
+ if (bflush)
+ {
+ flush_block_only(false);
+ if (base.avail_out == 0) return NeedMore;
+ }
+ }
+ else if (_matchAvailable != false)
+ {
+
+ // If there was no match at the previous position, output a
+ // single literal. If there was a match but the current match
+ // is longer, truncate the previous match to a single literal.
+
+ bflush = _tr_tally(0, _window[_startInsertString - 1] & 0xff);
+
+ if (bflush)
+ {
+ flush_block_only(false);
+ }
+ _startInsertString++;
+ _validBytesAhead--;
+ if (base.avail_out == 0) return NeedMore;
+ }
+ else
+ {
+ // There is no previous match to compare with, wait for
+ // the next step to decide.
+
+ _matchAvailable = true;
+ _startInsertString++;
+ _validBytesAhead--;
+ }
+ }
+
+ if (_matchAvailable != false)
+ {
+ bflush = _tr_tally(0, _window[_startInsertString - 1] & 0xff);
+ _matchAvailable = false;
+ }
+ flush_block_only(flush == FlushType.Z_FINISH);
+
+ if (base.avail_out == 0)
+ {
+ if (flush == FlushType.Z_FINISH) return FinishStarted;
+ else return NeedMore;
+ }
+
+ return flush == FlushType.Z_FINISH ? FinishDone : BlockDone;
+ }
+
+ private int longest_match(int cur_match)
+ {
+ int chain_length = _maxChainLength; // max hash chain length
+ int scan = _startInsertString; // current string
+ int match; // matched string
+ int len; // length of current match
+ int best_len = _previousLength; // best match length so far
+ int limit = _startInsertString > (_windowSize - MIN_LOOKAHEAD) ?
+ _startInsertString - (_windowSize - MIN_LOOKAHEAD) : 0;
+ int nice_match = this.nice_match;
+
+ // Stop when cur_match becomes <= limit. To simplify the code,
+ // we prevent matches with the string of window index 0.
+
+ int wmask = _windowMask;
+
+ int strend = _startInsertString + MAX_MATCH;
+ byte scan_end1 = _window[scan + best_len - 1];
+ byte scan_end = _window[scan + best_len];
+
+ // The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+ // It is easy to get rid of this optimization if necessary.
+
+ // Do not waste too much time if we already have a good match:
+ if (_previousLength >= good_match)
+ {
+ chain_length >>= 2;
+ }
+
+ // Do not look for matches beyond the end of the input. This is necessary
+ // to make deflate deterministic.
+ if (nice_match > _validBytesAhead) nice_match = _validBytesAhead;
+
+ do
+ {
+ match = cur_match;
+
+ // Skip to next match if the match length cannot increase
+ // or if the match length is less than 2:
+ if (_window[match + best_len] != scan_end ||
+ _window[match + best_len - 1] != scan_end1 ||
+ _window[match] != _window[scan] ||
+ _window[++match] != _window[scan + 1]) continue;
+
+ // The check at best_len-1 can be removed because it will be made
+ // again later. (This heuristic is not always a win.)
+ // It is not necessary to compare scan[2] and match[2] since they
+ // are always equal when the other bytes match, given that
+ // the hash keys are equal and that HASH_BITS >= 8.
+ scan += 2; match++;
+
+ // We check for insufficient lookahead only every 8th comparison;
+ // the 256th check will be made at strstart+258.
+ do
+ {
+ } while (_window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ scan < strend);
+
+ len = MAX_MATCH - (int)(strend - scan);
+ scan = strend - MAX_MATCH;
+
+ if (len > best_len)
+ {
+ _startMatchString = cur_match;
+ best_len = len;
+ if (len >= nice_match) break;
+ scan_end1 = _window[scan + best_len - 1];
+ scan_end = _window[scan + best_len];
+ }
+
+ } while ((cur_match = (_previous[cur_match & wmask] & 0xffff)) > limit
+ && --chain_length != 0);
+
+ if (best_len <= _validBytesAhead) return best_len;
+ return _validBytesAhead;
+ }
+
+ public ZLibStatus deflate(FlushType flush)
+ {
+ FlushType old_flush;
+
+ if (flush > FlushType.Z_FINISH || flush < 0)
+ {
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+
+ if (base.next_out == null ||
+ (base.next_in == null && base.avail_in != 0) ||
+ (_status == FINISH_STATE && flush != FlushType.Z_FINISH))
+ {
+ base.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_STREAM_ERROR)];
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+ if (base.avail_out == 0)
+ {
+ base.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_BUF_ERROR)];
+ return ZLibStatus.Z_BUF_ERROR;
+ }
+
+ old_flush = last_flush;
+ last_flush = flush;
+
+ // Write the zlib header
+ if (_status == INIT_STATE)
+ {
+ int header = (Z_DEFLATED + ((this._windowBits - 8) << 4)) << 8;
+ int level_flags = (((int)this.level - 1) & 0xff) >> 1;
+
+ if (level_flags > 3) level_flags = 3;
+ header |= (level_flags << 6);
+ if (this._startInsertString != 0) header |= PRESET_DICT;
+ header += 31 - (header % 31);
+
+ _status = BUSY_STATE;
+ putShortMSB(header);
+
+
+ // Save the adler32 of the preset dictionary:
+ if (this._startInsertString != 0)
+ {
+ putShortMSB((int)(base.adler >> 16));
+ putShortMSB((int)(base.adler & 0xffff));
+ }
+ base.adler = Adler32.adler32(0, null, 0, 0);
+ }
+
+ // Flush as much pending output as possible
+ if (pending != 0)
+ {
+ this.flush_pending();
+ if (base.avail_out == 0)
+ {
+ //System.out.println(" avail_out==0");
+ // Since avail_out is 0, deflate will be called again with
+ // more output space, but possibly with both pending and
+ // avail_in equal to zero. There won't be anything to do,
+ // but this is not an error situation so make sure we
+ // return OK instead of BUF_ERROR at next call of deflate:
+ last_flush = (FlushType)(-1);
+ return ZLibStatus.Z_OK;
+ }
+
+ // Make sure there is something to do and avoid duplicate consecutive
+ // flushes. For repeated and useless calls with Z_FINISH, we keep
+ // returning Z_STREAM_END instead of Z_BUFF_ERROR.
+ }
+ else if (base.avail_in == 0 && flush <= old_flush &&
+ flush != FlushType.Z_FINISH)
+ {
+ base.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_BUF_ERROR)];
+ return ZLibStatus.Z_BUF_ERROR;
+ }
+
+ // User must not provide more input after the first FINISH:
+ if (_status == FINISH_STATE && base.avail_in != 0)
+ {
+ base.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_BUF_ERROR)];
+ return ZLibStatus.Z_BUF_ERROR;
+ }
+
+ // Start a new block or continue the current one.
+ if (base.avail_in != 0 || this._validBytesAhead != 0 ||
+ (flush != FlushType.Z_NO_FLUSH && _status != FINISH_STATE))
+ {
+ int bstate = -1;
+ switch (config_table[level].Function)
+ {
+ case DefalteFlavor.STORED:
+ bstate = deflate_stored(flush);
+ break;
+ case DefalteFlavor.FAST:
+ bstate = deflate_fast(flush);
+ break;
+ case DefalteFlavor.SLOW:
+ bstate = deflate_slow(flush);
+ break;
+ default:
+ break;
+ }
+
+ if (bstate == FinishStarted || bstate == FinishDone)
+ {
+ _status = FINISH_STATE;
+ }
+ if (bstate == NeedMore || bstate == FinishStarted)
+ {
+ if (base.avail_out == 0)
+ {
+ last_flush = (FlushType)(-1); // avoid BUF_ERROR next call, see above
+ }
+ return ZLibStatus.Z_OK;
+ // If flush != Z_NO_FLUSH && avail_out == 0, the next call
+ // of deflate should use the same flush parameter to make sure
+ // that the flush is complete. So we don't have to output an
+ // empty block here, this will be done at next call. This also
+ // ensures that for a very small output buffer, we emit at most
+ // one empty block.
+ }
+
+ if (bstate == BlockDone)
+ {
+ if (flush == FlushType.Z_PARTIAL_FLUSH)
+ {
+ _tr_align();
+ }
+ else
+ { // FULL_FLUSH or SYNC_FLUSH
+ _tr_stored_block(0, 0, false);
+ // For a full flush, this empty block will be recognized
+ // as a special marker by inflate_sync().
+ if (flush == FlushType.Z_FULL_FLUSH)
+ {
+ //state.head[s.hash_size-1]=0;
+ for (int i = 0; i < this._hashSize/*-1*/; i++) // forget history
+ this._head[i] = 0;
+ }
+ }
+ this.flush_pending();
+ if (base.avail_out == 0)
+ {
+ last_flush = (FlushType)(-1); // avoid BUF_ERROR at next call, see above
+ return ZLibStatus.Z_OK;
+ }
+ }
+ }
+
+ if (flush != FlushType.Z_FINISH) return ZLibStatus.Z_OK;
+ if (noheader != 0) return ZLibStatus.Z_STREAM_END;
+
+ // Write the zlib trailer (adler32)
+ putShortMSB((int)(base.adler >> 16));
+ putShortMSB((int)(base.adler & 0xffff));
+ this.flush_pending();
+
+ // If avail_out is zero, the application will call deflate again
+ // to flush the rest.
+ noheader = -1; // write the trailer only once!
+ return pending != 0 ? ZLibStatus.Z_OK : ZLibStatus.Z_STREAM_END;
+ }
+
+
+ private static readonly StaticTree static_l_desc = new StaticTree(static_ltree, Deflate.extra_lbits, LITERALS + 1, L_CODES, MAX_BITS);
+
+ private static readonly StaticTree static_d_desc = new StaticTree(static_dtree, Deflate.extra_dbits, 0, D_CODES, MAX_BITS);
+
+ private static readonly StaticTree static_bl_desc = new StaticTree(null, Deflate.extra_blbits, 0, BL_CODES, MAX_BL_BITS);
+
+ private class Config
+ {
+ ///
+ /// Reduce lazy search above this match length
+ ///
+ internal int GoodLength { get; private set; }
+ ///
+ /// Gets or sets whether not to perform lazy search above this match length
+ ///
+ ///
+ /// The max lazy.
+ ///
+ internal int MaxLazy { get; private set; }
+ ///
+ /// Gets or sets whether to quit search above this match length
+ ///
+ ///
+ /// The length of the nice.
+ ///
+ internal int NiceLength { get; private set; }
+ internal int MaxChain { get; private set; }
+ internal DefalteFlavor Function { get; private set; }
+ internal Config(int goodLength, int maxLazy, int niceLength, int maxChain, DefalteFlavor function)
+ {
+ this.GoodLength = goodLength;
+ this.MaxLazy = maxLazy;
+ this.NiceLength = niceLength;
+ this.MaxChain = maxChain;
+ this.Function = function;
+ }
+ }
+
+
+ // Flush as much pending output as possible. All deflate() output goes
+ // through this function so some applications may wish to modify it
+ // to avoid allocating a large strm->next_out buffer and copying into it.
+ // (See also read_buf()).
+ internal void flush_pending()
+ {
+ int len = this.pending;
+
+ if (len > avail_out) len = avail_out;
+ if (len == 0) return;
+
+ if (this.pending_buf.Length <= this.pending_out ||
+ next_out.Length <= next_out_index ||
+ this.pending_buf.Length < (this.pending_out + len) ||
+ next_out.Length < (next_out_index + len))
+ {
+ // System.out.println(this.pending_buf.length+", "+this.pending_out+
+ // ", "+next_out.length+", "+next_out_index+", "+len);
+ // System.out.println("avail_out="+avail_out);
+ }
+
+ System.Array.Copy(this.pending_buf, this.pending_out,
+ next_out, next_out_index, len);
+
+ next_out_index += len;
+ this.pending_out += len;
+ total_out += len;
+ avail_out -= len;
+ this.pending -= len;
+ if (this.pending == 0)
+ {
+ this.pending_out = 0;
+ }
+ }
+
+ // Read a new buffer from the current input stream, update the adler32
+ // and total number of bytes read. All deflate() input goes through
+ // this function so some applications may wish to modify it to avoid
+ // allocating a large strm->next_in buffer and copying from it.
+ // (See also flush_pending()).
+ internal int read_buf(byte[] buf, int start, int size)
+ {
+ int len = avail_in;
+
+ if (len > size) len = size;
+ if (len == 0) return 0;
+
+ avail_in -= len;
+
+ if (this.noheader == 0)
+ {
+ adler = Adler32.adler32(adler, next_in, next_in_index, len);
+ }
+ System.Array.Copy(next_in, next_in_index, buf, start, len);
+ next_in_index += len;
+ total_in += len;
+ return len;
+ }
+
+ public ZLibStatus deflate(byte[] inputBufer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType)
+ {
+ this.next_in = inputBufer;
+ this.next_in_index = inputOffset;
+ this.avail_in = inputCount;
+ this.next_out = outputBuffer;
+ this.next_out_index = outputOffset;
+ this.avail_out = outputCount;
+ return this.deflate(flushType);
+ }
+
+ public ZLibStatus deflate(byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType)
+ {
+ this.next_out = outputBuffer;
+ this.next_out_index = outputOffset;
+ this.avail_out = outputCount;
+ return this.deflate(flushType);
+ }
+
+
+ // TODO: Delete this
+ public ZLibStatus inflateEnd()
+ {
+ throw new NotImplementedException();
+ }
+
+ public ZLibStatus inflate(byte[] bufer, int offset, int count, byte[] p1, int p2, int p3, FlushType flushType)
+ {
+ throw new NotImplementedException();
+ }
+
+ public ZLibStatus inflate(byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v13/Inflate.cs b/Renci.SshNet/Compression/v13/Inflate.cs
new file mode 100644
index 0000000..c05e2d8
--- /dev/null
+++ b/Renci.SshNet/Compression/v13/Inflate.cs
@@ -0,0 +1,524 @@
+using System;
+/*
+ * $Id: Inflate.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public enum InflateMode : int
+ {
+ ///
+ ///waiting for method byte
+ ///
+ METHOD = 0,
+ ///
+ /// waiting for flag byte
+ ///
+ FLAG = 1,
+ ///
+ /// four dictionary check bytes to go
+ ///
+ DICT4 = 2,
+ ///
+ /// three dictionary check bytes to go
+ ///
+ DICT3 = 3,
+ ///
+ /// two dictionary check bytes to go
+ ///
+ DICT2 = 4,
+ ///
+ /// one dictionary check byte to go
+ ///
+ DICT1 = 5,
+ ///
+ /// waiting for inflateSetDictionary
+ ///
+ DICT0 = 6,
+ ///
+ /// decompressing blocks
+ ///
+ BLOCKS = 7,
+ ///
+ /// four check bytes to go
+ ///
+ CHECK4 = 8,
+ ///
+ /// three check bytes to go
+ ///
+ CHECK3 = 9,
+ ///
+ /// two check bytes to go
+ ///
+ CHECK2 = 10,
+ ///
+ /// one check byte to go
+ ///
+ CHECK1 = 11,
+ ///
+ /// finished check, done
+ ///
+ DONE = 12,
+ ///
+ /// got an error--stay here
+ ///
+ BAD = 13
+ }
+
+ internal sealed class Inflate : ZStream, ICompressor
+ {
+ // preset dictionary flag in zlib header
+ private const int PRESET_DICT = 0x20;
+
+ private const int Z_DEFLATED = 8;
+
+ private static readonly byte[] mark = { (byte)0, (byte)0, (byte)0xff, (byte)0xff };
+
+ ///
+ /// The current inflate mode
+ ///
+ private InflateMode _mode;
+
+ ///
+ /// if FLAGS, method byte
+ ///
+ private int method;
+
+ ///
+ /// Computed check value
+ ///
+ private long[] _was = new long[1];
+
+ ///
+ /// The stream check value
+ ///
+ private long _need;
+
+ ///
+ /// if BAD, inflateSync's marker bytes count
+ ///
+ private int _marker;
+
+ // mode independent information
+ ///
+ /// Flag for no wrapper
+ ///
+ private int _nowrap;
+
+ ///
+ /// log2(window size) (8..15, defaults to 15)
+ ///
+ private int _wbits;
+
+ ///
+ /// Current inflate_blocks state
+ ///
+ private InflateBlocks _blocks;
+
+ public Inflate()
+ {
+ this.inflateInit();
+ }
+
+ public Inflate(bool nowrap)
+ {
+ this.inflateInit(nowrap);
+ }
+
+ private ZLibStatus InflateReset()
+ {
+ base.total_in = base.total_out = 0;
+ base.msg = null;
+ this._mode = this._nowrap != 0 ? InflateMode.BLOCKS : InflateMode.METHOD;
+ this._blocks.reset(this, null);
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus InflateEnd()
+ {
+ if (_blocks != null)
+ _blocks.free(this);
+ _blocks = null;
+ // ZFREE(z, z->state);
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus InflateInit(int w)
+ {
+ base.msg = null;
+ _blocks = null;
+
+ // handle undocumented nowrap option (no zlib header or check)
+ _nowrap = 0;
+ if (w < 0)
+ {
+ w = -w;
+ _nowrap = 1;
+ }
+
+ // set window size
+ if (w < 8 || w > 15)
+ {
+ InflateEnd();
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+ _wbits = w;
+
+ this._blocks = new InflateBlocks(this, this._nowrap != 0 ? null : this, 1 << w);
+
+ // reset state
+ InflateReset();
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus inflate(FlushType ff)
+ {
+ ZLibStatus r;
+ int b;
+
+ if (base.next_in == null)
+ return ZLibStatus.Z_STREAM_ERROR;
+ var f = ff == FlushType.Z_FINISH ? ZLibStatus.Z_BUF_ERROR : ZLibStatus.Z_OK;
+ r = ZLibStatus.Z_BUF_ERROR;
+ while (true)
+ {
+ //System.out.println("mode: "+this.mode);
+ switch (this._mode)
+ {
+ case InflateMode.METHOD:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ if (((this.method = base.next_in[base.next_in_index++]) & 0xf) != Z_DEFLATED)
+ {
+ this._mode = InflateMode.BAD;
+ base.msg = "unknown compression method";
+ this._marker = 5; // can't try inflateSync
+ break;
+ }
+ if ((this.method >> 4) + 8 > this._wbits)
+ {
+ this._mode = InflateMode.BAD;
+ base.msg = "invalid window size";
+ this._marker = 5; // can't try inflateSync
+ break;
+ }
+ this._mode = InflateMode.FLAG;
+ goto case InflateMode.FLAG;
+ case InflateMode.FLAG:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ b = (base.next_in[base.next_in_index++]) & 0xff;
+
+ if ((((this.method << 8) + b) % 31) != 0)
+ {
+ this._mode = InflateMode.BAD;
+ base.msg = "incorrect header check";
+ this._marker = 5; // can't try inflateSync
+ break;
+ }
+
+ if ((b & PRESET_DICT) == 0)
+ {
+ this._mode = InflateMode.BLOCKS;
+ break;
+ }
+ this._mode = InflateMode.DICT4;
+ goto case InflateMode.DICT4;
+ case InflateMode.DICT4:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need = ((base.next_in[base.next_in_index++] & 0xff) << 24) & 0xff000000L;
+ this._mode = InflateMode.DICT3;
+ goto case InflateMode.DICT3;
+ case InflateMode.DICT3:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += ((base.next_in[base.next_in_index++] & 0xff) << 16) & 0xff0000L;
+ this._mode = InflateMode.DICT2;
+ goto case InflateMode.DICT2;
+ case InflateMode.DICT2:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += ((base.next_in[base.next_in_index++] & 0xff) << 8) & 0xff00L;
+ this._mode = InflateMode.DICT1;
+ goto case InflateMode.DICT1;
+ case InflateMode.DICT1:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += (base.next_in[base.next_in_index++] & 0xffL);
+ base.adler = this._need;
+ this._mode = InflateMode.DICT0;
+ return ZLibStatus.Z_NEED_DICT;
+ case InflateMode.DICT0:
+ this._mode = InflateMode.BAD;
+ base.msg = "need dictionary";
+ this._marker = 0; // can try inflateSync
+ return ZLibStatus.Z_STREAM_ERROR;
+ case InflateMode.BLOCKS:
+
+ r = this._blocks.proc(this, r);
+ if (r == ZLibStatus.Z_DATA_ERROR)
+ {
+ this._mode = InflateMode.BAD;
+ this._marker = 0; // can try inflateSync
+ break;
+ }
+ if (r == ZLibStatus.Z_OK)
+ {
+ r = f;
+ }
+ if (r != ZLibStatus.Z_STREAM_END)
+ {
+ return r;
+ }
+ r = f;
+ this._blocks.reset(this, this._was);
+ if (this._nowrap != 0)
+ {
+ this._mode = InflateMode.DONE;
+ break;
+ }
+ this._mode = InflateMode.CHECK4;
+ goto case InflateMode.CHECK4;
+ case InflateMode.CHECK4:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need = ((base.next_in[base.next_in_index++] & 0xff) << 24) & 0xff000000L;
+ this._mode = InflateMode.CHECK3;
+ goto case InflateMode.CHECK3;
+ case InflateMode.CHECK3:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += ((base.next_in[base.next_in_index++] & 0xff) << 16) & 0xff0000L;
+ this._mode = InflateMode.CHECK2;
+ goto case InflateMode.CHECK2;
+ case InflateMode.CHECK2:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += ((base.next_in[base.next_in_index++] & 0xff) << 8) & 0xff00L;
+ this._mode = InflateMode.CHECK1;
+ goto case InflateMode.CHECK1;
+ case InflateMode.CHECK1:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += (base.next_in[base.next_in_index++] & 0xffL);
+
+ if (((int)(this._was[0])) != ((int)(this._need)))
+ {
+ this._mode = InflateMode.BAD;
+ base.msg = "incorrect data check";
+ this._marker = 5; // can't try inflateSync
+ break;
+ }
+
+ this._mode = InflateMode.DONE;
+ goto case InflateMode.DONE;
+ case InflateMode.DONE:
+ return ZLibStatus.Z_STREAM_END;
+ case InflateMode.BAD:
+ return ZLibStatus.Z_DATA_ERROR;
+ default:
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+ }
+ }
+
+ public ZLibStatus InflateSetDictionary(byte[] dictionary, int dictLength)
+ {
+ int index = 0;
+ int length = dictLength;
+ if (this._mode != InflateMode.DICT0)
+ return ZLibStatus.Z_STREAM_ERROR;
+
+ if (Adler32.adler32(1L, dictionary, 0, dictLength) != base.adler)
+ {
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+
+ base.adler = Adler32.adler32(0, null, 0, 0);
+
+ if (length >= (1 << this._wbits))
+ {
+ length = (1 << this._wbits) - 1;
+ index = dictLength - length;
+ }
+ this._blocks.set_dictionary(dictionary, index, length);
+ this._mode = InflateMode.BLOCKS;
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus InflateSync()
+ {
+ int n; // number of bytes to look at
+ int p; // pointer to bytes
+ int m; // number of marker bytes found in a row
+ long r, w; // temporaries to save total_in and total_out
+
+ // set up
+ if (this._mode != InflateMode.BAD)
+ {
+ this._mode = InflateMode.BAD;
+ this._marker = 0;
+ }
+ if ((n = base.avail_in) == 0)
+ return ZLibStatus.Z_BUF_ERROR;
+ p = base.next_in_index;
+ m = this._marker;
+
+ // search
+ while (n != 0 && m < 4)
+ {
+ if (base.next_in[p] == mark[m])
+ {
+ m++;
+ }
+ else if (base.next_in[p] != 0)
+ {
+ m = 0;
+ }
+ else
+ {
+ m = 4 - m;
+ }
+ p++; n--;
+ }
+
+ // restore
+ base.total_in += p - base.next_in_index;
+ base.next_in_index = p;
+ base.avail_in = n;
+ this._marker = m;
+
+ // return no joy or set up to restart on a new block
+ if (m != 4)
+ {
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ r = base.total_in; w = base.total_out;
+ InflateReset();
+ base.total_in = r; base.total_out = w;
+ this._mode = InflateMode.BLOCKS;
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus inflateInit()
+ {
+ return inflateInit(DEF_WBITS);
+ }
+ public ZLibStatus inflateInit(bool nowrap)
+ {
+ return inflateInit(DEF_WBITS, nowrap);
+ }
+ public ZLibStatus inflateInit(int w)
+ {
+ return inflateInit(w, false);
+ }
+
+ public ZLibStatus inflateInit(int w, bool nowrap)
+ {
+ return this.InflateInit(nowrap ? -w : w);
+ }
+
+ public ZLibStatus inflateEnd()
+ {
+ var ret = this.InflateEnd();
+ return ret;
+ }
+ public ZLibStatus inflateSync()
+ {
+ return this.InflateSync();
+ }
+
+ public ZLibStatus inflateSetDictionary(byte[] dictionary, int dictLength)
+ {
+ return this.InflateSetDictionary(dictionary, dictLength);
+ }
+
+ public ZLibStatus inflate(byte[] inputBufer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType)
+ {
+ this.next_in = inputBufer;
+ this.next_in_index = inputOffset;
+ this.avail_in = inputCount;
+ this.next_out = outputBuffer;
+ this.next_out_index = outputOffset;
+ this.avail_out = outputCount;
+ return this.inflate(flushType);
+ }
+
+ public ZLibStatus inflate(byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType)
+ {
+ this.next_out = outputBuffer;
+ this.next_out_index = outputOffset;
+ this.avail_out = outputCount;
+ return this.inflate(flushType);
+ }
+
+ // TODO: Dlete this
+ public ZLibStatus deflate(byte[] bufer, int offset, int count, byte[] p1, int p2, int p3, FlushType flushType)
+ {
+ throw new NotImplementedException();
+ }
+
+ public ZLibStatus deflateEnd()
+ {
+ throw new NotImplementedException();
+ }
+
+ public ZLibStatus deflate(byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v13/InflateBlocks.cs b/Renci.SshNet/Compression/v13/InflateBlocks.cs
new file mode 100644
index 0000000..609265f
--- /dev/null
+++ b/Renci.SshNet/Compression/v13/InflateBlocks.cs
@@ -0,0 +1,717 @@
+using System;
+/*
+ * $Id: InfBlocks.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public enum InflateBlockMode
+ {
+ ///
+ /// get type bits (3, including end bit)
+ ///
+ TYPE = 0,
+ ///
+ /// get lengths for stored
+ ///
+ LENS = 1,
+ ///
+ /// cessing stored block
+ ///
+ STORED = 2,
+ ///
+ /// get table lengths
+ ///
+ TABLE = 3,
+ ///
+ /// get bit lengths tree for a dynamic block
+ ///
+ BTREE = 4,
+ ///
+ /// get length, distance trees for a dynamic block
+ ///
+ DTREE = 5,
+ ///
+ /// processing fixed or dynamic block
+ ///
+ CODES = 6,
+ ///
+ /// output remaining window bytes
+ ///
+ DRY = 7,
+ ///
+ /// finished last block, done
+ ///
+ DONE = 8,
+ ///
+ /// ot a data error--stuck here
+ ///
+ BAD = 9
+ }
+
+ internal sealed class InflateBlocks : InflateCodes
+ {
+ private const int MANY = 1440;
+
+ // And'ing with mask[n] masks the lower n bits
+ private static readonly int[] inflate_mask = {
+ 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
+ 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
+ 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
+ 0x00007fff, 0x0000ffff
+ };
+
+ // Table for deflate from PKZIP's appnote.txt.
+ static readonly int[] border = { // Order of the bit length code lengths
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
+ };
+
+ internal InflateBlockMode mode; // current inflate_block mode
+
+ internal int left; // if STORED, bytes left to copy
+
+ internal int table; // table lengths (14 bits)
+ internal int index; // index into blens (or border)
+ internal int[] blens; // bit lengths of codes
+ internal int[] bb = new int[1]; // bit length tree depth
+ internal int[] tb = new int[1]; // bit length decoding tree
+
+ //internal InfCodes codes = new InfCodes(); // if CODES, current state
+
+ int last; // true if this block is the last block
+
+ // mode independent information
+ internal int bitk; // bits in bit buffer
+ internal int bitb; // bit buffer
+ internal int[] hufts; // single malloc for tree space
+ internal byte[] window; // sliding window
+ internal int end; // one byte after sliding window
+ internal int read; // window read pointer
+ internal int write; // window write pointer
+ internal Object checkfn; // check function
+ internal long check; // check on output
+
+ internal InflateTree inftree = new InflateTree();
+
+ internal InflateBlocks(ICompressor z, Object checkfn, int w)
+ {
+ hufts = new int[MANY * 3];
+ window = new byte[w];
+ end = w;
+ this.checkfn = checkfn;
+ mode = InflateBlockMode.TYPE;
+ reset(z, null);
+ }
+
+ internal void reset(ICompressor z, long[] c)
+ {
+ if (c != null) c[0] = check;
+ if (mode == InflateBlockMode.BTREE || mode == InflateBlockMode.DTREE)
+ {
+ }
+
+ mode = InflateBlockMode.TYPE;
+ bitk = 0;
+ bitb = 0;
+ read = write = 0;
+
+ if (checkfn != null)
+ z.adler = check = Adler32.adler32(0L, null, 0, 0);
+ }
+
+ internal ZLibStatus proc(ICompressor z, ZLibStatus r)
+ {
+ int t; // temporary storage
+ ZLibStatus tt;
+ int b; // bit buffer
+ int k; // bits in bit buffer
+ int p; // input data pointer
+ int n; // bytes available there
+ int q; // output window write pointer
+ int m;
+ { // bytes to end of window or read pointer
+
+ // copy input/output information to locals (UPDATE macro restores)
+ p = z.next_in_index; n = z.avail_in; b = bitb; k = bitk;
+ }
+ {
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+ }
+
+ // process input based on current state
+ while (true)
+ {
+ switch (mode)
+ {
+ case InflateBlockMode.TYPE:
+
+ while (k < (3))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+ t = (int)(b & 7);
+ last = t & 1;
+
+ switch (t >> 1)
+ {
+ case 0:
+ { // stored
+ b >>= (3); k -= (3);
+ }
+ t = k & 7;
+ { // go to byte boundary
+
+ b >>= (t); k -= (t);
+ }
+ mode = InflateBlockMode.LENS; // get length of stored block
+ break;
+ case 1:
+ { // fixed
+ int[] bl = new int[1];
+ int[] bd = new int[1];
+ int[][] tl = new int[1][];
+ int[][] td = new int[1][];
+
+ InflateTree.InflateTreesFixed(bl, bd, tl, td);
+ codesinit(bl[0], bd[0], tl[0], 0, td[0], 0);
+ }
+ {
+
+ b >>= (3); k -= (3);
+ }
+
+ mode = InflateBlockMode.CODES;
+ break;
+ case 2:
+ { // dynamic
+
+ b >>= (3); k -= (3);
+ }
+
+ mode = InflateBlockMode.TABLE;
+ break;
+ case 3:
+ { // illegal
+
+ b >>= (3); k -= (3);
+ }
+ mode = InflateBlockMode.BAD;
+ z.msg = "invalid block type";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ break;
+ case InflateBlockMode.LENS:
+
+ while (k < (32))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ if ((((~b) >> 16) & 0xffff) != (b & 0xffff))
+ {
+ mode = InflateBlockMode.BAD;
+ z.msg = "invalid stored block lengths";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ left = (b & 0xffff);
+ b = k = 0; // dump bits
+ mode = left != 0 ? InflateBlockMode.STORED : (last != 0 ? InflateBlockMode.DRY : InflateBlockMode.TYPE);
+ break;
+ case InflateBlockMode.STORED:
+ if (n == 0)
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+
+ if (m == 0)
+ {
+ if (q == end && read != 0)
+ {
+ q = 0; m = (int)(q < read ? read - q - 1 : end - q);
+ }
+ if (m == 0)
+ {
+ write = q;
+ r = inflate_flush(z, r);
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+ if (q == end && read != 0)
+ {
+ q = 0; m = (int)(q < read ? read - q - 1 : end - q);
+ }
+ if (m == 0)
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ }
+ }
+ r = ZLibStatus.Z_OK;
+
+ t = left;
+ if (t > n) t = n;
+ if (t > m) t = m;
+ System.Array.Copy(z.next_in, p, window, q, t);
+ p += t; n -= t;
+ q += t; m -= t;
+ if ((left -= t) != 0)
+ break;
+ mode = last != 0 ? InflateBlockMode.DRY : InflateBlockMode.TYPE;
+ break;
+ case InflateBlockMode.TABLE:
+
+ while (k < (14))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ table = t = (b & 0x3fff);
+ if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
+ {
+ mode = InflateBlockMode.BAD;
+ z.msg = "too many length or distance symbols";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
+ if (blens == null || blens.Length < t)
+ {
+ blens = new int[t];
+ }
+ else
+ {
+ for (int i = 0; i < t; i++) { blens[i] = 0; }
+ }
+ {
+
+ b >>= (14); k -= (14);
+ }
+
+ index = 0;
+ mode = InflateBlockMode.BTREE;
+ goto case InflateBlockMode.BTREE;
+ case InflateBlockMode.BTREE:
+ while (index < 4 + (table >> 10))
+ {
+ while (k < (3))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ blens[border[index++]] = b & 7;
+ {
+
+ b >>= (3); k -= (3);
+ }
+ }
+
+ while (index < 19)
+ {
+ blens[border[index++]] = 0;
+ }
+
+ bb[0] = 7;
+ tt = inftree.InflateTreesBits(blens, bb, tb, hufts, z);
+ if (tt != ZLibStatus.Z_OK)
+ {
+ r = tt;
+ if (r == ZLibStatus.Z_DATA_ERROR)
+ {
+ blens = null;
+ mode = InflateBlockMode.BAD;
+ }
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+
+ index = 0;
+ mode = InflateBlockMode.DTREE;
+ goto case InflateBlockMode.DTREE;
+ case InflateBlockMode.DTREE:
+ while (true)
+ {
+ t = table;
+ if (!(index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)))
+ {
+ break;
+ }
+
+ int i, j, c;
+
+ t = bb[0];
+
+ while (k < (t))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ if (tb[0] == -1)
+ {
+ //System.err.println("null...");
+ }
+
+ t = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 1];
+ c = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 2];
+
+ if (c < 16)
+ {
+ b >>= (t); k -= (t);
+ blens[index++] = c;
+ }
+ else
+ { // c == 16..18
+ i = c == 18 ? 7 : c - 14;
+ j = c == 18 ? 11 : 3;
+
+ while (k < (t + i))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ b >>= (t); k -= (t);
+
+ j += (b & inflate_mask[i]);
+
+ b >>= (i); k -= (i);
+
+ i = index;
+ t = table;
+ if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
+ (c == 16 && i < 1))
+ {
+ blens = null;
+ mode = InflateBlockMode.BAD;
+ z.msg = "invalid bit length repeat";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+
+ c = c == 16 ? blens[i - 1] : 0;
+ do
+ {
+ blens[i++] = c;
+ }
+ while (--j != 0);
+ index = i;
+ }
+ }
+
+ tb[0] = -1;
+ {
+ int[] bl = new int[1];
+ int[] bd = new int[1];
+ int[] tl = new int[1];
+ int[] td = new int[1];
+ bl[0] = 9; // must be <= 9 for lookahead assumptions
+ bd[0] = 6; // must be <= 9 for lookahead assumptions
+
+ t = table;
+ tt = inftree.InflateTreesDynamic(257 + (t & 0x1f),
+ 1 + ((t >> 5) & 0x1f),
+ blens, bl, bd, tl, td, hufts, z);
+
+ if (tt != ZLibStatus.Z_OK)
+ {
+ if (tt == ZLibStatus.Z_DATA_ERROR)
+ {
+ blens = null;
+ mode = InflateBlockMode.BAD;
+ }
+ r = tt;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ codesinit(bl[0], bd[0], hufts, tl[0], hufts, td[0]);
+ }
+ mode = InflateBlockMode.CODES;
+ goto case InflateBlockMode.CODES;
+ case InflateBlockMode.CODES:
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+
+ if ((r = codesproc(this, z, r)) != ZLibStatus.Z_STREAM_END)
+ {
+ return inflate_flush(z, r);
+ }
+ r = ZLibStatus.Z_OK;
+
+ p = z.next_in_index; n = z.avail_in; b = bitb; k = bitk;
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+
+ if (last == 0)
+ {
+ mode = InflateBlockMode.TYPE;
+ break;
+ }
+ mode = InflateBlockMode.DRY;
+ goto case InflateBlockMode.DRY;
+ case InflateBlockMode.DRY:
+ write = q;
+ r = inflate_flush(z, r);
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+ if (read != write)
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ mode = InflateBlockMode.DONE;
+ goto case InflateBlockMode.DONE;
+ case InflateBlockMode.DONE:
+ r = ZLibStatus.Z_STREAM_END;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ case InflateBlockMode.BAD:
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+
+ default:
+ r = ZLibStatus.Z_STREAM_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ }
+ }
+
+ internal void free(ICompressor z)
+ {
+ reset(z, null);
+ window = null;
+ hufts = null;
+ //ZFREE(z, s);
+ }
+
+ internal void set_dictionary(byte[] d, int start, int n)
+ {
+ System.Array.Copy(d, start, window, 0, n);
+ read = write = n;
+ }
+
+ // Returns true if inflate is currently at the end of a block generated
+ // by Z_SYNC_FLUSH or FlushType.Z_FULL_FLUSH.
+ internal ZLibStatus sync_point()
+ {
+ return mode == InflateBlockMode.LENS ? ZLibStatus.Z_STREAM_END : ZLibStatus.Z_OK;
+ }
+
+ // copy as much as possible from the sliding window to the output area
+ internal ZLibStatus inflate_flush(ICompressor z, ZLibStatus r)
+ {
+ int n;
+ int p;
+ int q;
+
+ // local copies of source and destination pointers
+ p = z.next_out_index;
+ q = read;
+
+ // compute number of bytes to copy as far as end of window
+ n = (int)((q <= write ? write : end) - q);
+ if (n > z.avail_out) n = z.avail_out;
+ if (n != 0 && r == ZLibStatus.Z_BUF_ERROR) r = ZLibStatus.Z_OK;
+
+ // update counters
+ z.avail_out -= n;
+ z.total_out += n;
+
+ // update check information
+ if (checkfn != null)
+ z.adler = check = Adler32.adler32(check, window, q, n);
+
+ // copy as far as end of window
+ System.Array.Copy(window, q, z.next_out, p, n);
+ p += n;
+ q += n;
+
+ // see if more to copy at beginning of window
+ if (q == end)
+ {
+ // wrap pointers
+ q = 0;
+ if (write == end)
+ write = 0;
+
+ // compute bytes to copy
+ n = write - q;
+ if (n > z.avail_out) n = z.avail_out;
+ if (n != 0 && r == ZLibStatus.Z_BUF_ERROR) r = ZLibStatus.Z_OK;
+
+ // update counters
+ z.avail_out -= n;
+ z.total_out += n;
+
+ // update check information
+ if (checkfn != null)
+ z.adler = check = Adler32.adler32(check, window, q, n);
+
+ // copy
+ System.Array.Copy(window, q, z.next_out, p, n);
+ p += n;
+ q += n;
+ }
+
+ // update pointers
+ z.next_out_index = p;
+ read = q;
+
+ // done
+ return r;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v13/InflateCodes.cs b/Renci.SshNet/Compression/v13/InflateCodes.cs
new file mode 100644
index 0000000..5bc7260
--- /dev/null
+++ b/Renci.SshNet/Compression/v13/InflateCodes.cs
@@ -0,0 +1,685 @@
+using System;
+/*
+ * $Id: InfCodes.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public enum InflateCodeMode
+ {
+ ///
+ /// x: set up for InflateCodeMode.LEN
+ ///
+ START = 0,
+ ///
+ /// i: get length/literal/eob next
+ ///
+ LEN = 1,
+ ///
+ /// i: getting length extra (have base)
+ ///
+ LENEXT = 2,
+ ///
+ /// i: get distance next
+ ///
+ DIST = 3,
+ ///
+ /// : getting distance extra
+ ///
+ DISTEXT = 4,
+ ///
+ /// o: copying bytes in window, waiting for space
+ ///
+ COPY = 5,
+ ///
+ /// o: got literal, waiting for output space
+ ///
+ LIT = 6,
+ ///
+ /// o: got eob, possibly still output waiting
+ ///
+ WASH = 7,
+ ///
+ /// x: got eob and all data flushed
+ ///
+ END = 8,
+ ///
+ /// x: got error
+ ///
+ BADCODE = 9
+ }
+
+ internal abstract class InflateCodes// : ZStream
+ {
+ private static readonly int[] inflate_mask = {
+ 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
+ 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
+ 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
+ 0x00007fff, 0x0000ffff
+ };
+
+ InflateCodeMode mode; // current inflate_codes mode
+
+ // mode dependent information
+ int len;
+
+ int[] tree; // pointer into tree
+ int tree_index = 0;
+ int need; // bits needed
+
+ int lit;
+
+ // if EXT or COPY, where and how much
+ int get; // bits to get for extra
+ int dist; // distance back to copy from
+
+ byte lbits; // ltree bits decoded per branch
+ byte dbits; // dtree bits decoder per branch
+ int[] ltree; // literal/length/eob tree
+ int ltree_index; // literal/length/eob tree
+ int[] dtree; // distance tree
+ int dtree_index; // distance tree
+
+ internal InflateCodes()
+ {
+ }
+ internal void codesinit(int bl, int bd,
+ int[] tl, int tl_index,
+ int[] td, int td_index)
+ {
+ mode = InflateCodeMode.START;
+ lbits = (byte)bl;
+ dbits = (byte)bd;
+ ltree = tl;
+ ltree_index = tl_index;
+ dtree = td;
+ dtree_index = td_index;
+ tree = null;
+ }
+
+ internal ZLibStatus codesproc(InflateBlocks s, ICompressor z, ZLibStatus r)
+ {
+ int j; // temporary storage
+ int tindex; // temporary pointer
+ int e; // extra bits or operation
+ int b = 0; // bit buffer
+ int k = 0; // bits in bit buffer
+ int p = 0; // input data pointer
+ int n; // bytes available there
+ int q; // output window write pointer
+ int m; // bytes to end of window or read pointer
+ int f; // pointer to copy strings from
+
+ // copy input/output information to locals (UPDATE macro restores)
+ p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk;
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ // process input and output based on current state
+ while (true)
+ {
+ switch (mode)
+ {
+ // waiting for "i:"=input, "o:"=output, "x:"=nothing
+ case InflateCodeMode.START: // x: set up for LEN
+ if (m >= 258 && n >= 10)
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ r = inflate_fast(lbits, dbits,
+ ltree, ltree_index,
+ dtree, dtree_index,
+ s, z);
+
+ p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk;
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (r != ZLibStatus.Z_OK)
+ {
+ mode = r == ZLibStatus.Z_STREAM_END ? InflateCodeMode.WASH : InflateCodeMode.BADCODE;
+ break;
+ }
+ }
+ need = lbits;
+ tree = ltree;
+ tree_index = ltree_index;
+
+ mode = InflateCodeMode.LEN;
+ goto case InflateCodeMode.LEN;
+ case InflateCodeMode.LEN: // i: get length/literal/eob next
+ j = need;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ tindex = (tree_index + (b & inflate_mask[j])) * 3;
+
+ b >>= (tree[tindex + 1]);
+ k -= (tree[tindex + 1]);
+
+ e = tree[tindex];
+
+ if (e == 0)
+ { // literal
+ lit = tree[tindex + 2];
+ mode = InflateCodeMode.LIT;
+ break;
+ }
+ if ((e & 16) != 0)
+ { // length
+ get = e & 15;
+ len = tree[tindex + 2];
+ mode = InflateCodeMode.LENEXT;
+ break;
+ }
+ if ((e & 64) == 0)
+ { // next table
+ need = e;
+ tree_index = tindex / 3 + tree[tindex + 2];
+ break;
+ }
+ if ((e & 32) != 0)
+ { // end of block
+ mode = InflateCodeMode.WASH;
+ break;
+ }
+ mode = InflateCodeMode.BADCODE; // invalid code
+ z.msg = "invalid literal/length code";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ case InflateCodeMode.LENEXT: // i: getting length extra (have base)
+ j = get;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--; b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ len += (b & inflate_mask[j]);
+
+ b >>= j;
+ k -= j;
+
+ need = dbits;
+ tree = dtree;
+ tree_index = dtree_index;
+ mode = InflateCodeMode.DIST;
+ goto case InflateCodeMode.DIST;
+ case InflateCodeMode.DIST: // i: get distance next
+ j = need;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--; b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ tindex = (tree_index + (b & inflate_mask[j])) * 3;
+
+ b >>= tree[tindex + 1];
+ k -= tree[tindex + 1];
+
+ e = (tree[tindex]);
+ if ((e & 16) != 0)
+ { // distance
+ get = e & 15;
+ dist = tree[tindex + 2];
+ mode = InflateCodeMode.DISTEXT;
+ break;
+ }
+ if ((e & 64) == 0)
+ { // next table
+ need = e;
+ tree_index = tindex / 3 + tree[tindex + 2];
+ break;
+ }
+ mode = InflateCodeMode.BADCODE; // invalid code
+ z.msg = "invalid distance code";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ case InflateCodeMode.DISTEXT: // i: getting distance extra
+ j = get;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--; b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ dist += (b & inflate_mask[j]);
+
+ b >>= j;
+ k -= j;
+
+ mode = InflateCodeMode.COPY;
+ goto case InflateCodeMode.COPY;
+ case InflateCodeMode.COPY: // o: copying bytes in window, waiting for space
+ f = q - dist;
+ while (f < 0)
+ { // modulo window size-"while" instead
+ f += s.end; // of "if" handles invalid distances
+ }
+ while (len != 0)
+ {
+
+ if (m == 0)
+ {
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+ if (m == 0)
+ {
+ s.write = q; r = s.inflate_flush(z, r);
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+
+ if (m == 0)
+ {
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ }
+ }
+
+ s.window[q++] = s.window[f++]; m--;
+
+ if (f == s.end)
+ f = 0;
+ len--;
+ }
+ mode = InflateCodeMode.START;
+ break;
+ case InflateCodeMode.LIT: // o: got literal, waiting for output space
+ if (m == 0)
+ {
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+ if (m == 0)
+ {
+ s.write = q; r = s.inflate_flush(z, r);
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+ if (m == 0)
+ {
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ }
+ }
+ r = ZLibStatus.Z_OK;
+
+ s.window[q++] = (byte)lit; m--;
+
+ mode = InflateCodeMode.START;
+ break;
+ case InflateCodeMode.WASH: // o: got eob, possibly more output
+ if (k > 7)
+ { // return unused byte, if any
+ k -= 8;
+ n++;
+ p--; // can always return one
+ }
+
+ s.write = q; r = s.inflate_flush(z, r);
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (s.read != s.write)
+ {
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ mode = InflateCodeMode.END;
+ goto case InflateCodeMode.END;
+ case InflateCodeMode.END:
+ r = ZLibStatus.Z_STREAM_END;
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ case InflateCodeMode.BADCODE: // x: got error
+
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ default:
+ r = ZLibStatus.Z_STREAM_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ }
+ }
+
+ // Called with number of bytes left to write in window at least 258
+ // (the maximum string length) and number of input bytes available
+ // at least ten. The ten bytes are six bytes for the longest length/
+ // distance pair plus four bytes for overloading the bit buffer.
+
+ internal ZLibStatus inflate_fast(int bl, int bd,
+ int[] tl, int tl_index,
+ int[] td, int td_index,
+ InflateBlocks s, ICompressor z)
+ {
+ int t; // temporary pointer
+ int[] tp; // temporary pointer
+ int tp_index; // temporary pointer
+ int e; // extra bits or operation
+ int b; // bit buffer
+ int k; // bits in bit buffer
+ int p; // input data pointer
+ int n; // bytes available there
+ int q; // output window write pointer
+ int m; // bytes to end of window or read pointer
+ int ml; // mask for literal/length tree
+ int md; // mask for distance tree
+ int c; // bytes to copy
+ int d; // distance back to copy from
+ int r; // copy source pointer
+
+ int tp_index_t_3; // (tp_index+t)*3
+
+ // load input, output, bit values
+ p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk;
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ // initialize masks
+ ml = inflate_mask[bl];
+ md = inflate_mask[bd];
+
+ // do until not enough input or output space for fast loop
+ do
+ { // assume called with m >= 258 && n >= 10
+ // get literal/length code
+ while (k < (20))
+ { // max bits for literal/length code
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k; k += 8;
+ }
+
+ t = b & ml;
+ tp = tl;
+ tp_index = tl_index;
+ tp_index_t_3 = (tp_index + t) * 3;
+ if ((e = tp[tp_index_t_3]) == 0)
+ {
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ s.window[q++] = (byte)tp[tp_index_t_3 + 2];
+ m--;
+ continue;
+ }
+ do
+ {
+
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ if ((e & 16) != 0)
+ {
+ e &= 15;
+ c = tp[tp_index_t_3 + 2] + ((int)b & inflate_mask[e]);
+
+ b >>= e; k -= e;
+
+ // decode distance base of block to copy
+ while (k < (15))
+ { // max bits for distance code
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k; k += 8;
+ }
+
+ t = b & md;
+ tp = td;
+ tp_index = td_index;
+ tp_index_t_3 = (tp_index + t) * 3;
+ e = tp[tp_index_t_3];
+
+ do
+ {
+
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ if ((e & 16) != 0)
+ {
+ // get extra bits to add to distance base
+ e &= 15;
+ while (k < (e))
+ { // get extra bits (up to 13)
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k; k += 8;
+ }
+
+ d = tp[tp_index_t_3 + 2] + (b & inflate_mask[e]);
+
+ b >>= (e); k -= (e);
+
+ // do the copy
+ m -= c;
+ if (q >= d)
+ { // offset before dest
+ // just copy
+ r = q - d;
+ if (q - r > 0 && 2 > (q - r))
+ {
+ s.window[q++] = s.window[r++]; // minimum count is three,
+ s.window[q++] = s.window[r++]; // so unroll loop a little
+ c -= 2;
+ }
+ else
+ {
+ System.Array.Copy(s.window, r, s.window, q, 2);
+ q += 2; r += 2; c -= 2;
+ }
+ }
+ else
+ { // else offset after destination
+ r = q - d;
+ do
+ {
+ r += s.end; // force pointer in window
+ } while (r < 0); // covers invalid distances
+ e = s.end - r;
+ if (c > e)
+ { // if source crosses,
+ c -= e; // wrapped copy
+ if (q - r > 0 && e > (q - r))
+ {
+ do { s.window[q++] = s.window[r++]; }
+ while (--e != 0);
+ }
+ else
+ {
+ System.Array.Copy(s.window, r, s.window, q, e);
+ q += e; r += e; e = 0;
+ }
+ r = 0; // copy rest from start of window
+ }
+
+ }
+
+ // copy all or what's left
+ if (q - r > 0 && c > (q - r))
+ {
+ do { s.window[q++] = s.window[r++]; }
+ while (--c != 0);
+ }
+ else
+ {
+ System.Array.Copy(s.window, r, s.window, q, c);
+ q += c; r += c; c = 0;
+ }
+ break;
+ }
+ else if ((e & 64) == 0)
+ {
+ t += tp[tp_index_t_3 + 2];
+ t += (b & inflate_mask[e]);
+ tp_index_t_3 = (tp_index + t) * 3;
+ e = tp[tp_index_t_3];
+ }
+ else
+ {
+ z.msg = "invalid distance code";
+
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ }
+ while (true);
+ break;
+ }
+
+ if ((e & 64) == 0)
+ {
+ t += tp[tp_index_t_3 + 2];
+ t += (b & inflate_mask[e]);
+ tp_index_t_3 = (tp_index + t) * 3;
+ if ((e = tp[tp_index_t_3]) == 0)
+ {
+
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ s.window[q++] = (byte)tp[tp_index_t_3 + 2];
+ m--;
+ break;
+ }
+ }
+ else if ((e & 32) != 0)
+ {
+
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_STREAM_END;
+ }
+ else
+ {
+ z.msg = "invalid literal/length code";
+
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ }
+ while (true);
+ }
+ while (m >= 258 && n >= 10);
+
+ // not enough input or output--restore pointers and return
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_OK;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v13/InflateTree.cs b/Renci.SshNet/Compression/v13/InflateTree.cs
new file mode 100644
index 0000000..c8a3dbf
--- /dev/null
+++ b/Renci.SshNet/Compression/v13/InflateTree.cs
@@ -0,0 +1,554 @@
+using System;
+/*
+ * $Id: InfTree.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ internal sealed class InflateTree
+ {
+ private const int MANY = 1440;
+
+ private const int fixed_bl = 9;
+ private const int fixed_bd = 5;
+
+ static readonly int[] fixed_tl = {
+ 96,7,256, 0,8,80, 0,8,16, 84,8,115,
+ 82,7,31, 0,8,112, 0,8,48, 0,9,192,
+ 80,7,10, 0,8,96, 0,8,32, 0,9,160,
+ 0,8,0, 0,8,128, 0,8,64, 0,9,224,
+ 80,7,6, 0,8,88, 0,8,24, 0,9,144,
+ 83,7,59, 0,8,120, 0,8,56, 0,9,208,
+ 81,7,17, 0,8,104, 0,8,40, 0,9,176,
+ 0,8,8, 0,8,136, 0,8,72, 0,9,240,
+ 80,7,4, 0,8,84, 0,8,20, 85,8,227,
+ 83,7,43, 0,8,116, 0,8,52, 0,9,200,
+ 81,7,13, 0,8,100, 0,8,36, 0,9,168,
+ 0,8,4, 0,8,132, 0,8,68, 0,9,232,
+ 80,7,8, 0,8,92, 0,8,28, 0,9,152,
+ 84,7,83, 0,8,124, 0,8,60, 0,9,216,
+ 82,7,23, 0,8,108, 0,8,44, 0,9,184,
+ 0,8,12, 0,8,140, 0,8,76, 0,9,248,
+ 80,7,3, 0,8,82, 0,8,18, 85,8,163,
+ 83,7,35, 0,8,114, 0,8,50, 0,9,196,
+ 81,7,11, 0,8,98, 0,8,34, 0,9,164,
+ 0,8,2, 0,8,130, 0,8,66, 0,9,228,
+ 80,7,7, 0,8,90, 0,8,26, 0,9,148,
+ 84,7,67, 0,8,122, 0,8,58, 0,9,212,
+ 82,7,19, 0,8,106, 0,8,42, 0,9,180,
+ 0,8,10, 0,8,138, 0,8,74, 0,9,244,
+ 80,7,5, 0,8,86, 0,8,22, 192,8,0,
+ 83,7,51, 0,8,118, 0,8,54, 0,9,204,
+ 81,7,15, 0,8,102, 0,8,38, 0,9,172,
+ 0,8,6, 0,8,134, 0,8,70, 0,9,236,
+ 80,7,9, 0,8,94, 0,8,30, 0,9,156,
+ 84,7,99, 0,8,126, 0,8,62, 0,9,220,
+ 82,7,27, 0,8,110, 0,8,46, 0,9,188,
+ 0,8,14, 0,8,142, 0,8,78, 0,9,252,
+ 96,7,256, 0,8,81, 0,8,17, 85,8,131,
+ 82,7,31, 0,8,113, 0,8,49, 0,9,194,
+ 80,7,10, 0,8,97, 0,8,33, 0,9,162,
+ 0,8,1, 0,8,129, 0,8,65, 0,9,226,
+ 80,7,6, 0,8,89, 0,8,25, 0,9,146,
+ 83,7,59, 0,8,121, 0,8,57, 0,9,210,
+ 81,7,17, 0,8,105, 0,8,41, 0,9,178,
+ 0,8,9, 0,8,137, 0,8,73, 0,9,242,
+ 80,7,4, 0,8,85, 0,8,21, 80,8,258,
+ 83,7,43, 0,8,117, 0,8,53, 0,9,202,
+ 81,7,13, 0,8,101, 0,8,37, 0,9,170,
+ 0,8,5, 0,8,133, 0,8,69, 0,9,234,
+ 80,7,8, 0,8,93, 0,8,29, 0,9,154,
+ 84,7,83, 0,8,125, 0,8,61, 0,9,218,
+ 82,7,23, 0,8,109, 0,8,45, 0,9,186,
+ 0,8,13, 0,8,141, 0,8,77, 0,9,250,
+ 80,7,3, 0,8,83, 0,8,19, 85,8,195,
+ 83,7,35, 0,8,115, 0,8,51, 0,9,198,
+ 81,7,11, 0,8,99, 0,8,35, 0,9,166,
+ 0,8,3, 0,8,131, 0,8,67, 0,9,230,
+ 80,7,7, 0,8,91, 0,8,27, 0,9,150,
+ 84,7,67, 0,8,123, 0,8,59, 0,9,214,
+ 82,7,19, 0,8,107, 0,8,43, 0,9,182,
+ 0,8,11, 0,8,139, 0,8,75, 0,9,246,
+ 80,7,5, 0,8,87, 0,8,23, 192,8,0,
+ 83,7,51, 0,8,119, 0,8,55, 0,9,206,
+ 81,7,15, 0,8,103, 0,8,39, 0,9,174,
+ 0,8,7, 0,8,135, 0,8,71, 0,9,238,
+ 80,7,9, 0,8,95, 0,8,31, 0,9,158,
+ 84,7,99, 0,8,127, 0,8,63, 0,9,222,
+ 82,7,27, 0,8,111, 0,8,47, 0,9,190,
+ 0,8,15, 0,8,143, 0,8,79, 0,9,254,
+ 96,7,256, 0,8,80, 0,8,16, 84,8,115,
+ 82,7,31, 0,8,112, 0,8,48, 0,9,193,
+
+ 80,7,10, 0,8,96, 0,8,32, 0,9,161,
+ 0,8,0, 0,8,128, 0,8,64, 0,9,225,
+ 80,7,6, 0,8,88, 0,8,24, 0,9,145,
+ 83,7,59, 0,8,120, 0,8,56, 0,9,209,
+ 81,7,17, 0,8,104, 0,8,40, 0,9,177,
+ 0,8,8, 0,8,136, 0,8,72, 0,9,241,
+ 80,7,4, 0,8,84, 0,8,20, 85,8,227,
+ 83,7,43, 0,8,116, 0,8,52, 0,9,201,
+ 81,7,13, 0,8,100, 0,8,36, 0,9,169,
+ 0,8,4, 0,8,132, 0,8,68, 0,9,233,
+ 80,7,8, 0,8,92, 0,8,28, 0,9,153,
+ 84,7,83, 0,8,124, 0,8,60, 0,9,217,
+ 82,7,23, 0,8,108, 0,8,44, 0,9,185,
+ 0,8,12, 0,8,140, 0,8,76, 0,9,249,
+ 80,7,3, 0,8,82, 0,8,18, 85,8,163,
+ 83,7,35, 0,8,114, 0,8,50, 0,9,197,
+ 81,7,11, 0,8,98, 0,8,34, 0,9,165,
+ 0,8,2, 0,8,130, 0,8,66, 0,9,229,
+ 80,7,7, 0,8,90, 0,8,26, 0,9,149,
+ 84,7,67, 0,8,122, 0,8,58, 0,9,213,
+ 82,7,19, 0,8,106, 0,8,42, 0,9,181,
+ 0,8,10, 0,8,138, 0,8,74, 0,9,245,
+ 80,7,5, 0,8,86, 0,8,22, 192,8,0,
+ 83,7,51, 0,8,118, 0,8,54, 0,9,205,
+ 81,7,15, 0,8,102, 0,8,38, 0,9,173,
+ 0,8,6, 0,8,134, 0,8,70, 0,9,237,
+ 80,7,9, 0,8,94, 0,8,30, 0,9,157,
+ 84,7,99, 0,8,126, 0,8,62, 0,9,221,
+ 82,7,27, 0,8,110, 0,8,46, 0,9,189,
+ 0,8,14, 0,8,142, 0,8,78, 0,9,253,
+ 96,7,256, 0,8,81, 0,8,17, 85,8,131,
+ 82,7,31, 0,8,113, 0,8,49, 0,9,195,
+ 80,7,10, 0,8,97, 0,8,33, 0,9,163,
+ 0,8,1, 0,8,129, 0,8,65, 0,9,227,
+ 80,7,6, 0,8,89, 0,8,25, 0,9,147,
+ 83,7,59, 0,8,121, 0,8,57, 0,9,211,
+ 81,7,17, 0,8,105, 0,8,41, 0,9,179,
+ 0,8,9, 0,8,137, 0,8,73, 0,9,243,
+ 80,7,4, 0,8,85, 0,8,21, 80,8,258,
+ 83,7,43, 0,8,117, 0,8,53, 0,9,203,
+ 81,7,13, 0,8,101, 0,8,37, 0,9,171,
+ 0,8,5, 0,8,133, 0,8,69, 0,9,235,
+ 80,7,8, 0,8,93, 0,8,29, 0,9,155,
+ 84,7,83, 0,8,125, 0,8,61, 0,9,219,
+ 82,7,23, 0,8,109, 0,8,45, 0,9,187,
+ 0,8,13, 0,8,141, 0,8,77, 0,9,251,
+ 80,7,3, 0,8,83, 0,8,19, 85,8,195,
+ 83,7,35, 0,8,115, 0,8,51, 0,9,199,
+ 81,7,11, 0,8,99, 0,8,35, 0,9,167,
+ 0,8,3, 0,8,131, 0,8,67, 0,9,231,
+ 80,7,7, 0,8,91, 0,8,27, 0,9,151,
+ 84,7,67, 0,8,123, 0,8,59, 0,9,215,
+ 82,7,19, 0,8,107, 0,8,43, 0,9,183,
+ 0,8,11, 0,8,139, 0,8,75, 0,9,247,
+ 80,7,5, 0,8,87, 0,8,23, 192,8,0,
+ 83,7,51, 0,8,119, 0,8,55, 0,9,207,
+ 81,7,15, 0,8,103, 0,8,39, 0,9,175,
+ 0,8,7, 0,8,135, 0,8,71, 0,9,239,
+ 80,7,9, 0,8,95, 0,8,31, 0,9,159,
+ 84,7,99, 0,8,127, 0,8,63, 0,9,223,
+ 82,7,27, 0,8,111, 0,8,47, 0,9,191,
+ 0,8,15, 0,8,143, 0,8,79, 0,9,255
+ };
+ static readonly int[] fixed_td = {
+ 80,5,1, 87,5,257, 83,5,17, 91,5,4097,
+ 81,5,5, 89,5,1025, 85,5,65, 93,5,16385,
+ 80,5,3, 88,5,513, 84,5,33, 92,5,8193,
+ 82,5,9, 90,5,2049, 86,5,129, 192,5,24577,
+ 80,5,2, 87,5,385, 83,5,25, 91,5,6145,
+ 81,5,7, 89,5,1537, 85,5,97, 93,5,24577,
+ 80,5,4, 88,5,769, 84,5,49, 92,5,12289,
+ 82,5,13, 90,5,3073, 86,5,193, 192,5,24577
+ };
+
+ // Tables for deflate from PKZIP's appnote.txt.
+ static readonly int[] cplens = { // Copy lengths for literal codes 257..285
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
+ };
+
+ // see note #13 above about 258
+ static readonly int[] cplext = { // Extra bits for literal codes 257..285
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+ 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112 // 112==invalid
+ };
+
+ static readonly int[] cpdist = { // Copy offsets for distance codes 0..29
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+ 8193, 12289, 16385, 24577
+ };
+
+ static readonly int[] cpdext = { // Extra bits for distance codes
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+ 12, 12, 13, 13};
+
+ // If BMAX needs to be larger than 16, then h and x[] should be uLong.
+ const int BMAX = 15; // maximum bit length of any code
+
+ int[] hn = null; // hufts used in space
+ int[] v = null; // work area for huft_build
+ int[] c = null; // bit length count table
+ int[] r = null; // table entry for structure assignment
+ int[] u = null; // table stack
+ int[] x = null; // bit offsets, then code stack
+
+ private ZLibStatus HuftBuild(int[] b, // code lengths in bits (all assumed <= BMAX)
+ int bindex,
+ int n, // number of codes (assumed <= 288)
+ int s, // number of simple-valued codes (0..s-1)
+ int[] d, // list of base values for non-simple codes
+ int[] e, // list of extra bits for non-simple codes
+ int[] t, // result: starting table
+ int[] m, // maximum lookup bits, returns actual
+ int[] hp,// space for trees
+ int[] hn,// hufts used in space
+ int[] v // working area: values in order of bit length
+ )
+ {
+ // Given a list of code lengths and a maximum table size, make a set of
+ // tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR
+ // if the given code set is incomplete (the tables are still built in this
+ // case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of
+ // lengths), or Z_MEM_ERROR if not enough memory.
+
+ int a; // counter for codes of length k
+ int f; // i repeats in table every f entries
+ int g; // maximum code length
+ int h; // table level
+ int i; // counter, current code
+ int j; // counter
+ int k; // number of bits in current code
+ int l; // bits per table (returned in m)
+ int mask; // (1 << w) - 1, to avoid cc -O bug on HP
+ int p; // pointer into c[], b[], or v[]
+ int q; // points to current table
+ int w; // bits before this table == (l * h)
+ int xp; // pointer into x
+ int y; // number of dummy codes added
+ int z; // number of entries in current table
+
+ // Generate counts for each bit length
+
+ p = 0; i = n;
+ do
+ {
+ c[b[bindex + p]]++; p++; i--; // assume all entries <= BMAX
+ } while (i != 0);
+
+ if (c[0] == n)
+ { // null input--all zero length codes
+ t[0] = -1;
+ m[0] = 0;
+ return ZLibStatus.Z_OK;
+ }
+
+ // Find minimum and maximum length, bound *m by those
+ l = m[0];
+ for (j = 1; j <= BMAX; j++)
+ if (c[j] != 0) break;
+ k = j; // minimum code length
+ if (l < j)
+ {
+ l = j;
+ }
+ for (i = BMAX; i != 0; i--)
+ {
+ if (c[i] != 0) break;
+ }
+ g = i; // maximum code length
+ if (l > i)
+ {
+ l = i;
+ }
+ m[0] = l;
+
+ // Adjust last length count to fill out codes, if needed
+ for (y = 1 << j; j < i; j++, y <<= 1)
+ {
+ if ((y -= c[j]) < 0)
+ {
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ }
+ if ((y -= c[i]) < 0)
+ {
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ c[i] += y;
+
+ // Generate starting offsets into the value table for each length
+ x[1] = j = 0;
+ p = 1; xp = 2;
+ while (--i != 0)
+ { // note that i == g from above
+ x[xp] = (j += c[p]);
+ xp++;
+ p++;
+ }
+
+ // Make a table of values in order of bit lengths
+ i = 0; p = 0;
+ do
+ {
+ if ((j = b[bindex + p]) != 0)
+ {
+ v[x[j]++] = i;
+ }
+ p++;
+ }
+ while (++i < n);
+ n = x[g]; // set n to length of v
+
+ // Generate the Huffman codes and for each, make the table entries
+ x[0] = i = 0; // first Huffman code is zero
+ p = 0; // grab values in bit order
+ h = -1; // no tables yet--level -1
+ w = -l; // bits decoded == (l * h)
+ u[0] = 0; // just to keep compilers happy
+ q = 0; // ditto
+ z = 0; // ditto
+
+ // go through the bit lengths (k already is bits in shortest code)
+ for (; k <= g; k++)
+ {
+ a = c[k];
+ while (a-- != 0)
+ {
+ // here i is the Huffman code of length k bits for value *p
+ // make tables up to required level
+ while (k > w + l)
+ {
+ h++;
+ w += l; // previous table always l bits
+ // compute minimum size table less than or equal to l bits
+ z = g - w;
+ z = (z > l) ? l : z; // table size upper limit
+ if ((f = 1 << (j = k - w)) > a + 1)
+ { // try a k-w bit table
+ // too few codes for k-w bit table
+ f -= a + 1; // deduct codes from patterns left
+ xp = k;
+ if (j < z)
+ {
+ while (++j < z)
+ { // try smaller tables up to z bits
+ if ((f <<= 1) <= c[++xp])
+ break; // enough codes to use up j bits
+ f -= c[xp]; // else deduct codes from patterns
+ }
+ }
+ }
+ z = 1 << j; // table entries for j-bit table
+
+ // allocate new table
+ if (hn[0] + z > MANY)
+ { // (note: doesn't matter for fixed)
+ return ZLibStatus.Z_DATA_ERROR; // overflow of MANY
+ }
+ u[h] = q = /*hp+*/ hn[0]; // DEBUG
+ hn[0] += z;
+
+ // connect to last table, if there is one
+ if (h != 0)
+ {
+ x[h] = i; // save pattern for backing up
+ r[0] = (byte)j; // bits in this table
+ r[1] = (byte)l; // bits to dump before this table
+ j = i >> (w - l);
+ r[2] = (int)(q - u[h - 1] - j); // offset to this table
+ System.Array.Copy(r, 0, hp, (u[h - 1] + j) * 3, 3); // connect to last table
+ }
+ else
+ {
+ t[0] = q; // first table is returned result
+ }
+ }
+
+ // set up table entry in r
+ r[1] = (byte)(k - w);
+ if (p >= n)
+ {
+ r[0] = 128 + 64; // out of values--invalid code
+ }
+ else if (v[p] < s)
+ {
+ r[0] = (byte)(v[p] < 256 ? 0 : 32 + 64); // 256 is end-of-block
+ r[2] = v[p++]; // simple code is just the value
+ }
+ else
+ {
+ r[0] = (byte)(e[v[p] - s] + 16 + 64); // non-simple--look up in lists
+ r[2] = d[v[p++] - s];
+ }
+
+ // fill code-like entries with r
+ f = 1 << (k - w);
+ for (j = i >> w; j < z; j += f)
+ {
+ System.Array.Copy(r, 0, hp, (q + j) * 3, 3);
+ }
+
+ // backwards increment the k-bit code i
+ for (j = 1 << (k - 1); (i & j) != 0; j >>= 1)
+ {
+ i ^= j;
+ }
+ i ^= j;
+
+ // backup over finished tables
+ mask = (1 << w) - 1; // needed on HP, cc -O bug
+ while ((i & mask) != x[h])
+ {
+ h--; // don't need to update q
+ w -= l;
+ mask = (1 << w) - 1;
+ }
+ }
+ }
+ // Return Z_BUF_ERROR if we were given an incomplete table
+ return y != 0 && g != 1 ? ZLibStatus.Z_BUF_ERROR : ZLibStatus.Z_OK;
+ }
+
+ internal ZLibStatus InflateTreesBits(int[] c, // 19 code lengths
+ int[] bb, // bits tree desired/actual depth
+ int[] tb, // bits tree result
+ int[] hp, // space for trees
+ ICompressor z // for messages
+ )
+ {
+ ZLibStatus result;
+ InitWorkArea(19);
+ hn[0] = 0;
+ result = HuftBuild(c, 0, 19, 19, null, null, tb, bb, hp, hn, v);
+
+ if (result == ZLibStatus.Z_DATA_ERROR)
+ {
+ z.msg = "oversubscribed dynamic bit lengths tree";
+ }
+ else if (result == ZLibStatus.Z_BUF_ERROR || bb[0] == 0)
+ {
+ z.msg = "incomplete dynamic bit lengths tree";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ return result;
+ }
+
+ internal ZLibStatus InflateTreesDynamic(int nl, // number of literal/length codes
+ int nd, // number of distance codes
+ int[] c, // that many (total) code lengths
+ int[] bl, // literal desired/actual bit depth
+ int[] bd, // distance desired/actual bit depth
+ int[] tl, // literal/length tree result
+ int[] td, // distance tree result
+ int[] hp, // space for trees
+ ICompressor z // for messages
+ )
+ {
+ ZLibStatus result;
+
+ // build literal/length tree
+ InitWorkArea(288);
+ hn[0] = 0;
+ result = HuftBuild(c, 0, nl, 257, cplens, cplext, tl, bl, hp, hn, v);
+ if (result != ZLibStatus.Z_OK || bl[0] == 0)
+ {
+ if (result == ZLibStatus.Z_DATA_ERROR)
+ {
+ z.msg = "oversubscribed literal/length tree";
+ }
+ else if (result != ZLibStatus.Z_MEM_ERROR)
+ {
+ z.msg = "incomplete literal/length tree";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ return result;
+ }
+
+ // build distance tree
+ InitWorkArea(288);
+ result = HuftBuild(c, nl, nd, 0, cpdist, cpdext, td, bd, hp, hn, v);
+
+ if (result != ZLibStatus.Z_OK || (bd[0] == 0 && nl > 257))
+ {
+ if (result == ZLibStatus.Z_DATA_ERROR)
+ {
+ z.msg = "oversubscribed distance tree";
+ }
+ else if (result == ZLibStatus.Z_BUF_ERROR)
+ {
+ z.msg = "incomplete distance tree";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ else if (result != ZLibStatus.Z_MEM_ERROR)
+ {
+ z.msg = "empty distance tree with lengths";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ return result;
+ }
+
+ return ZLibStatus.Z_OK;
+ }
+
+ internal static ZLibStatus InflateTreesFixed(int[] bl, //literal desired/actual bit depth
+ int[] bd, //distance desired/actual bit depth
+ int[][] tl,//literal/length tree result
+ int[][] td //distance tree result
+ )
+ {
+ bl[0] = fixed_bl;
+ bd[0] = fixed_bd;
+ tl[0] = fixed_tl;
+ td[0] = fixed_td;
+ return ZLibStatus.Z_OK;
+ }
+
+ private void InitWorkArea(int vsize)
+ {
+ if (hn == null)
+ {
+ hn = new int[1];
+ v = new int[vsize];
+ c = new int[BMAX + 1];
+ r = new int[3];
+ u = new int[BMAX];
+ x = new int[BMAX + 1];
+ }
+ if (v.Length < vsize) { v = new int[vsize]; }
+ for (int i = 0; i < vsize; i++) { v[i] = 0; }
+ for (int i = 0; i < BMAX + 1; i++) { c[i] = 0; }
+ for (int i = 0; i < 3; i++) { r[i] = 0; }
+ // for(int i=0; i
+ /// Gets the static tree or null
+ ///
+ ///
+ /// The static_tree.
+ ///
+ public short[] TreeData { get; private set; }
+
+ ///
+ /// Gets the extra bits for each code or null.
+ ///
+ ///
+ /// The extra bits.
+ ///
+ public int[] ExtraBits { get; private set; }
+
+ ///
+ /// Gets the base index for extra_bits.
+ ///
+ ///
+ /// The extra base.
+ ///
+ public int ExtraBase { get; private set; }
+
+ ///
+ /// Gets the max number of elements in the tree.
+ ///
+ ///
+ /// The elements.
+ ///
+ public int Elements { get; private set; }
+
+ ///
+ /// Gets the max bit length for the codes.
+ ///
+ ///
+ /// The length of the max.
+ ///
+ public int MaxLength { get; private set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The tree data.
+ /// The extra bits.
+ /// The extra base.
+ /// The elements.
+ /// Length of the max.
+ public StaticTree(short[] treeData, int[] extraBits, int extraBase, int elements, int maxLength)
+ {
+ this.TreeData = treeData;
+ this.ExtraBits = extraBits;
+ this.ExtraBase = extraBase;
+ this.Elements = elements;
+ this.MaxLength = maxLength;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v13/Tree.cs b/Renci.SshNet/Compression/v13/Tree.cs
new file mode 100644
index 0000000..d2142c9
--- /dev/null
+++ b/Renci.SshNet/Compression/v13/Tree.cs
@@ -0,0 +1,334 @@
+using System;
+/*
+ * $Id: Tree.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+ internal sealed class Tree
+ {
+ private const int MAX_BITS = 15;
+
+ private const int LITERALS = 256;
+
+ private const int LENGTH_CODES = 29;
+
+ private const int L_CODES = (LITERALS + 1 + LENGTH_CODES);
+
+ private const int HEAP_SIZE = (2 * L_CODES + 1);
+
+ private static byte[] _dist_code = {
+ 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8,
+ 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17,
+ 18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
+ 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
+ };
+
+
+ ///
+ /// The corresponding static tree
+ ///
+ private StaticTree _staticTree;
+
+ ///
+ /// The dynamic tree
+ ///
+ private short[] _dynamicTree;
+
+ ///
+ /// Gets the largest code with non zero frequency.
+ ///
+ ///
+ /// The max_code.
+ ///
+ public int LargestCode { get; private set; }
+
+ public void Init(short[] dynamicTree, StaticTree staticTree)
+ {
+ this._staticTree = staticTree;
+ this._dynamicTree = dynamicTree;
+ }
+
+ ///
+ /// Mapping from a distance to a distance code. dist is the distance - 1 and must not have side effects. _dist_code[256] and _dist_code[257] are never used.
+ ///
+ /// The dist.
+ ///
+ public static int DistanceCode(int dist)
+ {
+ // TODO: Under multiple port forward after more then 50K requests gets index out of range
+ return ((dist) < 256 ? _dist_code[dist] : _dist_code[256 + ((dist) >> 7)]);
+ }
+
+ ///
+ /// Construct one Huffman tree and assigns the code bit strings and lengths. Update the total bit length for the current block.
+ ///
+ /// The s.
+ public void BuildTree(Deflate s)
+ {
+ short[] tree = _dynamicTree;
+ short[] stree = _staticTree.TreeData;
+ int elems = _staticTree.Elements;
+ int n, m; // iterate over heap elements
+ int max_code = -1; // largest code with non zero frequency
+ int node; // new node being created
+
+ // Construct the initial heap, with least frequent element in
+ // heap[1]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
+ // heap[0] is not used.
+ s.heap_len = 0;
+ s.heap_max = HEAP_SIZE;
+
+ for (n = 0; n < elems; n++)
+ {
+ if (tree[n * 2] != 0)
+ {
+ s.heap[++s.heap_len] = max_code = n;
+ s.depth[n] = 0;
+ }
+ else
+ {
+ tree[n * 2 + 1] = 0;
+ }
+ }
+
+ // The pkzip format requires that at least one distance code exists,
+ // and that at least one bit should be sent even if there is only one
+ // possible code. So to avoid special checks later on we force at least
+ // two codes of non zero frequency.
+ while (s.heap_len < 2)
+ {
+ node = s.heap[++s.heap_len] = (max_code < 2 ? ++max_code : 0);
+ tree[node * 2] = 1;
+ s.depth[node] = 0;
+ s.opt_len--; if (stree != null) s.static_len -= stree[node * 2 + 1];
+ // node is 0 or 1 so it does not have extra bits
+ }
+ this.LargestCode = max_code;
+
+ // The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
+ // establish sub-heaps of increasing lengths:
+
+ for (n = s.heap_len / 2; n >= 1; n--)
+ s.pqdownheap(tree, n);
+
+ // Construct the Huffman tree by repeatedly combining the least two
+ // frequent nodes.
+
+ node = elems; // next internal node of the tree
+ do
+ {
+ // n = node of least frequency
+ n = s.heap[1];
+ s.heap[1] = s.heap[s.heap_len--];
+ s.pqdownheap(tree, 1);
+ m = s.heap[1]; // m = node of next least frequency
+
+ s.heap[--s.heap_max] = n; // keep the nodes sorted by frequency
+ s.heap[--s.heap_max] = m;
+
+ // Create a new node father of n and m
+ tree[node * 2] = (short)(tree[n * 2] + tree[m * 2]);
+ s.depth[node] = (byte)(System.Math.Max(s.depth[n], s.depth[m]) + 1);
+ tree[n * 2 + 1] = tree[m * 2 + 1] = (short)node;
+
+ // and insert the new node in the heap
+ s.heap[1] = node++;
+ s.pqdownheap(tree, 1);
+ }
+ while (s.heap_len >= 2);
+
+ s.heap[--s.heap_max] = s.heap[1];
+
+ // At this point, the fields freq and dad are set. We can now
+ // generate the bit lengths.
+
+ ComputeBitLength(s);
+
+ // The field len is now set, we can generate the bit codes
+ GenerateCodes(tree, max_code, s.bl_count);
+ }
+
+ ///
+ /// Compute the optimal bit lengths for a tree and update the total bit length for the current block.
+ ///
+ /// The s.
+ private void ComputeBitLength(Deflate s)
+ {
+ short[] tree = _dynamicTree;
+ short[] stree = _staticTree.TreeData;
+ int[] extra = _staticTree.ExtraBits;
+ int based = _staticTree.ExtraBase;
+ int max_length = _staticTree.MaxLength;
+ int h; // heap index
+ int n, m; // iterate over the tree elements
+ int bits; // bit length
+ int xbits; // extra bits
+ short f; // frequency
+ int overflow = 0; // number of elements with bit length too large
+
+ for (bits = 0; bits <= MAX_BITS; bits++) s.bl_count[bits] = 0;
+
+ // In a first pass, compute the optimal bit lengths (which may
+ // overflow in the case of the bit length tree).
+ tree[s.heap[s.heap_max] * 2 + 1] = 0; // root of the heap
+
+ for (h = s.heap_max + 1; h < HEAP_SIZE; h++)
+ {
+ n = s.heap[h];
+ bits = tree[tree[n * 2 + 1] * 2 + 1] + 1;
+ if (bits > max_length) { bits = max_length; overflow++; }
+ tree[n * 2 + 1] = (short)bits;
+ // We overwrite tree[n*2+1] which is no longer needed
+
+ if (n > LargestCode) continue; // not a leaf node
+
+ s.bl_count[bits]++;
+ xbits = 0;
+ if (n >= based) xbits = extra[n - based];
+ f = tree[n * 2];
+ s.opt_len += f * (bits + xbits);
+ if (stree != null) s.static_len += f * (stree[n * 2 + 1] + xbits);
+ }
+ if (overflow == 0) return;
+
+ // This happens for example on obj2 and pic of the Calgary corpus
+ // Find the first bit length which could increase:
+ do
+ {
+ bits = max_length - 1;
+ while (s.bl_count[bits] == 0) bits--;
+ s.bl_count[bits]--; // move one leaf down the tree
+ s.bl_count[bits + 1] += 2; // move one overflow item as its brother
+ s.bl_count[max_length]--;
+ // The brother of the overflow item also moves one step up,
+ // but this does not affect bl_count[max_length]
+ overflow -= 2;
+ }
+ while (overflow > 0);
+
+ for (bits = max_length; bits != 0; bits--)
+ {
+ n = s.bl_count[bits];
+ while (n != 0)
+ {
+ m = s.heap[--h];
+ if (m > LargestCode) continue;
+ if (tree[m * 2 + 1] != bits)
+ {
+ s.opt_len += (int)(((long)bits - (long)tree[m * 2 + 1]) * (long)tree[m * 2]);
+ tree[m * 2 + 1] = (short)bits;
+ }
+ n--;
+ }
+ }
+ }
+
+ ///
+ /// Generate the codes for a given tree and bit counts (which need not be optimal).
+ ///
+ /// The tree to decorate.
+ /// The largest code with non zero frequency.
+ /// The number of codes at each bit length.
+ private static void GenerateCodes(short[] tree, int max_code, short[] bl_count)
+ {
+ short[] next_code = new short[MAX_BITS + 1]; // next code value for each bit length
+ short code = 0; // running code value
+ int bits; // bit index
+ int n; // code index
+
+ // The distribution counts are first used to generate the code values
+ // without bit reversal.
+ for (bits = 1; bits <= MAX_BITS; bits++)
+ {
+ next_code[bits] = code = (short)((code + bl_count[bits - 1]) << 1);
+ }
+
+ // Check that the bit counts in bl_count are consistent. The last code
+ // must be all ones.
+ //Assert (code + bl_count[MAX_BITS]-1 == (1<
+ /// Reverse the first len bits of a code, using straightforward code (a faster method would use a table)
+ ///
+ /// The value to invert.
+ /// The bit length.
+ ///
+ private static int BiReverse(int code, int len)
+ {
+ int res = 0;
+ do
+ {
+ res |= code & 1;
+ code >>= 1;
+ res <<= 1;
+ }
+ while (--len > 0);
+ return res >> 1;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v13/ZInputStream.cs b/Renci.SshNet/Compression/v13/ZInputStream.cs
new file mode 100644
index 0000000..0ef972c
--- /dev/null
+++ b/Renci.SshNet/Compression/v13/ZInputStream.cs
@@ -0,0 +1,202 @@
+/*
+Copyright (c) 2001 Lapo Luchini.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS
+OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+/* This file is a port of jzlib v1.0.7, com.jcraft.jzlib.ZInputStream.java
+ */
+
+using Renci.SshNet.Compression;
+using System;
+using System.Diagnostics;
+using System.IO;
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+ public class ZInputStream : Stream
+ {
+ private const int BufferSize = 512;
+ //private ZStream z = new ZStream();
+ private ICompressor _compressor;
+
+ // TODO Allow custom buf
+ private byte[] _buffer = new byte[BufferSize];
+ private CompressionMode _compressionMode;
+ private Stream _input;
+ private bool _isClosed;
+ private bool _noMoreInput = false;
+
+ public FlushType FlushMode { get; private set; }
+
+ public ZInputStream()
+ {
+ this.FlushMode = FlushType.Z_PARTIAL_FLUSH;
+ }
+
+ public ZInputStream(Stream input)
+ : this(input, false)
+ {
+ }
+
+ public ZInputStream(Stream input, bool nowrap)
+ : this()
+ {
+ Debug.Assert(input.CanRead);
+
+ this._input = input;
+ this._compressor = new Inflate(nowrap);
+ //this._compressor.inflateInit(nowrap);
+ this._compressionMode = CompressionMode.Decompress;
+ this._compressor.next_in = _buffer;
+ this._compressor.next_in_index = 0;
+ this._compressor.avail_in = 0;
+ }
+
+ public ZInputStream(Stream input, CompressionLevel level)
+ : this()
+ {
+ Debug.Assert(input.CanRead);
+
+ this._input = input;
+ this._compressor = new Deflate(level);
+ //this._compressor.deflateInit(level);
+ this._compressionMode = CompressionMode.Compress;
+ this._compressor.next_in = _buffer;
+ this._compressor.next_in_index = 0;
+ this._compressor.avail_in = 0;
+ }
+
+ #region Stream implementation
+
+ public sealed override bool CanRead
+ {
+ get { return !_isClosed; }
+ }
+
+ public sealed override bool CanSeek
+ {
+ get { return false; }
+ }
+
+ public sealed override bool CanWrite
+ {
+ get { return false; }
+ }
+
+ public override void Flush()
+ {
+ }
+
+ public override long Length
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ public override long Position
+ {
+ get { throw new NotSupportedException(); }
+ set { throw new NotSupportedException(); }
+ }
+
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ if (count == 0)
+ return 0;
+
+ //this._compressor.next_out = buffer;
+ //this._compressor.next_out_index = offset;
+ //this._compressor.avail_out = count;
+
+ ZLibStatus err = ZLibStatus.Z_OK;
+ do
+ {
+ if (this._compressor.avail_in == 0 && !_noMoreInput)
+ {
+ // if buffer is empty and more input is available, refill it
+ this._compressor.next_in_index = 0;
+ this._compressor.avail_in = _input.Read(_buffer, 0, _buffer.Length); //(bufsize 0 || this._compressor.avail_out == 0);
+ }
+
+ #endregion
+
+ public override void Close()
+ {
+ if (this._isClosed)
+ return;
+
+ try
+ {
+ try
+ {
+ Finish();
+ }
+ catch (IOException)
+ {
+ // Ignore
+ }
+ }
+ finally
+ {
+ this._isClosed = true;
+ End();
+ _output.Close();
+ _output = null;
+ }
+ }
+
+ private void End()
+ {
+ if (this._compressor == null)
+ return;
+ switch (this._compressionMode)
+ {
+ case CompressionMode.Compress:
+ this._compressor.deflateEnd();
+ break;
+ case CompressionMode.Decompress:
+ this._compressor.inflateEnd();
+ break;
+ default:
+ break;
+ }
+
+ //this._compressor.free();
+ this._compressor = null;
+ }
+
+ private void Finish()
+ {
+ do
+ {
+ var err = ZLibStatus.Z_OK;
+ switch (this._compressionMode)
+ {
+ case CompressionMode.Compress:
+ err = this._compressor.deflate(_buffer, 0, _buffer.Length, FlushType.Z_FINISH);
+ break;
+ case CompressionMode.Decompress:
+ err = this._compressor.inflate(_buffer, 0, _buffer.Length, FlushType.Z_FINISH);
+ break;
+ default:
+ break;
+ }
+
+ if (err != ZLibStatus.Z_STREAM_END && err != ZLibStatus.Z_OK)
+ // TODO
+ // throw new ZStreamException((compress?"de":"in")+"flating: "+z.msg);
+ //throw new IOException((_compressionMode ? "de" : "in") + "flating: " + z.msg);
+ throw new IOException(string.Format("{0}ion error: {1}", _compressionMode, err));
+
+ int count = _buffer.Length - this._compressor.avail_out;
+ if (count > 0)
+ {
+ _output.Write(_buffer, 0, count);
+ }
+ }
+ while (this._compressor.avail_in > 0 || this._compressor.avail_out == 0);
+
+ Flush();
+ }
+ }
+}
diff --git a/Renci.SshNet/Compression/v13/ZStream.cs b/Renci.SshNet/Compression/v13/ZStream.cs
new file mode 100644
index 0000000..0d5204b
--- /dev/null
+++ b/Renci.SshNet/Compression/v13/ZStream.cs
@@ -0,0 +1,100 @@
+using System;
+using System.IO;
+/*
+ * $Id: ZStream.cs,v 1.1 2006-07-31 13:59:26 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public interface ICompressor
+ {
+ ZLibStatus deflate(byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType);
+ ZLibStatus deflate(byte[] bufer, int offset, int count, byte[] p1, int p2, int p3, FlushType flushType);
+ ZLibStatus deflateEnd();
+
+ ZLibStatus inflate(byte[] bufer, int offset, int count, byte[] p1, int p2, int p3, FlushType flushType);
+ ZLibStatus inflate(byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType);
+ ZLibStatus inflateEnd();
+
+ //ZLibStatus inflate(FlushType flushType);
+
+ int avail_out { get; set; }
+
+ int avail_in { get; set; }
+
+ int next_out_index { get; set; }
+
+ byte[] next_out { get; set; }
+
+ byte[] next_in { get; set; }
+
+ int next_in_index { get; set; }
+
+ String msg { get; set; }
+
+ long adler { get; set; }
+
+ long total_in { get; set; }
+
+ long total_out { get; set; }
+ }
+
+
+ public abstract class ZStream
+ {
+
+ protected const int MAX_WBITS = 15; // 32K LZ77 window
+ protected const int DEF_WBITS = MAX_WBITS;
+
+ private const int MAX_MEM_LEVEL = 9;
+
+ public byte[] next_in { get; set; } // next input byte
+ public int next_in_index { get; set; }
+ public int avail_in { get; set; } // number of bytes available at next_in
+ public long total_in { get; set; } // total nb of input bytes read so far
+
+ public byte[] next_out { get; set; } // next output byte should be put there
+ public int next_out_index { get; set; }
+ public int avail_out { get; set; } // remaining free space at next_out
+ public long total_out { get; set; } // total nb of bytes output so far
+
+ public String msg { get; set; }
+
+ internal BlockType data_type; // best guess about the data type: ascii or binary
+
+ public long adler { get; set; }
+
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v13/Zlib.cs b/Renci.SshNet/Compression/v13/Zlib.cs
new file mode 100644
index 0000000..5890675
--- /dev/null
+++ b/Renci.SshNet/Compression/v13/Zlib.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Represents "zlib" compression implementation
+ ///
+ internal class Zlib : Compressor
+ {
+ ///
+ /// Gets algorithm name.
+ ///
+ public override string Name
+ {
+ get { return "zlib"; }
+ }
+
+ ///
+ /// Initializes the algorithm
+ ///
+ /// The session.
+ public override void Init(Session session)
+ {
+ base.Init(session);
+ this.IsActive = true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v13/ZlibOpenSsh.cs b/Renci.SshNet/Compression/v13/ZlibOpenSsh.cs
new file mode 100644
index 0000000..f82a4c0
--- /dev/null
+++ b/Renci.SshNet/Compression/v13/ZlibOpenSsh.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Represents "zlib@openssh.org" compression implementation
+ ///
+ public class ZlibOpenSsh : Compressor
+ {
+ ///
+ /// Gets algorithm name.
+ ///
+ public override string Name
+ {
+ get { return "zlib@openssh.org"; }
+ }
+
+ ///
+ /// Initializes the algorithm
+ ///
+ /// The session.
+ public override void Init(Session session)
+ {
+ base.Init(session);
+
+ session.UserAuthenticationSuccessReceived += Session_UserAuthenticationSuccessReceived;
+ }
+
+ private void Session_UserAuthenticationSuccessReceived(object sender, MessageEventArgs e)
+ {
+ this.IsActive = true;
+ this.Session.UserAuthenticationSuccessReceived -= Session_UserAuthenticationSuccessReceived;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v13/ZlibStream.cs b/Renci.SshNet/Compression/v13/ZlibStream.cs
new file mode 100644
index 0000000..fb5f9d2
--- /dev/null
+++ b/Renci.SshNet/Compression/v13/ZlibStream.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.IO;
+using Org.BouncyCastle.Utilities.Zlib;
+
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Implements Zlib compression algorithm.
+ ///
+ public class ZlibStream
+ {
+ private readonly Stream _baseStream;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The stream.
+ /// The mode.
+ public ZlibStream(Stream stream, CompressionMode mode)
+ {
+ switch (mode)
+ {
+ case CompressionMode.Compress:
+ //this._baseStream = new ZOutputStream(stream, CompressionLevel.Z_DEFAULT_COMPRESSION);
+ this._baseStream = new ZOutputStream(stream, CompressionLevel.Z_DEFAULT_COMPRESSION);
+ break;
+ case CompressionMode.Decompress:
+ this._baseStream = new ZOutputStream(stream);
+ break;
+ default:
+ break;
+ }
+
+ //this._baseStream.FlushMode = Ionic.Zlib.FlushType.Partial;
+ }
+
+ ///
+ /// Writes the specified buffer.
+ ///
+ /// The buffer.
+ /// The offset.
+ /// The count.
+ public void Write(byte[] buffer, int offset, int count)
+ {
+ this._baseStream.Write(buffer, offset, count);
+ }
+ }
+}
diff --git a/Renci.SshNet/Compression/v9/Adler32.cs b/Renci.SshNet/Compression/v9/Adler32.cs
new file mode 100644
index 0000000..c132fa9
--- /dev/null
+++ b/Renci.SshNet/Compression/v9/Adler32.cs
@@ -0,0 +1,95 @@
+using System;
+/*
+ * $Id: Adler32.cs,v 1.1 2006-07-31 13:59:25 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ internal static class Adler32
+ {
+
+ // largest prime smaller than 65536
+ private const int BASE = 65521;
+ // NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
+ private const int NMAX = 5552;
+
+ internal static long adler32(long adler, byte[] buf, int index, int len)
+ {
+ if (buf == null) { return 1L; }
+
+ long s1 = adler & 0xffff;
+ long s2 = (adler >> 16) & 0xffff;
+ int k;
+
+ while (len > 0)
+ {
+ k = len < NMAX ? len : NMAX;
+ len -= k;
+ while (k >= 16)
+ {
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ s1 += buf[index++] & 0xff; s2 += s1;
+ k -= 16;
+ }
+ if (k != 0)
+ {
+ do
+ {
+ s1 += buf[index++] & 0xff; s2 += s1;
+ }
+ while (--k != 0);
+ }
+ s1 %= BASE;
+ s2 %= BASE;
+ }
+ return (s2 << 16) | s1;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v9/CompressionMode.cs b/Renci.SshNet/Compression/v9/CompressionMode.cs
new file mode 100644
index 0000000..1577e0b
--- /dev/null
+++ b/Renci.SshNet/Compression/v9/CompressionMode.cs
@@ -0,0 +1,18 @@
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Specifies compression modes
+ ///
+ public enum CompressionMode
+ {
+ ///
+ /// Specifies that content should be compressed.
+ ///
+ Compress = 0,
+
+ ///
+ /// Specifies that content should be decompressed.
+ ///
+ Decompress = 1,
+ }
+}
diff --git a/Renci.SshNet/Compression/v9/Compressor.cs b/Renci.SshNet/Compression/v9/Compressor.cs
new file mode 100644
index 0000000..1479bb6
--- /dev/null
+++ b/Renci.SshNet/Compression/v9/Compressor.cs
@@ -0,0 +1,151 @@
+using System.Collections.Generic;
+using Renci.SshNet.Security;
+using System.IO;
+using System;
+
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Represents base class for compression algorithm implementation
+ ///
+ public abstract class Compressor : Algorithm, IDisposable
+ {
+ private readonly ZlibStream _compressor;
+ private readonly ZlibStream _decompressor;
+
+ private MemoryStream _compressorStream;
+ private MemoryStream _decompressorStream;
+
+ ///
+ /// Gets or sets a value indicating whether compression is active.
+ ///
+ ///
+ /// true if compression is active; otherwise, false.
+ ///
+ protected bool IsActive { get; set; }
+
+ ///
+ /// Gets the session.
+ ///
+ protected Session Session { get; private set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ 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);
+ }
+
+ ///
+ /// Initializes the algorithm
+ ///
+ /// The session.
+ public virtual void Init(Session session)
+ {
+ this.Session = session;
+ }
+
+ ///
+ /// Compresses the specified data.
+ ///
+ /// Data to compress.
+ /// Compressed 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();
+ }
+
+ ///
+ /// Decompresses the specified data.
+ ///
+ /// Compressed data.
+ /// Decompressed 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;
+
+ ///
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged ResourceMessages.
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Releases unmanaged and - optionally - managed resources
+ ///
+ /// true to release both managed and unmanaged resources; false to release only unmanaged ResourceMessages.
+ 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;
+ }
+ }
+
+ ///
+ /// Releases unmanaged resources and performs other cleanup operations before the
+ /// is reclaimed by garbage collection.
+ ///
+ ~Compressor()
+ {
+ // Do not re-create Dispose clean-up code here.
+ // Calling Dispose(false) is optimal in terms of
+ // readability and maintainability.
+ Dispose(false);
+ }
+
+ #endregion
+ }
+}
diff --git a/Renci.SshNet/Compression/v9/Deflate.cs b/Renci.SshNet/Compression/v9/Deflate.cs
new file mode 100644
index 0000000..7425e49
--- /dev/null
+++ b/Renci.SshNet/Compression/v9/Deflate.cs
@@ -0,0 +1,2226 @@
+using System;
+using System.Collections.Generic;
+/*
+ * $Id: Deflate.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public enum BlockType : byte
+ {
+ Z_BINARY = 0,
+ Z_ASCII = 1,
+ Z_UNKNOWN = 2
+ }
+
+ public enum DefalteFlavor : int
+ {
+ STORED = 0,
+ FAST = 1,
+ SLOW = 2
+ }
+
+ public sealed class Deflate : ZStream, ICompressor
+ {
+ private const int MAX_MEM_LEVEL = 9;
+
+ private const int Z_DEFAULT_COMPRESSION = -1;
+
+ private const int MAX_WBITS = 15; // 32K LZ77 window
+
+ private const int DEF_MEM_LEVEL = 8;
+
+ ///
+ /// The Bit length codes must not exceed MAX_BL_BITS bits
+ ///
+ private const int MAX_BL_BITS = 7;
+
+ // block not completed, need more input or more output
+ private const int NeedMore = 0;
+
+ // block flush performed
+ private const int BlockDone = 1;
+
+ // finish started, need only more output at next deflate
+ private const int FinishStarted = 2;
+
+ // finish done, accept no more input or output
+ private const int FinishDone = 3;
+
+ // preset dictionary flag in zlib header
+ private const int PRESET_DICT = 0x20;
+
+ private const int Z_VERSION_ERROR = -6;
+
+ private const int INIT_STATE = 42;
+ private const int BUSY_STATE = 113;
+ private const int FINISH_STATE = 666;
+
+ // The deflate compression method
+ private const int Z_DEFLATED = 8;
+
+ private const int STORED_BLOCK = 0;
+ private const int STATIC_TREES = 1;
+ private const int DYN_TREES = 2;
+
+ private const int Buf_size = 8 * 2;
+
+ // repeat previous bit length 3-6 times (2 bits of repeat count)
+ private const int REP_3_6 = 16;
+
+ // repeat a zero length 3-10 times (3 bits of repeat count)
+ private const int REPZ_3_10 = 17;
+
+ // repeat a zero length 11-138 times (7 bits of repeat count)
+ private const int REPZ_11_138 = 18;
+
+ private const int MIN_MATCH = 3;
+ private const int MAX_MATCH = 258;
+ private const int MIN_LOOKAHEAD = (MAX_MATCH + MIN_MATCH + 1);
+
+ private const int MAX_BITS = 15;
+ private const int D_CODES = 30;
+ private const int BL_CODES = 19;
+ private const int LENGTH_CODES = 29;
+ private const int LITERALS = 256;
+ private const int L_CODES = (LITERALS + 1 + LENGTH_CODES);
+ private const int HEAP_SIZE = (2 * L_CODES + 1);
+
+ private const int END_BLOCK = 256;
+
+ private static readonly IDictionary config_table = new Dictionary() {
+ {(CompressionLevel)0, new Config(0, 0, 0, 0, DefalteFlavor.STORED)},
+ {(CompressionLevel)1, new Config(4, 4, 8, 4, DefalteFlavor.FAST)},
+ {(CompressionLevel)2, new Config(4, 5, 16, 8, DefalteFlavor.FAST)},
+ {(CompressionLevel)3, new Config(4, 6, 32, 32, DefalteFlavor.FAST)},
+
+ {(CompressionLevel)4, new Config(4, 4, 16, 16, DefalteFlavor.SLOW)},
+ {(CompressionLevel)5, new Config(8, 16, 32, 32, DefalteFlavor.SLOW)},
+ {(CompressionLevel)6, new Config(8, 16, 128, 128, DefalteFlavor.SLOW)},
+ {(CompressionLevel)7, new Config(8, 32, 128, 256, DefalteFlavor.SLOW)},
+ {(CompressionLevel)8, new Config(32, 128, 258, 1024, DefalteFlavor.SLOW)},
+ {(CompressionLevel)9, new Config(32, 258, 258, 4096, DefalteFlavor.SLOW)},
+ };
+
+ #region Static definitions
+
+ private static readonly byte[] _length_code ={
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12,
+ 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
+ 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,
+ 19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22,
+ 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23,
+ 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28
+ };
+
+ private static readonly int[] base_length = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56,
+ 64, 80, 96, 112, 128, 160, 192, 224, 0
+ };
+
+ private static readonly int[] base_dist = {
+ 0, 1, 2, 3, 4, 6, 8, 12, 16, 24,
+ 32, 48, 64, 96, 128, 192, 256, 384, 512, 768,
+ 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576
+ };
+
+ // extra bits for each length code
+ private static readonly int[] extra_lbits ={
+ 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0
+ };
+
+ // extra bits for each distance code
+ private static readonly int[] extra_dbits ={
+ 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13
+ };
+
+ // extra bits for each bit length code
+ private static readonly int[] extra_blbits ={
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7
+ };
+
+ private static readonly byte[] bl_order ={
+ 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
+
+ private static readonly short[] static_ltree = {
+ 12, 8, 140, 8, 76, 8, 204, 8, 44, 8,
+ 172, 8, 108, 8, 236, 8, 28, 8, 156, 8,
+ 92, 8, 220, 8, 60, 8, 188, 8, 124, 8,
+ 252, 8, 2, 8, 130, 8, 66, 8, 194, 8,
+ 34, 8, 162, 8, 98, 8, 226, 8, 18, 8,
+ 146, 8, 82, 8, 210, 8, 50, 8, 178, 8,
+ 114, 8, 242, 8, 10, 8, 138, 8, 74, 8,
+ 202, 8, 42, 8, 170, 8, 106, 8, 234, 8,
+ 26, 8, 154, 8, 90, 8, 218, 8, 58, 8,
+ 186, 8, 122, 8, 250, 8, 6, 8, 134, 8,
+ 70, 8, 198, 8, 38, 8, 166, 8, 102, 8,
+ 230, 8, 22, 8, 150, 8, 86, 8, 214, 8,
+ 54, 8, 182, 8, 118, 8, 246, 8, 14, 8,
+ 142, 8, 78, 8, 206, 8, 46, 8, 174, 8,
+ 110, 8, 238, 8, 30, 8, 158, 8, 94, 8,
+ 222, 8, 62, 8, 190, 8, 126, 8, 254, 8,
+ 1, 8, 129, 8, 65, 8, 193, 8, 33, 8,
+ 161, 8, 97, 8, 225, 8, 17, 8, 145, 8,
+ 81, 8, 209, 8, 49, 8, 177, 8, 113, 8,
+ 241, 8, 9, 8, 137, 8, 73, 8, 201, 8,
+ 41, 8, 169, 8, 105, 8, 233, 8, 25, 8,
+ 153, 8, 89, 8, 217, 8, 57, 8, 185, 8,
+ 121, 8, 249, 8, 5, 8, 133, 8, 69, 8,
+ 197, 8, 37, 8, 165, 8, 101, 8, 229, 8,
+ 21, 8, 149, 8, 85, 8, 213, 8, 53, 8,
+ 181, 8, 117, 8, 245, 8, 13, 8, 141, 8,
+ 77, 8, 205, 8, 45, 8, 173, 8, 109, 8,
+ 237, 8, 29, 8, 157, 8, 93, 8, 221, 8,
+ 61, 8, 189, 8, 125, 8, 253, 8, 19, 9,
+ 275, 9, 147, 9, 403, 9, 83, 9, 339, 9,
+ 211, 9, 467, 9, 51, 9, 307, 9, 179, 9,
+ 435, 9, 115, 9, 371, 9, 243, 9, 499, 9,
+ 11, 9, 267, 9, 139, 9, 395, 9, 75, 9,
+ 331, 9, 203, 9, 459, 9, 43, 9, 299, 9,
+ 171, 9, 427, 9, 107, 9, 363, 9, 235, 9,
+ 491, 9, 27, 9, 283, 9, 155, 9, 411, 9,
+ 91, 9, 347, 9, 219, 9, 475, 9, 59, 9,
+ 315, 9, 187, 9, 443, 9, 123, 9, 379, 9,
+ 251, 9, 507, 9, 7, 9, 263, 9, 135, 9,
+ 391, 9, 71, 9, 327, 9, 199, 9, 455, 9,
+ 39, 9, 295, 9, 167, 9, 423, 9, 103, 9,
+ 359, 9, 231, 9, 487, 9, 23, 9, 279, 9,
+ 151, 9, 407, 9, 87, 9, 343, 9, 215, 9,
+ 471, 9, 55, 9, 311, 9, 183, 9, 439, 9,
+ 119, 9, 375, 9, 247, 9, 503, 9, 15, 9,
+ 271, 9, 143, 9, 399, 9, 79, 9, 335, 9,
+ 207, 9, 463, 9, 47, 9, 303, 9, 175, 9,
+ 431, 9, 111, 9, 367, 9, 239, 9, 495, 9,
+ 31, 9, 287, 9, 159, 9, 415, 9, 95, 9,
+ 351, 9, 223, 9, 479, 9, 63, 9, 319, 9,
+ 191, 9, 447, 9, 127, 9, 383, 9, 255, 9,
+ 511, 9, 0, 7, 64, 7, 32, 7, 96, 7,
+ 16, 7, 80, 7, 48, 7, 112, 7, 8, 7,
+ 72, 7, 40, 7, 104, 7, 24, 7, 88, 7,
+ 56, 7, 120, 7, 4, 7, 68, 7, 36, 7,
+ 100, 7, 20, 7, 84, 7, 52, 7, 116, 7,
+ 3, 8, 131, 8, 67, 8, 195, 8, 35, 8,
+ 163, 8, 99, 8, 227, 8
+ };
+
+ private static readonly short[] static_dtree = {
+ 0, 5, 16, 5, 8, 5, 24, 5, 4, 5,
+ 20, 5, 12, 5, 28, 5, 2, 5, 18, 5,
+ 10, 5, 26, 5, 6, 5, 22, 5, 14, 5,
+ 30, 5, 1, 5, 17, 5, 9, 5, 25, 5,
+ 5, 5, 21, 5, 13, 5, 29, 5, 3, 5,
+ 19, 5, 11, 5, 27, 5, 7, 5, 23, 5
+ };
+ #endregion
+
+ private static readonly String[] z_errmsg = {
+ "need dictionary", // ZLibStatus.Z_NEED_DICT 2
+ "stream end", // ZLibStatus.Z_STREAM_END 1
+ "", // ZLibStatus.Z_OK 0
+ "file error", // ZLibStatus.Z_ERRNO (-1)
+ "stream error", // ZLibStatus.Z_STREAM_ERROR (-2)
+ "data error", // ZLibStatus.Z_DATA_ERROR (-3)
+ "insufficient memory", // Z_MEM_ERROR (-4)
+ "buffer error", // ZLibStatus.Z_BUF_ERROR (-5)
+ "incompatible version",// Z_VERSION_ERROR (-6)
+ ""
+ };
+
+
+
+ ///
+ /// as the name implies
+ ///
+ private int _status;
+
+ private BlockType _dataType;
+
+ ///
+ /// STORED (for zip only) or DEFLATED
+ ///
+ private byte _method;
+
+ ///
+ /// size of pending_buf
+ ///
+ private int _pendingBufferSize;
+
+ ///
+ /// LZ77 window size (32K by default)
+ ///
+ private int _windowSize;
+
+ ///
+ /// log2(w_size) (8..16)
+ ///
+ private int _windowBits;
+
+ ///
+ /// w_size - 1
+ ///
+ private int _windowMask;
+
+ ///
+ /// Sliding window. Input bytes are read into the second half of the window,
+ /// and move to the first half later to keep a dictionary of at least wSize
+ /// bytes. With this organization, matches are limited to a distance of
+ /// wSize-MAX_MATCH bytes, but this ensures that IO is always
+ /// performed with a length multiple of the block size. Also, it limits
+ /// the window size to 64K, which is quite useful on MSDOS.
+ /// To do: use the user input buffer as sliding window.
+ ///
+ private byte[] _window;
+
+ ///
+ /// Actual size of window: 2*wSize, except when the user input buffer
+ /// is directly used as sliding window.
+ ///
+ private int _windowActualSize;
+
+ ///
+ /// Link to older string with same hash index. To limit the size of this
+ /// array to 64K, this link is maintained only for the last 32K strings.
+ /// An index in this array is thus a window index modulo 32K.
+ ///
+ private short[] _previous;
+
+ ///
+ /// Heads of the hash chains or NIL.
+ ///
+ private short[] _head;
+
+ ///
+ /// hash index of string to be inserted
+ ///
+ private int _insertedHashIndex;
+
+ ///
+ /// number of elements in hash table
+ ///
+ private int _hashSize;
+
+ ///
+ /// log2(hash_size)
+ ///
+ private int _hashBits;
+
+ ///
+ /// hash_size-1
+ ///
+ private int _hashMask;
+
+ ///
+ /// Number of bits by which ins_h must be shifted at each input
+ /// step. It must be such that after MIN_MATCH steps, the oldest
+ /// byte no longer takes part in the hash key, that is:
+ /// hash_shift * MIN_MATCH >= hash_bits
+ ///
+ private int _hashShift;
+
+ ///
+ /// Window position at the beginning of the current output block. Gets
+ /// negative when the window is moved backwards.
+ ///
+ private int _blockStart;
+
+ ///
+ /// length of best match
+ ///
+ private int _matchLength;
+
+ ///
+ /// previous match
+ ///
+ private int _previousMatch;
+
+ ///
+ /// set if previous match exists
+ ///
+ private bool _matchAvailable;
+
+ ///
+ /// start of string to insert
+ ///
+ private int _startInsertString;
+
+ ///
+ /// start of matching string
+ ///
+ private int _startMatchString;
+
+ ///
+ /// number of valid bytes ahead in window
+ ///
+ private int _validBytesAhead;
+
+ ///
+ /// Length of the best match at previous step. Matches not greater than this
+ /// are discarded. This is used in the lazy match evaluation.
+ ///
+ private int _previousLength;
+
+ ///
+ /// To speed up deflation, hash chains are never searched beyond this
+ /// length. A higher limit improves compression ratio but degrades the speed.
+ ///
+ private int _maxChainLength;
+
+ ///
+ /// Attempt to find a better match only when the current match is strictly
+ /// smaller than this value. This mechanism is used only for compression
+ /// levels >= 4.
+ ///
+ private int _maxLazyMatch;
+
+ // Insert new strings in the hash table only if the match length is not
+ // greater than this length. This saves time but degrades compression.
+ // max_insert_length is used only for compression levels <= 3.
+
+ ///
+ /// The compression level (1..9)
+ ///
+ private CompressionLevel level;
+
+ ///
+ /// The favor or force Huffman coding
+ ///
+ private CompressionStrategy strategy;
+
+ ///
+ /// Use a faster search when the previous match is longer than this
+ ///
+ private int good_match;
+
+ ///
+ /// Stop searching when current match exceeds this
+ ///
+ private int nice_match;
+
+ ///
+ /// literal and length tree
+ ///
+ private short[] dyn_ltree;
+
+ ///
+ /// The distance tree
+ ///
+ private short[] dyn_dtree;
+
+ ///
+ /// The Huffman tree for bit lengths
+ ///
+ private short[] bl_tree;
+
+ ///
+ /// The desc for literal tree
+ ///
+ private Tree l_desc = new Tree();
+
+ ///
+ /// The desc for distance tree
+ ///
+ private Tree d_desc = new Tree();
+
+ ///
+ /// The desc for bit length tree
+ ///
+ private Tree bl_desc = new Tree();
+
+ ///
+ /// index for literals or lengths
+ ///
+ private int l_buf;
+
+ ///
+ /// Size of match buffer for literals/lengths. There are 4 reasons for
+ /// limiting lit_bufsize to 64K:
+ /// - frequencies can be kept in 16 bit counters
+ /// - if compression is not successful for the first block, all input
+ /// data is still in the window so we can still emit a stored block even
+ /// when input comes from standard input. (This can also be done for
+ /// all blocks if lit_bufsize is not greater than 32K.)
+ /// - if compression is not successful for a file smaller than 64K, we can
+ /// even emit a stored file instead of a stored block (saving 5 bytes).
+ /// This is applicable only for zip (not gzip or zlib).
+ /// - creating new Huffman trees less frequently may not provide fast
+ /// adaptation to changes in the input data statistics. (Take for
+ /// example a binary file with poorly compressible code followed by
+ /// a highly compressible string table.) Smaller buffer sizes give
+ /// fast adaptation but have of course the overhead of transmitting
+ /// trees more frequently.
+ /// - I can't count above 4
+ ///
+ private int lit_bufsize;
+
+ ///
+ /// running index in l_buf
+ ///
+ private int last_lit;
+
+ // Buffer for distances. To simplify the code, d_buf and l_buf have
+ // the same number of elements. To use different lengths, an extra flag
+ // array would be necessary.
+
+ ///
+ /// The index of pendig_buf
+ ///
+ private int d_buf;
+
+ ///
+ /// The number of string matches in current block
+ ///
+ private int matches;
+
+ ///
+ /// The bit length of EOB code for last block
+ ///
+ private int last_eob_len;
+
+ ///
+ /// Output buffer. bits are inserted starting at the bottom (least
+ /// significant bits).
+ ///
+ private uint bi_buf;
+
+ ///
+ /// Number of valid bits in bi_buf. All bits above the last valid bit
+ /// are always zero.
+ ///
+ private int bi_valid;
+
+ ///
+ /// value of flush param for previous deflate call
+ ///
+ private FlushType last_flush;
+
+ ///
+ /// bit length of current block with optimal trees
+ ///
+ internal int opt_len;
+
+ ///
+ /// bit length of current block with static trees
+ ///
+ internal int static_len;
+
+ ///
+ /// The output still pending
+ ///
+ internal byte[] pending_buf;
+
+ ///
+ /// next pending byte to output to the stream
+ ///
+ internal int pending_out;
+
+ ///
+ /// nb of bytes in the pending buffer
+ ///
+ internal int pending;
+
+ ///
+ /// suppress zlib header and adler32
+ ///
+ internal int noheader;
+
+ ///
+ /// number of codes at each bit length for an optimal tree
+ ///
+ internal short[] bl_count = new short[MAX_BITS + 1];
+
+ ///
+ /// heap used to build the Huffman trees
+ ///
+ internal int[] heap = new int[2 * L_CODES + 1];
+
+ ///
+ /// The number of elements in the heap
+ ///
+ internal int heap_len;
+ ///
+ /// The element of largest frequency
+ ///
+ internal int heap_max;
+
+ // The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used.
+ // The same heap array is used to build all trees.
+
+ ///
+ /// Depth of each subtree used as tie breaker for trees of equal frequency
+ ///
+ internal byte[] depth = new byte[2 * L_CODES + 1];
+
+ public Deflate()
+ {
+ dyn_ltree = new short[HEAP_SIZE * 2];
+ dyn_dtree = new short[(2 * D_CODES + 1) * 2]; // distance tree
+ bl_tree = new short[(2 * BL_CODES + 1) * 2]; // Huffman tree for bit lengths
+ }
+
+ public Deflate(CompressionLevel level)
+ : this()
+ {
+ this.deflateInit(level);
+ }
+
+ public Deflate(CompressionLevel level, bool nowrap)
+ : this()
+ {
+ this.deflateInit(level, nowrap);
+ }
+
+ // Restore the heap property by moving down the tree starting at node k,
+ // exchanging a node with the smallest of its two sons if necessary, stopping
+ // when the heap property is re-established (each father smaller than its
+ // two sons).
+ internal void pqdownheap(short[] tree, // the tree to restore
+ int k // node to move down
+ )
+ {
+ int v = heap[k];
+ int j = k << 1; // left son of k
+ while (j <= heap_len)
+ {
+ // Set j to the smallest of the two sons:
+ if (j < heap_len &&
+ smaller(tree, heap[j + 1], heap[j], depth))
+ {
+ j++;
+ }
+ // Exit if v is smaller than both sons
+ if (smaller(tree, v, heap[j], depth)) break;
+
+ // Exchange v with the smallest son
+ heap[k] = heap[j]; k = j;
+ // And continue down the tree, setting j to the left son of k
+ j <<= 1;
+ }
+ heap[k] = v;
+ }
+
+ public ZLibStatus deflateInit(CompressionLevel level)
+ {
+ return deflateInit(level, MAX_WBITS);
+ }
+ public ZLibStatus deflateInit(CompressionLevel level, bool nowrap)
+ {
+ return deflateInit(level, MAX_WBITS, nowrap);
+ }
+
+ public ZLibStatus deflateInit(CompressionLevel level, int bits, bool nowrap)
+ {
+ return this.deflateInit(level, nowrap ? -bits : bits);
+ }
+
+ internal ZLibStatus deflateInit(CompressionLevel level, int bits)
+ {
+ return deflateInit2(level, Z_DEFLATED, bits, DEF_MEM_LEVEL, CompressionStrategy.Z_DEFAULT_STRATEGY);
+ }
+
+ private ZLibStatus deflateInit2(CompressionLevel level, int method, int windowBits, int memLevel, CompressionStrategy strategy)
+ {
+ int noheader = 0;
+ // byte[] my_version=ZLIB_VERSION;
+
+ //
+ // if (version == null || version[0] != my_version[0]
+ // || stream_size != sizeof(z_stream)) {
+ // return Z_VERSION_ERROR;
+ // }
+
+ base.msg = null;
+
+ if (level == CompressionLevel.Z_DEFAULT_COMPRESSION) level = (CompressionLevel)6;
+
+ if (windowBits < 0)
+ { // undocumented feature: suppress zlib header
+ noheader = 1;
+ windowBits = -windowBits;
+ }
+
+ if (memLevel < 1 || memLevel > MAX_MEM_LEVEL ||
+ method != Z_DEFLATED ||
+ windowBits < 9 || windowBits > 15 || level < 0 || level > (CompressionLevel)9 ||
+ strategy < 0 || strategy > CompressionStrategy.Z_HUFFMAN_ONLY)
+ {
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+
+ this.noheader = noheader;
+ _windowBits = windowBits;
+ _windowSize = 1 << _windowBits;
+ _windowMask = _windowSize - 1;
+
+ _hashBits = memLevel + 7;
+ _hashSize = 1 << _hashBits;
+ _hashMask = _hashSize - 1;
+ _hashShift = ((_hashBits + MIN_MATCH - 1) / MIN_MATCH);
+
+ _window = new byte[_windowSize * 2];
+ _previous = new short[_windowSize];
+ _head = new short[_hashSize];
+
+ lit_bufsize = 1 << (memLevel + 6); // 16K elements by default
+
+ // We overlay pending_buf and d_buf+l_buf. This works since the average
+ // output size for (length,distance) codes is <= 24 bits.
+ pending_buf = new byte[lit_bufsize * 4];
+ _pendingBufferSize = lit_bufsize * 4;
+
+ d_buf = lit_bufsize / 2;
+ l_buf = (1 + 2) * lit_bufsize;
+
+ this.level = level;
+
+ //System.out.println("level="+level);
+
+ this.strategy = strategy;
+ this._method = (byte)method;
+
+ return deflateReset();
+ }
+
+ private ZLibStatus deflateReset()
+ {
+ base.total_in = base.total_out = 0;
+ base.msg = null; //
+ base.data_type = BlockType.Z_UNKNOWN;
+
+ pending = 0;
+ pending_out = 0;
+
+ if (noheader < 0)
+ {
+ noheader = 0; // was set to -1 by deflate(..., FlushType.Z_FINISH);
+ }
+ _status = (noheader != 0) ? BUSY_STATE : INIT_STATE;
+ base.adler = Adler32.adler32(0, null, 0, 0);
+
+ last_flush = FlushType.Z_NO_FLUSH;
+
+ tr_init();
+ lm_init();
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus deflateEnd()
+ {
+ if (_status != INIT_STATE && _status != BUSY_STATE && _status != FINISH_STATE)
+ {
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+ // Deallocate in reverse order of allocations:
+ pending_buf = null;
+ _head = null;
+ _previous = null;
+ _window = null;
+ // free
+ // dstate=null;
+ return _status == BUSY_STATE ? ZLibStatus.Z_DATA_ERROR : ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus deflateParams(CompressionLevel _level, CompressionStrategy _strategy)
+ {
+ ZLibStatus err = ZLibStatus.Z_OK;
+
+ if (_level == CompressionLevel.Z_DEFAULT_COMPRESSION)
+ {
+ _level = (CompressionLevel)6;
+ }
+ if (_level < 0 || _level > (CompressionLevel)9 ||
+ _strategy < 0 || _strategy > CompressionStrategy.Z_HUFFMAN_ONLY)
+ {
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+
+ if (config_table[level].Function != config_table[_level].Function &&
+ base.total_in != 0)
+ {
+ // Flush the last buffer:
+ err = this.deflate(FlushType.Z_PARTIAL_FLUSH);
+ }
+
+ if (level != _level)
+ {
+ level = _level;
+ _maxLazyMatch = config_table[level].MaxLazy;
+ good_match = config_table[level].GoodLength;
+ nice_match = config_table[level].NiceLength;
+ _maxChainLength = config_table[level].MaxChain;
+ }
+ strategy = _strategy;
+ return err;
+ }
+
+ public ZLibStatus deflateSetDictionary(byte[] dictionary, int dictLength)
+ {
+ int length = dictLength;
+ int index = 0;
+
+ if (dictionary == null || _status != INIT_STATE)
+ return ZLibStatus.Z_STREAM_ERROR;
+
+ base.adler = Adler32.adler32(base.adler, dictionary, 0, dictLength);
+
+ if (length < MIN_MATCH) return ZLibStatus.Z_OK;
+ if (length > _windowSize - MIN_LOOKAHEAD)
+ {
+ length = _windowSize - MIN_LOOKAHEAD;
+ index = dictLength - length; // use the tail of the dictionary
+ }
+ System.Array.Copy(dictionary, index, _window, 0, length);
+ _startInsertString = length;
+ _blockStart = length;
+
+ // Insert all strings in the hash table (except for the last two bytes).
+ // s->lookahead stays null, so s->ins_h will be recomputed at the next
+ // call of fill_window.
+
+ _insertedHashIndex = _window[0] & 0xff;
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[1] & 0xff)) & _hashMask;
+
+ for (int n = 0; n <= length - MIN_MATCH; n++)
+ {
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[(n) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+ _previous[n & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)n;
+ }
+ return ZLibStatus.Z_OK;
+ }
+
+ private void lm_init()
+ {
+ _windowActualSize = 2 * _windowSize;
+
+ _head[_hashSize - 1] = 0;
+ for (int i = 0; i < _hashSize - 1; i++)
+ {
+ _head[i] = 0;
+ }
+
+ // Set the default configuration parameters:
+ _maxLazyMatch = Deflate.config_table[level].MaxLazy;
+ good_match = Deflate.config_table[level].GoodLength;
+ nice_match = Deflate.config_table[level].NiceLength;
+ _maxChainLength = Deflate.config_table[level].MaxChain;
+
+ _startInsertString = 0;
+ _blockStart = 0;
+ _validBytesAhead = 0;
+ _matchLength = _previousLength = MIN_MATCH - 1;
+ _matchAvailable = false;
+ _insertedHashIndex = 0;
+ }
+
+ // Initialize the tree data structures for a new zlib stream.
+ private void tr_init()
+ {
+
+ l_desc.Init(dyn_ltree, Deflate.static_l_desc);
+
+ d_desc.Init(dyn_dtree, Deflate.static_d_desc);
+
+ bl_desc.Init(bl_tree, Deflate.static_bl_desc);
+
+
+ bi_buf = 0;
+ bi_valid = 0;
+ last_eob_len = 8; // enough lookahead for inflate
+
+ // Initialize the first block of the first file:
+ init_block();
+ }
+
+ private void init_block()
+ {
+ // Initialize the trees.
+ for (int i = 0; i < L_CODES; i++) dyn_ltree[i * 2] = 0;
+ for (int i = 0; i < D_CODES; i++) dyn_dtree[i * 2] = 0;
+ for (int i = 0; i < BL_CODES; i++) bl_tree[i * 2] = 0;
+
+ dyn_ltree[END_BLOCK * 2] = 1;
+ opt_len = static_len = 0;
+ last_lit = matches = 0;
+ }
+
+ private static bool smaller(short[] tree, int n, int m, byte[] depth)
+ {
+ short tn2 = tree[n * 2];
+ short tm2 = tree[m * 2];
+ return (tn2 < tm2 ||
+ (tn2 == tm2 && depth[n] <= depth[m]));
+ }
+
+ // Scan a literal or distance tree to determine the frequencies of the codes
+ // in the bit length tree.
+ private void scan_tree(short[] tree,// the tree to be scanned
+ int max_code // and its largest code of non zero frequency
+ )
+ {
+ int n; // iterates over all tree elements
+ int prevlen = -1; // last emitted length
+ int curlen; // length of current code
+ int nextlen = tree[0 * 2 + 1]; // length of next code
+ int count = 0; // repeat count of the current code
+ int max_count = 7; // max repeat count
+ int min_count = 4; // min repeat count
+
+ if (nextlen == 0) { max_count = 138; min_count = 3; }
+ tree[(max_code + 1) * 2 + 1] = -1; // guard
+
+ for (n = 0; n <= max_code; n++)
+ {
+ curlen = nextlen; nextlen = tree[(n + 1) * 2 + 1];
+ if (++count < max_count && curlen == nextlen)
+ {
+ continue;
+ }
+ else if (count < min_count)
+ {
+ bl_tree[curlen * 2] += (short)count;
+ }
+ else if (curlen != 0)
+ {
+ if (curlen != prevlen) bl_tree[curlen * 2]++;
+ bl_tree[REP_3_6 * 2]++;
+ }
+ else if (count <= 10)
+ {
+ bl_tree[REPZ_3_10 * 2]++;
+ }
+ else
+ {
+ bl_tree[REPZ_11_138 * 2]++;
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0)
+ {
+ max_count = 138; min_count = 3;
+ }
+ else if (curlen == nextlen)
+ {
+ max_count = 6; min_count = 3;
+ }
+ else
+ {
+ max_count = 7; min_count = 4;
+ }
+ }
+ }
+
+ // Construct the Huffman tree for the bit lengths and return the index in
+ // bl_order of the last bit length code to send.
+ private int build_bl_tree()
+ {
+ int max_blindex; // index of last bit length code of non zero freq
+
+ // Determine the bit length frequencies for literal and distance trees
+ scan_tree(dyn_ltree, l_desc.LargestCode);
+ scan_tree(dyn_dtree, d_desc.LargestCode);
+
+ // Build the bit length tree:
+ bl_desc.BuildTree(this);
+ // opt_len now includes the length of the tree representations, except
+ // the lengths of the bit lengths codes and the 5+5+4 bits for the counts.
+
+ // Determine the number of bit length codes to send. The pkzip format
+ // requires that at least 4 bit length codes be sent. (appnote.txt says
+ // 3 but the actual value used is 4.)
+ for (max_blindex = BL_CODES - 1; max_blindex >= 3; max_blindex--)
+ {
+ if (bl_tree[Deflate.bl_order[max_blindex] * 2 + 1] != 0) break;
+ }
+ // Update opt_len to include the bit length tree and counts
+ opt_len += 3 * (max_blindex + 1) + 5 + 5 + 4;
+
+ return max_blindex;
+ }
+
+
+ // Send the header for a block using dynamic Huffman trees: the counts, the
+ // lengths of the bit length codes, the literal tree and the distance tree.
+ // IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
+ private void send_all_trees(int lcodes, int dcodes, int blcodes)
+ {
+ int rank; // index in bl_order
+
+ send_bits(lcodes - 257, 5); // not +255 as stated in appnote.txt
+ send_bits(dcodes - 1, 5);
+ send_bits(blcodes - 4, 4); // not -3 as stated in appnote.txt
+ for (rank = 0; rank < blcodes; rank++)
+ {
+ send_bits(bl_tree[Deflate.bl_order[rank] * 2 + 1], 3);
+ }
+ send_tree(dyn_ltree, lcodes - 1); // literal tree
+ send_tree(dyn_dtree, dcodes - 1); // distance tree
+ }
+
+ // Send a literal or distance tree in compressed form, using the codes in
+ // bl_tree.
+ private void send_tree(short[] tree,// the tree to be sent
+ int max_code // and its largest code of non zero frequency
+ )
+ {
+ int n; // iterates over all tree elements
+ int prevlen = -1; // last emitted length
+ int curlen; // length of current code
+ int nextlen = tree[0 * 2 + 1]; // length of next code
+ int count = 0; // repeat count of the current code
+ int max_count = 7; // max repeat count
+ int min_count = 4; // min repeat count
+
+ if (nextlen == 0) { max_count = 138; min_count = 3; }
+
+ for (n = 0; n <= max_code; n++)
+ {
+ curlen = nextlen; nextlen = tree[(n + 1) * 2 + 1];
+ if (++count < max_count && curlen == nextlen)
+ {
+ continue;
+ }
+ else if (count < min_count)
+ {
+ do { send_code(curlen, bl_tree); } while (--count != 0);
+ }
+ else if (curlen != 0)
+ {
+ if (curlen != prevlen)
+ {
+ send_code(curlen, bl_tree); count--;
+ }
+ send_code(REP_3_6, bl_tree);
+ send_bits(count - 3, 2);
+ }
+ else if (count <= 10)
+ {
+ send_code(REPZ_3_10, bl_tree);
+ send_bits(count - 3, 3);
+ }
+ else
+ {
+ send_code(REPZ_11_138, bl_tree);
+ send_bits(count - 11, 7);
+ }
+ count = 0; prevlen = curlen;
+ if (nextlen == 0)
+ {
+ max_count = 138; min_count = 3;
+ }
+ else if (curlen == nextlen)
+ {
+ max_count = 6; min_count = 3;
+ }
+ else
+ {
+ max_count = 7; min_count = 4;
+ }
+ }
+ }
+
+ // Output a byte on the stream.
+ // IN assertion: there is enough room in pending_buf.
+ private void put_byte(byte[] p, int start, int len)
+ {
+ System.Array.Copy(p, start, pending_buf, pending, len);
+ pending += len;
+ }
+
+ private void put_byte(byte c)
+ {
+ pending_buf[pending++] = c;
+ }
+ private void put_short(int w)
+ {
+ pending_buf[pending++] = (byte)(w/*&0xff*/);
+ pending_buf[pending++] = (byte)(w >> 8);
+ }
+ private void putShortMSB(int b)
+ {
+ pending_buf[pending++] = (byte)(b >> 8);
+ pending_buf[pending++] = (byte)(b/*&0xff*/);
+ }
+
+ private void send_code(int c, short[] tree)
+ {
+ int c2 = c * 2;
+ send_bits((tree[c2] & 0xffff), (tree[c2 + 1] & 0xffff));
+ }
+
+ private void send_bits(int val, int length)
+ {
+ if (bi_valid > Buf_size - length)
+ {
+ bi_buf |= (uint)(val << bi_valid);
+ pending_buf[pending++] = (byte)(bi_buf/*&0xff*/);
+ pending_buf[pending++] = (byte)(bi_buf >> 8);
+ bi_buf = ((uint)val) >> (Buf_size - bi_valid);
+ bi_valid += length - Buf_size;
+ }
+ else
+ {
+ bi_buf |= (uint)(val << bi_valid);
+ bi_valid += length;
+ }
+ // int len = length;
+ // if (bi_valid > (int)Buf_size - len) {
+ // int val = value;
+ // // bi_buf |= (val << bi_valid);
+ // bi_buf = (short)((ushort)bi_buf | (ushort)((val << bi_valid)&0xffff));
+ // put_short(bi_buf);
+ // bi_buf = (short)(((uint)val) >> (Buf_size - bi_valid));
+ // bi_valid += len - Buf_size;
+ // } else {
+ // // bi_buf |= (value) << bi_valid;
+ // bi_buf = (short)((ushort)bi_buf | (ushort)(((value) << bi_valid)&0xffff));
+ // bi_valid += len;
+ // }
+ }
+
+ // Send one empty static block to give enough lookahead for inflate.
+ // This takes 10 bits, of which 7 may remain in the bit buffer.
+ // The current inflate code requires 9 bits of lookahead. If the
+ // last two codes for the previous block (real code plus EOB) were coded
+ // on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode
+ // the last real code. In this case we send two empty static blocks instead
+ // of one. (There are no problems if the previous block is stored or fixed.)
+ // To simplify the code, we assume the worst case of last real code encoded
+ // on one bit only.
+ private void _tr_align()
+ {
+ send_bits(STATIC_TREES << 1, 3);
+ send_code(END_BLOCK, Deflate.static_ltree);
+
+ bi_flush();
+
+ // Of the 10 bits for the empty block, we have already sent
+ // (10 - bi_valid) bits. The lookahead for the last real code (before
+ // the EOB of the previous block) was thus at least one plus the length
+ // of the EOB plus what we have just sent of the empty static block.
+ if (1 + last_eob_len + 10 - bi_valid < 9)
+ {
+ send_bits(STATIC_TREES << 1, 3);
+ send_code(END_BLOCK, Deflate.static_ltree);
+ bi_flush();
+ }
+ last_eob_len = 7;
+ }
+
+
+ // Save the match info and tally the frequency counts. Return true if
+ // the current block must be flushed.
+ private bool _tr_tally(int dist, // distance of matched string
+ int lc // match length-MIN_MATCH or unmatched char (if dist==0)
+ )
+ {
+
+ pending_buf[d_buf + last_lit * 2] = (byte)(dist >> 8);
+ pending_buf[d_buf + last_lit * 2 + 1] = (byte)dist;
+
+ pending_buf[l_buf + last_lit] = (byte)lc; last_lit++;
+
+ if (dist == 0)
+ {
+ // lc is the unmatched char
+ dyn_ltree[lc * 2]++;
+ }
+ else
+ {
+ matches++;
+ // Here, lc is the match length - MIN_MATCH
+ dist--; // dist = match distance - 1
+ dyn_ltree[(Deflate._length_code[lc] + LITERALS + 1) * 2]++;
+ dyn_dtree[Tree.DistanceCode(dist) * 2]++;
+ }
+
+ if ((last_lit & 0x1fff) == 0 && level > (CompressionLevel)2)
+ {
+ // Compute an upper bound for the compressed length
+ int out_length = last_lit * 8;
+ int in_length = _startInsertString - _blockStart;
+ int dcode;
+ for (dcode = 0; dcode < D_CODES; dcode++)
+ {
+ out_length += (int)((int)dyn_dtree[dcode * 2] *
+ (5L + Deflate.extra_dbits[dcode]));
+ }
+ out_length >>= 3;
+ if ((matches < (last_lit / 2)) && out_length < in_length / 2) return true;
+ }
+
+ return (last_lit == lit_bufsize - 1);
+ // We avoid equality with lit_bufsize because of wraparound at 64K
+ // on 16 bit machines and because stored blocks are restricted to
+ // 64K-1 bytes.
+ }
+
+ // Send the block data compressed using the given Huffman trees
+ private void compress_block(short[] ltree, short[] dtree)
+ {
+ int dist; // distance of matched string
+ int lc; // match length or unmatched char (if dist == 0)
+ int lx = 0; // running index in l_buf
+ int code; // the code to send
+ int extra; // number of extra bits to send
+
+ if (last_lit != 0)
+ {
+ do
+ {
+ dist = ((pending_buf[d_buf + lx * 2] << 8) & 0xff00) |
+ (pending_buf[d_buf + lx * 2 + 1] & 0xff);
+ lc = (pending_buf[l_buf + lx]) & 0xff; lx++;
+
+ if (dist == 0)
+ {
+ send_code(lc, ltree); // send a literal byte
+ }
+ else
+ {
+ // Here, lc is the match length - MIN_MATCH
+ code = Deflate._length_code[lc];
+
+ send_code(code + LITERALS + 1, ltree); // send the length code
+ extra = Deflate.extra_lbits[code];
+ if (extra != 0)
+ {
+ lc -= Deflate.base_length[code];
+ send_bits(lc, extra); // send the extra length bits
+ }
+ dist--; // dist is now the match distance - 1
+ code = Tree.DistanceCode(dist);
+
+ send_code(code, dtree); // send the distance code
+ extra = Deflate.extra_dbits[code];
+ if (extra != 0)
+ {
+ dist -= Deflate.base_dist[code];
+ send_bits(dist, extra); // send the extra distance bits
+ }
+ } // literal or match pair ?
+
+ // Check that the overlay between pending_buf and d_buf+l_buf is ok:
+ }
+ while (lx < last_lit);
+ }
+
+ send_code(END_BLOCK, ltree);
+ last_eob_len = ltree[END_BLOCK * 2 + 1];
+ }
+
+ // Set the data type to ASCII or BINARY, using a crude approximation:
+ // binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise.
+ // IN assertion: the fields freq of dyn_ltree are set and the total of all
+ // frequencies does not exceed 64K (to fit in an int on 16 bit machines).
+ private void set_data_type()
+ {
+ int n = 0;
+ int ascii_freq = 0;
+ int bin_freq = 0;
+ while (n < 7) { bin_freq += dyn_ltree[n * 2]; n++; }
+ while (n < 128) { ascii_freq += dyn_ltree[n * 2]; n++; }
+ while (n < LITERALS) { bin_freq += dyn_ltree[n * 2]; n++; }
+ this._dataType = (bin_freq > (ascii_freq >> 2) ? BlockType.Z_BINARY : BlockType.Z_ASCII);
+ }
+
+ // Flush the bit buffer, keeping at most 7 bits in it.
+ private void bi_flush()
+ {
+ if (bi_valid == 16)
+ {
+ pending_buf[pending++] = (byte)(bi_buf/*&0xff*/);
+ pending_buf[pending++] = (byte)(bi_buf >> 8);
+ bi_buf = 0;
+ bi_valid = 0;
+ }
+ else if (bi_valid >= 8)
+ {
+ pending_buf[pending++] = (byte)(bi_buf);
+ bi_buf >>= 8;
+ bi_buf &= 0x00ff;
+ bi_valid -= 8;
+ }
+ }
+
+ // Flush the bit buffer and align the output on a byte boundary
+ private void bi_windup()
+ {
+ if (bi_valid > 8)
+ {
+ pending_buf[pending++] = (byte)(bi_buf);
+ pending_buf[pending++] = (byte)(bi_buf >> 8);
+ }
+ else if (bi_valid > 0)
+ {
+ pending_buf[pending++] = (byte)(bi_buf);
+ }
+ bi_buf = 0;
+ bi_valid = 0;
+ }
+
+ // Copy a stored block, storing first the length and its
+ // one's complement if requested.
+ private void copy_block(int buf, // the input data
+ int len, // its length
+ bool header // true if block header must be written
+ )
+ {
+ //int index=0;
+ bi_windup(); // align on byte boundary
+ last_eob_len = 8; // enough lookahead for inflate
+
+ if (header)
+ {
+ put_short((short)len);
+ put_short((short)~len);
+ }
+
+ // while(len--!=0) {
+ // put_byte(window[buf+index]);
+ // index++;
+ // }
+ put_byte(_window, buf, len);
+ }
+
+ private void flush_block_only(bool eof)
+ {
+ _tr_flush_block(_blockStart >= 0 ? _blockStart : -1,
+ _startInsertString - _blockStart,
+ eof);
+ _blockStart = _startInsertString;
+ this.flush_pending();
+ }
+
+ // Copy without compression as much as possible from the input stream, return
+ // the current block state.
+ // This function does not insert new strings in the dictionary since
+ // uncompressible data is probably not useful. This function is used
+ // only for the level=0 compression option.
+ // NOTE: this function should be optimized to avoid extra copying from
+ // window to pending_buf.
+ private int deflate_stored(FlushType flush)
+ {
+ // Stored blocks are limited to 0xffff bytes, pending_buf is limited
+ // to pending_buf_size, and each stored block has a 5 byte header:
+
+ int max_block_size = 0xffff;
+ int max_start;
+
+ if (max_block_size > _pendingBufferSize - 5)
+ {
+ max_block_size = _pendingBufferSize - 5;
+ }
+
+ // Copy as much as possible from input to output:
+ while (true)
+ {
+ // Fill the window as much as possible:
+ if (_validBytesAhead <= 1)
+ {
+ fill_window();
+ if (_validBytesAhead == 0 && flush == FlushType.Z_NO_FLUSH) return NeedMore;
+ if (_validBytesAhead == 0) break; // flush the current block
+ }
+
+ _startInsertString += _validBytesAhead;
+ _validBytesAhead = 0;
+
+ // Emit a stored block if pending_buf will be full:
+ max_start = _blockStart + max_block_size;
+ if (_startInsertString == 0 || _startInsertString >= max_start)
+ {
+ // strstart == 0 is possible when wraparound on 16-bit machine
+ _validBytesAhead = (int)(_startInsertString - max_start);
+ _startInsertString = (int)max_start;
+
+ flush_block_only(false);
+ if (base.avail_out == 0) return NeedMore;
+
+ }
+
+ // Flush if we may have to slide, otherwise block_start may become
+ // negative and the data will be gone:
+ if (_startInsertString - _blockStart >= _windowSize - MIN_LOOKAHEAD)
+ {
+ flush_block_only(false);
+ if (base.avail_out == 0) return NeedMore;
+ }
+ }
+
+ flush_block_only(flush == FlushType.Z_FINISH);
+ if (base.avail_out == 0)
+ return (flush == FlushType.Z_FINISH) ? FinishStarted : NeedMore;
+
+ return flush == FlushType.Z_FINISH ? FinishDone : BlockDone;
+ }
+
+ // Send a stored block
+ private void _tr_stored_block(int buf, // input block
+ int stored_len, // length of input block
+ bool eof // true if this is the last block for a file
+ )
+ {
+ send_bits((STORED_BLOCK << 1) + (eof ? 1 : 0), 3); // send block type
+ copy_block(buf, stored_len, true); // with header
+ }
+
+ // Determine the best encoding for the current block: dynamic trees, static
+ // trees or store, and output the encoded block to the zip file.
+ private void _tr_flush_block(int buf, // input block, or NULL if too old
+ int stored_len, // length of input block
+ bool eof // true if this is the last block for a file
+ )
+ {
+ int opt_lenb, static_lenb;// opt_len and static_len in bytes
+ int max_blindex = 0; // index of last bit length code of non zero freq
+
+ // Build the Huffman trees unless a stored block is forced
+ if (level > 0)
+ {
+ // Check if the file is ascii or binary
+ if (this._dataType == BlockType.Z_UNKNOWN) set_data_type();
+
+ // Construct the literal and distance trees
+ l_desc.BuildTree(this);
+
+ d_desc.BuildTree(this);
+
+ // At this point, opt_len and static_len are the total bit lengths of
+ // the compressed block data, excluding the tree representations.
+
+ // Build the bit length tree for the above two trees, and get the index
+ // in bl_order of the last bit length code to send.
+ max_blindex = build_bl_tree();
+
+ // Determine the best encoding. Compute first the block length in bytes
+ opt_lenb = (opt_len + 3 + 7) >> 3;
+ static_lenb = (static_len + 3 + 7) >> 3;
+
+ if (static_lenb <= opt_lenb) opt_lenb = static_lenb;
+ }
+ else
+ {
+ opt_lenb = static_lenb = stored_len + 5; // force a stored block
+ }
+
+ if (stored_len + 4 <= opt_lenb && buf != -1)
+ {
+ // 4: two words for the lengths
+ // The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
+ // Otherwise we can't have processed more than WSIZE input bytes since
+ // the last block flush, because compression would have been
+ // successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
+ // transform a block into a stored block.
+ _tr_stored_block(buf, stored_len, eof);
+ }
+ else if (static_lenb == opt_lenb)
+ {
+ send_bits((STATIC_TREES << 1) + (eof ? 1 : 0), 3);
+ compress_block(Deflate.static_ltree, Deflate.static_dtree);
+ }
+ else
+ {
+ send_bits((DYN_TREES << 1) + (eof ? 1 : 0), 3);
+ send_all_trees(l_desc.LargestCode + 1, d_desc.LargestCode + 1, max_blindex + 1);
+ compress_block(dyn_ltree, dyn_dtree);
+ }
+
+ // The above check is made mod 2^32, for files larger than 512 MB
+ // and uLong implemented on 32 bits.
+
+ init_block();
+
+ if (eof)
+ {
+ bi_windup();
+ }
+ }
+
+ // Fill the window when the lookahead becomes insufficient.
+ // Updates strstart and lookahead.
+ //
+ // IN assertion: lookahead < MIN_LOOKAHEAD
+ // OUT assertions: strstart <= window_size-MIN_LOOKAHEAD
+ // At least one byte has been read, or avail_in == 0; reads are
+ // performed for at least two bytes (required for the zip translate_eol
+ // option -- not supported here).
+ private void fill_window()
+ {
+ int n, m;
+ int p;
+ int more; // Amount of free space at the end of the window.
+
+ do
+ {
+ more = (_windowActualSize - _validBytesAhead - _startInsertString);
+
+ // Deal with !@#$% 64K limit:
+ if (more == 0 && _startInsertString == 0 && _validBytesAhead == 0)
+ {
+ more = _windowSize;
+ }
+ else if (more == -1)
+ {
+ // Very unlikely, but possible on 16 bit machine if strstart == 0
+ // and lookahead == 1 (input done one byte at time)
+ more--;
+
+ // If the window is almost full and there is insufficient lookahead,
+ // move the upper half to the lower one to make room in the upper half.
+ }
+ else if (_startInsertString >= _windowSize + _windowSize - MIN_LOOKAHEAD)
+ {
+ System.Array.Copy(_window, _windowSize, _window, 0, _windowSize);
+ _startMatchString -= _windowSize;
+ _startInsertString -= _windowSize; // we now have strstart >= MAX_DIST
+ _blockStart -= _windowSize;
+
+ // Slide the hash table (could be avoided with 32 bit values
+ // at the expense of memory usage). We slide even when level == 0
+ // to keep the hash table consistent if we switch back to level > 0
+ // later. (Using level 0 permanently is not an optimal usage of
+ // zlib, so we don't care about this pathological case.)
+
+ n = _hashSize;
+ p = n;
+ do
+ {
+ m = (_head[--p] & 0xffff);
+ _head[p] = (short)(m >= _windowSize ? (m - _windowSize) : 0);
+ }
+ while (--n != 0);
+
+ n = _windowSize;
+ p = n;
+ do
+ {
+ m = (_previous[--p] & 0xffff);
+ _previous[p] = (short)(m >= _windowSize ? (m - _windowSize) : 0);
+ // If n is not on any hash chain, prev[n] is garbage but
+ // its value will never be used.
+ }
+ while (--n != 0);
+ more += _windowSize;
+ }
+
+ if (base.avail_in == 0) return;
+
+ // If there was no sliding:
+ // strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 &&
+ // more == window_size - lookahead - strstart
+ // => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1)
+ // => more >= window_size - 2*WSIZE + 2
+ // In the BIG_MEM or MMAP case (not yet supported),
+ // window_size == input_size + MIN_LOOKAHEAD &&
+ // strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD.
+ // Otherwise, window_size == 2*WSIZE so more >= 2.
+ // If there was sliding, more >= WSIZE. So in all cases, more >= 2.
+
+ n = this.read_buf(_window, _startInsertString + _validBytesAhead, more);
+ _validBytesAhead += n;
+
+ // Initialize the hash value now that we have some input:
+ if (_validBytesAhead >= MIN_MATCH)
+ {
+ _insertedHashIndex = _window[_startInsertString] & 0xff;
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[_startInsertString + 1] & 0xff)) & _hashMask;
+ }
+ // If the whole input has less than MIN_MATCH bytes, ins_h is garbage,
+ // but this is not important since only literal bytes will be emitted.
+ }
+ while (_validBytesAhead < MIN_LOOKAHEAD && base.avail_in != 0);
+ }
+
+ // Compress as much as possible from the input stream, return the current
+ // block state.
+ // This function does not perform lazy evaluation of matches and inserts
+ // new strings in the dictionary only for unmatched strings or for short
+ // matches. It is used only for the fast compression options.
+ private int deflate_fast(FlushType flush)
+ {
+ // short hash_head = 0; // head of the hash chain
+ int hash_head = 0; // head of the hash chain
+ bool bflush; // set if current block must be flushed
+
+ while (true)
+ {
+ // Make sure that we always have enough lookahead, except
+ // at the end of the input file. We need MAX_MATCH bytes
+ // for the next match, plus MIN_MATCH bytes to insert the
+ // string following the next match.
+ if (_validBytesAhead < MIN_LOOKAHEAD)
+ {
+ fill_window();
+ if (_validBytesAhead < MIN_LOOKAHEAD && flush == FlushType.Z_NO_FLUSH)
+ {
+ return NeedMore;
+ }
+ if (_validBytesAhead == 0) break; // flush the current block
+ }
+
+ // Insert the string window[strstart .. strstart+2] in the
+ // dictionary, and set hash_head to the head of the hash chain:
+ if (_validBytesAhead >= MIN_MATCH)
+ {
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[(_startInsertString) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+
+ // prev[strstart&w_mask]=hash_head=head[ins_h];
+ hash_head = (_head[_insertedHashIndex] & 0xffff);
+ _previous[_startInsertString & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)_startInsertString;
+ }
+
+ // Find the longest match, discarding those <= prev_length.
+ // At this point we have always match_length < MIN_MATCH
+
+ if (hash_head != 0L &&
+ ((_startInsertString - hash_head) & 0xffff) <= _windowSize - MIN_LOOKAHEAD
+ )
+ {
+ // To simplify the code, we prevent matches with the string
+ // of window index 0 (in particular we have to avoid a match
+ // of the string with itself at the start of the input file).
+ if (strategy != CompressionStrategy.Z_HUFFMAN_ONLY)
+ {
+ _matchLength = longest_match(hash_head);
+ }
+ // longest_match() sets match_start
+ }
+ if (_matchLength >= MIN_MATCH)
+ {
+ // check_match(strstart, match_start, match_length);
+
+ bflush = _tr_tally(_startInsertString - _startMatchString, _matchLength - MIN_MATCH);
+
+ _validBytesAhead -= _matchLength;
+
+ // Insert new strings in the hash table only if the match length
+ // is not too large. This saves time but degrades compression.
+ if (_matchLength <= _maxLazyMatch &&
+ _validBytesAhead >= MIN_MATCH)
+ {
+ _matchLength--; // string at strstart already in hash table
+ do
+ {
+ _startInsertString++;
+
+ _insertedHashIndex = ((_insertedHashIndex << _hashShift) ^ (_window[(_startInsertString) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+ // prev[strstart&w_mask]=hash_head=head[ins_h];
+ hash_head = (_head[_insertedHashIndex] & 0xffff);
+ _previous[_startInsertString & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)_startInsertString;
+
+ // strstart never exceeds WSIZE-MAX_MATCH, so there are
+ // always MIN_MATCH bytes ahead.
+ }
+ while (--_matchLength != 0);
+ _startInsertString++;
+ }
+ else
+ {
+ _startInsertString += _matchLength;
+ _matchLength = 0;
+ _insertedHashIndex = _window[_startInsertString] & 0xff;
+
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[_startInsertString + 1] & 0xff)) & _hashMask;
+ // If lookahead < MIN_MATCH, ins_h is garbage, but it does not
+ // matter since it will be recomputed at next deflate call.
+ }
+ }
+ else
+ {
+ // No match, output a literal byte
+
+ bflush = _tr_tally(0, _window[_startInsertString] & 0xff);
+ _validBytesAhead--;
+ _startInsertString++;
+ }
+ if (bflush)
+ {
+
+ flush_block_only(false);
+ if (base.avail_out == 0) return NeedMore;
+ }
+ }
+
+ flush_block_only(flush == FlushType.Z_FINISH);
+ if (base.avail_out == 0)
+ {
+ if (flush == FlushType.Z_FINISH) return FinishStarted;
+ else return NeedMore;
+ }
+ return flush == FlushType.Z_FINISH ? FinishDone : BlockDone;
+ }
+
+ // Same as above, but achieves better compression. We use a lazy
+ // evaluation for matches: a match is finally adopted only if there is
+ // no better match at the next window position.
+ private int deflate_slow(FlushType flush)
+ {
+ // short hash_head = 0; // head of hash chain
+ int hash_head = 0; // head of hash chain
+ bool bflush; // set if current block must be flushed
+
+ // Process the input block.
+ while (true)
+ {
+ // Make sure that we always have enough lookahead, except
+ // at the end of the input file. We need MAX_MATCH bytes
+ // for the next match, plus MIN_MATCH bytes to insert the
+ // string following the next match.
+
+ if (_validBytesAhead < MIN_LOOKAHEAD)
+ {
+ fill_window();
+ if (_validBytesAhead < MIN_LOOKAHEAD && flush == FlushType.Z_NO_FLUSH)
+ {
+ return NeedMore;
+ }
+ if (_validBytesAhead == 0) break; // flush the current block
+ }
+
+ // Insert the string window[strstart .. strstart+2] in the
+ // dictionary, and set hash_head to the head of the hash chain:
+
+ if (_validBytesAhead >= MIN_MATCH)
+ {
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[(_startInsertString) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+ // prev[strstart&w_mask]=hash_head=head[ins_h];
+ hash_head = (_head[_insertedHashIndex] & 0xffff);
+ _previous[_startInsertString & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)_startInsertString;
+ }
+
+ // Find the longest match, discarding those <= prev_length.
+ _previousLength = _matchLength; _previousMatch = _startMatchString;
+ _matchLength = MIN_MATCH - 1;
+
+ if (hash_head != 0 && _previousLength < _maxLazyMatch &&
+ ((_startInsertString - hash_head) & 0xffff) <= _windowSize - MIN_LOOKAHEAD
+ )
+ {
+ // To simplify the code, we prevent matches with the string
+ // of window index 0 (in particular we have to avoid a match
+ // of the string with itself at the start of the input file).
+
+ if (strategy != CompressionStrategy.Z_HUFFMAN_ONLY)
+ {
+ _matchLength = longest_match(hash_head);
+ }
+ // longest_match() sets match_start
+
+ if (_matchLength <= 5 && (strategy == CompressionStrategy.Z_FILTERED ||
+ (_matchLength == MIN_MATCH &&
+ _startInsertString - _startMatchString > 4096)))
+ {
+
+ // If prev_match is also MIN_MATCH, match_start is garbage
+ // but we will ignore the current match anyway.
+ _matchLength = MIN_MATCH - 1;
+ }
+ }
+
+ // If there was a match at the previous step and the current
+ // match is not better, output the previous match:
+ if (_previousLength >= MIN_MATCH && _matchLength <= _previousLength)
+ {
+ int max_insert = _startInsertString + _validBytesAhead - MIN_MATCH;
+ // Do not insert strings in hash table beyond this.
+
+ // check_match(strstart-1, prev_match, prev_length);
+
+ bflush = _tr_tally(_startInsertString - 1 - _previousMatch, _previousLength - MIN_MATCH);
+
+ // Insert in hash table all strings up to the end of the match.
+ // strstart-1 and strstart are already inserted. If there is not
+ // enough lookahead, the last two strings are not inserted in
+ // the hash table.
+ _validBytesAhead -= _previousLength - 1;
+ _previousLength -= 2;
+ do
+ {
+ if (++_startInsertString <= max_insert)
+ {
+ _insertedHashIndex = (((_insertedHashIndex) << _hashShift) ^ (_window[(_startInsertString) + (MIN_MATCH - 1)] & 0xff)) & _hashMask;
+ //prev[strstart&w_mask]=hash_head=head[ins_h];
+ hash_head = (_head[_insertedHashIndex] & 0xffff);
+ _previous[_startInsertString & _windowMask] = _head[_insertedHashIndex];
+ _head[_insertedHashIndex] = (short)_startInsertString;
+ }
+ }
+ while (--_previousLength != 0);
+ _matchAvailable = false;
+ _matchLength = MIN_MATCH - 1;
+ _startInsertString++;
+
+ if (bflush)
+ {
+ flush_block_only(false);
+ if (base.avail_out == 0) return NeedMore;
+ }
+ }
+ else if (_matchAvailable != false)
+ {
+
+ // If there was no match at the previous position, output a
+ // single literal. If there was a match but the current match
+ // is longer, truncate the previous match to a single literal.
+
+ bflush = _tr_tally(0, _window[_startInsertString - 1] & 0xff);
+
+ if (bflush)
+ {
+ flush_block_only(false);
+ }
+ _startInsertString++;
+ _validBytesAhead--;
+ if (base.avail_out == 0) return NeedMore;
+ }
+ else
+ {
+ // There is no previous match to compare with, wait for
+ // the next step to decide.
+
+ _matchAvailable = true;
+ _startInsertString++;
+ _validBytesAhead--;
+ }
+ }
+
+ if (_matchAvailable != false)
+ {
+ bflush = _tr_tally(0, _window[_startInsertString - 1] & 0xff);
+ _matchAvailable = false;
+ }
+ flush_block_only(flush == FlushType.Z_FINISH);
+
+ if (base.avail_out == 0)
+ {
+ if (flush == FlushType.Z_FINISH) return FinishStarted;
+ else return NeedMore;
+ }
+
+ return flush == FlushType.Z_FINISH ? FinishDone : BlockDone;
+ }
+
+ private int longest_match(int cur_match)
+ {
+ int chain_length = _maxChainLength; // max hash chain length
+ int scan = _startInsertString; // current string
+ int match; // matched string
+ int len; // length of current match
+ int best_len = _previousLength; // best match length so far
+ int limit = _startInsertString > (_windowSize - MIN_LOOKAHEAD) ?
+ _startInsertString - (_windowSize - MIN_LOOKAHEAD) : 0;
+ int nice_match = this.nice_match;
+
+ // Stop when cur_match becomes <= limit. To simplify the code,
+ // we prevent matches with the string of window index 0.
+
+ int wmask = _windowMask;
+
+ int strend = _startInsertString + MAX_MATCH;
+ byte scan_end1 = _window[scan + best_len - 1];
+ byte scan_end = _window[scan + best_len];
+
+ // The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
+ // It is easy to get rid of this optimization if necessary.
+
+ // Do not waste too much time if we already have a good match:
+ if (_previousLength >= good_match)
+ {
+ chain_length >>= 2;
+ }
+
+ // Do not look for matches beyond the end of the input. This is necessary
+ // to make deflate deterministic.
+ if (nice_match > _validBytesAhead) nice_match = _validBytesAhead;
+
+ do
+ {
+ match = cur_match;
+
+ // Skip to next match if the match length cannot increase
+ // or if the match length is less than 2:
+ if (_window[match + best_len] != scan_end ||
+ _window[match + best_len - 1] != scan_end1 ||
+ _window[match] != _window[scan] ||
+ _window[++match] != _window[scan + 1]) continue;
+
+ // The check at best_len-1 can be removed because it will be made
+ // again later. (This heuristic is not always a win.)
+ // It is not necessary to compare scan[2] and match[2] since they
+ // are always equal when the other bytes match, given that
+ // the hash keys are equal and that HASH_BITS >= 8.
+ scan += 2; match++;
+
+ // We check for insufficient lookahead only every 8th comparison;
+ // the 256th check will be made at strstart+258.
+ do
+ {
+ } while (_window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ _window[++scan] == _window[++match] &&
+ scan < strend);
+
+ len = MAX_MATCH - (int)(strend - scan);
+ scan = strend - MAX_MATCH;
+
+ if (len > best_len)
+ {
+ _startMatchString = cur_match;
+ best_len = len;
+ if (len >= nice_match) break;
+ scan_end1 = _window[scan + best_len - 1];
+ scan_end = _window[scan + best_len];
+ }
+
+ } while ((cur_match = (_previous[cur_match & wmask] & 0xffff)) > limit
+ && --chain_length != 0);
+
+ if (best_len <= _validBytesAhead) return best_len;
+ return _validBytesAhead;
+ }
+
+ public ZLibStatus deflate(FlushType flush)
+ {
+ FlushType old_flush;
+
+ if (flush > FlushType.Z_FINISH || flush < 0)
+ {
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+
+ if (base.next_out == null ||
+ (base.next_in == null && base.avail_in != 0) ||
+ (_status == FINISH_STATE && flush != FlushType.Z_FINISH))
+ {
+ base.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_STREAM_ERROR)];
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+ if (base.avail_out == 0)
+ {
+ base.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_BUF_ERROR)];
+ return ZLibStatus.Z_BUF_ERROR;
+ }
+
+ old_flush = last_flush;
+ last_flush = flush;
+
+ // Write the zlib header
+ if (_status == INIT_STATE)
+ {
+ int header = (Z_DEFLATED + ((this._windowBits - 8) << 4)) << 8;
+ int level_flags = (((int)this.level - 1) & 0xff) >> 1;
+
+ if (level_flags > 3) level_flags = 3;
+ header |= (level_flags << 6);
+ if (this._startInsertString != 0) header |= PRESET_DICT;
+ header += 31 - (header % 31);
+
+ _status = BUSY_STATE;
+ putShortMSB(header);
+
+
+ // Save the adler32 of the preset dictionary:
+ if (this._startInsertString != 0)
+ {
+ putShortMSB((int)(base.adler >> 16));
+ putShortMSB((int)(base.adler & 0xffff));
+ }
+ base.adler = Adler32.adler32(0, null, 0, 0);
+ }
+
+ // Flush as much pending output as possible
+ if (pending != 0)
+ {
+ this.flush_pending();
+ if (base.avail_out == 0)
+ {
+ //System.out.println(" avail_out==0");
+ // Since avail_out is 0, deflate will be called again with
+ // more output space, but possibly with both pending and
+ // avail_in equal to zero. There won't be anything to do,
+ // but this is not an error situation so make sure we
+ // return OK instead of BUF_ERROR at next call of deflate:
+ last_flush = (FlushType)(-1);
+ return ZLibStatus.Z_OK;
+ }
+
+ // Make sure there is something to do and avoid duplicate consecutive
+ // flushes. For repeated and useless calls with Z_FINISH, we keep
+ // returning Z_STREAM_END instead of Z_BUFF_ERROR.
+ }
+ else if (base.avail_in == 0 && flush <= old_flush &&
+ flush != FlushType.Z_FINISH)
+ {
+ base.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_BUF_ERROR)];
+ return ZLibStatus.Z_BUF_ERROR;
+ }
+
+ // User must not provide more input after the first FINISH:
+ if (_status == FINISH_STATE && base.avail_in != 0)
+ {
+ base.msg = z_errmsg[ZLibStatus.Z_NEED_DICT - (ZLibStatus.Z_BUF_ERROR)];
+ return ZLibStatus.Z_BUF_ERROR;
+ }
+
+ // Start a new block or continue the current one.
+ if (base.avail_in != 0 || this._validBytesAhead != 0 ||
+ (flush != FlushType.Z_NO_FLUSH && _status != FINISH_STATE))
+ {
+ int bstate = -1;
+ switch (config_table[level].Function)
+ {
+ case DefalteFlavor.STORED:
+ bstate = deflate_stored(flush);
+ break;
+ case DefalteFlavor.FAST:
+ bstate = deflate_fast(flush);
+ break;
+ case DefalteFlavor.SLOW:
+ bstate = deflate_slow(flush);
+ break;
+ default:
+ break;
+ }
+
+ if (bstate == FinishStarted || bstate == FinishDone)
+ {
+ _status = FINISH_STATE;
+ }
+ if (bstate == NeedMore || bstate == FinishStarted)
+ {
+ if (base.avail_out == 0)
+ {
+ last_flush = (FlushType)(-1); // avoid BUF_ERROR next call, see above
+ }
+ return ZLibStatus.Z_OK;
+ // If flush != Z_NO_FLUSH && avail_out == 0, the next call
+ // of deflate should use the same flush parameter to make sure
+ // that the flush is complete. So we don't have to output an
+ // empty block here, this will be done at next call. This also
+ // ensures that for a very small output buffer, we emit at most
+ // one empty block.
+ }
+
+ if (bstate == BlockDone)
+ {
+ if (flush == FlushType.Z_PARTIAL_FLUSH)
+ {
+ _tr_align();
+ }
+ else
+ { // FULL_FLUSH or SYNC_FLUSH
+ _tr_stored_block(0, 0, false);
+ // For a full flush, this empty block will be recognized
+ // as a special marker by inflate_sync().
+ if (flush == FlushType.Z_FULL_FLUSH)
+ {
+ //state.head[s.hash_size-1]=0;
+ for (int i = 0; i < this._hashSize/*-1*/; i++) // forget history
+ this._head[i] = 0;
+ }
+ }
+ this.flush_pending();
+ if (base.avail_out == 0)
+ {
+ last_flush = (FlushType)(-1); // avoid BUF_ERROR at next call, see above
+ return ZLibStatus.Z_OK;
+ }
+ }
+ }
+
+ if (flush != FlushType.Z_FINISH) return ZLibStatus.Z_OK;
+ if (noheader != 0) return ZLibStatus.Z_STREAM_END;
+
+ // Write the zlib trailer (adler32)
+ putShortMSB((int)(base.adler >> 16));
+ putShortMSB((int)(base.adler & 0xffff));
+ this.flush_pending();
+
+ // If avail_out is zero, the application will call deflate again
+ // to flush the rest.
+ noheader = -1; // write the trailer only once!
+ return pending != 0 ? ZLibStatus.Z_OK : ZLibStatus.Z_STREAM_END;
+ }
+
+
+ private static readonly StaticTree static_l_desc = new StaticTree(static_ltree, Deflate.extra_lbits, LITERALS + 1, L_CODES, MAX_BITS);
+
+ private static readonly StaticTree static_d_desc = new StaticTree(static_dtree, Deflate.extra_dbits, 0, D_CODES, MAX_BITS);
+
+ private static readonly StaticTree static_bl_desc = new StaticTree(null, Deflate.extra_blbits, 0, BL_CODES, MAX_BL_BITS);
+
+ private class Config
+ {
+ ///
+ /// Reduce lazy search above this match length
+ ///
+ internal int GoodLength { get; private set; }
+ ///
+ /// Gets or sets whether not to perform lazy search above this match length
+ ///
+ ///
+ /// The max lazy.
+ ///
+ internal int MaxLazy { get; private set; }
+ ///
+ /// Gets or sets whether to quit search above this match length
+ ///
+ ///
+ /// The length of the nice.
+ ///
+ internal int NiceLength { get; private set; }
+ internal int MaxChain { get; private set; }
+ internal DefalteFlavor Function { get; private set; }
+ internal Config(int goodLength, int maxLazy, int niceLength, int maxChain, DefalteFlavor function)
+ {
+ this.GoodLength = goodLength;
+ this.MaxLazy = maxLazy;
+ this.NiceLength = niceLength;
+ this.MaxChain = maxChain;
+ this.Function = function;
+ }
+ }
+
+
+ // Flush as much pending output as possible. All deflate() output goes
+ // through this function so some applications may wish to modify it
+ // to avoid allocating a large strm->next_out buffer and copying into it.
+ // (See also read_buf()).
+ internal void flush_pending()
+ {
+ int len = this.pending;
+
+ if (len > avail_out) len = avail_out;
+ if (len == 0) return;
+
+ if (this.pending_buf.Length <= this.pending_out ||
+ next_out.Length <= next_out_index ||
+ this.pending_buf.Length < (this.pending_out + len) ||
+ next_out.Length < (next_out_index + len))
+ {
+ // System.out.println(this.pending_buf.length+", "+this.pending_out+
+ // ", "+next_out.length+", "+next_out_index+", "+len);
+ // System.out.println("avail_out="+avail_out);
+ }
+
+ System.Array.Copy(this.pending_buf, this.pending_out,
+ next_out, next_out_index, len);
+
+ next_out_index += len;
+ this.pending_out += len;
+ total_out += len;
+ avail_out -= len;
+ this.pending -= len;
+ if (this.pending == 0)
+ {
+ this.pending_out = 0;
+ }
+ }
+
+ // Read a new buffer from the current input stream, update the adler32
+ // and total number of bytes read. All deflate() input goes through
+ // this function so some applications may wish to modify it to avoid
+ // allocating a large strm->next_in buffer and copying from it.
+ // (See also flush_pending()).
+ internal int read_buf(byte[] buf, int start, int size)
+ {
+ int len = avail_in;
+
+ if (len > size) len = size;
+ if (len == 0) return 0;
+
+ avail_in -= len;
+
+ if (this.noheader == 0)
+ {
+ adler = Adler32.adler32(adler, next_in, next_in_index, len);
+ }
+ System.Array.Copy(next_in, next_in_index, buf, start, len);
+ next_in_index += len;
+ total_in += len;
+ return len;
+ }
+
+ public ZLibStatus deflate(byte[] inputBufer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType)
+ {
+ this.next_in = inputBufer;
+ this.next_in_index = inputOffset;
+ this.avail_in = inputCount;
+ this.next_out = outputBuffer;
+ this.next_out_index = outputOffset;
+ this.avail_out = outputCount;
+ return this.deflate(flushType);
+ }
+
+ public ZLibStatus deflate(byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType)
+ {
+ this.next_out = outputBuffer;
+ this.next_out_index = outputOffset;
+ this.avail_out = outputCount;
+ return this.deflate(flushType);
+ }
+
+
+ // TODO: Delete this
+ public ZLibStatus inflateEnd()
+ {
+ throw new NotImplementedException();
+ }
+
+ public ZLibStatus inflate(byte[] bufer, int offset, int count, byte[] p1, int p2, int p3, FlushType flushType)
+ {
+ throw new NotImplementedException();
+ }
+
+ public ZLibStatus inflate(byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v9/Inflate.cs b/Renci.SshNet/Compression/v9/Inflate.cs
new file mode 100644
index 0000000..c05e2d8
--- /dev/null
+++ b/Renci.SshNet/Compression/v9/Inflate.cs
@@ -0,0 +1,524 @@
+using System;
+/*
+ * $Id: Inflate.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public enum InflateMode : int
+ {
+ ///
+ ///waiting for method byte
+ ///
+ METHOD = 0,
+ ///
+ /// waiting for flag byte
+ ///
+ FLAG = 1,
+ ///
+ /// four dictionary check bytes to go
+ ///
+ DICT4 = 2,
+ ///
+ /// three dictionary check bytes to go
+ ///
+ DICT3 = 3,
+ ///
+ /// two dictionary check bytes to go
+ ///
+ DICT2 = 4,
+ ///
+ /// one dictionary check byte to go
+ ///
+ DICT1 = 5,
+ ///
+ /// waiting for inflateSetDictionary
+ ///
+ DICT0 = 6,
+ ///
+ /// decompressing blocks
+ ///
+ BLOCKS = 7,
+ ///
+ /// four check bytes to go
+ ///
+ CHECK4 = 8,
+ ///
+ /// three check bytes to go
+ ///
+ CHECK3 = 9,
+ ///
+ /// two check bytes to go
+ ///
+ CHECK2 = 10,
+ ///
+ /// one check byte to go
+ ///
+ CHECK1 = 11,
+ ///
+ /// finished check, done
+ ///
+ DONE = 12,
+ ///
+ /// got an error--stay here
+ ///
+ BAD = 13
+ }
+
+ internal sealed class Inflate : ZStream, ICompressor
+ {
+ // preset dictionary flag in zlib header
+ private const int PRESET_DICT = 0x20;
+
+ private const int Z_DEFLATED = 8;
+
+ private static readonly byte[] mark = { (byte)0, (byte)0, (byte)0xff, (byte)0xff };
+
+ ///
+ /// The current inflate mode
+ ///
+ private InflateMode _mode;
+
+ ///
+ /// if FLAGS, method byte
+ ///
+ private int method;
+
+ ///
+ /// Computed check value
+ ///
+ private long[] _was = new long[1];
+
+ ///
+ /// The stream check value
+ ///
+ private long _need;
+
+ ///
+ /// if BAD, inflateSync's marker bytes count
+ ///
+ private int _marker;
+
+ // mode independent information
+ ///
+ /// Flag for no wrapper
+ ///
+ private int _nowrap;
+
+ ///
+ /// log2(window size) (8..15, defaults to 15)
+ ///
+ private int _wbits;
+
+ ///
+ /// Current inflate_blocks state
+ ///
+ private InflateBlocks _blocks;
+
+ public Inflate()
+ {
+ this.inflateInit();
+ }
+
+ public Inflate(bool nowrap)
+ {
+ this.inflateInit(nowrap);
+ }
+
+ private ZLibStatus InflateReset()
+ {
+ base.total_in = base.total_out = 0;
+ base.msg = null;
+ this._mode = this._nowrap != 0 ? InflateMode.BLOCKS : InflateMode.METHOD;
+ this._blocks.reset(this, null);
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus InflateEnd()
+ {
+ if (_blocks != null)
+ _blocks.free(this);
+ _blocks = null;
+ // ZFREE(z, z->state);
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus InflateInit(int w)
+ {
+ base.msg = null;
+ _blocks = null;
+
+ // handle undocumented nowrap option (no zlib header or check)
+ _nowrap = 0;
+ if (w < 0)
+ {
+ w = -w;
+ _nowrap = 1;
+ }
+
+ // set window size
+ if (w < 8 || w > 15)
+ {
+ InflateEnd();
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+ _wbits = w;
+
+ this._blocks = new InflateBlocks(this, this._nowrap != 0 ? null : this, 1 << w);
+
+ // reset state
+ InflateReset();
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus inflate(FlushType ff)
+ {
+ ZLibStatus r;
+ int b;
+
+ if (base.next_in == null)
+ return ZLibStatus.Z_STREAM_ERROR;
+ var f = ff == FlushType.Z_FINISH ? ZLibStatus.Z_BUF_ERROR : ZLibStatus.Z_OK;
+ r = ZLibStatus.Z_BUF_ERROR;
+ while (true)
+ {
+ //System.out.println("mode: "+this.mode);
+ switch (this._mode)
+ {
+ case InflateMode.METHOD:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ if (((this.method = base.next_in[base.next_in_index++]) & 0xf) != Z_DEFLATED)
+ {
+ this._mode = InflateMode.BAD;
+ base.msg = "unknown compression method";
+ this._marker = 5; // can't try inflateSync
+ break;
+ }
+ if ((this.method >> 4) + 8 > this._wbits)
+ {
+ this._mode = InflateMode.BAD;
+ base.msg = "invalid window size";
+ this._marker = 5; // can't try inflateSync
+ break;
+ }
+ this._mode = InflateMode.FLAG;
+ goto case InflateMode.FLAG;
+ case InflateMode.FLAG:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ b = (base.next_in[base.next_in_index++]) & 0xff;
+
+ if ((((this.method << 8) + b) % 31) != 0)
+ {
+ this._mode = InflateMode.BAD;
+ base.msg = "incorrect header check";
+ this._marker = 5; // can't try inflateSync
+ break;
+ }
+
+ if ((b & PRESET_DICT) == 0)
+ {
+ this._mode = InflateMode.BLOCKS;
+ break;
+ }
+ this._mode = InflateMode.DICT4;
+ goto case InflateMode.DICT4;
+ case InflateMode.DICT4:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need = ((base.next_in[base.next_in_index++] & 0xff) << 24) & 0xff000000L;
+ this._mode = InflateMode.DICT3;
+ goto case InflateMode.DICT3;
+ case InflateMode.DICT3:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += ((base.next_in[base.next_in_index++] & 0xff) << 16) & 0xff0000L;
+ this._mode = InflateMode.DICT2;
+ goto case InflateMode.DICT2;
+ case InflateMode.DICT2:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += ((base.next_in[base.next_in_index++] & 0xff) << 8) & 0xff00L;
+ this._mode = InflateMode.DICT1;
+ goto case InflateMode.DICT1;
+ case InflateMode.DICT1:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += (base.next_in[base.next_in_index++] & 0xffL);
+ base.adler = this._need;
+ this._mode = InflateMode.DICT0;
+ return ZLibStatus.Z_NEED_DICT;
+ case InflateMode.DICT0:
+ this._mode = InflateMode.BAD;
+ base.msg = "need dictionary";
+ this._marker = 0; // can try inflateSync
+ return ZLibStatus.Z_STREAM_ERROR;
+ case InflateMode.BLOCKS:
+
+ r = this._blocks.proc(this, r);
+ if (r == ZLibStatus.Z_DATA_ERROR)
+ {
+ this._mode = InflateMode.BAD;
+ this._marker = 0; // can try inflateSync
+ break;
+ }
+ if (r == ZLibStatus.Z_OK)
+ {
+ r = f;
+ }
+ if (r != ZLibStatus.Z_STREAM_END)
+ {
+ return r;
+ }
+ r = f;
+ this._blocks.reset(this, this._was);
+ if (this._nowrap != 0)
+ {
+ this._mode = InflateMode.DONE;
+ break;
+ }
+ this._mode = InflateMode.CHECK4;
+ goto case InflateMode.CHECK4;
+ case InflateMode.CHECK4:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need = ((base.next_in[base.next_in_index++] & 0xff) << 24) & 0xff000000L;
+ this._mode = InflateMode.CHECK3;
+ goto case InflateMode.CHECK3;
+ case InflateMode.CHECK3:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += ((base.next_in[base.next_in_index++] & 0xff) << 16) & 0xff0000L;
+ this._mode = InflateMode.CHECK2;
+ goto case InflateMode.CHECK2;
+ case InflateMode.CHECK2:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += ((base.next_in[base.next_in_index++] & 0xff) << 8) & 0xff00L;
+ this._mode = InflateMode.CHECK1;
+ goto case InflateMode.CHECK1;
+ case InflateMode.CHECK1:
+
+ if (base.avail_in == 0) return r; r = f;
+
+ base.avail_in--; base.total_in++;
+ this._need += (base.next_in[base.next_in_index++] & 0xffL);
+
+ if (((int)(this._was[0])) != ((int)(this._need)))
+ {
+ this._mode = InflateMode.BAD;
+ base.msg = "incorrect data check";
+ this._marker = 5; // can't try inflateSync
+ break;
+ }
+
+ this._mode = InflateMode.DONE;
+ goto case InflateMode.DONE;
+ case InflateMode.DONE:
+ return ZLibStatus.Z_STREAM_END;
+ case InflateMode.BAD:
+ return ZLibStatus.Z_DATA_ERROR;
+ default:
+ return ZLibStatus.Z_STREAM_ERROR;
+ }
+ }
+ }
+
+ public ZLibStatus InflateSetDictionary(byte[] dictionary, int dictLength)
+ {
+ int index = 0;
+ int length = dictLength;
+ if (this._mode != InflateMode.DICT0)
+ return ZLibStatus.Z_STREAM_ERROR;
+
+ if (Adler32.adler32(1L, dictionary, 0, dictLength) != base.adler)
+ {
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+
+ base.adler = Adler32.adler32(0, null, 0, 0);
+
+ if (length >= (1 << this._wbits))
+ {
+ length = (1 << this._wbits) - 1;
+ index = dictLength - length;
+ }
+ this._blocks.set_dictionary(dictionary, index, length);
+ this._mode = InflateMode.BLOCKS;
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus InflateSync()
+ {
+ int n; // number of bytes to look at
+ int p; // pointer to bytes
+ int m; // number of marker bytes found in a row
+ long r, w; // temporaries to save total_in and total_out
+
+ // set up
+ if (this._mode != InflateMode.BAD)
+ {
+ this._mode = InflateMode.BAD;
+ this._marker = 0;
+ }
+ if ((n = base.avail_in) == 0)
+ return ZLibStatus.Z_BUF_ERROR;
+ p = base.next_in_index;
+ m = this._marker;
+
+ // search
+ while (n != 0 && m < 4)
+ {
+ if (base.next_in[p] == mark[m])
+ {
+ m++;
+ }
+ else if (base.next_in[p] != 0)
+ {
+ m = 0;
+ }
+ else
+ {
+ m = 4 - m;
+ }
+ p++; n--;
+ }
+
+ // restore
+ base.total_in += p - base.next_in_index;
+ base.next_in_index = p;
+ base.avail_in = n;
+ this._marker = m;
+
+ // return no joy or set up to restart on a new block
+ if (m != 4)
+ {
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ r = base.total_in; w = base.total_out;
+ InflateReset();
+ base.total_in = r; base.total_out = w;
+ this._mode = InflateMode.BLOCKS;
+ return ZLibStatus.Z_OK;
+ }
+
+ public ZLibStatus inflateInit()
+ {
+ return inflateInit(DEF_WBITS);
+ }
+ public ZLibStatus inflateInit(bool nowrap)
+ {
+ return inflateInit(DEF_WBITS, nowrap);
+ }
+ public ZLibStatus inflateInit(int w)
+ {
+ return inflateInit(w, false);
+ }
+
+ public ZLibStatus inflateInit(int w, bool nowrap)
+ {
+ return this.InflateInit(nowrap ? -w : w);
+ }
+
+ public ZLibStatus inflateEnd()
+ {
+ var ret = this.InflateEnd();
+ return ret;
+ }
+ public ZLibStatus inflateSync()
+ {
+ return this.InflateSync();
+ }
+
+ public ZLibStatus inflateSetDictionary(byte[] dictionary, int dictLength)
+ {
+ return this.InflateSetDictionary(dictionary, dictLength);
+ }
+
+ public ZLibStatus inflate(byte[] inputBufer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType)
+ {
+ this.next_in = inputBufer;
+ this.next_in_index = inputOffset;
+ this.avail_in = inputCount;
+ this.next_out = outputBuffer;
+ this.next_out_index = outputOffset;
+ this.avail_out = outputCount;
+ return this.inflate(flushType);
+ }
+
+ public ZLibStatus inflate(byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType)
+ {
+ this.next_out = outputBuffer;
+ this.next_out_index = outputOffset;
+ this.avail_out = outputCount;
+ return this.inflate(flushType);
+ }
+
+ // TODO: Dlete this
+ public ZLibStatus deflate(byte[] bufer, int offset, int count, byte[] p1, int p2, int p3, FlushType flushType)
+ {
+ throw new NotImplementedException();
+ }
+
+ public ZLibStatus deflateEnd()
+ {
+ throw new NotImplementedException();
+ }
+
+ public ZLibStatus deflate(byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v9/InflateBlocks.cs b/Renci.SshNet/Compression/v9/InflateBlocks.cs
new file mode 100644
index 0000000..273389f
--- /dev/null
+++ b/Renci.SshNet/Compression/v9/InflateBlocks.cs
@@ -0,0 +1,721 @@
+using System;
+/*
+ * $Id: InfBlocks.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public enum InflateBlockMode
+ {
+ ///
+ /// get type bits (3, including end bit)
+ ///
+ TYPE = 0,
+ ///
+ /// get lengths for stored
+ ///
+ LENS = 1,
+ ///
+ /// cessing stored block
+ ///
+ STORED = 2,
+ ///
+ /// get table lengths
+ ///
+ TABLE = 3,
+ ///
+ /// get bit lengths tree for a dynamic block
+ ///
+ BTREE = 4,
+ ///
+ /// get length, distance trees for a dynamic block
+ ///
+ DTREE = 5,
+ ///
+ /// processing fixed or dynamic block
+ ///
+ CODES = 6,
+ ///
+ /// output remaining window bytes
+ ///
+ DRY = 7,
+ ///
+ /// finished last block, done
+ ///
+ DONE = 8,
+ ///
+ /// ot a data error--stuck here
+ ///
+ BAD = 9
+ }
+
+ internal sealed class InflateBlocks : InflateCodes
+ {
+ private const int MANY = 1440;
+
+ // And'ing with mask[n] masks the lower n bits
+ private static readonly int[] inflate_mask = {
+ 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
+ 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
+ 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
+ 0x00007fff, 0x0000ffff
+ };
+
+ // Table for deflate from PKZIP's appnote.txt.
+ static readonly int[] border = { // Order of the bit length code lengths
+ 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
+ };
+
+ internal InflateBlockMode mode; // current inflate_block mode
+
+ internal int left; // if STORED, bytes left to copy
+
+ internal int table; // table lengths (14 bits)
+ internal int index; // index into blens (or border)
+ internal int[] blens; // bit lengths of codes
+ internal int[] bb = new int[1]; // bit length tree depth
+ internal int[] tb = new int[1]; // bit length decoding tree
+
+ //internal InfCodes codes = new InfCodes(); // if CODES, current state
+
+ int last; // true if this block is the last block
+
+ // mode independent information
+ internal int bitk; // bits in bit buffer
+ internal int bitb; // bit buffer
+ internal int[] hufts; // single malloc for tree space
+ internal byte[] window; // sliding window
+ internal int end; // one byte after sliding window
+ internal int read; // window read pointer
+ internal int write; // window write pointer
+ internal Object checkfn; // check function
+ internal long check; // check on output
+
+ internal InflateTree inftree = new InflateTree();
+
+ internal InflateBlocks(ZStream z, Object checkfn, int w)
+ {
+ hufts = new int[MANY * 3];
+ window = new byte[w];
+ end = w;
+ this.checkfn = checkfn;
+ mode = InflateBlockMode.TYPE;
+ reset(z, null);
+ }
+
+ internal void reset(ZStream z, long[] c)
+ {
+ if (c != null) c[0] = check;
+ if (mode == InflateBlockMode.BTREE || mode == InflateBlockMode.DTREE)
+ {
+ }
+ if (mode == InflateBlockMode.CODES)
+ {
+ codesfree(z);
+ }
+ mode = InflateBlockMode.TYPE;
+ bitk = 0;
+ bitb = 0;
+ read = write = 0;
+
+ if (checkfn != null)
+ z.adler = check = Adler32.adler32(0L, null, 0, 0);
+ }
+
+ internal ZLibStatus proc(ZStream z, ZLibStatus r)
+ {
+ int t; // temporary storage
+ ZLibStatus tt;
+ int b; // bit buffer
+ int k; // bits in bit buffer
+ int p; // input data pointer
+ int n; // bytes available there
+ int q; // output window write pointer
+ int m;
+ { // bytes to end of window or read pointer
+
+ // copy input/output information to locals (UPDATE macro restores)
+ p = z.next_in_index; n = z.avail_in; b = bitb; k = bitk;
+ }
+ {
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+ }
+
+ // process input based on current state
+ while (true)
+ {
+ switch (mode)
+ {
+ case InflateBlockMode.TYPE:
+
+ while (k < (3))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+ t = (int)(b & 7);
+ last = t & 1;
+
+ switch (t >> 1)
+ {
+ case 0:
+ { // stored
+ b >>= (3); k -= (3);
+ }
+ t = k & 7;
+ { // go to byte boundary
+
+ b >>= (t); k -= (t);
+ }
+ mode = InflateBlockMode.LENS; // get length of stored block
+ break;
+ case 1:
+ { // fixed
+ int[] bl = new int[1];
+ int[] bd = new int[1];
+ int[][] tl = new int[1][];
+ int[][] td = new int[1][];
+
+ InflateTree.InflateTreesFixed(bl, bd, tl, td, z);
+ codesinit(bl[0], bd[0], tl[0], 0, td[0], 0, z);
+ }
+ {
+
+ b >>= (3); k -= (3);
+ }
+
+ mode = InflateBlockMode.CODES;
+ break;
+ case 2:
+ { // dynamic
+
+ b >>= (3); k -= (3);
+ }
+
+ mode = InflateBlockMode.TABLE;
+ break;
+ case 3:
+ { // illegal
+
+ b >>= (3); k -= (3);
+ }
+ mode = InflateBlockMode.BAD;
+ z.msg = "invalid block type";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ break;
+ case InflateBlockMode.LENS:
+
+ while (k < (32))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ if ((((~b) >> 16) & 0xffff) != (b & 0xffff))
+ {
+ mode = InflateBlockMode.BAD;
+ z.msg = "invalid stored block lengths";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ left = (b & 0xffff);
+ b = k = 0; // dump bits
+ mode = left != 0 ? InflateBlockMode.STORED : (last != 0 ? InflateBlockMode.DRY : InflateBlockMode.TYPE);
+ break;
+ case InflateBlockMode.STORED:
+ if (n == 0)
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+
+ if (m == 0)
+ {
+ if (q == end && read != 0)
+ {
+ q = 0; m = (int)(q < read ? read - q - 1 : end - q);
+ }
+ if (m == 0)
+ {
+ write = q;
+ r = inflate_flush(z, r);
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+ if (q == end && read != 0)
+ {
+ q = 0; m = (int)(q < read ? read - q - 1 : end - q);
+ }
+ if (m == 0)
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ }
+ }
+ r = ZLibStatus.Z_OK;
+
+ t = left;
+ if (t > n) t = n;
+ if (t > m) t = m;
+ System.Array.Copy(z.next_in, p, window, q, t);
+ p += t; n -= t;
+ q += t; m -= t;
+ if ((left -= t) != 0)
+ break;
+ mode = last != 0 ? InflateBlockMode.DRY : InflateBlockMode.TYPE;
+ break;
+ case InflateBlockMode.TABLE:
+
+ while (k < (14))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ table = t = (b & 0x3fff);
+ if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
+ {
+ mode = InflateBlockMode.BAD;
+ z.msg = "too many length or distance symbols";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
+ if (blens == null || blens.Length < t)
+ {
+ blens = new int[t];
+ }
+ else
+ {
+ for (int i = 0; i < t; i++) { blens[i] = 0; }
+ }
+ {
+
+ b >>= (14); k -= (14);
+ }
+
+ index = 0;
+ mode = InflateBlockMode.BTREE;
+ goto case InflateBlockMode.BTREE;
+ case InflateBlockMode.BTREE:
+ while (index < 4 + (table >> 10))
+ {
+ while (k < (3))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ blens[border[index++]] = b & 7;
+ {
+
+ b >>= (3); k -= (3);
+ }
+ }
+
+ while (index < 19)
+ {
+ blens[border[index++]] = 0;
+ }
+
+ bb[0] = 7;
+ tt = inftree.InflateTreesBits(blens, bb, tb, hufts, z);
+ if (tt != ZLibStatus.Z_OK)
+ {
+ r = tt;
+ if (r == ZLibStatus.Z_DATA_ERROR)
+ {
+ blens = null;
+ mode = InflateBlockMode.BAD;
+ }
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+
+ index = 0;
+ mode = InflateBlockMode.DTREE;
+ goto case InflateBlockMode.DTREE;
+ case InflateBlockMode.DTREE:
+ while (true)
+ {
+ t = table;
+ if (!(index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)))
+ {
+ break;
+ }
+
+ int i, j, c;
+
+ t = bb[0];
+
+ while (k < (t))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ if (tb[0] == -1)
+ {
+ //System.err.println("null...");
+ }
+
+ t = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 1];
+ c = hufts[(tb[0] + (b & inflate_mask[t])) * 3 + 2];
+
+ if (c < 16)
+ {
+ b >>= (t); k -= (t);
+ blens[index++] = c;
+ }
+ else
+ { // c == 16..18
+ i = c == 18 ? 7 : c - 14;
+ j = c == 18 ? 11 : 3;
+
+ while (k < (t + i))
+ {
+ if (n != 0)
+ {
+ r = ZLibStatus.Z_OK;
+ }
+ else
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n;
+ z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ };
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ b >>= (t); k -= (t);
+
+ j += (b & inflate_mask[i]);
+
+ b >>= (i); k -= (i);
+
+ i = index;
+ t = table;
+ if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
+ (c == 16 && i < 1))
+ {
+ blens = null;
+ mode = InflateBlockMode.BAD;
+ z.msg = "invalid bit length repeat";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+
+ c = c == 16 ? blens[i - 1] : 0;
+ do
+ {
+ blens[i++] = c;
+ }
+ while (--j != 0);
+ index = i;
+ }
+ }
+
+ tb[0] = -1;
+ {
+ int[] bl = new int[1];
+ int[] bd = new int[1];
+ int[] tl = new int[1];
+ int[] td = new int[1];
+ bl[0] = 9; // must be <= 9 for lookahead assumptions
+ bd[0] = 6; // must be <= 9 for lookahead assumptions
+
+ t = table;
+ tt = inftree.InflateTreesDynamic(257 + (t & 0x1f),
+ 1 + ((t >> 5) & 0x1f),
+ blens, bl, bd, tl, td, hufts, z);
+
+ if (tt != ZLibStatus.Z_OK)
+ {
+ if (tt == ZLibStatus.Z_DATA_ERROR)
+ {
+ blens = null;
+ mode = InflateBlockMode.BAD;
+ }
+ r = tt;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ codesinit(bl[0], bd[0], hufts, tl[0], hufts, td[0], z);
+ }
+ mode = InflateBlockMode.CODES;
+ goto case InflateBlockMode.CODES;
+ case InflateBlockMode.CODES:
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+
+ if ((r = codesproc(this, z, r)) != ZLibStatus.Z_STREAM_END)
+ {
+ return inflate_flush(z, r);
+ }
+ r = ZLibStatus.Z_OK;
+ codesfree(z);
+
+ p = z.next_in_index; n = z.avail_in; b = bitb; k = bitk;
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+
+ if (last == 0)
+ {
+ mode = InflateBlockMode.TYPE;
+ break;
+ }
+ mode = InflateBlockMode.DRY;
+ goto case InflateBlockMode.DRY;
+ case InflateBlockMode.DRY:
+ write = q;
+ r = inflate_flush(z, r);
+ q = write; m = (int)(q < read ? read - q - 1 : end - q);
+ if (read != write)
+ {
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ mode = InflateBlockMode.DONE;
+ goto case InflateBlockMode.DONE;
+ case InflateBlockMode.DONE:
+ r = ZLibStatus.Z_STREAM_END;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ case InflateBlockMode.BAD:
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+
+ default:
+ r = ZLibStatus.Z_STREAM_ERROR;
+
+ bitb = b; bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ write = q;
+ return inflate_flush(z, r);
+ }
+ }
+ }
+
+ internal void free(ZStream z)
+ {
+ reset(z, null);
+ window = null;
+ hufts = null;
+ //ZFREE(z, s);
+ }
+
+ internal void set_dictionary(byte[] d, int start, int n)
+ {
+ System.Array.Copy(d, start, window, 0, n);
+ read = write = n;
+ }
+
+ // Returns true if inflate is currently at the end of a block generated
+ // by Z_SYNC_FLUSH or FlushType.Z_FULL_FLUSH.
+ internal ZLibStatus sync_point()
+ {
+ return mode == InflateBlockMode.LENS ? ZLibStatus.Z_STREAM_END : ZLibStatus.Z_OK;
+ }
+
+ // copy as much as possible from the sliding window to the output area
+ internal ZLibStatus inflate_flush(ZStream z, ZLibStatus r)
+ {
+ int n;
+ int p;
+ int q;
+
+ // local copies of source and destination pointers
+ p = z.next_out_index;
+ q = read;
+
+ // compute number of bytes to copy as far as end of window
+ n = (int)((q <= write ? write : end) - q);
+ if (n > z.avail_out) n = z.avail_out;
+ if (n != 0 && r == ZLibStatus.Z_BUF_ERROR) r = ZLibStatus.Z_OK;
+
+ // update counters
+ z.avail_out -= n;
+ z.total_out += n;
+
+ // update check information
+ if (checkfn != null)
+ z.adler = check = Adler32.adler32(check, window, q, n);
+
+ // copy as far as end of window
+ System.Array.Copy(window, q, z.next_out, p, n);
+ p += n;
+ q += n;
+
+ // see if more to copy at beginning of window
+ if (q == end)
+ {
+ // wrap pointers
+ q = 0;
+ if (write == end)
+ write = 0;
+
+ // compute bytes to copy
+ n = write - q;
+ if (n > z.avail_out) n = z.avail_out;
+ if (n != 0 && r == ZLibStatus.Z_BUF_ERROR) r = ZLibStatus.Z_OK;
+
+ // update counters
+ z.avail_out -= n;
+ z.total_out += n;
+
+ // update check information
+ if (checkfn != null)
+ z.adler = check = Adler32.adler32(check, window, q, n);
+
+ // copy
+ System.Array.Copy(window, q, z.next_out, p, n);
+ p += n;
+ q += n;
+ }
+
+ // update pointers
+ z.next_out_index = p;
+ read = q;
+
+ // done
+ return r;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v9/InflateCodes.cs b/Renci.SshNet/Compression/v9/InflateCodes.cs
new file mode 100644
index 0000000..3214e56
--- /dev/null
+++ b/Renci.SshNet/Compression/v9/InflateCodes.cs
@@ -0,0 +1,690 @@
+using System;
+/*
+ * $Id: InfCodes.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public enum InflateCodeMode
+ {
+ ///
+ /// x: set up for InflateCodeMode.LEN
+ ///
+ START = 0,
+ ///
+ /// i: get length/literal/eob next
+ ///
+ LEN = 1,
+ ///
+ /// i: getting length extra (have base)
+ ///
+ LENEXT = 2,
+ ///
+ /// i: get distance next
+ ///
+ DIST = 3,
+ ///
+ /// : getting distance extra
+ ///
+ DISTEXT = 4,
+ ///
+ /// o: copying bytes in window, waiting for space
+ ///
+ COPY = 5,
+ ///
+ /// o: got literal, waiting for output space
+ ///
+ LIT = 6,
+ ///
+ /// o: got eob, possibly still output waiting
+ ///
+ WASH = 7,
+ ///
+ /// x: got eob and all data flushed
+ ///
+ END = 8,
+ ///
+ /// x: got error
+ ///
+ BADCODE = 9
+ }
+
+ internal abstract class InflateCodes// : ZStream
+ {
+ private static readonly int[] inflate_mask = {
+ 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
+ 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
+ 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
+ 0x00007fff, 0x0000ffff
+ };
+
+ InflateCodeMode mode; // current inflate_codes mode
+
+ // mode dependent information
+ int len;
+
+ int[] tree; // pointer into tree
+ int tree_index = 0;
+ int need; // bits needed
+
+ int lit;
+
+ // if EXT or COPY, where and how much
+ int get; // bits to get for extra
+ int dist; // distance back to copy from
+
+ byte lbits; // ltree bits decoded per branch
+ byte dbits; // dtree bits decoder per branch
+ int[] ltree; // literal/length/eob tree
+ int ltree_index; // literal/length/eob tree
+ int[] dtree; // distance tree
+ int dtree_index; // distance tree
+
+ internal InflateCodes()
+ {
+ }
+ internal void codesinit(int bl, int bd,
+ int[] tl, int tl_index,
+ int[] td, int td_index, ZStream z)
+ {
+ mode = InflateCodeMode.START;
+ lbits = (byte)bl;
+ dbits = (byte)bd;
+ ltree = tl;
+ ltree_index = tl_index;
+ dtree = td;
+ dtree_index = td_index;
+ tree = null;
+ }
+
+ internal ZLibStatus codesproc(InflateBlocks s, ZStream z, ZLibStatus r)
+ {
+ int j; // temporary storage
+ int tindex; // temporary pointer
+ int e; // extra bits or operation
+ int b = 0; // bit buffer
+ int k = 0; // bits in bit buffer
+ int p = 0; // input data pointer
+ int n; // bytes available there
+ int q; // output window write pointer
+ int m; // bytes to end of window or read pointer
+ int f; // pointer to copy strings from
+
+ // copy input/output information to locals (UPDATE macro restores)
+ p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk;
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ // process input and output based on current state
+ while (true)
+ {
+ switch (mode)
+ {
+ // waiting for "i:"=input, "o:"=output, "x:"=nothing
+ case InflateCodeMode.START: // x: set up for LEN
+ if (m >= 258 && n >= 10)
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ r = inflate_fast(lbits, dbits,
+ ltree, ltree_index,
+ dtree, dtree_index,
+ s, z);
+
+ p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk;
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (r != ZLibStatus.Z_OK)
+ {
+ mode = r == ZLibStatus.Z_STREAM_END ? InflateCodeMode.WASH : InflateCodeMode.BADCODE;
+ break;
+ }
+ }
+ need = lbits;
+ tree = ltree;
+ tree_index = ltree_index;
+
+ mode = InflateCodeMode.LEN;
+ goto case InflateCodeMode.LEN;
+ case InflateCodeMode.LEN: // i: get length/literal/eob next
+ j = need;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ tindex = (tree_index + (b & inflate_mask[j])) * 3;
+
+ b >>= (tree[tindex + 1]);
+ k -= (tree[tindex + 1]);
+
+ e = tree[tindex];
+
+ if (e == 0)
+ { // literal
+ lit = tree[tindex + 2];
+ mode = InflateCodeMode.LIT;
+ break;
+ }
+ if ((e & 16) != 0)
+ { // length
+ get = e & 15;
+ len = tree[tindex + 2];
+ mode = InflateCodeMode.LENEXT;
+ break;
+ }
+ if ((e & 64) == 0)
+ { // next table
+ need = e;
+ tree_index = tindex / 3 + tree[tindex + 2];
+ break;
+ }
+ if ((e & 32) != 0)
+ { // end of block
+ mode = InflateCodeMode.WASH;
+ break;
+ }
+ mode = InflateCodeMode.BADCODE; // invalid code
+ z.msg = "invalid literal/length code";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ case InflateCodeMode.LENEXT: // i: getting length extra (have base)
+ j = get;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--; b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ len += (b & inflate_mask[j]);
+
+ b >>= j;
+ k -= j;
+
+ need = dbits;
+ tree = dtree;
+ tree_index = dtree_index;
+ mode = InflateCodeMode.DIST;
+ goto case InflateCodeMode.DIST;
+ case InflateCodeMode.DIST: // i: get distance next
+ j = need;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--; b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ tindex = (tree_index + (b & inflate_mask[j])) * 3;
+
+ b >>= tree[tindex + 1];
+ k -= tree[tindex + 1];
+
+ e = (tree[tindex]);
+ if ((e & 16) != 0)
+ { // distance
+ get = e & 15;
+ dist = tree[tindex + 2];
+ mode = InflateCodeMode.DISTEXT;
+ break;
+ }
+ if ((e & 64) == 0)
+ { // next table
+ need = e;
+ tree_index = tindex / 3 + tree[tindex + 2];
+ break;
+ }
+ mode = InflateCodeMode.BADCODE; // invalid code
+ z.msg = "invalid distance code";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ case InflateCodeMode.DISTEXT: // i: getting distance extra
+ j = get;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--; b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ dist += (b & inflate_mask[j]);
+
+ b >>= j;
+ k -= j;
+
+ mode = InflateCodeMode.COPY;
+ goto case InflateCodeMode.COPY;
+ case InflateCodeMode.COPY: // o: copying bytes in window, waiting for space
+ f = q - dist;
+ while (f < 0)
+ { // modulo window size-"while" instead
+ f += s.end; // of "if" handles invalid distances
+ }
+ while (len != 0)
+ {
+
+ if (m == 0)
+ {
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+ if (m == 0)
+ {
+ s.write = q; r = s.inflate_flush(z, r);
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+
+ if (m == 0)
+ {
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ }
+ }
+
+ s.window[q++] = s.window[f++]; m--;
+
+ if (f == s.end)
+ f = 0;
+ len--;
+ }
+ mode = InflateCodeMode.START;
+ break;
+ case InflateCodeMode.LIT: // o: got literal, waiting for output space
+ if (m == 0)
+ {
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+ if (m == 0)
+ {
+ s.write = q; r = s.inflate_flush(z, r);
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+ if (m == 0)
+ {
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ }
+ }
+ r = ZLibStatus.Z_OK;
+
+ s.window[q++] = (byte)lit; m--;
+
+ mode = InflateCodeMode.START;
+ break;
+ case InflateCodeMode.WASH: // o: got eob, possibly more output
+ if (k > 7)
+ { // return unused byte, if any
+ k -= 8;
+ n++;
+ p--; // can always return one
+ }
+
+ s.write = q; r = s.inflate_flush(z, r);
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (s.read != s.write)
+ {
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ mode = InflateCodeMode.END;
+ goto case InflateCodeMode.END;
+ case InflateCodeMode.END:
+ r = ZLibStatus.Z_STREAM_END;
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ case InflateCodeMode.BADCODE: // x: got error
+
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ default:
+ r = ZLibStatus.Z_STREAM_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ }
+ }
+
+ internal void codesfree(ZStream z)
+ {
+ // ZFREE(z, c);
+ }
+
+ // Called with number of bytes left to write in window at least 258
+ // (the maximum string length) and number of input bytes available
+ // at least ten. The ten bytes are six bytes for the longest length/
+ // distance pair plus four bytes for overloading the bit buffer.
+
+ internal ZLibStatus inflate_fast(int bl, int bd,
+ int[] tl, int tl_index,
+ int[] td, int td_index,
+ InflateBlocks s, ZStream z)
+ {
+ int t; // temporary pointer
+ int[] tp; // temporary pointer
+ int tp_index; // temporary pointer
+ int e; // extra bits or operation
+ int b; // bit buffer
+ int k; // bits in bit buffer
+ int p; // input data pointer
+ int n; // bytes available there
+ int q; // output window write pointer
+ int m; // bytes to end of window or read pointer
+ int ml; // mask for literal/length tree
+ int md; // mask for distance tree
+ int c; // bytes to copy
+ int d; // distance back to copy from
+ int r; // copy source pointer
+
+ int tp_index_t_3; // (tp_index+t)*3
+
+ // load input, output, bit values
+ p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk;
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ // initialize masks
+ ml = inflate_mask[bl];
+ md = inflate_mask[bd];
+
+ // do until not enough input or output space for fast loop
+ do
+ { // assume called with m >= 258 && n >= 10
+ // get literal/length code
+ while (k < (20))
+ { // max bits for literal/length code
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k; k += 8;
+ }
+
+ t = b & ml;
+ tp = tl;
+ tp_index = tl_index;
+ tp_index_t_3 = (tp_index + t) * 3;
+ if ((e = tp[tp_index_t_3]) == 0)
+ {
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ s.window[q++] = (byte)tp[tp_index_t_3 + 2];
+ m--;
+ continue;
+ }
+ do
+ {
+
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ if ((e & 16) != 0)
+ {
+ e &= 15;
+ c = tp[tp_index_t_3 + 2] + ((int)b & inflate_mask[e]);
+
+ b >>= e; k -= e;
+
+ // decode distance base of block to copy
+ while (k < (15))
+ { // max bits for distance code
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k; k += 8;
+ }
+
+ t = b & md;
+ tp = td;
+ tp_index = td_index;
+ tp_index_t_3 = (tp_index + t) * 3;
+ e = tp[tp_index_t_3];
+
+ do
+ {
+
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ if ((e & 16) != 0)
+ {
+ // get extra bits to add to distance base
+ e &= 15;
+ while (k < (e))
+ { // get extra bits (up to 13)
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k; k += 8;
+ }
+
+ d = tp[tp_index_t_3 + 2] + (b & inflate_mask[e]);
+
+ b >>= (e); k -= (e);
+
+ // do the copy
+ m -= c;
+ if (q >= d)
+ { // offset before dest
+ // just copy
+ r = q - d;
+ if (q - r > 0 && 2 > (q - r))
+ {
+ s.window[q++] = s.window[r++]; // minimum count is three,
+ s.window[q++] = s.window[r++]; // so unroll loop a little
+ c -= 2;
+ }
+ else
+ {
+ System.Array.Copy(s.window, r, s.window, q, 2);
+ q += 2; r += 2; c -= 2;
+ }
+ }
+ else
+ { // else offset after destination
+ r = q - d;
+ do
+ {
+ r += s.end; // force pointer in window
+ } while (r < 0); // covers invalid distances
+ e = s.end - r;
+ if (c > e)
+ { // if source crosses,
+ c -= e; // wrapped copy
+ if (q - r > 0 && e > (q - r))
+ {
+ do { s.window[q++] = s.window[r++]; }
+ while (--e != 0);
+ }
+ else
+ {
+ System.Array.Copy(s.window, r, s.window, q, e);
+ q += e; r += e; e = 0;
+ }
+ r = 0; // copy rest from start of window
+ }
+
+ }
+
+ // copy all or what's left
+ if (q - r > 0 && c > (q - r))
+ {
+ do { s.window[q++] = s.window[r++]; }
+ while (--c != 0);
+ }
+ else
+ {
+ System.Array.Copy(s.window, r, s.window, q, c);
+ q += c; r += c; c = 0;
+ }
+ break;
+ }
+ else if ((e & 64) == 0)
+ {
+ t += tp[tp_index_t_3 + 2];
+ t += (b & inflate_mask[e]);
+ tp_index_t_3 = (tp_index + t) * 3;
+ e = tp[tp_index_t_3];
+ }
+ else
+ {
+ z.msg = "invalid distance code";
+
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ }
+ while (true);
+ break;
+ }
+
+ if ((e & 64) == 0)
+ {
+ t += tp[tp_index_t_3 + 2];
+ t += (b & inflate_mask[e]);
+ tp_index_t_3 = (tp_index + t) * 3;
+ if ((e = tp[tp_index_t_3]) == 0)
+ {
+
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ s.window[q++] = (byte)tp[tp_index_t_3 + 2];
+ m--;
+ break;
+ }
+ }
+ else if ((e & 32) != 0)
+ {
+
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_STREAM_END;
+ }
+ else
+ {
+ z.msg = "invalid literal/length code";
+
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ }
+ while (true);
+ }
+ while (m >= 258 && n >= 10);
+
+ // not enough input or output--restore pointers and return
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_OK;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v9/InflateTree.cs b/Renci.SshNet/Compression/v9/InflateTree.cs
new file mode 100644
index 0000000..f9da579
--- /dev/null
+++ b/Renci.SshNet/Compression/v9/InflateTree.cs
@@ -0,0 +1,555 @@
+using System;
+/*
+ * $Id: InfTree.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ internal sealed class InflateTree
+ {
+ private const int MANY = 1440;
+
+ private const int fixed_bl = 9;
+ private const int fixed_bd = 5;
+
+ static readonly int[] fixed_tl = {
+ 96,7,256, 0,8,80, 0,8,16, 84,8,115,
+ 82,7,31, 0,8,112, 0,8,48, 0,9,192,
+ 80,7,10, 0,8,96, 0,8,32, 0,9,160,
+ 0,8,0, 0,8,128, 0,8,64, 0,9,224,
+ 80,7,6, 0,8,88, 0,8,24, 0,9,144,
+ 83,7,59, 0,8,120, 0,8,56, 0,9,208,
+ 81,7,17, 0,8,104, 0,8,40, 0,9,176,
+ 0,8,8, 0,8,136, 0,8,72, 0,9,240,
+ 80,7,4, 0,8,84, 0,8,20, 85,8,227,
+ 83,7,43, 0,8,116, 0,8,52, 0,9,200,
+ 81,7,13, 0,8,100, 0,8,36, 0,9,168,
+ 0,8,4, 0,8,132, 0,8,68, 0,9,232,
+ 80,7,8, 0,8,92, 0,8,28, 0,9,152,
+ 84,7,83, 0,8,124, 0,8,60, 0,9,216,
+ 82,7,23, 0,8,108, 0,8,44, 0,9,184,
+ 0,8,12, 0,8,140, 0,8,76, 0,9,248,
+ 80,7,3, 0,8,82, 0,8,18, 85,8,163,
+ 83,7,35, 0,8,114, 0,8,50, 0,9,196,
+ 81,7,11, 0,8,98, 0,8,34, 0,9,164,
+ 0,8,2, 0,8,130, 0,8,66, 0,9,228,
+ 80,7,7, 0,8,90, 0,8,26, 0,9,148,
+ 84,7,67, 0,8,122, 0,8,58, 0,9,212,
+ 82,7,19, 0,8,106, 0,8,42, 0,9,180,
+ 0,8,10, 0,8,138, 0,8,74, 0,9,244,
+ 80,7,5, 0,8,86, 0,8,22, 192,8,0,
+ 83,7,51, 0,8,118, 0,8,54, 0,9,204,
+ 81,7,15, 0,8,102, 0,8,38, 0,9,172,
+ 0,8,6, 0,8,134, 0,8,70, 0,9,236,
+ 80,7,9, 0,8,94, 0,8,30, 0,9,156,
+ 84,7,99, 0,8,126, 0,8,62, 0,9,220,
+ 82,7,27, 0,8,110, 0,8,46, 0,9,188,
+ 0,8,14, 0,8,142, 0,8,78, 0,9,252,
+ 96,7,256, 0,8,81, 0,8,17, 85,8,131,
+ 82,7,31, 0,8,113, 0,8,49, 0,9,194,
+ 80,7,10, 0,8,97, 0,8,33, 0,9,162,
+ 0,8,1, 0,8,129, 0,8,65, 0,9,226,
+ 80,7,6, 0,8,89, 0,8,25, 0,9,146,
+ 83,7,59, 0,8,121, 0,8,57, 0,9,210,
+ 81,7,17, 0,8,105, 0,8,41, 0,9,178,
+ 0,8,9, 0,8,137, 0,8,73, 0,9,242,
+ 80,7,4, 0,8,85, 0,8,21, 80,8,258,
+ 83,7,43, 0,8,117, 0,8,53, 0,9,202,
+ 81,7,13, 0,8,101, 0,8,37, 0,9,170,
+ 0,8,5, 0,8,133, 0,8,69, 0,9,234,
+ 80,7,8, 0,8,93, 0,8,29, 0,9,154,
+ 84,7,83, 0,8,125, 0,8,61, 0,9,218,
+ 82,7,23, 0,8,109, 0,8,45, 0,9,186,
+ 0,8,13, 0,8,141, 0,8,77, 0,9,250,
+ 80,7,3, 0,8,83, 0,8,19, 85,8,195,
+ 83,7,35, 0,8,115, 0,8,51, 0,9,198,
+ 81,7,11, 0,8,99, 0,8,35, 0,9,166,
+ 0,8,3, 0,8,131, 0,8,67, 0,9,230,
+ 80,7,7, 0,8,91, 0,8,27, 0,9,150,
+ 84,7,67, 0,8,123, 0,8,59, 0,9,214,
+ 82,7,19, 0,8,107, 0,8,43, 0,9,182,
+ 0,8,11, 0,8,139, 0,8,75, 0,9,246,
+ 80,7,5, 0,8,87, 0,8,23, 192,8,0,
+ 83,7,51, 0,8,119, 0,8,55, 0,9,206,
+ 81,7,15, 0,8,103, 0,8,39, 0,9,174,
+ 0,8,7, 0,8,135, 0,8,71, 0,9,238,
+ 80,7,9, 0,8,95, 0,8,31, 0,9,158,
+ 84,7,99, 0,8,127, 0,8,63, 0,9,222,
+ 82,7,27, 0,8,111, 0,8,47, 0,9,190,
+ 0,8,15, 0,8,143, 0,8,79, 0,9,254,
+ 96,7,256, 0,8,80, 0,8,16, 84,8,115,
+ 82,7,31, 0,8,112, 0,8,48, 0,9,193,
+
+ 80,7,10, 0,8,96, 0,8,32, 0,9,161,
+ 0,8,0, 0,8,128, 0,8,64, 0,9,225,
+ 80,7,6, 0,8,88, 0,8,24, 0,9,145,
+ 83,7,59, 0,8,120, 0,8,56, 0,9,209,
+ 81,7,17, 0,8,104, 0,8,40, 0,9,177,
+ 0,8,8, 0,8,136, 0,8,72, 0,9,241,
+ 80,7,4, 0,8,84, 0,8,20, 85,8,227,
+ 83,7,43, 0,8,116, 0,8,52, 0,9,201,
+ 81,7,13, 0,8,100, 0,8,36, 0,9,169,
+ 0,8,4, 0,8,132, 0,8,68, 0,9,233,
+ 80,7,8, 0,8,92, 0,8,28, 0,9,153,
+ 84,7,83, 0,8,124, 0,8,60, 0,9,217,
+ 82,7,23, 0,8,108, 0,8,44, 0,9,185,
+ 0,8,12, 0,8,140, 0,8,76, 0,9,249,
+ 80,7,3, 0,8,82, 0,8,18, 85,8,163,
+ 83,7,35, 0,8,114, 0,8,50, 0,9,197,
+ 81,7,11, 0,8,98, 0,8,34, 0,9,165,
+ 0,8,2, 0,8,130, 0,8,66, 0,9,229,
+ 80,7,7, 0,8,90, 0,8,26, 0,9,149,
+ 84,7,67, 0,8,122, 0,8,58, 0,9,213,
+ 82,7,19, 0,8,106, 0,8,42, 0,9,181,
+ 0,8,10, 0,8,138, 0,8,74, 0,9,245,
+ 80,7,5, 0,8,86, 0,8,22, 192,8,0,
+ 83,7,51, 0,8,118, 0,8,54, 0,9,205,
+ 81,7,15, 0,8,102, 0,8,38, 0,9,173,
+ 0,8,6, 0,8,134, 0,8,70, 0,9,237,
+ 80,7,9, 0,8,94, 0,8,30, 0,9,157,
+ 84,7,99, 0,8,126, 0,8,62, 0,9,221,
+ 82,7,27, 0,8,110, 0,8,46, 0,9,189,
+ 0,8,14, 0,8,142, 0,8,78, 0,9,253,
+ 96,7,256, 0,8,81, 0,8,17, 85,8,131,
+ 82,7,31, 0,8,113, 0,8,49, 0,9,195,
+ 80,7,10, 0,8,97, 0,8,33, 0,9,163,
+ 0,8,1, 0,8,129, 0,8,65, 0,9,227,
+ 80,7,6, 0,8,89, 0,8,25, 0,9,147,
+ 83,7,59, 0,8,121, 0,8,57, 0,9,211,
+ 81,7,17, 0,8,105, 0,8,41, 0,9,179,
+ 0,8,9, 0,8,137, 0,8,73, 0,9,243,
+ 80,7,4, 0,8,85, 0,8,21, 80,8,258,
+ 83,7,43, 0,8,117, 0,8,53, 0,9,203,
+ 81,7,13, 0,8,101, 0,8,37, 0,9,171,
+ 0,8,5, 0,8,133, 0,8,69, 0,9,235,
+ 80,7,8, 0,8,93, 0,8,29, 0,9,155,
+ 84,7,83, 0,8,125, 0,8,61, 0,9,219,
+ 82,7,23, 0,8,109, 0,8,45, 0,9,187,
+ 0,8,13, 0,8,141, 0,8,77, 0,9,251,
+ 80,7,3, 0,8,83, 0,8,19, 85,8,195,
+ 83,7,35, 0,8,115, 0,8,51, 0,9,199,
+ 81,7,11, 0,8,99, 0,8,35, 0,9,167,
+ 0,8,3, 0,8,131, 0,8,67, 0,9,231,
+ 80,7,7, 0,8,91, 0,8,27, 0,9,151,
+ 84,7,67, 0,8,123, 0,8,59, 0,9,215,
+ 82,7,19, 0,8,107, 0,8,43, 0,9,183,
+ 0,8,11, 0,8,139, 0,8,75, 0,9,247,
+ 80,7,5, 0,8,87, 0,8,23, 192,8,0,
+ 83,7,51, 0,8,119, 0,8,55, 0,9,207,
+ 81,7,15, 0,8,103, 0,8,39, 0,9,175,
+ 0,8,7, 0,8,135, 0,8,71, 0,9,239,
+ 80,7,9, 0,8,95, 0,8,31, 0,9,159,
+ 84,7,99, 0,8,127, 0,8,63, 0,9,223,
+ 82,7,27, 0,8,111, 0,8,47, 0,9,191,
+ 0,8,15, 0,8,143, 0,8,79, 0,9,255
+ };
+ static readonly int[] fixed_td = {
+ 80,5,1, 87,5,257, 83,5,17, 91,5,4097,
+ 81,5,5, 89,5,1025, 85,5,65, 93,5,16385,
+ 80,5,3, 88,5,513, 84,5,33, 92,5,8193,
+ 82,5,9, 90,5,2049, 86,5,129, 192,5,24577,
+ 80,5,2, 87,5,385, 83,5,25, 91,5,6145,
+ 81,5,7, 89,5,1537, 85,5,97, 93,5,24577,
+ 80,5,4, 88,5,769, 84,5,49, 92,5,12289,
+ 82,5,13, 90,5,3073, 86,5,193, 192,5,24577
+ };
+
+ // Tables for deflate from PKZIP's appnote.txt.
+ static readonly int[] cplens = { // Copy lengths for literal codes 257..285
+ 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+ 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0
+ };
+
+ // see note #13 above about 258
+ static readonly int[] cplext = { // Extra bits for literal codes 257..285
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+ 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112 // 112==invalid
+ };
+
+ static readonly int[] cpdist = { // Copy offsets for distance codes 0..29
+ 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+ 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+ 8193, 12289, 16385, 24577
+ };
+
+ static readonly int[] cpdext = { // Extra bits for distance codes
+ 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+ 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+ 12, 12, 13, 13};
+
+ // If BMAX needs to be larger than 16, then h and x[] should be uLong.
+ const int BMAX = 15; // maximum bit length of any code
+
+ int[] hn = null; // hufts used in space
+ int[] v = null; // work area for huft_build
+ int[] c = null; // bit length count table
+ int[] r = null; // table entry for structure assignment
+ int[] u = null; // table stack
+ int[] x = null; // bit offsets, then code stack
+
+ private ZLibStatus HuftBuild(int[] b, // code lengths in bits (all assumed <= BMAX)
+ int bindex,
+ int n, // number of codes (assumed <= 288)
+ int s, // number of simple-valued codes (0..s-1)
+ int[] d, // list of base values for non-simple codes
+ int[] e, // list of extra bits for non-simple codes
+ int[] t, // result: starting table
+ int[] m, // maximum lookup bits, returns actual
+ int[] hp,// space for trees
+ int[] hn,// hufts used in space
+ int[] v // working area: values in order of bit length
+ )
+ {
+ // Given a list of code lengths and a maximum table size, make a set of
+ // tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR
+ // if the given code set is incomplete (the tables are still built in this
+ // case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of
+ // lengths), or Z_MEM_ERROR if not enough memory.
+
+ int a; // counter for codes of length k
+ int f; // i repeats in table every f entries
+ int g; // maximum code length
+ int h; // table level
+ int i; // counter, current code
+ int j; // counter
+ int k; // number of bits in current code
+ int l; // bits per table (returned in m)
+ int mask; // (1 << w) - 1, to avoid cc -O bug on HP
+ int p; // pointer into c[], b[], or v[]
+ int q; // points to current table
+ int w; // bits before this table == (l * h)
+ int xp; // pointer into x
+ int y; // number of dummy codes added
+ int z; // number of entries in current table
+
+ // Generate counts for each bit length
+
+ p = 0; i = n;
+ do
+ {
+ c[b[bindex + p]]++; p++; i--; // assume all entries <= BMAX
+ } while (i != 0);
+
+ if (c[0] == n)
+ { // null input--all zero length codes
+ t[0] = -1;
+ m[0] = 0;
+ return ZLibStatus.Z_OK;
+ }
+
+ // Find minimum and maximum length, bound *m by those
+ l = m[0];
+ for (j = 1; j <= BMAX; j++)
+ if (c[j] != 0) break;
+ k = j; // minimum code length
+ if (l < j)
+ {
+ l = j;
+ }
+ for (i = BMAX; i != 0; i--)
+ {
+ if (c[i] != 0) break;
+ }
+ g = i; // maximum code length
+ if (l > i)
+ {
+ l = i;
+ }
+ m[0] = l;
+
+ // Adjust last length count to fill out codes, if needed
+ for (y = 1 << j; j < i; j++, y <<= 1)
+ {
+ if ((y -= c[j]) < 0)
+ {
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ }
+ if ((y -= c[i]) < 0)
+ {
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ c[i] += y;
+
+ // Generate starting offsets into the value table for each length
+ x[1] = j = 0;
+ p = 1; xp = 2;
+ while (--i != 0)
+ { // note that i == g from above
+ x[xp] = (j += c[p]);
+ xp++;
+ p++;
+ }
+
+ // Make a table of values in order of bit lengths
+ i = 0; p = 0;
+ do
+ {
+ if ((j = b[bindex + p]) != 0)
+ {
+ v[x[j]++] = i;
+ }
+ p++;
+ }
+ while (++i < n);
+ n = x[g]; // set n to length of v
+
+ // Generate the Huffman codes and for each, make the table entries
+ x[0] = i = 0; // first Huffman code is zero
+ p = 0; // grab values in bit order
+ h = -1; // no tables yet--level -1
+ w = -l; // bits decoded == (l * h)
+ u[0] = 0; // just to keep compilers happy
+ q = 0; // ditto
+ z = 0; // ditto
+
+ // go through the bit lengths (k already is bits in shortest code)
+ for (; k <= g; k++)
+ {
+ a = c[k];
+ while (a-- != 0)
+ {
+ // here i is the Huffman code of length k bits for value *p
+ // make tables up to required level
+ while (k > w + l)
+ {
+ h++;
+ w += l; // previous table always l bits
+ // compute minimum size table less than or equal to l bits
+ z = g - w;
+ z = (z > l) ? l : z; // table size upper limit
+ if ((f = 1 << (j = k - w)) > a + 1)
+ { // try a k-w bit table
+ // too few codes for k-w bit table
+ f -= a + 1; // deduct codes from patterns left
+ xp = k;
+ if (j < z)
+ {
+ while (++j < z)
+ { // try smaller tables up to z bits
+ if ((f <<= 1) <= c[++xp])
+ break; // enough codes to use up j bits
+ f -= c[xp]; // else deduct codes from patterns
+ }
+ }
+ }
+ z = 1 << j; // table entries for j-bit table
+
+ // allocate new table
+ if (hn[0] + z > MANY)
+ { // (note: doesn't matter for fixed)
+ return ZLibStatus.Z_DATA_ERROR; // overflow of MANY
+ }
+ u[h] = q = /*hp+*/ hn[0]; // DEBUG
+ hn[0] += z;
+
+ // connect to last table, if there is one
+ if (h != 0)
+ {
+ x[h] = i; // save pattern for backing up
+ r[0] = (byte)j; // bits in this table
+ r[1] = (byte)l; // bits to dump before this table
+ j = i >> (w - l);
+ r[2] = (int)(q - u[h - 1] - j); // offset to this table
+ System.Array.Copy(r, 0, hp, (u[h - 1] + j) * 3, 3); // connect to last table
+ }
+ else
+ {
+ t[0] = q; // first table is returned result
+ }
+ }
+
+ // set up table entry in r
+ r[1] = (byte)(k - w);
+ if (p >= n)
+ {
+ r[0] = 128 + 64; // out of values--invalid code
+ }
+ else if (v[p] < s)
+ {
+ r[0] = (byte)(v[p] < 256 ? 0 : 32 + 64); // 256 is end-of-block
+ r[2] = v[p++]; // simple code is just the value
+ }
+ else
+ {
+ r[0] = (byte)(e[v[p] - s] + 16 + 64); // non-simple--look up in lists
+ r[2] = d[v[p++] - s];
+ }
+
+ // fill code-like entries with r
+ f = 1 << (k - w);
+ for (j = i >> w; j < z; j += f)
+ {
+ System.Array.Copy(r, 0, hp, (q + j) * 3, 3);
+ }
+
+ // backwards increment the k-bit code i
+ for (j = 1 << (k - 1); (i & j) != 0; j >>= 1)
+ {
+ i ^= j;
+ }
+ i ^= j;
+
+ // backup over finished tables
+ mask = (1 << w) - 1; // needed on HP, cc -O bug
+ while ((i & mask) != x[h])
+ {
+ h--; // don't need to update q
+ w -= l;
+ mask = (1 << w) - 1;
+ }
+ }
+ }
+ // Return Z_BUF_ERROR if we were given an incomplete table
+ return y != 0 && g != 1 ? ZLibStatus.Z_BUF_ERROR : ZLibStatus.Z_OK;
+ }
+
+ internal ZLibStatus InflateTreesBits(int[] c, // 19 code lengths
+ int[] bb, // bits tree desired/actual depth
+ int[] tb, // bits tree result
+ int[] hp, // space for trees
+ ZStream z // for messages
+ )
+ {
+ ZLibStatus result;
+ InitWorkArea(19);
+ hn[0] = 0;
+ result = HuftBuild(c, 0, 19, 19, null, null, tb, bb, hp, hn, v);
+
+ if (result == ZLibStatus.Z_DATA_ERROR)
+ {
+ z.msg = "oversubscribed dynamic bit lengths tree";
+ }
+ else if (result == ZLibStatus.Z_BUF_ERROR || bb[0] == 0)
+ {
+ z.msg = "incomplete dynamic bit lengths tree";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ return result;
+ }
+
+ internal ZLibStatus InflateTreesDynamic(int nl, // number of literal/length codes
+ int nd, // number of distance codes
+ int[] c, // that many (total) code lengths
+ int[] bl, // literal desired/actual bit depth
+ int[] bd, // distance desired/actual bit depth
+ int[] tl, // literal/length tree result
+ int[] td, // distance tree result
+ int[] hp, // space for trees
+ ZStream z // for messages
+ )
+ {
+ ZLibStatus result;
+
+ // build literal/length tree
+ InitWorkArea(288);
+ hn[0] = 0;
+ result = HuftBuild(c, 0, nl, 257, cplens, cplext, tl, bl, hp, hn, v);
+ if (result != ZLibStatus.Z_OK || bl[0] == 0)
+ {
+ if (result == ZLibStatus.Z_DATA_ERROR)
+ {
+ z.msg = "oversubscribed literal/length tree";
+ }
+ else if (result != ZLibStatus.Z_MEM_ERROR)
+ {
+ z.msg = "incomplete literal/length tree";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ return result;
+ }
+
+ // build distance tree
+ InitWorkArea(288);
+ result = HuftBuild(c, nl, nd, 0, cpdist, cpdext, td, bd, hp, hn, v);
+
+ if (result != ZLibStatus.Z_OK || (bd[0] == 0 && nl > 257))
+ {
+ if (result == ZLibStatus.Z_DATA_ERROR)
+ {
+ z.msg = "oversubscribed distance tree";
+ }
+ else if (result == ZLibStatus.Z_BUF_ERROR)
+ {
+ z.msg = "incomplete distance tree";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ else if (result != ZLibStatus.Z_MEM_ERROR)
+ {
+ z.msg = "empty distance tree with lengths";
+ result = ZLibStatus.Z_DATA_ERROR;
+ }
+ return result;
+ }
+
+ return ZLibStatus.Z_OK;
+ }
+
+ internal static ZLibStatus InflateTreesFixed(int[] bl, //literal desired/actual bit depth
+ int[] bd, //distance desired/actual bit depth
+ int[][] tl,//literal/length tree result
+ int[][] td,//distance tree result
+ ZStream z //for memory allocation
+ )
+ {
+ bl[0] = fixed_bl;
+ bd[0] = fixed_bd;
+ tl[0] = fixed_tl;
+ td[0] = fixed_td;
+ return ZLibStatus.Z_OK;
+ }
+
+ private void InitWorkArea(int vsize)
+ {
+ if (hn == null)
+ {
+ hn = new int[1];
+ v = new int[vsize];
+ c = new int[BMAX + 1];
+ r = new int[3];
+ u = new int[BMAX];
+ x = new int[BMAX + 1];
+ }
+ if (v.Length < vsize) { v = new int[vsize]; }
+ for (int i = 0; i < vsize; i++) { v[i] = 0; }
+ for (int i = 0; i < BMAX + 1; i++) { c[i] = 0; }
+ for (int i = 0; i < 3; i++) { r[i] = 0; }
+ // for(int i=0; i
+ /// Gets the static tree or null
+ ///
+ ///
+ /// The static_tree.
+ ///
+ public short[] TreeData { get; private set; }
+
+ ///
+ /// Gets the extra bits for each code or null.
+ ///
+ ///
+ /// The extra bits.
+ ///
+ public int[] ExtraBits { get; private set; }
+
+ ///
+ /// Gets the base index for extra_bits.
+ ///
+ ///
+ /// The extra base.
+ ///
+ public int ExtraBase { get; private set; }
+
+ ///
+ /// Gets the max number of elements in the tree.
+ ///
+ ///
+ /// The elements.
+ ///
+ public int Elements { get; private set; }
+
+ ///
+ /// Gets the max bit length for the codes.
+ ///
+ ///
+ /// The length of the max.
+ ///
+ public int MaxLength { get; private set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The tree data.
+ /// The extra bits.
+ /// The extra base.
+ /// The elements.
+ /// Length of the max.
+ public StaticTree(short[] treeData, int[] extraBits, int extraBase, int elements, int maxLength)
+ {
+ this.TreeData = treeData;
+ this.ExtraBits = extraBits;
+ this.ExtraBase = extraBase;
+ this.Elements = elements;
+ this.MaxLength = maxLength;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v9/Tree.cs b/Renci.SshNet/Compression/v9/Tree.cs
new file mode 100644
index 0000000..d2142c9
--- /dev/null
+++ b/Renci.SshNet/Compression/v9/Tree.cs
@@ -0,0 +1,334 @@
+using System;
+/*
+ * $Id: Tree.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+ internal sealed class Tree
+ {
+ private const int MAX_BITS = 15;
+
+ private const int LITERALS = 256;
+
+ private const int LENGTH_CODES = 29;
+
+ private const int L_CODES = (LITERALS + 1 + LENGTH_CODES);
+
+ private const int HEAP_SIZE = (2 * L_CODES + 1);
+
+ private static byte[] _dist_code = {
+ 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8,
+ 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
+ 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
+ 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
+ 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
+ 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
+ 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17,
+ 18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22,
+ 23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,
+ 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
+ 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29,
+ 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
+ };
+
+
+ ///
+ /// The corresponding static tree
+ ///
+ private StaticTree _staticTree;
+
+ ///
+ /// The dynamic tree
+ ///
+ private short[] _dynamicTree;
+
+ ///
+ /// Gets the largest code with non zero frequency.
+ ///
+ ///
+ /// The max_code.
+ ///
+ public int LargestCode { get; private set; }
+
+ public void Init(short[] dynamicTree, StaticTree staticTree)
+ {
+ this._staticTree = staticTree;
+ this._dynamicTree = dynamicTree;
+ }
+
+ ///
+ /// Mapping from a distance to a distance code. dist is the distance - 1 and must not have side effects. _dist_code[256] and _dist_code[257] are never used.
+ ///
+ /// The dist.
+ ///
+ public static int DistanceCode(int dist)
+ {
+ // TODO: Under multiple port forward after more then 50K requests gets index out of range
+ return ((dist) < 256 ? _dist_code[dist] : _dist_code[256 + ((dist) >> 7)]);
+ }
+
+ ///
+ /// Construct one Huffman tree and assigns the code bit strings and lengths. Update the total bit length for the current block.
+ ///
+ /// The s.
+ public void BuildTree(Deflate s)
+ {
+ short[] tree = _dynamicTree;
+ short[] stree = _staticTree.TreeData;
+ int elems = _staticTree.Elements;
+ int n, m; // iterate over heap elements
+ int max_code = -1; // largest code with non zero frequency
+ int node; // new node being created
+
+ // Construct the initial heap, with least frequent element in
+ // heap[1]. The sons of heap[n] are heap[2*n] and heap[2*n+1].
+ // heap[0] is not used.
+ s.heap_len = 0;
+ s.heap_max = HEAP_SIZE;
+
+ for (n = 0; n < elems; n++)
+ {
+ if (tree[n * 2] != 0)
+ {
+ s.heap[++s.heap_len] = max_code = n;
+ s.depth[n] = 0;
+ }
+ else
+ {
+ tree[n * 2 + 1] = 0;
+ }
+ }
+
+ // The pkzip format requires that at least one distance code exists,
+ // and that at least one bit should be sent even if there is only one
+ // possible code. So to avoid special checks later on we force at least
+ // two codes of non zero frequency.
+ while (s.heap_len < 2)
+ {
+ node = s.heap[++s.heap_len] = (max_code < 2 ? ++max_code : 0);
+ tree[node * 2] = 1;
+ s.depth[node] = 0;
+ s.opt_len--; if (stree != null) s.static_len -= stree[node * 2 + 1];
+ // node is 0 or 1 so it does not have extra bits
+ }
+ this.LargestCode = max_code;
+
+ // The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree,
+ // establish sub-heaps of increasing lengths:
+
+ for (n = s.heap_len / 2; n >= 1; n--)
+ s.pqdownheap(tree, n);
+
+ // Construct the Huffman tree by repeatedly combining the least two
+ // frequent nodes.
+
+ node = elems; // next internal node of the tree
+ do
+ {
+ // n = node of least frequency
+ n = s.heap[1];
+ s.heap[1] = s.heap[s.heap_len--];
+ s.pqdownheap(tree, 1);
+ m = s.heap[1]; // m = node of next least frequency
+
+ s.heap[--s.heap_max] = n; // keep the nodes sorted by frequency
+ s.heap[--s.heap_max] = m;
+
+ // Create a new node father of n and m
+ tree[node * 2] = (short)(tree[n * 2] + tree[m * 2]);
+ s.depth[node] = (byte)(System.Math.Max(s.depth[n], s.depth[m]) + 1);
+ tree[n * 2 + 1] = tree[m * 2 + 1] = (short)node;
+
+ // and insert the new node in the heap
+ s.heap[1] = node++;
+ s.pqdownheap(tree, 1);
+ }
+ while (s.heap_len >= 2);
+
+ s.heap[--s.heap_max] = s.heap[1];
+
+ // At this point, the fields freq and dad are set. We can now
+ // generate the bit lengths.
+
+ ComputeBitLength(s);
+
+ // The field len is now set, we can generate the bit codes
+ GenerateCodes(tree, max_code, s.bl_count);
+ }
+
+ ///
+ /// Compute the optimal bit lengths for a tree and update the total bit length for the current block.
+ ///
+ /// The s.
+ private void ComputeBitLength(Deflate s)
+ {
+ short[] tree = _dynamicTree;
+ short[] stree = _staticTree.TreeData;
+ int[] extra = _staticTree.ExtraBits;
+ int based = _staticTree.ExtraBase;
+ int max_length = _staticTree.MaxLength;
+ int h; // heap index
+ int n, m; // iterate over the tree elements
+ int bits; // bit length
+ int xbits; // extra bits
+ short f; // frequency
+ int overflow = 0; // number of elements with bit length too large
+
+ for (bits = 0; bits <= MAX_BITS; bits++) s.bl_count[bits] = 0;
+
+ // In a first pass, compute the optimal bit lengths (which may
+ // overflow in the case of the bit length tree).
+ tree[s.heap[s.heap_max] * 2 + 1] = 0; // root of the heap
+
+ for (h = s.heap_max + 1; h < HEAP_SIZE; h++)
+ {
+ n = s.heap[h];
+ bits = tree[tree[n * 2 + 1] * 2 + 1] + 1;
+ if (bits > max_length) { bits = max_length; overflow++; }
+ tree[n * 2 + 1] = (short)bits;
+ // We overwrite tree[n*2+1] which is no longer needed
+
+ if (n > LargestCode) continue; // not a leaf node
+
+ s.bl_count[bits]++;
+ xbits = 0;
+ if (n >= based) xbits = extra[n - based];
+ f = tree[n * 2];
+ s.opt_len += f * (bits + xbits);
+ if (stree != null) s.static_len += f * (stree[n * 2 + 1] + xbits);
+ }
+ if (overflow == 0) return;
+
+ // This happens for example on obj2 and pic of the Calgary corpus
+ // Find the first bit length which could increase:
+ do
+ {
+ bits = max_length - 1;
+ while (s.bl_count[bits] == 0) bits--;
+ s.bl_count[bits]--; // move one leaf down the tree
+ s.bl_count[bits + 1] += 2; // move one overflow item as its brother
+ s.bl_count[max_length]--;
+ // The brother of the overflow item also moves one step up,
+ // but this does not affect bl_count[max_length]
+ overflow -= 2;
+ }
+ while (overflow > 0);
+
+ for (bits = max_length; bits != 0; bits--)
+ {
+ n = s.bl_count[bits];
+ while (n != 0)
+ {
+ m = s.heap[--h];
+ if (m > LargestCode) continue;
+ if (tree[m * 2 + 1] != bits)
+ {
+ s.opt_len += (int)(((long)bits - (long)tree[m * 2 + 1]) * (long)tree[m * 2]);
+ tree[m * 2 + 1] = (short)bits;
+ }
+ n--;
+ }
+ }
+ }
+
+ ///
+ /// Generate the codes for a given tree and bit counts (which need not be optimal).
+ ///
+ /// The tree to decorate.
+ /// The largest code with non zero frequency.
+ /// The number of codes at each bit length.
+ private static void GenerateCodes(short[] tree, int max_code, short[] bl_count)
+ {
+ short[] next_code = new short[MAX_BITS + 1]; // next code value for each bit length
+ short code = 0; // running code value
+ int bits; // bit index
+ int n; // code index
+
+ // The distribution counts are first used to generate the code values
+ // without bit reversal.
+ for (bits = 1; bits <= MAX_BITS; bits++)
+ {
+ next_code[bits] = code = (short)((code + bl_count[bits - 1]) << 1);
+ }
+
+ // Check that the bit counts in bl_count are consistent. The last code
+ // must be all ones.
+ //Assert (code + bl_count[MAX_BITS]-1 == (1<
+ /// Reverse the first len bits of a code, using straightforward code (a faster method would use a table)
+ ///
+ /// The value to invert.
+ /// The bit length.
+ ///
+ private static int BiReverse(int code, int len)
+ {
+ int res = 0;
+ do
+ {
+ res |= code & 1;
+ code >>= 1;
+ res <<= 1;
+ }
+ while (--len > 0);
+ return res >> 1;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v9/ZInputStream.cs b/Renci.SshNet/Compression/v9/ZInputStream.cs
new file mode 100644
index 0000000..0ef972c
--- /dev/null
+++ b/Renci.SshNet/Compression/v9/ZInputStream.cs
@@ -0,0 +1,202 @@
+/*
+Copyright (c) 2001 Lapo Luchini.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS
+OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+/* This file is a port of jzlib v1.0.7, com.jcraft.jzlib.ZInputStream.java
+ */
+
+using Renci.SshNet.Compression;
+using System;
+using System.Diagnostics;
+using System.IO;
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+ public class ZInputStream : Stream
+ {
+ private const int BufferSize = 512;
+ //private ZStream z = new ZStream();
+ private ICompressor _compressor;
+
+ // TODO Allow custom buf
+ private byte[] _buffer = new byte[BufferSize];
+ private CompressionMode _compressionMode;
+ private Stream _input;
+ private bool _isClosed;
+ private bool _noMoreInput = false;
+
+ public FlushType FlushMode { get; private set; }
+
+ public ZInputStream()
+ {
+ this.FlushMode = FlushType.Z_PARTIAL_FLUSH;
+ }
+
+ public ZInputStream(Stream input)
+ : this(input, false)
+ {
+ }
+
+ public ZInputStream(Stream input, bool nowrap)
+ : this()
+ {
+ Debug.Assert(input.CanRead);
+
+ this._input = input;
+ this._compressor = new Inflate(nowrap);
+ //this._compressor.inflateInit(nowrap);
+ this._compressionMode = CompressionMode.Decompress;
+ this._compressor.next_in = _buffer;
+ this._compressor.next_in_index = 0;
+ this._compressor.avail_in = 0;
+ }
+
+ public ZInputStream(Stream input, CompressionLevel level)
+ : this()
+ {
+ Debug.Assert(input.CanRead);
+
+ this._input = input;
+ this._compressor = new Deflate(level);
+ //this._compressor.deflateInit(level);
+ this._compressionMode = CompressionMode.Compress;
+ this._compressor.next_in = _buffer;
+ this._compressor.next_in_index = 0;
+ this._compressor.avail_in = 0;
+ }
+
+ #region Stream implementation
+
+ public sealed override bool CanRead
+ {
+ get { return !_isClosed; }
+ }
+
+ public sealed override bool CanSeek
+ {
+ get { return false; }
+ }
+
+ public sealed override bool CanWrite
+ {
+ get { return false; }
+ }
+
+ public override void Flush()
+ {
+ }
+
+ public override long Length
+ {
+ get { throw new NotSupportedException(); }
+ }
+
+ public override long Position
+ {
+ get { throw new NotSupportedException(); }
+ set { throw new NotSupportedException(); }
+ }
+
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ if (count == 0)
+ return 0;
+
+ //this._compressor.next_out = buffer;
+ //this._compressor.next_out_index = offset;
+ //this._compressor.avail_out = count;
+
+ ZLibStatus err = ZLibStatus.Z_OK;
+ do
+ {
+ if (this._compressor.avail_in == 0 && !_noMoreInput)
+ {
+ // if buffer is empty and more input is available, refill it
+ this._compressor.next_in_index = 0;
+ this._compressor.avail_in = _input.Read(_buffer, 0, _buffer.Length); //(bufsize 0 || this._compressor.avail_out == 0);
+ }
+
+ #endregion
+
+ public override void Close()
+ {
+ if (this._isClosed)
+ return;
+
+ try
+ {
+ try
+ {
+ Finish();
+ }
+ catch (IOException)
+ {
+ // Ignore
+ }
+ }
+ finally
+ {
+ this._isClosed = true;
+ End();
+ _output.Close();
+ _output = null;
+ }
+ }
+
+ private void End()
+ {
+ if (this._compressor == null)
+ return;
+ switch (this._compressionMode)
+ {
+ case CompressionMode.Compress:
+ this._compressor.deflateEnd();
+ break;
+ case CompressionMode.Decompress:
+ this._compressor.inflateEnd();
+ break;
+ default:
+ break;
+ }
+
+ //this._compressor.free();
+ this._compressor = null;
+ }
+
+ private void Finish()
+ {
+ do
+ {
+ var err = ZLibStatus.Z_OK;
+ switch (this._compressionMode)
+ {
+ case CompressionMode.Compress:
+ err = this._compressor.deflate(_buffer, 0, _buffer.Length, FlushType.Z_FINISH);
+ break;
+ case CompressionMode.Decompress:
+ err = this._compressor.inflate(_buffer, 0, _buffer.Length, FlushType.Z_FINISH);
+ break;
+ default:
+ break;
+ }
+
+ if (err != ZLibStatus.Z_STREAM_END && err != ZLibStatus.Z_OK)
+ // TODO
+ // throw new ZStreamException((compress?"de":"in")+"flating: "+z.msg);
+ //throw new IOException((_compressionMode ? "de" : "in") + "flating: " + z.msg);
+ throw new IOException(string.Format("{0}ion error: {1}", _compressionMode, err));
+
+ int count = _buffer.Length - this._compressor.avail_out;
+ if (count > 0)
+ {
+ _output.Write(_buffer, 0, count);
+ }
+ }
+ while (this._compressor.avail_in > 0 || this._compressor.avail_out == 0);
+
+ Flush();
+ }
+ }
+}
diff --git a/Renci.SshNet/Compression/v9/ZStream.cs b/Renci.SshNet/Compression/v9/ZStream.cs
new file mode 100644
index 0000000..b151ba1
--- /dev/null
+++ b/Renci.SshNet/Compression/v9/ZStream.cs
@@ -0,0 +1,94 @@
+using System;
+using System.IO;
+/*
+ * $Id: ZStream.cs,v 1.1 2006-07-31 13:59:26 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public interface ICompressor
+ {
+ ZLibStatus deflate(byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType);
+ ZLibStatus deflate(byte[] bufer, int offset, int count, byte[] p1, int p2, int p3, FlushType flushType);
+
+ ZLibStatus deflateEnd();
+
+ ZLibStatus inflate(byte[] bufer, int offset, int count, byte[] p1, int p2, int p3, FlushType flushType);
+ ZLibStatus inflate(byte[] outputBuffer, int outputOffset, int outputCount, FlushType flushType);
+
+ ZLibStatus inflateEnd();
+
+ //ZLibStatus inflate(FlushType flushType);
+
+ int avail_out { get; set; }
+
+ int avail_in { get; set; }
+
+ //int next_out_index { get; set; }
+
+ //byte[] next_out { get; set; }
+
+ byte[] next_in { get; set; }
+
+ int next_in_index { get; set; }
+ }
+
+
+ public abstract class ZStream
+ {
+
+ protected const int MAX_WBITS = 15; // 32K LZ77 window
+ protected const int DEF_WBITS = MAX_WBITS;
+
+ private const int MAX_MEM_LEVEL = 9;
+
+ public byte[] next_in { get; set; } // next input byte
+ public int next_in_index { get; set; }
+ public int avail_in { get; set; } // number of bytes available at next_in
+ public long total_in { get; set; } // total nb of input bytes read so far
+
+ public byte[] next_out { get; set; } // next output byte should be put there
+ public int next_out_index { get; set; }
+ public int avail_out { get; set; } // remaining free space at next_out
+ public long total_out { get; set; } // total nb of bytes output so far
+
+ public String msg { get; set; }
+
+ internal BlockType data_type; // best guess about the data type: ascii or binary
+
+ public long adler;
+
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v9/Zlib.cs b/Renci.SshNet/Compression/v9/Zlib.cs
new file mode 100644
index 0000000..5890675
--- /dev/null
+++ b/Renci.SshNet/Compression/v9/Zlib.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Represents "zlib" compression implementation
+ ///
+ internal class Zlib : Compressor
+ {
+ ///
+ /// Gets algorithm name.
+ ///
+ public override string Name
+ {
+ get { return "zlib"; }
+ }
+
+ ///
+ /// Initializes the algorithm
+ ///
+ /// The session.
+ public override void Init(Session session)
+ {
+ base.Init(session);
+ this.IsActive = true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v9/ZlibOpenSsh.cs b/Renci.SshNet/Compression/v9/ZlibOpenSsh.cs
new file mode 100644
index 0000000..f82a4c0
--- /dev/null
+++ b/Renci.SshNet/Compression/v9/ZlibOpenSsh.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Represents "zlib@openssh.org" compression implementation
+ ///
+ public class ZlibOpenSsh : Compressor
+ {
+ ///
+ /// Gets algorithm name.
+ ///
+ public override string Name
+ {
+ get { return "zlib@openssh.org"; }
+ }
+
+ ///
+ /// Initializes the algorithm
+ ///
+ /// The session.
+ public override void Init(Session session)
+ {
+ base.Init(session);
+
+ session.UserAuthenticationSuccessReceived += Session_UserAuthenticationSuccessReceived;
+ }
+
+ private void Session_UserAuthenticationSuccessReceived(object sender, MessageEventArgs e)
+ {
+ this.IsActive = true;
+ this.Session.UserAuthenticationSuccessReceived -= Session_UserAuthenticationSuccessReceived;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/Compression/v9/ZlibStream.cs b/Renci.SshNet/Compression/v9/ZlibStream.cs
new file mode 100644
index 0000000..fb5f9d2
--- /dev/null
+++ b/Renci.SshNet/Compression/v9/ZlibStream.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.IO;
+using Org.BouncyCastle.Utilities.Zlib;
+
+namespace Renci.SshNet.Compression
+{
+ ///
+ /// Implements Zlib compression algorithm.
+ ///
+ public class ZlibStream
+ {
+ private readonly Stream _baseStream;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The stream.
+ /// The mode.
+ public ZlibStream(Stream stream, CompressionMode mode)
+ {
+ switch (mode)
+ {
+ case CompressionMode.Compress:
+ //this._baseStream = new ZOutputStream(stream, CompressionLevel.Z_DEFAULT_COMPRESSION);
+ this._baseStream = new ZOutputStream(stream, CompressionLevel.Z_DEFAULT_COMPRESSION);
+ break;
+ case CompressionMode.Decompress:
+ this._baseStream = new ZOutputStream(stream);
+ break;
+ default:
+ break;
+ }
+
+ //this._baseStream.FlushMode = Ionic.Zlib.FlushType.Partial;
+ }
+
+ ///
+ /// Writes the specified buffer.
+ ///
+ /// The buffer.
+ /// The offset.
+ /// The count.
+ public void Write(byte[] buffer, int offset, int count)
+ {
+ this._baseStream.Write(buffer, offset, count);
+ }
+ }
+}
diff --git a/Renci.SshNet/Compression/{B60A61FD-33DF-43A1-B48C-A8E3DB53FA13}.tmp b/Renci.SshNet/Compression/{B60A61FD-33DF-43A1-B48C-A8E3DB53FA13}.tmp
new file mode 100644
index 0000000..3214e56
--- /dev/null
+++ b/Renci.SshNet/Compression/{B60A61FD-33DF-43A1-B48C-A8E3DB53FA13}.tmp
@@ -0,0 +1,690 @@
+using System;
+/*
+ * $Id: InfCodes.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the distribution.
+
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib
+{
+
+ public enum InflateCodeMode
+ {
+ ///
+ /// x: set up for InflateCodeMode.LEN
+ ///
+ START = 0,
+ ///
+ /// i: get length/literal/eob next
+ ///
+ LEN = 1,
+ ///
+ /// i: getting length extra (have base)
+ ///
+ LENEXT = 2,
+ ///
+ /// i: get distance next
+ ///
+ DIST = 3,
+ ///
+ /// : getting distance extra
+ ///
+ DISTEXT = 4,
+ ///
+ /// o: copying bytes in window, waiting for space
+ ///
+ COPY = 5,
+ ///
+ /// o: got literal, waiting for output space
+ ///
+ LIT = 6,
+ ///
+ /// o: got eob, possibly still output waiting
+ ///
+ WASH = 7,
+ ///
+ /// x: got eob and all data flushed
+ ///
+ END = 8,
+ ///
+ /// x: got error
+ ///
+ BADCODE = 9
+ }
+
+ internal abstract class InflateCodes// : ZStream
+ {
+ private static readonly int[] inflate_mask = {
+ 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
+ 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
+ 0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
+ 0x00007fff, 0x0000ffff
+ };
+
+ InflateCodeMode mode; // current inflate_codes mode
+
+ // mode dependent information
+ int len;
+
+ int[] tree; // pointer into tree
+ int tree_index = 0;
+ int need; // bits needed
+
+ int lit;
+
+ // if EXT or COPY, where and how much
+ int get; // bits to get for extra
+ int dist; // distance back to copy from
+
+ byte lbits; // ltree bits decoded per branch
+ byte dbits; // dtree bits decoder per branch
+ int[] ltree; // literal/length/eob tree
+ int ltree_index; // literal/length/eob tree
+ int[] dtree; // distance tree
+ int dtree_index; // distance tree
+
+ internal InflateCodes()
+ {
+ }
+ internal void codesinit(int bl, int bd,
+ int[] tl, int tl_index,
+ int[] td, int td_index, ZStream z)
+ {
+ mode = InflateCodeMode.START;
+ lbits = (byte)bl;
+ dbits = (byte)bd;
+ ltree = tl;
+ ltree_index = tl_index;
+ dtree = td;
+ dtree_index = td_index;
+ tree = null;
+ }
+
+ internal ZLibStatus codesproc(InflateBlocks s, ZStream z, ZLibStatus r)
+ {
+ int j; // temporary storage
+ int tindex; // temporary pointer
+ int e; // extra bits or operation
+ int b = 0; // bit buffer
+ int k = 0; // bits in bit buffer
+ int p = 0; // input data pointer
+ int n; // bytes available there
+ int q; // output window write pointer
+ int m; // bytes to end of window or read pointer
+ int f; // pointer to copy strings from
+
+ // copy input/output information to locals (UPDATE macro restores)
+ p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk;
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ // process input and output based on current state
+ while (true)
+ {
+ switch (mode)
+ {
+ // waiting for "i:"=input, "o:"=output, "x:"=nothing
+ case InflateCodeMode.START: // x: set up for LEN
+ if (m >= 258 && n >= 10)
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ r = inflate_fast(lbits, dbits,
+ ltree, ltree_index,
+ dtree, dtree_index,
+ s, z);
+
+ p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk;
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (r != ZLibStatus.Z_OK)
+ {
+ mode = r == ZLibStatus.Z_STREAM_END ? InflateCodeMode.WASH : InflateCodeMode.BADCODE;
+ break;
+ }
+ }
+ need = lbits;
+ tree = ltree;
+ tree_index = ltree_index;
+
+ mode = InflateCodeMode.LEN;
+ goto case InflateCodeMode.LEN;
+ case InflateCodeMode.LEN: // i: get length/literal/eob next
+ j = need;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ tindex = (tree_index + (b & inflate_mask[j])) * 3;
+
+ b >>= (tree[tindex + 1]);
+ k -= (tree[tindex + 1]);
+
+ e = tree[tindex];
+
+ if (e == 0)
+ { // literal
+ lit = tree[tindex + 2];
+ mode = InflateCodeMode.LIT;
+ break;
+ }
+ if ((e & 16) != 0)
+ { // length
+ get = e & 15;
+ len = tree[tindex + 2];
+ mode = InflateCodeMode.LENEXT;
+ break;
+ }
+ if ((e & 64) == 0)
+ { // next table
+ need = e;
+ tree_index = tindex / 3 + tree[tindex + 2];
+ break;
+ }
+ if ((e & 32) != 0)
+ { // end of block
+ mode = InflateCodeMode.WASH;
+ break;
+ }
+ mode = InflateCodeMode.BADCODE; // invalid code
+ z.msg = "invalid literal/length code";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ case InflateCodeMode.LENEXT: // i: getting length extra (have base)
+ j = get;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--; b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ len += (b & inflate_mask[j]);
+
+ b >>= j;
+ k -= j;
+
+ need = dbits;
+ tree = dtree;
+ tree_index = dtree_index;
+ mode = InflateCodeMode.DIST;
+ goto case InflateCodeMode.DIST;
+ case InflateCodeMode.DIST: // i: get distance next
+ j = need;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--; b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ tindex = (tree_index + (b & inflate_mask[j])) * 3;
+
+ b >>= tree[tindex + 1];
+ k -= tree[tindex + 1];
+
+ e = (tree[tindex]);
+ if ((e & 16) != 0)
+ { // distance
+ get = e & 15;
+ dist = tree[tindex + 2];
+ mode = InflateCodeMode.DISTEXT;
+ break;
+ }
+ if ((e & 64) == 0)
+ { // next table
+ need = e;
+ tree_index = tindex / 3 + tree[tindex + 2];
+ break;
+ }
+ mode = InflateCodeMode.BADCODE; // invalid code
+ z.msg = "invalid distance code";
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ case InflateCodeMode.DISTEXT: // i: getting distance extra
+ j = get;
+
+ while (k < (j))
+ {
+ if (n != 0) r = ZLibStatus.Z_OK;
+ else
+ {
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ n--; b |= (z.next_in[p++] & 0xff) << k;
+ k += 8;
+ }
+
+ dist += (b & inflate_mask[j]);
+
+ b >>= j;
+ k -= j;
+
+ mode = InflateCodeMode.COPY;
+ goto case InflateCodeMode.COPY;
+ case InflateCodeMode.COPY: // o: copying bytes in window, waiting for space
+ f = q - dist;
+ while (f < 0)
+ { // modulo window size-"while" instead
+ f += s.end; // of "if" handles invalid distances
+ }
+ while (len != 0)
+ {
+
+ if (m == 0)
+ {
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+ if (m == 0)
+ {
+ s.write = q; r = s.inflate_flush(z, r);
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+
+ if (m == 0)
+ {
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ }
+ }
+
+ s.window[q++] = s.window[f++]; m--;
+
+ if (f == s.end)
+ f = 0;
+ len--;
+ }
+ mode = InflateCodeMode.START;
+ break;
+ case InflateCodeMode.LIT: // o: got literal, waiting for output space
+ if (m == 0)
+ {
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+ if (m == 0)
+ {
+ s.write = q; r = s.inflate_flush(z, r);
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (q == s.end && s.read != 0) { q = 0; m = q < s.read ? s.read - q - 1 : s.end - q; }
+ if (m == 0)
+ {
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ }
+ }
+ r = ZLibStatus.Z_OK;
+
+ s.window[q++] = (byte)lit; m--;
+
+ mode = InflateCodeMode.START;
+ break;
+ case InflateCodeMode.WASH: // o: got eob, possibly more output
+ if (k > 7)
+ { // return unused byte, if any
+ k -= 8;
+ n++;
+ p--; // can always return one
+ }
+
+ s.write = q; r = s.inflate_flush(z, r);
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ if (s.read != s.write)
+ {
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ mode = InflateCodeMode.END;
+ goto case InflateCodeMode.END;
+ case InflateCodeMode.END:
+ r = ZLibStatus.Z_STREAM_END;
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ case InflateCodeMode.BADCODE: // x: got error
+
+ r = ZLibStatus.Z_DATA_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+
+ default:
+ r = ZLibStatus.Z_STREAM_ERROR;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+ return s.inflate_flush(z, r);
+ }
+ }
+ }
+
+ internal void codesfree(ZStream z)
+ {
+ // ZFREE(z, c);
+ }
+
+ // Called with number of bytes left to write in window at least 258
+ // (the maximum string length) and number of input bytes available
+ // at least ten. The ten bytes are six bytes for the longest length/
+ // distance pair plus four bytes for overloading the bit buffer.
+
+ internal ZLibStatus inflate_fast(int bl, int bd,
+ int[] tl, int tl_index,
+ int[] td, int td_index,
+ InflateBlocks s, ZStream z)
+ {
+ int t; // temporary pointer
+ int[] tp; // temporary pointer
+ int tp_index; // temporary pointer
+ int e; // extra bits or operation
+ int b; // bit buffer
+ int k; // bits in bit buffer
+ int p; // input data pointer
+ int n; // bytes available there
+ int q; // output window write pointer
+ int m; // bytes to end of window or read pointer
+ int ml; // mask for literal/length tree
+ int md; // mask for distance tree
+ int c; // bytes to copy
+ int d; // distance back to copy from
+ int r; // copy source pointer
+
+ int tp_index_t_3; // (tp_index+t)*3
+
+ // load input, output, bit values
+ p = z.next_in_index; n = z.avail_in; b = s.bitb; k = s.bitk;
+ q = s.write; m = q < s.read ? s.read - q - 1 : s.end - q;
+
+ // initialize masks
+ ml = inflate_mask[bl];
+ md = inflate_mask[bd];
+
+ // do until not enough input or output space for fast loop
+ do
+ { // assume called with m >= 258 && n >= 10
+ // get literal/length code
+ while (k < (20))
+ { // max bits for literal/length code
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k; k += 8;
+ }
+
+ t = b & ml;
+ tp = tl;
+ tp_index = tl_index;
+ tp_index_t_3 = (tp_index + t) * 3;
+ if ((e = tp[tp_index_t_3]) == 0)
+ {
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ s.window[q++] = (byte)tp[tp_index_t_3 + 2];
+ m--;
+ continue;
+ }
+ do
+ {
+
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ if ((e & 16) != 0)
+ {
+ e &= 15;
+ c = tp[tp_index_t_3 + 2] + ((int)b & inflate_mask[e]);
+
+ b >>= e; k -= e;
+
+ // decode distance base of block to copy
+ while (k < (15))
+ { // max bits for distance code
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k; k += 8;
+ }
+
+ t = b & md;
+ tp = td;
+ tp_index = td_index;
+ tp_index_t_3 = (tp_index + t) * 3;
+ e = tp[tp_index_t_3];
+
+ do
+ {
+
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ if ((e & 16) != 0)
+ {
+ // get extra bits to add to distance base
+ e &= 15;
+ while (k < (e))
+ { // get extra bits (up to 13)
+ n--;
+ b |= (z.next_in[p++] & 0xff) << k; k += 8;
+ }
+
+ d = tp[tp_index_t_3 + 2] + (b & inflate_mask[e]);
+
+ b >>= (e); k -= (e);
+
+ // do the copy
+ m -= c;
+ if (q >= d)
+ { // offset before dest
+ // just copy
+ r = q - d;
+ if (q - r > 0 && 2 > (q - r))
+ {
+ s.window[q++] = s.window[r++]; // minimum count is three,
+ s.window[q++] = s.window[r++]; // so unroll loop a little
+ c -= 2;
+ }
+ else
+ {
+ System.Array.Copy(s.window, r, s.window, q, 2);
+ q += 2; r += 2; c -= 2;
+ }
+ }
+ else
+ { // else offset after destination
+ r = q - d;
+ do
+ {
+ r += s.end; // force pointer in window
+ } while (r < 0); // covers invalid distances
+ e = s.end - r;
+ if (c > e)
+ { // if source crosses,
+ c -= e; // wrapped copy
+ if (q - r > 0 && e > (q - r))
+ {
+ do { s.window[q++] = s.window[r++]; }
+ while (--e != 0);
+ }
+ else
+ {
+ System.Array.Copy(s.window, r, s.window, q, e);
+ q += e; r += e; e = 0;
+ }
+ r = 0; // copy rest from start of window
+ }
+
+ }
+
+ // copy all or what's left
+ if (q - r > 0 && c > (q - r))
+ {
+ do { s.window[q++] = s.window[r++]; }
+ while (--c != 0);
+ }
+ else
+ {
+ System.Array.Copy(s.window, r, s.window, q, c);
+ q += c; r += c; c = 0;
+ }
+ break;
+ }
+ else if ((e & 64) == 0)
+ {
+ t += tp[tp_index_t_3 + 2];
+ t += (b & inflate_mask[e]);
+ tp_index_t_3 = (tp_index + t) * 3;
+ e = tp[tp_index_t_3];
+ }
+ else
+ {
+ z.msg = "invalid distance code";
+
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ }
+ while (true);
+ break;
+ }
+
+ if ((e & 64) == 0)
+ {
+ t += tp[tp_index_t_3 + 2];
+ t += (b & inflate_mask[e]);
+ tp_index_t_3 = (tp_index + t) * 3;
+ if ((e = tp[tp_index_t_3]) == 0)
+ {
+
+ b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
+
+ s.window[q++] = (byte)tp[tp_index_t_3 + 2];
+ m--;
+ break;
+ }
+ }
+ else if ((e & 32) != 0)
+ {
+
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_STREAM_END;
+ }
+ else
+ {
+ z.msg = "invalid literal/length code";
+
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_DATA_ERROR;
+ }
+ }
+ while (true);
+ }
+ while (m >= 258 && n >= 10);
+
+ // not enough input or output--restore pointers and return
+ c = z.avail_in - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= c << 3;
+
+ s.bitb = b; s.bitk = k;
+ z.avail_in = n; z.total_in += p - z.next_in_index; z.next_in_index = p;
+ s.write = q;
+
+ return ZLibStatus.Z_OK;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Renci.SshNet/ConnectionInfo.cs b/Renci.SshNet/ConnectionInfo.cs
index a8dfb49..d30196c 100644
--- a/Renci.SshNet/ConnectionInfo.cs
+++ b/Renci.SshNet/ConnectionInfo.cs
@@ -1,48 +1,27 @@
using System;
-using System.Linq;
using System.Collections.Generic;
-using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
using Renci.SshNet.Security;
-using Renci.SshNet.Compression;
-using Renci.SshNet.Messages;
-using Renci.SshNet.Messages.Authentication;
-using Renci.SshNet.Common;
-using System.Threading;
-using System.Net;
using Renci.SshNet.Messages.Connection;
-using Renci.SshNet.Security.Cryptography.Ciphers;
using System.Security.Cryptography;
+using Renci.SshNet.Common;
+using Renci.SshNet.Messages.Authentication;
using Renci.SshNet.Security.Cryptography;
using Renci.SshNet.Security.Cryptography.Ciphers.Modes;
+using Renci.SshNet.Security.Cryptography.Ciphers;
+using System.Collections.ObjectModel;
+using System.Net;
+using Renci.SshNet.Compression;
+
namespace Renci.SshNet
{
///
- /// Represents remote connection information base class.
+ /// Represents remote connection information class.
///
- public abstract class ConnectionInfo
+ public class ConnectionInfo
{
- ///
- /// Gets connection name
- ///
- public abstract string Name { get; }
-
- ///
- /// Gets a value indicating whether connection is authenticated.
- ///
- ///
- /// true if connection is authenticated; otherwise, false.
- ///
- public bool IsAuthenticated { get; private set; }
-
- ///
- /// Gets the authentication error message.
- ///
- public string ErrorMessage { get; private set; }
-
- ///
- /// Gets reference to the session object.
- ///
- protected Session Session { get; private set; }
+ internal static int DEFAULT_PORT = 22;
///
/// Gets supported key exchange algorithms for this connection.
@@ -57,17 +36,17 @@ public abstract class ConnectionInfo
///
/// Gets supported hash algorithms for this connection.
///
- public IDictionary> HmacAlgorithms { get; private set; }
+ public IDictionary HmacAlgorithms { get; private set; }
///
/// Gets supported host key algorithms for this connection.
///
- public IDictionary> HostKeyAlgorithms { get; private set; }
+ public IDictionary> HostKeyAlgorithms { get; private set; }
///
/// Gets supported authentication methods for this connection.
///
- public IDictionary AuthenticationMethods { get; private set; }
+ public IEnumerable AuthenticationMethods { get; private set; }
///
/// Gets supported compression algorithms for this connection.
@@ -79,6 +58,14 @@ public abstract class ConnectionInfo
///
public IDictionary ChannelRequests { get; private set; }
+ ///
+ /// Gets a value indicating whether connection is authenticated.
+ ///
+ ///
+ /// true if connection is authenticated; otherwise, false.
+ ///
+ public bool IsAuthenticated { get; private set; }
+
///
/// Gets connection host.
///
@@ -94,14 +81,53 @@ public abstract class ConnectionInfo
///
public string Username { get; private set; }
+ ///
+ /// Gets proxy type.
+ ///
+ ///
+ /// The type of the proxy.
+ ///
+ public ProxyTypes ProxyType { get; private set; }
+
+ ///
+ /// Gets proxy connection host.
+ ///
+ public string ProxyHost { get; private set; }
+
+ ///
+ /// Gets proxy connection port.
+ ///
+ public int ProxyPort { get; private set; }
+
+ ///
+ /// Gets proxy connection username.
+ ///
+ public string ProxyUsername { get; private set; }
+
+ ///
+ /// Gets proxy connection password.
+ ///
+ public string ProxyPassword { get; private set; }
+
///
/// Gets or sets connection timeout.
///
///
/// Connection timeout.
///
+ ///
+ ///
+ ///
public TimeSpan Timeout { get; set; }
+ ///
+ /// Gets or sets the default encoding.
+ ///
+ ///
+ /// The default encoding.
+ ///
+ public Encoding Encoding { get; set; }
+
///
/// Gets or sets number of retry attempts when session channel creation failed.
///
@@ -121,17 +147,131 @@ public abstract class ConnectionInfo
///
/// Occurs when authentication banner is sent by the server.
///
+ ///
+ ///
+ ///
public event EventHandler AuthenticationBanner;
///
- /// Prevents a default instance of the class from being created.
+ /// Gets the current key exchange algorithm.
///
- private ConnectionInfo()
+ public string CurrentKeyExchangeAlgorithm { get; internal set; }
+
+ ///
+ /// Gets the current server encryption.
+ ///
+ public string CurrentServerEncryption { get; internal set; }
+
+ ///
+ /// Gets the current client encryption.
+ ///
+ public string CurrentClientEncryption { get; internal set; }
+
+ ///
+ /// Gets the current server hash algorithm.
+ ///
+ public string CurrentServerHmacAlgorithm { get; internal set; }
+
+ ///
+ /// Gets the current client hash algorithm.
+ ///
+ public string CurrentClientHmacAlgorithm { get; internal set; }
+
+ ///
+ /// Gets the current host key algorithm.
+ ///
+ public string CurrentHostKeyAlgorithm { get; internal set; }
+
+ ///
+ /// Gets the current server compression algorithm.
+ ///
+ public string CurrentServerCompressionAlgorithm { get; internal set; }
+
+ ///
+ /// Gets the server version.
+ ///
+ public string ServerVersion { get; internal set; }
+
+ ///
+ /// Get the client version.
+ ///
+ public string ClientVersion { get; internal set; }
+
+ ///
+ /// Gets the current client compression algorithm.
+ ///
+ public string CurrentClientCompressionAlgorithm { get; internal set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The host.
+ /// The username.
+ /// The authentication methods.
+ public ConnectionInfo(string host, string username, params AuthenticationMethod[] authenticationMethods)
+ : this(host, ConnectionInfo.DEFAULT_PORT, username, ProxyTypes.None, null, 0, null, null, authenticationMethods)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The host.
+ /// The port.
+ /// The username.
+ /// The authentication methods.
+ public ConnectionInfo(string host, int port, string username, params AuthenticationMethod[] authenticationMethods)
+ : this(host, port, username, ProxyTypes.None, null, 0, null, null, authenticationMethods)
{
+ }
+
+ // TODO: DOCS Add exception documentation for this class.
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Connection host.
+ /// Connection port.
+ /// Connection username.
+ /// Type of the proxy.
+ /// The proxy host.
+ /// The proxy port.
+ /// The proxy username.
+ /// The proxy password.
+ /// The authentication methods.
+ /// host
+ /// proxyPort
+ /// is invalid, or is null or contains whitespace characters.
+ /// is not within and .
+ /// is invalid, or is null or contains whitespace characters.
+ public ConnectionInfo(string host, int port, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, string proxyPassword, params AuthenticationMethod[] authenticationMethods)
+ {
+ if (!host.IsValidHost())
+ throw new ArgumentException("host");
+
+ if (proxyType != ProxyTypes.None)
+ {
+ if (string.IsNullOrEmpty(proxyHost) && !proxyHost.IsValidHost())
+ throw new ArgumentException("proxyHost");
+
+ if (!proxyPort.IsValidPort())
+ throw new ArgumentOutOfRangeException("proxyPort");
+ }
+
+ if (!port.IsValidPort())
+ throw new ArgumentOutOfRangeException("port");
+
+ if (username.IsNullOrWhiteSpace())
+ throw new ArgumentException("username");
+
+ if (authenticationMethods == null || authenticationMethods.Length < 1)
+ throw new ArgumentException("authenticationMethods");
+
// Set default connection values
this.Timeout = TimeSpan.FromSeconds(30);
this.RetryAttempts = 10;
this.MaxSessions = 10;
+ this.Encoding = Encoding.UTF8;
this.KeyExchangeAlgorithms = new Dictionary()
{
@@ -139,49 +279,61 @@ private ConnectionInfo()
{"diffie-hellman-group-exchange-sha1", typeof(KeyExchangeDiffieHellmanGroupExchangeSha1)},
{"diffie-hellman-group14-sha1", typeof(KeyExchangeDiffieHellmanGroup14Sha1)},
{"diffie-hellman-group1-sha1", typeof(KeyExchangeDiffieHellmanGroup1Sha1)},
+ //{"ecdh-sha2-nistp256", typeof(KeyExchangeEllipticCurveDiffieHellman)},
+ //{"ecdh-sha2-nistp256", typeof(...)},
+ //{"ecdh-sha2-nistp384", typeof(...)},
+ //{"ecdh-sha2-nistp521", typeof(...)},
+ //"gss-group1-sha1-toWM5Slw5Ew8Mqkay+al2g==" - WinSSHD
+ //"gss-gex-sha1-toWM5Slw5Ew8Mqkay+al2g==" - WinSSHD
+
};
this.Encryptions = new Dictionary()
{
+ {"aes256-ctr", new CipherInfo(256, (key, iv)=>{ return new AesCipher(key, new CtrCipherMode(iv), null); }) },
{"3des-cbc", new CipherInfo(192, (key, iv)=>{ return new TripleDesCipher(key, new CbcCipherMode(iv), null); }) },
{"aes128-cbc", new CipherInfo(128, (key, iv)=>{ return new AesCipher(key, new CbcCipherMode(iv), null); }) },
{"aes192-cbc", new CipherInfo(192, (key, iv)=>{ return new AesCipher(key, new CbcCipherMode(iv), null); }) },
{"aes256-cbc", new CipherInfo(256, (key, iv)=>{ return new AesCipher(key, new CbcCipherMode(iv), null); }) },
{"blowfish-cbc", new CipherInfo(128, (key, iv)=>{ return new BlowfishCipher(key, new CbcCipherMode(iv), null); }) },
- ////{"twofish-cbc", typeof(...)},
- ////{"twofish192-cbc", typeof(...)},
- ////{"twofish128-cbc", typeof(...)},
- ////{"twofish256-cbc", typeof(...)},
+ {"twofish-cbc", new CipherInfo(256, (key, iv)=>{ return new TwofishCipher(key, new CbcCipherMode(iv), null); }) },
+ {"twofish192-cbc", new CipherInfo(192, (key, iv)=>{ return new TwofishCipher(key, new CbcCipherMode(iv), null); }) },
+ {"twofish128-cbc", new CipherInfo(128, (key, iv)=>{ return new TwofishCipher(key, new CbcCipherMode(iv), null); }) },
+ {"twofish256-cbc", new CipherInfo(256, (key, iv)=>{ return new TwofishCipher(key, new CbcCipherMode(iv), null); }) },
////{"serpent256-cbc", typeof(CipherSerpent256CBC)},
////{"serpent192-cbc", typeof(...)},
////{"serpent128-cbc", typeof(...)},
- ////{"arcfour128", typeof(...)},
- ////{"arcfour256", typeof(...)},
- ////{"arcfour", typeof(...)},
+ {"arcfour", new CipherInfo(128, (key, iv)=>{ return new Arc4Cipher(key, false); }) },
+ {"arcfour128", new CipherInfo(128, (key, iv)=>{ return new Arc4Cipher(key, true); }) },
+ {"arcfour256", new CipherInfo(256, (key, iv)=>{ return new Arc4Cipher(key, true); }) },
////{"idea-cbc", typeof(...)},
{"cast128-cbc", new CipherInfo(128, (key, iv)=>{ return new CastCipher(key, new CbcCipherMode(iv), null); }) },
////{"rijndael-cbc@lysator.liu.se", typeof(...)},
{"aes128-ctr", new CipherInfo(128, (key, iv)=>{ return new AesCipher(key, new CtrCipherMode(iv), null); }) },
{"aes192-ctr", new CipherInfo(192, (key, iv)=>{ return new AesCipher(key, new CtrCipherMode(iv), null); }) },
- {"aes256-ctr", new CipherInfo(256, (key, iv)=>{ return new AesCipher(key, new CtrCipherMode(iv), null); }) },
};
- this.HmacAlgorithms = new Dictionary>()
+ this.HmacAlgorithms = new Dictionary()
{
- {"hmac-md5", (key) => { return new HMac(key.Take(16).ToArray());}},
- {"hmac-sha1", (key) => { return new HMac(key.Take(20).ToArray());}},
+ {"hmac-md5", new HashInfo(16 * 8, (key)=>{ return new HMac(key); }) },
+ {"hmac-sha1", new HashInfo(20 * 8, (key)=>{ return new HMac(key); }) },
+ {"hmac-sha2-256", new HashInfo(32 * 8, (key)=>{ return new HMac(key); }) },
+ {"hmac-sha2-256-96", new HashInfo(32 * 8, (key)=>{ return new HMac(key, 96); }) },
+ //{"hmac-sha2-512", new HashInfo(64 * 8, (key)=>{ return new HMac(key); }) },
+ //{"hmac-sha2-512-96", new HashInfo(64 * 8, (key)=>{ return new HMac(key, 96); }) },
//{"umac-64@openssh.com", typeof(HMacSha1)},
- //{"hmac-ripemd160", typeof(HMacSha1)},
- //{"hmac-ripemd160@openssh.com", typeof(HMacSha1)},
- //{"hmac-md5-96", typeof(...)},
- //{"hmac-sha1-96", typeof(...)},
+ {"hmac-ripemd160", new HashInfo(160, (key)=>{ return new HMac(key); }) },
+ {"hmac-ripemd160@openssh.com", new HashInfo(160, (key)=>{ return new HMac(key); }) },
+ {"hmac-md5-96", new HashInfo(16 * 8, (key)=>{ return new HMac(key, 96); }) },
+ {"hmac-sha1-96", new HashInfo(20 * 8, (key)=>{ return new HMac(key, 96); }) },
//{"none", typeof(...)},
};
- this.HostKeyAlgorithms = new Dictionary>()
+ this.HostKeyAlgorithms = new Dictionary>()
{
{"ssh-rsa", (data) => { return new KeyHostAlgorithm("ssh-rsa", new RsaKey(), data); }},
{"ssh-dss", (data) => { return new KeyHostAlgorithm("ssh-dss", new DsaKey(), data); }},
+ //{"ecdsa-sha2-nistp256 "}
//{"x509v3-sign-rsa", () => { ... },
//{"x509v3-sign-dss", () => { ... },
//{"spki-sign-rsa", () => { ... },
@@ -190,24 +342,14 @@ private ConnectionInfo()
//{"pgp-sign-dss", () => { ... },
};
- this.AuthenticationMethods = new Dictionary()
- {
- {"none", typeof(ConnectionInfo)},
- {"publickey", typeof(PrivateKeyConnectionInfo)},
- {"password", typeof(PasswordConnectionInfo)},
- {"keyboard-interactive", typeof(KeyboardInteractiveConnectionInfo)},
- //{"hostbased", typeof(...)},
- //{"gssapi-keyex", typeof(...)},
- //{"gssapi-with-mic", typeof(...)},
- };
-
this.CompressionAlgorithms = new Dictionary()
{
+ //{"zlib@openssh.com", typeof(ZlibOpenSsh)},
+ //{"zlib", typeof(Zlib)},
{"none", null},
- {"zlib", typeof(Zlib)},
- {"zlib@openssh.com", typeof(ZlibOpenSsh)},
};
+
this.ChannelRequests = new Dictionary()
{
{EnvironmentVariableRequestInfo.NAME, new EnvironmentVariableRequestInfo()},
@@ -224,32 +366,18 @@ private ConnectionInfo()
{EndOfWriteRequestInfo.NAME, new EndOfWriteRequestInfo()},
{KeepAliveRequestInfo.NAME, new KeepAliveRequestInfo()},
};
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// Connection host.
- /// Connection port.
- /// Connection username.
- /// is invalid, or is null or contains whitespace characters.
- /// is not within and .
- /// is null or empty.
- protected ConnectionInfo(string host, int port, string username)
- : this()
- {
- if (!host.IsValidHost())
- throw new ArgumentException("Hostname not valid");
-
- if (!port.IsValidPort())
- throw new ArgumentException("Port value in not in valid range");
-
- if (username.IsNullOrWhiteSpace())
- throw new ArgumentException("Username not valid");
this.Host = host;
this.Port = port;
this.Username = username;
+
+ this.ProxyType = proxyType;
+ this.ProxyHost = proxyHost;
+ this.ProxyPort = proxyPort;
+ this.ProxyUsername = proxyUsername;
+ this.ProxyPassword = proxyPassword;
+
+ this.AuthenticationMethods = authenticationMethods;
}
///
@@ -258,100 +386,70 @@ protected ConnectionInfo(string host, int port, string username)
/// The session to be authenticated.
/// true if authenticated; otherwise false.
/// is null.
+ /// No suitable authentication method found to complete authentication.
public bool Authenticate(Session session)
{
+ var authenticated = AuthenticationResult.Failure;
+
if (session == null)
throw new ArgumentNullException("session");
- this.Session = session;
-
- this.Session.RegisterMessage("SSH_MSG_USERAUTH_FAILURE");
- this.Session.RegisterMessage("SSH_MSG_USERAUTH_SUCCESS");
- this.Session.RegisterMessage("SSH_MSG_USERAUTH_BANNER");
+ session.RegisterMessage("SSH_MSG_USERAUTH_FAILURE");
+ session.RegisterMessage("SSH_MSG_USERAUTH_SUCCESS");
+ session.RegisterMessage("SSH_MSG_USERAUTH_BANNER");
- this.Session.UserAuthenticationFailureReceived += Session_UserAuthenticationFailureReceived;
- this.Session.UserAuthenticationSuccessReceived += Session_UserAuthenticationSuccessMessageReceived;
- this.Session.UserAuthenticationBannerReceived += Session_UserAuthenticationBannerMessageReceived;
- this.Session.MessageReceived += Session_MessageReceived;
+ session.UserAuthenticationBannerReceived += Session_UserAuthenticationBannerReceived;
- this.OnAuthenticate();
+ // Try to authenticate against none
+ var noneAuthenticationMethod = new NoneAuthenticationMethod(this.Username);
- this.Session.UserAuthenticationFailureReceived -= Session_UserAuthenticationFailureReceived;
- this.Session.UserAuthenticationSuccessReceived -= Session_UserAuthenticationSuccessMessageReceived;
- this.Session.UserAuthenticationBannerReceived -= Session_UserAuthenticationBannerMessageReceived;
- this.Session.MessageReceived -= Session_MessageReceived;
+ authenticated = noneAuthenticationMethod.Authenticate(session);
- this.Session.UnRegisterMessage("SSH_MSG_USERAUTH_FAILURE");
- this.Session.UnRegisterMessage("SSH_MSG_USERAUTH_SUCCESS");
- this.Session.UnRegisterMessage("SSH_MSG_USERAUTH_BANNER");
-
- return this.IsAuthenticated;
- }
+ var allowedAuthentications = noneAuthenticationMethod.AllowedAuthentications;
- ///
- /// Called when connection needs to be authenticated.
- ///
- protected abstract void OnAuthenticate();
+ var triedAuthentications = new List();
+ while (authenticated != AuthenticationResult.Success)
+ {
+ // Find first authentication method
+ var method = this.AuthenticationMethods.Where((a) => allowedAuthentications.Contains(a.Name) && !triedAuthentications.Contains(a.Name)).FirstOrDefault();
+ if (method == null)
+ throw new SshAuthenticationException("No suitable authentication method found to complete authentication.");
+
+ triedAuthentications.Add(method.Name);
+
+ authenticated = method.Authenticate(session);
+
+ if (authenticated == AuthenticationResult.PartialSuccess || (method.AllowedAuthentications != null && method.AllowedAuthentications.Count() < allowedAuthentications.Count()))
+ {
+ // If further authentication is required then continue to try another method
+ allowedAuthentications = method.AllowedAuthentications;
+ continue;
+ }
+
+ // If authentication Fail, and all the authentication have been tried.
+ if (authenticated == AuthenticationResult.Failure && (triedAuthentications.Count() == allowedAuthentications.Count()))
+ {
+ break;
+ }
+ }
- ///
- /// Sends SSH message to the server.
- ///
- /// The message.
- protected void SendMessage(Message message)
- {
- this.Session.SendMessage(message);
- }
+ session.UserAuthenticationBannerReceived -= Session_UserAuthenticationBannerReceived;
- ///
- /// Waits the handle to signal.
- ///
- /// The event wait handle.
- protected void WaitHandle(WaitHandle eventWaitHandle)
- {
- this.Session.WaitHandle(eventWaitHandle);
- }
+ session.UnRegisterMessage("SSH_MSG_USERAUTH_FAILURE");
+ session.UnRegisterMessage("SSH_MSG_USERAUTH_SUCCESS");
+ session.UnRegisterMessage("SSH_MSG_USERAUTH_BANNER");
- ///
- /// Handles the UserAuthenticationFailureReceived event of the session.
- ///
- /// The source of the event.
- /// The event data.
- protected virtual void Session_UserAuthenticationFailureReceived(object sender, MessageEventArgs e)
- {
- this.ErrorMessage = e.Message.Message;
- this.IsAuthenticated = false;
- }
+ this.IsAuthenticated = authenticated == AuthenticationResult.Success;
- ///
- /// Handles the UserAuthenticationSuccessMessageReceived event of the session.
- ///
- /// The source of the event.
- /// The event data.
- protected virtual void Session_UserAuthenticationSuccessMessageReceived(object sender, MessageEventArgs e)
- {
- this.IsAuthenticated = true;
+ return authenticated == AuthenticationResult.Success;
}
- ///
- /// Handles the UserAuthenticationBannerMessageReceived event of the session.
- ///
- /// The source of the event.
- /// The event data.
- protected virtual void Session_UserAuthenticationBannerMessageReceived(object sender, MessageEventArgs e)
+ private void Session_UserAuthenticationBannerReceived(object sender, MessageEventArgs e)
{
if (this.AuthenticationBanner != null)
{
this.AuthenticationBanner(this, new AuthenticationBannerEventArgs(this.Username, e.Message.Message, e.Message.Language));
}
}
-
- ///
- /// Handles the MessageReceived event of the session.
- ///
- /// The source of the event.
- /// The event data.
- protected virtual void Session_MessageReceived(object sender, MessageEventArgs e)
- {
- }
}
}
diff --git a/Renci.SshNet/Documentation/Content/About.aml b/Renci.SshNet/Documentation/Content/About.aml
deleted file mode 100644
index 848a316..0000000
--- a/Renci.SshNet/Documentation/Content/About.aml
+++ /dev/null
@@ -1,55 +0,0 @@
-
-
-
-
-
- This preliminary documentation. I will add more information later so if you have any feedback as far as what missing or what need to be corrected please let me know.
- At this moment SFTP documentation not yet available.
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Renci.SshNet/Documentation/Content/Guide/Guide.Command.Asynchronous.aml b/Renci.SshNet/Documentation/Content/Guide/Guide.Command.Asynchronous.aml
deleted file mode 100644
index b48763e..0000000
--- a/Renci.SshNet/Documentation/Content/Guide/Guide.Command.Asynchronous.aml
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
-
- Execut command asynchronously
-
- If you need to execute long running command you might want to execute it in asynchronously.
- To execute command asynchronously you need to create command first and then call M:Renci.SshClient.SshCommand.BeginExecute(System.AsyncCallback, System.Object) method
-
- If an exception occures while command is being executed it will be thrown when M:Renci.SshClient.SshCommand.EndExecute(System.IAsyncResult) is called.
-
- See examples below:
-
-
-
- Display exit status when command is executed.
-
- using (var client = new SshClient("host", "username", "password"))
- {
- client.Connect();
- var cmd = client.CreateCommand("sleep 30s;date"); // Perform long running task
- var asynch = cmd.BeginExecute(null, null);
- while (!asynch.IsCompleted)
- {
- Console.WriteLine("Waiting for command to complete...");
- Thread.Sleep(2000);
- }
- cmd.EndExecute(asynch);
- client.Disconnect();
- }
-
-
-
-
-
-
- M:Renci.SshClient.SshCommand.BeginExecute(System.AsyncCallback, System.Object)
- M:Renci.SshClient.SshCommand.EndExecute(System.IAsyncResult)
- T:Renci.SshClient.SshCommand
-
-
-
\ No newline at end of file
diff --git a/Renci.SshNet/Documentation/Content/Guide/Guide.Command.Error.aml b/Renci.SshNet/Documentation/Content/Guide/Guide.Command.Error.aml
deleted file mode 100644
index 6a5e18d..0000000
--- a/Renci.SshNet/Documentation/Content/Guide/Guide.Command.Error.aml
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
- Execution errors
-
- When command is executed and error occured you can access to errir description by accessing P:Renci.SshClient.SshCommand.Error property.
- You can also check P:Renci.SshClient.SshCommand.ExitStatus which is in case of error should not be 0.
- See examples below:
-
-
-
- Execute invalid command and display execution error.
-
- using (var client = new SshClient("host", "username", "password"))
- {
- client.Connect();
- var cmd = client.CreateCommand(";");
- cmd.Execute();
- if (!string.IsNullOrEmpty(cmd.Error))
- {
- Console.WriteLine(cmd.Error);
- }
- client.Disconnect();
- }
-
-
-
-
-
-
- P:Renci.SshClient.SshCommand.ExitStatus
- P:Renci.SshClient.SshCommand.Error
- T:Renci.SshClient.SshCommand
-
-
-
\ No newline at end of file
diff --git a/Renci.SshNet/Documentation/Content/Guide/Guide.Command.Multitasking.aml b/Renci.SshNet/Documentation/Content/Guide/Guide.Command.Multitasking.aml
deleted file mode 100644
index fa13204..0000000
--- a/Renci.SshNet/Documentation/Content/Guide/Guide.Command.Multitasking.aml
+++ /dev/null
@@ -1,38 +0,0 @@
-
-
-
-
- Library support multiple command execution at once. However there are some limitation to be aware of.
- While you can run multiple commands on multiple threads at the same time usually only 10 commands are executed at the same time.
- This is due to server default limitation which allows only 10 session channels top be open at the same time.
- This limitation can be change on the server level, if so you can you T:Renci.SshClient.ConnectionInfo object to increase or decrease this value.
- This rule is only true when you try to run multiple commands on the same connection.
- Of course if you will be using multiple connection this rul does not apply.
-
-
-
- Running multiple command using one connection.
-
- System.Threading.Tasks.Parallel.For(0, 10000,
- () =>
- {
- var client = new SshClient("host", "username", "password");
- client.Connect();
- return client;
- },
- (int counter, ParallelLoopState pls, SshClient client) =>
- {
- var cmd = client.RunCommand(string.Format("echo {0}}", counter));
- Console.WriteLine(cmd.Result);
- return client;
- },
- (SshClient client) =>
- {
- client.Disconnect();
- client.Dispose();
- }
-
-
-
-
-
\ No newline at end of file
diff --git a/Renci.SshNet/Documentation/Content/Guide/Guide.Command.StatusCode.aml b/Renci.SshNet/Documentation/Content/Guide/Guide.Command.StatusCode.aml
deleted file mode 100644
index 60ba87b..0000000
--- a/Renci.SshNet/Documentation/Content/Guide/Guide.Command.StatusCode.aml
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
- Execution errors
-
- When command is executed you can retrive command execution exit status by accessing P:Renci.SshClient.SshCommand.ExitStatus property.
- See examples below:
-
-
-
- Display exit status when command is executed.
-
- using (var client = new SshClient("host", "username", "password"))
- {
- client.Connect();
- var cmd = client.RunCommand("exit 128");
- cmd.Execute();
- Console.WriteLine(cmd.ExitStatus); // Should display 128
- client.Disconnect();
- }
-
-
-
-
-
-
- P:Renci.SshClient.SshCommand.ExitStatus
- T:Renci.SshClient.SshCommand
-
-
-
\ No newline at end of file
diff --git a/Renci.SshNet/Documentation/Content/Guide/Guide.Command.Timeout.aml b/Renci.SshNet/Documentation/Content/Guide/Guide.Command.Timeout.aml
deleted file mode 100644
index ff25ce6..0000000
--- a/Renci.SshNet/Documentation/Content/Guide/Guide.Command.Timeout.aml
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
-
- Command execution
-
- When you need to terminte the command after specific time has passed you can use P:Renci.SshClient.SshCommand.CommandTimeout property.
- To specify time out property you must to create T:Renci.SshClient.SshCommand first.
- See examples below:
-
-
-
- Execute command and specify 10 sec timeout
-
- using (var client = new SshClient("host", "username", "password"))
- {
- client.Connect();
- var cmd = client.CreateCommand("sleep 10s");
- cmd.CommandTimeout = TimeSpan.FromSeconds(5);
- cmd.Execute();
- client.Disconnect();
- }
-
-
-
-
-
-
- P:Renci.SshClient.SshCommand.CommandTimeout
- T:Renci.SshClient.SshCommand
-
-
-
\ No newline at end of file
diff --git a/Renci.SshNet/Documentation/Content/Guide/Guide.Command.aml b/Renci.SshNet/Documentation/Content/Guide/Guide.Command.aml
deleted file mode 100644
index 0268a64..0000000
--- a/Renci.SshNet/Documentation/Content/Guide/Guide.Command.aml
+++ /dev/null
@@ -1,88 +0,0 @@
-
-
-
- Command execution
-
- All commands executed using T:Renci.SshClient.SshCommand object.
- See examples below:
-
-
-
- Execute single comamnd and display result
-
- using (var client = new SshClient("host", "username", "password"))
- {
- client.Connect();
- var cmd = client.RunCommand("ls -l");
- Console.WriteLine(cmd.Result);
- client.Disconnect();
- }
-
-
-
- Create command object then execute it
-
- using (var client = new SshClient("host", "username", "password"))
- {
- client.Connect();
- var cmd = client.CreateCommand("date");
- var result cmd.Execute();
- Console.WriteLine(result);
- client.Disconnect();
- }
-
-
-
- Create command object then use it to execute multiple times
-
- using (var client = new SshClient("host", "username", "password"))
- {
- client.Connect();
- var cmd = client.CreateCommand("date");
- cmd.Execute();
- Console.WriteLine(cmd.Result);
- cmd.Execute("ls -l");
- Console.WriteLine(cmd.Result);
- client.Disconnect();
- }
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Renci.SshNet/Documentation/Content/Guide/Guide.Connection.ChangePassword.aml b/Renci.SshNet/Documentation/Content/Guide/Guide.Connection.ChangePassword.aml
deleted file mode 100644
index 135ce7b..0000000
--- a/Renci.SshNet/Documentation/Content/Guide/Guide.Connection.ChangePassword.aml
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
-
- When user logs on and his password is expired you can ask user for a new passowrd and change it.
- Note: the event handler will be executed on new thread.
-
-
-
- Change user's password.
-
- var connectionInfo = new PasswordConnectionInfo("host", "username", "password");
- connectionInfo.PasswordExpired += delegate(object sender, AuthenticationPasswordChangeEventArgs e)
- {
- e.NewPassword = "123456";
- };
-
- using (var client = new SshClient(connectionInfo))
- {
- client.Connect();
- client.Disconnect();
- }
-
-
-
-
-
-
- T:Renci.SshClient.PasswordConnectionInfo
- T:Renci.SshClient.SshClient
- M:Renci.SshClient.SshBaseClient.Connect()
-
-
-
\ No newline at end of file
diff --git a/Renci.SshNet/Documentation/Content/Guide/Guide.Connection.Interactive.aml b/Renci.SshNet/Documentation/Content/Guide/Guide.Connection.Interactive.aml
deleted file mode 100644
index c1209ea..0000000
--- a/Renci.SshNet/Documentation/Content/Guide/Guide.Connection.Interactive.aml
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
-
-
-
- If you use interactive method of authentication you need to attach to E:Renci.SshClient.KeyboardInteractiveConnectionInfo.AuthenticationPrompt event and provide an information requested when an event raised. It can be raised more then once if server needs to.
-
-
-
-
- Change user's password.
-
- var connectionInfo = new KeyboardInteractiveConnectionInfo("host", "username");
- connectionInfo.AuthenticationPrompt += delegate(object sender, AuthenticationPromptEventArgs e)
- {
- Console.WriteLine(e.Instruction);
-
- foreach (var prompt in e.Prompts)
- {
- Console.WriteLine(prompt.Request);
- prompt.Response = Console.ReadLine();
- }
- };
-
- using (var client = new SshClient(connectionInfo))
- {
- client.Connect();
- client.Disconnect();
- }
-
-
-
-
-
-
- T:Renci.SshClient.KeyboardInteractiveConnectionInfo
- T:Renci.SshClient.SshClient
- M:Renci.SshClient.SshBaseClient.Connect()
-
-
-
\ No newline at end of file
diff --git a/Renci.SshNet/Documentation/Content/Guide/Guide.Connection.Password.aml b/Renci.SshNet/Documentation/Content/Guide/Guide.Connection.Password.aml
deleted file mode 100644
index d38cc83..0000000
--- a/Renci.SshNet/Documentation/Content/Guide/Guide.Connection.Password.aml
+++ /dev/null
@@ -1,42 +0,0 @@
-
-
-
-
- At this point some examples how to connect using password.
-
-
-
-
- Use T:Renci.SshClient.PasswordConnectionInfo object to connect.
-
-
- var connectionInfo = new PasswordConnectionInfo("host", "username", "password");
- using (var client = new SshClient(connectionInfo))
- {
- client.Connect();
- client.Disconnect();
- }
-
-
-
-
-
- Use shortcut version to connet.
-
- using (var client = new SshClient("host", "username", "password"))
- {
- client.Connect();
- client.Disconnect();
- }
-
-
-
-
-
-
- T:Renci.SshClient.PasswordConnectionInfo
- T:Renci.SshClient.SshClient
- M:Renci.SshClient.SshBaseClient.Connect()
-
-
-
\ No newline at end of file
diff --git a/Renci.SshNet/Documentation/Content/Guide/Guide.Connection.PrivateKey.aml b/Renci.SshNet/Documentation/Content/Guide/Guide.Connection.PrivateKey.aml
deleted file mode 100644
index 6aa6a54..0000000
--- a/Renci.SshNet/Documentation/Content/Guide/Guide.Connection.PrivateKey.aml
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
-
-
- At this point some examples how to connect using password.
-
-
-
- Connecting using username and private key
-
- using (var client = new SshClient("host", "username", new PrivateKeyFile(File.OpenRead(@"private.key"))))
- {
- client.Connect();
- client.Disconnect();
- }
-
-
-
- Connecting using username, private key and passphrase
-
- using (var client = new SshClient("host", "username", new PrivateKeyFile(File.OpenRead(@"private.key"), "passphrase")))
- {
- client.Connect();
- client.Disconnect();
- }
-
-
-
-
-
-
- T:Renci.SshClient.PrivateKeyConnectionInfo
- T:Renci.SshClient.SshClient
- M:Renci.SshClient.SshBaseClient.Connect()
-
-
-
\ No newline at end of file
diff --git a/Renci.SshNet/Documentation/Content/Guide/Guide.Connection.Prompt.aml b/Renci.SshNet/Documentation/Content/Guide/Guide.Connection.Prompt.aml
deleted file mode 100644
index c9bab9a..0000000
--- a/Renci.SshNet/Documentation/Content/Guide/Guide.Connection.Prompt.aml
+++ /dev/null
@@ -1,35 +0,0 @@
-
-
-
-
-
- If you need to display banner to the user return by the server when you log on you need to attach to E:Renci.SshClient.ConnectionInfo.AuthenticationBanner event.
-
-
-
-
- Change user's password.
-
- var connectionInfo = new PasswordConnectionInfo("host", "username", "password");
- connectionInfo.AuthenticationBanner += delegate(object sender, AuthenticationBannerEventArgs e)
- {
- Console.WriteLine(e.BannerMessage);
- };
-
- using (var client = new SshClient(connectionInfo))
- {
- client.Connect();
- client.Disconnect();
- }
-
-
-
-
-
-
- T:Renci.SshClient.PasswordConnectionInfo
- T:Renci.SshClient.SshClient
- M:Renci.SshClient.SshBaseClient.Connect()
-
-
-
\ No newline at end of file
diff --git a/Renci.SshNet/Documentation/Content/Guide/Guide.Connection.Timeout.aml b/Renci.SshNet/Documentation/Content/Guide/Guide.Connection.Timeout.aml
deleted file mode 100644
index d784fdf..0000000
--- a/Renci.SshNet/Documentation/Content/Guide/Guide.Connection.Timeout.aml
+++ /dev/null
@@ -1,32 +0,0 @@
-
-
-
- Specify connection time out.
-
-
- If connection is to slow you can set P:Renci.SshClient.ConnectionInfo.Timeout property to specify time to allow connection to complete.
-
-
-
-
- Specify 30 seconds timeout.
-
- var connectionInfo = new PasswordConnectionInfo("host", "username", "password");
- connectionInfo.Timeout = TimeSpan.FromSeconds(30);
- using (var client = new SshClient(connectionInfo))
- {
- client.Connect();
- client.Disconnect();
- }
-
-
-
-
-
-
- T:Renci.SshClient.PasswordConnectionInfo
- T:Renci.SshClient.SshClient
- M:Renci.SshClient.SshBaseClient.Connect()
-
-
-
\ No newline at end of file
diff --git a/Renci.SshNet/Documentation/Content/Guide/Guide.Connection.aml b/Renci.SshNet/Documentation/Content/Guide/Guide.Connection.aml
deleted file mode 100644
index 0c4dfa7..0000000
--- a/Renci.SshNet/Documentation/Content/Guide/Guide.Connection.aml
+++ /dev/null
@@ -1,125 +0,0 @@
-
-
-
-
- Establish connection
-
- To establish connection you need to provide valid credentials. Both T:Renci.SshClient.SshClient and T:Renci.SshClient.SftpClient accept same paramters. See examples below:
-
-
-
- Connecting using username and password to server's default port
-
- using (var client = new SshClient("host", "username", "password"))
- {
- client.Connect();
- client.Disconnect();
- }
-
-
-
- Connecting using username and password to server's port 1234
-
- using (var client = new SftpClient("host", 1234, "username", "password"))
- {
- client.Connect();
- client.Disconnect();
- }
-
-
-
-
- Connecting using username and private key to server's default port
-
- using (var client = new SshClient("host", "username", new PrivateKeyFile(File.OpenRead(@"private.key"))))
- {
- client.Connect();
- client.Disconnect();
- }
-
-
-
- Connecting using username and private key to server's port 1234
-
- using (var client = new SftpClient("host", 1234, "username", new PrivateKeyFile(File.OpenRead(@"private.key"))))
- {
- client.Connect();
- client.Disconnect();
- }
-
-
-
-
-
-
-
-
-
-
- Using ConnectionInfo object to connect.
-
-
-
- In more complex scenarious when additional parameters are needed during connection phase you can use T:Renci.SshClient.ConnectionInfo inherited object.
- T:Renci.SshClient.ConnectionInfo is an abstact class and you need to use one of the inhertied classes.
- Which class to use depends on how you want to connect to the server.
- To connect using private key you need to use T:Renci.SshClient.PrivateKeyConnectionInfo object.
- To connect using username and password combination use T:Renci.SshClient.PasswordConnectionInfo.
- If you have an interactive scenario you need to use T:Renci.SshClient.KeyboardInteractiveConnectionInfo.
-
- See some usage examples below:
-
-
-
-
- Use T:Renci.SshClient.PasswordConnectionInfo objet to provide username and password.
-
-
- var connectionInfo = new PasswordConnectionInfo("host", "username", "password");
- using (var client = new SshClient(connectionInfo))
- {
- client.Connect();
- client.Disconnect();
- }
-
-
-
-
- Use T:Renci.SshClient.PrivateKeyConnectionInfo objet to provide username and private key file
-
-
- var connectionInfo = new PrivateKeyConnectionInfo("host", "username", new PrivateKeyFile(File.OpenRead(@"private.key")));
- using (var client = new SshClient(connectionInfo))
- {
- client.Connect();
- client.Disconnect();
- }
-
-
-
-
- Use T:Renci.SshClient.PrivateKeyConnectionInfo objet to provide username and private key file with passphrase.
-
-
- var connectionInfo = new PrivateKeyConnectionInfo("host", "username", new PrivateKeyFile(File.OpenRead(@"private.key"), "passphrase"));
- using (var client = new SshClient(connectionInfo))
- {
- client.Connect();
- client.Disconnect();
- }
-
-
-
-
-
-
-
-
- T:Renci.SshClient.ConnectionInfo
- T:Renci.SshClient.PrivateKeyConnectionInfo
- T:Renci.SshClient.PasswordConnectionInfo
- T:Renci.SshClient.SshClient
- M:Renci.SshClient.SshBaseClient.Connect
-
-
-
\ No newline at end of file
diff --git a/Renci.SshNet/Documentation/Content/Guide/Guide.PortForward.Local.aml b/Renci.SshNet/Documentation/Content/Guide/Guide.PortForward.Local.aml
deleted file mode 100644
index 3ca6c2a..0000000
--- a/Renci.SshNet/Documentation/Content/Guide/Guide.PortForward.Local.aml
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
-
-
- Start and stop local port forwarding.
-
- using (var client = new SshClient("host", "username", "password"))
- {
- client.Connect();
- var port = client.AddForwardedPort<ForwardedPortLocal>(8084, "host to be forwarded", 80);
- port.Exception += delegate(object sender, ExceptionEventArgs e)
- {
- Console.WriteLine(e.Exception.ToString());
- };
- port.Start();
-
- Thread.Sleep(1000 * 60 * 20); // Wait 20 minutes for port to be forwarded
-
- port.Stop();
- }
-
-
-
-
- T:Renci.SshClient.SshClient
- T:Renci.SshClient.ForwardedPortLocal
-
-
-
\ No newline at end of file
diff --git a/Renci.SshNet/Documentation/Content/Guide/Guide.PortForward.Remote.aml b/Renci.SshNet/Documentation/Content/Guide/Guide.PortForward.Remote.aml
deleted file mode 100644
index 2ecc7f7..0000000
--- a/Renci.SshNet/Documentation/Content/Guide/Guide.PortForward.Remote.aml
+++ /dev/null
@@ -1,30 +0,0 @@
-
-
-
-
-
- Start and stop local port forwarding.
-
- using (var client = new SshClient("host", "username", "password"))
- {
- client.Connect();
- var port = client.AddForwardedPort<ForwardedPortRemote>(8082, "host to be forwarded", 80);
- port.Exception += delegate(object sender, ExceptionEventArgs e)
- {
- Console.WriteLine(e.Exception.ToString());
- };
- port.Start();
-
- Thread.Sleep(1000 * 60 * 20); // Wait 20 minutes for port to be forwarded
-
- port.Stop();
- }
-
-
-
-
- T:Renci.SshClient.SshClient
- T:Renci.SshClient.ForwardedPortLocal
-
-
-
\ No newline at end of file
diff --git a/Renci.SshNet/Documentation/Content/Guide/Guide.PortForward.aml b/Renci.SshNet/Documentation/Content/Guide/Guide.PortForward.aml
deleted file mode 100644
index 15d9365..0000000
--- a/Renci.SshNet/Documentation/Content/Guide/Guide.PortForward.aml
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
- Port forwarding supported for remote and local ports.
- Multiple port can be forwarded simultaneously.
- To start port forwarding you need to create an T:Renci.SshClient.ForwardedPortLocal or T:Renci.SshClient.ForwardedPortRemote object.
- Once port object is created you can use M:Renci.SshClient.ForwardedPort.Start start port forwarding or M:Renci.SshClient.ForwardedPort.Stop to stop it.
-
-
-
- An exception can be thrown while port is forwarded. When this happens an E:Renci.SshClient.ForwardedPort.Exception event is raised.
-
-
-
-
-
\ No newline at end of file
diff --git a/Renci.SshNet/Documentation/Content/Guide/Guide.SFtp.aml b/Renci.SshNet/Documentation/Content/Guide/Guide.SFtp.aml
deleted file mode 100644
index 0305ee4..0000000
--- a/Renci.SshNet/Documentation/Content/Guide/Guide.SFtp.aml
+++ /dev/null
@@ -1,85 +0,0 @@
-
-
-
-
-
-
-
-
- Required introduction
-
-
-
-
- Syntax section title
-
- Syntax content
-
-
-
-
- Parameter reference
-
-
-
-
-
-
-
-
-
-
-
- Optional section title
-
-
- Add one or more sections with content
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Renci.SshNet/Documentation/Content/Guide/Guide.aml b/Renci.SshNet/Documentation/Content/Guide/Guide.aml
deleted file mode 100644
index f8d285a..0000000
--- a/Renci.SshNet/Documentation/Content/Guide/Guide.aml
+++ /dev/null
@@ -1,75 +0,0 @@
-
-
-
-
-
- Required introduction
-
-
-
- Keyword content
-
-
-
-
- Namespaces content
-
-
-
-
-
- Background content
-
-
-
- "Implementing [Technology Name] Classes" title
-
- Implementation content
-
-
-
- "[Technology Name] Classes at a Glance" title
-
- At a Glance content
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Renci.SshNet/Documentation/Content/HowTo.Connect.aml b/Renci.SshNet/Documentation/Content/HowTo.Connect.aml
deleted file mode 100644
index e209bb6..0000000
--- a/Renci.SshNet/Documentation/Content/HowTo.Connect.aml
+++ /dev/null
@@ -1,44 +0,0 @@
-
-
-
-
-
- The library supports differnet method to connect to SSH server.
- It also has support to add a custom authentication method if needed. Method supported out of the box are :publickey, password and keyboard-interactive. There is also support for different events that can occure during authentication. For example: server can send an information that need to be presented to the user upon login, user's password is expired and new password could be provided to change user's password and others scenrios.
-
- By using T:Renci.SshClient.ConnectionInfo you can specify connection timeout, which in this case will wait 30 seconds while tying to connect to the server after which it will throw an exception if it did not connect.
-
-
-
-
- Connect using password.
-
- Following examples show how to connect using username and password combination.
-
-
- Try to connect to the host within 30 seconds.
-
- var connectionInfo = new PasswordConnectionInfo("host", "username", "password");
- connectionInfo.Timeout = TimeSpan.FromSeconds(30);
- using (var client = new SshClient(connectionInfo))
- {
- client.Connect();
- client.Disconnect();
- }
-
-
-
-
-
-
-
-
-
- T:Renci.SshClient.ConnectionInfo
- T:Renci.SshClient.PrivateKeyConnectionInfo
- T:Renci.SshClient.PasswordConnectionInfo
- T:Renci.SshClient.SshClient
- M:Renci.SshClient.SshBaseClient.Connect()
-
-
-
\ No newline at end of file
diff --git a/Renci.SshNet/Documentation/Content/Reference.aml b/Renci.SshNet/Documentation/Content/Reference.aml
deleted file mode 100644
index 2a9679a..0000000
--- a/Renci.SshNet/Documentation/Content/Reference.aml
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
-
-
-
- Assembly name
-
-
-
- API member ID
-
-
-
-
\ No newline at end of file
diff --git a/Renci.SshNet/Documentation/Renci.SshClient.content b/Renci.SshNet/Documentation/Renci.SshClient.content
deleted file mode 100644
index 112aed9..0000000
--- a/Renci.SshNet/Documentation/Renci.SshClient.content
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Renci.SshNet/Documentation/SshClient.shfbproj b/Renci.SshNet/Documentation/SshClient.shfbproj
deleted file mode 100644
index 566e84c..0000000
--- a/Renci.SshNet/Documentation/SshClient.shfbproj
+++ /dev/null
@@ -1,140 +0,0 @@
-
-
-
- Debug
- AnyCPU
- 2.0
- {0b73772a-c19f-4218-bd92-efa8d5f2ddd3}
- 1.9.0.0
-
- Documentation
- Documentation
- Documentation
-
- .\Help\
- SshClient
- en-US
-
-
-
- 4.0.30319
- A Ssh.Net Client Documentation
-
-
- http://sshnet.codeplex.com
- Summary, Parameter, Returns, AutoDocumentCtors, Namespace, TypeParameter
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/Renci.SshNet/ExpectAction.cs b/Renci.SshNet/ExpectAction.cs
new file mode 100644
index 0000000..61bd8c6
--- /dev/null
+++ b/Renci.SshNet/ExpectAction.cs
@@ -0,0 +1,60 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace Renci.SshNet
+{
+ ///
+ /// Specifies behavior for expected expression
+ ///
+ public class ExpectAction
+ {
+ ///
+ /// Gets the expected regular expression.
+ ///
+ public Regex Expect { get; private set; }
+
+ ///
+ /// Gets the action to perform when expected expression is found.
+ ///
+ public Action Action { get; private set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The expect regular expression.
+ /// The action to perform.
+ /// or is null.
+ public ExpectAction(Regex expect, Action action)
+ {
+ if (expect == null)
+ throw new ArgumentNullException("expect");
+
+ if (action == null)
+ throw new ArgumentNullException("action");
+
+ this.Expect = expect;
+ this.Action = action;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The expect expression.
+ /// The action to perform.
+ /// or is null.
+ public ExpectAction(string expect, Action action)
+ {
+ if (expect == null)
+ throw new ArgumentNullException("expect");
+
+ if (action == null)
+ throw new ArgumentNullException("action");
+
+ this.Expect = new Regex(Regex.Escape(expect));
+ this.Action = action;
+ }
+ }
+}
diff --git a/Renci.SshNet/ExpectAsyncResult.cs b/Renci.SshNet/ExpectAsyncResult.cs
new file mode 100644
index 0000000..b89e6f7
--- /dev/null
+++ b/Renci.SshNet/ExpectAsyncResult.cs
@@ -0,0 +1,23 @@
+using Renci.SshNet.Common;
+using System;
+using System.Threading;
+
+namespace Renci.SshNet
+{
+ ///
+ /// Provides additional information for asynchronous command execution
+ ///
+ public class ExpectAsyncResult : AsyncResult
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The shell stream.
+ /// The async callback.
+ /// The state.
+ internal ExpectAsyncResult(AsyncCallback asyncCallback, Object state)
+ : base(asyncCallback, state)
+ {
+ }
+ }
+}
diff --git a/Renci.SshNet/ForwardedPort.cs b/Renci.SshNet/ForwardedPort.cs
index bb8f6c2..a126441 100644
--- a/Renci.SshNet/ForwardedPort.cs
+++ b/Renci.SshNet/ForwardedPort.cs
@@ -16,26 +16,6 @@ public abstract class ForwardedPort
///
internal Session Session { get; set; }
- ///
- /// Gets the bound host.
- ///
- public string BoundHost { get; internal set; }
-
- ///
- /// Gets the bound port.
- ///
- public uint BoundPort { get; internal set; }
-
- ///
- /// Gets the forwarded host.
- ///
- public string Host { get; internal set; }
-
- ///
- /// Gets the forwarded port.
- ///
- public uint Port { get; internal set; }
-
///
/// Gets or sets a value indicating whether port forwarding started.
///
@@ -54,14 +34,6 @@ public abstract class ForwardedPort
///
public event EventHandler RequestReceived;
- ///
- /// Initializes a new instance of the class.
- ///
- internal ForwardedPort()
- {
-
- }
-
///
/// Starts port forwarding.
///
@@ -85,7 +57,10 @@ public virtual void Start()
///
public virtual void Stop()
{
- this.Session.ErrorOccured -= Session_ErrorOccured;
+ if (this.Session != null)
+ {
+ this.Session.ErrorOccured -= Session_ErrorOccured;
+ }
}
///
diff --git a/Renci.SshNet/ForwardedPortDynamic.NET.cs b/Renci.SshNet/ForwardedPortDynamic.NET.cs
new file mode 100644
index 0000000..d4aa516
--- /dev/null
+++ b/Renci.SshNet/ForwardedPortDynamic.NET.cs
@@ -0,0 +1,282 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Net;
+using System.Net.Sockets;
+using System.Threading;
+using Renci.SshNet.Channels;
+using Renci.SshNet.Common;
+
+namespace Renci.SshNet
+{
+ public partial class ForwardedPortDynamic
+ {
+ private TcpListener _listener;
+ private object _listenerLocker = new object();
+
+ partial void InternalStart()
+ {
+ // If port already started don't start it again
+ if (this.IsStarted)
+ return;
+
+ var ip = IPAddress.Any;
+ if (!string.IsNullOrEmpty(this.BoundHost))
+ {
+ ip = this.BoundHost.GetIPAddress();
+ }
+
+ var ep = new IPEndPoint(ip, (int)this.BoundPort);
+
+ this._listener = new TcpListener(ep);
+ this._listener.Start();
+
+ this._listenerTaskCompleted = new ManualResetEvent(false);
+ this.ExecuteThread(() =>
+ {
+ try
+ {
+ while (true)
+ {
+ lock (this._listenerLocker)
+ {
+ if (this._listener == null)
+ break;
+ }
+
+ var socket = this._listener.AcceptSocket();
+
+ this.ExecuteThread(() =>
+ {
+ try
+ {
+ using (var channel = this.Session.CreateChannel())
+ {
+ var version = new byte[1];
+
+ socket.Receive(version);
+
+ if (version[0] == 4)
+ {
+ this.HandleSocks4(socket, channel);
+ }
+ else if (version[0] == 5)
+ {
+ this.HandleSocks5(socket, channel);
+ }
+ else
+ {
+ throw new NotSupportedException(string.Format("SOCKS version {0} is not supported.", version));
+ }
+
+ channel.Bind();
+
+ channel.Close();
+ }
+ }
+ catch (Exception exp)
+ {
+ this.RaiseExceptionEvent(exp);
+ }
+ });
+ }
+ }
+ catch (SocketException exp)
+ {
+ if (!(exp.SocketErrorCode == SocketError.Interrupted))
+ {
+ this.RaiseExceptionEvent(exp);
+ }
+ }
+ catch (Exception exp)
+ {
+ this.RaiseExceptionEvent(exp);
+ }
+ finally
+ {
+ this._listenerTaskCompleted.Set();
+ }
+ });
+
+ this.IsStarted = true;
+ }
+
+ partial void InternalStop()
+ {
+ // If port not started you cant stop it
+ if (!this.IsStarted)
+ return;
+
+ lock (this._listenerLocker)
+ {
+ this._listener.Stop();
+ this._listener = null;
+ }
+ this._listenerTaskCompleted.WaitOne(this.Session.ConnectionInfo.Timeout);
+ this._listenerTaskCompleted.Dispose();
+ this._listenerTaskCompleted = null;
+ this.IsStarted = false;
+ }
+
+ private void HandleSocks4(Socket socket, ChannelDirectTcpip channel)
+ {
+ using (var stream = new NetworkStream(socket))
+ {
+ var commandCode = stream.ReadByte();
+ // TODO: See what need to be done depends on the code
+
+ var portBuffer = new byte[2];
+ stream.Read(portBuffer, 0, portBuffer.Length);
+ var port = (uint)(portBuffer[0] * 256 + portBuffer[1]);
+
+ var ipBuffer = new byte[4];
+ stream.Read(ipBuffer, 0, ipBuffer.Length);
+ var ipAddress = new IPAddress(ipBuffer);
+
+ var username = ReadString(stream);
+
+ var host = ipAddress.ToString();
+
+ this.RaiseRequestReceived(host, port);
+
+ channel.Open(host, port, socket);
+
+ stream.WriteByte(0x00);
+
+ if (channel.IsOpen)
+ {
+ stream.WriteByte(0x5a);
+ }
+ else
+ {
+ stream.WriteByte(0x5b);
+ }
+
+ stream.Write(portBuffer, 0, portBuffer.Length);
+ stream.Write(ipBuffer, 0, ipBuffer.Length);
+ }
+ }
+
+ private void HandleSocks5(Socket socket, ChannelDirectTcpip channel)
+ {
+ using (var stream = new NetworkStream(socket))
+ {
+ var authenticationMethodsCount = stream.ReadByte();
+
+ var authenticationMethods = new byte[authenticationMethodsCount];
+ stream.Read(authenticationMethods, 0, authenticationMethods.Length);
+
+ stream.WriteByte(0x05);
+
+ if (authenticationMethods.Min() == 0)
+ {
+ stream.WriteByte(0x00);
+ }
+ else
+ {
+ stream.WriteByte(0xFF);
+ }
+
+ var version = stream.ReadByte();
+
+ if (version != 5)
+ throw new ProxyException("SOCKS5: Version 5 is expected.");
+
+ var commandCode = stream.ReadByte();
+
+ if (stream.ReadByte() != 0)
+ {
+ throw new ProxyException("SOCKS5: 0 is expected.");
+ }
+
+ var addressType = stream.ReadByte();
+
+ IPAddress ipAddress = null;
+ byte[] addressBuffer = null;
+ switch (addressType)
+ {
+ case 0x01:
+ {
+ addressBuffer = new byte[4];
+ stream.Read(addressBuffer, 0, 4);
+
+ ipAddress = new IPAddress(addressBuffer);
+ }
+ break;
+ case 0x03:
+ {
+ var length = stream.ReadByte();
+ addressBuffer = new byte[length];
+ stream.Read(addressBuffer, 0, addressBuffer.Length);
+
+ ipAddress = IPAddress.Parse(new Renci.SshNet.Common.ASCIIEncoding().GetString(addressBuffer));
+ }
+ break;
+ case 0x04:
+ {
+ addressBuffer = new byte[16];
+ stream.Read(addressBuffer, 0, 16);
+
+ ipAddress = new IPAddress(addressBuffer);
+ }
+ break;
+ default:
+ throw new ProxyException(string.Format("SOCKS5: Address type '{0}' is not supported.", addressType));
+ }
+
+ var portBuffer = new byte[2];
+ stream.Read(portBuffer, 0, portBuffer.Length);
+ var port = (uint)(portBuffer[0] * 256 + portBuffer[1]);
+ var host = ipAddress.ToString();
+
+ this.RaiseRequestReceived(host, port);
+
+ channel.Open(host, port, socket);
+
+ stream.WriteByte(0x05);
+
+ if (channel.IsOpen)
+ {
+ stream.WriteByte(0x00);
+ }
+ else
+ {
+ stream.WriteByte(0x01);
+ }
+
+ stream.WriteByte(0x00);
+
+ var buffer = ipAddress.GetAddressBytes();
+
+ if (ipAddress.AddressFamily == AddressFamily.InterNetwork)
+ {
+ stream.WriteByte(0x01);
+ }
+ else if (ipAddress.AddressFamily == AddressFamily.InterNetwork)
+ {
+ stream.WriteByte(0x04);
+ }
+ else
+ {
+ throw new NotSupportedException("Not supported address family.");
+ }
+
+ stream.Write(buffer, 0, buffer.Length);
+ stream.Write(portBuffer, 0, portBuffer.Length);
+ }
+ }
+
+ private static string ReadString(NetworkStream stream)
+ {
+ StringBuilder text = new StringBuilder();
+ var aa = (char)stream.ReadByte();
+ while (aa != 0)
+ {
+ text.Append(aa);
+ aa = (char)stream.ReadByte();
+ }
+ return text.ToString();
+ }
+ }
+}
diff --git a/Renci.SshNet/ForwardedPortDynamic.NET40.cs b/Renci.SshNet/ForwardedPortDynamic.NET40.cs
new file mode 100644
index 0000000..952b354
--- /dev/null
+++ b/Renci.SshNet/ForwardedPortDynamic.NET40.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace Renci.SshNet
+{
+ public partial class ForwardedPortDynamic
+ {
+ partial void ExecuteThread(Action action)
+ {
+ ThreadPool.QueueUserWorkItem((o) => { action(); });
+ }
+ }
+}
diff --git a/Renci.SshNet/ForwardedPortDynamic.cs b/Renci.SshNet/ForwardedPortDynamic.cs
new file mode 100644
index 0000000..dc3ed39
--- /dev/null
+++ b/Renci.SshNet/ForwardedPortDynamic.cs
@@ -0,0 +1,126 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+
+namespace Renci.SshNet
+{
+ ///
+ /// Provides functionality for dynamic port forwarding
+ ///
+ public partial class ForwardedPortDynamic : ForwardedPort, IDisposable
+ {
+ private EventWaitHandle _listenerTaskCompleted;
+
+ ///
+ /// Gets the bound host.
+ ///
+ public string BoundHost { get; protected set; }
+
+ ///
+ /// Gets the bound port.
+ ///
+ public uint BoundPort { get; protected set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The port.
+ public ForwardedPortDynamic(uint port)
+ : this(string.Empty, port)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The host.
+ /// The port.
+ public ForwardedPortDynamic(string host, uint port)
+ {
+ this.BoundHost = host;
+ this.BoundPort = port;
+ }
+
+ ///
+ /// Starts local port forwarding.
+ ///
+ public override void Start()
+ {
+ this.InternalStart();
+ }
+
+ ///
+ /// Stops local port forwarding.
+ ///
+ public override void Stop()
+ {
+ base.Stop();
+
+ this.InternalStop();
+ }
+
+ partial void InternalStart();
+
+ partial void InternalStop();
+
+ partial void ExecuteThread(Action action);
+
+ #region IDisposable Members
+
+ private bool _isDisposed = false;
+
+ ///
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged ResourceMessages.
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Releases unmanaged and - optionally - managed resources
+ ///
+ /// true to release both managed and unmanaged resources; false to release only unmanaged ResourceMessages.
+ protected virtual void Dispose(bool disposing)
+ {
+ // Check to see if Dispose has already been called.
+ if (!this._isDisposed)
+ {
+ this.InternalStop();
+
+ // If disposing equals true, dispose all managed
+ // and unmanaged ResourceMessages.
+ if (disposing)
+ {
+ // Dispose managed ResourceMessages.
+ if (this._listenerTaskCompleted != null)
+ {
+ this._listenerTaskCompleted.Dispose();
+ this._listenerTaskCompleted = null;
+ }
+ }
+
+ // Note disposing has been done.
+ _isDisposed = true;
+ }
+ }
+
+ ///
+ /// Releases unmanaged resources and performs other cleanup operations before the
+ /// is reclaimed by garbage collection.
+ ///
+ ~ForwardedPortDynamic()
+ {
+ // Do not re-create Dispose clean-up code here.
+ // Calling Dispose(false) is optimal in terms of
+ // readability and maintainability.
+ Dispose(false);
+ }
+
+ #endregion
+ }
+}
diff --git a/Renci.SshNet/ForwardedPortLocal.NET.cs b/Renci.SshNet/ForwardedPortLocal.NET.cs
new file mode 100644
index 0000000..d24ff46
--- /dev/null
+++ b/Renci.SshNet/ForwardedPortLocal.NET.cs
@@ -0,0 +1,119 @@
+using System;
+using System.Linq;
+using System.Net.Sockets;
+using System.Net;
+using System.Threading;
+using Renci.SshNet.Channels;
+
+namespace Renci.SshNet
+{
+ ///
+ /// Provides functionality for local port forwarding
+ ///
+ public partial class ForwardedPortLocal
+ {
+ private TcpListener _listener;
+ private object _listenerLocker = new object();
+
+ partial void InternalStart()
+ {
+ // If port already started don't start it again
+ if (this.IsStarted)
+ return;
+
+ IPAddress addr = this.BoundHost.GetIPAddress();
+ var ep = new IPEndPoint(addr, (int)this.BoundPort);
+
+ this._listener = new TcpListener(ep);
+ this._listener.Start();
+
+ this.Session.ErrorOccured += Session_ErrorOccured;
+ this.Session.Disconnected += Session_Disconnected;
+
+ this._listenerTaskCompleted = new ManualResetEvent(false);
+ this.ExecuteThread(() =>
+ {
+ try
+ {
+ while (true)
+ {
+ lock (this._listenerLocker)
+ {
+ if (this._listener == null)
+ break;
+ }
+
+ var socket = this._listener.AcceptSocket();
+
+ this.ExecuteThread(() =>
+ {
+ try
+ {
+ IPEndPoint originatorEndPoint = socket.RemoteEndPoint as IPEndPoint;
+
+ this.RaiseRequestReceived(originatorEndPoint.Address.ToString(), (uint)originatorEndPoint.Port);
+
+ var channel = this.Session.CreateChannel();
+
+ channel.Open(this.Host, this.Port, socket);
+
+ channel.Bind();
+
+ channel.Close();
+ }
+ catch (Exception exp)
+ {
+ this.RaiseExceptionEvent(exp);
+ }
+ });
+ }
+ }
+ catch (SocketException exp)
+ {
+ if (!(exp.SocketErrorCode == SocketError.Interrupted))
+ {
+ this.RaiseExceptionEvent(exp);
+ }
+ }
+ catch (Exception exp)
+ {
+ this.RaiseExceptionEvent(exp);
+ }
+ finally
+ {
+ this._listenerTaskCompleted.Set();
+ }
+ });
+
+ this.IsStarted = true;
+ }
+
+ partial void InternalStop()
+ {
+ // If port not started you cant stop it
+ if (!this.IsStarted)
+ return;
+
+ lock (this._listenerLocker)
+ {
+ this._listener.Stop();
+ this._listener = null;
+ }
+ this._listenerTaskCompleted.WaitOne(this.Session.ConnectionInfo.Timeout);
+ this._listenerTaskCompleted.Dispose();
+ this._listenerTaskCompleted = null;
+
+ this.IsStarted = false;
+ }
+
+ private void Session_ErrorOccured(object sender, Common.ExceptionEventArgs e)
+ {
+ this._listener.Stop();
+ }
+
+ private void Session_Disconnected(object sender, EventArgs e)
+ {
+ this._listener.Stop();
+ }
+ }
+}
diff --git a/Renci.SshNet/ForwardedPortLocal.NET40.cs b/Renci.SshNet/ForwardedPortLocal.NET40.cs
index 150d38e..1618901 100644
--- a/Renci.SshNet/ForwardedPortLocal.NET40.cs
+++ b/Renci.SshNet/ForwardedPortLocal.NET40.cs
@@ -1,9 +1,6 @@
-using System.Threading.Tasks;
-using System;
-using System.Net.Sockets;
-using System.Net;
+using System;
using System.Threading;
-using Renci.SshNet.Channels;
+using System.Threading.Tasks;
namespace Renci.SshNet
{
@@ -12,84 +9,9 @@ namespace Renci.SshNet
///
public partial class ForwardedPortLocal
{
- private TcpListener _listener;
-
partial void ExecuteThread(Action action)
{
- Task.Factory.StartNew(action);
- }
-
- partial void InternalStart()
- {
- // If port already started don't start it again
- if (this.IsStarted)
- return;
-
- var ep = new IPEndPoint(Dns.GetHostAddresses(this.BoundHost)[0], (int)this.BoundPort);
-
- this._listener = new TcpListener(ep);
- this._listener.Start();
-
- this._listenerTaskCompleted = new ManualResetEvent(false);
- this.ExecuteThread(() =>
- {
- try
- {
- while (true)
- {
- var socket = this._listener.AcceptSocket();
-
- this.ExecuteThread(() =>
- {
- try
- {
- IPEndPoint originatorEndPoint = socket.RemoteEndPoint as IPEndPoint;
-
- this.RaiseRequestReceived(originatorEndPoint.Address.ToString(), (uint)originatorEndPoint.Port);
-
- var channel = this.Session.CreateChannel();
-
- channel.Bind(this.Host, this.Port, socket);
- }
- catch (Exception exp)
- {
- this.RaiseExceptionEvent(exp);
- }
- });
- }
- }
- catch (SocketException exp)
- {
- if (!(exp.SocketErrorCode == SocketError.Interrupted))
- {
- this.RaiseExceptionEvent(exp);
- }
- }
- catch (Exception exp)
- {
- this.RaiseExceptionEvent(exp);
- }
- finally
- {
- this._listenerTaskCompleted.Set();
- }
- });
-
- this.IsStarted = true;
- }
-
- partial void InternalStop()
- {
- // If port not started you cant stop it
- if (!this.IsStarted)
- return;
-
- this._listener.Stop();
- this._listenerTaskCompleted.WaitOne(this.Session.ConnectionInfo.Timeout);
- this._listenerTaskCompleted.Dispose();
- this._listenerTaskCompleted = null;
-
- this.IsStarted = false;
+ ThreadPool.QueueUserWorkItem((o) => { action(); });
}
}
}
diff --git a/Renci.SshNet/ForwardedPortLocal.cs b/Renci.SshNet/ForwardedPortLocal.cs
index 599f64e..1c724e9 100644
--- a/Renci.SshNet/ForwardedPortLocal.cs
+++ b/Renci.SshNet/ForwardedPortLocal.cs
@@ -10,6 +10,74 @@ public partial class ForwardedPortLocal : ForwardedPort, IDisposable
{
private EventWaitHandle _listenerTaskCompleted;
+ ///
+ /// Gets the bound host.
+ ///
+ public string BoundHost { get; protected set; }
+
+ ///
+ /// Gets the bound port.
+ ///
+ public uint BoundPort { get; protected set; }
+
+ ///
+ /// Gets the forwarded host.
+ ///
+ public string Host { get; protected set; }
+
+ ///
+ /// Gets the forwarded port.
+ ///
+ public uint Port { get; protected set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The bound port.
+ /// The host.
+ /// The port.
+ ///
+ ///
+ ///
+ public ForwardedPortLocal(uint boundPort, string host, uint port)
+ : this(string.Empty, boundPort, host, port)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The bound host.
+ /// The bound port.
+ /// The host.
+ /// The port.
+ public ForwardedPortLocal(string boundHost, uint boundPort, string host, uint port)
+ {
+ if (boundHost == null)
+ throw new ArgumentNullException("boundHost");
+
+ if (host == null)
+ throw new ArgumentNullException("host");
+
+ if (!boundHost.IsValidHost())
+ throw new ArgumentException("boundHost");
+
+ if (!boundPort.IsValidPort())
+ throw new ArgumentOutOfRangeException("boundPort");
+
+ if (!host.IsValidHost())
+ throw new ArgumentException("host");
+
+ if (!port.IsValidPort())
+ throw new ArgumentOutOfRangeException("port");
+
+ this.BoundHost = boundHost;
+ this.BoundPort = boundPort;
+ this.Host = host;
+ this.Port = port;
+ }
+
+
///
/// Starts local port forwarding.
///
@@ -57,6 +125,8 @@ protected virtual void Dispose(bool disposing)
// Check to see if Dispose has already been called.
if (!this._isDisposed)
{
+ this.InternalStop();
+
// If disposing equals true, dispose all managed
// and unmanaged ResourceMessages.
if (disposing)
diff --git a/Renci.SshNet/ForwardedPortRemote.NET.cs b/Renci.SshNet/ForwardedPortRemote.NET.cs
new file mode 100644
index 0000000..3627d8b
--- /dev/null
+++ b/Renci.SshNet/ForwardedPortRemote.NET.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Net;
+
+namespace Renci.SshNet
+{
+ ///
+ /// Provides functionality for remote port forwarding
+ ///
+ public partial class ForwardedPortRemote
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The bound port.
+ /// The host.
+ /// The port.
+ ///
+ ///
+ ///
+ public ForwardedPortRemote(uint boundPort, string host, uint port)
+ : this(string.Empty, boundPort, host, port)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The bound host.
+ /// The bound port.
+ /// The host.
+ /// The port.
+ public ForwardedPortRemote(string boundHost, uint boundPort, string host, uint port)
+ : this(Dns.GetHostEntry(boundHost).AddressList[0], boundPort, Dns.GetHostEntry(host).AddressList[0], port)
+ {
+ }
+ }
+}
diff --git a/Renci.SshNet/ForwardedPortRemote.NET40.cs b/Renci.SshNet/ForwardedPortRemote.NET40.cs
index 257cc72..7b3a9ed 100644
--- a/Renci.SshNet/ForwardedPortRemote.NET40.cs
+++ b/Renci.SshNet/ForwardedPortRemote.NET40.cs
@@ -1,4 +1,5 @@
using System;
+using System.Threading;
using System.Threading.Tasks;
namespace Renci.SshNet
@@ -10,7 +11,7 @@ public partial class ForwardedPortRemote
{
partial void ExecuteThread(Action action)
{
- Task.Factory.StartNew(action);
+ ThreadPool.QueueUserWorkItem((o) => { action(); });
}
}
}
diff --git a/Renci.SshNet/ForwardedPortRemote.cs b/Renci.SshNet/ForwardedPortRemote.cs
index a9310b0..67128a3 100644
--- a/Renci.SshNet/ForwardedPortRemote.cs
+++ b/Renci.SshNet/ForwardedPortRemote.cs
@@ -5,6 +5,7 @@
using Renci.SshNet.Common;
using System.Diagnostics;
using System.Globalization;
+using System.Net;
namespace Renci.SshNet
{
@@ -17,6 +18,77 @@ public partial class ForwardedPortRemote : ForwardedPort, IDisposable
private EventWaitHandle _globalRequestResponse = new AutoResetEvent(false);
+ ///
+ /// Gets the bound host.
+ ///
+ public IPAddress BoundHostAddress { get; protected set; }
+
+ ///
+ /// Gets the bound host.
+ ///
+ public string BoundHost
+ {
+ get
+ {
+ return this.BoundHostAddress.ToString();
+ }
+ }
+
+ ///
+ /// Gets the bound port.
+ ///
+ public uint BoundPort { get; protected set; }
+
+ ///
+ /// Gets the forwarded host.
+ ///
+ public IPAddress HostAddress { get; protected set; }
+
+ ///
+ /// Gets the forwarded host.
+ ///
+ public string Host
+ {
+ get
+ {
+ return this.HostAddress.ToString();
+ }
+ }
+
+ ///
+ /// Gets the forwarded port.
+ ///
+ public uint Port { get; protected set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The bound host address.
+ /// The bound port.
+ /// The host address.
+ /// The port.
+ /// boundHost
+ /// boundPort
+ public ForwardedPortRemote(IPAddress boundHostAddress, uint boundPort, IPAddress hostAddress, uint port)
+ {
+ if (boundHostAddress == null)
+ throw new ArgumentNullException("boundHost");
+
+ if (hostAddress == null)
+ throw new ArgumentNullException("host");
+
+ if (!boundPort.IsValidPort())
+ throw new ArgumentOutOfRangeException("boundPort");
+
+ if (!port.IsValidPort())
+ throw new ArgumentOutOfRangeException("port");
+
+ this.BoundHostAddress = boundHostAddress;
+ this.BoundPort = boundPort;
+ this.HostAddress = hostAddress;
+ this.Port = port;
+ }
+
///
/// Starts remote port forwarding.
///
@@ -92,7 +164,7 @@ private void Session_ChannelOpening(object sender, MessageEventArgs(e.Message.LocalChannelNumber, e.Message.InitialWindowSize, e.Message.MaximumPacketSize);
- channel.Bind(this.Host, this.Port);
+ channel.Bind(this.HostAddress, this.Port);
}
catch (Exception exp)
{
diff --git a/Renci.SshNet/HashInfo.cs b/Renci.SshNet/HashInfo.cs
new file mode 100644
index 0000000..0ef66e2
--- /dev/null
+++ b/Renci.SshNet/HashInfo.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Renci.SshNet.Security.Cryptography;
+using System.Security.Cryptography;
+
+namespace Renci.SshNet
+{
+ ///
+ /// Holds information about key size and cipher to use
+ ///
+ public class HashInfo
+ {
+ ///
+ /// Gets the size of the key.
+ ///
+ ///
+ /// The size of the key.
+ ///
+ public int KeySize { get; private set; }
+
+ ///
+ /// Gets the cipher.
+ ///
+ public Func HashAlgorithm { get; private set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Size of the key.
+ /// The cipher.
+ public HashInfo(int keySize, Func hash)
+ {
+ this.KeySize = keySize;
+ this.HashAlgorithm = (key) => (hash(key.Take(this.KeySize / 8).ToArray()));
+ }
+ }
+}
diff --git a/Renci.SshNet/KeyboardInteractiveAuthenticationMethod.NET40.cs b/Renci.SshNet/KeyboardInteractiveAuthenticationMethod.NET40.cs
new file mode 100644
index 0000000..bae885e
--- /dev/null
+++ b/Renci.SshNet/KeyboardInteractiveAuthenticationMethod.NET40.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using Renci.SshNet.Messages;
+using Renci.SshNet.Messages.Authentication;
+using Renci.SshNet.Common;
+using System.Threading.Tasks;
+
+namespace Renci.SshNet
+{
+ public partial class KeyboardInteractiveAuthenticationMethod : AuthenticationMethod
+ {
+ /// is null.
+ partial void ExecuteThread(Action action)
+ {
+ ThreadPool.QueueUserWorkItem((o) => { action(); });
+ }
+ }
+}
diff --git a/Renci.SshNet/KeyboardInteractiveAuthenticationMethod.cs b/Renci.SshNet/KeyboardInteractiveAuthenticationMethod.cs
new file mode 100644
index 0000000..1df7631
--- /dev/null
+++ b/Renci.SshNet/KeyboardInteractiveAuthenticationMethod.cs
@@ -0,0 +1,198 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using Renci.SshNet.Messages;
+using Renci.SshNet.Messages.Authentication;
+using Renci.SshNet.Common;
+
+namespace Renci.SshNet
+{
+ ///
+ /// Provides functionality to perform keyboard interactive authentication.
+ ///
+ public partial class KeyboardInteractiveAuthenticationMethod : AuthenticationMethod, IDisposable
+ {
+ private AuthenticationResult _authenticationResult = AuthenticationResult.Failure;
+
+ private Session _session;
+
+ private EventWaitHandle _authenticationCompleted = new AutoResetEvent(false);
+
+ private Exception _exception;
+
+ private RequestMessage _requestMessage;
+
+ ///
+ /// Gets authentication method name
+ ///
+ public override string Name
+ {
+ get { return this._requestMessage.MethodName; }
+ }
+
+ ///
+ /// Occurs when server prompts for more authentication information.
+ ///
+ public event EventHandler AuthenticationPrompt;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The username.
+ /// is whitespace or null.
+ public KeyboardInteractiveAuthenticationMethod(string username)
+ : base(username)
+ {
+ this._requestMessage = new RequestMessageKeyboardInteractive(ServiceName.Connection, username);
+ }
+
+ ///
+ /// Authenticates the specified session.
+ ///
+ /// The session to authenticate.
+ /// Result of authentication process.
+ public override AuthenticationResult Authenticate(Session session)
+ {
+ this._session = session;
+
+ session.UserAuthenticationSuccessReceived += Session_UserAuthenticationSuccessReceived;
+ session.UserAuthenticationFailureReceived += Session_UserAuthenticationFailureReceived;
+ session.MessageReceived += Session_MessageReceived;
+
+ session.RegisterMessage("SSH_MSG_USERAUTH_INFO_REQUEST");
+
+ session.SendMessage(this._requestMessage);
+
+ session.WaitHandle(this._authenticationCompleted);
+
+ session.UnRegisterMessage("SSH_MSG_USERAUTH_INFO_REQUEST");
+
+
+ session.UserAuthenticationSuccessReceived -= Session_UserAuthenticationSuccessReceived;
+ session.UserAuthenticationFailureReceived -= Session_UserAuthenticationFailureReceived;
+ session.MessageReceived -= Session_MessageReceived;
+
+
+ if (this._exception != null)
+ {
+ throw this._exception;
+ }
+
+ return this._authenticationResult;
+ }
+
+ private void Session_UserAuthenticationSuccessReceived(object sender, MessageEventArgs e)
+ {
+ this._authenticationResult = AuthenticationResult.Success;
+
+ this._authenticationCompleted.Set();
+ }
+
+ private void Session_UserAuthenticationFailureReceived(object sender, MessageEventArgs e)
+ {
+ if (e.Message.PartialSuccess)
+ this._authenticationResult = AuthenticationResult.PartialSuccess;
+ else
+ this._authenticationResult = AuthenticationResult.Failure;
+
+ // Copy allowed authentication methods
+ this.AllowedAuthentications = e.Message.AllowedAuthentications.ToList();
+
+ this._authenticationCompleted.Set();
+ }
+
+ private void Session_MessageReceived(object sender, MessageEventArgs e)
+ {
+ var informationRequestMessage = e.Message as InformationRequestMessage;
+ if (informationRequestMessage != null)
+ {
+ var eventArgs = new AuthenticationPromptEventArgs(this.Username, informationRequestMessage.Instruction, informationRequestMessage.Language, informationRequestMessage.Prompts);
+
+ this.ExecuteThread(() =>
+ {
+ try
+ {
+ if (this.AuthenticationPrompt != null)
+ {
+ this.AuthenticationPrompt(this, eventArgs);
+ }
+
+ var informationResponse = new InformationResponseMessage();
+
+ foreach (var response in from r in eventArgs.Prompts orderby r.Id ascending select r.Response)
+ {
+ informationResponse.Responses.Add(response);
+ }
+
+ // Send information response message
+ this._session.SendMessage(informationResponse);
+ }
+ catch (Exception exp)
+ {
+ this._exception = exp;
+ this._authenticationCompleted.Set();
+ }
+ });
+ }
+ }
+
+ partial void ExecuteThread(Action action);
+
+ #region IDisposable Members
+
+ private bool isDisposed = false;
+
+ ///
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Releases unmanaged and - optionally - managed resources
+ ///
+ /// true to release both managed and unmanaged resources; false to release only unmanaged resources.
+ 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 resources.
+ if (disposing)
+ {
+ // Dispose managed resources.
+ if (this._authenticationCompleted != null)
+ {
+ this._authenticationCompleted.Dispose();
+ this._authenticationCompleted = null;
+ }
+ }
+
+ // Note disposing has been done.
+ isDisposed = true;
+ }
+ }
+
+ ///
+ /// Releases unmanaged resources and performs other cleanup operations before the
+ /// is reclaimed by garbage collection.
+ ///
+ ~KeyboardInteractiveAuthenticationMethod()
+ {
+ // Do not re-create Dispose clean-up code here.
+ // Calling Dispose(false) is optimal in terms of
+ // readability and maintainability.
+ Dispose(false);
+ }
+
+ #endregion
+
+ }
+}
diff --git a/Renci.SshNet/KeyboardInteractiveConnectionInfo.cs b/Renci.SshNet/KeyboardInteractiveConnectionInfo.cs
index fef39d9..f988be9 100644
--- a/Renci.SshNet/KeyboardInteractiveConnectionInfo.cs
+++ b/Renci.SshNet/KeyboardInteractiveConnectionInfo.cs
@@ -2,9 +2,6 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
-using System.Threading;
-using Renci.SshNet.Messages.Authentication;
-using Renci.SshNet.Messages;
using Renci.SshNet.Common;
namespace Renci.SshNet
@@ -12,37 +9,40 @@ namespace Renci.SshNet
///
/// Provides connection information when keyboard interactive authentication method is used
///
- public partial class KeyboardInteractiveConnectionInfo : ConnectionInfo, IDisposable
+ ///
+ ///
+ ///
+ public class KeyboardInteractiveConnectionInfo : ConnectionInfo, IDisposable
{
- private EventWaitHandle _authenticationCompleted = new AutoResetEvent(false);
-
- private Exception _exception;
+ ///
+ /// Occurs when server prompts for more authentication information.
+ ///
+ ///
+ ///
+ ///
+ public event EventHandler AuthenticationPrompt;
- private RequestMessage _requestMessage;
+ // TODO: DOCS Add exception documentation for this class.
///
- /// Gets connection name
+ /// Initializes a new instance of the class.
///
- public override string Name
+ /// The host.
+ /// The username.
+ public KeyboardInteractiveConnectionInfo(string host, string username)
+ : this(host, ConnectionInfo.DEFAULT_PORT, username, ProxyTypes.None, string.Empty, 0, string.Empty, string.Empty)
{
- get
- {
- return this._requestMessage.MethodName;
- }
- }
- ///
- /// Occurs when server prompts for more authentication information.
- ///
- public event EventHandler AuthenticationPrompt;
+ }
///
/// Initializes a new instance of the class.
///
/// The host.
+ /// The port.
/// The username.
- public KeyboardInteractiveConnectionInfo(string host, string username)
- : this(host, 22, username)
+ public KeyboardInteractiveConnectionInfo(string host, int port, string username)
+ : this(host, port, username, ProxyTypes.None, string.Empty, 0, string.Empty, string.Empty)
{
}
@@ -53,94 +53,100 @@ public KeyboardInteractiveConnectionInfo(string host, string username)
/// Connection host.
/// Connection port.
/// Connection username.
- public KeyboardInteractiveConnectionInfo(string host, int port, string username)
- : base(host, port, username)
+ /// Type of the proxy.
+ /// The proxy host.
+ /// The proxy port.
+ public KeyboardInteractiveConnectionInfo(string host, int port, string username, ProxyTypes proxyType, string proxyHost, int proxyPort)
+ : this(host, port, username, proxyType, proxyHost, proxyPort, string.Empty, string.Empty)
{
- this._requestMessage = new RequestMessageKeyboardInteractive(ServiceName.Connection, username);
}
///
- /// Called when connection needs to be authenticated.
+ /// Initializes a new instance of the class.
///
- protected override void OnAuthenticate()
+ /// Connection host.
+ /// Connection port.
+ /// Connection username.
+ /// Type of the proxy.
+ /// The proxy host.
+ /// The proxy port.
+ /// The proxy username.
+ public KeyboardInteractiveConnectionInfo(string host, int port, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername)
+ : this(host, port, username, proxyType, proxyHost, proxyPort, proxyUsername, string.Empty)
{
- this.Session.RegisterMessage("SSH_MSG_USERAUTH_INFO_REQUEST");
-
- this.Session.SendMessage(this._requestMessage);
-
- this.WaitHandle(this._authenticationCompleted);
-
- this.Session.UnRegisterMessage("SSH_MSG_USERAUTH_INFO_REQUEST");
+ }
- if (this._exception != null)
- {
- throw this._exception;
- }
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Connection host.
+ /// Connection username.
+ /// Type of the proxy.
+ /// The proxy host.
+ /// The proxy port.
+ public KeyboardInteractiveConnectionInfo(string host, string username, ProxyTypes proxyType, string proxyHost, int proxyPort)
+ : this(host, ConnectionInfo.DEFAULT_PORT, username, proxyType, proxyHost, proxyPort, string.Empty, string.Empty)
+ {
}
///
- /// Handles the UserAuthenticationSuccessMessageReceived event of the session.
+ /// Initializes a new instance of the class.
///
- /// The source of the event.
- /// The event data.
- protected override void Session_UserAuthenticationSuccessMessageReceived(object sender, MessageEventArgs e)
+ /// Connection host.
+ /// Connection username.
+ /// Type of the proxy.
+ /// The proxy host.
+ /// The proxy port.
+ /// The proxy username.
+ public KeyboardInteractiveConnectionInfo(string host, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername)
+ : this(host, ConnectionInfo.DEFAULT_PORT, username, proxyType, proxyHost, proxyPort, proxyUsername, string.Empty)
{
- base.Session_UserAuthenticationSuccessMessageReceived(sender, e);
- this._authenticationCompleted.Set();
}
///
- /// Handles the UserAuthenticationFailureReceived event of the session.
+ /// Initializes a new instance of the class.
///
- /// The source of the event.
- /// The event data.
- protected override void Session_UserAuthenticationFailureReceived(object sender, MessageEventArgs e)
+ /// Connection host.
+ /// Connection username.
+ /// Type of the proxy.
+ /// The proxy host.
+ /// The proxy port.
+ /// The proxy username.
+ /// The proxy password.
+ public KeyboardInteractiveConnectionInfo(string host, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, string proxyPassword)
+ : this(host, ConnectionInfo.DEFAULT_PORT, username, proxyType, proxyHost, proxyPort, proxyUsername, proxyPassword)
{
- base.Session_UserAuthenticationFailureReceived(sender, e);
- this._authenticationCompleted.Set();
}
///
- /// Handles the MessageReceived event of the session.
+ /// Initializes a new instance of the class.
///
- /// The source of the event.
- /// The event data.
- protected override void Session_MessageReceived(object sender, MessageEventArgs e)
+ /// Connection host.
+ /// Connection port.
+ /// Connection username.
+ /// Type of the proxy.
+ /// The proxy host.
+ /// The proxy port.
+ /// The proxy username.
+ /// The proxy password.
+ public KeyboardInteractiveConnectionInfo(string host, int port, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, string proxyPassword)
+ : base(host, port, username, proxyType, proxyHost, proxyPort, proxyUsername, proxyPassword, new KeyboardInteractiveAuthenticationMethod(username))
{
- var informationRequestMessage = e.Message as InformationRequestMessage;
- if (informationRequestMessage != null)
+ foreach (var authenticationMethod in this.AuthenticationMethods.OfType())
{
- var eventArgs = new AuthenticationPromptEventArgs(this.Username, informationRequestMessage.Instruction, informationRequestMessage.Language, informationRequestMessage.Prompts);
-
- this.ExecuteThread(() =>
- {
- try
- {
- if (this.AuthenticationPrompt != null)
- {
- this.AuthenticationPrompt(this, eventArgs);
- }
-
- var informationResponse = new InformationResponseMessage();
+ authenticationMethod.AuthenticationPrompt += AuthenticationMethod_AuthenticationPrompt;
+ }
- foreach (var response in from r in eventArgs.Prompts orderby r.Id ascending select r.Response)
- {
- informationResponse.Responses.Add(response);
- }
+ }
- // Send information response message
- this.SendMessage(informationResponse);
- }
- catch (Exception exp)
- {
- this._exception = exp;
- this._authenticationCompleted.Set();
- }
- });
+ private void AuthenticationMethod_AuthenticationPrompt(object sender, AuthenticationPromptEventArgs e)
+ {
+ if (this.AuthenticationPrompt != null)
+ {
+ this.AuthenticationPrompt(sender, e);
}
}
- partial void ExecuteThread(Action action);
#region IDisposable Members
@@ -170,10 +176,12 @@ protected virtual void Dispose(bool disposing)
if (disposing)
{
// Dispose managed resources.
- if (this._authenticationCompleted != null)
+ if (this.AuthenticationMethods != null)
{
- this._authenticationCompleted.Dispose();
- this._authenticationCompleted = null;
+ foreach (var authenticationMethods in this.AuthenticationMethods.OfType())
+ {
+ authenticationMethods.Dispose();
+ }
}
}
@@ -184,7 +192,7 @@ protected virtual void Dispose(bool disposing)
///
/// Releases unmanaged resources and performs other cleanup operations before the
- /// is reclaimed by garbage collection.
+ /// is reclaimed by garbage collection.
///
~KeyboardInteractiveConnectionInfo()
{
diff --git a/Renci.SshNet/MessageEventArgs.cs b/Renci.SshNet/MessageEventArgs.cs
index fe8352e..fddf7ad 100644
--- a/Renci.SshNet/MessageEventArgs.cs
+++ b/Renci.SshNet/MessageEventArgs.cs
@@ -17,8 +17,12 @@ public class MessageEventArgs : EventArgs
/// Initializes a new instance of the class.
///
/// The message.
+ /// is null.
public MessageEventArgs(T message)
{
+ if (message == null)
+ throw new ArgumentNullException("message");
+
this.Message = message;
}
}
diff --git a/Renci.SshNet/Messages/Authentication/BannerMessage.cs b/Renci.SshNet/Messages/Authentication/BannerMessage.cs
index 17d0cfe..d408457 100644
--- a/Renci.SshNet/Messages/Authentication/BannerMessage.cs
+++ b/Renci.SshNet/Messages/Authentication/BannerMessage.cs
@@ -32,7 +32,7 @@ protected override void LoadData()
///
protected override void SaveData()
{
- this.Write(this.Message, Encoding.UTF8);
+ this.Write(this.Message);
this.Write(this.Language);
}
}
diff --git a/Renci.SshNet/Messages/Authentication/PublicKeyMessage.cs b/Renci.SshNet/Messages/Authentication/PublicKeyMessage.cs
index f0ea0fd..7bbe024 100644
--- a/Renci.SshNet/Messages/Authentication/PublicKeyMessage.cs
+++ b/Renci.SshNet/Messages/Authentication/PublicKeyMessage.cs
@@ -27,7 +27,7 @@ internal class PublicKeyMessage : Message
///
protected override void LoadData()
{
- this.PublicKeyAlgorithmName = this.ReadString();
+ this.PublicKeyAlgorithmName = this.ReadAsciiString();
this.PublicKeyData = this.ReadBinaryString();
}
@@ -36,7 +36,7 @@ protected override void LoadData()
///
protected override void SaveData()
{
- this.Write(this.PublicKeyAlgorithmName);
+ this.WriteAscii(this.PublicKeyAlgorithmName);
this.WriteBinaryString(this.PublicKeyData);
}
}
diff --git a/Renci.SshNet/Messages/Authentication/RequestMessage.cs b/Renci.SshNet/Messages/Authentication/RequestMessage.cs
index f27fafe..df5220f 100644
--- a/Renci.SshNet/Messages/Authentication/RequestMessage.cs
+++ b/Renci.SshNet/Messages/Authentication/RequestMessage.cs
@@ -54,19 +54,19 @@ protected override void LoadData()
///
protected override void SaveData()
{
- this.Write(this.Username, Encoding.UTF8);
+ this.Write(this.Username);
switch (this.ServiceName)
{
case ServiceName.UserAuthentication:
- this.Write("ssh-userauth", Encoding.UTF8);
+ this.WriteAscii("ssh-userauth");
break;
case ServiceName.Connection:
- this.Write("ssh-connection", Encoding.UTF8);
+ this.WriteAscii("ssh-connection");
break;
default:
throw new NotSupportedException("Not supported service name");
}
- this.Write(this.MethodName);
+ this.WriteAscii(this.MethodName);
}
}
}
diff --git a/Renci.SshNet/Messages/Authentication/RequestMessageHost.cs b/Renci.SshNet/Messages/Authentication/RequestMessageHost.cs
index 731d66e..c7357da 100644
--- a/Renci.SshNet/Messages/Authentication/RequestMessageHost.cs
+++ b/Renci.SshNet/Messages/Authentication/RequestMessageHost.cs
@@ -83,10 +83,10 @@ protected override void SaveData()
{
base.SaveData();
- this.Write(this.PublicKeyAlgorithm);
+ this.WriteAscii(this.PublicKeyAlgorithm);
this.WriteBinaryString(this.PublicHostKey);
this.Write(this.ClientHostName);
- this.Write(this.ClientUsername, Encoding.UTF8);
+ this.Write(this.ClientUsername);
if (this.Signature != null)
this.WriteBinaryString(this.Signature);
diff --git a/Renci.SshNet/Messages/Authentication/RequestMessageKeyboardInteractive.cs b/Renci.SshNet/Messages/Authentication/RequestMessageKeyboardInteractive.cs
index 51f28c7..8807d1d 100644
--- a/Renci.SshNet/Messages/Authentication/RequestMessageKeyboardInteractive.cs
+++ b/Renci.SshNet/Messages/Authentication/RequestMessageKeyboardInteractive.cs
@@ -52,7 +52,7 @@ protected override void SaveData()
this.Write(this.Language);
- this.Write(this.SubMethods, Encoding.UTF8);
+ this.Write(this.SubMethods);
}
}
}
diff --git a/Renci.SshNet/Messages/Authentication/RequestMessagePassword.cs b/Renci.SshNet/Messages/Authentication/RequestMessagePassword.cs
index f21b741..f275803 100644
--- a/Renci.SshNet/Messages/Authentication/RequestMessagePassword.cs
+++ b/Renci.SshNet/Messages/Authentication/RequestMessagePassword.cs
@@ -24,12 +24,12 @@ public override string MethodName
///
/// Gets authentication password.
///
- public string Password { get; private set; }
+ public byte[] Password { get; private set; }
///
/// Gets new authentication password.
///
- public string NewPassword { get; private set; }
+ public byte[] NewPassword { get; private set; }
///
/// Initializes a new instance of the class.
@@ -37,10 +37,10 @@ public override string MethodName
/// Name of the service.
/// Authentication username.
/// Authentication password.
- public RequestMessagePassword(ServiceName serviceName, string username, string password)
+ public RequestMessagePassword(ServiceName serviceName, string username, byte[] password)
: base(serviceName, username)
{
- this.Password = password ?? string.Empty;
+ this.Password = password;
}
///
@@ -50,10 +50,10 @@ public RequestMessagePassword(ServiceName serviceName, string username, string p
/// Authentication username.
/// Authentication password.
/// New authentication password.
- public RequestMessagePassword(ServiceName serviceName, string username, string password, string newPassword)
+ public RequestMessagePassword(ServiceName serviceName, string username, byte[] password, byte[] newPassword)
: this(serviceName, username, password)
{
- this.NewPassword = newPassword ?? string.Empty;
+ this.NewPassword = newPassword;
}
///
@@ -63,13 +63,15 @@ protected override void SaveData()
{
base.SaveData();
- this.Write(!string.IsNullOrEmpty(this.NewPassword));
+ this.Write(this.NewPassword != null);
- this.Write(this.Password, Encoding.UTF8);
+ this.Write((uint)this.Password.Length);
+ this.Write(this.Password);
- if (!string.IsNullOrEmpty(this.NewPassword))
+ if (this.NewPassword != null)
{
- this.Write(this.NewPassword, Encoding.UTF8);
+ this.Write((uint)this.NewPassword.Length);
+ this.Write(this.NewPassword);
}
}
}
diff --git a/Renci.SshNet/Messages/Authentication/RequestMessagePublicKey.cs b/Renci.SshNet/Messages/Authentication/RequestMessagePublicKey.cs
index 94aa7bf..2442a22 100644
--- a/Renci.SshNet/Messages/Authentication/RequestMessagePublicKey.cs
+++ b/Renci.SshNet/Messages/Authentication/RequestMessagePublicKey.cs
@@ -85,7 +85,7 @@ protected override void SaveData()
{
this.Write(true);
}
- this.Write(this.PublicKeyAlgorithmName);
+ this.WriteAscii(this.PublicKeyAlgorithmName);
this.WriteBinaryString(this.PublicKeyData);
if (this.Signature != null)
this.WriteBinaryString(this.Signature);
diff --git a/Renci.SshNet/Messages/Connection/ChannelExtendedDataMessage.cs b/Renci.SshNet/Messages/Connection/ChannelExtendedDataMessage.cs
index 5cb2131..38a03ae 100644
--- a/Renci.SshNet/Messages/Connection/ChannelExtendedDataMessage.cs
+++ b/Renci.SshNet/Messages/Connection/ChannelExtendedDataMessage.cs
@@ -28,9 +28,11 @@ public ChannelExtendedDataMessage()
/// Initializes a new instance of the class.
///
/// The local channel number.
- public ChannelExtendedDataMessage(uint localChannelNumber)
+ public ChannelExtendedDataMessage(uint localChannelNumber, uint dataTypeCode, byte[] data)
{
this.LocalChannelNumber = localChannelNumber;
+ this.DataTypeCode = dataTypeCode;
+ this.Data = data;
}
///
diff --git a/Renci.SshNet/Messages/Connection/ChannelOpen/ChannelOpenMessage.cs b/Renci.SshNet/Messages/Connection/ChannelOpen/ChannelOpenMessage.cs
index a10c302..aebeda7 100644
--- a/Renci.SshNet/Messages/Connection/ChannelOpen/ChannelOpenMessage.cs
+++ b/Renci.SshNet/Messages/Connection/ChannelOpen/ChannelOpenMessage.cs
@@ -72,7 +72,7 @@ public ChannelOpenMessage(uint channelNumber, uint initialWindowSize, uint maxim
///
protected override void LoadData()
{
- var channelName = this.ReadString();
+ var channelName = this.ReadAsciiString();
this.LocalChannelNumber = this.ReadUInt32();
this.InitialWindowSize = this.ReadUInt32();
this.MaximumPacketSize = this.ReadUInt32();
@@ -108,7 +108,7 @@ protected override void LoadData()
///
protected override void SaveData()
{
- this.Write(this.ChannelType);
+ this.WriteAscii(this.ChannelType);
this.Write(this.LocalChannelNumber);
this.Write(this.InitialWindowSize);
this.Write(this.MaximumPacketSize);
diff --git a/Renci.SshNet/Messages/Connection/ChannelRequest/BreakRequestInfo.cs b/Renci.SshNet/Messages/Connection/ChannelRequest/BreakRequestInfo.cs
new file mode 100644
index 0000000..cf9e3ab
--- /dev/null
+++ b/Renci.SshNet/Messages/Connection/ChannelRequest/BreakRequestInfo.cs
@@ -0,0 +1,72 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Renci.SshNet.Messages.Connection
+{
+ ///
+ /// Represents "break" type channel request information
+ ///
+ internal class BreakRequestInfo : RequestInfo
+ {
+ ///
+ /// Channel request name
+ ///
+ public const string NAME = "break";
+
+ ///
+ /// Gets the name of the request.
+ ///
+ ///
+ /// The name of the request.
+ ///
+ public override string RequestName
+ {
+ get { return BreakRequestInfo.NAME; }
+ }
+
+ ///
+ /// Gets break length in milliseconds.
+ ///
+ public UInt32 BreakLength { get; private set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public BreakRequestInfo()
+ {
+ this.WantReply = true;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Length of the break.
+ public BreakRequestInfo(UInt32 breakLength)
+ : this()
+ {
+ this.BreakLength = breakLength;
+ }
+
+ ///
+ /// Called when type specific data need to be loaded.
+ ///
+ protected override void LoadData()
+ {
+ base.LoadData();
+
+ this.BreakLength = this.ReadUInt32();
+ }
+
+ ///
+ /// Called when type specific data need to be saved.
+ ///
+ protected override void SaveData()
+ {
+ base.SaveData();
+
+ this.Write(this.BreakLength);
+ }
+ }
+}
diff --git a/Renci.SshNet/Messages/Connection/ChannelRequest/ChannelRequestMessage.cs b/Renci.SshNet/Messages/Connection/ChannelRequest/ChannelRequestMessage.cs
index 34feca0..d602f9c 100644
--- a/Renci.SshNet/Messages/Connection/ChannelRequest/ChannelRequestMessage.cs
+++ b/Renci.SshNet/Messages/Connection/ChannelRequest/ChannelRequestMessage.cs
@@ -49,7 +49,7 @@ protected override void LoadData()
{
base.LoadData();
- this.RequestName = this.ReadString();
+ this.RequestName = this.ReadAsciiString();
this.RequestData = this.ReadBytes();
}
@@ -60,7 +60,7 @@ protected override void SaveData()
{
base.SaveData();
- this.Write(this.RequestName);
+ this.WriteAscii(this.RequestName);
this.Write(this.RequestData);
}
}
diff --git a/Renci.SshNet/Messages/Connection/ChannelRequest/ExecRequestInfo.cs b/Renci.SshNet/Messages/Connection/ChannelRequest/ExecRequestInfo.cs
index 1d0b72b..86c4b54 100644
--- a/Renci.SshNet/Messages/Connection/ChannelRequest/ExecRequestInfo.cs
+++ b/Renci.SshNet/Messages/Connection/ChannelRequest/ExecRequestInfo.cs
@@ -26,8 +26,19 @@ public override string RequestName
///
/// Gets command to execute.
///
+ ///
+ /// The command.
+ ///
public string Command { get; private set; }
+ ///
+ /// Gets the encoding.
+ ///
+ ///
+ /// The encoding.
+ ///
+ public Encoding Encoding { get; private set; }
+
///
/// Initializes a new instance of the class.
///
@@ -40,10 +51,15 @@ public ExecRequestInfo()
/// Initializes a new instance of the class.
///
/// The command.
- public ExecRequestInfo(string command)
+ /// is null.
+ public ExecRequestInfo(string command, Encoding encoding)
: this()
{
+ if (command == null)
+ throw new System.ArgumentNullException("command");
+
this.Command = command;
+ this.Encoding = encoding;
}
///
@@ -63,7 +79,7 @@ protected override void SaveData()
{
base.SaveData();
- this.Write(this.Command, Encoding.UTF8);
+ this.Write(this.Command, this.Encoding);
}
}
}
diff --git a/Renci.SshNet/Messages/Connection/ChannelRequest/ExitSignalRequestInfo.cs b/Renci.SshNet/Messages/Connection/ChannelRequest/ExitSignalRequestInfo.cs
index a64e0ef..8be8535 100644
--- a/Renci.SshNet/Messages/Connection/ChannelRequest/ExitSignalRequestInfo.cs
+++ b/Renci.SshNet/Messages/Connection/ChannelRequest/ExitSignalRequestInfo.cs
@@ -79,7 +79,7 @@ protected override void LoadData()
{
base.LoadData();
- this.SignalName = this.ReadString();
+ this.SignalName = this.ReadAsciiString();
this.CoreDumped = this.ReadBoolean();
this.ErrorMessage = this.ReadString();
this.Language = this.ReadString();
@@ -92,10 +92,10 @@ protected override void SaveData()
{
base.SaveData();
- this.Write(this.SignalName);
+ this.WriteAscii(this.SignalName);
this.Write(this.CoreDumped);
this.Write(this.ErrorMessage);
- this.Write(this.Language, Encoding.UTF8);
+ this.Write(this.Language);
}
}
diff --git a/Renci.SshNet/Messages/Connection/ChannelRequest/PseudoTerminalInfo.cs b/Renci.SshNet/Messages/Connection/ChannelRequest/PseudoTerminalInfo.cs
index be70305..5bc34cf 100644
--- a/Renci.SshNet/Messages/Connection/ChannelRequest/PseudoTerminalInfo.cs
+++ b/Renci.SshNet/Messages/Connection/ChannelRequest/PseudoTerminalInfo.cs
@@ -1,4 +1,7 @@
-namespace Renci.SshNet.Messages.Connection
+using System;
+using Renci.SshNet.Common;
+using System.Collections.Generic;
+namespace Renci.SshNet.Messages.Connection
{
///
/// Represents "pty-req" type channel request information
@@ -67,7 +70,7 @@ public override string RequestName
///
/// The terminal mode.
///
- public string TerminalMode { get; set; }
+ public IDictionary TerminalModeValues { get; set; }
///
/// Initializes a new instance of the class.
@@ -85,8 +88,8 @@ public PseudoTerminalRequestInfo()
/// The rows.
/// The width.
/// The height.
- /// The terminal mode.
- public PseudoTerminalRequestInfo(string environmentVariable, uint columns, uint rows, uint width, uint height, string terminalMode)
+ /// The terminal mode values.
+ public PseudoTerminalRequestInfo(string environmentVariable, uint columns, uint rows, uint width, uint height, IDictionary terminalModeValues)
: this()
{
this.EnvironmentVariable = environmentVariable;
@@ -94,22 +97,7 @@ public PseudoTerminalRequestInfo(string environmentVariable, uint columns, uint
this.Rows = rows;
this.PixelWidth = width;
this.PixelHeight = height;
- this.TerminalMode = terminalMode;
- }
-
- ///
- /// Called when type specific data need to be loaded.
- ///
- protected override void LoadData()
- {
- base.LoadData();
-
- this.EnvironmentVariable = this.ReadString();
- this.Columns = this.ReadUInt32();
- this.Rows = this.ReadUInt32();
- this.PixelWidth = this.ReadUInt32();
- this.PixelHeight = this.ReadUInt32();
- this.TerminalMode = this.ReadString();
+ this.TerminalModeValues = terminalModeValues;
}
///
@@ -124,8 +112,22 @@ protected override void SaveData()
this.Write(this.Rows);
this.Write(this.Rows);
this.Write(this.PixelHeight);
- this.Write(this.TerminalMode);
+ if (this.TerminalModeValues != null)
+ {
+ this.Write((uint)this.TerminalModeValues.Count * (1 + 4) + 1);
+
+ foreach (var item in this.TerminalModeValues)
+ {
+ this.Write((byte)item.Key);
+ this.Write(item.Value);
+ }
+ this.Write((byte)0);
+ }
+ else
+ {
+ this.Write((uint)0);
+ }
}
}
}
diff --git a/Renci.SshNet/Messages/Connection/ChannelRequest/SignalRequestInfo.cs b/Renci.SshNet/Messages/Connection/ChannelRequest/SignalRequestInfo.cs
index eb50dce..2e65001 100644
--- a/Renci.SshNet/Messages/Connection/ChannelRequest/SignalRequestInfo.cs
+++ b/Renci.SshNet/Messages/Connection/ChannelRequest/SignalRequestInfo.cs
@@ -54,7 +54,7 @@ protected override void LoadData()
{
base.LoadData();
- this.SignalName = this.ReadString();
+ this.SignalName = this.ReadAsciiString();
}
///
@@ -64,7 +64,7 @@ protected override void SaveData()
{
base.SaveData();
- this.Write(this.SignalName);
+ this.WriteAscii(this.SignalName);
}
}
}
diff --git a/Renci.SshNet/Messages/Connection/ChannelRequest/SubsystemRequestInfo.cs b/Renci.SshNet/Messages/Connection/ChannelRequest/SubsystemRequestInfo.cs
index 81e5d6d..ea31542 100644
--- a/Renci.SshNet/Messages/Connection/ChannelRequest/SubsystemRequestInfo.cs
+++ b/Renci.SshNet/Messages/Connection/ChannelRequest/SubsystemRequestInfo.cs
@@ -54,7 +54,7 @@ protected override void LoadData()
{
base.LoadData();
- this.SubsystemName = this.ReadString();
+ this.SubsystemName = this.ReadAsciiString();
}
///
@@ -64,7 +64,7 @@ protected override void SaveData()
{
base.SaveData();
- this.Write(this.SubsystemName);
+ this.WriteAscii(this.SubsystemName);
}
}
}
diff --git a/Renci.SshNet/Messages/Connection/ChannelRequest/X11ForwardingRequestInfo.cs b/Renci.SshNet/Messages/Connection/ChannelRequest/X11ForwardingRequestInfo.cs
index 3ccb2e9..12cfc84 100644
--- a/Renci.SshNet/Messages/Connection/ChannelRequest/X11ForwardingRequestInfo.cs
+++ b/Renci.SshNet/Messages/Connection/ChannelRequest/X11ForwardingRequestInfo.cs
@@ -85,7 +85,7 @@ protected override void LoadData()
base.LoadData();
this.IsSingleConnection = this.ReadBoolean();
- this.AuthenticationProtocol = this.ReadString();
+ this.AuthenticationProtocol = this.ReadAsciiString();
this.AuthenticationCookie = this.ReadBinaryString();
this.ScreenNumber = this.ReadUInt32();
}
@@ -98,7 +98,7 @@ protected override void SaveData()
base.SaveData();
this.Write(this.IsSingleConnection);
- this.Write(this.AuthenticationProtocol);
+ this.WriteAscii(this.AuthenticationProtocol);
this.WriteBinaryString(this.AuthenticationCookie);
this.Write(this.ScreenNumber);
}
diff --git a/Renci.SshNet/Messages/Connection/GlobalRequestMessage.cs b/Renci.SshNet/Messages/Connection/GlobalRequestMessage.cs
index c9a6891..4f60c36 100644
--- a/Renci.SshNet/Messages/Connection/GlobalRequestMessage.cs
+++ b/Renci.SshNet/Messages/Connection/GlobalRequestMessage.cs
@@ -73,22 +73,25 @@ public GlobalRequestMessage(GlobalRequestName requestName, bool wantReply, strin
///
protected override void LoadData()
{
- var requestName = this.ReadString();
+ var requestName = this.ReadAsciiString();
+
+ this.WantReply = this.ReadBoolean();
+
switch (requestName)
{
case "tcpip-forward":
this.RequestName = GlobalRequestName.TcpIpForward;
+ this.AddressToBind = this.ReadString();
+ this.PortToBind = this.ReadUInt32();
break;
case "cancel-tcpip-forward":
this.RequestName = GlobalRequestName.CancelTcpIpForward;
+ this.AddressToBind = this.ReadString();
+ this.PortToBind = this.ReadUInt32();
break;
default:
break;
}
-
- this.WantReply = this.ReadBoolean();
- this.AddressToBind = this.ReadString();
- this.PortToBind = this.ReadUInt32();
}
///
@@ -99,10 +102,10 @@ protected override void SaveData()
switch (this.RequestName)
{
case GlobalRequestName.TcpIpForward:
- this.Write("tcpip-forward");
+ this.WriteAscii("tcpip-forward");
break;
case GlobalRequestName.CancelTcpIpForward:
- this.Write("cancel-tcpip-forward");
+ this.WriteAscii("cancel-tcpip-forward");
break;
default:
break;
diff --git a/Renci.SshNet/Messages/Message.cs b/Renci.SshNet/Messages/Message.cs
index 0614676..4fe37f1 100644
--- a/Renci.SshNet/Messages/Message.cs
+++ b/Renci.SshNet/Messages/Message.cs
@@ -10,25 +10,6 @@ namespace Renci.SshNet.Messages
///
public abstract class Message : SshData
{
- ///
- /// Loads the specified data.
- ///
- /// SSH message type
- /// Message data.
- /// SSH message object
- internal static T Load(byte[] data) where T : Message, new()
- {
- T message = new T();
-
- message.LoadBytes(data);
-
- message.ResetReader();
-
- message.LoadData();
-
- return message;
- }
-
///
/// Gets the index that represents zero in current data type.
///
@@ -46,7 +27,7 @@ protected override int ZeroReaderIndex
///
/// Gets data bytes array
///
- ///
+ /// Byte array representation of the message
public override byte[] GetBytes()
{
var messageAttribute = this.GetType().GetCustomAttributes(typeof(MessageAttribute), true).SingleOrDefault() as MessageAttribute;
diff --git a/Renci.SshNet/Messages/Transport/DisconnectMessage.cs b/Renci.SshNet/Messages/Transport/DisconnectMessage.cs
index 22ea569..bfc7bdb 100644
--- a/Renci.SshNet/Messages/Transport/DisconnectMessage.cs
+++ b/Renci.SshNet/Messages/Transport/DisconnectMessage.cs
@@ -6,7 +6,7 @@ namespace Renci.SshNet.Messages.Transport
/// Represents SSH_MSG_DISCONNECT message.
///
[Message("SSH_MSG_DISCONNECT", 1)]
- public class DisconnectMessage : Message,IKeyExchangedAllowed
+ public class DisconnectMessage : Message, IKeyExchangedAllowed
{
///
/// Gets disconnect reason code.
@@ -58,7 +58,7 @@ protected override void LoadData()
protected override void SaveData()
{
this.Write((uint)this.ReasonCode);
- this.Write(this.Description, Encoding.UTF8);
+ this.Write(this.Description);
this.Write(this.Language ?? "en");
}
}
diff --git a/Renci.SshNet/Messages/Transport/KeyExchangeDhGroupExchangeInit.cs b/Renci.SshNet/Messages/Transport/KeyExchangeDhGroupExchangeInit.cs
index 3d00cc3..8ecdf82 100644
--- a/Renci.SshNet/Messages/Transport/KeyExchangeDhGroupExchangeInit.cs
+++ b/Renci.SshNet/Messages/Transport/KeyExchangeDhGroupExchangeInit.cs
@@ -10,7 +10,7 @@ namespace Renci.SshNet.Messages.Transport
/// Represents SSH_MSG_KEX_DH_GEX_INIT message.
///
[Message("SSH_MSG_KEX_DH_GEX_INIT", 32)]
- internal class KeyExchangeDhGroupExchangeInit : Message,IKeyExchangedAllowed
+ internal class KeyExchangeDhGroupExchangeInit : Message, IKeyExchangedAllowed
{
///
/// Gets the E value.
diff --git a/Renci.SshNet/Messages/Transport/KeyExchangeDhGroupExchangeRequest.cs b/Renci.SshNet/Messages/Transport/KeyExchangeDhGroupExchangeRequest.cs
index 19725db..7c29004 100644
--- a/Renci.SshNet/Messages/Transport/KeyExchangeDhGroupExchangeRequest.cs
+++ b/Renci.SshNet/Messages/Transport/KeyExchangeDhGroupExchangeRequest.cs
@@ -9,7 +9,7 @@ namespace Renci.SshNet.Messages.Transport
/// Represents SSH_MSG_KEX_DH_GEX_REQUEST message.
///
[Message("SSH_MSG_KEX_DH_GEX_REQUEST", 34)]
- internal class KeyExchangeDhGroupExchangeRequest : Message,IKeyExchangedAllowed
+ internal class KeyExchangeDhGroupExchangeRequest : Message, IKeyExchangedAllowed
{
///
/// Gets or sets the minimal size in bits of an acceptable group.
diff --git a/Renci.SshNet/Messages/Transport/KeyExchangeDhInitMessage.cs b/Renci.SshNet/Messages/Transport/KeyExchangeDhInitMessage.cs
index b19f109..30e88c0 100644
--- a/Renci.SshNet/Messages/Transport/KeyExchangeDhInitMessage.cs
+++ b/Renci.SshNet/Messages/Transport/KeyExchangeDhInitMessage.cs
@@ -6,7 +6,7 @@ namespace Renci.SshNet.Messages.Transport
/// Represents SSH_MSG_KEXDH_INIT message.
///
[Message("SSH_MSG_KEXDH_INIT", 30)]
- internal class KeyExchangeDhInitMessage : Message,IKeyExchangedAllowed
+ internal class KeyExchangeDhInitMessage : Message, IKeyExchangedAllowed
{
///
/// Gets the E value.
diff --git a/Renci.SshNet/Messages/Transport/KeyExchangeEcdhInitMessage.cs b/Renci.SshNet/Messages/Transport/KeyExchangeEcdhInitMessage.cs
new file mode 100644
index 0000000..9753bbe
--- /dev/null
+++ b/Renci.SshNet/Messages/Transport/KeyExchangeEcdhInitMessage.cs
@@ -0,0 +1,50 @@
+using Renci.SshNet.Common;
+using System.Linq;
+using System.Collections.Generic;
+
+namespace Renci.SshNet.Messages.Transport
+{
+ ///
+ /// Represents SSH_MSG_KEXECDH_INIT message.
+ ///
+ [Message("SSH_MSG_KEXECDH_INIT", 30)]
+ internal class KeyExchangeEcdhInitMessage : Message, IKeyExchangedAllowed
+ {
+ ///
+ /// Gets the client's ephemeral contribution to the ECDH exchange, encoded as an octet string
+ ///
+ public byte[] QC { get; private set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The client exchange value.
+ public KeyExchangeEcdhInitMessage(BigInteger d, BigInteger Q)
+ {
+ var a = d.ToByteArray().Reverse();
+ var b = Q.ToByteArray().Reverse();
+ var data = new List();
+ data.Add(0x04);
+ data.AddRange(d.ToByteArray().Reverse());
+ data.AddRange(Q.ToByteArray().Reverse());
+ this.QC = data.ToArray();
+ }
+
+ ///
+ /// Called when type specific data need to be loaded.
+ ///
+ protected override void LoadData()
+ {
+ this.ResetReader();
+ this.QC = this.ReadBinaryString();
+ }
+
+ ///
+ /// Called when type specific data need to be saved.
+ ///
+ protected override void SaveData()
+ {
+ this.WriteBinaryString(this.QC);
+ }
+ }
+}
diff --git a/Renci.SshNet/Messages/Transport/KeyExchangeEcdhReplyMessage.cs b/Renci.SshNet/Messages/Transport/KeyExchangeEcdhReplyMessage.cs
new file mode 100644
index 0000000..a7d1d3a
--- /dev/null
+++ b/Renci.SshNet/Messages/Transport/KeyExchangeEcdhReplyMessage.cs
@@ -0,0 +1,50 @@
+using System;
+using Renci.SshNet.Common;
+
+namespace Renci.SshNet.Messages.Transport
+{
+ ///
+ /// Represents SSH_MSG_KEXECDH_REPLY message.
+ ///
+ [Message("SSH_MSG_KEXECDH_REPLY", 31)]
+ public class KeyExchangeEcdhReplyMessage : Message
+ {
+ ///
+ /// Gets a string encoding an X.509v3 certificate containing the server's ECDSA public host key
+ ///
+ /// The host key.
+ public byte[] KS { get; private set; }
+
+ ///
+ /// Gets the the server's ephemeral contribution to the ECDH exchange, encoded as an octet string.
+ ///
+ public byte[] QS { get; private set; }
+
+ ///
+ /// Gets the an octet string containing the server's signature of the newly established exchange hash value.
+ ///
+ /// The signature.
+ public byte[] Signature { get; private set; }
+
+ ///
+ /// Called when type specific data need to be loaded.
+ ///
+ protected override void LoadData()
+ {
+ this.ResetReader();
+ this.KS = this.ReadBinaryString();
+ this.QS = this.ReadBinaryString();
+ this.Signature = this.ReadBinaryString();
+ }
+
+ ///
+ /// Called when type specific data need to be saved.
+ ///
+ protected override void SaveData()
+ {
+ this.WriteBinaryString(this.KS);
+ this.WriteBinaryString(this.QS);
+ this.WriteBinaryString(this.Signature);
+ }
+ }
+}
diff --git a/Renci.SshNet/Messages/Transport/KeyExchangeInitMessage.cs b/Renci.SshNet/Messages/Transport/KeyExchangeInitMessage.cs
index 7e8556c..312b3b1 100644
--- a/Renci.SshNet/Messages/Transport/KeyExchangeInitMessage.cs
+++ b/Renci.SshNet/Messages/Transport/KeyExchangeInitMessage.cs
@@ -8,7 +8,7 @@ namespace Renci.SshNet.Messages.Transport
/// Represents SSH_MSG_KEXINIT message.
///
[Message("SSH_MSG_KEXINIT", 20)]
- public class KeyExchangeInitMessage : Message,IKeyExchangedAllowed
+ public class KeyExchangeInitMessage : Message, IKeyExchangedAllowed
{
private static RNGCryptoServiceProvider _randomizer = new System.Security.Cryptography.RNGCryptoServiceProvider();
diff --git a/Renci.SshNet/Messages/Transport/NewKeysMessage.cs b/Renci.SshNet/Messages/Transport/NewKeysMessage.cs
index d5b6512..2d678c4 100644
--- a/Renci.SshNet/Messages/Transport/NewKeysMessage.cs
+++ b/Renci.SshNet/Messages/Transport/NewKeysMessage.cs
@@ -4,7 +4,7 @@
/// Represents SSH_MSG_KEXINIT message.
///
[Message("SSH_MSG_NEWKEYS", 21)]
- public class NewKeysMessage : Message,IKeyExchangedAllowed
+ public class NewKeysMessage : Message, IKeyExchangedAllowed
{
///
/// Called when type specific data need to be loaded.
diff --git a/Renci.SshNet/Messages/Transport/ServiceAcceptMessage.cs b/Renci.SshNet/Messages/Transport/ServiceAcceptMessage.cs
index d6bc98b..06e6ce6 100644
--- a/Renci.SshNet/Messages/Transport/ServiceAcceptMessage.cs
+++ b/Renci.SshNet/Messages/Transport/ServiceAcceptMessage.cs
@@ -21,7 +21,7 @@ public class ServiceAcceptMessage : Message
///
protected override void LoadData()
{
- var serviceName = this.ReadString();
+ var serviceName = this.ReadAsciiString();
switch (serviceName)
{
case "ssh-userauth":
diff --git a/Renci.SshNet/Messages/Transport/ServiceRequestMessage.cs b/Renci.SshNet/Messages/Transport/ServiceRequestMessage.cs
index 3a50bb6..a3687dc 100644
--- a/Renci.SshNet/Messages/Transport/ServiceRequestMessage.cs
+++ b/Renci.SshNet/Messages/Transport/ServiceRequestMessage.cs
@@ -41,10 +41,10 @@ protected override void SaveData()
switch (this.ServiceName)
{
case ServiceName.UserAuthentication:
- this.Write("ssh-userauth");
+ this.WriteAscii("ssh-userauth");
break;
case ServiceName.Connection:
- this.Write("ssh-connection");
+ this.WriteAscii("ssh-connection");
break;
default:
throw new NotSupportedException("Not supported service name");
diff --git a/Renci.SshNet/NetConfClient.cs b/Renci.SshNet/NetConfClient.cs
new file mode 100644
index 0000000..e859b7a
--- /dev/null
+++ b/Renci.SshNet/NetConfClient.cs
@@ -0,0 +1,221 @@
+using System;
+using System.Linq;
+using System.Collections.Generic;
+using System.IO;
+using Renci.SshNet.Sftp;
+using System.Text;
+using Renci.SshNet.Common;
+using System.Globalization;
+using System.Threading;
+using Renci.SshNet.NetConf;
+using System.Xml;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Renci.SshNet
+{
+ // TODO: Please help with documentation here, as I don't know the details, specially for the methods not documented.
+ ///
+ /// Contains operation for working with NetConf server.
+ ///
+ public partial class NetConfClient : BaseClient
+ {
+ ///
+ /// Holds SftpSession instance that used to communicate to the SFTP server
+ ///
+ private NetConfSession _netConfSession;
+
+ private bool _disposeConnectionInfo;
+
+ ///
+ /// Gets or sets the operation timeout.
+ ///
+ /// The operation timeout.
+ public TimeSpan OperationTimeout { get; set; }
+
+ #region Constructors
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The connection info.
+ /// is null.
+ public NetConfClient(ConnectionInfo connectionInfo)
+ : base(connectionInfo)
+ {
+ this.AutomaticMessageIdHandling = true;
+ this.OperationTimeout = new TimeSpan(0, 0, 0, 0, -1);
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Connection host.
+ /// Connection port.
+ /// Authentication username.
+ /// Authentication password.
+ /// is null.
+ /// is invalid, or is null or contains whitespace characters.
+ /// is not within and .
+ [SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification = "Disposed in Dispose(bool) method.")]
+ public NetConfClient(string host, int port, string username, string password)
+ : this(new PasswordConnectionInfo(host, port, username, password))
+ {
+ this._disposeConnectionInfo = true;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Connection host.
+ /// Authentication username.
+ /// Authentication password.
+ /// is null.
+ /// is invalid, or is null or contains whitespace characters.
+ public NetConfClient(string host, string username, string password)
+ : this(host, ConnectionInfo.DEFAULT_PORT, username, password)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Connection host.
+ /// Connection port.
+ /// Authentication username.
+ /// Authentication private key file(s) .
+ /// is null.
+ /// is invalid, -or- is null or contains whitespace characters.
+ /// is not within and .
+ [SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification = "Disposed in Dispose(bool) method.")]
+ public NetConfClient(string host, int port, string username, params PrivateKeyFile[] keyFiles)
+ : this(new PrivateKeyConnectionInfo(host, port, username, keyFiles))
+ {
+ this._disposeConnectionInfo = true;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Connection host.
+ /// Authentication username.
+ /// Authentication private key file(s) .
+ /// is null.
+ /// is invalid, -or- is null or contains whitespace characters.
+ public NetConfClient(string host, string username, params PrivateKeyFile[] keyFiles)
+ : this(host, ConnectionInfo.DEFAULT_PORT, username, keyFiles)
+ {
+ }
+
+ #endregion
+
+ ///
+ /// Gets NetConf server capabilities.
+ ///
+ /// Client is not connected.
+ public XmlDocument ServerCapabilities
+ {
+ get
+ {
+ return this._netConfSession.ServerCapabilities;
+ }
+ }
+
+ ///
+ /// Gets NetConf client capabilities.
+ ///
+ /// Client is not connected.
+ public XmlDocument ClientCapabilities
+ {
+ get
+ {
+ return this._netConfSession.ClientCapabilities;
+ }
+ }
+
+ ///
+ /// Gets or sets a value indicating whether [automatic message id handling].
+ ///
+ ///
+ /// true if [automatic message id handling]; otherwise, false.
+ ///
+ public bool AutomaticMessageIdHandling { get; set; }
+
+ ///
+ /// Sends the receive RPC.
+ ///
+ /// The RPC.
+ /// Reply message to RPC request
+ /// Client is not connected.
+ public XmlDocument SendReceiveRpc(XmlDocument rpc)
+ {
+ return this._netConfSession.SendReceiveRpc(rpc, this.AutomaticMessageIdHandling);
+ }
+
+ ///
+ /// Sends the receive RPC.
+ ///
+ /// The XML.
+ /// Reply message to RPC request
+ public XmlDocument SendReceiveRpc(string xml)
+ {
+ var rpc = new XmlDocument();
+ rpc.LoadXml(xml);
+ return SendReceiveRpc(rpc);
+ }
+
+ ///
+ /// Sends the close RPC.
+ ///
+ /// Reply message to closing RPC request
+ /// Client is not connected.
+ public XmlDocument SendCloseRpc()
+ {
+ XmlDocument rpc = new XmlDocument();
+
+ rpc.LoadXml("");
+
+ return this._netConfSession.SendReceiveRpc(rpc, this.AutomaticMessageIdHandling);
+ }
+
+ ///
+ /// Called when client is connected to the server.
+ ///
+ protected override void OnConnected()
+ {
+ base.OnConnected();
+
+ this._netConfSession = new NetConfSession(this.Session, this.OperationTimeout);
+
+ this._netConfSession.Connect();
+ }
+
+ ///
+ /// Called when client is disconnecting from the server.
+ ///
+ protected override void OnDisconnecting()
+ {
+ base.OnDisconnecting();
+
+ this._netConfSession.Disconnect();
+ }
+
+ ///
+ /// Releases unmanaged and - optionally - managed resources
+ ///
+ /// true to release both managed and unmanaged resources; false to release only unmanaged ResourceMessages.
+ protected override void Dispose(bool disposing)
+ {
+ if (this._netConfSession != null)
+ {
+ this._netConfSession.Dispose();
+ this._netConfSession = null;
+ }
+
+ base.Dispose(disposing);
+
+ if (this._disposeConnectionInfo)
+ ((IDisposable)this.ConnectionInfo).Dispose();
+
+ }
+ }
+}
diff --git a/Renci.SshNet/Netconf/NetConfSession.cs b/Renci.SshNet/Netconf/NetConfSession.cs
new file mode 100644
index 0000000..9e3fd7c
--- /dev/null
+++ b/Renci.SshNet/Netconf/NetConfSession.cs
@@ -0,0 +1,212 @@
+using System;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using Renci.SshNet.Channels;
+using Renci.SshNet.Common;
+using System.Diagnostics;
+using System.Collections.Generic;
+using System.Globalization;
+using Renci.SshNet.Sftp.Responses;
+using Renci.SshNet.Sftp.Requests;
+using Renci.SshNet.Sftp;
+using Renci.SshNet.Messages.Connection;
+using System.Xml;
+using System.Text.RegularExpressions;
+
+namespace Renci.SshNet.NetConf
+{
+ internal class NetConfSession : SubsystemSession
+ {
+ private StringBuilder _data = new StringBuilder();
+
+ private bool _usingFramingProtocol = false;
+
+ private const string _prompt = "]]>]]>";
+
+ private EventWaitHandle _serverCapabilitiesConfirmed = new AutoResetEvent(false);
+
+ private EventWaitHandle _rpcReplyReceived = new AutoResetEvent(false);
+
+ private StringBuilder _rpcReply = new StringBuilder();
+
+ private int _messageId = 0;
+
+ ///
+ /// Gets NetConf server capabilities.
+ ///
+ public XmlDocument ServerCapabilities { get; private set; }
+
+ ///
+ /// Gets NetConf client capabilities.
+ ///
+ public XmlDocument ClientCapabilities { get; private set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The session.
+ /// The operation timeout.
+ public NetConfSession(Session session, TimeSpan operationTimeout)
+ : base(session, "netconf", operationTimeout, Encoding.UTF8)
+ {
+ ClientCapabilities = new XmlDocument();
+ ClientCapabilities.LoadXml("" +
+ "" +
+ "" +
+ "" +
+ "urn:ietf:params:netconf:base:1.0" +
+ "" +
+ "" +
+ "");
+
+ }
+
+ public XmlDocument SendReceiveRpc(XmlDocument rpc, bool automaticMessageIdHandling)
+ {
+ this._data.Clear();
+
+ XmlNamespaceManager ns = null;
+ if (automaticMessageIdHandling)
+ {
+ _messageId++;
+ ns = new XmlNamespaceManager(rpc.NameTable);
+ ns.AddNamespace("nc", "urn:ietf:params:xml:ns:netconf:base:1.0");
+ rpc.SelectSingleNode("/nc:rpc/@message-id", ns).Value = _messageId.ToString();
+ }
+ _rpcReply = new StringBuilder();
+ _rpcReplyReceived.Reset();
+ var reply = new XmlDocument();
+ if (_usingFramingProtocol)
+ {
+ StringBuilder command = new StringBuilder(rpc.InnerXml.Length + 10);
+ command.AppendFormat("\n#{0}\n", rpc.InnerXml.Length);
+ command.Append(rpc.InnerXml);
+ command.Append("\n##\n");
+ this.SendData(Encoding.UTF8.GetBytes(command.ToString()));
+
+ this.WaitHandle(this._rpcReplyReceived, this._operationTimeout);
+ reply.LoadXml(_rpcReply.ToString());
+ }
+ else
+ {
+ this.SendData(Encoding.UTF8.GetBytes(rpc.InnerXml + _prompt));
+ this.WaitHandle(this._rpcReplyReceived, this._operationTimeout);
+ reply.LoadXml(_rpcReply.ToString());
+ }
+ if (automaticMessageIdHandling)
+ {
+ //string reply_id = rpc.SelectSingleNode("/nc:rpc-reply/@message-id", ns).Value;
+ string reply_id = rpc.SelectSingleNode("/nc:rpc/@message-id", ns).Value;
+ if (reply_id != _messageId.ToString())
+ {
+ throw new NetConfServerException("The rpc message id does not match the rpc-reply message id.");
+ }
+ }
+ return reply;
+ }
+
+ protected override void OnChannelOpen()
+ {
+ this._data.Clear();
+
+ string message = string.Format("{0}{1}", this.ClientCapabilities.InnerXml, _prompt);
+
+ this.SendData(Encoding.UTF8.GetBytes(message));
+
+ this.WaitHandle(this._serverCapabilitiesConfirmed, this._operationTimeout);
+ }
+
+ protected override void OnDataReceived(uint dataTypeCode, byte[] data)
+ {
+ string chunk = Encoding.UTF8.GetString(data);
+
+ if (this.ServerCapabilities == null) // This must be server capabilities, old protocol
+ {
+ this._data.Append(chunk);
+
+ if (!chunk.Contains(_prompt))
+ {
+ return;
+ }
+ try
+ {
+ chunk = this._data.ToString();
+ this._data.Clear();
+
+ this.ServerCapabilities = new XmlDocument();
+ this.ServerCapabilities.LoadXml(chunk.Replace(_prompt, ""));
+ }
+ catch (XmlException e)
+ {
+ throw new NetConfServerException("Server capabilities received are not well formed XML", e);
+ }
+
+ XmlNamespaceManager ns = new XmlNamespaceManager(this.ServerCapabilities.NameTable);
+
+ ns.AddNamespace("nc", "urn:ietf:params:xml:ns:netconf:base:1.0");
+
+ this._usingFramingProtocol = (this.ServerCapabilities.SelectSingleNode("/nc:hello/nc:capabilities/nc:capability[text()='urn:ietf:params:netconf:base:1.1']", ns) != null);
+
+ this._serverCapabilitiesConfirmed.Set();
+ }
+ else if (this._usingFramingProtocol)
+ {
+ int position = 0;
+
+ for (; ; )
+ {
+ Match match = Regex.Match(chunk.Substring(position), @"\n#(?\d+)\n");
+ if (!match.Success)
+ {
+ break;
+ }
+ int fractionLength = Convert.ToInt32(match.Groups["length"].Value);
+ this._rpcReply.Append(chunk, position + match.Index + match.Length, fractionLength);
+ position += match.Index + match.Length + fractionLength;
+ }
+ if (Regex.IsMatch(chunk.Substring(position), @"\n##\n"))
+ {
+ this._rpcReplyReceived.Set();
+ }
+ }
+ else // Old protocol
+ {
+ this._data.Append(chunk);
+
+ if (!chunk.Contains(_prompt))
+ {
+ return;
+ //throw new NetConfServerException("Server XML message does not end with the prompt " + _prompt);
+ }
+
+ chunk = this._data.ToString();
+ this._data.Clear();
+
+ this._rpcReply.Append(chunk.Replace(_prompt, ""));
+ this._rpcReplyReceived.Set();
+ }
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ base.Dispose(disposing);
+
+ if (disposing)
+ {
+ if (this._serverCapabilitiesConfirmed != null)
+ {
+ this._serverCapabilitiesConfirmed.Dispose();
+ this._serverCapabilitiesConfirmed = null;
+ }
+
+ if (this._rpcReplyReceived != null)
+ {
+ this._rpcReplyReceived.Dispose();
+ this._rpcReplyReceived = null;
+ }
+ }
+ }
+ }
+}
diff --git a/Renci.SshNet/NoneAuthenticationMethod.cs b/Renci.SshNet/NoneAuthenticationMethod.cs
new file mode 100644
index 0000000..2c9b858
--- /dev/null
+++ b/Renci.SshNet/NoneAuthenticationMethod.cs
@@ -0,0 +1,140 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using Renci.SshNet.Messages.Authentication;
+using Renci.SshNet.Messages;
+
+namespace Renci.SshNet
+{
+ ///
+ /// Provides functionality for "none" authentication method
+ ///
+ public class NoneAuthenticationMethod : AuthenticationMethod, IDisposable
+ {
+ private AuthenticationResult _authenticationResult = AuthenticationResult.Failure;
+
+ private EventWaitHandle _authenticationCompleted = new AutoResetEvent(false);
+
+ ///
+ /// Gets connection name
+ ///
+ public override string Name
+ {
+ get { return "none"; }
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The username.
+ /// is whitespace or null.
+ public NoneAuthenticationMethod(string username)
+ : base(username)
+ {
+
+ }
+
+ ///
+ /// Authenticates the specified session.
+ ///
+ /// The session.
+ ///
+ /// Result of authentication process.
+ ///
+ /// is null.
+ public override AuthenticationResult Authenticate(Session session)
+ {
+ if (session == null)
+ throw new ArgumentNullException("session");
+
+ session.UserAuthenticationSuccessReceived += Session_UserAuthenticationSuccessReceived;
+ session.UserAuthenticationFailureReceived += Session_UserAuthenticationFailureReceived;
+
+ session.SendMessage(new RequestMessageNone(ServiceName.Connection, this.Username));
+
+ session.WaitHandle(this._authenticationCompleted);
+
+ session.UserAuthenticationSuccessReceived -= Session_UserAuthenticationSuccessReceived;
+ session.UserAuthenticationFailureReceived -= Session_UserAuthenticationFailureReceived;
+
+ return this._authenticationResult;
+ }
+
+ private void Session_UserAuthenticationSuccessReceived(object sender, MessageEventArgs e)
+ {
+ this._authenticationResult = AuthenticationResult.Success;
+
+ this._authenticationCompleted.Set();
+ }
+
+ private void Session_UserAuthenticationFailureReceived(object sender, MessageEventArgs e)
+ {
+ if (e.Message.PartialSuccess)
+ this._authenticationResult = AuthenticationResult.PartialSuccess;
+ else
+ this._authenticationResult = AuthenticationResult.Failure;
+
+ // Copy allowed authentication methods
+ this.AllowedAuthentications = e.Message.AllowedAuthentications.ToList();
+
+ this._authenticationCompleted.Set();
+ }
+
+ #region IDisposable Members
+
+ private bool isDisposed = false;
+
+ ///
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Releases unmanaged and - optionally - managed resources
+ ///
+ /// true to release both managed and unmanaged resources; false to release only unmanaged resources.
+ 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 resources.
+ if (disposing)
+ {
+ // Dispose managed resources.
+ if (this._authenticationCompleted != null)
+ {
+ this._authenticationCompleted.Dispose();
+ this._authenticationCompleted = null;
+ }
+ }
+
+ // Note disposing has been done.
+ isDisposed = true;
+ }
+ }
+
+ ///
+ /// Releases unmanaged resources and performs other cleanup operations before the
+ /// is reclaimed by garbage collection.
+ ///
+ ~NoneAuthenticationMethod()
+ {
+ // Do not re-create Dispose clean-up code here.
+ // Calling Dispose(false) is optimal in terms of
+ // readability and maintainability.
+ Dispose(false);
+ }
+
+ #endregion
+
+ }
+}
diff --git a/Renci.SshNet/NoneConnectionInfo.cs b/Renci.SshNet/NoneConnectionInfo.cs
index 0b8b5bc..efd8420 100644
--- a/Renci.SshNet/NoneConnectionInfo.cs
+++ b/Renci.SshNet/NoneConnectionInfo.cs
@@ -30,25 +30,114 @@ public override string Name
return "none";
}
}
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The host.
+ /// The username.
+ public NoneConnectionInfo(string host, string username)
+ : this(host, 22, username, ProxyTypes.None, string.Empty, 0, string.Empty, string.Empty)
+ {
+
+ }
+
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
+ ///
+ /// The host.
+ /// The port.
+ /// The username.
+ public NoneConnectionInfo(string host, int port, string username)
+ : this(host, port, username, ProxyTypes.None, string.Empty, 0, string.Empty, string.Empty)
+ {
+
+ }
+
+ ///
+ /// Initializes a new instance of the class.
///
/// Connection host.
+ /// Connection port.
/// Connection username.
- public NoneConnectionInfo(string host, string username)
- : this(host, 22, username)
+ /// Type of the proxy.
+ /// The proxy host.
+ /// The proxy port.
+ public NoneConnectionInfo(string host, int port, string username, ProxyTypes proxyType, string proxyHost, int proxyPort)
+ : this(host, port, username, proxyType, proxyHost, proxyPort, string.Empty, string.Empty)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Connection host.
+ /// Connection port.
+ /// Connection username.
+ /// Type of the proxy.
+ /// The proxy host.
+ /// The proxy port.
+ /// The proxy username.
+ public NoneConnectionInfo(string host, int port, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername)
+ : this(host, port, username, proxyType, proxyHost, proxyPort, proxyUsername, string.Empty)
{
+ }
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Connection host.
+ /// Connection username.
+ /// Type of the proxy.
+ /// The proxy host.
+ /// The proxy port.
+ public NoneConnectionInfo(string host, string username, ProxyTypes proxyType, string proxyHost, int proxyPort)
+ : this(host, 22, username, proxyType, proxyHost, proxyPort, string.Empty, string.Empty)
+ {
}
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
+ ///
+ /// Connection host.
+ /// Connection username.
+ /// Type of the proxy.
+ /// The proxy host.
+ /// The proxy port.
+ /// The proxy username.
+ public NoneConnectionInfo(string host, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername)
+ : this(host, 22, username, proxyType, proxyHost, proxyPort, proxyUsername, string.Empty)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Connection host.
+ /// Connection username.
+ /// Type of the proxy.
+ /// The proxy host.
+ /// The proxy port.
+ /// The proxy username.
+ /// The proxy password.
+ public NoneConnectionInfo(string host, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, string proxyPassword)
+ : this(host, 22, username, proxyType, proxyHost, proxyPort, proxyUsername, proxyPassword)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
///
/// Connection host.
/// Connection port.
/// Connection username.
- public NoneConnectionInfo(string host, int port, string username)
- : base(host, port, username)
+ /// Type of the proxy.
+ /// The proxy host.
+ /// The proxy port.
+ /// The proxy username.
+ /// The proxy password.
+ public NoneConnectionInfo(string host, int port, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, string proxyPassword)
+ : base(host, port, username, proxyType, proxyHost, proxyPort, proxyUsername, proxyPassword)
{
}
diff --git a/Renci.SshNet/PasswordAuthenticationMethod.NET40.cs b/Renci.SshNet/PasswordAuthenticationMethod.NET40.cs
new file mode 100644
index 0000000..c5b3d5f
--- /dev/null
+++ b/Renci.SshNet/PasswordAuthenticationMethod.NET40.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using Renci.SshNet.Common;
+using Renci.SshNet.Messages.Authentication;
+using Renci.SshNet.Messages;
+using System.Threading.Tasks;
+
+namespace Renci.SshNet
+{
+ public partial class PasswordAuthenticationMethod : AuthenticationMethod
+ {
+ /// is null.
+ partial void ExecuteThread(Action action)
+ {
+ ThreadPool.QueueUserWorkItem((o) => { action(); });
+ }
+ }
+}
diff --git a/Renci.SshNet/PasswordAuthenticationMethod.cs b/Renci.SshNet/PasswordAuthenticationMethod.cs
new file mode 100644
index 0000000..5c77057
--- /dev/null
+++ b/Renci.SshNet/PasswordAuthenticationMethod.cs
@@ -0,0 +1,217 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using Renci.SshNet.Common;
+using Renci.SshNet.Messages.Authentication;
+using Renci.SshNet.Messages;
+
+namespace Renci.SshNet
+{
+ ///
+ /// Provides functionality to perform password authentication.
+ ///
+ public partial class PasswordAuthenticationMethod : AuthenticationMethod, IDisposable
+ {
+ private AuthenticationResult _authenticationResult = AuthenticationResult.Failure;
+
+ private Session _session;
+
+ private EventWaitHandle _authenticationCompleted = new AutoResetEvent(false);
+
+ private Exception _exception;
+
+ private RequestMessage _requestMessage;
+
+ private byte[] _password;
+
+ ///
+ /// Gets authentication method name
+ ///
+ public override string Name
+ {
+ get { return this._requestMessage.MethodName; }
+ }
+
+ ///
+ /// Occurs when user's password has expired and needs to be changed.
+ ///
+ public event EventHandler PasswordExpired;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The username.
+ /// The password.
+ /// is whitespace or null.
+ /// is null.
+ public PasswordAuthenticationMethod(string username, string password)
+ : this(username, Encoding.UTF8.GetBytes(password))
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The username.
+ /// The password.
+ /// is whitespace or null.
+ /// is null.
+ public PasswordAuthenticationMethod(string username, byte[] password)
+ : base(username)
+ {
+ if (password == null)
+ throw new ArgumentNullException("password");
+
+ this._password = password;
+
+ this._requestMessage = new RequestMessagePassword(ServiceName.Connection, this.Username, this._password);
+ }
+
+ ///
+ /// Authenticates the specified session.
+ ///
+ /// The session to authenticate.
+ ///
+ /// Result of authentication process.
+ ///
+ /// is null.
+ public override AuthenticationResult Authenticate(Session session)
+ {
+ if (session == null)
+ throw new ArgumentNullException("session");
+
+ this._session = session;
+
+ session.UserAuthenticationSuccessReceived += Session_UserAuthenticationSuccessReceived;
+ session.UserAuthenticationFailureReceived += Session_UserAuthenticationFailureReceived;
+ session.MessageReceived += Session_MessageReceived;
+
+ session.RegisterMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
+
+ session.SendMessage(this._requestMessage);
+
+ session.WaitHandle(this._authenticationCompleted);
+
+ session.UserAuthenticationSuccessReceived -= Session_UserAuthenticationSuccessReceived;
+ session.UserAuthenticationFailureReceived -= Session_UserAuthenticationFailureReceived;
+ session.MessageReceived -= Session_MessageReceived;
+
+
+ if (this._exception != null)
+ {
+ throw this._exception;
+ }
+
+ return this._authenticationResult;
+ }
+
+ private void Session_UserAuthenticationSuccessReceived(object sender, MessageEventArgs e)
+ {
+ this._authenticationResult = AuthenticationResult.Success;
+
+ this._authenticationCompleted.Set();
+ }
+
+ private void Session_UserAuthenticationFailureReceived(object sender, MessageEventArgs e)
+ {
+ if (e.Message.PartialSuccess)
+ this._authenticationResult = AuthenticationResult.PartialSuccess;
+ else
+ this._authenticationResult = AuthenticationResult.Failure;
+
+ // Copy allowed authentication methods
+ this.AllowedAuthentications = e.Message.AllowedAuthentications.ToList();
+
+ this._authenticationCompleted.Set();
+ }
+
+ private void Session_MessageReceived(object sender, MessageEventArgs e)
+ {
+ if (e.Message is PasswordChangeRequiredMessage)
+ {
+ this._session.UnRegisterMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
+
+ this.ExecuteThread(() =>
+ {
+ try
+ {
+ var eventArgs = new AuthenticationPasswordChangeEventArgs(this.Username);
+
+ // Raise an event to allow user to supply a new password
+ if (this.PasswordExpired != null)
+ {
+ this.PasswordExpired(this, eventArgs);
+ }
+
+ // Send new authentication request with new password
+ this._session.SendMessage(new RequestMessagePassword(ServiceName.Connection, this.Username, this._password, eventArgs.NewPassword));
+ }
+ catch (Exception exp)
+ {
+ this._exception = exp;
+ this._authenticationCompleted.Set();
+ }
+ });
+ }
+ }
+
+ partial void ExecuteThread(Action action);
+
+ #region IDisposable Members
+
+ private bool isDisposed = false;
+
+ ///
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Releases unmanaged and - optionally - managed resources
+ ///
+ /// true to release both managed and unmanaged resources; false to release only unmanaged resources.
+ 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 resources.
+ if (disposing)
+ {
+ // Dispose managed resources.
+ if (this._authenticationCompleted != null)
+ {
+ this._authenticationCompleted.Dispose();
+ this._authenticationCompleted = null;
+ }
+ }
+
+ // Note disposing has been done.
+ isDisposed = true;
+ }
+ }
+
+ ///
+ /// Releases unmanaged resources and performs other cleanup operations before the
+ /// is reclaimed by garbage collection.
+ ///
+ ~PasswordAuthenticationMethod()
+ {
+ // Do not re-create Dispose clean-up code here.
+ // Calling Dispose(false) is optimal in terms of
+ // readability and maintainability.
+ Dispose(false);
+ }
+
+ #endregion
+
+ }
+}
diff --git a/Renci.SshNet/PasswordConnectionInfo.cs b/Renci.SshNet/PasswordConnectionInfo.cs
index e174825..15dc40c 100644
--- a/Renci.SshNet/PasswordConnectionInfo.cs
+++ b/Renci.SshNet/PasswordConnectionInfo.cs
@@ -2,50 +2,42 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
-using System.Threading;
-using Renci.SshNet.Messages.Authentication;
using Renci.SshNet.Common;
-using Renci.SshNet.Messages;
namespace Renci.SshNet
{
///
/// Provides connection information when password authentication method is used
///
- public partial class PasswordConnectionInfo : ConnectionInfo, IDisposable
+ ///
+ ///
+ ///
+ ///
+ ///
+ public class PasswordConnectionInfo : ConnectionInfo, IDisposable
{
- private EventWaitHandle _authenticationCompleted = new AutoResetEvent(false);
-
- private Exception _exception;
-
- private RequestMessage _requestMessage;
-
- private string _password;
-
- ///
- /// Gets connection name
- ///
- public override string Name
- {
- get
- {
- return this._requestMessage.MethodName;
- }
- }
-
///
/// Occurs when user's password has expired and needs to be changed.
///
+ ///
+ ///
+ ///
public event EventHandler PasswordExpired;
///
- /// Initializes a new instance of the class.
+ /// Initializes a new instance of the class.
///
/// Connection host.
/// Connection username.
/// Connection password.
+ ///
+ ///
+ ///
+ /// is null.
+ /// is invalid, or is null or contains whitespace characters.
+ /// is not within and .
public PasswordConnectionInfo(string host, string username, string password)
- : this(host, 22, username, password)
+ : this(host, ConnectionInfo.DEFAULT_PORT, username, Encoding.UTF8.GetBytes(password))
{
}
@@ -59,94 +51,219 @@ public PasswordConnectionInfo(string host, string username, string password)
/// Connection password.
/// is null.
/// is invalid, or is null or contains whitespace characters.
- /// is not within and .
+ /// is not within and .
public PasswordConnectionInfo(string host, int port, string username, string password)
- : base(host, port, username)
+ : this(host, port, username, Encoding.UTF8.GetBytes(password), ProxyTypes.None, string.Empty, 0, string.Empty, string.Empty)
{
- if (password == null)
- throw new ArgumentNullException("password");
+ }
- this._password = password;
- this._requestMessage = new RequestMessagePassword(ServiceName.Connection, this.Username, password);
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Connection host.
+ /// The port.
+ /// Connection username.
+ /// Connection password.
+ /// Type of the proxy.
+ /// The proxy host.
+ /// The proxy port.
+ public PasswordConnectionInfo(string host, int port, string username, string password, ProxyTypes proxyType, string proxyHost, int proxyPort)
+ : this(host, port, username, Encoding.UTF8.GetBytes(password), proxyType, proxyHost, proxyPort, string.Empty, string.Empty)
+ {
}
///
- /// Called when connection needs to be authenticated.
+ /// Initializes a new instance of the class.
///
- protected override void OnAuthenticate()
+ /// Connection host.
+ /// The port.
+ /// Connection username.
+ /// Connection password.
+ /// Type of the proxy.
+ /// The proxy host.
+ /// The proxy port.
+ /// The proxy username.
+ public PasswordConnectionInfo(string host, int port, string username, string password, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername)
+ : this(host, port, username, Encoding.UTF8.GetBytes(password), proxyType, proxyHost, proxyPort, proxyUsername, string.Empty)
{
- this.Session.RegisterMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
+ }
- this.SendMessage(this._requestMessage);
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Connection host.
+ /// Connection username.
+ /// Connection password.
+ /// Type of the proxy.
+ /// The proxy host.
+ /// The proxy port.
+ public PasswordConnectionInfo(string host, string username, string password, ProxyTypes proxyType, string proxyHost, int proxyPort)
+ : this(host, ConnectionInfo.DEFAULT_PORT, username, Encoding.UTF8.GetBytes(password), proxyType, proxyHost, proxyPort, string.Empty, string.Empty)
+ {
+ }
- this.WaitHandle(this._authenticationCompleted);
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Connection host.
+ /// Connection username.
+ /// Connection password.
+ /// Type of the proxy.
+ /// The proxy host.
+ /// The proxy port.
+ /// The proxy username.
+ public PasswordConnectionInfo(string host, string username, string password, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername)
+ : this(host, ConnectionInfo.DEFAULT_PORT, username, Encoding.UTF8.GetBytes(password), proxyType, proxyHost, proxyPort, proxyUsername, string.Empty)
+ {
+ }
- if (this._exception != null)
- {
- throw this._exception;
- }
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Connection host.
+ /// Connection username.
+ /// Connection password.
+ /// Type of the proxy.
+ /// The proxy host.
+ /// The proxy port.
+ /// The proxy username.
+ /// The proxy password.
+ public PasswordConnectionInfo(string host, string username, string password, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, string proxyPassword)
+ : this(host, ConnectionInfo.DEFAULT_PORT, username, Encoding.UTF8.GetBytes(password), proxyType, proxyHost, proxyPort, proxyUsername, proxyPassword)
+ {
}
///
- /// Handles the UserAuthenticationSuccessMessageReceived event of the session.
+ /// Initializes a new instance of the class.
///
- /// The source of the event.
- /// The event data.
- protected override void Session_UserAuthenticationSuccessMessageReceived(object sender, MessageEventArgs e)
+ /// Connection host.
+ /// Connection username.
+ /// Connection password.
+ public PasswordConnectionInfo(string host, string username, byte[] password)
+ : this(host, ConnectionInfo.DEFAULT_PORT, username, password)
{
- base.Session_UserAuthenticationSuccessMessageReceived(sender, e);
- this._authenticationCompleted.Set();
+
}
///
- /// Handles the UserAuthenticationFailureReceived event of the session.
+ /// Initializes a new instance of the class.
///
- /// The source of the event.
- /// The event data.
- protected override void Session_UserAuthenticationFailureReceived(object sender, MessageEventArgs e)
+ /// Connection host.
+ /// Connection port.
+ /// Connection username.
+ /// Connection password.
+ /// is null.
+ /// is invalid, or is null or contains whitespace characters.
+ /// is not within and .
+ public PasswordConnectionInfo(string host, int port, string username, byte[] password)
+ : this(host, port, username, password, ProxyTypes.None, string.Empty, 0, string.Empty, string.Empty)
{
- base.Session_UserAuthenticationFailureReceived(sender, e);
- this._authenticationCompleted.Set();
}
///
- /// Handles the MessageReceived event of the session.
+ /// Initializes a new instance of the class.
///
- /// The source of the event.
- /// The event data.
- protected override void Session_MessageReceived(object sender, MessageEventArgs e)
+ /// Connection host.
+ /// The port.
+ /// Connection username.
+ /// Connection password.
+ /// Type of the proxy.
+ /// The proxy host.
+ /// The proxy port.
+ public PasswordConnectionInfo(string host, int port, string username, byte[] password, ProxyTypes proxyType, string proxyHost, int proxyPort)
+ : this(host, port, username, password, proxyType, proxyHost, proxyPort, string.Empty, string.Empty)
{
- base.Session_MessageReceived(sender, e);
+ }
- if (e.Message is PasswordChangeRequiredMessage)
- {
- this.Session.UnRegisterMessage("SSH_MSG_USERAUTH_PASSWD_CHANGEREQ");
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Connection host.
+ /// The port.
+ /// Connection username.
+ /// Connection password.
+ /// Type of the proxy.
+ /// The proxy host.
+ /// The proxy port.
+ /// The proxy username.
+ public PasswordConnectionInfo(string host, int port, string username, byte[] password, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername)
+ : this(host, port, username, password, proxyType, proxyHost, proxyPort, proxyUsername, string.Empty)
+ {
+ }
- this.ExecuteThread(() =>
- {
- try
- {
- var eventArgs = new AuthenticationPasswordChangeEventArgs(this.Username);
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Connection host.
+ /// Connection username.
+ /// Connection password.
+ /// Type of the proxy.
+ /// The proxy host.
+ /// The proxy port.
+ public PasswordConnectionInfo(string host, string username, byte[] password, ProxyTypes proxyType, string proxyHost, int proxyPort)
+ : this(host, ConnectionInfo.DEFAULT_PORT, username, password, proxyType, proxyHost, proxyPort, string.Empty, string.Empty)
+ {
+ }
- // Raise an event to allow user to supply a new password
- if (this.PasswordExpired != null)
- {
- this.PasswordExpired(this, eventArgs);
- }
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Connection host.
+ /// Connection username.
+ /// Connection password.
+ /// Type of the proxy.
+ /// The proxy host.
+ /// The proxy port.
+ /// The proxy username.
+ public PasswordConnectionInfo(string host, string username, byte[] password, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername)
+ : this(host, ConnectionInfo.DEFAULT_PORT, username, password, proxyType, proxyHost, proxyPort, proxyUsername, string.Empty)
+ {
+ }
- // Send new authentication request with new password
- this.SendMessage(new RequestMessagePassword(ServiceName.Connection, this.Username, this._password, eventArgs.NewPassword));
- }
- catch (Exception exp)
- {
- this._exception = exp;
- this._authenticationCompleted.Set();
- }
- });
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Connection host.
+ /// Connection username.
+ /// Connection password.
+ /// Type of the proxy.
+ /// The proxy host.
+ /// The proxy port.
+ /// The proxy username.
+ /// The proxy password.
+ public PasswordConnectionInfo(string host, string username, byte[] password, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, string proxyPassword)
+ : this(host, ConnectionInfo.DEFAULT_PORT, username, password, proxyType, proxyHost, proxyPort, proxyUsername, proxyPassword)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Connection host.
+ /// The port.
+ /// Connection username.
+ /// Connection password.
+ /// Type of the proxy.
+ /// The proxy host.
+ /// The proxy port.
+ /// The proxy username.
+ /// The proxy password.
+ public PasswordConnectionInfo(string host, int port, string username, byte[] password, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, string proxyPassword)
+ : base(host, port, username, proxyType, proxyHost, proxyPort, proxyUsername, proxyPassword, new PasswordAuthenticationMethod(username, password))
+ {
+ foreach (var authenticationMethod in this.AuthenticationMethods.OfType())
+ {
+ authenticationMethod.PasswordExpired += AuthenticationMethod_PasswordExpired;
}
}
- partial void ExecuteThread(Action action);
+ private void AuthenticationMethod_PasswordExpired(object sender, AuthenticationPasswordChangeEventArgs e)
+ {
+ if (this.PasswordExpired != null)
+ {
+ this.PasswordExpired(sender, e);
+ }
+ }
#region IDisposable Members
@@ -176,10 +293,12 @@ protected virtual void Dispose(bool disposing)
if (disposing)
{
// Dispose managed resources.
- if (this._authenticationCompleted != null)
+ if (this.AuthenticationMethods != null)
{
- this._authenticationCompleted.Dispose();
- this._authenticationCompleted = null;
+ foreach (var authenticationMethods in this.AuthenticationMethods.OfType())
+ {
+ authenticationMethods.Dispose();
+ }
}
}
diff --git a/Renci.SshNet/PrivateKeyAuthenticationMethod.cs b/Renci.SshNet/PrivateKeyAuthenticationMethod.cs
new file mode 100644
index 0000000..589409e
--- /dev/null
+++ b/Renci.SshNet/PrivateKeyAuthenticationMethod.cs
@@ -0,0 +1,232 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Collections.ObjectModel;
+using Renci.SshNet.Messages.Authentication;
+using Renci.SshNet.Messages;
+using Renci.SshNet.Common;
+using System.Threading;
+
+namespace Renci.SshNet
+{
+ ///
+ /// Provides functionality to perform private key authentication.
+ ///
+ public class PrivateKeyAuthenticationMethod : AuthenticationMethod, IDisposable
+ {
+ private AuthenticationResult _authenticationResult = AuthenticationResult.Failure;
+
+ private EventWaitHandle _authenticationCompleted = new ManualResetEvent(false);
+
+ private bool _isSignatureRequired;
+
+ ///
+ /// Gets authentication method name
+ ///
+ public override string Name
+ {
+ get { return "publickey"; }
+ }
+
+ ///
+ /// Gets the key files used for authentication.
+ ///
+ public ICollection KeyFiles { get; private set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The username.
+ /// The key files.
+ /// is whitespace or null.
+ public PrivateKeyAuthenticationMethod(string username, params PrivateKeyFile[] keyFiles)
+ : base(username)
+ {
+ if (keyFiles == null)
+ throw new ArgumentNullException("keyFiles");
+
+ this.KeyFiles = new Collection(keyFiles);
+ }
+
+ ///
+ /// Authenticates the specified session.
+ ///
+ /// The session to authenticate.
+ ///
+ /// Result of authentication process.
+ ///
+ public override AuthenticationResult Authenticate(Session session)
+ {
+ session.UserAuthenticationSuccessReceived += Session_UserAuthenticationSuccessReceived;
+ session.UserAuthenticationFailureReceived += Session_UserAuthenticationFailureReceived;
+ session.MessageReceived += Session_MessageReceived;
+
+ session.RegisterMessage("SSH_MSG_USERAUTH_PK_OK");
+
+ foreach (var keyFile in this.KeyFiles)
+ {
+ this._authenticationCompleted.Reset();
+ this._isSignatureRequired = false;
+
+ var message = new RequestMessagePublicKey(ServiceName.Connection, this.Username, keyFile.HostKey.Name, keyFile.HostKey.Data);
+
+ if (this.KeyFiles.Count < 2)
+ {
+ // If only one key file provided then send signature for very first request
+ var signatureData = new SignatureData(message, session.SessionId).GetBytes();
+
+ message.Signature = keyFile.HostKey.Sign(signatureData);
+ }
+
+ // Send public key authentication request
+ session.SendMessage(message);
+
+ session.WaitHandle(this._authenticationCompleted);
+
+ if (this._isSignatureRequired)
+ {
+ this._authenticationCompleted.Reset();
+
+ var signatureMessage = new RequestMessagePublicKey(ServiceName.Connection, this.Username, keyFile.HostKey.Name, keyFile.HostKey.Data);
+
+ var signatureData = new SignatureData(message, session.SessionId).GetBytes();
+
+ signatureMessage.Signature = keyFile.HostKey.Sign(signatureData);
+
+ // Send public key authentication request with signature
+ session.SendMessage(signatureMessage);
+ }
+
+ session.WaitHandle(this._authenticationCompleted);
+
+ if (this._authenticationResult == AuthenticationResult.Success)
+ {
+ break;
+ }
+ }
+
+ session.UserAuthenticationSuccessReceived -= Session_UserAuthenticationSuccessReceived;
+ session.UserAuthenticationFailureReceived -= Session_UserAuthenticationFailureReceived;
+ session.MessageReceived -= Session_MessageReceived;
+
+ session.UnRegisterMessage("SSH_MSG_USERAUTH_PK_OK");
+
+ return this._authenticationResult;
+ }
+
+ private void Session_UserAuthenticationSuccessReceived(object sender, MessageEventArgs e)
+ {
+ this._authenticationResult = AuthenticationResult.Success;
+
+ this._authenticationCompleted.Set();
+ }
+
+ private void Session_UserAuthenticationFailureReceived(object sender, MessageEventArgs e)
+ {
+ if (e.Message.PartialSuccess)
+ this._authenticationResult = AuthenticationResult.PartialSuccess;
+ else
+ this._authenticationResult = AuthenticationResult.Failure;
+
+ // Copy allowed authentication methods
+ this.AllowedAuthentications = e.Message.AllowedAuthentications.ToList();
+
+ this._authenticationCompleted.Set();
+ }
+
+ private void Session_MessageReceived(object sender, MessageEventArgs e)
+ {
+ var publicKeyMessage = e.Message as PublicKeyMessage;
+ if (publicKeyMessage != null)
+ {
+ this._isSignatureRequired = true;
+ this._authenticationCompleted.Set();
+ }
+ }
+
+ #region IDisposable Members
+
+ private bool isDisposed = false;
+
+ ///
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Releases unmanaged and - optionally - managed resources
+ ///
+ /// true to release both managed and unmanaged resources; false to release only unmanaged resources.
+ 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 resources.
+ if (disposing)
+ {
+ // Dispose managed resources.
+ if (this._authenticationCompleted != null)
+ {
+ this._authenticationCompleted.Dispose();
+ this._authenticationCompleted = null;
+ }
+ }
+
+ // Note disposing has been done.
+ isDisposed = true;
+ }
+ }
+
+ ///
+ /// Releases unmanaged resources and performs other cleanup operations before the
+ /// is reclaimed by garbage collection.
+ ///
+ ~PrivateKeyAuthenticationMethod()
+ {
+ // Do not re-create Dispose clean-up code here.
+ // Calling Dispose(false) is optimal in terms of
+ // readability and maintainability.
+ Dispose(false);
+ }
+
+ #endregion
+
+ private class SignatureData : SshData
+ {
+ private RequestMessagePublicKey _message;
+
+ private byte[] _sessionId;
+
+ public SignatureData(RequestMessagePublicKey message, byte[] sessionId)
+ {
+ this._message = message;
+ this._sessionId = sessionId;
+ }
+
+ protected override void LoadData()
+ {
+ throw new System.NotImplementedException();
+ }
+
+ protected override void SaveData()
+ {
+ this.WriteBinaryString(this._sessionId);
+ this.Write((byte)50);
+ this.Write(this._message.Username);
+ this.WriteAscii("ssh-connection");
+ this.WriteAscii("publickey");
+ this.Write((byte)1);
+ this.WriteAscii(this._message.PublicKeyAlgorithmName);
+ this.WriteBinaryString(this._message.PublicKeyData);
+ }
+ }
+
+ }
+}
diff --git a/Renci.SshNet/PrivateKeyConnectionInfo.cs b/Renci.SshNet/PrivateKeyConnectionInfo.cs
index 0a1d727..008e974 100644
--- a/Renci.SshNet/PrivateKeyConnectionInfo.cs
+++ b/Renci.SshNet/PrivateKeyConnectionInfo.cs
@@ -3,33 +3,17 @@
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
-using System.Threading;
-using Renci.SshNet.Messages.Authentication;
-using Renci.SshNet.Messages;
-using Renci.SshNet.Common;
namespace Renci.SshNet
{
///
/// Provides connection information when private key authentication method is used
///
+ ///
+ ///
+ ///
public class PrivateKeyConnectionInfo : ConnectionInfo, IDisposable
{
- private EventWaitHandle _publicKeyRequestMessageResponseWaitHandle = new ManualResetEvent(false);
-
- private bool _isSignatureRequired;
-
- ///
- /// Gets connection name
- ///
- public override string Name
- {
- get
- {
- return "publickey";
- }
- }
-
///
/// Gets the key files used for authentication.
///
@@ -41,8 +25,12 @@ public override string Name
/// Connection host.
/// Connection username.
/// Connection key files.
+ ///
+ ///
+ ///
+ ///
public PrivateKeyConnectionInfo(string host, string username, params PrivateKeyFile[] keyFiles)
- : this(host, 22, username, keyFiles)
+ : this(host, ConnectionInfo.DEFAULT_PORT, username, ProxyTypes.None, string.Empty, 0, string.Empty, string.Empty, keyFiles)
{
}
@@ -55,139 +43,107 @@ public PrivateKeyConnectionInfo(string host, string username, params PrivateKeyF
/// Connection username.
/// Connection key files.
public PrivateKeyConnectionInfo(string host, int port, string username, params PrivateKeyFile[] keyFiles)
- : base(host, port, username)
+ : this(host, port, username, ProxyTypes.None, string.Empty, 0, string.Empty, string.Empty, keyFiles)
{
- this.KeyFiles = new Collection(keyFiles);
}
///
- /// Called when connection needs to be authenticated.
+ /// Initializes a new instance of the class.
///
- protected override void OnAuthenticate()
+ /// Connection host.
+ /// The port.
+ /// Connection username.
+ /// Type of the proxy.
+ /// The proxy host.
+ /// The proxy port.
+ /// The key files.
+ public PrivateKeyConnectionInfo(string host, int port, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, params PrivateKeyFile[] keyFiles)
+ : this(host, port, username, proxyType, proxyHost, proxyPort, string.Empty, string.Empty, keyFiles)
{
- if (this.KeyFiles == null)
- return;
-
- this.Session.RegisterMessage("SSH_MSG_USERAUTH_PK_OK");
-
- foreach (var keyFile in this.KeyFiles)
- {
- this._publicKeyRequestMessageResponseWaitHandle.Reset();
- this._isSignatureRequired = false;
-
- var message = new RequestMessagePublicKey(ServiceName.Connection, this.Username, keyFile.HostKey.Name, keyFile.HostKey.Data);
-
- if (this.KeyFiles.Count < 2)
- {
- // If only one key file provided then send signature for very first request
- var signatureData = new SignatureData(message, this.Session.SessionId).GetBytes();
-
- message.Signature = keyFile.HostKey.Sign(signatureData);
- }
-
- // Send public key authentication request
- this.SendMessage(message);
-
- this.WaitHandle(this._publicKeyRequestMessageResponseWaitHandle);
-
- if (this._isSignatureRequired)
- {
- this._publicKeyRequestMessageResponseWaitHandle.Reset();
-
- var signatureMessage = new RequestMessagePublicKey(ServiceName.Connection, this.Username, keyFile.HostKey.Name, keyFile.HostKey.Data);
-
- var signatureData = new SignatureData(message, this.Session.SessionId).GetBytes();
-
- signatureMessage.Signature = keyFile.HostKey.Sign(signatureData);
-
- // Send public key authentication request with signature
- this.SendMessage(signatureMessage);
- }
-
- this.WaitHandle(this._publicKeyRequestMessageResponseWaitHandle);
-
- if (this.IsAuthenticated)
- {
- break;
- }
- }
-
- this.Session.UnRegisterMessage("SSH_MSG_USERAUTH_PK_OK");
}
///
- /// Handles the UserAuthenticationSuccessMessageReceived event of the session.
+ /// Initializes a new instance of the class.
///
- /// The source of the event.
- /// The event data.
- protected override void Session_UserAuthenticationSuccessMessageReceived(object sender, MessageEventArgs e)
+ /// Connection host.
+ /// The port.
+ /// Connection username.
+ /// Type of the proxy.
+ /// The proxy host.
+ /// The proxy port.
+ /// The proxy username.
+ /// The key files.
+ public PrivateKeyConnectionInfo(string host, int port, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, params PrivateKeyFile[] keyFiles)
+ : this(host, port, username, proxyType, proxyHost, proxyPort, proxyUsername, string.Empty, keyFiles)
{
- base.Session_UserAuthenticationSuccessMessageReceived(sender, e);
-
- this._publicKeyRequestMessageResponseWaitHandle.Set();
}
///
- /// Handles the UserAuthenticationFailureReceived event of the session.
+ /// Initializes a new instance of the class.
///
- /// The source of the event.
- /// The event data.
- protected override void Session_UserAuthenticationFailureReceived(object sender, MessageEventArgs e)
+ /// Connection host.
+ /// Connection username.
+ /// Type of the proxy.
+ /// The proxy host.
+ /// The proxy port.
+ /// The key files.
+ public PrivateKeyConnectionInfo(string host, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, params PrivateKeyFile[] keyFiles)
+ : this(host, ConnectionInfo.DEFAULT_PORT, username, proxyType, proxyHost, proxyPort, string.Empty, string.Empty, keyFiles)
{
- base.Session_UserAuthenticationFailureReceived(sender, e);
- this._publicKeyRequestMessageResponseWaitHandle.Set();
}
///
- /// Handles the MessageReceived event of the session.
+ /// Initializes a new instance of the class.
///
- /// The source of the event.
- /// The event data.
- protected override void Session_MessageReceived(object sender, MessageEventArgs e)
+ /// Connection host.
+ /// Connection username.
+ /// Type of the proxy.
+ /// The proxy host.
+ /// The proxy port.
+ /// The proxy username.
+ /// The key files.
+ public PrivateKeyConnectionInfo(string host, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, params PrivateKeyFile[] keyFiles)
+ : this(host, ConnectionInfo.DEFAULT_PORT, username, proxyType, proxyHost, proxyPort, proxyUsername, string.Empty, keyFiles)
{
- base.Session_MessageReceived(sender, e);
-
- var publicKeyMessage = e.Message as PublicKeyMessage;
- if (publicKeyMessage != null)
- {
- this._isSignatureRequired = true;
- this._publicKeyRequestMessageResponseWaitHandle.Set();
- }
}
- private class SignatureData : SshData
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Connection host.
+ /// Connection username.
+ /// Type of the proxy.
+ /// The proxy host.
+ /// The proxy port.
+ /// The proxy username.
+ /// The proxy password.
+ /// The key files.
+ public PrivateKeyConnectionInfo(string host, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, string proxyPassword, params PrivateKeyFile[] keyFiles)
+ : this(host, ConnectionInfo.DEFAULT_PORT, username, proxyType, proxyHost, proxyPort, proxyUsername, proxyPassword, keyFiles)
{
- private RequestMessagePublicKey _message;
-
- private byte[] _sessionId;
-
- public SignatureData(RequestMessagePublicKey message, byte[] sessionId)
- {
- this._message = message;
- this._sessionId = sessionId;
- }
-
- protected override void LoadData()
- {
- throw new System.NotImplementedException();
- }
+ }
- protected override void SaveData()
- {
- this.WriteBinaryString(this._sessionId);
- this.Write((byte)50);
- this.Write(this._message.Username);
- this.Write("ssh-connection");
- this.Write("publickey");
- this.Write((byte)1);
- this.Write(this._message.PublicKeyAlgorithmName);
- this.WriteBinaryString(this._message.PublicKeyData);
- }
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Connection host.
+ /// The port.
+ /// Connection username.
+ /// Type of the proxy.
+ /// The proxy host.
+ /// The proxy port.
+ /// The proxy username.
+ /// The proxy password.
+ /// The key files.
+ public PrivateKeyConnectionInfo(string host, int port, string username, ProxyTypes proxyType, string proxyHost, int proxyPort, string proxyUsername, string proxyPassword, params PrivateKeyFile[] keyFiles)
+ : base(host, port, username, proxyType, proxyHost, proxyPort, proxyUsername, proxyPassword, new PrivateKeyAuthenticationMethod(username, keyFiles))
+ {
+ this.KeyFiles = new Collection(keyFiles);
}
#region IDisposable Members
- private bool _isDisposed = false;
+ private bool isDisposed = false;
///
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
@@ -206,28 +162,30 @@ public void Dispose()
protected virtual void Dispose(bool disposing)
{
// Check to see if Dispose has already been called.
- if (!this._isDisposed)
+ if (!this.isDisposed)
{
// If disposing equals true, dispose all managed
// and unmanaged resources.
if (disposing)
{
// Dispose managed resources.
- if (this._publicKeyRequestMessageResponseWaitHandle != null)
+ if (this.AuthenticationMethods != null)
{
- this._publicKeyRequestMessageResponseWaitHandle.Dispose();
- this._publicKeyRequestMessageResponseWaitHandle = null;
+ foreach (var authenticationMethods in this.AuthenticationMethods.OfType())
+ {
+ authenticationMethods.Dispose();
+ }
}
}
// Note disposing has been done.
- _isDisposed = true;
+ isDisposed = true;
}
}
///
/// Releases unmanaged resources and performs other cleanup operations before the
- /// is reclaimed by garbage collection.
+ /// is reclaimed by garbage collection.
///
~PrivateKeyConnectionInfo()
{
@@ -238,6 +196,5 @@ protected virtual void Dispose(bool disposing)
}
#endregion
-
}
}
diff --git a/Renci.SshNet/PrivateKeyFile.cs b/Renci.SshNet/PrivateKeyFile.cs
index 3668c46..d18f7dc 100644
--- a/Renci.SshNet/PrivateKeyFile.cs
+++ b/Renci.SshNet/PrivateKeyFile.cs
@@ -13,34 +13,30 @@
using Renci.SshNet.Security.Cryptography.Ciphers;
using Renci.SshNet.Security.Cryptography.Ciphers.Modes;
using Renci.SshNet.Security.Cryptography.Ciphers.Paddings;
+using System.Diagnostics.CodeAnalysis;
namespace Renci.SshNet
{
///
- /// old private key information/
+ /// Represents private key information
///
- public class PrivateKeyFile
+ ///
+ ///
+ ///
+ public class PrivateKeyFile : IDisposable
{
#if SILVERLIGHT
- private static Regex _privateKeyRegex = new Regex(@"^-----BEGIN (?\w+) PRIVATE KEY-----\r?\n(Proc-Type: 4,ENCRYPTED\r?\nDEK-Info: (?[A-Z0-9-]+),(?[A-F0-9]+)\r?\n\r?\n)?(?([a-zA-Z0-9/+=]{1,64}\r?\n)+)-----END \k PRIVATE KEY-----.*", RegexOptions.Multiline);
+ private static Regex _privateKeyRegex = new Regex(@"^-+ *BEGIN (?\w+( \w+)*) PRIVATE KEY *-+\r?\n(Proc-Type: 4,ENCRYPTED\r?\nDEK-Info: (?[A-Z0-9-]+),(?[A-F0-9]+)\r?\n\r?\n)?(?([a-zA-Z0-9/+=]{1,80}\r?\n)+)-+ *END \k PRIVATE KEY *-+", RegexOptions.Multiline);
#else
- private static readonly Regex _privateKeyRegex = new Regex(@"^-----BEGIN (?\w+) PRIVATE KEY-----\r?\n(Proc-Type: 4,ENCRYPTED\r?\nDEK-Info: (?[A-Z0-9-]+),(?[A-F0-9]+)\r?\n\r?\n)?(?([a-zA-Z0-9/+=]{1,72}\r?\n)+)-----END \k PRIVATE KEY-----.*", RegexOptions.Compiled | RegexOptions.Multiline);
+ private static Regex _privateKeyRegex = new Regex(@"^-+ *BEGIN (?\w+( \w+)*) PRIVATE KEY *-+\r?\n(Proc-Type: 4,ENCRYPTED\r?\nDEK-Info: (?[A-Z0-9-]+),(?[A-F0-9]+)\r?\n\r?\n)?(?([a-zA-Z0-9/+=]{1,80}\r?\n)+)-+ *END \k PRIVATE KEY *-+", RegexOptions.Compiled | RegexOptions.Multiline);
#endif
+ private Key _key;
+
///
/// Gets the host key.
///
- public HostAlgorithm HostKey;
-
- public static bool IsValid(string privateKey)
- {
- using (var sr = new StreamReader(privateKey))
- {
- return _privateKeyRegex.Match(sr.ReadToEnd()).Success;
- }
- }
-
-
+ public HostAlgorithm HostKey { get; private set; }
///
/// Initializes a new instance of the class.
@@ -60,9 +56,9 @@ public PrivateKeyFile(Stream privateKey)
public PrivateKeyFile(string fileName)
{
if (string.IsNullOrEmpty(fileName))
- throw new ArgumentException("FileName not valid");
+ throw new ArgumentNullException("fileName");
- using (var keyFile = File.Open(fileName, FileMode.Open,FileAccess.Read,FileShare.Read))
+ using (var keyFile = File.Open(fileName, FileMode.Open))
{
this.Open(keyFile, null);
}
@@ -78,14 +74,21 @@ public PrivateKeyFile(string fileName)
public PrivateKeyFile(string fileName, string passPhrase)
{
if (string.IsNullOrEmpty(fileName))
- throw new ArgumentException("FileName not valid");
+ throw new ArgumentNullException("fileName");
- using (var keyFile = File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
+ using (var keyFile = File.Open(fileName, FileMode.Open))
{
this.Open(keyFile, passPhrase);
}
}
+ public static bool IsValid(string privateKey)
+ {
+ using (var sr = new StreamReader(privateKey))
+ {
+ return _privateKeyRegex.Match(sr.ReadToEnd()).Success;
+ }
+ }
///
/// Initializes a new instance of the class.
@@ -103,6 +106,7 @@ public PrivateKeyFile(Stream privateKey, string passPhrase)
///
/// The private key.
/// The pass phrase.
+ [SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification = "this._key disposed in Dispose(bool) method.")]
private void Open(Stream privateKey, string passPhrase)
{
if (privateKey == null)
@@ -128,7 +132,7 @@ private void Open(Stream privateKey, string passPhrase)
var binaryData = System.Convert.FromBase64String(data);
- byte[] decryptedData;
+ byte[] decryptedData = null;
if (!string.IsNullOrEmpty(cipherName) && !string.IsNullOrEmpty(salt))
{
@@ -143,24 +147,23 @@ private void Open(Stream privateKey, string passPhrase)
switch (cipherName)
{
case "DES-EDE3-CBC":
- cipher = new CipherInfo(192, (key, iv) => new TripleDesCipher(key, new CbcCipherMode(iv), new PKCS7Padding()));
+ cipher = new CipherInfo(192, (key, iv) => { return new TripleDesCipher(key, new CbcCipherMode(iv), new PKCS7Padding()); });
break;
case "DES-EDE3-CFB":
- cipher = new CipherInfo(192, (key, iv) => new TripleDesCipher(key, new CfbCipherMode(iv), new PKCS7Padding()));
+ cipher = new CipherInfo(192, (key, iv) => { return new TripleDesCipher(key, new CfbCipherMode(iv), new PKCS7Padding()); });
break;
case "DES-CBC":
- cipher = new CipherInfo(64, (key, iv) => new DesCipher(key, new CbcCipherMode(iv), new PKCS7Padding()));
+ cipher = new CipherInfo(64, (key, iv) => { return new DesCipher(key, new CbcCipherMode(iv), new PKCS7Padding()); });
+ break;
+ case "AES-128-CBC":
+ cipher = new CipherInfo(128, (key, iv) => { return new AesCipher(key, new CbcCipherMode(iv), new PKCS7Padding()); });
+ break;
+ case "AES-192-CBC":
+ cipher = new CipherInfo(192, (key, iv) => { return new AesCipher(key, new CbcCipherMode(iv), new PKCS7Padding()); });
+ break;
+ case "AES-256-CBC":
+ cipher = new CipherInfo(256, (key, iv) => { return new AesCipher(key, new CbcCipherMode(iv), new PKCS7Padding()); });
break;
- // TODO: Implement more private key ciphers
- //case "AES-128-CBC":
- // cipher = new CipherInfo(128, (key, iv) => { return new AesCipher(key, new CbcCipherMode(iv), new PKCS7Padding()); });
- // break;
- //case "AES-192-CBC":
- // cipher = new CipherInfo(192, (key, iv) => { return new AesCipher(key, new CbcCipherMode(iv), new PKCS7Padding()); });
- // break;
- //case "AES-256-CBC":
- // cipher = new CipherInfo(256, (key, iv) => { return new AesCipher(key, new CbcCipherMode(iv), new PKCS7Padding()); });
- // break;
default:
throw new SshException(string.Format(CultureInfo.CurrentCulture, "Private key cipher \"{0}\" is not supported.", cipherName));
}
@@ -175,16 +178,112 @@ private void Open(Stream privateKey, string passPhrase)
switch (keyName)
{
case "RSA":
- this.HostKey = new KeyHostAlgorithm("ssh-rsa", new RsaKey(decryptedData.ToArray()));
+ this._key = new RsaKey(decryptedData.ToArray());
+ this.HostKey = new KeyHostAlgorithm("ssh-rsa", this._key);
break;
case "DSA":
- this.HostKey = new KeyHostAlgorithm("ssh-dss", new DsaKey(decryptedData.ToArray()));
+ this._key = new DsaKey(decryptedData.ToArray());
+ this.HostKey = new KeyHostAlgorithm("ssh-dss", this._key);
+ break;
+ case "SSH2 ENCRYPTED":
+ var reader = new SshDataReader(decryptedData);
+ var magicNumber = reader.ReadUInt32();
+ if (magicNumber != 0x3f6ff9eb)
+ {
+ throw new SshException("Invalid SSH2 private key.");
+ }
+
+ var totalLength = reader.ReadUInt32(); // Read total bytes length including magic number
+ var keyType = reader.ReadString();
+ var ssh2CipherName = reader.ReadString();
+ var blobSize = (int)reader.ReadUInt32();
+
+ byte[] keyData = null;
+ if (ssh2CipherName == "none")
+ {
+ keyData = reader.ReadBytes(blobSize);
+ }
+ //else if (ssh2CipherName == "3des-cbc")
+ //{
+ // var key = GetCipherKey(passPhrase, 192 / 8);
+ // var ssh2Сipher = new TripleDesCipher(key, null, null);
+ // keyData = ssh2Сipher.Decrypt(reader.ReadBytes(blobSize));
+ //}
+ else
+ {
+ throw new SshException(string.Format("Cipher method '{0}' is not supported.", cipherName));
+ }
+
+ // TODO: Create two specific data types to avoid using SshDataReader class
+
+ reader = new SshDataReader(keyData);
+
+ var decryptedLength = reader.ReadUInt32();
+
+ if (decryptedLength + 4 != blobSize)
+ throw new SshException("Invalid passphrase.");
+
+ if (keyType == "if-modn{sign{rsa-pkcs1-sha1},encrypt{rsa-pkcs1v2-oaep}}")
+ {
+ var exponent = reader.ReadBigIntWithBits();//e
+ var d = reader.ReadBigIntWithBits();//d
+ var modulus = reader.ReadBigIntWithBits();//n
+ var inverseQ = reader.ReadBigIntWithBits();//u
+ var q = reader.ReadBigIntWithBits();//p
+ var p = reader.ReadBigIntWithBits();//q
+ this._key = new RsaKey(modulus, exponent, d, p, q, inverseQ);
+ this.HostKey = new KeyHostAlgorithm("ssh-rsa", this._key);
+ }
+ else if (keyType == "dl-modp{sign{dsa-nist-sha1},dh{plain}}")
+ {
+ var zero = reader.ReadUInt32();
+ if (zero != 0)
+ {
+ throw new SshException("Invalid private key");
+ }
+ var p = reader.ReadBigIntWithBits();
+ var g = reader.ReadBigIntWithBits();
+ var q = reader.ReadBigIntWithBits();
+ var y = reader.ReadBigIntWithBits();
+ var x = reader.ReadBigIntWithBits();
+ this._key = new DsaKey(p, q, g, y, x);
+ this.HostKey = new KeyHostAlgorithm("ssh-dss", this._key);
+ }
+ else
+ {
+ throw new NotSupportedException(string.Format("Key type '{0}' is not supported.", keyType));
+ }
break;
default:
throw new NotSupportedException(string.Format(CultureInfo.CurrentCulture, "Key '{0}' is not supported.", keyName));
}
}
+ private static byte[] GetCipherKey(string passphrase, int length)
+ {
+ List cipherKey = new List();
+
+ using (var md5 = new MD5Hash())
+ {
+ byte[] passwordBytes = Encoding.UTF8.GetBytes(passphrase);
+
+ var hash = md5.ComputeHash(passwordBytes.ToArray()).AsEnumerable();
+
+ cipherKey.AddRange(hash);
+
+ while (cipherKey.Count < length)
+ {
+ hash = passwordBytes.Concat(hash);
+
+ hash = md5.ComputeHash(hash.ToArray());
+
+ cipherKey.AddRange(hash);
+ }
+ }
+
+ return cipherKey.Take(length).ToArray();
+ }
+
///
/// Decrypts encrypted private key file data.
///
@@ -192,9 +291,10 @@ private void Open(Stream privateKey, string passPhrase)
/// Encrypted data.
/// Decryption pass phrase.
/// Decryption binary salt.
- ///
- /// , , or is null.
- public static byte[] DecryptKey(CipherInfo cipherInfo, byte[] cipherData, string passPhrase, byte[] binarySalt)
+ /// Decrypted byte array.
+ /// cipherInfo
+ /// , , or is null.
+ private static byte[] DecryptKey(CipherInfo cipherInfo, byte[] cipherData, string passPhrase, byte[] binarySalt)
{
if (cipherInfo == null)
throw new ArgumentNullException("cipherInfo");
@@ -211,7 +311,8 @@ public static byte[] DecryptKey(CipherInfo cipherInfo, byte[] cipherData, string
{
var passwordBytes = Encoding.UTF8.GetBytes(passPhrase);
- var initVector = passwordBytes.Concat(binarySalt);
+ // Use 8 bytes binary salkt
+ var initVector = passwordBytes.Concat(binarySalt.Take(8));
var hash = md5.ComputeHash(initVector.ToArray()).AsEnumerable();
@@ -231,5 +332,107 @@ public static byte[] DecryptKey(CipherInfo cipherInfo, byte[] cipherData, string
return cipher.Decrypt(cipherData);
}
+
+ #region IDisposable Members
+
+ private bool _isDisposed = false;
+
+ ///
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged ResourceMessages.
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Releases unmanaged and - optionally - managed resources
+ ///
+ /// true to release both managed and unmanaged resources; false to release only unmanaged ResourceMessages.
+ 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._key != null)
+ {
+ ((IDisposable)this._key).Dispose();
+ this._key = null;
+ }
+ }
+
+ // Note disposing has been done.
+ _isDisposed = true;
+ }
+ }
+
+ ///
+ /// Releases unmanaged resources and performs other cleanup operations before the
+ /// is reclaimed by garbage collection.
+ ///
+ ~PrivateKeyFile()
+ {
+ // Do not re-create Dispose clean-up code here.
+ // Calling Dispose(false) is optimal in terms of
+ // readability and maintainability.
+ Dispose(false);
+ }
+
+ #endregion
+
+ private class SshDataReader : SshData
+ {
+ public SshDataReader(byte[] data)
+ {
+ this.LoadBytes(data);
+ }
+
+ public new UInt32 ReadUInt32()
+ {
+ return base.ReadUInt32();
+ }
+
+ public new string ReadString()
+ {
+ return base.ReadString();
+ }
+
+ public new byte[] ReadBytes(int length)
+ {
+ return base.ReadBytes(length);
+ }
+
+ ///
+ /// Reads next mpint data type from internal buffer where length specified in bits.
+ ///
+ /// mpint read.
+ public BigInteger ReadBigIntWithBits()
+ {
+ var length = (int)base.ReadUInt32();
+
+ length = (int)(length + 7) / 8;
+
+ var data = base.ReadBytes(length);
+ var bytesArray = new byte[data.Length + 1];
+ Buffer.BlockCopy(data, 0, bytesArray, 1, data.Length);
+
+ return new BigInteger(bytesArray.Reverse().ToArray());
+ }
+
+ protected override void LoadData()
+ {
+ }
+
+ protected override void SaveData()
+ {
+ }
+ }
}
}
diff --git a/Renci.SshNet/Properties/AssemblyInfo.cs b/Renci.SshNet/Properties/AssemblyInfo.cs
index 92f8c16..60b05c0 100644
--- a/Renci.SshNet/Properties/AssemblyInfo.cs
+++ b/Renci.SshNet/Properties/AssemblyInfo.cs
@@ -8,10 +8,9 @@
// associated with an assembly.
[assembly: AssemblyTitle("SshNet")]
[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Renci")]
[assembly: AssemblyProduct("SSH.NET")]
-[assembly: AssemblyCopyright("Copyright © Renci 2011")]
+[assembly: AssemblyCopyright("Copyright © Renci 2013")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
@@ -33,7 +32,13 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("0.1")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
+[assembly: AssemblyVersion("2013.4.7")]
+[assembly: AssemblyFileVersion("2013.4.7")]
+[assembly: AssemblyInformationalVersion("2013.4.7")]
[assembly: CLSCompliant(false)]
[assembly: InternalsVisibleTo("Renci.SshNet.Tests")]
+#if DEBUG
+[assembly: AssemblyConfiguration("Debug")]
+#else
+[assembly: AssemblyConfiguration("Release")]
+#endif
\ No newline at end of file
diff --git a/Renci.SshNet/ProxyTypes.cs b/Renci.SshNet/ProxyTypes.cs
new file mode 100644
index 0000000..30e37a3
--- /dev/null
+++ b/Renci.SshNet/ProxyTypes.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Renci.SshNet
+{
+ ///
+ /// Specifies the type of proxy client will use to connect to server.
+ ///
+ public enum ProxyTypes
+ {
+ /// No proxy server.
+ None,
+ /// A SOCKS4 proxy server.
+ Socks4,
+ /// A SOCKS5 proxy server.
+ Socks5,
+ /// A HTTP proxy server.
+ Http,
+ }
+}
diff --git a/Renci.SshNet/Renci.SshNet.csproj b/Renci.SshNet/Renci.SshNet.csproj
index 35a509f..ac0f129 100644
--- a/Renci.SshNet/Renci.SshNet.csproj
+++ b/Renci.SshNet/Renci.SshNet.csproj
@@ -12,61 +12,39 @@
Renci.SshNet
v4.0
512
-
-
-
-
-
-
-
-
true
full
false
bin\Debug\
- TRACE;DEBUG;NOTIMEOUT
+ DEBUG;TRACE
prompt
- 4
+ 0
bin\Debug\Renci.SshNet.xml
- x86
pdbonly
true
bin\Release\
-
-
+ TRACE
prompt
4
bin\Release\Renci.SshNet.xml
- x86
-
-
- true
- bin\DebugNoTimeout\
- TRACE;DEBUG
- full
- AnyCPU
- bin\Debug\Renci.SshClient.dll.CodeAnalysisLog.xml
- true
- GlobalSuppressions.cs
- prompt
- MinimumRecommendedRules.ruleset
- ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets
- false
- ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules
- false
- bin\DebugNoTimeout\Renci.SshNet.xml
-
+
+
+ Code
+
+
+ Code
+
@@ -77,6 +55,7 @@
+
@@ -90,19 +69,36 @@
+
+
+ Code
+
+
+
+
Code
-
- Code
-
+
Code
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
Code
@@ -110,6 +106,7 @@
+
@@ -121,12 +118,74 @@
+
+ Code
+
+
-
+
+ Code
+
+
+
+
+ Code
+
+
+
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+
+
+
+
+
Code
+
+
+
+ Code
+
+
+ Code
+
+
+
+ Code
+
+
+ Code
+
+
+
+ Code
+
+
+
+
+
+ Code
+
+
+
+ Code
+
+
+ Code
+
+
Code
@@ -136,8 +195,6 @@
-
-
@@ -169,6 +226,7 @@
+
@@ -201,7 +259,6 @@
-
@@ -221,10 +278,8 @@
-
-
-
-
+
+
@@ -246,6 +301,7 @@
+
Code
@@ -319,13 +375,19 @@
-
-
-
+
+
+
+
+
+
+ Code
+
+
@@ -342,7 +404,11 @@
-
+
+ Code
+
+
+
@@ -358,6 +424,9 @@
+
+ Code
+
@@ -366,45 +435,27 @@
Code
+
Code
+
+ Code
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
From 2bbd11f04cec10d27dfaa9cd6b9cd6d688d582d7 Mon Sep 17 00:00:00 2001
From: Martin Dimov
Date: Sun, 20 Jul 2014 22:17:09 +0200
Subject: [PATCH 011/134] ssh buffer up, timing
---
Renci.SshNet/Sftp/SftpFileStream.cs | 6 +++---
Sshfs/Sshfs/MainForm.cs | 2 ++
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/Renci.SshNet/Sftp/SftpFileStream.cs b/Renci.SshNet/Sftp/SftpFileStream.cs
index f489200..c493d7a 100644
--- a/Renci.SshNet/Sftp/SftpFileStream.cs
+++ b/Renci.SshNet/Sftp/SftpFileStream.cs
@@ -189,13 +189,13 @@ public virtual byte[] Handle
public TimeSpan Timeout { get; set; }
internal SftpFileStream(SftpSession session, string path, FileMode mode)
- : this(session, path, mode, FileAccess.ReadWrite, 4096, false)
+ : this(session, path, mode, FileAccess.ReadWrite, 65536, false)
{
// Nothing to do here.
}
internal SftpFileStream(SftpSession session, string path, FileMode mode, FileAccess access)
- : this(session, path, mode, access, 4096, false)
+ : this(session, path, mode, access, 65536, false)
{
// Nothing to do here.
}
@@ -216,7 +216,7 @@ internal SftpFileStream(SftpSession session, string path, FileMode mode, FileAcc
{
throw new ArgumentNullException("path");
}
- if (bufferSize <= 0 || bufferSize > 16 * 1024)
+ if (bufferSize <= 0 || bufferSize > 64 * 1024)
{
throw new ArgumentOutOfRangeException("bufferSize");
}
diff --git a/Sshfs/Sshfs/MainForm.cs b/Sshfs/Sshfs/MainForm.cs
index 8c3b172..bbfb2f4 100644
--- a/Sshfs/Sshfs/MainForm.cs
+++ b/Sshfs/Sshfs/MainForm.cs
@@ -15,6 +15,7 @@
using Microsoft.Win32;
using Renci.SshNet;
using Sshfs.Properties;
+using System.Threading;
#endregion
@@ -422,6 +423,7 @@ private void MainForm_Shown(object sender, EventArgs e)
foreach (var drive in _drives.Where(d => d.Automount))
{
MountDrive(drive);
+ Thread.Sleep(100);//pokus
}
if (_drives.Count != 0 && _drives[0].Automount)
muButton.Enabled = false;
From caa2dbb999cdac319d6926cf69082902dcfbf10f Mon Sep 17 00:00:00 2001
From: Martin Dimov
Date: Sun, 20 Jul 2014 23:01:09 +0200
Subject: [PATCH 012/134] mounting tuning automount is mounting in sequence
---
Sshfs/Sshfs/MainForm.cs | 7 ++++++-
Sshfs/Sshfs/SftpDrive.cs | 2 +-
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/Sshfs/Sshfs/MainForm.cs b/Sshfs/Sshfs/MainForm.cs
index bbfb2f4..dafd24a 100644
--- a/Sshfs/Sshfs/MainForm.cs
+++ b/Sshfs/Sshfs/MainForm.cs
@@ -402,6 +402,7 @@ private void muButton_Click(object sender, EventArgs e)
else
{
drive.Unmount();
+ muButton.Enabled = false;
}
}
@@ -423,7 +424,11 @@ private void MainForm_Shown(object sender, EventArgs e)
foreach (var drive in _drives.Where(d => d.Automount))
{
MountDrive(drive);
- Thread.Sleep(100);//pokus
+ //no parallel mounting on startup fix:
+ while (drive.Status == DriveStatus.Mounting)
+ {
+ Thread.Sleep(100);
+ }
}
if (_drives.Count != 0 && _drives[0].Automount)
muButton.Enabled = false;
diff --git a/Sshfs/Sshfs/SftpDrive.cs b/Sshfs/Sshfs/SftpDrive.cs
index 251c805..0113ce0 100644
--- a/Sshfs/Sshfs/SftpDrive.cs
+++ b/Sshfs/Sshfs/SftpDrive.cs
@@ -204,7 +204,7 @@ public void Mount()
Directory.GetLogicalDrives().All(
drive => drive[0] != Letter))
{
- Thread.Sleep(1000);
+ Thread.Sleep(200);
}
}, _mountCancel.Token);
From 2235b8f64e00c85fe33be75f359be9da585364cb Mon Sep 17 00:00:00 2001
From: Martin Dimov
Date: Mon, 21 Jul 2014 18:43:37 +0200
Subject: [PATCH 013/134] swap to .net 4.5
---
DokanNet/DokanNet.csproj | 8 ++++++--
Renci.SshNet/Renci.SshNet.csproj | 5 ++++-
Sshfs/Sshfs/Properties/AssemblyInfo.cs | 4 ++--
Sshfs/Sshfs/Properties/Resources.Designer.cs | 17 ++++++++++++++++-
Sshfs/Sshfs/Properties/Settings.Designer.cs | 4 ++--
Sshfs/Sshfs/Sshfs.csproj | 14 ++++++++------
Sshfs/Sshfs/app.config | 6 +++---
7 files changed, 41 insertions(+), 17 deletions(-)
diff --git a/DokanNet/DokanNet.csproj b/DokanNet/DokanNet.csproj
index 85ded30..5952eda 100644
--- a/DokanNet/DokanNet.csproj
+++ b/DokanNet/DokanNet.csproj
@@ -13,7 +13,7 @@
3.5
- v4.0
+ v4.5
@@ -52,6 +52,7 @@
AllRules.ruleset
false
x86
+ false
pdbonly
@@ -63,6 +64,7 @@
4
AllRules.ruleset
AnyCPU
+ false
@@ -83,6 +85,7 @@
;E:\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules
false
false
+ false
bin\x86\Release\
@@ -100,6 +103,7 @@
false
;E:\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules
false
+ false
true
@@ -152,7 +156,7 @@
-
+
+
+
+
+ Debug
+ AnyCPU
+ 8.0.30703
+ 2.0
+ {2F5F8C90-0BD1-424F-997C-7BC6280919D1}
+ Library
+ Properties
+ Renci.SshNet
+ Renci.SshNet
+ v4.0
+ 512
+ SAK
+ SAK
+ SAK
+ SAK
+
+
+ true
+ full
+ false
+ bin\Debug\
+ TRACE;DEBUG
+ prompt
+ 4
+ bin\Debug\Renci.SshNet.xml
+
+
+ none
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+ bin\Release\Renci.SshNet.xml
+ 1591
+
+
+ true
+
+
+ ..\Renci.SshNet.snk
+
+
+
+
+
+
+
+
+
+ Code
+
+
+ Code
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Code
+
+
+
+
+
+
+
+
+ Code
+
+
+
+
+
+
+
+ Code
+
+
+
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Code
+
+
+
+
+
+
+ Code
+
+
+
+
+ Code
+
+
+
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+
+
+
+
+
+ Code
+
+
+
+
+ Code
+
+
+ Code
+
+
+
+ Code
+
+
+ Code
+
+
+
+ Code
+
+
+
+
+
+ Code
+
+
+
+ Code
+
+
+ Code
+
+
+
+
+ Code
+
+
+ Code
+
+
+
+
+
+
+
+
+
+
+
+ Code
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Code
+
+
+
+
+
+ Code
+
+
+
+
+
+
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+
+
+
+
+
+
+
+
+ Code
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Code
+
+
+
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+ Code
+
+
+
+
+
+
+
+
+
+ Code
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Code
+
+
+
+
+
+
+
+
+
+
+
+
+ Code
+
+
+
+
+
+
+ Code
+
+
+
+
+ Code
+
+
+ Code
+
+
+
+
+ Code
+
+
+
+
+ Code
+
+
+
+
+
+
+
+
+ Renci.SshNet.snk
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Renci.SshNet/Renci.SshNet.csproj.vspscc b/Renci.SshNet/Renci.SshNet.csproj.vspscc
index b6d3289..feffdec 100644
--- a/Renci.SshNet/Renci.SshNet.csproj.vspscc
+++ b/Renci.SshNet/Renci.SshNet.csproj.vspscc
@@ -1,10 +1,10 @@
-""
-{
-"FILE_VERSION" = "9237"
-"ENLISTMENT_CHOICE" = "NEVER"
-"PROJECT_FILE_RELATIVE_PATH" = ""
-"NUMBER_OF_EXCLUDED_FILES" = "0"
-"ORIGINAL_PROJECT_FILE_PATH" = ""
-"NUMBER_OF_NESTED_PROJECTS" = "0"
-"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
-}
+""
+{
+"FILE_VERSION" = "9237"
+"ENLISTMENT_CHOICE" = "NEVER"
+"PROJECT_FILE_RELATIVE_PATH" = ""
+"NUMBER_OF_EXCLUDED_FILES" = "0"
+"ORIGINAL_PROJECT_FILE_PATH" = ""
+"NUMBER_OF_NESTED_PROJECTS" = "0"
+"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
+}
diff --git a/Renci.SshNet/ScpClient.NET.cs b/Renci.SshNet/ScpClient.NET.cs
index 6967894..294f515 100644
--- a/Renci.SshNet/ScpClient.NET.cs
+++ b/Renci.SshNet/ScpClient.NET.cs
@@ -1,312 +1,303 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Renci.SshNet.Channels;
-using System.IO;
-using Renci.SshNet.Common;
-using Renci.SshNet.Messages.Connection;
-using System.Text.RegularExpressions;
-using System.Threading;
-using System.Diagnostics;
-
-namespace Renci.SshNet
-{
- ///
- /// Provides SCP client functionality.
- ///
- public partial class ScpClient
- {
- private static Regex _rootPath = new Regex(@"^(/|[A-Z][:])", RegexOptions.Compiled | RegexOptions.IgnoreCase);
-
- ///
- /// Uploads the specified file to the remote host.
- ///
- /// The file system info.
- /// The path.
- /// fileSystemInfo
- /// path
- ///
- /// or is null.
- public void Upload(FileInfo fileInfo, string path)
- {
- if (fileInfo == null)
- throw new ArgumentNullException("fileSystemInfo");
-
- if (string.IsNullOrEmpty(path))
- throw new ArgumentException("path");
-
- using (var input = new PipeStream())
- using (var channel = this.Session.CreateChannel())
- {
- channel.DataReceived += delegate(object sender, Common.ChannelDataEventArgs e)
- {
- input.Write(e.Data, 0, e.Data.Length);
- input.Flush();
- };
-
- channel.Open();
-
- // Send channel command request
- channel.SendExecRequest(string.Format("scp -t \"{0}\"", path));
- this.CheckReturnCode(input);
-
- this.InternalUpload(channel, input, fileInfo, fileInfo.Name);
-
- channel.Close();
- }
- }
-
- ///
- /// Uploads the specified directory to the remote host.
- ///
- /// The directory info.
- /// The path.
- /// fileSystemInfo
- /// path
- public void Upload(DirectoryInfo directoryInfo, string path)
- {
- if (directoryInfo == null)
- throw new ArgumentNullException("fileSystemInfo");
-
- if (string.IsNullOrEmpty(path))
- throw new ArgumentException("path");
-
- using (var input = new PipeStream())
- using (var channel = this.Session.CreateChannel())
- {
- channel.DataReceived += delegate(object sender, Common.ChannelDataEventArgs e)
- {
- input.Write(e.Data, 0, e.Data.Length);
- input.Flush();
- };
-
- channel.Open();
-
- // Send channel command request
- channel.SendExecRequest(string.Format("scp -rt \"{0}\"", path));
- this.CheckReturnCode(input);
-
- this.InternalSetTimestamp(channel, input, directoryInfo.LastWriteTimeUtc, directoryInfo.LastAccessTimeUtc);
- this.SendData(channel, string.Format("D0755 0 {0}\n", Path.GetFileName(path)));
- this.CheckReturnCode(input);
-
- this.InternalUpload(channel, input, directoryInfo as DirectoryInfo, directoryInfo.Name);
-
- this.SendData(channel, "E\n");
- this.CheckReturnCode(input);
-
- channel.Close();
- }
- }
-
- ///
- /// Downloads the specified file from the remote host to local file.
- ///
- /// Remote host file name.
- /// Local file information.
- /// or is null.
- public void Download(string filename, FileInfo fileInfo)
- {
- if (fileInfo == null)
- throw new ArgumentNullException("fileInfo");
-
- if (string.IsNullOrEmpty(filename))
- throw new ArgumentException("filename");
-
- using (var input = new PipeStream())
- using (var channel = this.Session.CreateChannel())
- {
- channel.DataReceived += delegate(object sender, Common.ChannelDataEventArgs e)
- {
- input.Write(e.Data, 0, e.Data.Length);
- input.Flush();
- };
-
- channel.Open();
-
- // Send channel command request
- channel.SendExecRequest(string.Format("scp -pf \"{0}\"", filename));
- this.SendConfirmation(channel); // Send reply
-
- this.InternalDownload(channel, input, fileInfo);
-
- channel.Close();
- }
- }
-
- ///
- /// Downloads the specified directory from the remote host to local directory.
- ///
- /// Remote host directory name.
- /// Local directory information.
- /// or is null.
- public void Download(string directoryName, DirectoryInfo directoryInfo)
- {
- if (directoryInfo == null)
- throw new ArgumentNullException("directoryInfo");
-
- if (string.IsNullOrEmpty(directoryName))
- throw new ArgumentException("directoryName");
-
- using (var input = new PipeStream())
- using (var channel = this.Session.CreateChannel())
- {
- channel.DataReceived += delegate(object sender, Common.ChannelDataEventArgs e)
- {
- input.Write(e.Data, 0, e.Data.Length);
- input.Flush();
- };
-
- channel.Open();
-
- // Send channel command request
- channel.SendExecRequest(string.Format("scp -prf \"{0}\"", directoryName));
- this.SendConfirmation(channel); // Send reply
-
- this.InternalDownload(channel, input, directoryInfo);
-
- channel.Close();
- }
- }
-
- private void InternalUpload(ChannelSession channel, Stream input, FileInfo fileInfo, string filename)
- {
- this.InternalSetTimestamp(channel, input, fileInfo.LastWriteTimeUtc, fileInfo.LastAccessTimeUtc);
- using (var source = fileInfo.OpenRead())
- {
- this.InternalUpload(channel, input, source, filename);
- }
- }
-
- private void InternalUpload(ChannelSession channel, Stream input, DirectoryInfo directoryInfo, string directoryName)
- {
- // Upload files
- var files = directoryInfo.GetFiles();
- foreach (var file in files)
- {
- this.InternalUpload(channel, input, file, file.Name);
- }
-
- // Upload directories
- var directories = directoryInfo.GetDirectories();
- foreach (var directory in directories)
- {
- this.InternalSetTimestamp(channel, input, directoryInfo.LastWriteTimeUtc, directoryInfo.LastAccessTimeUtc);
- this.SendData(channel, string.Format("D0755 0 {0}\n", directory.Name));
- this.CheckReturnCode(input);
-
- this.InternalUpload(channel, input, directory, directory.Name);
-
- this.SendData(channel, "E\n");
- this.CheckReturnCode(input);
- }
- }
-
- private void InternalDownload(ChannelSession channel, Stream input, FileSystemInfo fileSystemInfo)
- {
- DateTime modifiedTime = DateTime.Now;
- DateTime accessedTime = DateTime.Now;
-
- var startDirectoryFullName = fileSystemInfo.FullName;
- var currentDirectoryFullName = startDirectoryFullName;
- var directoryCounter = 0;
-
- while (true)
- {
- var message = ReadString(input);
-
- if (message == "E")
- {
- this.SendConfirmation(channel); // Send reply
-
- directoryCounter--;
-
- currentDirectoryFullName = new DirectoryInfo(currentDirectoryFullName).Parent.FullName;
-
- if (directoryCounter == 0)
- break;
- continue;
- }
-
- var match = _directoryInfoRe.Match(message);
- if (match.Success)
- {
- this.SendConfirmation(channel); // Send reply
-
- // Read directory
- var mode = long.Parse(match.Result("${mode}"));
- var filename = match.Result("${filename}");
-
- DirectoryInfo newDirectoryInfo;
- if (directoryCounter > 0)
- {
- newDirectoryInfo = Directory.CreateDirectory(string.Format("{0}{1}{2}", currentDirectoryFullName, Path.DirectorySeparatorChar, filename));
- newDirectoryInfo.LastAccessTime = accessedTime;
- newDirectoryInfo.LastWriteTime = modifiedTime;
- }
- else
- {
- // Dont create directory for first level
- newDirectoryInfo = fileSystemInfo as DirectoryInfo;
- }
-
- directoryCounter++;
-
- currentDirectoryFullName = newDirectoryInfo.FullName;
- continue;
- }
-
- match = _fileInfoRe.Match(message);
- if (match.Success)
- {
- // Read file
- this.SendConfirmation(channel); // Send reply
-
- var mode = match.Result("${mode}");
- var length = long.Parse(match.Result("${length}"));
- var fileName = match.Result("${filename}");
-
- var fileInfo = fileSystemInfo as FileInfo;
-
- if (fileInfo == null)
- fileInfo = new FileInfo(string.Format("{0}{1}{2}", currentDirectoryFullName, Path.DirectorySeparatorChar, fileName));
-
- using (var output = fileInfo.OpenWrite())
- {
- this.InternalDownload(channel, input, output, fileName, length);
- }
-
- fileInfo.LastAccessTime = accessedTime;
- fileInfo.LastWriteTime = modifiedTime;
-
- if (directoryCounter == 0)
- break;
- continue;
- }
-
- match = _timestampRe.Match(message);
- if (match.Success)
- {
- // Read timestamp
- this.SendConfirmation(channel); // Send reply
-
- var mtime = long.Parse(match.Result("${mtime}"));
- var atime = long.Parse(match.Result("${atime}"));
-
- var zeroTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
- modifiedTime = zeroTime.AddSeconds(mtime);
- accessedTime = zeroTime.AddSeconds(atime);
- continue;
- }
-
- this.SendConfirmation(channel, 1, string.Format("\"{0}\" is not valid protocol message.", message));
- }
- }
-
- partial void SendData(ChannelSession channel, string command)
- {
- channel.SendData(System.Text.Encoding.Default.GetBytes(command));
- }
- }
-}
+using System;
+using Renci.SshNet.Channels;
+using System.IO;
+using Renci.SshNet.Common;
+using System.Text.RegularExpressions;
+
+namespace Renci.SshNet
+{
+ ///
+ /// Provides SCP client functionality.
+ ///
+ public partial class ScpClient
+ {
+ private static readonly Regex _directoryInfoRe = new Regex(@"D(?\d{4}) (?\d+) (?.+)");
+ private static readonly Regex _timestampRe = new Regex(@"T(?\d+) 0 (?\d+) 0");
+
+ ///
+ /// Uploads the specified file to the remote host.
+ ///
+ /// The file system info.
+ /// The path.
+ /// is null.
+ /// is null or empty.
+ public void Upload(FileInfo fileInfo, string path)
+ {
+ if (fileInfo == null)
+ throw new ArgumentNullException("fileInfo");
+ if (string.IsNullOrEmpty(path))
+ throw new ArgumentException("path");
+
+ using (var input = new PipeStream())
+ using (var channel = this.Session.CreateClientChannel())
+ {
+ channel.DataReceived += delegate(object sender, ChannelDataEventArgs e)
+ {
+ input.Write(e.Data, 0, e.Data.Length);
+ input.Flush();
+ };
+
+ channel.Open();
+
+ // Send channel command request
+ channel.SendExecRequest(string.Format("scp -t \"{0}\"", path));
+ this.CheckReturnCode(input);
+
+ this.InternalUpload(channel, input, fileInfo, fileInfo.Name);
+
+ channel.Close();
+ }
+ }
+
+ ///
+ /// Uploads the specified directory to the remote host.
+ ///
+ /// The directory info.
+ /// The path.
+ /// fileSystemInfo
+ /// is null or empty.
+ public void Upload(DirectoryInfo directoryInfo, string path)
+ {
+ if (directoryInfo == null)
+ throw new ArgumentNullException("directoryInfo");
+ if (string.IsNullOrEmpty(path))
+ throw new ArgumentException("path");
+
+ using (var input = new PipeStream())
+ using (var channel = this.Session.CreateClientChannel())
+ {
+ channel.DataReceived += delegate(object sender, ChannelDataEventArgs e)
+ {
+ input.Write(e.Data, 0, e.Data.Length);
+ input.Flush();
+ };
+
+ channel.Open();
+
+ // Send channel command request
+ channel.SendExecRequest(string.Format("scp -rt \"{0}\"", path));
+ this.CheckReturnCode(input);
+
+ this.InternalSetTimestamp(channel, input, directoryInfo.LastWriteTimeUtc, directoryInfo.LastAccessTimeUtc);
+ this.SendData(channel, string.Format("D0755 0 {0}\n", Path.GetFileName(path)));
+ this.CheckReturnCode(input);
+
+ this.InternalUpload(channel, input, directoryInfo);
+
+ this.SendData(channel, "E\n");
+ this.CheckReturnCode(input);
+
+ channel.Close();
+ }
+ }
+
+ ///
+ /// Downloads the specified file from the remote host to local file.
+ ///
+ /// Remote host file name.
+ /// Local file information.
+ /// is null.
+ /// is null or empty.
+ public void Download(string filename, FileInfo fileInfo)
+ {
+ if (string.IsNullOrEmpty(filename))
+ throw new ArgumentException("filename");
+ if (fileInfo == null)
+ throw new ArgumentNullException("fileInfo");
+
+ using (var input = new PipeStream())
+ using (var channel = this.Session.CreateClientChannel())
+ {
+ channel.DataReceived += delegate(object sender, ChannelDataEventArgs e)
+ {
+ input.Write(e.Data, 0, e.Data.Length);
+ input.Flush();
+ };
+
+ channel.Open();
+
+ // Send channel command request
+ channel.SendExecRequest(string.Format("scp -pf \"{0}\"", filename));
+ this.SendConfirmation(channel); // Send reply
+
+ this.InternalDownload(channel, input, fileInfo);
+
+ channel.Close();
+ }
+ }
+
+ ///
+ /// Downloads the specified directory from the remote host to local directory.
+ ///
+ /// Remote host directory name.
+ /// Local directory information.
+ /// is null or empty.
+ /// is null.
+ public void Download(string directoryName, DirectoryInfo directoryInfo)
+ {
+ if (string.IsNullOrEmpty(directoryName))
+ throw new ArgumentException("directoryName");
+ if (directoryInfo == null)
+ throw new ArgumentNullException("directoryInfo");
+
+ using (var input = new PipeStream())
+ using (var channel = this.Session.CreateClientChannel())
+ {
+ channel.DataReceived += delegate(object sender, ChannelDataEventArgs e)
+ {
+ input.Write(e.Data, 0, e.Data.Length);
+ input.Flush();
+ };
+
+ channel.Open();
+
+ // Send channel command request
+ channel.SendExecRequest(string.Format("scp -prf \"{0}\"", directoryName));
+ this.SendConfirmation(channel); // Send reply
+
+ this.InternalDownload(channel, input, directoryInfo);
+
+ channel.Close();
+ }
+ }
+
+ private void InternalUpload(ChannelSession channel, Stream input, FileInfo fileInfo, string filename)
+ {
+ this.InternalSetTimestamp(channel, input, fileInfo.LastWriteTimeUtc, fileInfo.LastAccessTimeUtc);
+ using (var source = fileInfo.OpenRead())
+ {
+ this.InternalUpload(channel, input, source, filename);
+ }
+ }
+
+ private void InternalUpload(ChannelSession channel, Stream input, DirectoryInfo directoryInfo)
+ {
+ // Upload files
+ var files = directoryInfo.GetFiles();
+ foreach (var file in files)
+ {
+ this.InternalUpload(channel, input, file, file.Name);
+ }
+
+ // Upload directories
+ var directories = directoryInfo.GetDirectories();
+ foreach (var directory in directories)
+ {
+ this.InternalSetTimestamp(channel, input, directoryInfo.LastWriteTimeUtc, directoryInfo.LastAccessTimeUtc);
+ this.SendData(channel, string.Format("D0755 0 {0}\n", directory.Name));
+ this.CheckReturnCode(input);
+
+ this.InternalUpload(channel, input, directory);
+
+ this.SendData(channel, "E\n");
+ this.CheckReturnCode(input);
+ }
+ }
+
+ private void InternalDownload(ChannelSession channel, Stream input, FileSystemInfo fileSystemInfo)
+ {
+ DateTime modifiedTime = DateTime.Now;
+ DateTime accessedTime = DateTime.Now;
+
+ var startDirectoryFullName = fileSystemInfo.FullName;
+ var currentDirectoryFullName = startDirectoryFullName;
+ var directoryCounter = 0;
+
+ while (true)
+ {
+ var message = ReadString(input);
+
+ if (message == "E")
+ {
+ this.SendConfirmation(channel); // Send reply
+
+ directoryCounter--;
+
+ currentDirectoryFullName = new DirectoryInfo(currentDirectoryFullName).Parent.FullName;
+
+ if (directoryCounter == 0)
+ break;
+ continue;
+ }
+
+ var match = _directoryInfoRe.Match(message);
+ if (match.Success)
+ {
+ this.SendConfirmation(channel); // Send reply
+
+ // Read directory
+ var mode = long.Parse(match.Result("${mode}"));
+ var filename = match.Result("${filename}");
+
+ DirectoryInfo newDirectoryInfo;
+ if (directoryCounter > 0)
+ {
+ newDirectoryInfo = Directory.CreateDirectory(string.Format("{0}{1}{2}", currentDirectoryFullName, Path.DirectorySeparatorChar, filename));
+ newDirectoryInfo.LastAccessTime = accessedTime;
+ newDirectoryInfo.LastWriteTime = modifiedTime;
+ }
+ else
+ {
+ // Dont create directory for first level
+ newDirectoryInfo = fileSystemInfo as DirectoryInfo;
+ }
+
+ directoryCounter++;
+
+ currentDirectoryFullName = newDirectoryInfo.FullName;
+ continue;
+ }
+
+ match = _fileInfoRe.Match(message);
+ if (match.Success)
+ {
+ // Read file
+ this.SendConfirmation(channel); // Send reply
+
+ var mode = match.Result("${mode}");
+ var length = long.Parse(match.Result("${length}"));
+ var fileName = match.Result("${filename}");
+
+ var fileInfo = fileSystemInfo as FileInfo;
+
+ if (fileInfo == null)
+ fileInfo = new FileInfo(string.Format("{0}{1}{2}", currentDirectoryFullName, Path.DirectorySeparatorChar, fileName));
+
+ using (var output = fileInfo.OpenWrite())
+ {
+ this.InternalDownload(channel, input, output, fileName, length);
+ }
+
+ fileInfo.LastAccessTime = accessedTime;
+ fileInfo.LastWriteTime = modifiedTime;
+
+ if (directoryCounter == 0)
+ break;
+ continue;
+ }
+
+ match = _timestampRe.Match(message);
+ if (match.Success)
+ {
+ // Read timestamp
+ this.SendConfirmation(channel); // Send reply
+
+ var mtime = long.Parse(match.Result("${mtime}"));
+ var atime = long.Parse(match.Result("${atime}"));
+
+ var zeroTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
+ modifiedTime = zeroTime.AddSeconds(mtime);
+ accessedTime = zeroTime.AddSeconds(atime);
+ continue;
+ }
+
+ this.SendConfirmation(channel, 1, string.Format("\"{0}\" is not valid protocol message.", message));
+ }
+ }
+
+ partial void SendData(ChannelSession channel, string command)
+ {
+ channel.SendData(System.Text.Encoding.Default.GetBytes(command));
+ }
+ }
+}
diff --git a/Renci.SshNet/ScpClient.cs b/Renci.SshNet/ScpClient.cs
index 341f61a..b13a584 100644
--- a/Renci.SshNet/ScpClient.cs
+++ b/Renci.SshNet/ScpClient.cs
@@ -1,421 +1,408 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Renci.SshNet.Channels;
-using System.IO;
-using Renci.SshNet.Common;
-using Renci.SshNet.Messages.Connection;
-using System.Text.RegularExpressions;
-using System.Threading;
-using System.Diagnostics;
-using System.Diagnostics.CodeAnalysis;
-
-namespace Renci.SshNet
-{
- ///
- /// Provides SCP client functionality.
- ///
- public partial class ScpClient : BaseClient
- {
- private static Regex _fileInfoRe = new Regex(@"C(?\d{4}) (?\d+) (?.+)");
-
- private static Regex _directoryInfoRe = new Regex(@"D(?\d{4}) (?\d+) (?.+)");
-
- private static Regex _timestampRe = new Regex(@"T(?\d+) 0 (?\d+) 0");
-
- private static char[] _byteToChar;
-
- private bool _disposeConnectionInfo;
-
- ///
- /// Gets or sets the operation timeout.
- ///
- /// The operation timeout.
- public TimeSpan OperationTimeout { get; set; }
-
- ///
- /// Gets or sets the size of the buffer.
- ///
- /// The size of the buffer.
- public uint BufferSize { get; set; }
-
- ///
- /// Occurs when downloading file.
- ///
- public event EventHandler Downloading;
-
- ///
- /// Occurs when uploading file.
- ///
- public event EventHandler Uploading;
-
- #region Constructors
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The connection info.
- /// is null.
- public ScpClient(ConnectionInfo connectionInfo)
- : base(connectionInfo)
- {
- this.OperationTimeout = new TimeSpan(0, 0, 0, 0, -1);
- this.BufferSize = 1024 * 16;
-
- if (_byteToChar == null)
- {
- _byteToChar = new char[128];
- var ch = '\0';
- for (int i = 0; i < 128; i++)
- {
- _byteToChar[i] = ch++;
- }
- }
-
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// Connection host.
- /// Connection port.
- /// Authentication username.
- /// Authentication password.
- /// is null.
- /// is invalid, or is null or contains whitespace characters.
- /// is not within and .
- [SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification = "Disposed in Dispose(bool) method.")]
- public ScpClient(string host, int port, string username, string password)
- : this(new PasswordConnectionInfo(host, port, username, password))
- {
- this._disposeConnectionInfo = true;
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// Connection host.
- /// Authentication username.
- /// Authentication password.
- /// is null.
- /// is invalid, or is null or contains whitespace characters.
- public ScpClient(string host, string username, string password)
- : this(host, ConnectionInfo.DEFAULT_PORT, username, password)
- {
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// Connection host.
- /// Connection port.
- /// Authentication username.
- /// Authentication private key file(s) .
- /// is null.
- /// is invalid, -or- is null or contains whitespace characters.
- /// is not within and .
- [SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification = "Disposed in Dispose(bool) method.")]
- public ScpClient(string host, int port, string username, params PrivateKeyFile[] keyFiles)
- : this(new PrivateKeyConnectionInfo(host, port, username, keyFiles))
- {
- this._disposeConnectionInfo = true;
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// Connection host.
- /// Authentication username.
- /// Authentication private key file(s) .
- /// is null.
- /// is invalid, -or- is null or contains whitespace characters.
- public ScpClient(string host, string username, params PrivateKeyFile[] keyFiles)
- : this(host, ConnectionInfo.DEFAULT_PORT, username, keyFiles)
- {
- }
-
- #endregion
-
- ///
- /// Uploads the specified stream to the remote host.
- ///
- /// Stream to upload.
- /// Remote host file name.
- public void Upload(Stream source, string path)
- {
- using (var input = new PipeStream())
- using (var channel = this.Session.CreateChannel())
- {
- channel.DataReceived += delegate(object sender, Common.ChannelDataEventArgs e)
- {
- input.Write(e.Data, 0, e.Data.Length);
- input.Flush();
- };
-
- channel.Open();
-
- var pathParts = path.Split('\\', '/');
-
- // Send channel command request
- channel.SendExecRequest(string.Format("scp -rt \"{0}\"", pathParts[0]));
- this.CheckReturnCode(input);
-
- // Prepare directory structure
- for (int i = 0; i < pathParts.Length - 1; i++)
- {
- this.InternalSetTimestamp(channel, input, DateTime.UtcNow, DateTime.UtcNow);
- this.SendData(channel, string.Format("D0755 0 {0}\n", pathParts[i]));
- this.CheckReturnCode(input);
- }
-
- this.InternalUpload(channel, input, source, pathParts.Last());
-
- // Finish directory structure
- for (int i = 0; i < pathParts.Length - 1; i++)
- {
- this.SendData(channel, "E\n");
- this.CheckReturnCode(input);
- }
-
- channel.Close();
- }
- }
-
- ///
- /// Downloads the specified file from the remote host to the stream.
- ///
- /// Remote host file name.
- /// The stream where to download remote file.
- /// is null or contains whitespace characters.
- /// is null.
- /// Method calls made by this method to , may under certain conditions result in exceptions thrown by the stream.
- public void Download(string filename, Stream destination)
- {
- if (filename.IsNullOrWhiteSpace())
- throw new ArgumentException("filename");
-
- if (destination == null)
- throw new ArgumentNullException("destination");
-
- using (var input = new PipeStream())
- using (var channel = this.Session.CreateChannel())
- {
- channel.DataReceived += delegate(object sender, Common.ChannelDataEventArgs e)
- {
- input.Write(e.Data, 0, e.Data.Length);
- input.Flush();
- };
-
- channel.Open();
-
- // Send channel command request
- channel.SendExecRequest(string.Format("scp -f \"{0}\"", filename));
- this.SendConfirmation(channel); // Send reply
-
- var message = ReadString(input);
- var match = _fileInfoRe.Match(message);
-
- if (match.Success)
- {
- // Read file
- this.SendConfirmation(channel); // Send reply
-
- var mode = match.Result("${mode}");
- var length = long.Parse(match.Result("${length}"));
- var fileName = match.Result("${filename}");
-
- this.InternalDownload(channel, input, destination, fileName, length);
- }
- else
- {
- this.SendConfirmation(channel, 1, string.Format("\"{0}\" is not valid protocol message.", message));
- }
-
- channel.Close();
- }
- }
-
- private void InternalSetTimestamp(ChannelSession channel, Stream input, DateTime lastWriteTime, DateTime lastAccessime)
- {
- var zeroTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
- var modificationSeconds = (long)(lastWriteTime - zeroTime).TotalSeconds;
- var accessSeconds = (long)(lastAccessime - zeroTime).TotalSeconds;
- this.SendData(channel, string.Format("T{0} 0 {1} 0\n", modificationSeconds, accessSeconds));
- this.CheckReturnCode(input);
- }
-
- private void InternalUpload(ChannelSession channel, Stream input, Stream source, string filename)
- {
- var length = source.Length;
-
- this.SendData(channel, string.Format("C0644 {0} {1}\n", length, Path.GetFileName(filename)));
-
- var buffer = new byte[this.BufferSize];
-
- var read = source.Read(buffer, 0, buffer.Length);
-
- long totalRead = 0;
-
- while (read > 0)
- {
- this.SendData(channel, buffer, read);
-
- totalRead += read;
-
- this.RaiseUploadingEvent(filename, length, totalRead);
-
- read = source.Read(buffer, 0, buffer.Length);
- }
-
- this.SendConfirmation(channel);
- this.CheckReturnCode(input);
- }
-
- private void InternalDownload(ChannelSession channel, Stream input, Stream output, string filename, long length)
- {
- var buffer = new byte[Math.Min(length, this.BufferSize)];
- var needToRead = length;
-
- do
- {
- var read = input.Read(buffer, 0, (int)Math.Min(needToRead, this.BufferSize));
-
- output.Write(buffer, 0, read);
-
- this.RaiseDownloadingEvent(filename, length, length - needToRead);
-
- needToRead -= read;
- }
- while (needToRead > 0);
-
- output.Flush();
-
- // Raise one more time when file downloaded
- this.RaiseDownloadingEvent(filename, length, length - needToRead);
-
- // Send confirmation byte after last data byte was read
- this.SendConfirmation(channel);
-
- this.CheckReturnCode(input);
- }
-
- private void RaiseDownloadingEvent(string filename, long size, long downloaded)
- {
- if (this.Downloading != null)
- {
- this.Downloading(this, new ScpDownloadEventArgs(filename, size, downloaded));
- }
- }
-
- private void RaiseUploadingEvent(string filename, long size, long uploaded)
- {
- if (this.Uploading != null)
- {
- this.Uploading(this, new ScpUploadEventArgs(filename, size, uploaded));
- }
- }
-
- private void SendConfirmation(ChannelSession channel)
- {
- this.SendData(channel, new byte[] { 0 });
- }
-
- private void SendConfirmation(ChannelSession channel, byte errorCode, string message)
- {
- this.SendData(channel, new byte[] { errorCode });
- this.SendData(channel, string.Format("{0}\n", message));
- }
-
- ///
- /// Checks the return code.
- ///
- /// The output stream.
- private void CheckReturnCode(Stream input)
- {
- var b = ReadByte(input);
-
- if (b > 0)
- {
- var errorText = ReadString(input);
-
- throw new ScpException(errorText);
- }
- }
-
- partial void SendData(ChannelSession channel, string command);
-
- private void SendData(ChannelSession channel, byte[] buffer, int length)
- {
- if (length == buffer.Length)
- {
- channel.SendData(buffer);
- }
- else
- {
- channel.SendData(buffer.Take(length).ToArray());
- }
- }
-
- private void SendData(ChannelSession channel, byte[] buffer)
- {
- channel.SendData(buffer);
- }
-
- private static int ReadByte(Stream stream)
- {
- var b = stream.ReadByte();
-
- while (b < 0)
- {
- Thread.Sleep(100);
- b = stream.ReadByte();
- }
-
- return b;
- }
-
- private static string ReadString(Stream stream)
- {
- var hasError = false;
-
- StringBuilder sb = new StringBuilder();
-
- var b = ReadByte(stream);
-
- if (b == 1 || b == 2)
- {
- hasError = true;
- b = ReadByte(stream);
- }
-
- var ch = _byteToChar[b];
-
- while (ch != '\n')
- {
- sb.Append(ch);
-
- b = ReadByte(stream);
-
- ch = _byteToChar[b];
- }
-
- if (hasError)
- throw new ScpException(sb.ToString());
-
- return sb.ToString();
- }
-
- ///
- /// Releases unmanaged and - optionally - managed resources
- ///
- /// true to release both managed and unmanaged resources; false to release only unmanaged ResourceMessages.
- protected override void Dispose(bool disposing)
- {
- base.Dispose(disposing);
-
- if (this._disposeConnectionInfo)
- ((IDisposable)this.ConnectionInfo).Dispose();
- }
- }
-}
+using System;
+using System.Linq;
+using System.Text;
+using Renci.SshNet.Channels;
+using System.IO;
+using Renci.SshNet.Common;
+using System.Text.RegularExpressions;
+using System.Threading;
+using System.Diagnostics.CodeAnalysis;
+
+namespace Renci.SshNet
+{
+ ///
+ /// Provides SCP client functionality.
+ ///
+ public partial class ScpClient : BaseClient
+ {
+ private static readonly Regex _fileInfoRe = new Regex(@"C(?\d{4}) (?\d+) (?.+)");
+ private static char[] _byteToChar;
+
+ ///
+ /// Gets or sets the operation timeout.
+ ///
+ ///
+ /// The timeout to wait until an operation completes. The default value is negative
+ /// one (-1) milliseconds, which indicates an infinite time-out period.
+ ///
+ public TimeSpan OperationTimeout { get; set; }
+
+ ///
+ /// Gets or sets the size of the buffer.
+ ///
+ ///
+ /// The size of the buffer. The default buffer size is 16384 bytes.
+ ///
+ public uint BufferSize { get; set; }
+
+ ///
+ /// Occurs when downloading file.
+ ///
+ public event EventHandler Downloading;
+
+ ///
+ /// Occurs when uploading file.
+ ///
+ public event EventHandler Uploading;
+
+ #region Constructors
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The connection info.
+ /// is null.
+ public ScpClient(ConnectionInfo connectionInfo)
+ : this(connectionInfo, false)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Connection host.
+ /// Connection port.
+ /// Authentication username.
+ /// Authentication password.
+ /// is null.
+ /// is invalid, or is null or contains whitespace characters.
+ /// is not within and .
+ [SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification = "Disposed in Dispose(bool) method.")]
+ public ScpClient(string host, int port, string username, string password)
+ : this(new PasswordConnectionInfo(host, port, username, password), true)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Connection host.
+ /// Authentication username.
+ /// Authentication password.
+ /// is null.
+ /// is invalid, or is null or contains whitespace characters.
+ public ScpClient(string host, string username, string password)
+ : this(host, ConnectionInfo.DEFAULT_PORT, username, password)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Connection host.
+ /// Connection port.
+ /// Authentication username.
+ /// Authentication private key file(s) .
+ /// is null.
+ /// is invalid, -or- is null or contains whitespace characters.
+ /// is not within and .
+ [SuppressMessage("Microsoft.Reliability", "CA2000:DisposeObjectsBeforeLosingScope", Justification = "Disposed in Dispose(bool) method.")]
+ public ScpClient(string host, int port, string username, params PrivateKeyFile[] keyFiles)
+ : this(new PrivateKeyConnectionInfo(host, port, username, keyFiles), true)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Connection host.
+ /// Authentication username.
+ /// Authentication private key file(s) .
+ /// is null.
+ /// is invalid, -or- is null or contains whitespace characters.
+ public ScpClient(string host, string username, params PrivateKeyFile[] keyFiles)
+ : this(host, ConnectionInfo.DEFAULT_PORT, username, keyFiles)
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The connection info.
+ /// Specified whether this instance owns the connection info.
+ /// is null.
+ ///
+ /// If is true, then the
+ /// connection info will be disposed when this instance is disposed.
+ ///
+ private ScpClient(ConnectionInfo connectionInfo, bool ownsConnectionInfo)
+ : base(connectionInfo, ownsConnectionInfo)
+ {
+ this.OperationTimeout = new TimeSpan(0, 0, 0, 0, -1);
+ this.BufferSize = 1024 * 16;
+
+ if (_byteToChar == null)
+ {
+ _byteToChar = new char[128];
+ var ch = '\0';
+ for (int i = 0; i < 128; i++)
+ {
+ _byteToChar[i] = ch++;
+ }
+ }
+ }
+
+ #endregion
+
+ ///
+ /// Uploads the specified stream to the remote host.
+ ///
+ /// Stream to upload.
+ /// Remote host file name.
+ public void Upload(Stream source, string path)
+ {
+ using (var input = new PipeStream())
+ using (var channel = this.Session.CreateClientChannel())
+ {
+ channel.DataReceived += delegate(object sender, ChannelDataEventArgs e)
+ {
+ input.Write(e.Data, 0, e.Data.Length);
+ input.Flush();
+ };
+
+ channel.Open();
+
+ int pathEnd = path.LastIndexOfAny(new[] { '\\', '/' });
+ if (pathEnd != -1)
+ {
+ // split the path from the file
+ string pathOnly = path.Substring(0, pathEnd);
+ string fileOnly = path.Substring(pathEnd + 1);
+ // Send channel command request
+ channel.SendExecRequest(string.Format("scp -t \"{0}\"", pathOnly));
+ this.CheckReturnCode(input);
+
+ path = fileOnly;
+ }
+
+ this.InternalUpload(channel, input, source, path);
+
+ channel.Close();
+ }
+ }
+
+ ///
+ /// Downloads the specified file from the remote host to the stream.
+ ///
+ /// Remote host file name.
+ /// The stream where to download remote file.
+ /// is null or contains whitespace characters.
+ /// is null.
+ /// Method calls made by this method to , may under certain conditions result in exceptions thrown by the stream.
+ public void Download(string filename, Stream destination)
+ {
+ if (filename.IsNullOrWhiteSpace())
+ throw new ArgumentException("filename");
+
+ if (destination == null)
+ throw new ArgumentNullException("destination");
+
+ using (var input = new PipeStream())
+ using (var channel = this.Session.CreateClientChannel())
+ {
+ channel.DataReceived += delegate(object sender, ChannelDataEventArgs e)
+ {
+ input.Write(e.Data, 0, e.Data.Length);
+ input.Flush();
+ };
+
+ channel.Open();
+
+ // Send channel command request
+ channel.SendExecRequest(string.Format("scp -f \"{0}\"", filename));
+ this.SendConfirmation(channel); // Send reply
+
+ var message = ReadString(input);
+ var match = _fileInfoRe.Match(message);
+
+ if (match.Success)
+ {
+ // Read file
+ this.SendConfirmation(channel); // Send reply
+
+ var mode = match.Result("${mode}");
+ var length = long.Parse(match.Result("${length}"));
+ var fileName = match.Result("${filename}");
+
+ this.InternalDownload(channel, input, destination, fileName, length);
+ }
+ else
+ {
+ this.SendConfirmation(channel, 1, string.Format("\"{0}\" is not valid protocol message.", message));
+ }
+
+ channel.Close();
+ }
+ }
+
+ private void InternalSetTimestamp(ChannelSession channel, Stream input, DateTime lastWriteTime, DateTime lastAccessime)
+ {
+ var zeroTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
+ var modificationSeconds = (long)(lastWriteTime - zeroTime).TotalSeconds;
+ var accessSeconds = (long)(lastAccessime - zeroTime).TotalSeconds;
+ this.SendData(channel, string.Format("T{0} 0 {1} 0\n", modificationSeconds, accessSeconds));
+ this.CheckReturnCode(input);
+ }
+
+ private void InternalUpload(ChannelSession channel, Stream input, Stream source, string filename)
+ {
+ var length = source.Length;
+
+ this.SendData(channel, string.Format("C0644 {0} {1}\n", length, Path.GetFileName(filename)));
+
+ var buffer = new byte[this.BufferSize];
+
+ var read = source.Read(buffer, 0, buffer.Length);
+
+ long totalRead = 0;
+
+ while (read > 0)
+ {
+ this.SendData(channel, buffer, read);
+
+ totalRead += read;
+
+ this.RaiseUploadingEvent(filename, length, totalRead);
+
+ read = source.Read(buffer, 0, buffer.Length);
+ }
+
+ this.SendConfirmation(channel);
+ this.CheckReturnCode(input);
+ }
+
+ private void InternalDownload(ChannelSession channel, Stream input, Stream output, string filename, long length)
+ {
+ var buffer = new byte[Math.Min(length, this.BufferSize)];
+ var needToRead = length;
+
+ do
+ {
+ var read = input.Read(buffer, 0, (int)Math.Min(needToRead, this.BufferSize));
+
+ output.Write(buffer, 0, read);
+
+ this.RaiseDownloadingEvent(filename, length, length - needToRead);
+
+ needToRead -= read;
+ }
+ while (needToRead > 0);
+
+ output.Flush();
+
+ // Raise one more time when file downloaded
+ this.RaiseDownloadingEvent(filename, length, length - needToRead);
+
+ // Send confirmation byte after last data byte was read
+ this.SendConfirmation(channel);
+
+ this.CheckReturnCode(input);
+ }
+
+ private void RaiseDownloadingEvent(string filename, long size, long downloaded)
+ {
+ if (this.Downloading != null)
+ {
+ this.Downloading(this, new ScpDownloadEventArgs(filename, size, downloaded));
+ }
+ }
+
+ private void RaiseUploadingEvent(string filename, long size, long uploaded)
+ {
+ if (this.Uploading != null)
+ {
+ this.Uploading(this, new ScpUploadEventArgs(filename, size, uploaded));
+ }
+ }
+
+ private void SendConfirmation(ChannelSession channel)
+ {
+ this.SendData(channel, new byte[] { 0 });
+ }
+
+ private void SendConfirmation(ChannelSession channel, byte errorCode, string message)
+ {
+ this.SendData(channel, new[] { errorCode });
+ this.SendData(channel, string.Format("{0}\n", message));
+ }
+
+ ///
+ /// Checks the return code.
+ ///
+ /// The output stream.
+ private void CheckReturnCode(Stream input)
+ {
+ var b = ReadByte(input);
+
+ if (b > 0)
+ {
+ var errorText = ReadString(input);
+
+ throw new ScpException(errorText);
+ }
+ }
+
+ partial void SendData(ChannelSession channel, string command);
+
+ private void SendData(ChannelSession channel, byte[] buffer, int length)
+ {
+ if (length == buffer.Length)
+ {
+ channel.SendData(buffer);
+ }
+ else
+ {
+ channel.SendData(buffer.Take(length).ToArray());
+ }
+ }
+
+ private void SendData(ChannelSession channel, byte[] buffer)
+ {
+ channel.SendData(buffer);
+ }
+
+ private static int ReadByte(Stream stream)
+ {
+ var b = stream.ReadByte();
+
+ while (b < 0)
+ {
+ Thread.Sleep(100);
+ b = stream.ReadByte();
+ }
+
+ return b;
+ }
+
+ private static string ReadString(Stream stream)
+ {
+ var hasError = false;
+
+ var sb = new StringBuilder();
+
+ var b = ReadByte(stream);
+
+ if (b == 1 || b == 2)
+ {
+ hasError = true;
+ b = ReadByte(stream);
+ }
+
+ var ch = _byteToChar[b];
+
+ while (ch != '\n')
+ {
+ sb.Append(ch);
+
+ b = ReadByte(stream);
+
+ ch = _byteToChar[b];
+ }
+
+ if (hasError)
+ throw new ScpException(sb.ToString());
+
+ return sb.ToString();
+ }
+ }
+}
diff --git a/Renci.SshNet/Security/Algorithm.cs b/Renci.SshNet/Security/Algorithm.cs
index 180c9d0..184a824 100644
--- a/Renci.SshNet/Security/Algorithm.cs
+++ b/Renci.SshNet/Security/Algorithm.cs
@@ -1,13 +1,13 @@
-namespace Renci.SshNet.Security
-{
- ///
- /// Represents the abstract base class from which all implementations of algorithms must inherit.
- ///
- public abstract class Algorithm
- {
- ///
- /// Gets algorithm name.
- ///
- public abstract string Name { get; }
- }
-}
+namespace Renci.SshNet.Security
+{
+ ///
+ /// Represents the abstract base class from which all implementations of algorithms must inherit.
+ ///
+ public abstract class Algorithm
+ {
+ ///
+ /// Gets algorithm name.
+ ///
+ public abstract string Name { get; }
+ }
+}
diff --git a/Renci.SshNet/Security/CertificateHostAlgorithm.cs b/Renci.SshNet/Security/CertificateHostAlgorithm.cs
index 57ff0f7..4ef8ba5 100644
--- a/Renci.SshNet/Security/CertificateHostAlgorithm.cs
+++ b/Renci.SshNet/Security/CertificateHostAlgorithm.cs
@@ -1,55 +1,50 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace Renci.SshNet.Security
-{
- ///
- /// Implements certificate support for host algorithm.
- ///
- public class CertificateHostAlgorithm : HostAlgorithm
- {
- ///
- /// Gets the host key data.
- ///
- public override byte[] Data
- {
- get { throw new NotImplementedException(); }
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The host key name.
- public CertificateHostAlgorithm(string name)
- : base(name)
- {
-
- }
-
- ///
- /// Signs the specified data.
- ///
- /// The data.
- /// Signed data.
- ///
- public override byte[] Sign(byte[] data)
- {
- throw new NotImplementedException();
- }
-
- ///
- /// Verifies the signature.
- ///
- /// The data.
- /// The signature.
- /// True if signature was successfully verified; otherwise false.
- ///
- public override bool VerifySignature(byte[] data, byte[] signature)
- {
- throw new NotImplementedException();
- }
-
- }
-}
+using System;
+
+namespace Renci.SshNet.Security
+{
+ ///
+ /// Implements certificate support for host algorithm.
+ ///
+ public class CertificateHostAlgorithm : HostAlgorithm
+ {
+ ///
+ /// Gets the host key data.
+ ///
+ public override byte[] Data
+ {
+ get { throw new NotImplementedException(); }
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The host key name.
+ public CertificateHostAlgorithm(string name)
+ : base(name)
+ {
+ }
+
+ ///
+ /// Signs the specified data.
+ ///
+ /// The data.
+ /// Signed data.
+ ///
+ public override byte[] Sign(byte[] data)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Verifies the signature.
+ ///
+ /// The data.
+ /// The signature.
+ /// True if signature was successfully verified; otherwise false.
+ ///
+ public override bool VerifySignature(byte[] data, byte[] signature)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/Renci.SshNet/Security/Cryptography/AsymmetricCipher.cs b/Renci.SshNet/Security/Cryptography/AsymmetricCipher.cs
index d7a67d4..e5e70be 100644
--- a/Renci.SshNet/Security/Cryptography/AsymmetricCipher.cs
+++ b/Renci.SshNet/Security/Cryptography/AsymmetricCipher.cs
@@ -1,18 +1,13 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace Renci.SshNet.Security.Cryptography
-{
- ///
- /// Base class for asymmetric cipher implementations.
- ///
- public abstract class AsymmetricCipher : Cipher
- {
- public override byte MinimumSize
- {
- get { return 0; }
- }
- }
-}
+namespace Renci.SshNet.Security.Cryptography
+{
+ ///
+ /// Base class for asymmetric cipher implementations.
+ ///
+ public abstract class AsymmetricCipher : Cipher
+ {
+ public override byte MinimumSize
+ {
+ get { return 0; }
+ }
+ }
+}
diff --git a/Renci.SshNet/Security/Cryptography/BlockCipher.cs b/Renci.SshNet/Security/Cryptography/BlockCipher.cs
index 43b67df..5e0edb6 100644
--- a/Renci.SshNet/Security/Cryptography/BlockCipher.cs
+++ b/Renci.SshNet/Security/Cryptography/BlockCipher.cs
@@ -1,158 +1,148 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Renci.SshNet.Security.Cryptography.Ciphers;
-
-namespace Renci.SshNet.Security.Cryptography
-{
- ///
- /// Base class for block cipher implementations.
- ///
- public abstract class BlockCipher : SymmetricCipher
- {
- private CipherMode _mode;
-
- private CipherPadding _padding;
-
- ///
- /// Gets the size of the block in bytes.
- ///
- ///
- /// The size of the block in bytes.
- ///
- protected readonly byte _blockSize;
-
- ///
- /// Gets the minimum data size.
- ///
- ///
- /// The minimum data size.
- ///
- public override byte MinimumSize
- {
- get { return this.BlockSize; }
- }
-
- ///
- /// Gets the size of the block.
- ///
- ///
- /// The size of the block.
- ///
- public byte BlockSize
- {
- get
- {
- return this._blockSize;
- }
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The key.
- /// Size of the block.
- /// Cipher mode.
- /// Cipher padding.
- /// is null.
- protected BlockCipher(byte[] key, byte blockSize, CipherMode mode, CipherPadding padding)
- : base(key)
- {
- this._blockSize = blockSize;
- this._mode = mode;
- this._padding = padding;
-
- if (this._mode != null)
- this._mode.Init(this);
- }
-
- ///
- /// Encrypts the specified data.
- ///
- /// The data.
- /// Encrypted data
- public override byte[] Encrypt(byte[] data)
- {
- var output = new byte[data.Length];
-
- if (data.Length % this._blockSize > 0)
- {
- if (this._padding == null)
- {
- throw new ArgumentException("data");
- }
- else
- {
- data = this._padding.Pad(this._blockSize, data);
- }
- }
-
- var writtenBytes = 0;
-
- for (int i = 0; i < data.Length / this._blockSize; i++)
- {
- if (this._mode == null)
- {
- writtenBytes += this.EncryptBlock(data, i * this._blockSize, this._blockSize, output, i * this._blockSize);
- }
- else
- {
- writtenBytes += this._mode.EncryptBlock(data, i * this._blockSize, this._blockSize, output, i * this._blockSize);
- }
- }
-
- if (writtenBytes < data.Length)
- {
- throw new InvalidOperationException("Encryption error.");
- }
-
- return output;
- }
-
- ///
- /// Decrypts the specified data.
- ///
- /// The data.
- /// Decrypted data
- public override byte[] Decrypt(byte[] data)
- {
- if (data.Length % this._blockSize > 0)
- {
- {
- if (this._padding == null)
- {
- throw new ArgumentException("data");
- }
- else
- {
- data = this._padding.Pad(this._blockSize, data);
- }
- }
- }
-
- var output = new byte[data.Length];
-
- var writtenBytes = 0;
- for (int i = 0; i < data.Length / this._blockSize; i++)
- {
- if (this._mode == null)
- {
- writtenBytes += this.DecryptBlock(data, i * this._blockSize, this._blockSize, output, i * this._blockSize);
- }
- else
- {
- writtenBytes += this._mode.DecryptBlock(data, i * this._blockSize, this._blockSize, output, i * this._blockSize);
-
- }
- }
-
- if (writtenBytes < data.Length)
- {
- throw new InvalidOperationException("Encryption error.");
- }
-
- return output;
- }
- }
-}
+using System;
+using Renci.SshNet.Security.Cryptography.Ciphers;
+
+namespace Renci.SshNet.Security.Cryptography
+{
+ ///
+ /// Base class for block cipher implementations.
+ ///
+ public abstract class BlockCipher : SymmetricCipher
+ {
+ private readonly CipherMode _mode;
+
+ private readonly CipherPadding _padding;
+
+ ///
+ /// Gets the size of the block in bytes.
+ ///
+ ///
+ /// The size of the block in bytes.
+ ///
+ protected readonly byte _blockSize;
+
+ ///
+ /// Gets the minimum data size.
+ ///
+ ///
+ /// The minimum data size.
+ ///
+ public override byte MinimumSize
+ {
+ get { return this.BlockSize; }
+ }
+
+ ///
+ /// Gets the size of the block.
+ ///
+ ///
+ /// The size of the block.
+ ///
+ public byte BlockSize
+ {
+ get
+ {
+ return this._blockSize;
+ }
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The key.
+ /// Size of the block.
+ /// Cipher mode.
+ /// Cipher padding.
+ /// is null.
+ protected BlockCipher(byte[] key, byte blockSize, CipherMode mode, CipherPadding padding)
+ : base(key)
+ {
+ this._blockSize = blockSize;
+ this._mode = mode;
+ this._padding = padding;
+
+ if (this._mode != null)
+ this._mode.Init(this);
+ }
+
+ ///
+ /// Encrypts the specified data.
+ ///
+ /// The data.
+ /// Encrypted data
+ public override byte[] Encrypt(byte[] data)
+ {
+ var output = new byte[data.Length];
+
+ if (data.Length % this._blockSize > 0)
+ {
+ if (this._padding == null)
+ {
+ throw new ArgumentException("data");
+ }
+ data = this._padding.Pad(this._blockSize, data);
+ }
+
+ var writtenBytes = 0;
+
+ for (int i = 0; i < data.Length / this._blockSize; i++)
+ {
+ if (this._mode == null)
+ {
+ writtenBytes += this.EncryptBlock(data, i * this._blockSize, this._blockSize, output, i * this._blockSize);
+ }
+ else
+ {
+ writtenBytes += this._mode.EncryptBlock(data, i * this._blockSize, this._blockSize, output, i * this._blockSize);
+ }
+ }
+
+ if (writtenBytes < data.Length)
+ {
+ throw new InvalidOperationException("Encryption error.");
+ }
+
+ return output;
+ }
+
+ ///
+ /// Decrypts the specified data.
+ ///
+ /// The data.
+ /// Decrypted data
+ public override byte[] Decrypt(byte[] data)
+ {
+ if (data.Length % this._blockSize > 0)
+ {
+ {
+ if (this._padding == null)
+ {
+ throw new ArgumentException("data");
+ }
+ data = this._padding.Pad(this._blockSize, data);
+ }
+ }
+
+ var output = new byte[data.Length];
+
+ var writtenBytes = 0;
+ for (int i = 0; i < data.Length / this._blockSize; i++)
+ {
+ if (this._mode == null)
+ {
+ writtenBytes += this.DecryptBlock(data, i * this._blockSize, this._blockSize, output, i * this._blockSize);
+ }
+ else
+ {
+ writtenBytes += this._mode.DecryptBlock(data, i * this._blockSize, this._blockSize, output, i * this._blockSize);
+ }
+ }
+
+ if (writtenBytes < data.Length)
+ {
+ throw new InvalidOperationException("Encryption error.");
+ }
+
+ return output;
+ }
+ }
+}
diff --git a/Renci.SshNet/Security/Cryptography/Cipher.cs b/Renci.SshNet/Security/Cryptography/Cipher.cs
index ed41f0a..433e234 100644
--- a/Renci.SshNet/Security/Cryptography/Cipher.cs
+++ b/Renci.SshNet/Security/Cryptography/Cipher.cs
@@ -1,247 +1,244 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace Renci.SshNet.Security.Cryptography
-{
- ///
- /// Base class for cipher implementation.
- ///
- public abstract class Cipher
- {
- ///
- /// Gets the minimum data size.
- ///
- ///
- /// The minimum data size.
- ///
- public abstract byte MinimumSize { get; }
-
- ///
- /// Encrypts the specified input.
- ///
- /// The input.
- /// Encrypted data.
- public abstract byte[] Encrypt(byte[] input);
-
- ///
- /// Decrypts the specified input.
- ///
- /// The input.
- /// Decrypted data.
- public abstract byte[] Decrypt(byte[] input);
-
- #region Packing functions
-
- ///
- /// Populates buffer with big endian number representation.
- ///
- /// The number to convert.
- /// The buffer.
- protected static void UInt32ToBigEndian(uint number, byte[] buffer)
- {
- buffer[0] = (byte)(number >> 24);
- buffer[1] = (byte)(number >> 16);
- buffer[2] = (byte)(number >> 8);
- buffer[3] = (byte)(number);
- }
-
- ///
- /// Populates buffer with big endian number representation.
- ///
- /// The number to convert.
- /// The buffer.
- /// The buffer offset.
- protected static void UInt32ToBigEndian(uint number, byte[] buffer, int offset)
- {
- buffer[offset] = (byte)(number >> 24);
- buffer[offset + 1] = (byte)(number >> 16);
- buffer[offset + 2] = (byte)(number >> 8);
- buffer[offset + 3] = (byte)(number);
- }
-
- ///
- /// Converts big endian bytes into number.
- ///
- /// The buffer.
- /// Converted .
- protected static uint BigEndianToUInt32(byte[] buffer)
- {
- uint n = (uint)buffer[0] << 24;
- n |= (uint)buffer[1] << 16;
- n |= (uint)buffer[2] << 8;
- n |= (uint)buffer[3];
- return n;
- }
-
- ///
- /// Converts big endian bytes into number.
- ///
- /// The buffer.
- /// The buffer offset.
- /// Converted .
- protected static uint BigEndianToUInt32(byte[] buffer, int offset)
- {
- uint n = (uint)buffer[offset] << 24;
- n |= (uint)buffer[offset + 1] << 16;
- n |= (uint)buffer[offset + 2] << 8;
- n |= (uint)buffer[offset + 3];
- return n;
- }
-
- ///
- /// Converts big endian bytes into number.
- ///
- /// The buffer.
- /// Converted .
- protected static ulong BigEndianToUInt64(byte[] buffer)
- {
- uint hi = BigEndianToUInt32(buffer);
- uint lo = BigEndianToUInt32(buffer, 4);
- return ((ulong)hi << 32) | (ulong)lo;
- }
-
- ///
- /// Converts big endian bytes into number.
- ///
- /// The buffer.
- /// The buffer offset.
- /// Converted .
- protected static ulong BigEndianToUInt64(byte[] buffer, int offset)
- {
- uint hi = BigEndianToUInt32(buffer, offset);
- uint lo = BigEndianToUInt32(buffer, offset + 4);
- return ((ulong)hi << 32) | (ulong)lo;
- }
-
- ///
- /// Populates buffer with big endian number representation.
- ///
- /// The number to convert.
- /// The buffer.
- protected static void UInt64ToBigEndian(ulong number, byte[] buffer)
- {
- UInt32ToBigEndian((uint)(number >> 32), buffer);
- UInt32ToBigEndian((uint)(number), buffer, 4);
- }
-
- ///
- /// Populates buffer with big endian number representation.
- ///
- /// The number to convert.
- /// The buffer.
- /// The buffer offset.
- protected static void UInt64ToBigEndian(ulong number, byte[] buffer, int offset)
- {
- UInt32ToBigEndian((uint)(number >> 32), buffer, offset);
- UInt32ToBigEndian((uint)(number), buffer, offset + 4);
- }
-
- ///
- /// Populates buffer with little endian number representation.
- ///
- /// The number to convert.
- /// The buffer.
- protected static void UInt32ToLittleEndian(uint number, byte[] buffer)
- {
- buffer[0] = (byte)(number);
- buffer[1] = (byte)(number >> 8);
- buffer[2] = (byte)(number >> 16);
- buffer[3] = (byte)(number >> 24);
- }
-
- ///
- /// Populates buffer with little endian number representation.
- ///
- /// The number to convert.
- /// The buffer.
- /// The buffer offset.
- protected static void UInt32ToLittleEndian(uint number, byte[] buffer, int offset)
- {
- buffer[offset] = (byte)(number);
- buffer[offset + 1] = (byte)(number >> 8);
- buffer[offset + 2] = (byte)(number >> 16);
- buffer[offset + 3] = (byte)(number >> 24);
- }
-
- ///
- /// Converts little endian bytes into number.
- ///
- /// The buffer.
- /// Converted .
- protected static uint LittleEndianToUInt32(byte[] buffer)
- {
- uint n = (uint)buffer[0];
- n |= (uint)buffer[1] << 8;
- n |= (uint)buffer[2] << 16;
- n |= (uint)buffer[3] << 24;
- return n;
- }
-
- ///
- /// Converts little endian bytes into number.
- ///
- /// The buffer.
- /// The buffer offset.
- /// Converted .
- protected static uint LittleEndianToUInt32(byte[] buffer, int offset)
- {
- uint n = (uint)buffer[offset];
- n |= (uint)buffer[offset + 1] << 8;
- n |= (uint)buffer[offset + 2] << 16;
- n |= (uint)buffer[offset + 3] << 24;
- return n;
- }
-
- ///
- /// Converts little endian bytes into number.
- ///
- /// The buffer.
- /// Converted .
- protected static ulong LittleEndianToUInt64(byte[] buffer)
- {
- uint lo = LittleEndianToUInt32(buffer);
- uint hi = LittleEndianToUInt32(buffer, 4);
- return ((ulong)hi << 32) | (ulong)lo;
- }
-
- ///
- /// Converts little endian bytes into number.
- ///
- /// The buffer.
- /// The buffer offset.
- /// Converted .
- protected static ulong LittleEndianToUInt64(byte[] buffer, int offset)
- {
- uint lo = LittleEndianToUInt32(buffer, offset);
- uint hi = LittleEndianToUInt32(buffer, offset + 4);
- return ((ulong)hi << 32) | (ulong)lo;
- }
-
- ///
- /// Populates buffer with little endian number representation.
- ///
- /// The number to convert.
- /// The buffer.
- protected static void UInt64ToLittleEndian(ulong number, byte[] buffer)
- {
- UInt32ToLittleEndian((uint)(number), buffer);
- UInt32ToLittleEndian((uint)(number >> 32), buffer, 4);
- }
-
- ///
- /// Populates buffer with little endian number representation.
- ///
- /// The number to convert.
- /// The buffer.
- /// The buffer offset.
- protected static void UInt64ToLittleEndian(ulong number, byte[] buffer, int offset)
- {
- UInt32ToLittleEndian((uint)(number), buffer, offset);
- UInt32ToLittleEndian((uint)(number >> 32), buffer, offset + 4);
- }
-
- #endregion
- }
-}
+using System;
+
+namespace Renci.SshNet.Security.Cryptography
+{
+ ///
+ /// Base class for cipher implementation.
+ ///
+ public abstract class Cipher
+ {
+ ///
+ /// Gets the minimum data size.
+ ///
+ ///
+ /// The minimum data size.
+ ///
+ public abstract byte MinimumSize { get; }
+
+ ///
+ /// Encrypts the specified input.
+ ///
+ /// The input.
+ /// Encrypted data.
+ public abstract byte[] Encrypt(byte[] input);
+
+ ///
+ /// Decrypts the specified input.
+ ///
+ /// The input.
+ /// Decrypted data.
+ public abstract byte[] Decrypt(byte[] input);
+
+ #region Packing functions
+
+ ///
+ /// Populates buffer with big endian number representation.
+ ///
+ /// The number to convert.
+ /// The buffer.
+ protected static void UInt32ToBigEndian(uint number, byte[] buffer)
+ {
+ buffer[0] = (byte)(number >> 24);
+ buffer[1] = (byte)(number >> 16);
+ buffer[2] = (byte)(number >> 8);
+ buffer[3] = (byte)(number);
+ }
+
+ ///
+ /// Populates buffer with big endian number representation.
+ ///
+ /// The number to convert.
+ /// The buffer.
+ /// The buffer offset.
+ protected static void UInt32ToBigEndian(uint number, byte[] buffer, int offset)
+ {
+ buffer[offset] = (byte)(number >> 24);
+ buffer[offset + 1] = (byte)(number >> 16);
+ buffer[offset + 2] = (byte)(number >> 8);
+ buffer[offset + 3] = (byte)(number);
+ }
+
+ ///
+ /// Converts big endian bytes into number.
+ ///
+ /// The buffer.
+ /// Converted .
+ protected static uint BigEndianToUInt32(byte[] buffer)
+ {
+ uint n = (uint)buffer[0] << 24;
+ n |= (uint)buffer[1] << 16;
+ n |= (uint)buffer[2] << 8;
+ n |= (uint)buffer[3];
+ return n;
+ }
+
+ ///
+ /// Converts big endian bytes into number.
+ ///
+ /// The buffer.
+ /// The buffer offset.
+ /// Converted .
+ protected static uint BigEndianToUInt32(byte[] buffer, int offset)
+ {
+ uint n = (uint)buffer[offset] << 24;
+ n |= (uint)buffer[offset + 1] << 16;
+ n |= (uint)buffer[offset + 2] << 8;
+ n |= (uint)buffer[offset + 3];
+ return n;
+ }
+
+ ///
+ /// Converts big endian bytes into number.
+ ///
+ /// The buffer.
+ /// Converted .
+ protected static ulong BigEndianToUInt64(byte[] buffer)
+ {
+ uint hi = BigEndianToUInt32(buffer);
+ uint lo = BigEndianToUInt32(buffer, 4);
+ return ((ulong)hi << 32) | (ulong)lo;
+ }
+
+ ///
+ /// Converts big endian bytes into number.
+ ///
+ /// The buffer.
+ /// The buffer offset.
+ /// Converted .
+ protected static ulong BigEndianToUInt64(byte[] buffer, int offset)
+ {
+ uint hi = BigEndianToUInt32(buffer, offset);
+ uint lo = BigEndianToUInt32(buffer, offset + 4);
+ return ((ulong)hi << 32) | (ulong)lo;
+ }
+
+ ///
+ /// Populates buffer with big endian number representation.
+ ///
+ /// The number to convert.
+ /// The buffer.
+ protected static void UInt64ToBigEndian(ulong number, byte[] buffer)
+ {
+ UInt32ToBigEndian((uint)(number >> 32), buffer);
+ UInt32ToBigEndian((uint)(number), buffer, 4);
+ }
+
+ ///
+ /// Populates buffer with big endian number representation.
+ ///
+ /// The number to convert.
+ /// The buffer.
+ /// The buffer offset.
+ protected static void UInt64ToBigEndian(ulong number, byte[] buffer, int offset)
+ {
+ UInt32ToBigEndian((uint)(number >> 32), buffer, offset);
+ UInt32ToBigEndian((uint)(number), buffer, offset + 4);
+ }
+
+ ///
+ /// Populates buffer with little endian number representation.
+ ///
+ /// The number to convert.
+ /// The buffer.
+ protected static void UInt32ToLittleEndian(uint number, byte[] buffer)
+ {
+ buffer[0] = (byte)(number);
+ buffer[1] = (byte)(number >> 8);
+ buffer[2] = (byte)(number >> 16);
+ buffer[3] = (byte)(number >> 24);
+ }
+
+ ///
+ /// Populates buffer with little endian number representation.
+ ///
+ /// The number to convert.
+ /// The buffer.
+ /// The buffer offset.
+ protected static void UInt32ToLittleEndian(uint number, byte[] buffer, int offset)
+ {
+ buffer[offset] = (byte)(number);
+ buffer[offset + 1] = (byte)(number >> 8);
+ buffer[offset + 2] = (byte)(number >> 16);
+ buffer[offset + 3] = (byte)(number >> 24);
+ }
+
+ ///
+ /// Converts little endian bytes into number.
+ ///
+ /// The buffer.
+ /// Converted .
+ protected static uint LittleEndianToUInt32(byte[] buffer)
+ {
+ uint n = (uint)buffer[0];
+ n |= (uint)buffer[1] << 8;
+ n |= (uint)buffer[2] << 16;
+ n |= (uint)buffer[3] << 24;
+ return n;
+ }
+
+ ///
+ /// Converts little endian bytes into number.
+ ///
+ /// The buffer.
+ /// The buffer offset.
+ /// Converted .
+ protected static uint LittleEndianToUInt32(byte[] buffer, int offset)
+ {
+ uint n = (uint)buffer[offset];
+ n |= (uint)buffer[offset + 1] << 8;
+ n |= (uint)buffer[offset + 2] << 16;
+ n |= (uint)buffer[offset + 3] << 24;
+ return n;
+ }
+
+ ///
+ /// Converts little endian bytes into number.
+ ///
+ /// The buffer.
+ /// Converted .
+ protected static ulong LittleEndianToUInt64(byte[] buffer)
+ {
+ uint lo = LittleEndianToUInt32(buffer);
+ uint hi = LittleEndianToUInt32(buffer, 4);
+ return ((ulong)hi << 32) | (ulong)lo;
+ }
+
+ ///
+ /// Converts little endian bytes into number.
+ ///
+ /// The buffer.
+ /// The buffer offset.
+ /// Converted .
+ protected static ulong LittleEndianToUInt64(byte[] buffer, int offset)
+ {
+ uint lo = LittleEndianToUInt32(buffer, offset);
+ uint hi = LittleEndianToUInt32(buffer, offset + 4);
+ return ((ulong)hi << 32) | (ulong)lo;
+ }
+
+ ///
+ /// Populates buffer with little endian number representation.
+ ///
+ /// The number to convert.
+ /// The buffer.
+ protected static void UInt64ToLittleEndian(ulong number, byte[] buffer)
+ {
+ UInt32ToLittleEndian((uint)(number), buffer);
+ UInt32ToLittleEndian((uint)(number >> 32), buffer, 4);
+ }
+
+ ///
+ /// Populates buffer with little endian number representation.
+ ///
+ /// The number to convert.
+ /// The buffer.
+ /// The buffer offset.
+ protected static void UInt64ToLittleEndian(ulong number, byte[] buffer, int offset)
+ {
+ UInt32ToLittleEndian((uint)(number), buffer, offset);
+ UInt32ToLittleEndian((uint)(number >> 32), buffer, offset + 4);
+ }
+
+ #endregion
+ }
+}
diff --git a/Renci.SshNet/Security/Cryptography/CipherDigitalSignature.cs b/Renci.SshNet/Security/Cryptography/CipherDigitalSignature.cs
index 4e267cc..921b12e 100644
--- a/Renci.SshNet/Security/Cryptography/CipherDigitalSignature.cs
+++ b/Renci.SshNet/Security/Cryptography/CipherDigitalSignature.cs
@@ -1,99 +1,90 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Security.Cryptography;
-using Renci.SshNet.Common;
-
-namespace Renci.SshNet.Security.Cryptography
-{
- ///
- /// Implements digital signature where where asymmetric cipher is used,
- ///
- public abstract class CipherDigitalSignature : DigitalSignature
- {
- private AsymmetricCipher _cipher;
-
- private ObjectIdentifier _oid;
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The object identifier.
- /// The cipher.
- public CipherDigitalSignature(ObjectIdentifier oid, AsymmetricCipher cipher)
- {
- if (cipher == null)
- throw new ArgumentNullException("cipher");
-
- this._cipher = cipher;
- this._oid = oid;
- }
-
- ///
- /// Verifies the signature.
- ///
- /// The input.
- /// The signature.
- ///
- /// True if signature was successfully verified; otherwise false.
- ///
- public override bool Verify(byte[] input, byte[] signature)
- {
- var encryptedSignature = this._cipher.Decrypt(signature);
-
- var hashData = this.Hash(input);
-
- var expected = DerEncode(hashData);
-
- if (expected.SequenceEqual(encryptedSignature))
- return true;
- else
- return false;
- }
-
- ///
- /// Creates the signature.
- ///
- /// The input.
- ///
- /// Signed input data.
- ///
- public override byte[] Sign(byte[] input)
- {
- // Calculate hash value
- var hashData = this.Hash(input);
-
- // Calculate DER string
- var derEncodedHash = DerEncode(hashData);
-
- return this._cipher.Encrypt(derEncodedHash).TrimLeadingZero().ToArray();
- }
-
- ///
- /// Hashes the specified input.
- ///
- /// The input.
- /// Hashed data.
- protected abstract byte[] Hash(byte[] input);
-
- ///
- /// Encodes hash using DER.
- ///
- /// The hash data.
- /// DER Encoded byte array
- protected byte[] DerEncode(byte[] hashData)
- {
- var data = new DerData();
-
- var alg = new DerData();
- alg.Write(this._oid);
- alg.WriteNull();
-
- data.Write(alg);
- data.Write(hashData);
-
- return data.Encode();
- }
- }
-}
+using System;
+using System.Linq;
+using Renci.SshNet.Common;
+
+namespace Renci.SshNet.Security.Cryptography
+{
+ ///
+ /// Implements digital signature where where asymmetric cipher is used,
+ ///
+ public abstract class CipherDigitalSignature : DigitalSignature
+ {
+ private readonly AsymmetricCipher _cipher;
+
+ private readonly ObjectIdentifier _oid;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The object identifier.
+ /// The cipher.
+ public CipherDigitalSignature(ObjectIdentifier oid, AsymmetricCipher cipher)
+ {
+ if (cipher == null)
+ throw new ArgumentNullException("cipher");
+
+ this._cipher = cipher;
+ this._oid = oid;
+ }
+
+ ///
+ /// Verifies the signature.
+ ///
+ /// The input.
+ /// The signature.
+ ///
+ /// True if signature was successfully verified; otherwise false.
+ ///
+ public override bool Verify(byte[] input, byte[] signature)
+ {
+ var encryptedSignature = this._cipher.Decrypt(signature);
+ var hashData = this.Hash(input);
+ var expected = DerEncode(hashData);
+ return expected.SequenceEqual(encryptedSignature);
+ }
+
+ ///
+ /// Creates the signature.
+ ///
+ /// The input.
+ ///
+ /// Signed input data.
+ ///
+ public override byte[] Sign(byte[] input)
+ {
+ // Calculate hash value
+ var hashData = this.Hash(input);
+
+ // Calculate DER string
+ var derEncodedHash = DerEncode(hashData);
+
+ return this._cipher.Encrypt(derEncodedHash).TrimLeadingZero().ToArray();
+ }
+
+ ///
+ /// Hashes the specified input.
+ ///
+ /// The input.
+ /// Hashed data.
+ protected abstract byte[] Hash(byte[] input);
+
+ ///
+ /// Encodes hash using DER.
+ ///
+ /// The hash data.
+ /// DER Encoded byte array
+ protected byte[] DerEncode(byte[] hashData)
+ {
+ var data = new DerData();
+
+ var alg = new DerData();
+ alg.Write(this._oid);
+ alg.WriteNull();
+
+ data.Write(alg);
+ data.Write(hashData);
+
+ return data.Encode();
+ }
+ }
+}
diff --git a/Renci.SshNet/Security/Cryptography/Ciphers/AesCipher.cs b/Renci.SshNet/Security/Cryptography/Ciphers/AesCipher.cs
index a90e0a9..95b72cd 100644
--- a/Renci.SshNet/Security/Cryptography/Ciphers/AesCipher.cs
+++ b/Renci.SshNet/Security/Cryptography/Ciphers/AesCipher.cs
@@ -1,838 +1,835 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Globalization;
-
-namespace Renci.SshNet.Security.Cryptography.Ciphers
-{
- ///
- /// AES cipher implementation.
- ///
- public sealed class AesCipher : BlockCipher
- {
- private const uint m1 = 0x80808080;
-
- private const uint m2 = 0x7f7f7f7f;
-
- private const uint m3 = 0x0000001b;
-
- private int _rounds;
-
- private uint[] _encryptionKey;
-
- private uint[] _decryptionKey;
-
- private uint C0, C1, C2, C3;
-
- #region Static Definition Tables
-
- private static readonly byte[] S =
- {
- 99, 124, 119, 123, 242, 107, 111, 197,
- 48, 1, 103, 43, 254, 215, 171, 118,
- 202, 130, 201, 125, 250, 89, 71, 240,
- 173, 212, 162, 175, 156, 164, 114, 192,
- 183, 253, 147, 38, 54, 63, 247, 204,
- 52, 165, 229, 241, 113, 216, 49, 21,
- 4, 199, 35, 195, 24, 150, 5, 154,
- 7, 18, 128, 226, 235, 39, 178, 117,
- 9, 131, 44, 26, 27, 110, 90, 160,
- 82, 59, 214, 179, 41, 227, 47, 132,
- 83, 209, 0, 237, 32, 252, 177, 91,
- 106, 203, 190, 57, 74, 76, 88, 207,
- 208, 239, 170, 251, 67, 77, 51, 133,
- 69, 249, 2, 127, 80, 60, 159, 168,
- 81, 163, 64, 143, 146, 157, 56, 245,
- 188, 182, 218, 33, 16, 255, 243, 210,
- 205, 12, 19, 236, 95, 151, 68, 23,
- 196, 167, 126, 61, 100, 93, 25, 115,
- 96, 129, 79, 220, 34, 42, 144, 136,
- 70, 238, 184, 20, 222, 94, 11, 219,
- 224, 50, 58, 10, 73, 6, 36, 92,
- 194, 211, 172, 98, 145, 149, 228, 121,
- 231, 200, 55, 109, 141, 213, 78, 169,
- 108, 86, 244, 234, 101, 122, 174, 8,
- 186, 120, 37, 46, 28, 166, 180, 198,
- 232, 221, 116, 31, 75, 189, 139, 138,
- 112, 62, 181, 102, 72, 3, 246, 14,
- 97, 53, 87, 185, 134, 193, 29, 158,
- 225, 248, 152, 17, 105, 217, 142, 148,
- 155, 30, 135, 233, 206, 85, 40, 223,
- 140, 161, 137, 13, 191, 230, 66, 104,
- 65, 153, 45, 15, 176, 84, 187, 22,
- };
-
- // The inverse S-box
- private static readonly byte[] Si =
- {
- 82, 9, 106, 213, 48, 54, 165, 56,
- 191, 64, 163, 158, 129, 243, 215, 251,
- 124, 227, 57, 130, 155, 47, 255, 135,
- 52, 142, 67, 68, 196, 222, 233, 203,
- 84, 123, 148, 50, 166, 194, 35, 61,
- 238, 76, 149, 11, 66, 250, 195, 78,
- 8, 46, 161, 102, 40, 217, 36, 178,
- 118, 91, 162, 73, 109, 139, 209, 37,
- 114, 248, 246, 100, 134, 104, 152, 22,
- 212, 164, 92, 204, 93, 101, 182, 146,
- 108, 112, 72, 80, 253, 237, 185, 218,
- 94, 21, 70, 87, 167, 141, 157, 132,
- 144, 216, 171, 0, 140, 188, 211, 10,
- 247, 228, 88, 5, 184, 179, 69, 6,
- 208, 44, 30, 143, 202, 63, 15, 2,
- 193, 175, 189, 3, 1, 19, 138, 107,
- 58, 145, 17, 65, 79, 103, 220, 234,
- 151, 242, 207, 206, 240, 180, 230, 115,
- 150, 172, 116, 34, 231, 173, 53, 133,
- 226, 249, 55, 232, 28, 117, 223, 110,
- 71, 241, 26, 113, 29, 41, 197, 137,
- 111, 183, 98, 14, 170, 24, 190, 27,
- 252, 86, 62, 75, 198, 210, 121, 32,
- 154, 219, 192, 254, 120, 205, 90, 244,
- 31, 221, 168, 51, 136, 7, 199, 49,
- 177, 18, 16, 89, 39, 128, 236, 95,
- 96, 81, 127, 169, 25, 181, 74, 13,
- 45, 229, 122, 159, 147, 201, 156, 239,
- 160, 224, 59, 77, 174, 42, 245, 176,
- 200, 235, 187, 60, 131, 83, 153, 97,
- 23, 43, 4, 126, 186, 119, 214, 38,
- 225, 105, 20, 99, 85, 33, 12, 125,
- };
-
- // vector used in calculating key schedule (powers of x in GF(256))
- private static readonly byte[] rcon =
- {
- 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
- 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91
- };
-
- // precomputation tables of calculations for rounds
- private static readonly uint[] T0 =
- {
- 0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 0x0df2f2ff,
- 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591, 0x50303060, 0x03010102,
- 0xa96767ce, 0x7d2b2b56, 0x19fefee7, 0x62d7d7b5, 0xe6abab4d,
- 0x9a7676ec, 0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa,
- 0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb, 0xecadad41,
- 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45, 0xbf9c9c23, 0xf7a4a453,
- 0x967272e4, 0x5bc0c09b, 0xc2b7b775, 0x1cfdfde1, 0xae93933d,
- 0x6a26264c, 0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83,
- 0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x08f1f1f9, 0x937171e2,
- 0x73d8d8ab, 0x53313162, 0x3f15152a, 0x0c040408, 0x52c7c795,
- 0x65232346, 0x5ec3c39d, 0x28181830, 0xa1969637, 0x0f05050a,
- 0xb59a9a2f, 0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df,
- 0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea, 0x1b090912,
- 0x9e83831d, 0x742c2c58, 0x2e1a1a34, 0x2d1b1b36, 0xb26e6edc,
- 0xee5a5ab4, 0xfba0a05b, 0xf65252a4, 0x4d3b3b76, 0x61d6d6b7,
- 0xceb3b37d, 0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413,
- 0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1, 0x60202040,
- 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6, 0xbe6a6ad4, 0x46cbcb8d,
- 0xd9bebe67, 0x4b393972, 0xde4a4a94, 0xd44c4c98, 0xe85858b0,
- 0x4acfcf85, 0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed,
- 0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511, 0xcf45458a,
- 0x10f9f9e9, 0x06020204, 0x817f7ffe, 0xf05050a0, 0x443c3c78,
- 0xba9f9f25, 0xe3a8a84b, 0xf35151a2, 0xfea3a35d, 0xc0404080,
- 0x8a8f8f05, 0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1,
- 0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142, 0x30101020,
- 0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf, 0x4ccdcd81, 0x140c0c18,
- 0x35131326, 0x2fececc3, 0xe15f5fbe, 0xa2979735, 0xcc444488,
- 0x3917172e, 0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a,
- 0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6, 0xa06060c0,
- 0x98818119, 0xd14f4f9e, 0x7fdcdca3, 0x66222244, 0x7e2a2a54,
- 0xab90903b, 0x8388880b, 0xca46468c, 0x29eeeec7, 0xd3b8b86b,
- 0x3c141428, 0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad,
- 0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14, 0xdb494992,
- 0x0a06060c, 0x6c242448, 0xe45c5cb8, 0x5dc2c29f, 0x6ed3d3bd,
- 0xefacac43, 0xa66262c4, 0xa8919139, 0xa4959531, 0x37e4e4d3,
- 0x8b7979f2, 0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda,
- 0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949, 0xb46c6cd8,
- 0xfa5656ac, 0x07f4f4f3, 0x25eaeacf, 0xaf6565ca, 0x8e7a7af4,
- 0xe9aeae47, 0x18080810, 0xd5baba6f, 0x887878f0, 0x6f25254a,
- 0x722e2e5c, 0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697,
- 0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e, 0xdd4b4b96,
- 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f, 0x907070e0, 0x423e3e7c,
- 0xc4b5b571, 0xaa6666cc, 0xd8484890, 0x05030306, 0x01f6f6f7,
- 0x120e0e1c, 0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969,
- 0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27, 0x38e1e1d9,
- 0x13f8f8eb, 0xb398982b, 0x33111122, 0xbb6969d2, 0x70d9d9a9,
- 0x898e8e07, 0xa7949433, 0xb69b9b2d, 0x221e1e3c, 0x92878715,
- 0x20e9e9c9, 0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5,
- 0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, 0xdabfbf65,
- 0x31e6e6d7, 0xc6424284, 0xb86868d0, 0xc3414182, 0xb0999929,
- 0x772d2d5a, 0x110f0f1e, 0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d,
- 0x3a16162c
- };
-
- private static readonly uint[] T1 =
- {
- 0x6363c6a5, 0x7c7cf884, 0x7777ee99, 0x7b7bf68d, 0xf2f2ff0d,
- 0x6b6bd6bd, 0x6f6fdeb1, 0xc5c59154, 0x30306050, 0x01010203,
- 0x6767cea9, 0x2b2b567d, 0xfefee719, 0xd7d7b562, 0xabab4de6,
- 0x7676ec9a, 0xcaca8f45, 0x82821f9d, 0xc9c98940, 0x7d7dfa87,
- 0xfafaef15, 0x5959b2eb, 0x47478ec9, 0xf0f0fb0b, 0xadad41ec,
- 0xd4d4b367, 0xa2a25ffd, 0xafaf45ea, 0x9c9c23bf, 0xa4a453f7,
- 0x7272e496, 0xc0c09b5b, 0xb7b775c2, 0xfdfde11c, 0x93933dae,
- 0x26264c6a, 0x36366c5a, 0x3f3f7e41, 0xf7f7f502, 0xcccc834f,
- 0x3434685c, 0xa5a551f4, 0xe5e5d134, 0xf1f1f908, 0x7171e293,
- 0xd8d8ab73, 0x31316253, 0x15152a3f, 0x0404080c, 0xc7c79552,
- 0x23234665, 0xc3c39d5e, 0x18183028, 0x969637a1, 0x05050a0f,
- 0x9a9a2fb5, 0x07070e09, 0x12122436, 0x80801b9b, 0xe2e2df3d,
- 0xebebcd26, 0x27274e69, 0xb2b27fcd, 0x7575ea9f, 0x0909121b,
- 0x83831d9e, 0x2c2c5874, 0x1a1a342e, 0x1b1b362d, 0x6e6edcb2,
- 0x5a5ab4ee, 0xa0a05bfb, 0x5252a4f6, 0x3b3b764d, 0xd6d6b761,
- 0xb3b37dce, 0x2929527b, 0xe3e3dd3e, 0x2f2f5e71, 0x84841397,
- 0x5353a6f5, 0xd1d1b968, 0x00000000, 0xededc12c, 0x20204060,
- 0xfcfce31f, 0xb1b179c8, 0x5b5bb6ed, 0x6a6ad4be, 0xcbcb8d46,
- 0xbebe67d9, 0x3939724b, 0x4a4a94de, 0x4c4c98d4, 0x5858b0e8,
- 0xcfcf854a, 0xd0d0bb6b, 0xefefc52a, 0xaaaa4fe5, 0xfbfbed16,
- 0x434386c5, 0x4d4d9ad7, 0x33336655, 0x85851194, 0x45458acf,
- 0xf9f9e910, 0x02020406, 0x7f7ffe81, 0x5050a0f0, 0x3c3c7844,
- 0x9f9f25ba, 0xa8a84be3, 0x5151a2f3, 0xa3a35dfe, 0x404080c0,
- 0x8f8f058a, 0x92923fad, 0x9d9d21bc, 0x38387048, 0xf5f5f104,
- 0xbcbc63df, 0xb6b677c1, 0xdadaaf75, 0x21214263, 0x10102030,
- 0xffffe51a, 0xf3f3fd0e, 0xd2d2bf6d, 0xcdcd814c, 0x0c0c1814,
- 0x13132635, 0xececc32f, 0x5f5fbee1, 0x979735a2, 0x444488cc,
- 0x17172e39, 0xc4c49357, 0xa7a755f2, 0x7e7efc82, 0x3d3d7a47,
- 0x6464c8ac, 0x5d5dbae7, 0x1919322b, 0x7373e695, 0x6060c0a0,
- 0x81811998, 0x4f4f9ed1, 0xdcdca37f, 0x22224466, 0x2a2a547e,
- 0x90903bab, 0x88880b83, 0x46468cca, 0xeeeec729, 0xb8b86bd3,
- 0x1414283c, 0xdedea779, 0x5e5ebce2, 0x0b0b161d, 0xdbdbad76,
- 0xe0e0db3b, 0x32326456, 0x3a3a744e, 0x0a0a141e, 0x494992db,
- 0x06060c0a, 0x2424486c, 0x5c5cb8e4, 0xc2c29f5d, 0xd3d3bd6e,
- 0xacac43ef, 0x6262c4a6, 0x919139a8, 0x959531a4, 0xe4e4d337,
- 0x7979f28b, 0xe7e7d532, 0xc8c88b43, 0x37376e59, 0x6d6ddab7,
- 0x8d8d018c, 0xd5d5b164, 0x4e4e9cd2, 0xa9a949e0, 0x6c6cd8b4,
- 0x5656acfa, 0xf4f4f307, 0xeaeacf25, 0x6565caaf, 0x7a7af48e,
- 0xaeae47e9, 0x08081018, 0xbaba6fd5, 0x7878f088, 0x25254a6f,
- 0x2e2e5c72, 0x1c1c3824, 0xa6a657f1, 0xb4b473c7, 0xc6c69751,
- 0xe8e8cb23, 0xdddda17c, 0x7474e89c, 0x1f1f3e21, 0x4b4b96dd,
- 0xbdbd61dc, 0x8b8b0d86, 0x8a8a0f85, 0x7070e090, 0x3e3e7c42,
- 0xb5b571c4, 0x6666ccaa, 0x484890d8, 0x03030605, 0xf6f6f701,
- 0x0e0e1c12, 0x6161c2a3, 0x35356a5f, 0x5757aef9, 0xb9b969d0,
- 0x86861791, 0xc1c19958, 0x1d1d3a27, 0x9e9e27b9, 0xe1e1d938,
- 0xf8f8eb13, 0x98982bb3, 0x11112233, 0x6969d2bb, 0xd9d9a970,
- 0x8e8e0789, 0x949433a7, 0x9b9b2db6, 0x1e1e3c22, 0x87871592,
- 0xe9e9c920, 0xcece8749, 0x5555aaff, 0x28285078, 0xdfdfa57a,
- 0x8c8c038f, 0xa1a159f8, 0x89890980, 0x0d0d1a17, 0xbfbf65da,
- 0xe6e6d731, 0x424284c6, 0x6868d0b8, 0x414182c3, 0x999929b0,
- 0x2d2d5a77, 0x0f0f1e11, 0xb0b07bcb, 0x5454a8fc, 0xbbbb6dd6,
- 0x16162c3a
- };
-
- private static readonly uint[] T2 =
- {
- 0x63c6a563, 0x7cf8847c, 0x77ee9977, 0x7bf68d7b, 0xf2ff0df2,
- 0x6bd6bd6b, 0x6fdeb16f, 0xc59154c5, 0x30605030, 0x01020301,
- 0x67cea967, 0x2b567d2b, 0xfee719fe, 0xd7b562d7, 0xab4de6ab,
- 0x76ec9a76, 0xca8f45ca, 0x821f9d82, 0xc98940c9, 0x7dfa877d,
- 0xfaef15fa, 0x59b2eb59, 0x478ec947, 0xf0fb0bf0, 0xad41ecad,
- 0xd4b367d4, 0xa25ffda2, 0xaf45eaaf, 0x9c23bf9c, 0xa453f7a4,
- 0x72e49672, 0xc09b5bc0, 0xb775c2b7, 0xfde11cfd, 0x933dae93,
- 0x264c6a26, 0x366c5a36, 0x3f7e413f, 0xf7f502f7, 0xcc834fcc,
- 0x34685c34, 0xa551f4a5, 0xe5d134e5, 0xf1f908f1, 0x71e29371,
- 0xd8ab73d8, 0x31625331, 0x152a3f15, 0x04080c04, 0xc79552c7,
- 0x23466523, 0xc39d5ec3, 0x18302818, 0x9637a196, 0x050a0f05,
- 0x9a2fb59a, 0x070e0907, 0x12243612, 0x801b9b80, 0xe2df3de2,
- 0xebcd26eb, 0x274e6927, 0xb27fcdb2, 0x75ea9f75, 0x09121b09,
- 0x831d9e83, 0x2c58742c, 0x1a342e1a, 0x1b362d1b, 0x6edcb26e,
- 0x5ab4ee5a, 0xa05bfba0, 0x52a4f652, 0x3b764d3b, 0xd6b761d6,
- 0xb37dceb3, 0x29527b29, 0xe3dd3ee3, 0x2f5e712f, 0x84139784,
- 0x53a6f553, 0xd1b968d1, 0x00000000, 0xedc12ced, 0x20406020,
- 0xfce31ffc, 0xb179c8b1, 0x5bb6ed5b, 0x6ad4be6a, 0xcb8d46cb,
- 0xbe67d9be, 0x39724b39, 0x4a94de4a, 0x4c98d44c, 0x58b0e858,
- 0xcf854acf, 0xd0bb6bd0, 0xefc52aef, 0xaa4fe5aa, 0xfbed16fb,
- 0x4386c543, 0x4d9ad74d, 0x33665533, 0x85119485, 0x458acf45,
- 0xf9e910f9, 0x02040602, 0x7ffe817f, 0x50a0f050, 0x3c78443c,
- 0x9f25ba9f, 0xa84be3a8, 0x51a2f351, 0xa35dfea3, 0x4080c040,
- 0x8f058a8f, 0x923fad92, 0x9d21bc9d, 0x38704838, 0xf5f104f5,
- 0xbc63dfbc, 0xb677c1b6, 0xdaaf75da, 0x21426321, 0x10203010,
- 0xffe51aff, 0xf3fd0ef3, 0xd2bf6dd2, 0xcd814ccd, 0x0c18140c,
- 0x13263513, 0xecc32fec, 0x5fbee15f, 0x9735a297, 0x4488cc44,
- 0x172e3917, 0xc49357c4, 0xa755f2a7, 0x7efc827e, 0x3d7a473d,
- 0x64c8ac64, 0x5dbae75d, 0x19322b19, 0x73e69573, 0x60c0a060,
- 0x81199881, 0x4f9ed14f, 0xdca37fdc, 0x22446622, 0x2a547e2a,
- 0x903bab90, 0x880b8388, 0x468cca46, 0xeec729ee, 0xb86bd3b8,
- 0x14283c14, 0xdea779de, 0x5ebce25e, 0x0b161d0b, 0xdbad76db,
- 0xe0db3be0, 0x32645632, 0x3a744e3a, 0x0a141e0a, 0x4992db49,
- 0x060c0a06, 0x24486c24, 0x5cb8e45c, 0xc29f5dc2, 0xd3bd6ed3,
- 0xac43efac, 0x62c4a662, 0x9139a891, 0x9531a495, 0xe4d337e4,
- 0x79f28b79, 0xe7d532e7, 0xc88b43c8, 0x376e5937, 0x6ddab76d,
- 0x8d018c8d, 0xd5b164d5, 0x4e9cd24e, 0xa949e0a9, 0x6cd8b46c,
- 0x56acfa56, 0xf4f307f4, 0xeacf25ea, 0x65caaf65, 0x7af48e7a,
- 0xae47e9ae, 0x08101808, 0xba6fd5ba, 0x78f08878, 0x254a6f25,
- 0x2e5c722e, 0x1c38241c, 0xa657f1a6, 0xb473c7b4, 0xc69751c6,
- 0xe8cb23e8, 0xdda17cdd, 0x74e89c74, 0x1f3e211f, 0x4b96dd4b,
- 0xbd61dcbd, 0x8b0d868b, 0x8a0f858a, 0x70e09070, 0x3e7c423e,
- 0xb571c4b5, 0x66ccaa66, 0x4890d848, 0x03060503, 0xf6f701f6,
- 0x0e1c120e, 0x61c2a361, 0x356a5f35, 0x57aef957, 0xb969d0b9,
- 0x86179186, 0xc19958c1, 0x1d3a271d, 0x9e27b99e, 0xe1d938e1,
- 0xf8eb13f8, 0x982bb398, 0x11223311, 0x69d2bb69, 0xd9a970d9,
- 0x8e07898e, 0x9433a794, 0x9b2db69b, 0x1e3c221e, 0x87159287,
- 0xe9c920e9, 0xce8749ce, 0x55aaff55, 0x28507828, 0xdfa57adf,
- 0x8c038f8c, 0xa159f8a1, 0x89098089, 0x0d1a170d, 0xbf65dabf,
- 0xe6d731e6, 0x4284c642, 0x68d0b868, 0x4182c341, 0x9929b099,
- 0x2d5a772d, 0x0f1e110f, 0xb07bcbb0, 0x54a8fc54, 0xbb6dd6bb,
- 0x162c3a16
- };
-
- private static readonly uint[] T3 =
- {
- 0xc6a56363, 0xf8847c7c, 0xee997777, 0xf68d7b7b, 0xff0df2f2,
- 0xd6bd6b6b, 0xdeb16f6f, 0x9154c5c5, 0x60503030, 0x02030101,
- 0xcea96767, 0x567d2b2b, 0xe719fefe, 0xb562d7d7, 0x4de6abab,
- 0xec9a7676, 0x8f45caca, 0x1f9d8282, 0x8940c9c9, 0xfa877d7d,
- 0xef15fafa, 0xb2eb5959, 0x8ec94747, 0xfb0bf0f0, 0x41ecadad,
- 0xb367d4d4, 0x5ffda2a2, 0x45eaafaf, 0x23bf9c9c, 0x53f7a4a4,
- 0xe4967272, 0x9b5bc0c0, 0x75c2b7b7, 0xe11cfdfd, 0x3dae9393,
- 0x4c6a2626, 0x6c5a3636, 0x7e413f3f, 0xf502f7f7, 0x834fcccc,
- 0x685c3434, 0x51f4a5a5, 0xd134e5e5, 0xf908f1f1, 0xe2937171,
- 0xab73d8d8, 0x62533131, 0x2a3f1515, 0x080c0404, 0x9552c7c7,
- 0x46652323, 0x9d5ec3c3, 0x30281818, 0x37a19696, 0x0a0f0505,
- 0x2fb59a9a, 0x0e090707, 0x24361212, 0x1b9b8080, 0xdf3de2e2,
- 0xcd26ebeb, 0x4e692727, 0x7fcdb2b2, 0xea9f7575, 0x121b0909,
- 0x1d9e8383, 0x58742c2c, 0x342e1a1a, 0x362d1b1b, 0xdcb26e6e,
- 0xb4ee5a5a, 0x5bfba0a0, 0xa4f65252, 0x764d3b3b, 0xb761d6d6,
- 0x7dceb3b3, 0x527b2929, 0xdd3ee3e3, 0x5e712f2f, 0x13978484,
- 0xa6f55353, 0xb968d1d1, 0x00000000, 0xc12ceded, 0x40602020,
- 0xe31ffcfc, 0x79c8b1b1, 0xb6ed5b5b, 0xd4be6a6a, 0x8d46cbcb,
- 0x67d9bebe, 0x724b3939, 0x94de4a4a, 0x98d44c4c, 0xb0e85858,
- 0x854acfcf, 0xbb6bd0d0, 0xc52aefef, 0x4fe5aaaa, 0xed16fbfb,
- 0x86c54343, 0x9ad74d4d, 0x66553333, 0x11948585, 0x8acf4545,
- 0xe910f9f9, 0x04060202, 0xfe817f7f, 0xa0f05050, 0x78443c3c,
- 0x25ba9f9f, 0x4be3a8a8, 0xa2f35151, 0x5dfea3a3, 0x80c04040,
- 0x058a8f8f, 0x3fad9292, 0x21bc9d9d, 0x70483838, 0xf104f5f5,
- 0x63dfbcbc, 0x77c1b6b6, 0xaf75dada, 0x42632121, 0x20301010,
- 0xe51affff, 0xfd0ef3f3, 0xbf6dd2d2, 0x814ccdcd, 0x18140c0c,
- 0x26351313, 0xc32fecec, 0xbee15f5f, 0x35a29797, 0x88cc4444,
- 0x2e391717, 0x9357c4c4, 0x55f2a7a7, 0xfc827e7e, 0x7a473d3d,
- 0xc8ac6464, 0xbae75d5d, 0x322b1919, 0xe6957373, 0xc0a06060,
- 0x19988181, 0x9ed14f4f, 0xa37fdcdc, 0x44662222, 0x547e2a2a,
- 0x3bab9090, 0x0b838888, 0x8cca4646, 0xc729eeee, 0x6bd3b8b8,
- 0x283c1414, 0xa779dede, 0xbce25e5e, 0x161d0b0b, 0xad76dbdb,
- 0xdb3be0e0, 0x64563232, 0x744e3a3a, 0x141e0a0a, 0x92db4949,
- 0x0c0a0606, 0x486c2424, 0xb8e45c5c, 0x9f5dc2c2, 0xbd6ed3d3,
- 0x43efacac, 0xc4a66262, 0x39a89191, 0x31a49595, 0xd337e4e4,
- 0xf28b7979, 0xd532e7e7, 0x8b43c8c8, 0x6e593737, 0xdab76d6d,
- 0x018c8d8d, 0xb164d5d5, 0x9cd24e4e, 0x49e0a9a9, 0xd8b46c6c,
- 0xacfa5656, 0xf307f4f4, 0xcf25eaea, 0xcaaf6565, 0xf48e7a7a,
- 0x47e9aeae, 0x10180808, 0x6fd5baba, 0xf0887878, 0x4a6f2525,
- 0x5c722e2e, 0x38241c1c, 0x57f1a6a6, 0x73c7b4b4, 0x9751c6c6,
- 0xcb23e8e8, 0xa17cdddd, 0xe89c7474, 0x3e211f1f, 0x96dd4b4b,
- 0x61dcbdbd, 0x0d868b8b, 0x0f858a8a, 0xe0907070, 0x7c423e3e,
- 0x71c4b5b5, 0xccaa6666, 0x90d84848, 0x06050303, 0xf701f6f6,
- 0x1c120e0e, 0xc2a36161, 0x6a5f3535, 0xaef95757, 0x69d0b9b9,
- 0x17918686, 0x9958c1c1, 0x3a271d1d, 0x27b99e9e, 0xd938e1e1,
- 0xeb13f8f8, 0x2bb39898, 0x22331111, 0xd2bb6969, 0xa970d9d9,
- 0x07898e8e, 0x33a79494, 0x2db69b9b, 0x3c221e1e, 0x15928787,
- 0xc920e9e9, 0x8749cece, 0xaaff5555, 0x50782828, 0xa57adfdf,
- 0x038f8c8c, 0x59f8a1a1, 0x09808989, 0x1a170d0d, 0x65dabfbf,
- 0xd731e6e6, 0x84c64242, 0xd0b86868, 0x82c34141, 0x29b09999,
- 0x5a772d2d, 0x1e110f0f, 0x7bcbb0b0, 0xa8fc5454, 0x6dd6bbbb,
- 0x2c3a1616
- };
-
- private static readonly uint[] Tinv0 =
- {
- 0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a, 0xcb6bab3b,
- 0xf1459d1f, 0xab58faac, 0x9303e34b, 0x55fa3020, 0xf66d76ad,
- 0x9176cc88, 0x254c02f5, 0xfcd7e54f, 0xd7cb2ac5, 0x80443526,
- 0x8fa362b5, 0x495ab1de, 0x671bba25, 0x980eea45, 0xe1c0fe5d,
- 0x02752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b, 0xe75f8f03,
- 0x959c9215, 0xeb7a6dbf, 0xda595295, 0x2d83bed4, 0xd3217458,
- 0x2969e049, 0x44c8c98e, 0x6a89c275, 0x78798ef4, 0x6b3e5899,
- 0xdd71b927, 0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d,
- 0x184adf63, 0x82311ae5, 0x60335197, 0x457f5362, 0xe07764b1,
- 0x84ae6bbb, 0x1ca081fe, 0x942b08f9, 0x58684870, 0x19fd458f,
- 0x876cde94, 0xb7f87b52, 0x23d373ab, 0xe2024b72, 0x578f1fe3,
- 0x2aab5566, 0x0728ebb2, 0x03c2b52f, 0x9a7bc586, 0xa50837d3,
- 0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed, 0x2b1ccf8a,
- 0x92b479a7, 0xf0f207f3, 0xa1e2694e, 0xcdf4da65, 0xd5be0506,
- 0x1f6234d1, 0x8afea6c4, 0x9d532e34, 0xa055f3a2, 0x32e18a05,
- 0x75ebf6a4, 0x39ec830b, 0xaaef6040, 0x069f715e, 0x51106ebd,
- 0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d, 0xb58d5491,
- 0x055dc471, 0x6fd40604, 0xff155060, 0x24fb9819, 0x97e9bdd6,
- 0xcc434089, 0x779ed967, 0xbd42e8b0, 0x888b8907, 0x385b19e7,
- 0xdbeec879, 0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x00000000,
- 0x83868009, 0x48ed2b32, 0xac70111e, 0x4e725a6c, 0xfbff0efd,
- 0x5638850f, 0x1ed5ae3d, 0x27392d36, 0x64d90f0a, 0x21a65c68,
- 0xd1545b9b, 0x3a2e3624, 0xb1670a0c, 0x0fe75793, 0xd296eeb4,
- 0x9e919b1b, 0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c,
- 0x0aba93e2, 0xe52aa0c0, 0x43e0223c, 0x1d171b12, 0x0b0d090e,
- 0xadc78bf2, 0xb9a8b62d, 0xc8a91e14, 0x8519f157, 0x4c0775af,
- 0xbbdd99ee, 0xfd607fa3, 0x9f2601f7, 0xbcf5725c, 0xc53b6644,
- 0x347efb5b, 0x7629438b, 0xdcc623cb, 0x68fcedb6, 0x63f1e4b8,
- 0xcadc31d7, 0x10856342, 0x40229713, 0x2011c684, 0x7d244a85,
- 0xf83dbbd2, 0x1132f9ae, 0x6da129c7, 0x4b2f9e1d, 0xf330b2dc,
- 0xec52860d, 0xd0e3c177, 0x6c16b32b, 0x99b970a9, 0xfa489411,
- 0x2264e947, 0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, 0xef903322,
- 0xc74e4987, 0xc1d138d9, 0xfea2ca8c, 0x360bd498, 0xcf81f5a6,
- 0x28de7aa5, 0x268eb7da, 0xa4bfad3f, 0xe49d3a2c, 0x0d927850,
- 0x9bcc5f6a, 0x62467e54, 0xc2138df6, 0xe8b8d890, 0x5ef7392e,
- 0xf5afc382, 0xbe805d9f, 0x7c93d069, 0xa92dd56f, 0xb31225cf,
- 0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb, 0x097826cd,
- 0xf418596e, 0x01b79aec, 0xa89a4f83, 0x656e95e6, 0x7ee6ffaa,
- 0x08cfbc21, 0xe6e815ef, 0xd99be7ba, 0xce366f4a, 0xd4099fea,
- 0xd67cb029, 0xafb2a431, 0x31233f2a, 0x3094a5c6, 0xc066a235,
- 0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733, 0x4a9804f1,
- 0xf7daec41, 0x0e50cd7f, 0x2ff69117, 0x8dd64d76, 0x4db0ef43,
- 0x544daacc, 0xdf0496e4, 0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1,
- 0x7f516546, 0x04ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb,
- 0x5a1d67b3, 0x52d2db92, 0x335610e9, 0x1347d66d, 0x8c61d79a,
- 0x7a0ca137, 0x8e14f859, 0x893c13eb, 0xee27a9ce, 0x35c961b7,
- 0xede51ce1, 0x3cb1477a, 0x59dfd29c, 0x3f73f255, 0x79ce1418,
- 0xbf37c773, 0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478,
- 0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2, 0x72c31d16,
- 0x0c25e2bc, 0x8b493c28, 0x41950dff, 0x7101a839, 0xdeb30c08,
- 0x9ce4b4d8, 0x90c15664, 0x6184cb7b, 0x70b632d5, 0x745c6c48,
- 0x4257b8d0
- };
-
- private static readonly uint[] Tinv1 =
- {
- 0xa7f45150, 0x65417e53, 0xa4171ac3, 0x5e273a96, 0x6bab3bcb,
- 0x459d1ff1, 0x58faacab, 0x03e34b93, 0xfa302055, 0x6d76adf6,
- 0x76cc8891, 0x4c02f525, 0xd7e54ffc, 0xcb2ac5d7, 0x44352680,
- 0xa362b58f, 0x5ab1de49, 0x1bba2567, 0x0eea4598, 0xc0fe5de1,
- 0x752fc302, 0xf04c8112, 0x97468da3, 0xf9d36bc6, 0x5f8f03e7,
- 0x9c921595, 0x7a6dbfeb, 0x595295da, 0x83bed42d, 0x217458d3,
- 0x69e04929, 0xc8c98e44, 0x89c2756a, 0x798ef478, 0x3e58996b,
- 0x71b927dd, 0x4fe1beb6, 0xad88f017, 0xac20c966, 0x3ace7db4,
- 0x4adf6318, 0x311ae582, 0x33519760, 0x7f536245, 0x7764b1e0,
- 0xae6bbb84, 0xa081fe1c, 0x2b08f994, 0x68487058, 0xfd458f19,
- 0x6cde9487, 0xf87b52b7, 0xd373ab23, 0x024b72e2, 0x8f1fe357,
- 0xab55662a, 0x28ebb207, 0xc2b52f03, 0x7bc5869a, 0x0837d3a5,
- 0x872830f2, 0xa5bf23b2, 0x6a0302ba, 0x8216ed5c, 0x1ccf8a2b,
- 0xb479a792, 0xf207f3f0, 0xe2694ea1, 0xf4da65cd, 0xbe0506d5,
- 0x6234d11f, 0xfea6c48a, 0x532e349d, 0x55f3a2a0, 0xe18a0532,
- 0xebf6a475, 0xec830b39, 0xef6040aa, 0x9f715e06, 0x106ebd51,
- 0x8a213ef9, 0x06dd963d, 0x053eddae, 0xbde64d46, 0x8d5491b5,
- 0x5dc47105, 0xd406046f, 0x155060ff, 0xfb981924, 0xe9bdd697,
- 0x434089cc, 0x9ed96777, 0x42e8b0bd, 0x8b890788, 0x5b19e738,
- 0xeec879db, 0x0a7ca147, 0x0f427ce9, 0x1e84f8c9, 0x00000000,
- 0x86800983, 0xed2b3248, 0x70111eac, 0x725a6c4e, 0xff0efdfb,
- 0x38850f56, 0xd5ae3d1e, 0x392d3627, 0xd90f0a64, 0xa65c6821,
- 0x545b9bd1, 0x2e36243a, 0x670a0cb1, 0xe757930f, 0x96eeb4d2,
- 0x919b1b9e, 0xc5c0804f, 0x20dc61a2, 0x4b775a69, 0x1a121c16,
- 0xba93e20a, 0x2aa0c0e5, 0xe0223c43, 0x171b121d, 0x0d090e0b,
- 0xc78bf2ad, 0xa8b62db9, 0xa91e14c8, 0x19f15785, 0x0775af4c,
- 0xdd99eebb, 0x607fa3fd, 0x2601f79f, 0xf5725cbc, 0x3b6644c5,
- 0x7efb5b34, 0x29438b76, 0xc623cbdc, 0xfcedb668, 0xf1e4b863,
- 0xdc31d7ca, 0x85634210, 0x22971340, 0x11c68420, 0x244a857d,
- 0x3dbbd2f8, 0x32f9ae11, 0xa129c76d, 0x2f9e1d4b, 0x30b2dcf3,
- 0x52860dec, 0xe3c177d0, 0x16b32b6c, 0xb970a999, 0x489411fa,
- 0x64e94722, 0x8cfca8c4, 0x3ff0a01a, 0x2c7d56d8, 0x903322ef,
- 0x4e4987c7, 0xd138d9c1, 0xa2ca8cfe, 0x0bd49836, 0x81f5a6cf,
- 0xde7aa528, 0x8eb7da26, 0xbfad3fa4, 0x9d3a2ce4, 0x9278500d,
- 0xcc5f6a9b, 0x467e5462, 0x138df6c2, 0xb8d890e8, 0xf7392e5e,
- 0xafc382f5, 0x805d9fbe, 0x93d0697c, 0x2dd56fa9, 0x1225cfb3,
- 0x99acc83b, 0x7d1810a7, 0x639ce86e, 0xbb3bdb7b, 0x7826cd09,
- 0x18596ef4, 0xb79aec01, 0x9a4f83a8, 0x6e95e665, 0xe6ffaa7e,
- 0xcfbc2108, 0xe815efe6, 0x9be7bad9, 0x366f4ace, 0x099fead4,
- 0x7cb029d6, 0xb2a431af, 0x233f2a31, 0x94a5c630, 0x66a235c0,
- 0xbc4e7437, 0xca82fca6, 0xd090e0b0, 0xd8a73315, 0x9804f14a,
- 0xdaec41f7, 0x50cd7f0e, 0xf691172f, 0xd64d768d, 0xb0ef434d,
- 0x4daacc54, 0x0496e4df, 0xb5d19ee3, 0x886a4c1b, 0x1f2cc1b8,
- 0x5165467f, 0xea5e9d04, 0x358c015d, 0x7487fa73, 0x410bfb2e,
- 0x1d67b35a, 0xd2db9252, 0x5610e933, 0x47d66d13, 0x61d79a8c,
- 0x0ca1377a, 0x14f8598e, 0x3c13eb89, 0x27a9ceee, 0xc961b735,
- 0xe51ce1ed, 0xb1477a3c, 0xdfd29c59, 0x73f2553f, 0xce141879,
- 0x37c773bf, 0xcdf753ea, 0xaafd5f5b, 0x6f3ddf14, 0xdb447886,
- 0xf3afca81, 0xc468b93e, 0x3424382c, 0x40a3c25f, 0xc31d1672,
- 0x25e2bc0c, 0x493c288b, 0x950dff41, 0x01a83971, 0xb30c08de,
- 0xe4b4d89c, 0xc1566490, 0x84cb7b61, 0xb632d570, 0x5c6c4874,
- 0x57b8d042
- };
-
- private static readonly uint[] Tinv2 =
- {
- 0xf45150a7, 0x417e5365, 0x171ac3a4, 0x273a965e, 0xab3bcb6b,
- 0x9d1ff145, 0xfaacab58, 0xe34b9303, 0x302055fa, 0x76adf66d,
- 0xcc889176, 0x02f5254c, 0xe54ffcd7, 0x2ac5d7cb, 0x35268044,
- 0x62b58fa3, 0xb1de495a, 0xba25671b, 0xea45980e, 0xfe5de1c0,
- 0x2fc30275, 0x4c8112f0, 0x468da397, 0xd36bc6f9, 0x8f03e75f,
- 0x9215959c, 0x6dbfeb7a, 0x5295da59, 0xbed42d83, 0x7458d321,
- 0xe0492969, 0xc98e44c8, 0xc2756a89, 0x8ef47879, 0x58996b3e,
- 0xb927dd71, 0xe1beb64f, 0x88f017ad, 0x20c966ac, 0xce7db43a,
- 0xdf63184a, 0x1ae58231, 0x51976033, 0x5362457f, 0x64b1e077,
- 0x6bbb84ae, 0x81fe1ca0, 0x08f9942b, 0x48705868, 0x458f19fd,
- 0xde94876c, 0x7b52b7f8, 0x73ab23d3, 0x4b72e202, 0x1fe3578f,
- 0x55662aab, 0xebb20728, 0xb52f03c2, 0xc5869a7b, 0x37d3a508,
- 0x2830f287, 0xbf23b2a5, 0x0302ba6a, 0x16ed5c82, 0xcf8a2b1c,
- 0x79a792b4, 0x07f3f0f2, 0x694ea1e2, 0xda65cdf4, 0x0506d5be,
- 0x34d11f62, 0xa6c48afe, 0x2e349d53, 0xf3a2a055, 0x8a0532e1,
- 0xf6a475eb, 0x830b39ec, 0x6040aaef, 0x715e069f, 0x6ebd5110,
- 0x213ef98a, 0xdd963d06, 0x3eddae05, 0xe64d46bd, 0x5491b58d,
- 0xc471055d, 0x06046fd4, 0x5060ff15, 0x981924fb, 0xbdd697e9,
- 0x4089cc43, 0xd967779e, 0xe8b0bd42, 0x8907888b, 0x19e7385b,
- 0xc879dbee, 0x7ca1470a, 0x427ce90f, 0x84f8c91e, 0x00000000,
- 0x80098386, 0x2b3248ed, 0x111eac70, 0x5a6c4e72, 0x0efdfbff,
- 0x850f5638, 0xae3d1ed5, 0x2d362739, 0x0f0a64d9, 0x5c6821a6,
- 0x5b9bd154, 0x36243a2e, 0x0a0cb167, 0x57930fe7, 0xeeb4d296,
- 0x9b1b9e91, 0xc0804fc5, 0xdc61a220, 0x775a694b, 0x121c161a,
- 0x93e20aba, 0xa0c0e52a, 0x223c43e0, 0x1b121d17, 0x090e0b0d,
- 0x8bf2adc7, 0xb62db9a8, 0x1e14c8a9, 0xf1578519, 0x75af4c07,
- 0x99eebbdd, 0x7fa3fd60, 0x01f79f26, 0x725cbcf5, 0x6644c53b,
- 0xfb5b347e, 0x438b7629, 0x23cbdcc6, 0xedb668fc, 0xe4b863f1,
- 0x31d7cadc, 0x63421085, 0x97134022, 0xc6842011, 0x4a857d24,
- 0xbbd2f83d, 0xf9ae1132, 0x29c76da1, 0x9e1d4b2f, 0xb2dcf330,
- 0x860dec52, 0xc177d0e3, 0xb32b6c16, 0x70a999b9, 0x9411fa48,
- 0xe9472264, 0xfca8c48c, 0xf0a01a3f, 0x7d56d82c, 0x3322ef90,
- 0x4987c74e, 0x38d9c1d1, 0xca8cfea2, 0xd498360b, 0xf5a6cf81,
- 0x7aa528de, 0xb7da268e, 0xad3fa4bf, 0x3a2ce49d, 0x78500d92,
- 0x5f6a9bcc, 0x7e546246, 0x8df6c213, 0xd890e8b8, 0x392e5ef7,
- 0xc382f5af, 0x5d9fbe80, 0xd0697c93, 0xd56fa92d, 0x25cfb312,
- 0xacc83b99, 0x1810a77d, 0x9ce86e63, 0x3bdb7bbb, 0x26cd0978,
- 0x596ef418, 0x9aec01b7, 0x4f83a89a, 0x95e6656e, 0xffaa7ee6,
- 0xbc2108cf, 0x15efe6e8, 0xe7bad99b, 0x6f4ace36, 0x9fead409,
- 0xb029d67c, 0xa431afb2, 0x3f2a3123, 0xa5c63094, 0xa235c066,
- 0x4e7437bc, 0x82fca6ca, 0x90e0b0d0, 0xa73315d8, 0x04f14a98,
- 0xec41f7da, 0xcd7f0e50, 0x91172ff6, 0x4d768dd6, 0xef434db0,
- 0xaacc544d, 0x96e4df04, 0xd19ee3b5, 0x6a4c1b88, 0x2cc1b81f,
- 0x65467f51, 0x5e9d04ea, 0x8c015d35, 0x87fa7374, 0x0bfb2e41,
- 0x67b35a1d, 0xdb9252d2, 0x10e93356, 0xd66d1347, 0xd79a8c61,
- 0xa1377a0c, 0xf8598e14, 0x13eb893c, 0xa9ceee27, 0x61b735c9,
- 0x1ce1ede5, 0x477a3cb1, 0xd29c59df, 0xf2553f73, 0x141879ce,
- 0xc773bf37, 0xf753eacd, 0xfd5f5baa, 0x3ddf146f, 0x447886db,
- 0xafca81f3, 0x68b93ec4, 0x24382c34, 0xa3c25f40, 0x1d1672c3,
- 0xe2bc0c25, 0x3c288b49, 0x0dff4195, 0xa8397101, 0x0c08deb3,
- 0xb4d89ce4, 0x566490c1, 0xcb7b6184, 0x32d570b6, 0x6c48745c,
- 0xb8d04257
- };
-
- private static readonly uint[] Tinv3 =
- {
- 0x5150a7f4, 0x7e536541, 0x1ac3a417, 0x3a965e27, 0x3bcb6bab,
- 0x1ff1459d, 0xacab58fa, 0x4b9303e3, 0x2055fa30, 0xadf66d76,
- 0x889176cc, 0xf5254c02, 0x4ffcd7e5, 0xc5d7cb2a, 0x26804435,
- 0xb58fa362, 0xde495ab1, 0x25671bba, 0x45980eea, 0x5de1c0fe,
- 0xc302752f, 0x8112f04c, 0x8da39746, 0x6bc6f9d3, 0x03e75f8f,
- 0x15959c92, 0xbfeb7a6d, 0x95da5952, 0xd42d83be, 0x58d32174,
- 0x492969e0, 0x8e44c8c9, 0x756a89c2, 0xf478798e, 0x996b3e58,
- 0x27dd71b9, 0xbeb64fe1, 0xf017ad88, 0xc966ac20, 0x7db43ace,
- 0x63184adf, 0xe582311a, 0x97603351, 0x62457f53, 0xb1e07764,
- 0xbb84ae6b, 0xfe1ca081, 0xf9942b08, 0x70586848, 0x8f19fd45,
- 0x94876cde, 0x52b7f87b, 0xab23d373, 0x72e2024b, 0xe3578f1f,
- 0x662aab55, 0xb20728eb, 0x2f03c2b5, 0x869a7bc5, 0xd3a50837,
- 0x30f28728, 0x23b2a5bf, 0x02ba6a03, 0xed5c8216, 0x8a2b1ccf,
- 0xa792b479, 0xf3f0f207, 0x4ea1e269, 0x65cdf4da, 0x06d5be05,
- 0xd11f6234, 0xc48afea6, 0x349d532e, 0xa2a055f3, 0x0532e18a,
- 0xa475ebf6, 0x0b39ec83, 0x40aaef60, 0x5e069f71, 0xbd51106e,
- 0x3ef98a21, 0x963d06dd, 0xddae053e, 0x4d46bde6, 0x91b58d54,
- 0x71055dc4, 0x046fd406, 0x60ff1550, 0x1924fb98, 0xd697e9bd,
- 0x89cc4340, 0x67779ed9, 0xb0bd42e8, 0x07888b89, 0xe7385b19,
- 0x79dbeec8, 0xa1470a7c, 0x7ce90f42, 0xf8c91e84, 0x00000000,
- 0x09838680, 0x3248ed2b, 0x1eac7011, 0x6c4e725a, 0xfdfbff0e,
- 0x0f563885, 0x3d1ed5ae, 0x3627392d, 0x0a64d90f, 0x6821a65c,
- 0x9bd1545b, 0x243a2e36, 0x0cb1670a, 0x930fe757, 0xb4d296ee,
- 0x1b9e919b, 0x804fc5c0, 0x61a220dc, 0x5a694b77, 0x1c161a12,
- 0xe20aba93, 0xc0e52aa0, 0x3c43e022, 0x121d171b, 0x0e0b0d09,
- 0xf2adc78b, 0x2db9a8b6, 0x14c8a91e, 0x578519f1, 0xaf4c0775,
- 0xeebbdd99, 0xa3fd607f, 0xf79f2601, 0x5cbcf572, 0x44c53b66,
- 0x5b347efb, 0x8b762943, 0xcbdcc623, 0xb668fced, 0xb863f1e4,
- 0xd7cadc31, 0x42108563, 0x13402297, 0x842011c6, 0x857d244a,
- 0xd2f83dbb, 0xae1132f9, 0xc76da129, 0x1d4b2f9e, 0xdcf330b2,
- 0x0dec5286, 0x77d0e3c1, 0x2b6c16b3, 0xa999b970, 0x11fa4894,
- 0x472264e9, 0xa8c48cfc, 0xa01a3ff0, 0x56d82c7d, 0x22ef9033,
- 0x87c74e49, 0xd9c1d138, 0x8cfea2ca, 0x98360bd4, 0xa6cf81f5,
- 0xa528de7a, 0xda268eb7, 0x3fa4bfad, 0x2ce49d3a, 0x500d9278,
- 0x6a9bcc5f, 0x5462467e, 0xf6c2138d, 0x90e8b8d8, 0x2e5ef739,
- 0x82f5afc3, 0x9fbe805d, 0x697c93d0, 0x6fa92dd5, 0xcfb31225,
- 0xc83b99ac, 0x10a77d18, 0xe86e639c, 0xdb7bbb3b, 0xcd097826,
- 0x6ef41859, 0xec01b79a, 0x83a89a4f, 0xe6656e95, 0xaa7ee6ff,
- 0x2108cfbc, 0xefe6e815, 0xbad99be7, 0x4ace366f, 0xead4099f,
- 0x29d67cb0, 0x31afb2a4, 0x2a31233f, 0xc63094a5, 0x35c066a2,
- 0x7437bc4e, 0xfca6ca82, 0xe0b0d090, 0x3315d8a7, 0xf14a9804,
- 0x41f7daec, 0x7f0e50cd, 0x172ff691, 0x768dd64d, 0x434db0ef,
- 0xcc544daa, 0xe4df0496, 0x9ee3b5d1, 0x4c1b886a, 0xc1b81f2c,
- 0x467f5165, 0x9d04ea5e, 0x015d358c, 0xfa737487, 0xfb2e410b,
- 0xb35a1d67, 0x9252d2db, 0xe9335610, 0x6d1347d6, 0x9a8c61d7,
- 0x377a0ca1, 0x598e14f8, 0xeb893c13, 0xceee27a9, 0xb735c961,
- 0xe1ede51c, 0x7a3cb147, 0x9c59dfd2, 0x553f73f2, 0x1879ce14,
- 0x73bf37c7, 0x53eacdf7, 0x5f5baafd, 0xdf146f3d, 0x7886db44,
- 0xca81f3af, 0xb93ec468, 0x382c3424, 0xc25f40a3, 0x1672c31d,
- 0xbc0c25e2, 0x288b493c, 0xff41950d, 0x397101a8, 0x08deb30c,
- 0xd89ce4b4, 0x6490c156, 0x7b6184cb, 0xd570b632, 0x48745c6c,
- 0xd04257b8
- };
-
- #endregion
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The key.
- /// The mode.
- /// The padding.
- /// is null.
- /// Keysize is not valid for this algorithm.
- public AesCipher(byte[] key, CipherMode mode, CipherPadding padding)
- : base(key, 16, mode, padding)
- {
- var keySize = key.Length * 8;
-
- if (!(keySize == 256 || keySize == 192 || keySize == 128))
- throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "KeySize '{0}' is not valid for this algorithm.", keySize));
- }
-
- ///
- /// Encrypts the specified region of the input byte array and copies the encrypted data to the specified region of the output byte array.
- ///
- /// The input data to encrypt.
- /// The offset into the input byte array from which to begin using data.
- /// The number of bytes in the input byte array to use as data.
- /// The output to which to write encrypted data.
- /// The offset into the output byte array from which to begin writing data.
- ///
- /// The number of bytes encrypted.
- ///
- /// or is null.
- /// or is too short.
- public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
- {
- if (inputBuffer == null)
- throw new ArgumentNullException("inputBuffer");
-
- if (outputBuffer == null)
- throw new ArgumentNullException("outputBuffer");
-
- if ((inputOffset + (32 / 2)) > inputBuffer.Length)
- {
- throw new IndexOutOfRangeException("input buffer too short");
- }
-
- if ((outputOffset + (32 / 2)) > outputBuffer.Length)
- {
- throw new IndexOutOfRangeException("output buffer too short");
- }
-
- if (this._encryptionKey == null)
- {
- this._encryptionKey = this.GenerateWorkingKey(true, this.Key);
- }
-
- this.UnPackBlock(inputBuffer, inputOffset);
-
- this.EncryptBlock(this._encryptionKey);
-
- this.PackBlock(outputBuffer, outputOffset);
-
- return this.BlockSize;
- }
-
- ///
- /// Decrypts the specified region of the input byte array and copies the decrypted data to the specified region of the output byte array.
- ///
- /// The input data to decrypt.
- /// The offset into the input byte array from which to begin using data.
- /// The number of bytes in the input byte array to use as data.
- /// The output to which to write decrypted data.
- /// The offset into the output byte array from which to begin writing data.
- ///
- /// The number of bytes decrypted.
- ///
- /// or is null.
- /// or is too short.
- public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
- {
- if (inputBuffer == null)
- throw new ArgumentNullException("inputBuffer");
-
- if (outputBuffer == null)
- throw new ArgumentNullException("outputBuffer");
-
- if ((inputOffset + (32 / 2)) > inputBuffer.Length)
- {
- throw new IndexOutOfRangeException("input buffer too short");
- }
-
- if ((outputOffset + (32 / 2)) > outputBuffer.Length)
- {
- throw new IndexOutOfRangeException("output buffer too short");
- }
-
- if (this._decryptionKey == null)
- {
- this._decryptionKey = this.GenerateWorkingKey(false, this.Key);
- }
-
- this.UnPackBlock(inputBuffer, inputOffset);
-
- this.DecryptBlock(this._decryptionKey);
-
- this.PackBlock(outputBuffer, outputOffset);
-
- return this.BlockSize;
- }
-
- private uint[] GenerateWorkingKey(bool isEncryption, byte[] key)
- {
- int KC = key.Length / 4; // key length in words
-
- if (((KC != 4) && (KC != 6) && (KC != 8)) || ((KC * 4) != key.Length))
- throw new ArgumentException("Key length not 128/192/256 bits.");
-
- _rounds = KC + 6; // This is not always true for the generalized Rijndael that allows larger block sizes
- uint[] W = new uint[(_rounds + 1) * 4]; // 4 words in a block
-
- //
- // copy the key into the round key array
- //
-
- int t = 0;
-
- for (int i = 0; i < key.Length; t++)
- {
- W[(t >> 2) * 4 + (t & 3)] = LittleEndianToUInt32(key, i);
- i += 4;
- }
-
- //
- // while not enough round key material calculated
- // calculate new values
- //
- int k = (_rounds + 1) << 2;
- for (int i = KC; (i < k); i++)
- {
- uint temp = W[((i - 1) >> 2) * 4 + ((i - 1) & 3)];
- if ((i % KC) == 0)
- {
- temp = SubWord(Shift(temp, 8)) ^ rcon[(i / KC) - 1];
- }
- else if ((KC > 6) && ((i % KC) == 4))
- {
- temp = SubWord(temp);
- }
-
- W[(i >> 2) * 4 + (i & 3)] = W[((i - KC) >> 2) * 4 + ((i - KC) & 3)] ^ temp;
- }
-
- if (!isEncryption)
- {
- for (int j = 1; j < _rounds; j++)
- {
- for (int i = 0; i < 4; i++)
- {
- W[j * 4 + i] = InvMcol(W[j * 4 + i]);
- }
- }
- }
-
- return W;
- }
-
- private uint Shift(uint r, int shift)
- {
- return (r >> shift) | (r << (32 - shift));
- }
-
- private uint FFmulX(uint x)
- {
- return ((x & m2) << 1) ^ (((x & m1) >> 7) * m3);
- }
-
- private uint InvMcol(uint x)
- {
- uint f2 = FFmulX(x);
- uint f4 = FFmulX(f2);
- uint f8 = FFmulX(f4);
- uint f9 = x ^ f8;
-
- return f2 ^ f4 ^ f8 ^ Shift(f2 ^ f9, 8) ^ Shift(f4 ^ f9, 16) ^ Shift(f9, 24);
- }
-
- private uint SubWord(uint x)
- {
- return (uint)S[x & 255]
- | (((uint)S[(x >> 8) & 255]) << 8)
- | (((uint)S[(x >> 16) & 255]) << 16)
- | (((uint)S[(x >> 24) & 255]) << 24);
- }
-
- private void UnPackBlock(byte[] bytes, int off)
- {
- C0 = LittleEndianToUInt32(bytes, off);
- C1 = LittleEndianToUInt32(bytes, off + 4);
- C2 = LittleEndianToUInt32(bytes, off + 8);
- C3 = LittleEndianToUInt32(bytes, off + 12);
- }
-
- private void PackBlock(byte[] bytes, int off)
- {
- UInt32ToLittleEndian(C0, bytes, off);
- UInt32ToLittleEndian(C1, bytes, off + 4);
- UInt32ToLittleEndian(C2, bytes, off + 8);
- UInt32ToLittleEndian(C3, bytes, off + 12);
- }
-
- private void EncryptBlock(uint[] KW)
- {
- int r;
- uint r0, r1, r2, r3;
-
- C0 ^= KW[0 * 4 + 0];
- C1 ^= KW[0 * 4 + 1];
- C2 ^= KW[0 * 4 + 2];
- C3 ^= KW[0 * 4 + 3];
-
- for (r = 1; r < _rounds - 1; )
- {
- r0 = T0[C0 & 255] ^ T1[(C1 >> 8) & 255] ^ T2[(C2 >> 16) & 255] ^ T3[C3 >> 24] ^ KW[r * 4 + 0];
- r1 = T0[C1 & 255] ^ T1[(C2 >> 8) & 255] ^ T2[(C3 >> 16) & 255] ^ T3[C0 >> 24] ^ KW[r * 4 + 1];
- r2 = T0[C2 & 255] ^ T1[(C3 >> 8) & 255] ^ T2[(C0 >> 16) & 255] ^ T3[C1 >> 24] ^ KW[r * 4 + 2];
- r3 = T0[C3 & 255] ^ T1[(C0 >> 8) & 255] ^ T2[(C1 >> 16) & 255] ^ T3[C2 >> 24] ^ KW[r++ * 4 + 3];
- C0 = T0[r0 & 255] ^ T1[(r1 >> 8) & 255] ^ T2[(r2 >> 16) & 255] ^ T3[r3 >> 24] ^ KW[r * 4 + 0];
- C1 = T0[r1 & 255] ^ T1[(r2 >> 8) & 255] ^ T2[(r3 >> 16) & 255] ^ T3[r0 >> 24] ^ KW[r * 4 + 1];
- C2 = T0[r2 & 255] ^ T1[(r3 >> 8) & 255] ^ T2[(r0 >> 16) & 255] ^ T3[r1 >> 24] ^ KW[r * 4 + 2];
- C3 = T0[r3 & 255] ^ T1[(r0 >> 8) & 255] ^ T2[(r1 >> 16) & 255] ^ T3[r2 >> 24] ^ KW[r++ * 4 + 3];
- }
-
- r0 = T0[C0 & 255] ^ T1[(C1 >> 8) & 255] ^ T2[(C2 >> 16) & 255] ^ T3[C3 >> 24] ^ KW[r * 4 + 0];
- r1 = T0[C1 & 255] ^ T1[(C2 >> 8) & 255] ^ T2[(C3 >> 16) & 255] ^ T3[C0 >> 24] ^ KW[r * 4 + 1];
- r2 = T0[C2 & 255] ^ T1[(C3 >> 8) & 255] ^ T2[(C0 >> 16) & 255] ^ T3[C1 >> 24] ^ KW[r * 4 + 2];
- r3 = T0[C3 & 255] ^ T1[(C0 >> 8) & 255] ^ T2[(C1 >> 16) & 255] ^ T3[C2 >> 24] ^ KW[r++ * 4 + 3];
-
- // the final round's table is a simple function of S so we don't use a whole other four tables for it
-
- C0 = (uint)S[r0 & 255] ^ (((uint)S[(r1 >> 8) & 255]) << 8) ^ (((uint)S[(r2 >> 16) & 255]) << 16) ^ (((uint)S[r3 >> 24]) << 24) ^ KW[r * 4 + 0];
- C1 = (uint)S[r1 & 255] ^ (((uint)S[(r2 >> 8) & 255]) << 8) ^ (((uint)S[(r3 >> 16) & 255]) << 16) ^ (((uint)S[r0 >> 24]) << 24) ^ KW[r * 4 + 1];
- C2 = (uint)S[r2 & 255] ^ (((uint)S[(r3 >> 8) & 255]) << 8) ^ (((uint)S[(r0 >> 16) & 255]) << 16) ^ (((uint)S[r1 >> 24]) << 24) ^ KW[r * 4 + 2];
- C3 = (uint)S[r3 & 255] ^ (((uint)S[(r0 >> 8) & 255]) << 8) ^ (((uint)S[(r1 >> 16) & 255]) << 16) ^ (((uint)S[r2 >> 24]) << 24) ^ KW[r * 4 + 3];
- }
-
- private void DecryptBlock(uint[] KW)
- {
- int r;
- uint r0, r1, r2, r3;
-
- C0 ^= KW[_rounds * 4 + 0];
- C1 ^= KW[_rounds * 4 + 1];
- C2 ^= KW[_rounds * 4 + 2];
- C3 ^= KW[_rounds * 4 + 3];
-
- for (r = _rounds - 1; r > 1; )
- {
- r0 = Tinv0[C0 & 255] ^ Tinv1[(C3 >> 8) & 255] ^ Tinv2[(C2 >> 16) & 255] ^ Tinv3[C1 >> 24] ^ KW[r * 4 + 0];
- r1 = Tinv0[C1 & 255] ^ Tinv1[(C0 >> 8) & 255] ^ Tinv2[(C3 >> 16) & 255] ^ Tinv3[C2 >> 24] ^ KW[r * 4 + 1];
- r2 = Tinv0[C2 & 255] ^ Tinv1[(C1 >> 8) & 255] ^ Tinv2[(C0 >> 16) & 255] ^ Tinv3[C3 >> 24] ^ KW[r * 4 + 2];
- r3 = Tinv0[C3 & 255] ^ Tinv1[(C2 >> 8) & 255] ^ Tinv2[(C1 >> 16) & 255] ^ Tinv3[C0 >> 24] ^ KW[r-- * 4 + 3];
- C0 = Tinv0[r0 & 255] ^ Tinv1[(r3 >> 8) & 255] ^ Tinv2[(r2 >> 16) & 255] ^ Tinv3[r1 >> 24] ^ KW[r * 4 + 0];
- C1 = Tinv0[r1 & 255] ^ Tinv1[(r0 >> 8) & 255] ^ Tinv2[(r3 >> 16) & 255] ^ Tinv3[r2 >> 24] ^ KW[r * 4 + 1];
- C2 = Tinv0[r2 & 255] ^ Tinv1[(r1 >> 8) & 255] ^ Tinv2[(r0 >> 16) & 255] ^ Tinv3[r3 >> 24] ^ KW[r * 4 + 2];
- C3 = Tinv0[r3 & 255] ^ Tinv1[(r2 >> 8) & 255] ^ Tinv2[(r1 >> 16) & 255] ^ Tinv3[r0 >> 24] ^ KW[r-- * 4 + 3];
- }
-
- r0 = Tinv0[C0 & 255] ^ Tinv1[(C3 >> 8) & 255] ^ Tinv2[(C2 >> 16) & 255] ^ Tinv3[C1 >> 24] ^ KW[r * 4 + 0];
- r1 = Tinv0[C1 & 255] ^ Tinv1[(C0 >> 8) & 255] ^ Tinv2[(C3 >> 16) & 255] ^ Tinv3[C2 >> 24] ^ KW[r * 4 + 1];
- r2 = Tinv0[C2 & 255] ^ Tinv1[(C1 >> 8) & 255] ^ Tinv2[(C0 >> 16) & 255] ^ Tinv3[C3 >> 24] ^ KW[r * 4 + 2];
- r3 = Tinv0[C3 & 255] ^ Tinv1[(C2 >> 8) & 255] ^ Tinv2[(C1 >> 16) & 255] ^ Tinv3[C0 >> 24] ^ KW[r * 4 + 3];
-
- // the final round's table is a simple function of Si so we don't use a whole other four tables for it
-
- C0 = (uint)Si[r0 & 255] ^ (((uint)Si[(r3 >> 8) & 255]) << 8) ^ (((uint)Si[(r2 >> 16) & 255]) << 16) ^ (((uint)Si[r1 >> 24]) << 24) ^ KW[0 * 4 + 0];
- C1 = (uint)Si[r1 & 255] ^ (((uint)Si[(r0 >> 8) & 255]) << 8) ^ (((uint)Si[(r3 >> 16) & 255]) << 16) ^ (((uint)Si[r2 >> 24]) << 24) ^ KW[0 * 4 + 1];
- C2 = (uint)Si[r2 & 255] ^ (((uint)Si[(r1 >> 8) & 255]) << 8) ^ (((uint)Si[(r0 >> 16) & 255]) << 16) ^ (((uint)Si[r3 >> 24]) << 24) ^ KW[0 * 4 + 2];
- C3 = (uint)Si[r3 & 255] ^ (((uint)Si[(r2 >> 8) & 255]) << 8) ^ (((uint)Si[(r1 >> 16) & 255]) << 16) ^ (((uint)Si[r0 >> 24]) << 24) ^ KW[0 * 4 + 3];
- }
- }
-}
+using System;
+using System.Globalization;
+
+namespace Renci.SshNet.Security.Cryptography.Ciphers
+{
+ ///
+ /// AES cipher implementation.
+ ///
+ public sealed class AesCipher : BlockCipher
+ {
+ private const uint m1 = 0x80808080;
+
+ private const uint m2 = 0x7f7f7f7f;
+
+ private const uint m3 = 0x0000001b;
+
+ private int _rounds;
+
+ private uint[] _encryptionKey;
+
+ private uint[] _decryptionKey;
+
+ private uint C0, C1, C2, C3;
+
+ #region Static Definition Tables
+
+ private static readonly byte[] S =
+ {
+ 99, 124, 119, 123, 242, 107, 111, 197,
+ 48, 1, 103, 43, 254, 215, 171, 118,
+ 202, 130, 201, 125, 250, 89, 71, 240,
+ 173, 212, 162, 175, 156, 164, 114, 192,
+ 183, 253, 147, 38, 54, 63, 247, 204,
+ 52, 165, 229, 241, 113, 216, 49, 21,
+ 4, 199, 35, 195, 24, 150, 5, 154,
+ 7, 18, 128, 226, 235, 39, 178, 117,
+ 9, 131, 44, 26, 27, 110, 90, 160,
+ 82, 59, 214, 179, 41, 227, 47, 132,
+ 83, 209, 0, 237, 32, 252, 177, 91,
+ 106, 203, 190, 57, 74, 76, 88, 207,
+ 208, 239, 170, 251, 67, 77, 51, 133,
+ 69, 249, 2, 127, 80, 60, 159, 168,
+ 81, 163, 64, 143, 146, 157, 56, 245,
+ 188, 182, 218, 33, 16, 255, 243, 210,
+ 205, 12, 19, 236, 95, 151, 68, 23,
+ 196, 167, 126, 61, 100, 93, 25, 115,
+ 96, 129, 79, 220, 34, 42, 144, 136,
+ 70, 238, 184, 20, 222, 94, 11, 219,
+ 224, 50, 58, 10, 73, 6, 36, 92,
+ 194, 211, 172, 98, 145, 149, 228, 121,
+ 231, 200, 55, 109, 141, 213, 78, 169,
+ 108, 86, 244, 234, 101, 122, 174, 8,
+ 186, 120, 37, 46, 28, 166, 180, 198,
+ 232, 221, 116, 31, 75, 189, 139, 138,
+ 112, 62, 181, 102, 72, 3, 246, 14,
+ 97, 53, 87, 185, 134, 193, 29, 158,
+ 225, 248, 152, 17, 105, 217, 142, 148,
+ 155, 30, 135, 233, 206, 85, 40, 223,
+ 140, 161, 137, 13, 191, 230, 66, 104,
+ 65, 153, 45, 15, 176, 84, 187, 22
+ };
+
+ // The inverse S-box
+ private static readonly byte[] Si =
+ {
+ 82, 9, 106, 213, 48, 54, 165, 56,
+ 191, 64, 163, 158, 129, 243, 215, 251,
+ 124, 227, 57, 130, 155, 47, 255, 135,
+ 52, 142, 67, 68, 196, 222, 233, 203,
+ 84, 123, 148, 50, 166, 194, 35, 61,
+ 238, 76, 149, 11, 66, 250, 195, 78,
+ 8, 46, 161, 102, 40, 217, 36, 178,
+ 118, 91, 162, 73, 109, 139, 209, 37,
+ 114, 248, 246, 100, 134, 104, 152, 22,
+ 212, 164, 92, 204, 93, 101, 182, 146,
+ 108, 112, 72, 80, 253, 237, 185, 218,
+ 94, 21, 70, 87, 167, 141, 157, 132,
+ 144, 216, 171, 0, 140, 188, 211, 10,
+ 247, 228, 88, 5, 184, 179, 69, 6,
+ 208, 44, 30, 143, 202, 63, 15, 2,
+ 193, 175, 189, 3, 1, 19, 138, 107,
+ 58, 145, 17, 65, 79, 103, 220, 234,
+ 151, 242, 207, 206, 240, 180, 230, 115,
+ 150, 172, 116, 34, 231, 173, 53, 133,
+ 226, 249, 55, 232, 28, 117, 223, 110,
+ 71, 241, 26, 113, 29, 41, 197, 137,
+ 111, 183, 98, 14, 170, 24, 190, 27,
+ 252, 86, 62, 75, 198, 210, 121, 32,
+ 154, 219, 192, 254, 120, 205, 90, 244,
+ 31, 221, 168, 51, 136, 7, 199, 49,
+ 177, 18, 16, 89, 39, 128, 236, 95,
+ 96, 81, 127, 169, 25, 181, 74, 13,
+ 45, 229, 122, 159, 147, 201, 156, 239,
+ 160, 224, 59, 77, 174, 42, 245, 176,
+ 200, 235, 187, 60, 131, 83, 153, 97,
+ 23, 43, 4, 126, 186, 119, 214, 38,
+ 225, 105, 20, 99, 85, 33, 12, 125
+ };
+
+ // vector used in calculating key schedule (powers of x in GF(256))
+ private static readonly byte[] rcon =
+ {
+ 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a,
+ 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91
+ };
+
+ // precomputation tables of calculations for rounds
+ private static readonly uint[] T0 =
+ {
+ 0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 0x0df2f2ff,
+ 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591, 0x50303060, 0x03010102,
+ 0xa96767ce, 0x7d2b2b56, 0x19fefee7, 0x62d7d7b5, 0xe6abab4d,
+ 0x9a7676ec, 0x45caca8f, 0x9d82821f, 0x40c9c989, 0x877d7dfa,
+ 0x15fafaef, 0xeb5959b2, 0xc947478e, 0x0bf0f0fb, 0xecadad41,
+ 0x67d4d4b3, 0xfda2a25f, 0xeaafaf45, 0xbf9c9c23, 0xf7a4a453,
+ 0x967272e4, 0x5bc0c09b, 0xc2b7b775, 0x1cfdfde1, 0xae93933d,
+ 0x6a26264c, 0x5a36366c, 0x413f3f7e, 0x02f7f7f5, 0x4fcccc83,
+ 0x5c343468, 0xf4a5a551, 0x34e5e5d1, 0x08f1f1f9, 0x937171e2,
+ 0x73d8d8ab, 0x53313162, 0x3f15152a, 0x0c040408, 0x52c7c795,
+ 0x65232346, 0x5ec3c39d, 0x28181830, 0xa1969637, 0x0f05050a,
+ 0xb59a9a2f, 0x0907070e, 0x36121224, 0x9b80801b, 0x3de2e2df,
+ 0x26ebebcd, 0x6927274e, 0xcdb2b27f, 0x9f7575ea, 0x1b090912,
+ 0x9e83831d, 0x742c2c58, 0x2e1a1a34, 0x2d1b1b36, 0xb26e6edc,
+ 0xee5a5ab4, 0xfba0a05b, 0xf65252a4, 0x4d3b3b76, 0x61d6d6b7,
+ 0xceb3b37d, 0x7b292952, 0x3ee3e3dd, 0x712f2f5e, 0x97848413,
+ 0xf55353a6, 0x68d1d1b9, 0x00000000, 0x2cededc1, 0x60202040,
+ 0x1ffcfce3, 0xc8b1b179, 0xed5b5bb6, 0xbe6a6ad4, 0x46cbcb8d,
+ 0xd9bebe67, 0x4b393972, 0xde4a4a94, 0xd44c4c98, 0xe85858b0,
+ 0x4acfcf85, 0x6bd0d0bb, 0x2aefefc5, 0xe5aaaa4f, 0x16fbfbed,
+ 0xc5434386, 0xd74d4d9a, 0x55333366, 0x94858511, 0xcf45458a,
+ 0x10f9f9e9, 0x06020204, 0x817f7ffe, 0xf05050a0, 0x443c3c78,
+ 0xba9f9f25, 0xe3a8a84b, 0xf35151a2, 0xfea3a35d, 0xc0404080,
+ 0x8a8f8f05, 0xad92923f, 0xbc9d9d21, 0x48383870, 0x04f5f5f1,
+ 0xdfbcbc63, 0xc1b6b677, 0x75dadaaf, 0x63212142, 0x30101020,
+ 0x1affffe5, 0x0ef3f3fd, 0x6dd2d2bf, 0x4ccdcd81, 0x140c0c18,
+ 0x35131326, 0x2fececc3, 0xe15f5fbe, 0xa2979735, 0xcc444488,
+ 0x3917172e, 0x57c4c493, 0xf2a7a755, 0x827e7efc, 0x473d3d7a,
+ 0xac6464c8, 0xe75d5dba, 0x2b191932, 0x957373e6, 0xa06060c0,
+ 0x98818119, 0xd14f4f9e, 0x7fdcdca3, 0x66222244, 0x7e2a2a54,
+ 0xab90903b, 0x8388880b, 0xca46468c, 0x29eeeec7, 0xd3b8b86b,
+ 0x3c141428, 0x79dedea7, 0xe25e5ebc, 0x1d0b0b16, 0x76dbdbad,
+ 0x3be0e0db, 0x56323264, 0x4e3a3a74, 0x1e0a0a14, 0xdb494992,
+ 0x0a06060c, 0x6c242448, 0xe45c5cb8, 0x5dc2c29f, 0x6ed3d3bd,
+ 0xefacac43, 0xa66262c4, 0xa8919139, 0xa4959531, 0x37e4e4d3,
+ 0x8b7979f2, 0x32e7e7d5, 0x43c8c88b, 0x5937376e, 0xb76d6dda,
+ 0x8c8d8d01, 0x64d5d5b1, 0xd24e4e9c, 0xe0a9a949, 0xb46c6cd8,
+ 0xfa5656ac, 0x07f4f4f3, 0x25eaeacf, 0xaf6565ca, 0x8e7a7af4,
+ 0xe9aeae47, 0x18080810, 0xd5baba6f, 0x887878f0, 0x6f25254a,
+ 0x722e2e5c, 0x241c1c38, 0xf1a6a657, 0xc7b4b473, 0x51c6c697,
+ 0x23e8e8cb, 0x7cdddda1, 0x9c7474e8, 0x211f1f3e, 0xdd4b4b96,
+ 0xdcbdbd61, 0x868b8b0d, 0x858a8a0f, 0x907070e0, 0x423e3e7c,
+ 0xc4b5b571, 0xaa6666cc, 0xd8484890, 0x05030306, 0x01f6f6f7,
+ 0x120e0e1c, 0xa36161c2, 0x5f35356a, 0xf95757ae, 0xd0b9b969,
+ 0x91868617, 0x58c1c199, 0x271d1d3a, 0xb99e9e27, 0x38e1e1d9,
+ 0x13f8f8eb, 0xb398982b, 0x33111122, 0xbb6969d2, 0x70d9d9a9,
+ 0x898e8e07, 0xa7949433, 0xb69b9b2d, 0x221e1e3c, 0x92878715,
+ 0x20e9e9c9, 0x49cece87, 0xff5555aa, 0x78282850, 0x7adfdfa5,
+ 0x8f8c8c03, 0xf8a1a159, 0x80898909, 0x170d0d1a, 0xdabfbf65,
+ 0x31e6e6d7, 0xc6424284, 0xb86868d0, 0xc3414182, 0xb0999929,
+ 0x772d2d5a, 0x110f0f1e, 0xcbb0b07b, 0xfc5454a8, 0xd6bbbb6d,
+ 0x3a16162c
+ };
+
+ private static readonly uint[] T1 =
+ {
+ 0x6363c6a5, 0x7c7cf884, 0x7777ee99, 0x7b7bf68d, 0xf2f2ff0d,
+ 0x6b6bd6bd, 0x6f6fdeb1, 0xc5c59154, 0x30306050, 0x01010203,
+ 0x6767cea9, 0x2b2b567d, 0xfefee719, 0xd7d7b562, 0xabab4de6,
+ 0x7676ec9a, 0xcaca8f45, 0x82821f9d, 0xc9c98940, 0x7d7dfa87,
+ 0xfafaef15, 0x5959b2eb, 0x47478ec9, 0xf0f0fb0b, 0xadad41ec,
+ 0xd4d4b367, 0xa2a25ffd, 0xafaf45ea, 0x9c9c23bf, 0xa4a453f7,
+ 0x7272e496, 0xc0c09b5b, 0xb7b775c2, 0xfdfde11c, 0x93933dae,
+ 0x26264c6a, 0x36366c5a, 0x3f3f7e41, 0xf7f7f502, 0xcccc834f,
+ 0x3434685c, 0xa5a551f4, 0xe5e5d134, 0xf1f1f908, 0x7171e293,
+ 0xd8d8ab73, 0x31316253, 0x15152a3f, 0x0404080c, 0xc7c79552,
+ 0x23234665, 0xc3c39d5e, 0x18183028, 0x969637a1, 0x05050a0f,
+ 0x9a9a2fb5, 0x07070e09, 0x12122436, 0x80801b9b, 0xe2e2df3d,
+ 0xebebcd26, 0x27274e69, 0xb2b27fcd, 0x7575ea9f, 0x0909121b,
+ 0x83831d9e, 0x2c2c5874, 0x1a1a342e, 0x1b1b362d, 0x6e6edcb2,
+ 0x5a5ab4ee, 0xa0a05bfb, 0x5252a4f6, 0x3b3b764d, 0xd6d6b761,
+ 0xb3b37dce, 0x2929527b, 0xe3e3dd3e, 0x2f2f5e71, 0x84841397,
+ 0x5353a6f5, 0xd1d1b968, 0x00000000, 0xededc12c, 0x20204060,
+ 0xfcfce31f, 0xb1b179c8, 0x5b5bb6ed, 0x6a6ad4be, 0xcbcb8d46,
+ 0xbebe67d9, 0x3939724b, 0x4a4a94de, 0x4c4c98d4, 0x5858b0e8,
+ 0xcfcf854a, 0xd0d0bb6b, 0xefefc52a, 0xaaaa4fe5, 0xfbfbed16,
+ 0x434386c5, 0x4d4d9ad7, 0x33336655, 0x85851194, 0x45458acf,
+ 0xf9f9e910, 0x02020406, 0x7f7ffe81, 0x5050a0f0, 0x3c3c7844,
+ 0x9f9f25ba, 0xa8a84be3, 0x5151a2f3, 0xa3a35dfe, 0x404080c0,
+ 0x8f8f058a, 0x92923fad, 0x9d9d21bc, 0x38387048, 0xf5f5f104,
+ 0xbcbc63df, 0xb6b677c1, 0xdadaaf75, 0x21214263, 0x10102030,
+ 0xffffe51a, 0xf3f3fd0e, 0xd2d2bf6d, 0xcdcd814c, 0x0c0c1814,
+ 0x13132635, 0xececc32f, 0x5f5fbee1, 0x979735a2, 0x444488cc,
+ 0x17172e39, 0xc4c49357, 0xa7a755f2, 0x7e7efc82, 0x3d3d7a47,
+ 0x6464c8ac, 0x5d5dbae7, 0x1919322b, 0x7373e695, 0x6060c0a0,
+ 0x81811998, 0x4f4f9ed1, 0xdcdca37f, 0x22224466, 0x2a2a547e,
+ 0x90903bab, 0x88880b83, 0x46468cca, 0xeeeec729, 0xb8b86bd3,
+ 0x1414283c, 0xdedea779, 0x5e5ebce2, 0x0b0b161d, 0xdbdbad76,
+ 0xe0e0db3b, 0x32326456, 0x3a3a744e, 0x0a0a141e, 0x494992db,
+ 0x06060c0a, 0x2424486c, 0x5c5cb8e4, 0xc2c29f5d, 0xd3d3bd6e,
+ 0xacac43ef, 0x6262c4a6, 0x919139a8, 0x959531a4, 0xe4e4d337,
+ 0x7979f28b, 0xe7e7d532, 0xc8c88b43, 0x37376e59, 0x6d6ddab7,
+ 0x8d8d018c, 0xd5d5b164, 0x4e4e9cd2, 0xa9a949e0, 0x6c6cd8b4,
+ 0x5656acfa, 0xf4f4f307, 0xeaeacf25, 0x6565caaf, 0x7a7af48e,
+ 0xaeae47e9, 0x08081018, 0xbaba6fd5, 0x7878f088, 0x25254a6f,
+ 0x2e2e5c72, 0x1c1c3824, 0xa6a657f1, 0xb4b473c7, 0xc6c69751,
+ 0xe8e8cb23, 0xdddda17c, 0x7474e89c, 0x1f1f3e21, 0x4b4b96dd,
+ 0xbdbd61dc, 0x8b8b0d86, 0x8a8a0f85, 0x7070e090, 0x3e3e7c42,
+ 0xb5b571c4, 0x6666ccaa, 0x484890d8, 0x03030605, 0xf6f6f701,
+ 0x0e0e1c12, 0x6161c2a3, 0x35356a5f, 0x5757aef9, 0xb9b969d0,
+ 0x86861791, 0xc1c19958, 0x1d1d3a27, 0x9e9e27b9, 0xe1e1d938,
+ 0xf8f8eb13, 0x98982bb3, 0x11112233, 0x6969d2bb, 0xd9d9a970,
+ 0x8e8e0789, 0x949433a7, 0x9b9b2db6, 0x1e1e3c22, 0x87871592,
+ 0xe9e9c920, 0xcece8749, 0x5555aaff, 0x28285078, 0xdfdfa57a,
+ 0x8c8c038f, 0xa1a159f8, 0x89890980, 0x0d0d1a17, 0xbfbf65da,
+ 0xe6e6d731, 0x424284c6, 0x6868d0b8, 0x414182c3, 0x999929b0,
+ 0x2d2d5a77, 0x0f0f1e11, 0xb0b07bcb, 0x5454a8fc, 0xbbbb6dd6,
+ 0x16162c3a
+ };
+
+ private static readonly uint[] T2 =
+ {
+ 0x63c6a563, 0x7cf8847c, 0x77ee9977, 0x7bf68d7b, 0xf2ff0df2,
+ 0x6bd6bd6b, 0x6fdeb16f, 0xc59154c5, 0x30605030, 0x01020301,
+ 0x67cea967, 0x2b567d2b, 0xfee719fe, 0xd7b562d7, 0xab4de6ab,
+ 0x76ec9a76, 0xca8f45ca, 0x821f9d82, 0xc98940c9, 0x7dfa877d,
+ 0xfaef15fa, 0x59b2eb59, 0x478ec947, 0xf0fb0bf0, 0xad41ecad,
+ 0xd4b367d4, 0xa25ffda2, 0xaf45eaaf, 0x9c23bf9c, 0xa453f7a4,
+ 0x72e49672, 0xc09b5bc0, 0xb775c2b7, 0xfde11cfd, 0x933dae93,
+ 0x264c6a26, 0x366c5a36, 0x3f7e413f, 0xf7f502f7, 0xcc834fcc,
+ 0x34685c34, 0xa551f4a5, 0xe5d134e5, 0xf1f908f1, 0x71e29371,
+ 0xd8ab73d8, 0x31625331, 0x152a3f15, 0x04080c04, 0xc79552c7,
+ 0x23466523, 0xc39d5ec3, 0x18302818, 0x9637a196, 0x050a0f05,
+ 0x9a2fb59a, 0x070e0907, 0x12243612, 0x801b9b80, 0xe2df3de2,
+ 0xebcd26eb, 0x274e6927, 0xb27fcdb2, 0x75ea9f75, 0x09121b09,
+ 0x831d9e83, 0x2c58742c, 0x1a342e1a, 0x1b362d1b, 0x6edcb26e,
+ 0x5ab4ee5a, 0xa05bfba0, 0x52a4f652, 0x3b764d3b, 0xd6b761d6,
+ 0xb37dceb3, 0x29527b29, 0xe3dd3ee3, 0x2f5e712f, 0x84139784,
+ 0x53a6f553, 0xd1b968d1, 0x00000000, 0xedc12ced, 0x20406020,
+ 0xfce31ffc, 0xb179c8b1, 0x5bb6ed5b, 0x6ad4be6a, 0xcb8d46cb,
+ 0xbe67d9be, 0x39724b39, 0x4a94de4a, 0x4c98d44c, 0x58b0e858,
+ 0xcf854acf, 0xd0bb6bd0, 0xefc52aef, 0xaa4fe5aa, 0xfbed16fb,
+ 0x4386c543, 0x4d9ad74d, 0x33665533, 0x85119485, 0x458acf45,
+ 0xf9e910f9, 0x02040602, 0x7ffe817f, 0x50a0f050, 0x3c78443c,
+ 0x9f25ba9f, 0xa84be3a8, 0x51a2f351, 0xa35dfea3, 0x4080c040,
+ 0x8f058a8f, 0x923fad92, 0x9d21bc9d, 0x38704838, 0xf5f104f5,
+ 0xbc63dfbc, 0xb677c1b6, 0xdaaf75da, 0x21426321, 0x10203010,
+ 0xffe51aff, 0xf3fd0ef3, 0xd2bf6dd2, 0xcd814ccd, 0x0c18140c,
+ 0x13263513, 0xecc32fec, 0x5fbee15f, 0x9735a297, 0x4488cc44,
+ 0x172e3917, 0xc49357c4, 0xa755f2a7, 0x7efc827e, 0x3d7a473d,
+ 0x64c8ac64, 0x5dbae75d, 0x19322b19, 0x73e69573, 0x60c0a060,
+ 0x81199881, 0x4f9ed14f, 0xdca37fdc, 0x22446622, 0x2a547e2a,
+ 0x903bab90, 0x880b8388, 0x468cca46, 0xeec729ee, 0xb86bd3b8,
+ 0x14283c14, 0xdea779de, 0x5ebce25e, 0x0b161d0b, 0xdbad76db,
+ 0xe0db3be0, 0x32645632, 0x3a744e3a, 0x0a141e0a, 0x4992db49,
+ 0x060c0a06, 0x24486c24, 0x5cb8e45c, 0xc29f5dc2, 0xd3bd6ed3,
+ 0xac43efac, 0x62c4a662, 0x9139a891, 0x9531a495, 0xe4d337e4,
+ 0x79f28b79, 0xe7d532e7, 0xc88b43c8, 0x376e5937, 0x6ddab76d,
+ 0x8d018c8d, 0xd5b164d5, 0x4e9cd24e, 0xa949e0a9, 0x6cd8b46c,
+ 0x56acfa56, 0xf4f307f4, 0xeacf25ea, 0x65caaf65, 0x7af48e7a,
+ 0xae47e9ae, 0x08101808, 0xba6fd5ba, 0x78f08878, 0x254a6f25,
+ 0x2e5c722e, 0x1c38241c, 0xa657f1a6, 0xb473c7b4, 0xc69751c6,
+ 0xe8cb23e8, 0xdda17cdd, 0x74e89c74, 0x1f3e211f, 0x4b96dd4b,
+ 0xbd61dcbd, 0x8b0d868b, 0x8a0f858a, 0x70e09070, 0x3e7c423e,
+ 0xb571c4b5, 0x66ccaa66, 0x4890d848, 0x03060503, 0xf6f701f6,
+ 0x0e1c120e, 0x61c2a361, 0x356a5f35, 0x57aef957, 0xb969d0b9,
+ 0x86179186, 0xc19958c1, 0x1d3a271d, 0x9e27b99e, 0xe1d938e1,
+ 0xf8eb13f8, 0x982bb398, 0x11223311, 0x69d2bb69, 0xd9a970d9,
+ 0x8e07898e, 0x9433a794, 0x9b2db69b, 0x1e3c221e, 0x87159287,
+ 0xe9c920e9, 0xce8749ce, 0x55aaff55, 0x28507828, 0xdfa57adf,
+ 0x8c038f8c, 0xa159f8a1, 0x89098089, 0x0d1a170d, 0xbf65dabf,
+ 0xe6d731e6, 0x4284c642, 0x68d0b868, 0x4182c341, 0x9929b099,
+ 0x2d5a772d, 0x0f1e110f, 0xb07bcbb0, 0x54a8fc54, 0xbb6dd6bb,
+ 0x162c3a16
+ };
+
+ private static readonly uint[] T3 =
+ {
+ 0xc6a56363, 0xf8847c7c, 0xee997777, 0xf68d7b7b, 0xff0df2f2,
+ 0xd6bd6b6b, 0xdeb16f6f, 0x9154c5c5, 0x60503030, 0x02030101,
+ 0xcea96767, 0x567d2b2b, 0xe719fefe, 0xb562d7d7, 0x4de6abab,
+ 0xec9a7676, 0x8f45caca, 0x1f9d8282, 0x8940c9c9, 0xfa877d7d,
+ 0xef15fafa, 0xb2eb5959, 0x8ec94747, 0xfb0bf0f0, 0x41ecadad,
+ 0xb367d4d4, 0x5ffda2a2, 0x45eaafaf, 0x23bf9c9c, 0x53f7a4a4,
+ 0xe4967272, 0x9b5bc0c0, 0x75c2b7b7, 0xe11cfdfd, 0x3dae9393,
+ 0x4c6a2626, 0x6c5a3636, 0x7e413f3f, 0xf502f7f7, 0x834fcccc,
+ 0x685c3434, 0x51f4a5a5, 0xd134e5e5, 0xf908f1f1, 0xe2937171,
+ 0xab73d8d8, 0x62533131, 0x2a3f1515, 0x080c0404, 0x9552c7c7,
+ 0x46652323, 0x9d5ec3c3, 0x30281818, 0x37a19696, 0x0a0f0505,
+ 0x2fb59a9a, 0x0e090707, 0x24361212, 0x1b9b8080, 0xdf3de2e2,
+ 0xcd26ebeb, 0x4e692727, 0x7fcdb2b2, 0xea9f7575, 0x121b0909,
+ 0x1d9e8383, 0x58742c2c, 0x342e1a1a, 0x362d1b1b, 0xdcb26e6e,
+ 0xb4ee5a5a, 0x5bfba0a0, 0xa4f65252, 0x764d3b3b, 0xb761d6d6,
+ 0x7dceb3b3, 0x527b2929, 0xdd3ee3e3, 0x5e712f2f, 0x13978484,
+ 0xa6f55353, 0xb968d1d1, 0x00000000, 0xc12ceded, 0x40602020,
+ 0xe31ffcfc, 0x79c8b1b1, 0xb6ed5b5b, 0xd4be6a6a, 0x8d46cbcb,
+ 0x67d9bebe, 0x724b3939, 0x94de4a4a, 0x98d44c4c, 0xb0e85858,
+ 0x854acfcf, 0xbb6bd0d0, 0xc52aefef, 0x4fe5aaaa, 0xed16fbfb,
+ 0x86c54343, 0x9ad74d4d, 0x66553333, 0x11948585, 0x8acf4545,
+ 0xe910f9f9, 0x04060202, 0xfe817f7f, 0xa0f05050, 0x78443c3c,
+ 0x25ba9f9f, 0x4be3a8a8, 0xa2f35151, 0x5dfea3a3, 0x80c04040,
+ 0x058a8f8f, 0x3fad9292, 0x21bc9d9d, 0x70483838, 0xf104f5f5,
+ 0x63dfbcbc, 0x77c1b6b6, 0xaf75dada, 0x42632121, 0x20301010,
+ 0xe51affff, 0xfd0ef3f3, 0xbf6dd2d2, 0x814ccdcd, 0x18140c0c,
+ 0x26351313, 0xc32fecec, 0xbee15f5f, 0x35a29797, 0x88cc4444,
+ 0x2e391717, 0x9357c4c4, 0x55f2a7a7, 0xfc827e7e, 0x7a473d3d,
+ 0xc8ac6464, 0xbae75d5d, 0x322b1919, 0xe6957373, 0xc0a06060,
+ 0x19988181, 0x9ed14f4f, 0xa37fdcdc, 0x44662222, 0x547e2a2a,
+ 0x3bab9090, 0x0b838888, 0x8cca4646, 0xc729eeee, 0x6bd3b8b8,
+ 0x283c1414, 0xa779dede, 0xbce25e5e, 0x161d0b0b, 0xad76dbdb,
+ 0xdb3be0e0, 0x64563232, 0x744e3a3a, 0x141e0a0a, 0x92db4949,
+ 0x0c0a0606, 0x486c2424, 0xb8e45c5c, 0x9f5dc2c2, 0xbd6ed3d3,
+ 0x43efacac, 0xc4a66262, 0x39a89191, 0x31a49595, 0xd337e4e4,
+ 0xf28b7979, 0xd532e7e7, 0x8b43c8c8, 0x6e593737, 0xdab76d6d,
+ 0x018c8d8d, 0xb164d5d5, 0x9cd24e4e, 0x49e0a9a9, 0xd8b46c6c,
+ 0xacfa5656, 0xf307f4f4, 0xcf25eaea, 0xcaaf6565, 0xf48e7a7a,
+ 0x47e9aeae, 0x10180808, 0x6fd5baba, 0xf0887878, 0x4a6f2525,
+ 0x5c722e2e, 0x38241c1c, 0x57f1a6a6, 0x73c7b4b4, 0x9751c6c6,
+ 0xcb23e8e8, 0xa17cdddd, 0xe89c7474, 0x3e211f1f, 0x96dd4b4b,
+ 0x61dcbdbd, 0x0d868b8b, 0x0f858a8a, 0xe0907070, 0x7c423e3e,
+ 0x71c4b5b5, 0xccaa6666, 0x90d84848, 0x06050303, 0xf701f6f6,
+ 0x1c120e0e, 0xc2a36161, 0x6a5f3535, 0xaef95757, 0x69d0b9b9,
+ 0x17918686, 0x9958c1c1, 0x3a271d1d, 0x27b99e9e, 0xd938e1e1,
+ 0xeb13f8f8, 0x2bb39898, 0x22331111, 0xd2bb6969, 0xa970d9d9,
+ 0x07898e8e, 0x33a79494, 0x2db69b9b, 0x3c221e1e, 0x15928787,
+ 0xc920e9e9, 0x8749cece, 0xaaff5555, 0x50782828, 0xa57adfdf,
+ 0x038f8c8c, 0x59f8a1a1, 0x09808989, 0x1a170d0d, 0x65dabfbf,
+ 0xd731e6e6, 0x84c64242, 0xd0b86868, 0x82c34141, 0x29b09999,
+ 0x5a772d2d, 0x1e110f0f, 0x7bcbb0b0, 0xa8fc5454, 0x6dd6bbbb,
+ 0x2c3a1616
+ };
+
+ private static readonly uint[] Tinv0 =
+ {
+ 0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a, 0xcb6bab3b,
+ 0xf1459d1f, 0xab58faac, 0x9303e34b, 0x55fa3020, 0xf66d76ad,
+ 0x9176cc88, 0x254c02f5, 0xfcd7e54f, 0xd7cb2ac5, 0x80443526,
+ 0x8fa362b5, 0x495ab1de, 0x671bba25, 0x980eea45, 0xe1c0fe5d,
+ 0x02752fc3, 0x12f04c81, 0xa397468d, 0xc6f9d36b, 0xe75f8f03,
+ 0x959c9215, 0xeb7a6dbf, 0xda595295, 0x2d83bed4, 0xd3217458,
+ 0x2969e049, 0x44c8c98e, 0x6a89c275, 0x78798ef4, 0x6b3e5899,
+ 0xdd71b927, 0xb64fe1be, 0x17ad88f0, 0x66ac20c9, 0xb43ace7d,
+ 0x184adf63, 0x82311ae5, 0x60335197, 0x457f5362, 0xe07764b1,
+ 0x84ae6bbb, 0x1ca081fe, 0x942b08f9, 0x58684870, 0x19fd458f,
+ 0x876cde94, 0xb7f87b52, 0x23d373ab, 0xe2024b72, 0x578f1fe3,
+ 0x2aab5566, 0x0728ebb2, 0x03c2b52f, 0x9a7bc586, 0xa50837d3,
+ 0xf2872830, 0xb2a5bf23, 0xba6a0302, 0x5c8216ed, 0x2b1ccf8a,
+ 0x92b479a7, 0xf0f207f3, 0xa1e2694e, 0xcdf4da65, 0xd5be0506,
+ 0x1f6234d1, 0x8afea6c4, 0x9d532e34, 0xa055f3a2, 0x32e18a05,
+ 0x75ebf6a4, 0x39ec830b, 0xaaef6040, 0x069f715e, 0x51106ebd,
+ 0xf98a213e, 0x3d06dd96, 0xae053edd, 0x46bde64d, 0xb58d5491,
+ 0x055dc471, 0x6fd40604, 0xff155060, 0x24fb9819, 0x97e9bdd6,
+ 0xcc434089, 0x779ed967, 0xbd42e8b0, 0x888b8907, 0x385b19e7,
+ 0xdbeec879, 0x470a7ca1, 0xe90f427c, 0xc91e84f8, 0x00000000,
+ 0x83868009, 0x48ed2b32, 0xac70111e, 0x4e725a6c, 0xfbff0efd,
+ 0x5638850f, 0x1ed5ae3d, 0x27392d36, 0x64d90f0a, 0x21a65c68,
+ 0xd1545b9b, 0x3a2e3624, 0xb1670a0c, 0x0fe75793, 0xd296eeb4,
+ 0x9e919b1b, 0x4fc5c080, 0xa220dc61, 0x694b775a, 0x161a121c,
+ 0x0aba93e2, 0xe52aa0c0, 0x43e0223c, 0x1d171b12, 0x0b0d090e,
+ 0xadc78bf2, 0xb9a8b62d, 0xc8a91e14, 0x8519f157, 0x4c0775af,
+ 0xbbdd99ee, 0xfd607fa3, 0x9f2601f7, 0xbcf5725c, 0xc53b6644,
+ 0x347efb5b, 0x7629438b, 0xdcc623cb, 0x68fcedb6, 0x63f1e4b8,
+ 0xcadc31d7, 0x10856342, 0x40229713, 0x2011c684, 0x7d244a85,
+ 0xf83dbbd2, 0x1132f9ae, 0x6da129c7, 0x4b2f9e1d, 0xf330b2dc,
+ 0xec52860d, 0xd0e3c177, 0x6c16b32b, 0x99b970a9, 0xfa489411,
+ 0x2264e947, 0xc48cfca8, 0x1a3ff0a0, 0xd82c7d56, 0xef903322,
+ 0xc74e4987, 0xc1d138d9, 0xfea2ca8c, 0x360bd498, 0xcf81f5a6,
+ 0x28de7aa5, 0x268eb7da, 0xa4bfad3f, 0xe49d3a2c, 0x0d927850,
+ 0x9bcc5f6a, 0x62467e54, 0xc2138df6, 0xe8b8d890, 0x5ef7392e,
+ 0xf5afc382, 0xbe805d9f, 0x7c93d069, 0xa92dd56f, 0xb31225cf,
+ 0x3b99acc8, 0xa77d1810, 0x6e639ce8, 0x7bbb3bdb, 0x097826cd,
+ 0xf418596e, 0x01b79aec, 0xa89a4f83, 0x656e95e6, 0x7ee6ffaa,
+ 0x08cfbc21, 0xe6e815ef, 0xd99be7ba, 0xce366f4a, 0xd4099fea,
+ 0xd67cb029, 0xafb2a431, 0x31233f2a, 0x3094a5c6, 0xc066a235,
+ 0x37bc4e74, 0xa6ca82fc, 0xb0d090e0, 0x15d8a733, 0x4a9804f1,
+ 0xf7daec41, 0x0e50cd7f, 0x2ff69117, 0x8dd64d76, 0x4db0ef43,
+ 0x544daacc, 0xdf0496e4, 0xe3b5d19e, 0x1b886a4c, 0xb81f2cc1,
+ 0x7f516546, 0x04ea5e9d, 0x5d358c01, 0x737487fa, 0x2e410bfb,
+ 0x5a1d67b3, 0x52d2db92, 0x335610e9, 0x1347d66d, 0x8c61d79a,
+ 0x7a0ca137, 0x8e14f859, 0x893c13eb, 0xee27a9ce, 0x35c961b7,
+ 0xede51ce1, 0x3cb1477a, 0x59dfd29c, 0x3f73f255, 0x79ce1418,
+ 0xbf37c773, 0xeacdf753, 0x5baafd5f, 0x146f3ddf, 0x86db4478,
+ 0x81f3afca, 0x3ec468b9, 0x2c342438, 0x5f40a3c2, 0x72c31d16,
+ 0x0c25e2bc, 0x8b493c28, 0x41950dff, 0x7101a839, 0xdeb30c08,
+ 0x9ce4b4d8, 0x90c15664, 0x6184cb7b, 0x70b632d5, 0x745c6c48,
+ 0x4257b8d0
+ };
+
+ private static readonly uint[] Tinv1 =
+ {
+ 0xa7f45150, 0x65417e53, 0xa4171ac3, 0x5e273a96, 0x6bab3bcb,
+ 0x459d1ff1, 0x58faacab, 0x03e34b93, 0xfa302055, 0x6d76adf6,
+ 0x76cc8891, 0x4c02f525, 0xd7e54ffc, 0xcb2ac5d7, 0x44352680,
+ 0xa362b58f, 0x5ab1de49, 0x1bba2567, 0x0eea4598, 0xc0fe5de1,
+ 0x752fc302, 0xf04c8112, 0x97468da3, 0xf9d36bc6, 0x5f8f03e7,
+ 0x9c921595, 0x7a6dbfeb, 0x595295da, 0x83bed42d, 0x217458d3,
+ 0x69e04929, 0xc8c98e44, 0x89c2756a, 0x798ef478, 0x3e58996b,
+ 0x71b927dd, 0x4fe1beb6, 0xad88f017, 0xac20c966, 0x3ace7db4,
+ 0x4adf6318, 0x311ae582, 0x33519760, 0x7f536245, 0x7764b1e0,
+ 0xae6bbb84, 0xa081fe1c, 0x2b08f994, 0x68487058, 0xfd458f19,
+ 0x6cde9487, 0xf87b52b7, 0xd373ab23, 0x024b72e2, 0x8f1fe357,
+ 0xab55662a, 0x28ebb207, 0xc2b52f03, 0x7bc5869a, 0x0837d3a5,
+ 0x872830f2, 0xa5bf23b2, 0x6a0302ba, 0x8216ed5c, 0x1ccf8a2b,
+ 0xb479a792, 0xf207f3f0, 0xe2694ea1, 0xf4da65cd, 0xbe0506d5,
+ 0x6234d11f, 0xfea6c48a, 0x532e349d, 0x55f3a2a0, 0xe18a0532,
+ 0xebf6a475, 0xec830b39, 0xef6040aa, 0x9f715e06, 0x106ebd51,
+ 0x8a213ef9, 0x06dd963d, 0x053eddae, 0xbde64d46, 0x8d5491b5,
+ 0x5dc47105, 0xd406046f, 0x155060ff, 0xfb981924, 0xe9bdd697,
+ 0x434089cc, 0x9ed96777, 0x42e8b0bd, 0x8b890788, 0x5b19e738,
+ 0xeec879db, 0x0a7ca147, 0x0f427ce9, 0x1e84f8c9, 0x00000000,
+ 0x86800983, 0xed2b3248, 0x70111eac, 0x725a6c4e, 0xff0efdfb,
+ 0x38850f56, 0xd5ae3d1e, 0x392d3627, 0xd90f0a64, 0xa65c6821,
+ 0x545b9bd1, 0x2e36243a, 0x670a0cb1, 0xe757930f, 0x96eeb4d2,
+ 0x919b1b9e, 0xc5c0804f, 0x20dc61a2, 0x4b775a69, 0x1a121c16,
+ 0xba93e20a, 0x2aa0c0e5, 0xe0223c43, 0x171b121d, 0x0d090e0b,
+ 0xc78bf2ad, 0xa8b62db9, 0xa91e14c8, 0x19f15785, 0x0775af4c,
+ 0xdd99eebb, 0x607fa3fd, 0x2601f79f, 0xf5725cbc, 0x3b6644c5,
+ 0x7efb5b34, 0x29438b76, 0xc623cbdc, 0xfcedb668, 0xf1e4b863,
+ 0xdc31d7ca, 0x85634210, 0x22971340, 0x11c68420, 0x244a857d,
+ 0x3dbbd2f8, 0x32f9ae11, 0xa129c76d, 0x2f9e1d4b, 0x30b2dcf3,
+ 0x52860dec, 0xe3c177d0, 0x16b32b6c, 0xb970a999, 0x489411fa,
+ 0x64e94722, 0x8cfca8c4, 0x3ff0a01a, 0x2c7d56d8, 0x903322ef,
+ 0x4e4987c7, 0xd138d9c1, 0xa2ca8cfe, 0x0bd49836, 0x81f5a6cf,
+ 0xde7aa528, 0x8eb7da26, 0xbfad3fa4, 0x9d3a2ce4, 0x9278500d,
+ 0xcc5f6a9b, 0x467e5462, 0x138df6c2, 0xb8d890e8, 0xf7392e5e,
+ 0xafc382f5, 0x805d9fbe, 0x93d0697c, 0x2dd56fa9, 0x1225cfb3,
+ 0x99acc83b, 0x7d1810a7, 0x639ce86e, 0xbb3bdb7b, 0x7826cd09,
+ 0x18596ef4, 0xb79aec01, 0x9a4f83a8, 0x6e95e665, 0xe6ffaa7e,
+ 0xcfbc2108, 0xe815efe6, 0x9be7bad9, 0x366f4ace, 0x099fead4,
+ 0x7cb029d6, 0xb2a431af, 0x233f2a31, 0x94a5c630, 0x66a235c0,
+ 0xbc4e7437, 0xca82fca6, 0xd090e0b0, 0xd8a73315, 0x9804f14a,
+ 0xdaec41f7, 0x50cd7f0e, 0xf691172f, 0xd64d768d, 0xb0ef434d,
+ 0x4daacc54, 0x0496e4df, 0xb5d19ee3, 0x886a4c1b, 0x1f2cc1b8,
+ 0x5165467f, 0xea5e9d04, 0x358c015d, 0x7487fa73, 0x410bfb2e,
+ 0x1d67b35a, 0xd2db9252, 0x5610e933, 0x47d66d13, 0x61d79a8c,
+ 0x0ca1377a, 0x14f8598e, 0x3c13eb89, 0x27a9ceee, 0xc961b735,
+ 0xe51ce1ed, 0xb1477a3c, 0xdfd29c59, 0x73f2553f, 0xce141879,
+ 0x37c773bf, 0xcdf753ea, 0xaafd5f5b, 0x6f3ddf14, 0xdb447886,
+ 0xf3afca81, 0xc468b93e, 0x3424382c, 0x40a3c25f, 0xc31d1672,
+ 0x25e2bc0c, 0x493c288b, 0x950dff41, 0x01a83971, 0xb30c08de,
+ 0xe4b4d89c, 0xc1566490, 0x84cb7b61, 0xb632d570, 0x5c6c4874,
+ 0x57b8d042
+ };
+
+ private static readonly uint[] Tinv2 =
+ {
+ 0xf45150a7, 0x417e5365, 0x171ac3a4, 0x273a965e, 0xab3bcb6b,
+ 0x9d1ff145, 0xfaacab58, 0xe34b9303, 0x302055fa, 0x76adf66d,
+ 0xcc889176, 0x02f5254c, 0xe54ffcd7, 0x2ac5d7cb, 0x35268044,
+ 0x62b58fa3, 0xb1de495a, 0xba25671b, 0xea45980e, 0xfe5de1c0,
+ 0x2fc30275, 0x4c8112f0, 0x468da397, 0xd36bc6f9, 0x8f03e75f,
+ 0x9215959c, 0x6dbfeb7a, 0x5295da59, 0xbed42d83, 0x7458d321,
+ 0xe0492969, 0xc98e44c8, 0xc2756a89, 0x8ef47879, 0x58996b3e,
+ 0xb927dd71, 0xe1beb64f, 0x88f017ad, 0x20c966ac, 0xce7db43a,
+ 0xdf63184a, 0x1ae58231, 0x51976033, 0x5362457f, 0x64b1e077,
+ 0x6bbb84ae, 0x81fe1ca0, 0x08f9942b, 0x48705868, 0x458f19fd,
+ 0xde94876c, 0x7b52b7f8, 0x73ab23d3, 0x4b72e202, 0x1fe3578f,
+ 0x55662aab, 0xebb20728, 0xb52f03c2, 0xc5869a7b, 0x37d3a508,
+ 0x2830f287, 0xbf23b2a5, 0x0302ba6a, 0x16ed5c82, 0xcf8a2b1c,
+ 0x79a792b4, 0x07f3f0f2, 0x694ea1e2, 0xda65cdf4, 0x0506d5be,
+ 0x34d11f62, 0xa6c48afe, 0x2e349d53, 0xf3a2a055, 0x8a0532e1,
+ 0xf6a475eb, 0x830b39ec, 0x6040aaef, 0x715e069f, 0x6ebd5110,
+ 0x213ef98a, 0xdd963d06, 0x3eddae05, 0xe64d46bd, 0x5491b58d,
+ 0xc471055d, 0x06046fd4, 0x5060ff15, 0x981924fb, 0xbdd697e9,
+ 0x4089cc43, 0xd967779e, 0xe8b0bd42, 0x8907888b, 0x19e7385b,
+ 0xc879dbee, 0x7ca1470a, 0x427ce90f, 0x84f8c91e, 0x00000000,
+ 0x80098386, 0x2b3248ed, 0x111eac70, 0x5a6c4e72, 0x0efdfbff,
+ 0x850f5638, 0xae3d1ed5, 0x2d362739, 0x0f0a64d9, 0x5c6821a6,
+ 0x5b9bd154, 0x36243a2e, 0x0a0cb167, 0x57930fe7, 0xeeb4d296,
+ 0x9b1b9e91, 0xc0804fc5, 0xdc61a220, 0x775a694b, 0x121c161a,
+ 0x93e20aba, 0xa0c0e52a, 0x223c43e0, 0x1b121d17, 0x090e0b0d,
+ 0x8bf2adc7, 0xb62db9a8, 0x1e14c8a9, 0xf1578519, 0x75af4c07,
+ 0x99eebbdd, 0x7fa3fd60, 0x01f79f26, 0x725cbcf5, 0x6644c53b,
+ 0xfb5b347e, 0x438b7629, 0x23cbdcc6, 0xedb668fc, 0xe4b863f1,
+ 0x31d7cadc, 0x63421085, 0x97134022, 0xc6842011, 0x4a857d24,
+ 0xbbd2f83d, 0xf9ae1132, 0x29c76da1, 0x9e1d4b2f, 0xb2dcf330,
+ 0x860dec52, 0xc177d0e3, 0xb32b6c16, 0x70a999b9, 0x9411fa48,
+ 0xe9472264, 0xfca8c48c, 0xf0a01a3f, 0x7d56d82c, 0x3322ef90,
+ 0x4987c74e, 0x38d9c1d1, 0xca8cfea2, 0xd498360b, 0xf5a6cf81,
+ 0x7aa528de, 0xb7da268e, 0xad3fa4bf, 0x3a2ce49d, 0x78500d92,
+ 0x5f6a9bcc, 0x7e546246, 0x8df6c213, 0xd890e8b8, 0x392e5ef7,
+ 0xc382f5af, 0x5d9fbe80, 0xd0697c93, 0xd56fa92d, 0x25cfb312,
+ 0xacc83b99, 0x1810a77d, 0x9ce86e63, 0x3bdb7bbb, 0x26cd0978,
+ 0x596ef418, 0x9aec01b7, 0x4f83a89a, 0x95e6656e, 0xffaa7ee6,
+ 0xbc2108cf, 0x15efe6e8, 0xe7bad99b, 0x6f4ace36, 0x9fead409,
+ 0xb029d67c, 0xa431afb2, 0x3f2a3123, 0xa5c63094, 0xa235c066,
+ 0x4e7437bc, 0x82fca6ca, 0x90e0b0d0, 0xa73315d8, 0x04f14a98,
+ 0xec41f7da, 0xcd7f0e50, 0x91172ff6, 0x4d768dd6, 0xef434db0,
+ 0xaacc544d, 0x96e4df04, 0xd19ee3b5, 0x6a4c1b88, 0x2cc1b81f,
+ 0x65467f51, 0x5e9d04ea, 0x8c015d35, 0x87fa7374, 0x0bfb2e41,
+ 0x67b35a1d, 0xdb9252d2, 0x10e93356, 0xd66d1347, 0xd79a8c61,
+ 0xa1377a0c, 0xf8598e14, 0x13eb893c, 0xa9ceee27, 0x61b735c9,
+ 0x1ce1ede5, 0x477a3cb1, 0xd29c59df, 0xf2553f73, 0x141879ce,
+ 0xc773bf37, 0xf753eacd, 0xfd5f5baa, 0x3ddf146f, 0x447886db,
+ 0xafca81f3, 0x68b93ec4, 0x24382c34, 0xa3c25f40, 0x1d1672c3,
+ 0xe2bc0c25, 0x3c288b49, 0x0dff4195, 0xa8397101, 0x0c08deb3,
+ 0xb4d89ce4, 0x566490c1, 0xcb7b6184, 0x32d570b6, 0x6c48745c,
+ 0xb8d04257
+ };
+
+ private static readonly uint[] Tinv3 =
+ {
+ 0x5150a7f4, 0x7e536541, 0x1ac3a417, 0x3a965e27, 0x3bcb6bab,
+ 0x1ff1459d, 0xacab58fa, 0x4b9303e3, 0x2055fa30, 0xadf66d76,
+ 0x889176cc, 0xf5254c02, 0x4ffcd7e5, 0xc5d7cb2a, 0x26804435,
+ 0xb58fa362, 0xde495ab1, 0x25671bba, 0x45980eea, 0x5de1c0fe,
+ 0xc302752f, 0x8112f04c, 0x8da39746, 0x6bc6f9d3, 0x03e75f8f,
+ 0x15959c92, 0xbfeb7a6d, 0x95da5952, 0xd42d83be, 0x58d32174,
+ 0x492969e0, 0x8e44c8c9, 0x756a89c2, 0xf478798e, 0x996b3e58,
+ 0x27dd71b9, 0xbeb64fe1, 0xf017ad88, 0xc966ac20, 0x7db43ace,
+ 0x63184adf, 0xe582311a, 0x97603351, 0x62457f53, 0xb1e07764,
+ 0xbb84ae6b, 0xfe1ca081, 0xf9942b08, 0x70586848, 0x8f19fd45,
+ 0x94876cde, 0x52b7f87b, 0xab23d373, 0x72e2024b, 0xe3578f1f,
+ 0x662aab55, 0xb20728eb, 0x2f03c2b5, 0x869a7bc5, 0xd3a50837,
+ 0x30f28728, 0x23b2a5bf, 0x02ba6a03, 0xed5c8216, 0x8a2b1ccf,
+ 0xa792b479, 0xf3f0f207, 0x4ea1e269, 0x65cdf4da, 0x06d5be05,
+ 0xd11f6234, 0xc48afea6, 0x349d532e, 0xa2a055f3, 0x0532e18a,
+ 0xa475ebf6, 0x0b39ec83, 0x40aaef60, 0x5e069f71, 0xbd51106e,
+ 0x3ef98a21, 0x963d06dd, 0xddae053e, 0x4d46bde6, 0x91b58d54,
+ 0x71055dc4, 0x046fd406, 0x60ff1550, 0x1924fb98, 0xd697e9bd,
+ 0x89cc4340, 0x67779ed9, 0xb0bd42e8, 0x07888b89, 0xe7385b19,
+ 0x79dbeec8, 0xa1470a7c, 0x7ce90f42, 0xf8c91e84, 0x00000000,
+ 0x09838680, 0x3248ed2b, 0x1eac7011, 0x6c4e725a, 0xfdfbff0e,
+ 0x0f563885, 0x3d1ed5ae, 0x3627392d, 0x0a64d90f, 0x6821a65c,
+ 0x9bd1545b, 0x243a2e36, 0x0cb1670a, 0x930fe757, 0xb4d296ee,
+ 0x1b9e919b, 0x804fc5c0, 0x61a220dc, 0x5a694b77, 0x1c161a12,
+ 0xe20aba93, 0xc0e52aa0, 0x3c43e022, 0x121d171b, 0x0e0b0d09,
+ 0xf2adc78b, 0x2db9a8b6, 0x14c8a91e, 0x578519f1, 0xaf4c0775,
+ 0xeebbdd99, 0xa3fd607f, 0xf79f2601, 0x5cbcf572, 0x44c53b66,
+ 0x5b347efb, 0x8b762943, 0xcbdcc623, 0xb668fced, 0xb863f1e4,
+ 0xd7cadc31, 0x42108563, 0x13402297, 0x842011c6, 0x857d244a,
+ 0xd2f83dbb, 0xae1132f9, 0xc76da129, 0x1d4b2f9e, 0xdcf330b2,
+ 0x0dec5286, 0x77d0e3c1, 0x2b6c16b3, 0xa999b970, 0x11fa4894,
+ 0x472264e9, 0xa8c48cfc, 0xa01a3ff0, 0x56d82c7d, 0x22ef9033,
+ 0x87c74e49, 0xd9c1d138, 0x8cfea2ca, 0x98360bd4, 0xa6cf81f5,
+ 0xa528de7a, 0xda268eb7, 0x3fa4bfad, 0x2ce49d3a, 0x500d9278,
+ 0x6a9bcc5f, 0x5462467e, 0xf6c2138d, 0x90e8b8d8, 0x2e5ef739,
+ 0x82f5afc3, 0x9fbe805d, 0x697c93d0, 0x6fa92dd5, 0xcfb31225,
+ 0xc83b99ac, 0x10a77d18, 0xe86e639c, 0xdb7bbb3b, 0xcd097826,
+ 0x6ef41859, 0xec01b79a, 0x83a89a4f, 0xe6656e95, 0xaa7ee6ff,
+ 0x2108cfbc, 0xefe6e815, 0xbad99be7, 0x4ace366f, 0xead4099f,
+ 0x29d67cb0, 0x31afb2a4, 0x2a31233f, 0xc63094a5, 0x35c066a2,
+ 0x7437bc4e, 0xfca6ca82, 0xe0b0d090, 0x3315d8a7, 0xf14a9804,
+ 0x41f7daec, 0x7f0e50cd, 0x172ff691, 0x768dd64d, 0x434db0ef,
+ 0xcc544daa, 0xe4df0496, 0x9ee3b5d1, 0x4c1b886a, 0xc1b81f2c,
+ 0x467f5165, 0x9d04ea5e, 0x015d358c, 0xfa737487, 0xfb2e410b,
+ 0xb35a1d67, 0x9252d2db, 0xe9335610, 0x6d1347d6, 0x9a8c61d7,
+ 0x377a0ca1, 0x598e14f8, 0xeb893c13, 0xceee27a9, 0xb735c961,
+ 0xe1ede51c, 0x7a3cb147, 0x9c59dfd2, 0x553f73f2, 0x1879ce14,
+ 0x73bf37c7, 0x53eacdf7, 0x5f5baafd, 0xdf146f3d, 0x7886db44,
+ 0xca81f3af, 0xb93ec468, 0x382c3424, 0xc25f40a3, 0x1672c31d,
+ 0xbc0c25e2, 0x288b493c, 0xff41950d, 0x397101a8, 0x08deb30c,
+ 0xd89ce4b4, 0x6490c156, 0x7b6184cb, 0xd570b632, 0x48745c6c,
+ 0xd04257b8
+ };
+
+ #endregion
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The key.
+ /// The mode.
+ /// The padding.
+ /// is null.
+ /// Keysize is not valid for this algorithm.
+ public AesCipher(byte[] key, CipherMode mode, CipherPadding padding)
+ : base(key, 16, mode, padding)
+ {
+ var keySize = key.Length * 8;
+
+ if (!(keySize == 256 || keySize == 192 || keySize == 128))
+ throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "KeySize '{0}' is not valid for this algorithm.", keySize));
+ }
+
+ ///
+ /// Encrypts the specified region of the input byte array and copies the encrypted data to the specified region of the output byte array.
+ ///
+ /// The input data to encrypt.
+ /// The offset into the input byte array from which to begin using data.
+ /// The number of bytes in the input byte array to use as data.
+ /// The output to which to write encrypted data.
+ /// The offset into the output byte array from which to begin writing data.
+ ///
+ /// The number of bytes encrypted.
+ ///
+ /// or is null.
+ /// or is too short.
+ public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
+ {
+ if (inputBuffer == null)
+ throw new ArgumentNullException("inputBuffer");
+
+ if (outputBuffer == null)
+ throw new ArgumentNullException("outputBuffer");
+
+ if ((inputOffset + (32 / 2)) > inputBuffer.Length)
+ {
+ throw new IndexOutOfRangeException("input buffer too short");
+ }
+
+ if ((outputOffset + (32 / 2)) > outputBuffer.Length)
+ {
+ throw new IndexOutOfRangeException("output buffer too short");
+ }
+
+ if (this._encryptionKey == null)
+ {
+ this._encryptionKey = this.GenerateWorkingKey(true, this.Key);
+ }
+
+ this.UnPackBlock(inputBuffer, inputOffset);
+
+ this.EncryptBlock(this._encryptionKey);
+
+ this.PackBlock(outputBuffer, outputOffset);
+
+ return this.BlockSize;
+ }
+
+ ///
+ /// Decrypts the specified region of the input byte array and copies the decrypted data to the specified region of the output byte array.
+ ///
+ /// The input data to decrypt.
+ /// The offset into the input byte array from which to begin using data.
+ /// The number of bytes in the input byte array to use as data.
+ /// The output to which to write decrypted data.
+ /// The offset into the output byte array from which to begin writing data.
+ ///
+ /// The number of bytes decrypted.
+ ///
+ /// or is null.
+ /// or is too short.
+ public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
+ {
+ if (inputBuffer == null)
+ throw new ArgumentNullException("inputBuffer");
+
+ if (outputBuffer == null)
+ throw new ArgumentNullException("outputBuffer");
+
+ if ((inputOffset + (32 / 2)) > inputBuffer.Length)
+ {
+ throw new IndexOutOfRangeException("input buffer too short");
+ }
+
+ if ((outputOffset + (32 / 2)) > outputBuffer.Length)
+ {
+ throw new IndexOutOfRangeException("output buffer too short");
+ }
+
+ if (this._decryptionKey == null)
+ {
+ this._decryptionKey = this.GenerateWorkingKey(false, this.Key);
+ }
+
+ this.UnPackBlock(inputBuffer, inputOffset);
+
+ this.DecryptBlock(this._decryptionKey);
+
+ this.PackBlock(outputBuffer, outputOffset);
+
+ return this.BlockSize;
+ }
+
+ private uint[] GenerateWorkingKey(bool isEncryption, byte[] key)
+ {
+ int KC = key.Length / 4; // key length in words
+
+ if (((KC != 4) && (KC != 6) && (KC != 8)) || ((KC * 4) != key.Length))
+ throw new ArgumentException("Key length not 128/192/256 bits.");
+
+ _rounds = KC + 6; // This is not always true for the generalized Rijndael that allows larger block sizes
+ uint[] W = new uint[(_rounds + 1) * 4]; // 4 words in a block
+
+ //
+ // copy the key into the round key array
+ //
+
+ int t = 0;
+
+ for (int i = 0; i < key.Length; t++)
+ {
+ W[(t >> 2) * 4 + (t & 3)] = LittleEndianToUInt32(key, i);
+ i += 4;
+ }
+
+ //
+ // while not enough round key material calculated
+ // calculate new values
+ //
+ int k = (_rounds + 1) << 2;
+ for (int i = KC; (i < k); i++)
+ {
+ uint temp = W[((i - 1) >> 2) * 4 + ((i - 1) & 3)];
+ if ((i % KC) == 0)
+ {
+ temp = SubWord(Shift(temp, 8)) ^ rcon[(i / KC) - 1];
+ }
+ else if ((KC > 6) && ((i % KC) == 4))
+ {
+ temp = SubWord(temp);
+ }
+
+ W[(i >> 2) * 4 + (i & 3)] = W[((i - KC) >> 2) * 4 + ((i - KC) & 3)] ^ temp;
+ }
+
+ if (!isEncryption)
+ {
+ for (int j = 1; j < _rounds; j++)
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ W[j * 4 + i] = InvMcol(W[j * 4 + i]);
+ }
+ }
+ }
+
+ return W;
+ }
+
+ private uint Shift(uint r, int shift)
+ {
+ return (r >> shift) | (r << (32 - shift));
+ }
+
+ private uint FFmulX(uint x)
+ {
+ return ((x & m2) << 1) ^ (((x & m1) >> 7) * m3);
+ }
+
+ private uint InvMcol(uint x)
+ {
+ uint f2 = FFmulX(x);
+ uint f4 = FFmulX(f2);
+ uint f8 = FFmulX(f4);
+ uint f9 = x ^ f8;
+
+ return f2 ^ f4 ^ f8 ^ Shift(f2 ^ f9, 8) ^ Shift(f4 ^ f9, 16) ^ Shift(f9, 24);
+ }
+
+ private uint SubWord(uint x)
+ {
+ return (uint)S[x & 255]
+ | (((uint)S[(x >> 8) & 255]) << 8)
+ | (((uint)S[(x >> 16) & 255]) << 16)
+ | (((uint)S[(x >> 24) & 255]) << 24);
+ }
+
+ private void UnPackBlock(byte[] bytes, int off)
+ {
+ C0 = LittleEndianToUInt32(bytes, off);
+ C1 = LittleEndianToUInt32(bytes, off + 4);
+ C2 = LittleEndianToUInt32(bytes, off + 8);
+ C3 = LittleEndianToUInt32(bytes, off + 12);
+ }
+
+ private void PackBlock(byte[] bytes, int off)
+ {
+ UInt32ToLittleEndian(C0, bytes, off);
+ UInt32ToLittleEndian(C1, bytes, off + 4);
+ UInt32ToLittleEndian(C2, bytes, off + 8);
+ UInt32ToLittleEndian(C3, bytes, off + 12);
+ }
+
+ private void EncryptBlock(uint[] KW)
+ {
+ int r;
+ uint r0, r1, r2, r3;
+
+ C0 ^= KW[0 * 4 + 0];
+ C1 ^= KW[0 * 4 + 1];
+ C2 ^= KW[0 * 4 + 2];
+ C3 ^= KW[0 * 4 + 3];
+
+ for (r = 1; r < _rounds - 1; )
+ {
+ r0 = T0[C0 & 255] ^ T1[(C1 >> 8) & 255] ^ T2[(C2 >> 16) & 255] ^ T3[C3 >> 24] ^ KW[r * 4 + 0];
+ r1 = T0[C1 & 255] ^ T1[(C2 >> 8) & 255] ^ T2[(C3 >> 16) & 255] ^ T3[C0 >> 24] ^ KW[r * 4 + 1];
+ r2 = T0[C2 & 255] ^ T1[(C3 >> 8) & 255] ^ T2[(C0 >> 16) & 255] ^ T3[C1 >> 24] ^ KW[r * 4 + 2];
+ r3 = T0[C3 & 255] ^ T1[(C0 >> 8) & 255] ^ T2[(C1 >> 16) & 255] ^ T3[C2 >> 24] ^ KW[r++ * 4 + 3];
+ C0 = T0[r0 & 255] ^ T1[(r1 >> 8) & 255] ^ T2[(r2 >> 16) & 255] ^ T3[r3 >> 24] ^ KW[r * 4 + 0];
+ C1 = T0[r1 & 255] ^ T1[(r2 >> 8) & 255] ^ T2[(r3 >> 16) & 255] ^ T3[r0 >> 24] ^ KW[r * 4 + 1];
+ C2 = T0[r2 & 255] ^ T1[(r3 >> 8) & 255] ^ T2[(r0 >> 16) & 255] ^ T3[r1 >> 24] ^ KW[r * 4 + 2];
+ C3 = T0[r3 & 255] ^ T1[(r0 >> 8) & 255] ^ T2[(r1 >> 16) & 255] ^ T3[r2 >> 24] ^ KW[r++ * 4 + 3];
+ }
+
+ r0 = T0[C0 & 255] ^ T1[(C1 >> 8) & 255] ^ T2[(C2 >> 16) & 255] ^ T3[C3 >> 24] ^ KW[r * 4 + 0];
+ r1 = T0[C1 & 255] ^ T1[(C2 >> 8) & 255] ^ T2[(C3 >> 16) & 255] ^ T3[C0 >> 24] ^ KW[r * 4 + 1];
+ r2 = T0[C2 & 255] ^ T1[(C3 >> 8) & 255] ^ T2[(C0 >> 16) & 255] ^ T3[C1 >> 24] ^ KW[r * 4 + 2];
+ r3 = T0[C3 & 255] ^ T1[(C0 >> 8) & 255] ^ T2[(C1 >> 16) & 255] ^ T3[C2 >> 24] ^ KW[r++ * 4 + 3];
+
+ // the final round's table is a simple function of S so we don't use a whole other four tables for it
+
+ C0 = (uint)S[r0 & 255] ^ (((uint)S[(r1 >> 8) & 255]) << 8) ^ (((uint)S[(r2 >> 16) & 255]) << 16) ^ (((uint)S[r3 >> 24]) << 24) ^ KW[r * 4 + 0];
+ C1 = (uint)S[r1 & 255] ^ (((uint)S[(r2 >> 8) & 255]) << 8) ^ (((uint)S[(r3 >> 16) & 255]) << 16) ^ (((uint)S[r0 >> 24]) << 24) ^ KW[r * 4 + 1];
+ C2 = (uint)S[r2 & 255] ^ (((uint)S[(r3 >> 8) & 255]) << 8) ^ (((uint)S[(r0 >> 16) & 255]) << 16) ^ (((uint)S[r1 >> 24]) << 24) ^ KW[r * 4 + 2];
+ C3 = (uint)S[r3 & 255] ^ (((uint)S[(r0 >> 8) & 255]) << 8) ^ (((uint)S[(r1 >> 16) & 255]) << 16) ^ (((uint)S[r2 >> 24]) << 24) ^ KW[r * 4 + 3];
+ }
+
+ private void DecryptBlock(uint[] KW)
+ {
+ int r;
+ uint r0, r1, r2, r3;
+
+ C0 ^= KW[_rounds * 4 + 0];
+ C1 ^= KW[_rounds * 4 + 1];
+ C2 ^= KW[_rounds * 4 + 2];
+ C3 ^= KW[_rounds * 4 + 3];
+
+ for (r = _rounds - 1; r > 1; )
+ {
+ r0 = Tinv0[C0 & 255] ^ Tinv1[(C3 >> 8) & 255] ^ Tinv2[(C2 >> 16) & 255] ^ Tinv3[C1 >> 24] ^ KW[r * 4 + 0];
+ r1 = Tinv0[C1 & 255] ^ Tinv1[(C0 >> 8) & 255] ^ Tinv2[(C3 >> 16) & 255] ^ Tinv3[C2 >> 24] ^ KW[r * 4 + 1];
+ r2 = Tinv0[C2 & 255] ^ Tinv1[(C1 >> 8) & 255] ^ Tinv2[(C0 >> 16) & 255] ^ Tinv3[C3 >> 24] ^ KW[r * 4 + 2];
+ r3 = Tinv0[C3 & 255] ^ Tinv1[(C2 >> 8) & 255] ^ Tinv2[(C1 >> 16) & 255] ^ Tinv3[C0 >> 24] ^ KW[r-- * 4 + 3];
+ C0 = Tinv0[r0 & 255] ^ Tinv1[(r3 >> 8) & 255] ^ Tinv2[(r2 >> 16) & 255] ^ Tinv3[r1 >> 24] ^ KW[r * 4 + 0];
+ C1 = Tinv0[r1 & 255] ^ Tinv1[(r0 >> 8) & 255] ^ Tinv2[(r3 >> 16) & 255] ^ Tinv3[r2 >> 24] ^ KW[r * 4 + 1];
+ C2 = Tinv0[r2 & 255] ^ Tinv1[(r1 >> 8) & 255] ^ Tinv2[(r0 >> 16) & 255] ^ Tinv3[r3 >> 24] ^ KW[r * 4 + 2];
+ C3 = Tinv0[r3 & 255] ^ Tinv1[(r2 >> 8) & 255] ^ Tinv2[(r1 >> 16) & 255] ^ Tinv3[r0 >> 24] ^ KW[r-- * 4 + 3];
+ }
+
+ r0 = Tinv0[C0 & 255] ^ Tinv1[(C3 >> 8) & 255] ^ Tinv2[(C2 >> 16) & 255] ^ Tinv3[C1 >> 24] ^ KW[r * 4 + 0];
+ r1 = Tinv0[C1 & 255] ^ Tinv1[(C0 >> 8) & 255] ^ Tinv2[(C3 >> 16) & 255] ^ Tinv3[C2 >> 24] ^ KW[r * 4 + 1];
+ r2 = Tinv0[C2 & 255] ^ Tinv1[(C1 >> 8) & 255] ^ Tinv2[(C0 >> 16) & 255] ^ Tinv3[C3 >> 24] ^ KW[r * 4 + 2];
+ r3 = Tinv0[C3 & 255] ^ Tinv1[(C2 >> 8) & 255] ^ Tinv2[(C1 >> 16) & 255] ^ Tinv3[C0 >> 24] ^ KW[r * 4 + 3];
+
+ // the final round's table is a simple function of Si so we don't use a whole other four tables for it
+
+ C0 = (uint)Si[r0 & 255] ^ (((uint)Si[(r3 >> 8) & 255]) << 8) ^ (((uint)Si[(r2 >> 16) & 255]) << 16) ^ (((uint)Si[r1 >> 24]) << 24) ^ KW[0 * 4 + 0];
+ C1 = (uint)Si[r1 & 255] ^ (((uint)Si[(r0 >> 8) & 255]) << 8) ^ (((uint)Si[(r3 >> 16) & 255]) << 16) ^ (((uint)Si[r2 >> 24]) << 24) ^ KW[0 * 4 + 1];
+ C2 = (uint)Si[r2 & 255] ^ (((uint)Si[(r1 >> 8) & 255]) << 8) ^ (((uint)Si[(r0 >> 16) & 255]) << 16) ^ (((uint)Si[r3 >> 24]) << 24) ^ KW[0 * 4 + 2];
+ C3 = (uint)Si[r3 & 255] ^ (((uint)Si[(r2 >> 8) & 255]) << 8) ^ (((uint)Si[(r1 >> 16) & 255]) << 16) ^ (((uint)Si[r0 >> 24]) << 24) ^ KW[0 * 4 + 3];
+ }
+ }
+}
diff --git a/Renci.SshNet/Security/Cryptography/Ciphers/Arc4Cipher.cs b/Renci.SshNet/Security/Cryptography/Ciphers/Arc4Cipher.cs
index 8349c0e..fb3c001 100644
--- a/Renci.SshNet/Security/Cryptography/Ciphers/Arc4Cipher.cs
+++ b/Renci.SshNet/Security/Cryptography/Ciphers/Arc4Cipher.cs
@@ -1,183 +1,175 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace Renci.SshNet.Security.Cryptography.Ciphers
-{
- ///
- /// Implements ARCH4 cipher algorithm
- ///
- public sealed class Arc4Cipher : StreamCipher
- {
- private readonly static int STATE_LENGTH = 256;
-
- ///
- /// Holds the state of the RC4 engine
- ///
- private byte[] _engineState;
-
- private int _x;
-
- private int _y;
-
- private byte[] _workingKey;
-
- ///
- /// Gets the minimum data size.
- ///
- ///
- /// The minimum data size.
- ///
- public override byte MinimumSize
- {
- get { return 0; }
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The key.
- /// if set to true will disharged first 1536 bytes.
- /// is null.
- public Arc4Cipher(byte[] key, bool dischargeFirstBytes)
- : base(key)
- {
- this._workingKey = key;
- SetKey(this._workingKey);
- // The first 1536 bytes of keystream
- // generated by the cipher MUST be discarded, and the first byte of the
- // first encrypted packet MUST be encrypted using the 1537th byte of
- // keystream.
- if (dischargeFirstBytes)
- this.Encrypt(new byte[1536]);
- }
-
- ///
- /// Encrypts the specified region of the input byte array and copies the encrypted data to the specified region of the output byte array.
- ///
- /// The input data to encrypt.
- /// The offset into the input byte array from which to begin using data.
- /// The number of bytes in the input byte array to use as data.
- /// The output to which to write encrypted data.
- /// The offset into the output byte array from which to begin writing data.
- ///
- /// The number of bytes encrypted.
- ///
- public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
- {
- return this.ProcessBytes(inputBuffer, inputOffset, inputCount, outputBuffer, outputOffset);
- }
-
- ///
- /// Decrypts the specified region of the input byte array and copies the decrypted data to the specified region of the output byte array.
- ///
- /// The input data to decrypt.
- /// The offset into the input byte array from which to begin using data.
- /// The number of bytes in the input byte array to use as data.
- /// The output to which to write decrypted data.
- /// The offset into the output byte array from which to begin writing data.
- ///
- /// The number of bytes decrypted.
- ///
- public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
- {
- return this.ProcessBytes(inputBuffer, inputOffset, inputCount, outputBuffer, outputOffset);
- }
-
- ///
- /// Encrypts the specified input.
- ///
- /// The input.
- ///
- /// Encrypted data.
- ///
- ///
- public override byte[] Encrypt(byte[] input)
- {
- var output = new byte[input.Length];
- this.ProcessBytes(input, 0, input.Length, output, 0);
- return output;
- }
-
- ///
- /// Decrypts the specified input.
- ///
- /// The input.
- ///
- /// Decrypted data.
- ///
- ///
- public override byte[] Decrypt(byte[] input)
- {
- var output = new byte[input.Length];
- this.ProcessBytes(input, 0, input.Length, output, 0);
- return output;
- }
-
- private int ProcessBytes(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
- {
- if ((inputOffset + inputCount) > inputBuffer.Length)
- {
- throw new IndexOutOfRangeException("input buffer too short");
- }
-
- if ((outputOffset + inputCount) > outputBuffer.Length)
- {
- throw new IndexOutOfRangeException("output buffer too short");
- }
-
- for (int i = 0; i < inputCount; i++)
- {
- this._x = (this._x + 1) & 0xff;
- this._y = (this._engineState[this._x] + this._y) & 0xff;
-
- // swap
- byte tmp = this._engineState[this._x];
- this._engineState[this._x] = this._engineState[this._y];
- this._engineState[this._y] = tmp;
-
- // xor
- outputBuffer[i + outputOffset] = (byte)(inputBuffer[i + inputOffset] ^ this._engineState[(this._engineState[this._x] + this._engineState[this._y]) & 0xff]);
- }
- return inputCount;
- }
-
- private void Reset()
- {
- SetKey(this._workingKey);
- }
-
- private void SetKey(byte[] keyBytes)
- {
- this._workingKey = keyBytes;
-
- this._x = 0;
- this._y = 0;
-
- if (this._engineState == null)
- {
- this._engineState = new byte[STATE_LENGTH];
- }
-
- // reset the state of the engine
- for (byte i = 0; i < STATE_LENGTH; i++)
- {
- this._engineState[i] = i;
- }
-
- int i1 = 0;
- int i2 = 0;
-
- for (int i = 0; i < STATE_LENGTH; i++)
- {
- i2 = ((keyBytes[i1] & 0xff) + this._engineState[i] + i2) & 0xff;
- // do the byte-swap inline
- byte tmp = this._engineState[i];
- this._engineState[i] = this._engineState[i2];
- this._engineState[i2] = tmp;
- i1 = (i1 + 1) % keyBytes.Length;
- }
- }
- }
-}
+using System;
+
+namespace Renci.SshNet.Security.Cryptography.Ciphers
+{
+ ///
+ /// Implements ARCH4 cipher algorithm
+ ///
+ public sealed class Arc4Cipher : StreamCipher
+ {
+ private static readonly int STATE_LENGTH = 256;
+
+ ///
+ /// Holds the state of the RC4 engine
+ ///
+ private byte[] _engineState;
+
+ private int _x;
+
+ private int _y;
+
+ private byte[] _workingKey;
+
+ ///
+ /// Gets the minimum data size.
+ ///
+ ///
+ /// The minimum data size.
+ ///
+ public override byte MinimumSize
+ {
+ get { return 0; }
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The key.
+ /// if set to true will disharged first 1536 bytes.
+ /// is null.
+ public Arc4Cipher(byte[] key, bool dischargeFirstBytes)
+ : base(key)
+ {
+ this._workingKey = key;
+ SetKey(this._workingKey);
+ // The first 1536 bytes of keystream
+ // generated by the cipher MUST be discarded, and the first byte of the
+ // first encrypted packet MUST be encrypted using the 1537th byte of
+ // keystream.
+ if (dischargeFirstBytes)
+ this.Encrypt(new byte[1536]);
+ }
+
+ ///
+ /// Encrypts the specified region of the input byte array and copies the encrypted data to the specified region of the output byte array.
+ ///
+ /// The input data to encrypt.
+ /// The offset into the input byte array from which to begin using data.
+ /// The number of bytes in the input byte array to use as data.
+ /// The output to which to write encrypted data.
+ /// The offset into the output byte array from which to begin writing data.
+ ///
+ /// The number of bytes encrypted.
+ ///
+ public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
+ {
+ return this.ProcessBytes(inputBuffer, inputOffset, inputCount, outputBuffer, outputOffset);
+ }
+
+ ///
+ /// Decrypts the specified region of the input byte array and copies the decrypted data to the specified region of the output byte array.
+ ///
+ /// The input data to decrypt.
+ /// The offset into the input byte array from which to begin using data.
+ /// The number of bytes in the input byte array to use as data.
+ /// The output to which to write decrypted data.
+ /// The offset into the output byte array from which to begin writing data.
+ ///
+ /// The number of bytes decrypted.
+ ///
+ public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
+ {
+ return this.ProcessBytes(inputBuffer, inputOffset, inputCount, outputBuffer, outputOffset);
+ }
+
+ ///
+ /// Encrypts the specified input.
+ ///
+ /// The input.
+ ///
+ /// Encrypted data.
+ ///
+ ///
+ public override byte[] Encrypt(byte[] input)
+ {
+ var output = new byte[input.Length];
+ this.ProcessBytes(input, 0, input.Length, output, 0);
+ return output;
+ }
+
+ ///
+ /// Decrypts the specified input.
+ ///
+ /// The input.
+ ///
+ /// Decrypted data.
+ ///
+ ///
+ public override byte[] Decrypt(byte[] input)
+ {
+ var output = new byte[input.Length];
+ this.ProcessBytes(input, 0, input.Length, output, 0);
+ return output;
+ }
+
+ private int ProcessBytes(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
+ {
+ if ((inputOffset + inputCount) > inputBuffer.Length)
+ {
+ throw new IndexOutOfRangeException("input buffer too short");
+ }
+
+ if ((outputOffset + inputCount) > outputBuffer.Length)
+ {
+ throw new IndexOutOfRangeException("output buffer too short");
+ }
+
+ for (int i = 0; i < inputCount; i++)
+ {
+ this._x = (this._x + 1) & 0xff;
+ this._y = (this._engineState[this._x] + this._y) & 0xff;
+
+ // swap
+ byte tmp = this._engineState[this._x];
+ this._engineState[this._x] = this._engineState[this._y];
+ this._engineState[this._y] = tmp;
+
+ // xor
+ outputBuffer[i + outputOffset] = (byte)(inputBuffer[i + inputOffset] ^ this._engineState[(this._engineState[this._x] + this._engineState[this._y]) & 0xff]);
+ }
+ return inputCount;
+ }
+
+ private void SetKey(byte[] keyBytes)
+ {
+ this._workingKey = keyBytes;
+
+ this._x = 0;
+ this._y = 0;
+
+ if (this._engineState == null)
+ {
+ this._engineState = new byte[STATE_LENGTH];
+ }
+
+ // reset the state of the engine
+ for (var i = 0; i < STATE_LENGTH; i++)
+ {
+ this._engineState[i] = (byte) i;
+ }
+
+ int i1 = 0;
+ int i2 = 0;
+
+ for (var i = 0; i < STATE_LENGTH; i++)
+ {
+ i2 = ((keyBytes[i1] & 0xff) + this._engineState[i] + i2) & 0xff;
+ // do the byte-swap inline
+ byte tmp = this._engineState[i];
+ this._engineState[i] = this._engineState[i2];
+ this._engineState[i2] = tmp;
+ i1 = (i1 + 1) % keyBytes.Length;
+ }
+ }
+ }
+}
diff --git a/Renci.SshNet/Security/Cryptography/Ciphers/BlowfishCipher.cs b/Renci.SshNet/Security/Cryptography/Ciphers/BlowfishCipher.cs
index 9f4e4ba..f78afec 100644
--- a/Renci.SshNet/Security/Cryptography/Ciphers/BlowfishCipher.cs
+++ b/Renci.SshNet/Security/Cryptography/Ciphers/BlowfishCipher.cs
@@ -1,519 +1,516 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace Renci.SshNet.Security.Cryptography.Ciphers
-{
- ///
- /// Blowfish cipher implementation.
- ///
- public sealed class BlowfishCipher : BlockCipher
- {
- #region Static reference tables
-
- private readonly static uint[] KP =
- {
- 0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344,
- 0xA4093822, 0x299F31D0, 0x082EFA98, 0xEC4E6C89,
- 0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C,
- 0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917,
- 0x9216D5D9, 0x8979FB1B
- },
- KS0 =
- {
- 0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7,
- 0xB8E1AFED, 0x6A267E96, 0xBA7C9045, 0xF12C7F99,
- 0x24A19947, 0xB3916CF7, 0x0801F2E2, 0x858EFC16,
- 0x636920D8, 0x71574E69, 0xA458FEA3, 0xF4933D7E,
- 0x0D95748F, 0x728EB658, 0x718BCD58, 0x82154AEE,
- 0x7B54A41D, 0xC25A59B5, 0x9C30D539, 0x2AF26013,
- 0xC5D1B023, 0x286085F0, 0xCA417918, 0xB8DB38EF,
- 0x8E79DCB0, 0x603A180E, 0x6C9E0E8B, 0xB01E8A3E,
- 0xD71577C1, 0xBD314B27, 0x78AF2FDA, 0x55605C60,
- 0xE65525F3, 0xAA55AB94, 0x57489862, 0x63E81440,
- 0x55CA396A, 0x2AAB10B6, 0xB4CC5C34, 0x1141E8CE,
- 0xA15486AF, 0x7C72E993, 0xB3EE1411, 0x636FBC2A,
- 0x2BA9C55D, 0x741831F6, 0xCE5C3E16, 0x9B87931E,
- 0xAFD6BA33, 0x6C24CF5C, 0x7A325381, 0x28958677,
- 0x3B8F4898, 0x6B4BB9AF, 0xC4BFE81B, 0x66282193,
- 0x61D809CC, 0xFB21A991, 0x487CAC60, 0x5DEC8032,
- 0xEF845D5D, 0xE98575B1, 0xDC262302, 0xEB651B88,
- 0x23893E81, 0xD396ACC5, 0x0F6D6FF3, 0x83F44239,
- 0x2E0B4482, 0xA4842004, 0x69C8F04A, 0x9E1F9B5E,
- 0x21C66842, 0xF6E96C9A, 0x670C9C61, 0xABD388F0,
- 0x6A51A0D2, 0xD8542F68, 0x960FA728, 0xAB5133A3,
- 0x6EEF0B6C, 0x137A3BE4, 0xBA3BF050, 0x7EFB2A98,
- 0xA1F1651D, 0x39AF0176, 0x66CA593E, 0x82430E88,
- 0x8CEE8619, 0x456F9FB4, 0x7D84A5C3, 0x3B8B5EBE,
- 0xE06F75D8, 0x85C12073, 0x401A449F, 0x56C16AA6,
- 0x4ED3AA62, 0x363F7706, 0x1BFEDF72, 0x429B023D,
- 0x37D0D724, 0xD00A1248, 0xDB0FEAD3, 0x49F1C09B,
- 0x075372C9, 0x80991B7B, 0x25D479D8, 0xF6E8DEF7,
- 0xE3FE501A, 0xB6794C3B, 0x976CE0BD, 0x04C006BA,
- 0xC1A94FB6, 0x409F60C4, 0x5E5C9EC2, 0x196A2463,
- 0x68FB6FAF, 0x3E6C53B5, 0x1339B2EB, 0x3B52EC6F,
- 0x6DFC511F, 0x9B30952C, 0xCC814544, 0xAF5EBD09,
- 0xBEE3D004, 0xDE334AFD, 0x660F2807, 0x192E4BB3,
- 0xC0CBA857, 0x45C8740F, 0xD20B5F39, 0xB9D3FBDB,
- 0x5579C0BD, 0x1A60320A, 0xD6A100C6, 0x402C7279,
- 0x679F25FE, 0xFB1FA3CC, 0x8EA5E9F8, 0xDB3222F8,
- 0x3C7516DF, 0xFD616B15, 0x2F501EC8, 0xAD0552AB,
- 0x323DB5FA, 0xFD238760, 0x53317B48, 0x3E00DF82,
- 0x9E5C57BB, 0xCA6F8CA0, 0x1A87562E, 0xDF1769DB,
- 0xD542A8F6, 0x287EFFC3, 0xAC6732C6, 0x8C4F5573,
- 0x695B27B0, 0xBBCA58C8, 0xE1FFA35D, 0xB8F011A0,
- 0x10FA3D98, 0xFD2183B8, 0x4AFCB56C, 0x2DD1D35B,
- 0x9A53E479, 0xB6F84565, 0xD28E49BC, 0x4BFB9790,
- 0xE1DDF2DA, 0xA4CB7E33, 0x62FB1341, 0xCEE4C6E8,
- 0xEF20CADA, 0x36774C01, 0xD07E9EFE, 0x2BF11FB4,
- 0x95DBDA4D, 0xAE909198, 0xEAAD8E71, 0x6B93D5A0,
- 0xD08ED1D0, 0xAFC725E0, 0x8E3C5B2F, 0x8E7594B7,
- 0x8FF6E2FB, 0xF2122B64, 0x8888B812, 0x900DF01C,
- 0x4FAD5EA0, 0x688FC31C, 0xD1CFF191, 0xB3A8C1AD,
- 0x2F2F2218, 0xBE0E1777, 0xEA752DFE, 0x8B021FA1,
- 0xE5A0CC0F, 0xB56F74E8, 0x18ACF3D6, 0xCE89E299,
- 0xB4A84FE0, 0xFD13E0B7, 0x7CC43B81, 0xD2ADA8D9,
- 0x165FA266, 0x80957705, 0x93CC7314, 0x211A1477,
- 0xE6AD2065, 0x77B5FA86, 0xC75442F5, 0xFB9D35CF,
- 0xEBCDAF0C, 0x7B3E89A0, 0xD6411BD3, 0xAE1E7E49,
- 0x00250E2D, 0x2071B35E, 0x226800BB, 0x57B8E0AF,
- 0x2464369B, 0xF009B91E, 0x5563911D, 0x59DFA6AA,
- 0x78C14389, 0xD95A537F, 0x207D5BA2, 0x02E5B9C5,
- 0x83260376, 0x6295CFA9, 0x11C81968, 0x4E734A41,
- 0xB3472DCA, 0x7B14A94A, 0x1B510052, 0x9A532915,
- 0xD60F573F, 0xBC9BC6E4, 0x2B60A476, 0x81E67400,
- 0x08BA6FB5, 0x571BE91F, 0xF296EC6B, 0x2A0DD915,
- 0xB6636521, 0xE7B9F9B6, 0xFF34052E, 0xC5855664,
- 0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A
- },
- KS1 =
- {
- 0x4B7A70E9, 0xB5B32944, 0xDB75092E, 0xC4192623,
- 0xAD6EA6B0, 0x49A7DF7D, 0x9CEE60B8, 0x8FEDB266,
- 0xECAA8C71, 0x699A17FF, 0x5664526C, 0xC2B19EE1,
- 0x193602A5, 0x75094C29, 0xA0591340, 0xE4183A3E,
- 0x3F54989A, 0x5B429D65, 0x6B8FE4D6, 0x99F73FD6,
- 0xA1D29C07, 0xEFE830F5, 0x4D2D38E6, 0xF0255DC1,
- 0x4CDD2086, 0x8470EB26, 0x6382E9C6, 0x021ECC5E,
- 0x09686B3F, 0x3EBAEFC9, 0x3C971814, 0x6B6A70A1,
- 0x687F3584, 0x52A0E286, 0xB79C5305, 0xAA500737,
- 0x3E07841C, 0x7FDEAE5C, 0x8E7D44EC, 0x5716F2B8,
- 0xB03ADA37, 0xF0500C0D, 0xF01C1F04, 0x0200B3FF,
- 0xAE0CF51A, 0x3CB574B2, 0x25837A58, 0xDC0921BD,
- 0xD19113F9, 0x7CA92FF6, 0x94324773, 0x22F54701,
- 0x3AE5E581, 0x37C2DADC, 0xC8B57634, 0x9AF3DDA7,
- 0xA9446146, 0x0FD0030E, 0xECC8C73E, 0xA4751E41,
- 0xE238CD99, 0x3BEA0E2F, 0x3280BBA1, 0x183EB331,
- 0x4E548B38, 0x4F6DB908, 0x6F420D03, 0xF60A04BF,
- 0x2CB81290, 0x24977C79, 0x5679B072, 0xBCAF89AF,
- 0xDE9A771F, 0xD9930810, 0xB38BAE12, 0xDCCF3F2E,
- 0x5512721F, 0x2E6B7124, 0x501ADDE6, 0x9F84CD87,
- 0x7A584718, 0x7408DA17, 0xBC9F9ABC, 0xE94B7D8C,
- 0xEC7AEC3A, 0xDB851DFA, 0x63094366, 0xC464C3D2,
- 0xEF1C1847, 0x3215D908, 0xDD433B37, 0x24C2BA16,
- 0x12A14D43, 0x2A65C451, 0x50940002, 0x133AE4DD,
- 0x71DFF89E, 0x10314E55, 0x81AC77D6, 0x5F11199B,
- 0x043556F1, 0xD7A3C76B, 0x3C11183B, 0x5924A509,
- 0xF28FE6ED, 0x97F1FBFA, 0x9EBABF2C, 0x1E153C6E,
- 0x86E34570, 0xEAE96FB1, 0x860E5E0A, 0x5A3E2AB3,
- 0x771FE71C, 0x4E3D06FA, 0x2965DCB9, 0x99E71D0F,
- 0x803E89D6, 0x5266C825, 0x2E4CC978, 0x9C10B36A,
- 0xC6150EBA, 0x94E2EA78, 0xA5FC3C53, 0x1E0A2DF4,
- 0xF2F74EA7, 0x361D2B3D, 0x1939260F, 0x19C27960,
- 0x5223A708, 0xF71312B6, 0xEBADFE6E, 0xEAC31F66,
- 0xE3BC4595, 0xA67BC883, 0xB17F37D1, 0x018CFF28,
- 0xC332DDEF, 0xBE6C5AA5, 0x65582185, 0x68AB9802,
- 0xEECEA50F, 0xDB2F953B, 0x2AEF7DAD, 0x5B6E2F84,
- 0x1521B628, 0x29076170, 0xECDD4775, 0x619F1510,
- 0x13CCA830, 0xEB61BD96, 0x0334FE1E, 0xAA0363CF,
- 0xB5735C90, 0x4C70A239, 0xD59E9E0B, 0xCBAADE14,
- 0xEECC86BC, 0x60622CA7, 0x9CAB5CAB, 0xB2F3846E,
- 0x648B1EAF, 0x19BDF0CA, 0xA02369B9, 0x655ABB50,
- 0x40685A32, 0x3C2AB4B3, 0x319EE9D5, 0xC021B8F7,
- 0x9B540B19, 0x875FA099, 0x95F7997E, 0x623D7DA8,
- 0xF837889A, 0x97E32D77, 0x11ED935F, 0x16681281,
- 0x0E358829, 0xC7E61FD6, 0x96DEDFA1, 0x7858BA99,
- 0x57F584A5, 0x1B227263, 0x9B83C3FF, 0x1AC24696,
- 0xCDB30AEB, 0x532E3054, 0x8FD948E4, 0x6DBC3128,
- 0x58EBF2EF, 0x34C6FFEA, 0xFE28ED61, 0xEE7C3C73,
- 0x5D4A14D9, 0xE864B7E3, 0x42105D14, 0x203E13E0,
- 0x45EEE2B6, 0xA3AAABEA, 0xDB6C4F15, 0xFACB4FD0,
- 0xC742F442, 0xEF6ABBB5, 0x654F3B1D, 0x41CD2105,
- 0xD81E799E, 0x86854DC7, 0xE44B476A, 0x3D816250,
- 0xCF62A1F2, 0x5B8D2646, 0xFC8883A0, 0xC1C7B6A3,
- 0x7F1524C3, 0x69CB7492, 0x47848A0B, 0x5692B285,
- 0x095BBF00, 0xAD19489D, 0x1462B174, 0x23820E00,
- 0x58428D2A, 0x0C55F5EA, 0x1DADF43E, 0x233F7061,
- 0x3372F092, 0x8D937E41, 0xD65FECF1, 0x6C223BDB,
- 0x7CDE3759, 0xCBEE7460, 0x4085F2A7, 0xCE77326E,
- 0xA6078084, 0x19F8509E, 0xE8EFD855, 0x61D99735,
- 0xA969A7AA, 0xC50C06C2, 0x5A04ABFC, 0x800BCADC,
- 0x9E447A2E, 0xC3453484, 0xFDD56705, 0x0E1E9EC9,
- 0xDB73DBD3, 0x105588CD, 0x675FDA79, 0xE3674340,
- 0xC5C43465, 0x713E38D8, 0x3D28F89E, 0xF16DFF20,
- 0x153E21E7, 0x8FB03D4A, 0xE6E39F2B, 0xDB83ADF7
- },
- KS2 =
- {
- 0xE93D5A68, 0x948140F7, 0xF64C261C, 0x94692934,
- 0x411520F7, 0x7602D4F7, 0xBCF46B2E, 0xD4A20068,
- 0xD4082471, 0x3320F46A, 0x43B7D4B7, 0x500061AF,
- 0x1E39F62E, 0x97244546, 0x14214F74, 0xBF8B8840,
- 0x4D95FC1D, 0x96B591AF, 0x70F4DDD3, 0x66A02F45,
- 0xBFBC09EC, 0x03BD9785, 0x7FAC6DD0, 0x31CB8504,
- 0x96EB27B3, 0x55FD3941, 0xDA2547E6, 0xABCA0A9A,
- 0x28507825, 0x530429F4, 0x0A2C86DA, 0xE9B66DFB,
- 0x68DC1462, 0xD7486900, 0x680EC0A4, 0x27A18DEE,
- 0x4F3FFEA2, 0xE887AD8C, 0xB58CE006, 0x7AF4D6B6,
- 0xAACE1E7C, 0xD3375FEC, 0xCE78A399, 0x406B2A42,
- 0x20FE9E35, 0xD9F385B9, 0xEE39D7AB, 0x3B124E8B,
- 0x1DC9FAF7, 0x4B6D1856, 0x26A36631, 0xEAE397B2,
- 0x3A6EFA74, 0xDD5B4332, 0x6841E7F7, 0xCA7820FB,
- 0xFB0AF54E, 0xD8FEB397, 0x454056AC, 0xBA489527,
- 0x55533A3A, 0x20838D87, 0xFE6BA9B7, 0xD096954B,
- 0x55A867BC, 0xA1159A58, 0xCCA92963, 0x99E1DB33,
- 0xA62A4A56, 0x3F3125F9, 0x5EF47E1C, 0x9029317C,
- 0xFDF8E802, 0x04272F70, 0x80BB155C, 0x05282CE3,
- 0x95C11548, 0xE4C66D22, 0x48C1133F, 0xC70F86DC,
- 0x07F9C9EE, 0x41041F0F, 0x404779A4, 0x5D886E17,
- 0x325F51EB, 0xD59BC0D1, 0xF2BCC18F, 0x41113564,
- 0x257B7834, 0x602A9C60, 0xDFF8E8A3, 0x1F636C1B,
- 0x0E12B4C2, 0x02E1329E, 0xAF664FD1, 0xCAD18115,
- 0x6B2395E0, 0x333E92E1, 0x3B240B62, 0xEEBEB922,
- 0x85B2A20E, 0xE6BA0D99, 0xDE720C8C, 0x2DA2F728,
- 0xD0127845, 0x95B794FD, 0x647D0862, 0xE7CCF5F0,
- 0x5449A36F, 0x877D48FA, 0xC39DFD27, 0xF33E8D1E,
- 0x0A476341, 0x992EFF74, 0x3A6F6EAB, 0xF4F8FD37,
- 0xA812DC60, 0xA1EBDDF8, 0x991BE14C, 0xDB6E6B0D,
- 0xC67B5510, 0x6D672C37, 0x2765D43B, 0xDCD0E804,
- 0xF1290DC7, 0xCC00FFA3, 0xB5390F92, 0x690FED0B,
- 0x667B9FFB, 0xCEDB7D9C, 0xA091CF0B, 0xD9155EA3,
- 0xBB132F88, 0x515BAD24, 0x7B9479BF, 0x763BD6EB,
- 0x37392EB3, 0xCC115979, 0x8026E297, 0xF42E312D,
- 0x6842ADA7, 0xC66A2B3B, 0x12754CCC, 0x782EF11C,
- 0x6A124237, 0xB79251E7, 0x06A1BBE6, 0x4BFB6350,
- 0x1A6B1018, 0x11CAEDFA, 0x3D25BDD8, 0xE2E1C3C9,
- 0x44421659, 0x0A121386, 0xD90CEC6E, 0xD5ABEA2A,
- 0x64AF674E, 0xDA86A85F, 0xBEBFE988, 0x64E4C3FE,
- 0x9DBC8057, 0xF0F7C086, 0x60787BF8, 0x6003604D,
- 0xD1FD8346, 0xF6381FB0, 0x7745AE04, 0xD736FCCC,
- 0x83426B33, 0xF01EAB71, 0xB0804187, 0x3C005E5F,
- 0x77A057BE, 0xBDE8AE24, 0x55464299, 0xBF582E61,
- 0x4E58F48F, 0xF2DDFDA2, 0xF474EF38, 0x8789BDC2,
- 0x5366F9C3, 0xC8B38E74, 0xB475F255, 0x46FCD9B9,
- 0x7AEB2661, 0x8B1DDF84, 0x846A0E79, 0x915F95E2,
- 0x466E598E, 0x20B45770, 0x8CD55591, 0xC902DE4C,
- 0xB90BACE1, 0xBB8205D0, 0x11A86248, 0x7574A99E,
- 0xB77F19B6, 0xE0A9DC09, 0x662D09A1, 0xC4324633,
- 0xE85A1F02, 0x09F0BE8C, 0x4A99A025, 0x1D6EFE10,
- 0x1AB93D1D, 0x0BA5A4DF, 0xA186F20F, 0x2868F169,
- 0xDCB7DA83, 0x573906FE, 0xA1E2CE9B, 0x4FCD7F52,
- 0x50115E01, 0xA70683FA, 0xA002B5C4, 0x0DE6D027,
- 0x9AF88C27, 0x773F8641, 0xC3604C06, 0x61A806B5,
- 0xF0177A28, 0xC0F586E0, 0x006058AA, 0x30DC7D62,
- 0x11E69ED7, 0x2338EA63, 0x53C2DD94, 0xC2C21634,
- 0xBBCBEE56, 0x90BCB6DE, 0xEBFC7DA1, 0xCE591D76,
- 0x6F05E409, 0x4B7C0188, 0x39720A3D, 0x7C927C24,
- 0x86E3725F, 0x724D9DB9, 0x1AC15BB4, 0xD39EB8FC,
- 0xED545578, 0x08FCA5B5, 0xD83D7CD3, 0x4DAD0FC4,
- 0x1E50EF5E, 0xB161E6F8, 0xA28514D9, 0x6C51133C,
- 0x6FD5C7E7, 0x56E14EC4, 0x362ABFCE, 0xDDC6C837,
- 0xD79A3234, 0x92638212, 0x670EFA8E, 0x406000E0
- },
- KS3 =
- {
- 0x3A39CE37, 0xD3FAF5CF, 0xABC27737, 0x5AC52D1B,
- 0x5CB0679E, 0x4FA33742, 0xD3822740, 0x99BC9BBE,
- 0xD5118E9D, 0xBF0F7315, 0xD62D1C7E, 0xC700C47B,
- 0xB78C1B6B, 0x21A19045, 0xB26EB1BE, 0x6A366EB4,
- 0x5748AB2F, 0xBC946E79, 0xC6A376D2, 0x6549C2C8,
- 0x530FF8EE, 0x468DDE7D, 0xD5730A1D, 0x4CD04DC6,
- 0x2939BBDB, 0xA9BA4650, 0xAC9526E8, 0xBE5EE304,
- 0xA1FAD5F0, 0x6A2D519A, 0x63EF8CE2, 0x9A86EE22,
- 0xC089C2B8, 0x43242EF6, 0xA51E03AA, 0x9CF2D0A4,
- 0x83C061BA, 0x9BE96A4D, 0x8FE51550, 0xBA645BD6,
- 0x2826A2F9, 0xA73A3AE1, 0x4BA99586, 0xEF5562E9,
- 0xC72FEFD3, 0xF752F7DA, 0x3F046F69, 0x77FA0A59,
- 0x80E4A915, 0x87B08601, 0x9B09E6AD, 0x3B3EE593,
- 0xE990FD5A, 0x9E34D797, 0x2CF0B7D9, 0x022B8B51,
- 0x96D5AC3A, 0x017DA67D, 0xD1CF3ED6, 0x7C7D2D28,
- 0x1F9F25CF, 0xADF2B89B, 0x5AD6B472, 0x5A88F54C,
- 0xE029AC71, 0xE019A5E6, 0x47B0ACFD, 0xED93FA9B,
- 0xE8D3C48D, 0x283B57CC, 0xF8D56629, 0x79132E28,
- 0x785F0191, 0xED756055, 0xF7960E44, 0xE3D35E8C,
- 0x15056DD4, 0x88F46DBA, 0x03A16125, 0x0564F0BD,
- 0xC3EB9E15, 0x3C9057A2, 0x97271AEC, 0xA93A072A,
- 0x1B3F6D9B, 0x1E6321F5, 0xF59C66FB, 0x26DCF319,
- 0x7533D928, 0xB155FDF5, 0x03563482, 0x8ABA3CBB,
- 0x28517711, 0xC20AD9F8, 0xABCC5167, 0xCCAD925F,
- 0x4DE81751, 0x3830DC8E, 0x379D5862, 0x9320F991,
- 0xEA7A90C2, 0xFB3E7BCE, 0x5121CE64, 0x774FBE32,
- 0xA8B6E37E, 0xC3293D46, 0x48DE5369, 0x6413E680,
- 0xA2AE0810, 0xDD6DB224, 0x69852DFD, 0x09072166,
- 0xB39A460A, 0x6445C0DD, 0x586CDECF, 0x1C20C8AE,
- 0x5BBEF7DD, 0x1B588D40, 0xCCD2017F, 0x6BB4E3BB,
- 0xDDA26A7E, 0x3A59FF45, 0x3E350A44, 0xBCB4CDD5,
- 0x72EACEA8, 0xFA6484BB, 0x8D6612AE, 0xBF3C6F47,
- 0xD29BE463, 0x542F5D9E, 0xAEC2771B, 0xF64E6370,
- 0x740E0D8D, 0xE75B1357, 0xF8721671, 0xAF537D5D,
- 0x4040CB08, 0x4EB4E2CC, 0x34D2466A, 0x0115AF84,
- 0xE1B00428, 0x95983A1D, 0x06B89FB4, 0xCE6EA048,
- 0x6F3F3B82, 0x3520AB82, 0x011A1D4B, 0x277227F8,
- 0x611560B1, 0xE7933FDC, 0xBB3A792B, 0x344525BD,
- 0xA08839E1, 0x51CE794B, 0x2F32C9B7, 0xA01FBAC9,
- 0xE01CC87E, 0xBCC7D1F6, 0xCF0111C3, 0xA1E8AAC7,
- 0x1A908749, 0xD44FBD9A, 0xD0DADECB, 0xD50ADA38,
- 0x0339C32A, 0xC6913667, 0x8DF9317C, 0xE0B12B4F,
- 0xF79E59B7, 0x43F5BB3A, 0xF2D519FF, 0x27D9459C,
- 0xBF97222C, 0x15E6FC2A, 0x0F91FC71, 0x9B941525,
- 0xFAE59361, 0xCEB69CEB, 0xC2A86459, 0x12BAA8D1,
- 0xB6C1075E, 0xE3056A0C, 0x10D25065, 0xCB03A442,
- 0xE0EC6E0E, 0x1698DB3B, 0x4C98A0BE, 0x3278E964,
- 0x9F1F9532, 0xE0D392DF, 0xD3A0342B, 0x8971F21E,
- 0x1B0A7441, 0x4BA3348C, 0xC5BE7120, 0xC37632D8,
- 0xDF359F8D, 0x9B992F2E, 0xE60B6F47, 0x0FE3F11D,
- 0xE54CDA54, 0x1EDAD891, 0xCE6279CF, 0xCD3E7E6F,
- 0x1618B166, 0xFD2C1D05, 0x848FD2C5, 0xF6FB2299,
- 0xF523F357, 0xA6327623, 0x93A83531, 0x56CCCD02,
- 0xACF08162, 0x5A75EBB5, 0x6E163697, 0x88D273CC,
- 0xDE966292, 0x81B949D0, 0x4C50901B, 0x71C65614,
- 0xE6C6C7BD, 0x327A140A, 0x45E1D006, 0xC3F27B9A,
- 0xC9AA53FD, 0x62A80F00, 0xBB25BFE2, 0x35BDD2F6,
- 0x71126905, 0xB2040222, 0xB6CBCF7C, 0xCD769C2B,
- 0x53113EC0, 0x1640E3D3, 0x38ABBD60, 0x2547ADF0,
- 0xBA38209C, 0xF746CE76, 0x77AFA1C5, 0x20756060,
- 0x85CBFE4E, 0x8AE88DD8, 0x7AAAF9B0, 0x4CF9AA7E,
- 0x1948C25C, 0x02FB8A8C, 0x01C36AE4, 0xD6EBE1F9,
- 0x90D4F869, 0xA65CDEA0, 0x3F09252D, 0xC208E69F,
- 0xB74E6132, 0xCE77E25B, 0x578FDFE3, 0x3AC372E6
- };
-
- #endregion
-
- private static readonly int _rounds = 16;
-
- private static readonly int _sboxSk = 256;
-
- private static readonly int _pSize = _rounds + 2;
-
- ///
- /// The s-boxes
- ///
- private readonly uint[] _s0, _s1, _s2, _s3;
-
- ///
- /// The p-array
- ///
- private readonly uint[] _p;
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The key.
- /// The mode.
- /// The padding.
- /// is null.
- /// Keysize is not valid for this algorithm.
- public BlowfishCipher(byte[] key, CipherMode mode, CipherPadding padding)
- : base(key, 8, mode, padding)
- {
- var keySize = key.Length * 8;
-
- if (keySize < 1 || keySize > 448)
- throw new ArgumentException(string.Format("KeySize '{0}' is not valid for this algorithm.", keySize));
-
- this._s0 = new uint[_sboxSk];
-
- this._s1 = new uint[_sboxSk];
-
- this._s2 = new uint[_sboxSk];
-
- this._s3 = new uint[_sboxSk];
-
- this._p = new uint[_pSize];
-
- this.SetKey(key);
- }
-
- ///
- /// Encrypts the specified region of the input byte array and copies the encrypted data to the specified region of the output byte array.
- ///
- /// The input data to encrypt.
- /// The offset into the input byte array from which to begin using data.
- /// The number of bytes in the input byte array to use as data.
- /// The output to which to write encrypted data.
- /// The offset into the output byte array from which to begin writing data.
- ///
- /// The number of bytes encrypted.
- ///
- public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
- {
- if (inputCount != this.BlockSize)
- throw new ArgumentException("inputCount");
-
- uint xl = BigEndianToUInt32(inputBuffer, inputOffset);
- uint xr = BigEndianToUInt32(inputBuffer, inputOffset + 4);
-
- xl ^= this._p[0];
-
- for (int i = 1; i < _rounds; i += 2)
- {
- xr ^= F(xl) ^ this._p[i];
- xl ^= F(xr) ^ this._p[i + 1];
- }
-
- xr ^= this._p[_rounds + 1];
-
- UInt32ToBigEndian(xr, outputBuffer, outputOffset);
- UInt32ToBigEndian(xl, outputBuffer, outputOffset + 4);
-
- return this.BlockSize;
- }
-
- ///
- /// Decrypts the specified region of the input byte array and copies the decrypted data to the specified region of the output byte array.
- ///
- /// The input data to decrypt.
- /// The offset into the input byte array from which to begin using data.
- /// The number of bytes in the input byte array to use as data.
- /// The output to which to write decrypted data.
- /// The offset into the output byte array from which to begin writing data.
- ///
- /// The number of bytes decrypted.
- ///
- public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
- {
- if (inputCount != this.BlockSize)
- throw new ArgumentException("inputCount");
-
- uint xl = BigEndianToUInt32(inputBuffer, inputOffset);
- uint xr = BigEndianToUInt32(inputBuffer, inputOffset + 4);
-
- xl ^= this._p[_rounds + 1];
-
- for (int i = _rounds; i > 0; i -= 2)
- {
- xr ^= F(xl) ^ this._p[i];
- xl ^= F(xr) ^ this._p[i - 1];
- }
-
- xr ^= this._p[0];
-
- UInt32ToBigEndian(xr, outputBuffer, outputOffset);
- UInt32ToBigEndian(xl, outputBuffer, outputOffset + 4);
-
- return this.BlockSize;
- }
-
- private uint F(uint x)
- {
- return (((this._s0[x >> 24] + this._s1[(x >> 16) & 0xff]) ^ this._s2[(x >> 8) & 0xff]) + this._s3[x & 0xff]);
- }
-
- private void SetKey(byte[] key)
- {
- /*
- * - comments are from _Applied Crypto_, Schneier, p338
- * please be careful comparing the two, AC numbers the
- * arrays from 1, the enclosed code from 0.
- *
- * (1)
- * Initialise the S-boxes and the P-array, with a fixed string
- * This string contains the hexadecimal digits of pi (3.141...)
- */
- Buffer.BlockCopy(KS0, 0, this._s0, 0, _sboxSk * sizeof(uint));
- Buffer.BlockCopy(KS1, 0, this._s1, 0, _sboxSk * sizeof(uint));
- Buffer.BlockCopy(KS2, 0, this._s2, 0, _sboxSk * sizeof(uint));
- Buffer.BlockCopy(KS3, 0, this._s3, 0, _sboxSk * sizeof(uint));
-
- Buffer.BlockCopy(KP, 0, this._p, 0, _pSize * sizeof(uint));
-
- /*
- * (2)
- * Now, XOR P[0] with the first 32 bits of the key, XOR P[1] with the
- * second 32-bits of the key, and so on for all bits of the key
- * (up to P[17]). Repeatedly cycle through the key bits until the
- * entire P-array has been XOR-ed with the key bits
- */
- int keyLength = key.Length;
- int keyIndex = 0;
-
- for (int i = 0; i < _pSize; i++)
- {
- // Get the 32 bits of the key, in 4 * 8 bit chunks
- uint data = 0x0000000;
- for (int j = 0; j < 4; j++)
- {
- // create a 32 bit block
- data = (data << 8) | (uint)key[keyIndex++];
-
- // wrap when we get to the end of the key
- if (keyIndex >= keyLength)
- {
- keyIndex = 0;
- }
- }
- // XOR the newly created 32 bit chunk onto the P-array
- this._p[i] ^= data;
- }
-
- /*
- * (3)
- * Encrypt the all-zero string with the Blowfish algorithm, using
- * the subkeys described in (1) and (2)
- *
- * (4)
- * Replace P1 and P2 with the output of step (3)
- *
- * (5)
- * Encrypt the output of step(3) using the Blowfish algorithm,
- * with the modified subkeys.
- *
- * (6)
- * Replace P3 and P4 with the output of step (5)
- *
- * (7)
- * Continue the process, replacing all elements of the P-array
- * and then all four S-boxes in order, with the output of the
- * continuously changing Blowfish algorithm
- */
-
- ProcessTable(0, 0, this._p);
- ProcessTable(this._p[_pSize - 2], this._p[_pSize - 1], this._s0);
- ProcessTable(this._s0[_sboxSk - 2], this._s0[_sboxSk - 1], this._s1);
- ProcessTable(this._s1[_sboxSk - 2], this._s1[_sboxSk - 1], this._s2);
- ProcessTable(this._s2[_sboxSk - 2], this._s2[_sboxSk - 1], this._s3);
- }
-
- ///
- /// apply the encryption cycle to each value pair in the table.
- ///
- /// The xl.
- /// The xr.
- /// The table.
- private void ProcessTable(uint xl, uint xr, uint[] table)
- {
- int size = table.Length;
-
- for (int s = 0; s < size; s += 2)
- {
- xl ^= _p[0];
-
- for (int i = 1; i < _rounds; i += 2)
- {
- xr ^= F(xl) ^ _p[i];
- xl ^= F(xr) ^ _p[i + 1];
- }
-
- xr ^= _p[_rounds + 1];
-
- table[s] = xr;
- table[s + 1] = xl;
-
- xr = xl; // end of cycle swap
- xl = table[s];
- }
- }
- }
-}
+using System;
+
+namespace Renci.SshNet.Security.Cryptography.Ciphers
+{
+ ///
+ /// Blowfish cipher implementation.
+ ///
+ public sealed class BlowfishCipher : BlockCipher
+ {
+ #region Static reference tables
+
+ private readonly static uint[] KP =
+ {
+ 0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344,
+ 0xA4093822, 0x299F31D0, 0x082EFA98, 0xEC4E6C89,
+ 0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C,
+ 0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917,
+ 0x9216D5D9, 0x8979FB1B
+ },
+ KS0 =
+ {
+ 0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7,
+ 0xB8E1AFED, 0x6A267E96, 0xBA7C9045, 0xF12C7F99,
+ 0x24A19947, 0xB3916CF7, 0x0801F2E2, 0x858EFC16,
+ 0x636920D8, 0x71574E69, 0xA458FEA3, 0xF4933D7E,
+ 0x0D95748F, 0x728EB658, 0x718BCD58, 0x82154AEE,
+ 0x7B54A41D, 0xC25A59B5, 0x9C30D539, 0x2AF26013,
+ 0xC5D1B023, 0x286085F0, 0xCA417918, 0xB8DB38EF,
+ 0x8E79DCB0, 0x603A180E, 0x6C9E0E8B, 0xB01E8A3E,
+ 0xD71577C1, 0xBD314B27, 0x78AF2FDA, 0x55605C60,
+ 0xE65525F3, 0xAA55AB94, 0x57489862, 0x63E81440,
+ 0x55CA396A, 0x2AAB10B6, 0xB4CC5C34, 0x1141E8CE,
+ 0xA15486AF, 0x7C72E993, 0xB3EE1411, 0x636FBC2A,
+ 0x2BA9C55D, 0x741831F6, 0xCE5C3E16, 0x9B87931E,
+ 0xAFD6BA33, 0x6C24CF5C, 0x7A325381, 0x28958677,
+ 0x3B8F4898, 0x6B4BB9AF, 0xC4BFE81B, 0x66282193,
+ 0x61D809CC, 0xFB21A991, 0x487CAC60, 0x5DEC8032,
+ 0xEF845D5D, 0xE98575B1, 0xDC262302, 0xEB651B88,
+ 0x23893E81, 0xD396ACC5, 0x0F6D6FF3, 0x83F44239,
+ 0x2E0B4482, 0xA4842004, 0x69C8F04A, 0x9E1F9B5E,
+ 0x21C66842, 0xF6E96C9A, 0x670C9C61, 0xABD388F0,
+ 0x6A51A0D2, 0xD8542F68, 0x960FA728, 0xAB5133A3,
+ 0x6EEF0B6C, 0x137A3BE4, 0xBA3BF050, 0x7EFB2A98,
+ 0xA1F1651D, 0x39AF0176, 0x66CA593E, 0x82430E88,
+ 0x8CEE8619, 0x456F9FB4, 0x7D84A5C3, 0x3B8B5EBE,
+ 0xE06F75D8, 0x85C12073, 0x401A449F, 0x56C16AA6,
+ 0x4ED3AA62, 0x363F7706, 0x1BFEDF72, 0x429B023D,
+ 0x37D0D724, 0xD00A1248, 0xDB0FEAD3, 0x49F1C09B,
+ 0x075372C9, 0x80991B7B, 0x25D479D8, 0xF6E8DEF7,
+ 0xE3FE501A, 0xB6794C3B, 0x976CE0BD, 0x04C006BA,
+ 0xC1A94FB6, 0x409F60C4, 0x5E5C9EC2, 0x196A2463,
+ 0x68FB6FAF, 0x3E6C53B5, 0x1339B2EB, 0x3B52EC6F,
+ 0x6DFC511F, 0x9B30952C, 0xCC814544, 0xAF5EBD09,
+ 0xBEE3D004, 0xDE334AFD, 0x660F2807, 0x192E4BB3,
+ 0xC0CBA857, 0x45C8740F, 0xD20B5F39, 0xB9D3FBDB,
+ 0x5579C0BD, 0x1A60320A, 0xD6A100C6, 0x402C7279,
+ 0x679F25FE, 0xFB1FA3CC, 0x8EA5E9F8, 0xDB3222F8,
+ 0x3C7516DF, 0xFD616B15, 0x2F501EC8, 0xAD0552AB,
+ 0x323DB5FA, 0xFD238760, 0x53317B48, 0x3E00DF82,
+ 0x9E5C57BB, 0xCA6F8CA0, 0x1A87562E, 0xDF1769DB,
+ 0xD542A8F6, 0x287EFFC3, 0xAC6732C6, 0x8C4F5573,
+ 0x695B27B0, 0xBBCA58C8, 0xE1FFA35D, 0xB8F011A0,
+ 0x10FA3D98, 0xFD2183B8, 0x4AFCB56C, 0x2DD1D35B,
+ 0x9A53E479, 0xB6F84565, 0xD28E49BC, 0x4BFB9790,
+ 0xE1DDF2DA, 0xA4CB7E33, 0x62FB1341, 0xCEE4C6E8,
+ 0xEF20CADA, 0x36774C01, 0xD07E9EFE, 0x2BF11FB4,
+ 0x95DBDA4D, 0xAE909198, 0xEAAD8E71, 0x6B93D5A0,
+ 0xD08ED1D0, 0xAFC725E0, 0x8E3C5B2F, 0x8E7594B7,
+ 0x8FF6E2FB, 0xF2122B64, 0x8888B812, 0x900DF01C,
+ 0x4FAD5EA0, 0x688FC31C, 0xD1CFF191, 0xB3A8C1AD,
+ 0x2F2F2218, 0xBE0E1777, 0xEA752DFE, 0x8B021FA1,
+ 0xE5A0CC0F, 0xB56F74E8, 0x18ACF3D6, 0xCE89E299,
+ 0xB4A84FE0, 0xFD13E0B7, 0x7CC43B81, 0xD2ADA8D9,
+ 0x165FA266, 0x80957705, 0x93CC7314, 0x211A1477,
+ 0xE6AD2065, 0x77B5FA86, 0xC75442F5, 0xFB9D35CF,
+ 0xEBCDAF0C, 0x7B3E89A0, 0xD6411BD3, 0xAE1E7E49,
+ 0x00250E2D, 0x2071B35E, 0x226800BB, 0x57B8E0AF,
+ 0x2464369B, 0xF009B91E, 0x5563911D, 0x59DFA6AA,
+ 0x78C14389, 0xD95A537F, 0x207D5BA2, 0x02E5B9C5,
+ 0x83260376, 0x6295CFA9, 0x11C81968, 0x4E734A41,
+ 0xB3472DCA, 0x7B14A94A, 0x1B510052, 0x9A532915,
+ 0xD60F573F, 0xBC9BC6E4, 0x2B60A476, 0x81E67400,
+ 0x08BA6FB5, 0x571BE91F, 0xF296EC6B, 0x2A0DD915,
+ 0xB6636521, 0xE7B9F9B6, 0xFF34052E, 0xC5855664,
+ 0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A
+ },
+ KS1 =
+ {
+ 0x4B7A70E9, 0xB5B32944, 0xDB75092E, 0xC4192623,
+ 0xAD6EA6B0, 0x49A7DF7D, 0x9CEE60B8, 0x8FEDB266,
+ 0xECAA8C71, 0x699A17FF, 0x5664526C, 0xC2B19EE1,
+ 0x193602A5, 0x75094C29, 0xA0591340, 0xE4183A3E,
+ 0x3F54989A, 0x5B429D65, 0x6B8FE4D6, 0x99F73FD6,
+ 0xA1D29C07, 0xEFE830F5, 0x4D2D38E6, 0xF0255DC1,
+ 0x4CDD2086, 0x8470EB26, 0x6382E9C6, 0x021ECC5E,
+ 0x09686B3F, 0x3EBAEFC9, 0x3C971814, 0x6B6A70A1,
+ 0x687F3584, 0x52A0E286, 0xB79C5305, 0xAA500737,
+ 0x3E07841C, 0x7FDEAE5C, 0x8E7D44EC, 0x5716F2B8,
+ 0xB03ADA37, 0xF0500C0D, 0xF01C1F04, 0x0200B3FF,
+ 0xAE0CF51A, 0x3CB574B2, 0x25837A58, 0xDC0921BD,
+ 0xD19113F9, 0x7CA92FF6, 0x94324773, 0x22F54701,
+ 0x3AE5E581, 0x37C2DADC, 0xC8B57634, 0x9AF3DDA7,
+ 0xA9446146, 0x0FD0030E, 0xECC8C73E, 0xA4751E41,
+ 0xE238CD99, 0x3BEA0E2F, 0x3280BBA1, 0x183EB331,
+ 0x4E548B38, 0x4F6DB908, 0x6F420D03, 0xF60A04BF,
+ 0x2CB81290, 0x24977C79, 0x5679B072, 0xBCAF89AF,
+ 0xDE9A771F, 0xD9930810, 0xB38BAE12, 0xDCCF3F2E,
+ 0x5512721F, 0x2E6B7124, 0x501ADDE6, 0x9F84CD87,
+ 0x7A584718, 0x7408DA17, 0xBC9F9ABC, 0xE94B7D8C,
+ 0xEC7AEC3A, 0xDB851DFA, 0x63094366, 0xC464C3D2,
+ 0xEF1C1847, 0x3215D908, 0xDD433B37, 0x24C2BA16,
+ 0x12A14D43, 0x2A65C451, 0x50940002, 0x133AE4DD,
+ 0x71DFF89E, 0x10314E55, 0x81AC77D6, 0x5F11199B,
+ 0x043556F1, 0xD7A3C76B, 0x3C11183B, 0x5924A509,
+ 0xF28FE6ED, 0x97F1FBFA, 0x9EBABF2C, 0x1E153C6E,
+ 0x86E34570, 0xEAE96FB1, 0x860E5E0A, 0x5A3E2AB3,
+ 0x771FE71C, 0x4E3D06FA, 0x2965DCB9, 0x99E71D0F,
+ 0x803E89D6, 0x5266C825, 0x2E4CC978, 0x9C10B36A,
+ 0xC6150EBA, 0x94E2EA78, 0xA5FC3C53, 0x1E0A2DF4,
+ 0xF2F74EA7, 0x361D2B3D, 0x1939260F, 0x19C27960,
+ 0x5223A708, 0xF71312B6, 0xEBADFE6E, 0xEAC31F66,
+ 0xE3BC4595, 0xA67BC883, 0xB17F37D1, 0x018CFF28,
+ 0xC332DDEF, 0xBE6C5AA5, 0x65582185, 0x68AB9802,
+ 0xEECEA50F, 0xDB2F953B, 0x2AEF7DAD, 0x5B6E2F84,
+ 0x1521B628, 0x29076170, 0xECDD4775, 0x619F1510,
+ 0x13CCA830, 0xEB61BD96, 0x0334FE1E, 0xAA0363CF,
+ 0xB5735C90, 0x4C70A239, 0xD59E9E0B, 0xCBAADE14,
+ 0xEECC86BC, 0x60622CA7, 0x9CAB5CAB, 0xB2F3846E,
+ 0x648B1EAF, 0x19BDF0CA, 0xA02369B9, 0x655ABB50,
+ 0x40685A32, 0x3C2AB4B3, 0x319EE9D5, 0xC021B8F7,
+ 0x9B540B19, 0x875FA099, 0x95F7997E, 0x623D7DA8,
+ 0xF837889A, 0x97E32D77, 0x11ED935F, 0x16681281,
+ 0x0E358829, 0xC7E61FD6, 0x96DEDFA1, 0x7858BA99,
+ 0x57F584A5, 0x1B227263, 0x9B83C3FF, 0x1AC24696,
+ 0xCDB30AEB, 0x532E3054, 0x8FD948E4, 0x6DBC3128,
+ 0x58EBF2EF, 0x34C6FFEA, 0xFE28ED61, 0xEE7C3C73,
+ 0x5D4A14D9, 0xE864B7E3, 0x42105D14, 0x203E13E0,
+ 0x45EEE2B6, 0xA3AAABEA, 0xDB6C4F15, 0xFACB4FD0,
+ 0xC742F442, 0xEF6ABBB5, 0x654F3B1D, 0x41CD2105,
+ 0xD81E799E, 0x86854DC7, 0xE44B476A, 0x3D816250,
+ 0xCF62A1F2, 0x5B8D2646, 0xFC8883A0, 0xC1C7B6A3,
+ 0x7F1524C3, 0x69CB7492, 0x47848A0B, 0x5692B285,
+ 0x095BBF00, 0xAD19489D, 0x1462B174, 0x23820E00,
+ 0x58428D2A, 0x0C55F5EA, 0x1DADF43E, 0x233F7061,
+ 0x3372F092, 0x8D937E41, 0xD65FECF1, 0x6C223BDB,
+ 0x7CDE3759, 0xCBEE7460, 0x4085F2A7, 0xCE77326E,
+ 0xA6078084, 0x19F8509E, 0xE8EFD855, 0x61D99735,
+ 0xA969A7AA, 0xC50C06C2, 0x5A04ABFC, 0x800BCADC,
+ 0x9E447A2E, 0xC3453484, 0xFDD56705, 0x0E1E9EC9,
+ 0xDB73DBD3, 0x105588CD, 0x675FDA79, 0xE3674340,
+ 0xC5C43465, 0x713E38D8, 0x3D28F89E, 0xF16DFF20,
+ 0x153E21E7, 0x8FB03D4A, 0xE6E39F2B, 0xDB83ADF7
+ },
+ KS2 =
+ {
+ 0xE93D5A68, 0x948140F7, 0xF64C261C, 0x94692934,
+ 0x411520F7, 0x7602D4F7, 0xBCF46B2E, 0xD4A20068,
+ 0xD4082471, 0x3320F46A, 0x43B7D4B7, 0x500061AF,
+ 0x1E39F62E, 0x97244546, 0x14214F74, 0xBF8B8840,
+ 0x4D95FC1D, 0x96B591AF, 0x70F4DDD3, 0x66A02F45,
+ 0xBFBC09EC, 0x03BD9785, 0x7FAC6DD0, 0x31CB8504,
+ 0x96EB27B3, 0x55FD3941, 0xDA2547E6, 0xABCA0A9A,
+ 0x28507825, 0x530429F4, 0x0A2C86DA, 0xE9B66DFB,
+ 0x68DC1462, 0xD7486900, 0x680EC0A4, 0x27A18DEE,
+ 0x4F3FFEA2, 0xE887AD8C, 0xB58CE006, 0x7AF4D6B6,
+ 0xAACE1E7C, 0xD3375FEC, 0xCE78A399, 0x406B2A42,
+ 0x20FE9E35, 0xD9F385B9, 0xEE39D7AB, 0x3B124E8B,
+ 0x1DC9FAF7, 0x4B6D1856, 0x26A36631, 0xEAE397B2,
+ 0x3A6EFA74, 0xDD5B4332, 0x6841E7F7, 0xCA7820FB,
+ 0xFB0AF54E, 0xD8FEB397, 0x454056AC, 0xBA489527,
+ 0x55533A3A, 0x20838D87, 0xFE6BA9B7, 0xD096954B,
+ 0x55A867BC, 0xA1159A58, 0xCCA92963, 0x99E1DB33,
+ 0xA62A4A56, 0x3F3125F9, 0x5EF47E1C, 0x9029317C,
+ 0xFDF8E802, 0x04272F70, 0x80BB155C, 0x05282CE3,
+ 0x95C11548, 0xE4C66D22, 0x48C1133F, 0xC70F86DC,
+ 0x07F9C9EE, 0x41041F0F, 0x404779A4, 0x5D886E17,
+ 0x325F51EB, 0xD59BC0D1, 0xF2BCC18F, 0x41113564,
+ 0x257B7834, 0x602A9C60, 0xDFF8E8A3, 0x1F636C1B,
+ 0x0E12B4C2, 0x02E1329E, 0xAF664FD1, 0xCAD18115,
+ 0x6B2395E0, 0x333E92E1, 0x3B240B62, 0xEEBEB922,
+ 0x85B2A20E, 0xE6BA0D99, 0xDE720C8C, 0x2DA2F728,
+ 0xD0127845, 0x95B794FD, 0x647D0862, 0xE7CCF5F0,
+ 0x5449A36F, 0x877D48FA, 0xC39DFD27, 0xF33E8D1E,
+ 0x0A476341, 0x992EFF74, 0x3A6F6EAB, 0xF4F8FD37,
+ 0xA812DC60, 0xA1EBDDF8, 0x991BE14C, 0xDB6E6B0D,
+ 0xC67B5510, 0x6D672C37, 0x2765D43B, 0xDCD0E804,
+ 0xF1290DC7, 0xCC00FFA3, 0xB5390F92, 0x690FED0B,
+ 0x667B9FFB, 0xCEDB7D9C, 0xA091CF0B, 0xD9155EA3,
+ 0xBB132F88, 0x515BAD24, 0x7B9479BF, 0x763BD6EB,
+ 0x37392EB3, 0xCC115979, 0x8026E297, 0xF42E312D,
+ 0x6842ADA7, 0xC66A2B3B, 0x12754CCC, 0x782EF11C,
+ 0x6A124237, 0xB79251E7, 0x06A1BBE6, 0x4BFB6350,
+ 0x1A6B1018, 0x11CAEDFA, 0x3D25BDD8, 0xE2E1C3C9,
+ 0x44421659, 0x0A121386, 0xD90CEC6E, 0xD5ABEA2A,
+ 0x64AF674E, 0xDA86A85F, 0xBEBFE988, 0x64E4C3FE,
+ 0x9DBC8057, 0xF0F7C086, 0x60787BF8, 0x6003604D,
+ 0xD1FD8346, 0xF6381FB0, 0x7745AE04, 0xD736FCCC,
+ 0x83426B33, 0xF01EAB71, 0xB0804187, 0x3C005E5F,
+ 0x77A057BE, 0xBDE8AE24, 0x55464299, 0xBF582E61,
+ 0x4E58F48F, 0xF2DDFDA2, 0xF474EF38, 0x8789BDC2,
+ 0x5366F9C3, 0xC8B38E74, 0xB475F255, 0x46FCD9B9,
+ 0x7AEB2661, 0x8B1DDF84, 0x846A0E79, 0x915F95E2,
+ 0x466E598E, 0x20B45770, 0x8CD55591, 0xC902DE4C,
+ 0xB90BACE1, 0xBB8205D0, 0x11A86248, 0x7574A99E,
+ 0xB77F19B6, 0xE0A9DC09, 0x662D09A1, 0xC4324633,
+ 0xE85A1F02, 0x09F0BE8C, 0x4A99A025, 0x1D6EFE10,
+ 0x1AB93D1D, 0x0BA5A4DF, 0xA186F20F, 0x2868F169,
+ 0xDCB7DA83, 0x573906FE, 0xA1E2CE9B, 0x4FCD7F52,
+ 0x50115E01, 0xA70683FA, 0xA002B5C4, 0x0DE6D027,
+ 0x9AF88C27, 0x773F8641, 0xC3604C06, 0x61A806B5,
+ 0xF0177A28, 0xC0F586E0, 0x006058AA, 0x30DC7D62,
+ 0x11E69ED7, 0x2338EA63, 0x53C2DD94, 0xC2C21634,
+ 0xBBCBEE56, 0x90BCB6DE, 0xEBFC7DA1, 0xCE591D76,
+ 0x6F05E409, 0x4B7C0188, 0x39720A3D, 0x7C927C24,
+ 0x86E3725F, 0x724D9DB9, 0x1AC15BB4, 0xD39EB8FC,
+ 0xED545578, 0x08FCA5B5, 0xD83D7CD3, 0x4DAD0FC4,
+ 0x1E50EF5E, 0xB161E6F8, 0xA28514D9, 0x6C51133C,
+ 0x6FD5C7E7, 0x56E14EC4, 0x362ABFCE, 0xDDC6C837,
+ 0xD79A3234, 0x92638212, 0x670EFA8E, 0x406000E0
+ },
+ KS3 =
+ {
+ 0x3A39CE37, 0xD3FAF5CF, 0xABC27737, 0x5AC52D1B,
+ 0x5CB0679E, 0x4FA33742, 0xD3822740, 0x99BC9BBE,
+ 0xD5118E9D, 0xBF0F7315, 0xD62D1C7E, 0xC700C47B,
+ 0xB78C1B6B, 0x21A19045, 0xB26EB1BE, 0x6A366EB4,
+ 0x5748AB2F, 0xBC946E79, 0xC6A376D2, 0x6549C2C8,
+ 0x530FF8EE, 0x468DDE7D, 0xD5730A1D, 0x4CD04DC6,
+ 0x2939BBDB, 0xA9BA4650, 0xAC9526E8, 0xBE5EE304,
+ 0xA1FAD5F0, 0x6A2D519A, 0x63EF8CE2, 0x9A86EE22,
+ 0xC089C2B8, 0x43242EF6, 0xA51E03AA, 0x9CF2D0A4,
+ 0x83C061BA, 0x9BE96A4D, 0x8FE51550, 0xBA645BD6,
+ 0x2826A2F9, 0xA73A3AE1, 0x4BA99586, 0xEF5562E9,
+ 0xC72FEFD3, 0xF752F7DA, 0x3F046F69, 0x77FA0A59,
+ 0x80E4A915, 0x87B08601, 0x9B09E6AD, 0x3B3EE593,
+ 0xE990FD5A, 0x9E34D797, 0x2CF0B7D9, 0x022B8B51,
+ 0x96D5AC3A, 0x017DA67D, 0xD1CF3ED6, 0x7C7D2D28,
+ 0x1F9F25CF, 0xADF2B89B, 0x5AD6B472, 0x5A88F54C,
+ 0xE029AC71, 0xE019A5E6, 0x47B0ACFD, 0xED93FA9B,
+ 0xE8D3C48D, 0x283B57CC, 0xF8D56629, 0x79132E28,
+ 0x785F0191, 0xED756055, 0xF7960E44, 0xE3D35E8C,
+ 0x15056DD4, 0x88F46DBA, 0x03A16125, 0x0564F0BD,
+ 0xC3EB9E15, 0x3C9057A2, 0x97271AEC, 0xA93A072A,
+ 0x1B3F6D9B, 0x1E6321F5, 0xF59C66FB, 0x26DCF319,
+ 0x7533D928, 0xB155FDF5, 0x03563482, 0x8ABA3CBB,
+ 0x28517711, 0xC20AD9F8, 0xABCC5167, 0xCCAD925F,
+ 0x4DE81751, 0x3830DC8E, 0x379D5862, 0x9320F991,
+ 0xEA7A90C2, 0xFB3E7BCE, 0x5121CE64, 0x774FBE32,
+ 0xA8B6E37E, 0xC3293D46, 0x48DE5369, 0x6413E680,
+ 0xA2AE0810, 0xDD6DB224, 0x69852DFD, 0x09072166,
+ 0xB39A460A, 0x6445C0DD, 0x586CDECF, 0x1C20C8AE,
+ 0x5BBEF7DD, 0x1B588D40, 0xCCD2017F, 0x6BB4E3BB,
+ 0xDDA26A7E, 0x3A59FF45, 0x3E350A44, 0xBCB4CDD5,
+ 0x72EACEA8, 0xFA6484BB, 0x8D6612AE, 0xBF3C6F47,
+ 0xD29BE463, 0x542F5D9E, 0xAEC2771B, 0xF64E6370,
+ 0x740E0D8D, 0xE75B1357, 0xF8721671, 0xAF537D5D,
+ 0x4040CB08, 0x4EB4E2CC, 0x34D2466A, 0x0115AF84,
+ 0xE1B00428, 0x95983A1D, 0x06B89FB4, 0xCE6EA048,
+ 0x6F3F3B82, 0x3520AB82, 0x011A1D4B, 0x277227F8,
+ 0x611560B1, 0xE7933FDC, 0xBB3A792B, 0x344525BD,
+ 0xA08839E1, 0x51CE794B, 0x2F32C9B7, 0xA01FBAC9,
+ 0xE01CC87E, 0xBCC7D1F6, 0xCF0111C3, 0xA1E8AAC7,
+ 0x1A908749, 0xD44FBD9A, 0xD0DADECB, 0xD50ADA38,
+ 0x0339C32A, 0xC6913667, 0x8DF9317C, 0xE0B12B4F,
+ 0xF79E59B7, 0x43F5BB3A, 0xF2D519FF, 0x27D9459C,
+ 0xBF97222C, 0x15E6FC2A, 0x0F91FC71, 0x9B941525,
+ 0xFAE59361, 0xCEB69CEB, 0xC2A86459, 0x12BAA8D1,
+ 0xB6C1075E, 0xE3056A0C, 0x10D25065, 0xCB03A442,
+ 0xE0EC6E0E, 0x1698DB3B, 0x4C98A0BE, 0x3278E964,
+ 0x9F1F9532, 0xE0D392DF, 0xD3A0342B, 0x8971F21E,
+ 0x1B0A7441, 0x4BA3348C, 0xC5BE7120, 0xC37632D8,
+ 0xDF359F8D, 0x9B992F2E, 0xE60B6F47, 0x0FE3F11D,
+ 0xE54CDA54, 0x1EDAD891, 0xCE6279CF, 0xCD3E7E6F,
+ 0x1618B166, 0xFD2C1D05, 0x848FD2C5, 0xF6FB2299,
+ 0xF523F357, 0xA6327623, 0x93A83531, 0x56CCCD02,
+ 0xACF08162, 0x5A75EBB5, 0x6E163697, 0x88D273CC,
+ 0xDE966292, 0x81B949D0, 0x4C50901B, 0x71C65614,
+ 0xE6C6C7BD, 0x327A140A, 0x45E1D006, 0xC3F27B9A,
+ 0xC9AA53FD, 0x62A80F00, 0xBB25BFE2, 0x35BDD2F6,
+ 0x71126905, 0xB2040222, 0xB6CBCF7C, 0xCD769C2B,
+ 0x53113EC0, 0x1640E3D3, 0x38ABBD60, 0x2547ADF0,
+ 0xBA38209C, 0xF746CE76, 0x77AFA1C5, 0x20756060,
+ 0x85CBFE4E, 0x8AE88DD8, 0x7AAAF9B0, 0x4CF9AA7E,
+ 0x1948C25C, 0x02FB8A8C, 0x01C36AE4, 0xD6EBE1F9,
+ 0x90D4F869, 0xA65CDEA0, 0x3F09252D, 0xC208E69F,
+ 0xB74E6132, 0xCE77E25B, 0x578FDFE3, 0x3AC372E6
+ };
+
+ #endregion
+
+ private const int _rounds = 16;
+
+ private const int _sboxSk = 256;
+
+ private const int _pSize = _rounds + 2;
+
+ ///
+ /// The s-boxes
+ ///
+ private readonly uint[] _s0, _s1, _s2, _s3;
+
+ ///
+ /// The p-array
+ ///
+ private readonly uint[] _p;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The key.
+ /// The mode.
+ /// The padding.
+ /// is null.
+ /// Keysize is not valid for this algorithm.
+ public BlowfishCipher(byte[] key, CipherMode mode, CipherPadding padding)
+ : base(key, 8, mode, padding)
+ {
+ var keySize = key.Length * 8;
+
+ if (keySize < 1 || keySize > 448)
+ throw new ArgumentException(string.Format("KeySize '{0}' is not valid for this algorithm.", keySize));
+
+ this._s0 = new uint[_sboxSk];
+
+ this._s1 = new uint[_sboxSk];
+
+ this._s2 = new uint[_sboxSk];
+
+ this._s3 = new uint[_sboxSk];
+
+ this._p = new uint[_pSize];
+
+ this.SetKey(key);
+ }
+
+ ///
+ /// Encrypts the specified region of the input byte array and copies the encrypted data to the specified region of the output byte array.
+ ///
+ /// The input data to encrypt.
+ /// The offset into the input byte array from which to begin using data.
+ /// The number of bytes in the input byte array to use as data.
+ /// The output to which to write encrypted data.
+ /// The offset into the output byte array from which to begin writing data.
+ ///
+ /// The number of bytes encrypted.
+ ///
+ public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
+ {
+ if (inputCount != this.BlockSize)
+ throw new ArgumentException("inputCount");
+
+ uint xl = BigEndianToUInt32(inputBuffer, inputOffset);
+ uint xr = BigEndianToUInt32(inputBuffer, inputOffset + 4);
+
+ xl ^= this._p[0];
+
+ for (int i = 1; i < _rounds; i += 2)
+ {
+ xr ^= F(xl) ^ this._p[i];
+ xl ^= F(xr) ^ this._p[i + 1];
+ }
+
+ xr ^= this._p[_rounds + 1];
+
+ UInt32ToBigEndian(xr, outputBuffer, outputOffset);
+ UInt32ToBigEndian(xl, outputBuffer, outputOffset + 4);
+
+ return this.BlockSize;
+ }
+
+ ///
+ /// Decrypts the specified region of the input byte array and copies the decrypted data to the specified region of the output byte array.
+ ///
+ /// The input data to decrypt.
+ /// The offset into the input byte array from which to begin using data.
+ /// The number of bytes in the input byte array to use as data.
+ /// The output to which to write decrypted data.
+ /// The offset into the output byte array from which to begin writing data.
+ ///
+ /// The number of bytes decrypted.
+ ///
+ public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
+ {
+ if (inputCount != this.BlockSize)
+ throw new ArgumentException("inputCount");
+
+ uint xl = BigEndianToUInt32(inputBuffer, inputOffset);
+ uint xr = BigEndianToUInt32(inputBuffer, inputOffset + 4);
+
+ xl ^= this._p[_rounds + 1];
+
+ for (int i = _rounds; i > 0; i -= 2)
+ {
+ xr ^= F(xl) ^ this._p[i];
+ xl ^= F(xr) ^ this._p[i - 1];
+ }
+
+ xr ^= this._p[0];
+
+ UInt32ToBigEndian(xr, outputBuffer, outputOffset);
+ UInt32ToBigEndian(xl, outputBuffer, outputOffset + 4);
+
+ return this.BlockSize;
+ }
+
+ private uint F(uint x)
+ {
+ return (((this._s0[x >> 24] + this._s1[(x >> 16) & 0xff]) ^ this._s2[(x >> 8) & 0xff]) + this._s3[x & 0xff]);
+ }
+
+ private void SetKey(byte[] key)
+ {
+ /*
+ * - comments are from _Applied Crypto_, Schneier, p338
+ * please be careful comparing the two, AC numbers the
+ * arrays from 1, the enclosed code from 0.
+ *
+ * (1)
+ * Initialise the S-boxes and the P-array, with a fixed string
+ * This string contains the hexadecimal digits of pi (3.141...)
+ */
+ Buffer.BlockCopy(KS0, 0, this._s0, 0, _sboxSk * sizeof(uint));
+ Buffer.BlockCopy(KS1, 0, this._s1, 0, _sboxSk * sizeof(uint));
+ Buffer.BlockCopy(KS2, 0, this._s2, 0, _sboxSk * sizeof(uint));
+ Buffer.BlockCopy(KS3, 0, this._s3, 0, _sboxSk * sizeof(uint));
+
+ Buffer.BlockCopy(KP, 0, this._p, 0, _pSize * sizeof(uint));
+
+ /*
+ * (2)
+ * Now, XOR P[0] with the first 32 bits of the key, XOR P[1] with the
+ * second 32-bits of the key, and so on for all bits of the key
+ * (up to P[17]). Repeatedly cycle through the key bits until the
+ * entire P-array has been XOR-ed with the key bits
+ */
+ int keyLength = key.Length;
+ int keyIndex = 0;
+
+ for (int i = 0; i < _pSize; i++)
+ {
+ // Get the 32 bits of the key, in 4 * 8 bit chunks
+ uint data = 0x0000000;
+ for (int j = 0; j < 4; j++)
+ {
+ // create a 32 bit block
+ data = (data << 8) | (uint)key[keyIndex++];
+
+ // wrap when we get to the end of the key
+ if (keyIndex >= keyLength)
+ {
+ keyIndex = 0;
+ }
+ }
+ // XOR the newly created 32 bit chunk onto the P-array
+ this._p[i] ^= data;
+ }
+
+ /*
+ * (3)
+ * Encrypt the all-zero string with the Blowfish algorithm, using
+ * the subkeys described in (1) and (2)
+ *
+ * (4)
+ * Replace P1 and P2 with the output of step (3)
+ *
+ * (5)
+ * Encrypt the output of step(3) using the Blowfish algorithm,
+ * with the modified subkeys.
+ *
+ * (6)
+ * Replace P3 and P4 with the output of step (5)
+ *
+ * (7)
+ * Continue the process, replacing all elements of the P-array
+ * and then all four S-boxes in order, with the output of the
+ * continuously changing Blowfish algorithm
+ */
+
+ ProcessTable(0, 0, this._p);
+ ProcessTable(this._p[_pSize - 2], this._p[_pSize - 1], this._s0);
+ ProcessTable(this._s0[_sboxSk - 2], this._s0[_sboxSk - 1], this._s1);
+ ProcessTable(this._s1[_sboxSk - 2], this._s1[_sboxSk - 1], this._s2);
+ ProcessTable(this._s2[_sboxSk - 2], this._s2[_sboxSk - 1], this._s3);
+ }
+
+ ///
+ /// apply the encryption cycle to each value pair in the table.
+ ///
+ /// The xl.
+ /// The xr.
+ /// The table.
+ private void ProcessTable(uint xl, uint xr, uint[] table)
+ {
+ int size = table.Length;
+
+ for (int s = 0; s < size; s += 2)
+ {
+ xl ^= _p[0];
+
+ for (int i = 1; i < _rounds; i += 2)
+ {
+ xr ^= F(xl) ^ _p[i];
+ xl ^= F(xr) ^ _p[i + 1];
+ }
+
+ xr ^= _p[_rounds + 1];
+
+ table[s] = xr;
+ table[s + 1] = xl;
+
+ xr = xl; // end of cycle swap
+ xl = table[s];
+ }
+ }
+ }
+}
diff --git a/Renci.SshNet/Security/Cryptography/Ciphers/CastCipher.cs b/Renci.SshNet/Security/Cryptography/Ciphers/CastCipher.cs
index 301f4a1..f9308e4 100644
--- a/Renci.SshNet/Security/Cryptography/Ciphers/CastCipher.cs
+++ b/Renci.SshNet/Security/Cryptography/Ciphers/CastCipher.cs
@@ -1,733 +1,726 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace Renci.SshNet.Security.Cryptography.Ciphers
-{
- ///
- /// Implements CAST cipher algorithm
- ///
- public sealed class CastCipher : BlockCipher
- {
- internal static readonly int MAX_ROUNDS = 16;
-
- internal static readonly int RED_ROUNDS = 12;
-
- ///
- /// The rotating round key
- ///
- private int[] _kr = new int[17];
-
- ///
- /// The masking round key
- ///
- private uint[] _km = new uint[17];
-
- private int _rounds = MAX_ROUNDS;
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The key.
- /// The mode.
- /// The padding.
- /// is null.
- /// Keysize is not valid for this algorithm.
- public CastCipher(byte[] key, CipherMode mode, CipherPadding padding)
- : base(key, 8, mode, padding)
- {
- var keySize = key.Length * 8;
-
- if (!(keySize >= 40 && keySize <= 128 && keySize % 8 == 0))
- throw new ArgumentException(string.Format("KeySize '{0}' is not valid for this algorithm.", keySize));
-
- this.SetKey(key);
- }
-
- ///
- /// Encrypts the specified region of the input byte array and copies the encrypted data to the specified region of the output byte array.
- ///
- /// The input data to encrypt.
- /// The offset into the input byte array from which to begin using data.
- /// The number of bytes in the input byte array to use as data.
- /// The output to which to write encrypted data.
- /// The offset into the output byte array from which to begin writing data.
- ///
- /// The number of bytes encrypted.
- ///
- public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
- {
- // process the input block
- // batch the units up into a 32 bit chunk and go for it
- // the array is in bytes, the increment is 8x8 bits = 64
-
- uint L0 = BigEndianToUInt32(inputBuffer, inputOffset);
- uint R0 = BigEndianToUInt32(inputBuffer, inputOffset + 4);
-
- uint[] result = new uint[2];
- this.CastEncipher(L0, R0, result);
-
- // now stuff them into the destination block
- UInt32ToBigEndian(result[0], outputBuffer, outputOffset);
- UInt32ToBigEndian(result[1], outputBuffer, outputOffset + 4);
-
- return this.BlockSize;
- }
-
- ///
- /// Decrypts the specified region of the input byte array and copies the decrypted data to the specified region of the output byte array.
- ///
- /// The input data to decrypt.
- /// The offset into the input byte array from which to begin using data.
- /// The number of bytes in the input byte array to use as data.
- /// The output to which to write decrypted data.
- /// The offset into the output byte array from which to begin writing data.
- ///
- /// The number of bytes decrypted.
- ///
- public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
- {
- // process the input block
- // batch the units up into a 32 bit chunk and go for it
- // the array is in bytes, the increment is 8x8 bits = 64
- uint L16 = BigEndianToUInt32(inputBuffer, inputOffset);
- uint R16 = BigEndianToUInt32(inputBuffer, inputOffset + 4);
-
- uint[] result = new uint[2];
- this.CastDecipher(L16, R16, result);
-
- // now stuff them into the destination block
- UInt32ToBigEndian(result[0], outputBuffer, outputOffset);
- UInt32ToBigEndian(result[1], outputBuffer, outputOffset + 4);
-
- return this.BlockSize;
- }
-
- #region Static Definition Tables
-
- internal static readonly uint[] S1 =
- {
- 0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949,
- 0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e,
- 0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d,
- 0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0,
- 0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7,
- 0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935,
- 0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d,
- 0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50,
- 0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe,
- 0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3,
- 0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167,
- 0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291,
- 0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779,
- 0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2,
- 0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511,
- 0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d,
- 0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5,
- 0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324,
- 0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c,
- 0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc,
- 0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d,
- 0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96,
- 0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a,
- 0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d,
- 0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd,
- 0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6,
- 0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9,
- 0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872,
- 0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c,
- 0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e,
- 0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9,
- 0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf
- },
- S2 =
- {
- 0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651,
- 0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3,
- 0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb,
- 0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806,
- 0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b,
- 0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359,
- 0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b,
- 0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c,
- 0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34,
- 0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb,
- 0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd,
- 0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860,
- 0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b,
- 0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304,
- 0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b,
- 0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf,
- 0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c,
- 0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13,
- 0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f,
- 0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6,
- 0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6,
- 0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58,
- 0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906,
- 0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d,
- 0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6,
- 0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4,
- 0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6,
- 0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f,
- 0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249,
- 0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa,
- 0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9,
- 0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1
- },
- S3 =
- {
- 0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90,
- 0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5,
- 0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e,
- 0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240,
- 0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5,
- 0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b,
- 0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71,
- 0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04,
- 0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82,
- 0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15,
- 0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2,
- 0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176,
- 0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148,
- 0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc,
- 0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341,
- 0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e,
- 0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51,
- 0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f,
- 0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a,
- 0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b,
- 0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b,
- 0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5,
- 0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45,
- 0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536,
- 0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc,
- 0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0,
- 0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69,
- 0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2,
- 0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49,
- 0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d,
- 0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a,
- 0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783
- },
- S4 =
- {
- 0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1,
- 0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf,
- 0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15,
- 0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121,
- 0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25,
- 0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5,
- 0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb,
- 0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5,
- 0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d,
- 0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6,
- 0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23,
- 0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003,
- 0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6,
- 0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119,
- 0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24,
- 0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a,
- 0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79,
- 0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df,
- 0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26,
- 0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab,
- 0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7,
- 0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417,
- 0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2,
- 0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2,
- 0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a,
- 0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919,
- 0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef,
- 0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876,
- 0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab,
- 0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04,
- 0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282,
- 0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2
- },
- S5 =
- {
- 0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f,
- 0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a,
- 0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff,
- 0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02,
- 0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a,
- 0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7,
- 0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9,
- 0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981,
- 0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774,
- 0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655,
- 0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2,
- 0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910,
- 0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1,
- 0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da,
- 0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049,
- 0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f,
- 0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba,
- 0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be,
- 0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3,
- 0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840,
- 0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4,
- 0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2,
- 0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7,
- 0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5,
- 0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e,
- 0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e,
- 0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801,
- 0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad,
- 0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0,
- 0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20,
- 0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8,
- 0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4
- },
- S6 =
- {
- 0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac,
- 0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138,
- 0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367,
- 0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98,
- 0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072,
- 0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3,
- 0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd,
- 0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8,
- 0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9,
- 0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54,
- 0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387,
- 0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc,
- 0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf,
- 0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf,
- 0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f,
- 0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289,
- 0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950,
- 0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f,
- 0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b,
- 0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be,
- 0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13,
- 0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976,
- 0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0,
- 0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891,
- 0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da,
- 0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc,
- 0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084,
- 0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25,
- 0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121,
- 0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5,
- 0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd,
- 0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f
- },
- S7 =
- {
- 0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f,
- 0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de,
- 0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43,
- 0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19,
- 0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2,
- 0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516,
- 0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88,
- 0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816,
- 0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756,
- 0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a,
- 0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264,
- 0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688,
- 0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28,
- 0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3,
- 0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7,
- 0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06,
- 0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033,
- 0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a,
- 0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566,
- 0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509,
- 0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962,
- 0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e,
- 0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c,
- 0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c,
- 0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285,
- 0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301,
- 0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be,
- 0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767,
- 0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647,
- 0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914,
- 0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c,
- 0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3
- },
- S8 =
- {
- 0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5,
- 0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc,
- 0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd,
- 0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d,
- 0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2,
- 0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862,
- 0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc,
- 0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c,
- 0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e,
- 0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039,
- 0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8,
- 0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42,
- 0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5,
- 0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472,
- 0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225,
- 0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c,
- 0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb,
- 0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054,
- 0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70,
- 0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc,
- 0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c,
- 0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3,
- 0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4,
- 0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101,
- 0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f,
- 0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e,
- 0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a,
- 0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c,
- 0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384,
- 0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c,
- 0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82,
- 0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e
- };
-
- #endregion
-
- ///
- /// Sets the subkeys using the same nomenclatureas described in RFC2144.
- ///
- /// The key.
- private void SetKey(byte[] key)
- {
- /*
- * Determine the key size here, if required
- *
- * if keysize <= 80bits, use 12 rounds instead of 16
- * if keysize < 128bits, pad with 0
- *
- * Typical key sizes => 40, 64, 80, 128
- */
-
- if (key.Length < 11)
- {
- this._rounds = RED_ROUNDS;
- }
-
- int[] z = new int[16];
- int[] x = new int[16];
-
- uint z03, z47, z8B, zCF;
- uint x03, x47, x8B, xCF;
-
- /* copy the key into x */
- for (int i = 0; i < key.Length; i++)
- {
- x[i] = (int)(key[i] & 0xff);
- }
-
- /*
- * This will look different because the selection of
- * bytes from the input key I've already chosen the
- * correct int.
- */
- x03 = IntsTo32bits(x, 0x0);
- x47 = IntsTo32bits(x, 0x4);
- x8B = IntsTo32bits(x, 0x8);
- xCF = IntsTo32bits(x, 0xC);
-
- z03 = x03 ^ S5[x[0xD]] ^ S6[x[0xF]] ^ S7[x[0xC]] ^ S8[x[0xE]] ^ S7[x[0x8]];
-
- Bits32ToInts(z03, z, 0x0);
- z47 = x8B ^ S5[z[0x0]] ^ S6[z[0x2]] ^ S7[z[0x1]] ^ S8[z[0x3]] ^ S8[x[0xA]];
- Bits32ToInts(z47, z, 0x4);
- z8B = xCF ^ S5[z[0x7]] ^ S6[z[0x6]] ^ S7[z[0x5]] ^ S8[z[0x4]] ^ S5[x[0x9]];
- Bits32ToInts(z8B, z, 0x8);
- zCF = x47 ^ S5[z[0xA]] ^ S6[z[0x9]] ^ S7[z[0xB]] ^ S8[z[0x8]] ^ S6[x[0xB]];
- Bits32ToInts(zCF, z, 0xC);
- this._km[1] = S5[z[0x8]] ^ S6[z[0x9]] ^ S7[z[0x7]] ^ S8[z[0x6]] ^ S5[z[0x2]];
- this._km[2] = S5[z[0xA]] ^ S6[z[0xB]] ^ S7[z[0x5]] ^ S8[z[0x4]] ^ S6[z[0x6]];
- this._km[3] = S5[z[0xC]] ^ S6[z[0xD]] ^ S7[z[0x3]] ^ S8[z[0x2]] ^ S7[z[0x9]];
- this._km[4] = S5[z[0xE]] ^ S6[z[0xF]] ^ S7[z[0x1]] ^ S8[z[0x0]] ^ S8[z[0xC]];
-
- z03 = IntsTo32bits(z, 0x0);
- z47 = IntsTo32bits(z, 0x4);
- z8B = IntsTo32bits(z, 0x8);
- zCF = IntsTo32bits(z, 0xC);
- x03 = z8B ^ S5[z[0x5]] ^ S6[z[0x7]] ^ S7[z[0x4]] ^ S8[z[0x6]] ^ S7[z[0x0]];
- Bits32ToInts(x03, x, 0x0);
- x47 = z03 ^ S5[x[0x0]] ^ S6[x[0x2]] ^ S7[x[0x1]] ^ S8[x[0x3]] ^ S8[z[0x2]];
- Bits32ToInts(x47, x, 0x4);
- x8B = z47 ^ S5[x[0x7]] ^ S6[x[0x6]] ^ S7[x[0x5]] ^ S8[x[0x4]] ^ S5[z[0x1]];
- Bits32ToInts(x8B, x, 0x8);
- xCF = zCF ^ S5[x[0xA]] ^ S6[x[0x9]] ^ S7[x[0xB]] ^ S8[x[0x8]] ^ S6[z[0x3]];
- Bits32ToInts(xCF, x, 0xC);
- this._km[5] = S5[x[0x3]] ^ S6[x[0x2]] ^ S7[x[0xC]] ^ S8[x[0xD]] ^ S5[x[0x8]];
- this._km[6] = S5[x[0x1]] ^ S6[x[0x0]] ^ S7[x[0xE]] ^ S8[x[0xF]] ^ S6[x[0xD]];
- this._km[7] = S5[x[0x7]] ^ S6[x[0x6]] ^ S7[x[0x8]] ^ S8[x[0x9]] ^ S7[x[0x3]];
- this._km[8] = S5[x[0x5]] ^ S6[x[0x4]] ^ S7[x[0xA]] ^ S8[x[0xB]] ^ S8[x[0x7]];
-
- x03 = IntsTo32bits(x, 0x0);
- x47 = IntsTo32bits(x, 0x4);
- x8B = IntsTo32bits(x, 0x8);
- xCF = IntsTo32bits(x, 0xC);
- z03 = x03 ^ S5[x[0xD]] ^ S6[x[0xF]] ^ S7[x[0xC]] ^ S8[x[0xE]] ^ S7[x[0x8]];
- Bits32ToInts(z03, z, 0x0);
- z47 = x8B ^ S5[z[0x0]] ^ S6[z[0x2]] ^ S7[z[0x1]] ^ S8[z[0x3]] ^ S8[x[0xA]];
- Bits32ToInts(z47, z, 0x4);
- z8B = xCF ^ S5[z[0x7]] ^ S6[z[0x6]] ^ S7[z[0x5]] ^ S8[z[0x4]] ^ S5[x[0x9]];
- Bits32ToInts(z8B, z, 0x8);
- zCF = x47 ^ S5[z[0xA]] ^ S6[z[0x9]] ^ S7[z[0xB]] ^ S8[z[0x8]] ^ S6[x[0xB]];
- Bits32ToInts(zCF, z, 0xC);
- this._km[9] = S5[z[0x3]] ^ S6[z[0x2]] ^ S7[z[0xC]] ^ S8[z[0xD]] ^ S5[z[0x9]];
- this._km[10] = S5[z[0x1]] ^ S6[z[0x0]] ^ S7[z[0xE]] ^ S8[z[0xF]] ^ S6[z[0xc]];
- this._km[11] = S5[z[0x7]] ^ S6[z[0x6]] ^ S7[z[0x8]] ^ S8[z[0x9]] ^ S7[z[0x2]];
- this._km[12] = S5[z[0x5]] ^ S6[z[0x4]] ^ S7[z[0xA]] ^ S8[z[0xB]] ^ S8[z[0x6]];
-
- z03 = IntsTo32bits(z, 0x0);
- z47 = IntsTo32bits(z, 0x4);
- z8B = IntsTo32bits(z, 0x8);
- zCF = IntsTo32bits(z, 0xC);
- x03 = z8B ^ S5[z[0x5]] ^ S6[z[0x7]] ^ S7[z[0x4]] ^ S8[z[0x6]] ^ S7[z[0x0]];
- Bits32ToInts(x03, x, 0x0);
- x47 = z03 ^ S5[x[0x0]] ^ S6[x[0x2]] ^ S7[x[0x1]] ^ S8[x[0x3]] ^ S8[z[0x2]];
- Bits32ToInts(x47, x, 0x4);
- x8B = z47 ^ S5[x[0x7]] ^ S6[x[0x6]] ^ S7[x[0x5]] ^ S8[x[0x4]] ^ S5[z[0x1]];
- Bits32ToInts(x8B, x, 0x8);
- xCF = zCF ^ S5[x[0xA]] ^ S6[x[0x9]] ^ S7[x[0xB]] ^ S8[x[0x8]] ^ S6[z[0x3]];
- Bits32ToInts(xCF, x, 0xC);
- this._km[13] = S5[x[0x8]] ^ S6[x[0x9]] ^ S7[x[0x7]] ^ S8[x[0x6]] ^ S5[x[0x3]];
- this._km[14] = S5[x[0xA]] ^ S6[x[0xB]] ^ S7[x[0x5]] ^ S8[x[0x4]] ^ S6[x[0x7]];
- this._km[15] = S5[x[0xC]] ^ S6[x[0xD]] ^ S7[x[0x3]] ^ S8[x[0x2]] ^ S7[x[0x8]];
- this._km[16] = S5[x[0xE]] ^ S6[x[0xF]] ^ S7[x[0x1]] ^ S8[x[0x0]] ^ S8[x[0xD]];
-
- x03 = IntsTo32bits(x, 0x0);
- x47 = IntsTo32bits(x, 0x4);
- x8B = IntsTo32bits(x, 0x8);
- xCF = IntsTo32bits(x, 0xC);
- z03 = x03 ^ S5[x[0xD]] ^ S6[x[0xF]] ^ S7[x[0xC]] ^ S8[x[0xE]] ^ S7[x[0x8]];
- Bits32ToInts(z03, z, 0x0);
- z47 = x8B ^ S5[z[0x0]] ^ S6[z[0x2]] ^ S7[z[0x1]] ^ S8[z[0x3]] ^ S8[x[0xA]];
- Bits32ToInts(z47, z, 0x4);
- z8B = xCF ^ S5[z[0x7]] ^ S6[z[0x6]] ^ S7[z[0x5]] ^ S8[z[0x4]] ^ S5[x[0x9]];
- Bits32ToInts(z8B, z, 0x8);
- zCF = x47 ^ S5[z[0xA]] ^ S6[z[0x9]] ^ S7[z[0xB]] ^ S8[z[0x8]] ^ S6[x[0xB]];
- Bits32ToInts(zCF, z, 0xC);
- this._kr[1] = (int)((S5[z[0x8]] ^ S6[z[0x9]] ^ S7[z[0x7]] ^ S8[z[0x6]] ^ S5[z[0x2]]) & 0x1f);
- this._kr[2] = (int)((S5[z[0xA]] ^ S6[z[0xB]] ^ S7[z[0x5]] ^ S8[z[0x4]] ^ S6[z[0x6]]) & 0x1f);
- this._kr[3] = (int)((S5[z[0xC]] ^ S6[z[0xD]] ^ S7[z[0x3]] ^ S8[z[0x2]] ^ S7[z[0x9]]) & 0x1f);
- this._kr[4] = (int)((S5[z[0xE]] ^ S6[z[0xF]] ^ S7[z[0x1]] ^ S8[z[0x0]] ^ S8[z[0xC]]) & 0x1f);
-
- z03 = IntsTo32bits(z, 0x0);
- z47 = IntsTo32bits(z, 0x4);
- z8B = IntsTo32bits(z, 0x8);
- zCF = IntsTo32bits(z, 0xC);
- x03 = z8B ^ S5[z[0x5]] ^ S6[z[0x7]] ^ S7[z[0x4]] ^ S8[z[0x6]] ^ S7[z[0x0]];
- Bits32ToInts(x03, x, 0x0);
- x47 = z03 ^ S5[x[0x0]] ^ S6[x[0x2]] ^ S7[x[0x1]] ^ S8[x[0x3]] ^ S8[z[0x2]];
- Bits32ToInts(x47, x, 0x4);
- x8B = z47 ^ S5[x[0x7]] ^ S6[x[0x6]] ^ S7[x[0x5]] ^ S8[x[0x4]] ^ S5[z[0x1]];
- Bits32ToInts(x8B, x, 0x8);
- xCF = zCF ^ S5[x[0xA]] ^ S6[x[0x9]] ^ S7[x[0xB]] ^ S8[x[0x8]] ^ S6[z[0x3]];
- Bits32ToInts(xCF, x, 0xC);
- this._kr[5] = (int)((S5[x[0x3]] ^ S6[x[0x2]] ^ S7[x[0xC]] ^ S8[x[0xD]] ^ S5[x[0x8]]) & 0x1f);
- this._kr[6] = (int)((S5[x[0x1]] ^ S6[x[0x0]] ^ S7[x[0xE]] ^ S8[x[0xF]] ^ S6[x[0xD]]) & 0x1f);
- this._kr[7] = (int)((S5[x[0x7]] ^ S6[x[0x6]] ^ S7[x[0x8]] ^ S8[x[0x9]] ^ S7[x[0x3]]) & 0x1f);
- this._kr[8] = (int)((S5[x[0x5]] ^ S6[x[0x4]] ^ S7[x[0xA]] ^ S8[x[0xB]] ^ S8[x[0x7]]) & 0x1f);
-
- x03 = IntsTo32bits(x, 0x0);
- x47 = IntsTo32bits(x, 0x4);
- x8B = IntsTo32bits(x, 0x8);
- xCF = IntsTo32bits(x, 0xC);
- z03 = x03 ^ S5[x[0xD]] ^ S6[x[0xF]] ^ S7[x[0xC]] ^ S8[x[0xE]] ^ S7[x[0x8]];
- Bits32ToInts(z03, z, 0x0);
- z47 = x8B ^ S5[z[0x0]] ^ S6[z[0x2]] ^ S7[z[0x1]] ^ S8[z[0x3]] ^ S8[x[0xA]];
- Bits32ToInts(z47, z, 0x4);
- z8B = xCF ^ S5[z[0x7]] ^ S6[z[0x6]] ^ S7[z[0x5]] ^ S8[z[0x4]] ^ S5[x[0x9]];
- Bits32ToInts(z8B, z, 0x8);
- zCF = x47 ^ S5[z[0xA]] ^ S6[z[0x9]] ^ S7[z[0xB]] ^ S8[z[0x8]] ^ S6[x[0xB]];
- Bits32ToInts(zCF, z, 0xC);
- this._kr[9] = (int)((S5[z[0x3]] ^ S6[z[0x2]] ^ S7[z[0xC]] ^ S8[z[0xD]] ^ S5[z[0x9]]) & 0x1f);
- this._kr[10] = (int)((S5[z[0x1]] ^ S6[z[0x0]] ^ S7[z[0xE]] ^ S8[z[0xF]] ^ S6[z[0xc]]) & 0x1f);
- this._kr[11] = (int)((S5[z[0x7]] ^ S6[z[0x6]] ^ S7[z[0x8]] ^ S8[z[0x9]] ^ S7[z[0x2]]) & 0x1f);
- this._kr[12] = (int)((S5[z[0x5]] ^ S6[z[0x4]] ^ S7[z[0xA]] ^ S8[z[0xB]] ^ S8[z[0x6]]) & 0x1f);
-
- z03 = IntsTo32bits(z, 0x0);
- z47 = IntsTo32bits(z, 0x4);
- z8B = IntsTo32bits(z, 0x8);
- zCF = IntsTo32bits(z, 0xC);
- x03 = z8B ^ S5[z[0x5]] ^ S6[z[0x7]] ^ S7[z[0x4]] ^ S8[z[0x6]] ^ S7[z[0x0]];
- Bits32ToInts(x03, x, 0x0);
- x47 = z03 ^ S5[x[0x0]] ^ S6[x[0x2]] ^ S7[x[0x1]] ^ S8[x[0x3]] ^ S8[z[0x2]];
- Bits32ToInts(x47, x, 0x4);
- x8B = z47 ^ S5[x[0x7]] ^ S6[x[0x6]] ^ S7[x[0x5]] ^ S8[x[0x4]] ^ S5[z[0x1]];
- Bits32ToInts(x8B, x, 0x8);
- xCF = zCF ^ S5[x[0xA]] ^ S6[x[0x9]] ^ S7[x[0xB]] ^ S8[x[0x8]] ^ S6[z[0x3]];
- Bits32ToInts(xCF, x, 0xC);
- this._kr[13] = (int)((S5[x[0x8]] ^ S6[x[0x9]] ^ S7[x[0x7]] ^ S8[x[0x6]] ^ S5[x[0x3]]) & 0x1f);
- this._kr[14] = (int)((S5[x[0xA]] ^ S6[x[0xB]] ^ S7[x[0x5]] ^ S8[x[0x4]] ^ S6[x[0x7]]) & 0x1f);
- this._kr[15] = (int)((S5[x[0xC]] ^ S6[x[0xD]] ^ S7[x[0x3]] ^ S8[x[0x2]] ^ S7[x[0x8]]) & 0x1f);
- this._kr[16] = (int)((S5[x[0xE]] ^ S6[x[0xF]] ^ S7[x[0x1]] ^ S8[x[0x0]] ^ S8[x[0xD]]) & 0x1f);
- }
-
- ///
- /// The first of the three processing functions for the encryption and decryption.
- ///
- /// The input to be processed.
- /// The mask to be used from Km[n].
- /// The rotation value to be used.
- ///
- private static uint F1(uint D, uint Kmi, int Kri)
- {
- uint I = Kmi + D;
- I = I << Kri | (I >> (32 - Kri));
- return ((S1[(I >> 24) & 0xff] ^ S2[(I >> 16) & 0xff]) - S3[(I >> 8) & 0xff]) + S4[I & 0xff];
- }
-
- ///
- /// The second of the three processing functions for the encryption and decryption.
- ///
- /// The input to be processed.
- /// The mask to be used from Km[n].
- /// The rotation value to be used.
- ///
- private static uint F2(uint D, uint Kmi, int Kri)
- {
- uint I = Kmi ^ D;
- I = I << Kri | (I >> (32 - Kri));
- return ((S1[(I >> 24) & 0xff] - S2[(I >> 16) & 0xff]) + S3[(I >> 8) & 0xff]) ^ S4[I & 0xff];
- }
-
- ///
- /// The third of the three processing functions for the encryption and decryption.
- ///
- /// The input to be processed.
- /// The mask to be used from Km[n].
- /// The rotation value to be used.
- ///
- private static uint F3(uint D, uint Kmi, int Kri)
- {
- uint I = Kmi - D;
- I = I << Kri | (I >> (32 - Kri));
- return ((S1[(I >> 24) & 0xff] + S2[(I >> 16) & 0xff]) ^ S3[(I >> 8) & 0xff]) - S4[I & 0xff];
- }
-
- ///
- /// Does the 16 rounds to encrypt the block.
- ///
- /// The LH-32bits of the plaintext block.
- /// The RH-32bits of the plaintext block.
- /// The result.
- private void CastEncipher(uint L0, uint R0, uint[] result)
- {
- uint Lp = L0; // the previous value, equiv to L[i-1]
- uint Rp = R0; // equivalent to R[i-1]
-
- /*
- * numbering consistent with paper to make
- * checking and validating easier
- */
- uint Li = L0, Ri = R0;
-
- for (int i = 1; i <= this._rounds; i++)
- {
- Lp = Li;
- Rp = Ri;
-
- Li = Rp;
- switch (i)
- {
- case 1:
- case 4:
- case 7:
- case 10:
- case 13:
- case 16:
- Ri = Lp ^ F1(Rp, this._km[i], this._kr[i]);
- break;
- case 2:
- case 5:
- case 8:
- case 11:
- case 14:
- Ri = Lp ^ F2(Rp, this._km[i], this._kr[i]);
- break;
- case 3:
- case 6:
- case 9:
- case 12:
- case 15:
- Ri = Lp ^ F3(Rp, this._km[i], this._kr[i]);
- break;
- }
- }
-
- result[0] = Ri;
- result[1] = Li;
-
- return;
- }
-
- private void CastDecipher(uint L16, uint R16, uint[] result)
- {
- uint Lp = L16; // the previous value, equiv to L[i-1]
- uint Rp = R16; // equivalent to R[i-1]
-
- /*
- * numbering consistent with paper to make
- * checking and validating easier
- */
- uint Li = L16, Ri = R16;
-
- for (int i = this._rounds; i > 0; i--)
- {
- Lp = Li;
- Rp = Ri;
-
- Li = Rp;
- switch (i)
- {
- case 1:
- case 4:
- case 7:
- case 10:
- case 13:
- case 16:
- Ri = Lp ^ F1(Rp, this._km[i], this._kr[i]);
- break;
- case 2:
- case 5:
- case 8:
- case 11:
- case 14:
- Ri = Lp ^ F2(Rp, this._km[i], this._kr[i]);
- break;
- case 3:
- case 6:
- case 9:
- case 12:
- case 15:
- Ri = Lp ^ F3(Rp, this._km[i], this._kr[i]);
- break;
- }
- }
-
- result[0] = Ri;
- result[1] = Li;
-
- return;
- }
-
- private static void Bits32ToInts(uint inData, int[] b, int offset)
- {
- b[offset + 3] = (int)(inData & 0xff);
- b[offset + 2] = (int)((inData >> 8) & 0xff);
- b[offset + 1] = (int)((inData >> 16) & 0xff);
- b[offset] = (int)((inData >> 24) & 0xff);
- }
-
- private static uint IntsTo32bits(int[] b, int i)
- {
- return (uint)(((b[i] & 0xff) << 24) |
- ((b[i + 1] & 0xff) << 16) |
- ((b[i + 2] & 0xff) << 8) |
- ((b[i + 3] & 0xff)));
- }
-
- }
-}
+using System;
+
+namespace Renci.SshNet.Security.Cryptography.Ciphers
+{
+ ///
+ /// Implements CAST cipher algorithm
+ ///
+ public sealed class CastCipher : BlockCipher
+ {
+ internal static readonly int MAX_ROUNDS = 16;
+
+ internal static readonly int RED_ROUNDS = 12;
+
+ ///
+ /// The rotating round key
+ ///
+ private readonly int[] _kr = new int[17];
+
+ ///
+ /// The masking round key
+ ///
+ private readonly uint[] _km = new uint[17];
+
+ private int _rounds = MAX_ROUNDS;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The key.
+ /// The mode.
+ /// The padding.
+ /// is null.
+ /// Keysize is not valid for this algorithm.
+ public CastCipher(byte[] key, CipherMode mode, CipherPadding padding)
+ : base(key, 8, mode, padding)
+ {
+ var keySize = key.Length * 8;
+
+ if (!(keySize >= 40 && keySize <= 128 && keySize % 8 == 0))
+ throw new ArgumentException(string.Format("KeySize '{0}' is not valid for this algorithm.", keySize));
+
+ this.SetKey(key);
+ }
+
+ ///
+ /// Encrypts the specified region of the input byte array and copies the encrypted data to the specified region of the output byte array.
+ ///
+ /// The input data to encrypt.
+ /// The offset into the input byte array from which to begin using data.
+ /// The number of bytes in the input byte array to use as data.
+ /// The output to which to write encrypted data.
+ /// The offset into the output byte array from which to begin writing data.
+ ///
+ /// The number of bytes encrypted.
+ ///
+ public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
+ {
+ // process the input block
+ // batch the units up into a 32 bit chunk and go for it
+ // the array is in bytes, the increment is 8x8 bits = 64
+
+ uint L0 = BigEndianToUInt32(inputBuffer, inputOffset);
+ uint R0 = BigEndianToUInt32(inputBuffer, inputOffset + 4);
+
+ uint[] result = new uint[2];
+ this.CastEncipher(L0, R0, result);
+
+ // now stuff them into the destination block
+ UInt32ToBigEndian(result[0], outputBuffer, outputOffset);
+ UInt32ToBigEndian(result[1], outputBuffer, outputOffset + 4);
+
+ return this.BlockSize;
+ }
+
+ ///
+ /// Decrypts the specified region of the input byte array and copies the decrypted data to the specified region of the output byte array.
+ ///
+ /// The input data to decrypt.
+ /// The offset into the input byte array from which to begin using data.
+ /// The number of bytes in the input byte array to use as data.
+ /// The output to which to write decrypted data.
+ /// The offset into the output byte array from which to begin writing data.
+ ///
+ /// The number of bytes decrypted.
+ ///
+ public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
+ {
+ // process the input block
+ // batch the units up into a 32 bit chunk and go for it
+ // the array is in bytes, the increment is 8x8 bits = 64
+ uint L16 = BigEndianToUInt32(inputBuffer, inputOffset);
+ uint R16 = BigEndianToUInt32(inputBuffer, inputOffset + 4);
+
+ uint[] result = new uint[2];
+ this.CastDecipher(L16, R16, result);
+
+ // now stuff them into the destination block
+ UInt32ToBigEndian(result[0], outputBuffer, outputOffset);
+ UInt32ToBigEndian(result[1], outputBuffer, outputOffset + 4);
+
+ return this.BlockSize;
+ }
+
+ #region Static Definition Tables
+
+ internal static readonly uint[] S1 =
+ {
+ 0x30fb40d4, 0x9fa0ff0b, 0x6beccd2f, 0x3f258c7a, 0x1e213f2f, 0x9c004dd3, 0x6003e540, 0xcf9fc949,
+ 0xbfd4af27, 0x88bbbdb5, 0xe2034090, 0x98d09675, 0x6e63a0e0, 0x15c361d2, 0xc2e7661d, 0x22d4ff8e,
+ 0x28683b6f, 0xc07fd059, 0xff2379c8, 0x775f50e2, 0x43c340d3, 0xdf2f8656, 0x887ca41a, 0xa2d2bd2d,
+ 0xa1c9e0d6, 0x346c4819, 0x61b76d87, 0x22540f2f, 0x2abe32e1, 0xaa54166b, 0x22568e3a, 0xa2d341d0,
+ 0x66db40c8, 0xa784392f, 0x004dff2f, 0x2db9d2de, 0x97943fac, 0x4a97c1d8, 0x527644b7, 0xb5f437a7,
+ 0xb82cbaef, 0xd751d159, 0x6ff7f0ed, 0x5a097a1f, 0x827b68d0, 0x90ecf52e, 0x22b0c054, 0xbc8e5935,
+ 0x4b6d2f7f, 0x50bb64a2, 0xd2664910, 0xbee5812d, 0xb7332290, 0xe93b159f, 0xb48ee411, 0x4bff345d,
+ 0xfd45c240, 0xad31973f, 0xc4f6d02e, 0x55fc8165, 0xd5b1caad, 0xa1ac2dae, 0xa2d4b76d, 0xc19b0c50,
+ 0x882240f2, 0x0c6e4f38, 0xa4e4bfd7, 0x4f5ba272, 0x564c1d2f, 0xc59c5319, 0xb949e354, 0xb04669fe,
+ 0xb1b6ab8a, 0xc71358dd, 0x6385c545, 0x110f935d, 0x57538ad5, 0x6a390493, 0xe63d37e0, 0x2a54f6b3,
+ 0x3a787d5f, 0x6276a0b5, 0x19a6fcdf, 0x7a42206a, 0x29f9d4d5, 0xf61b1891, 0xbb72275e, 0xaa508167,
+ 0x38901091, 0xc6b505eb, 0x84c7cb8c, 0x2ad75a0f, 0x874a1427, 0xa2d1936b, 0x2ad286af, 0xaa56d291,
+ 0xd7894360, 0x425c750d, 0x93b39e26, 0x187184c9, 0x6c00b32d, 0x73e2bb14, 0xa0bebc3c, 0x54623779,
+ 0x64459eab, 0x3f328b82, 0x7718cf82, 0x59a2cea6, 0x04ee002e, 0x89fe78e6, 0x3fab0950, 0x325ff6c2,
+ 0x81383f05, 0x6963c5c8, 0x76cb5ad6, 0xd49974c9, 0xca180dcf, 0x380782d5, 0xc7fa5cf6, 0x8ac31511,
+ 0x35e79e13, 0x47da91d0, 0xf40f9086, 0xa7e2419e, 0x31366241, 0x051ef495, 0xaa573b04, 0x4a805d8d,
+ 0x548300d0, 0x00322a3c, 0xbf64cddf, 0xba57a68e, 0x75c6372b, 0x50afd341, 0xa7c13275, 0x915a0bf5,
+ 0x6b54bfab, 0x2b0b1426, 0xab4cc9d7, 0x449ccd82, 0xf7fbf265, 0xab85c5f3, 0x1b55db94, 0xaad4e324,
+ 0xcfa4bd3f, 0x2deaa3e2, 0x9e204d02, 0xc8bd25ac, 0xeadf55b3, 0xd5bd9e98, 0xe31231b2, 0x2ad5ad6c,
+ 0x954329de, 0xadbe4528, 0xd8710f69, 0xaa51c90f, 0xaa786bf6, 0x22513f1e, 0xaa51a79b, 0x2ad344cc,
+ 0x7b5a41f0, 0xd37cfbad, 0x1b069505, 0x41ece491, 0xb4c332e6, 0x032268d4, 0xc9600acc, 0xce387e6d,
+ 0xbf6bb16c, 0x6a70fb78, 0x0d03d9c9, 0xd4df39de, 0xe01063da, 0x4736f464, 0x5ad328d8, 0xb347cc96,
+ 0x75bb0fc3, 0x98511bfb, 0x4ffbcc35, 0xb58bcf6a, 0xe11f0abc, 0xbfc5fe4a, 0xa70aec10, 0xac39570a,
+ 0x3f04442f, 0x6188b153, 0xe0397a2e, 0x5727cb79, 0x9ceb418f, 0x1cacd68d, 0x2ad37c96, 0x0175cb9d,
+ 0xc69dff09, 0xc75b65f0, 0xd9db40d8, 0xec0e7779, 0x4744ead4, 0xb11c3274, 0xdd24cb9e, 0x7e1c54bd,
+ 0xf01144f9, 0xd2240eb1, 0x9675b3fd, 0xa3ac3755, 0xd47c27af, 0x51c85f4d, 0x56907596, 0xa5bb15e6,
+ 0x580304f0, 0xca042cf1, 0x011a37ea, 0x8dbfaadb, 0x35ba3e4a, 0x3526ffa0, 0xc37b4d09, 0xbc306ed9,
+ 0x98a52666, 0x5648f725, 0xff5e569d, 0x0ced63d0, 0x7c63b2cf, 0x700b45e1, 0xd5ea50f1, 0x85a92872,
+ 0xaf1fbda7, 0xd4234870, 0xa7870bf3, 0x2d3b4d79, 0x42e04198, 0x0cd0ede7, 0x26470db8, 0xf881814c,
+ 0x474d6ad7, 0x7c0c5e5c, 0xd1231959, 0x381b7298, 0xf5d2f4db, 0xab838653, 0x6e2f1e23, 0x83719c9e,
+ 0xbd91e046, 0x9a56456e, 0xdc39200c, 0x20c8c571, 0x962bda1c, 0xe1e696ff, 0xb141ab08, 0x7cca89b9,
+ 0x1a69e783, 0x02cc4843, 0xa2f7c579, 0x429ef47d, 0x427b169c, 0x5ac9f049, 0xdd8f0f00, 0x5c8165bf
+ },
+ S2 =
+ {
+ 0x1f201094, 0xef0ba75b, 0x69e3cf7e, 0x393f4380, 0xfe61cf7a, 0xeec5207a, 0x55889c94, 0x72fc0651,
+ 0xada7ef79, 0x4e1d7235, 0xd55a63ce, 0xde0436ba, 0x99c430ef, 0x5f0c0794, 0x18dcdb7d, 0xa1d6eff3,
+ 0xa0b52f7b, 0x59e83605, 0xee15b094, 0xe9ffd909, 0xdc440086, 0xef944459, 0xba83ccb3, 0xe0c3cdfb,
+ 0xd1da4181, 0x3b092ab1, 0xf997f1c1, 0xa5e6cf7b, 0x01420ddb, 0xe4e7ef5b, 0x25a1ff41, 0xe180f806,
+ 0x1fc41080, 0x179bee7a, 0xd37ac6a9, 0xfe5830a4, 0x98de8b7f, 0x77e83f4e, 0x79929269, 0x24fa9f7b,
+ 0xe113c85b, 0xacc40083, 0xd7503525, 0xf7ea615f, 0x62143154, 0x0d554b63, 0x5d681121, 0xc866c359,
+ 0x3d63cf73, 0xcee234c0, 0xd4d87e87, 0x5c672b21, 0x071f6181, 0x39f7627f, 0x361e3084, 0xe4eb573b,
+ 0x602f64a4, 0xd63acd9c, 0x1bbc4635, 0x9e81032d, 0x2701f50c, 0x99847ab4, 0xa0e3df79, 0xba6cf38c,
+ 0x10843094, 0x2537a95e, 0xf46f6ffe, 0xa1ff3b1f, 0x208cfb6a, 0x8f458c74, 0xd9e0a227, 0x4ec73a34,
+ 0xfc884f69, 0x3e4de8df, 0xef0e0088, 0x3559648d, 0x8a45388c, 0x1d804366, 0x721d9bfd, 0xa58684bb,
+ 0xe8256333, 0x844e8212, 0x128d8098, 0xfed33fb4, 0xce280ae1, 0x27e19ba5, 0xd5a6c252, 0xe49754bd,
+ 0xc5d655dd, 0xeb667064, 0x77840b4d, 0xa1b6a801, 0x84db26a9, 0xe0b56714, 0x21f043b7, 0xe5d05860,
+ 0x54f03084, 0x066ff472, 0xa31aa153, 0xdadc4755, 0xb5625dbf, 0x68561be6, 0x83ca6b94, 0x2d6ed23b,
+ 0xeccf01db, 0xa6d3d0ba, 0xb6803d5c, 0xaf77a709, 0x33b4a34c, 0x397bc8d6, 0x5ee22b95, 0x5f0e5304,
+ 0x81ed6f61, 0x20e74364, 0xb45e1378, 0xde18639b, 0x881ca122, 0xb96726d1, 0x8049a7e8, 0x22b7da7b,
+ 0x5e552d25, 0x5272d237, 0x79d2951c, 0xc60d894c, 0x488cb402, 0x1ba4fe5b, 0xa4b09f6b, 0x1ca815cf,
+ 0xa20c3005, 0x8871df63, 0xb9de2fcb, 0x0cc6c9e9, 0x0beeff53, 0xe3214517, 0xb4542835, 0x9f63293c,
+ 0xee41e729, 0x6e1d2d7c, 0x50045286, 0x1e6685f3, 0xf33401c6, 0x30a22c95, 0x31a70850, 0x60930f13,
+ 0x73f98417, 0xa1269859, 0xec645c44, 0x52c877a9, 0xcdff33a6, 0xa02b1741, 0x7cbad9a2, 0x2180036f,
+ 0x50d99c08, 0xcb3f4861, 0xc26bd765, 0x64a3f6ab, 0x80342676, 0x25a75e7b, 0xe4e6d1fc, 0x20c710e6,
+ 0xcdf0b680, 0x17844d3b, 0x31eef84d, 0x7e0824e4, 0x2ccb49eb, 0x846a3bae, 0x8ff77888, 0xee5d60f6,
+ 0x7af75673, 0x2fdd5cdb, 0xa11631c1, 0x30f66f43, 0xb3faec54, 0x157fd7fa, 0xef8579cc, 0xd152de58,
+ 0xdb2ffd5e, 0x8f32ce19, 0x306af97a, 0x02f03ef8, 0x99319ad5, 0xc242fa0f, 0xa7e3ebb0, 0xc68e4906,
+ 0xb8da230c, 0x80823028, 0xdcdef3c8, 0xd35fb171, 0x088a1bc8, 0xbec0c560, 0x61a3c9e8, 0xbca8f54d,
+ 0xc72feffa, 0x22822e99, 0x82c570b4, 0xd8d94e89, 0x8b1c34bc, 0x301e16e6, 0x273be979, 0xb0ffeaa6,
+ 0x61d9b8c6, 0x00b24869, 0xb7ffce3f, 0x08dc283b, 0x43daf65a, 0xf7e19798, 0x7619b72f, 0x8f1c9ba4,
+ 0xdc8637a0, 0x16a7d3b1, 0x9fc393b7, 0xa7136eeb, 0xc6bcc63e, 0x1a513742, 0xef6828bc, 0x520365d6,
+ 0x2d6a77ab, 0x3527ed4b, 0x821fd216, 0x095c6e2e, 0xdb92f2fb, 0x5eea29cb, 0x145892f5, 0x91584f7f,
+ 0x5483697b, 0x2667a8cc, 0x85196048, 0x8c4bacea, 0x833860d4, 0x0d23e0f9, 0x6c387e8a, 0x0ae6d249,
+ 0xb284600c, 0xd835731d, 0xdcb1c647, 0xac4c56ea, 0x3ebd81b3, 0x230eabb0, 0x6438bc87, 0xf0b5b1fa,
+ 0x8f5ea2b3, 0xfc184642, 0x0a036b7a, 0x4fb089bd, 0x649da589, 0xa345415e, 0x5c038323, 0x3e5d3bb9,
+ 0x43d79572, 0x7e6dd07c, 0x06dfdf1e, 0x6c6cc4ef, 0x7160a539, 0x73bfbe70, 0x83877605, 0x4523ecf1
+ },
+ S3 =
+ {
+ 0x8defc240, 0x25fa5d9f, 0xeb903dbf, 0xe810c907, 0x47607fff, 0x369fe44b, 0x8c1fc644, 0xaececa90,
+ 0xbeb1f9bf, 0xeefbcaea, 0xe8cf1950, 0x51df07ae, 0x920e8806, 0xf0ad0548, 0xe13c8d83, 0x927010d5,
+ 0x11107d9f, 0x07647db9, 0xb2e3e4d4, 0x3d4f285e, 0xb9afa820, 0xfade82e0, 0xa067268b, 0x8272792e,
+ 0x553fb2c0, 0x489ae22b, 0xd4ef9794, 0x125e3fbc, 0x21fffcee, 0x825b1bfd, 0x9255c5ed, 0x1257a240,
+ 0x4e1a8302, 0xbae07fff, 0x528246e7, 0x8e57140e, 0x3373f7bf, 0x8c9f8188, 0xa6fc4ee8, 0xc982b5a5,
+ 0xa8c01db7, 0x579fc264, 0x67094f31, 0xf2bd3f5f, 0x40fff7c1, 0x1fb78dfc, 0x8e6bd2c1, 0x437be59b,
+ 0x99b03dbf, 0xb5dbc64b, 0x638dc0e6, 0x55819d99, 0xa197c81c, 0x4a012d6e, 0xc5884a28, 0xccc36f71,
+ 0xb843c213, 0x6c0743f1, 0x8309893c, 0x0feddd5f, 0x2f7fe850, 0xd7c07f7e, 0x02507fbf, 0x5afb9a04,
+ 0xa747d2d0, 0x1651192e, 0xaf70bf3e, 0x58c31380, 0x5f98302e, 0x727cc3c4, 0x0a0fb402, 0x0f7fef82,
+ 0x8c96fdad, 0x5d2c2aae, 0x8ee99a49, 0x50da88b8, 0x8427f4a0, 0x1eac5790, 0x796fb449, 0x8252dc15,
+ 0xefbd7d9b, 0xa672597d, 0xada840d8, 0x45f54504, 0xfa5d7403, 0xe83ec305, 0x4f91751a, 0x925669c2,
+ 0x23efe941, 0xa903f12e, 0x60270df2, 0x0276e4b6, 0x94fd6574, 0x927985b2, 0x8276dbcb, 0x02778176,
+ 0xf8af918d, 0x4e48f79e, 0x8f616ddf, 0xe29d840e, 0x842f7d83, 0x340ce5c8, 0x96bbb682, 0x93b4b148,
+ 0xef303cab, 0x984faf28, 0x779faf9b, 0x92dc560d, 0x224d1e20, 0x8437aa88, 0x7d29dc96, 0x2756d3dc,
+ 0x8b907cee, 0xb51fd240, 0xe7c07ce3, 0xe566b4a1, 0xc3e9615e, 0x3cf8209d, 0x6094d1e3, 0xcd9ca341,
+ 0x5c76460e, 0x00ea983b, 0xd4d67881, 0xfd47572c, 0xf76cedd9, 0xbda8229c, 0x127dadaa, 0x438a074e,
+ 0x1f97c090, 0x081bdb8a, 0x93a07ebe, 0xb938ca15, 0x97b03cff, 0x3dc2c0f8, 0x8d1ab2ec, 0x64380e51,
+ 0x68cc7bfb, 0xd90f2788, 0x12490181, 0x5de5ffd4, 0xdd7ef86a, 0x76a2e214, 0xb9a40368, 0x925d958f,
+ 0x4b39fffa, 0xba39aee9, 0xa4ffd30b, 0xfaf7933b, 0x6d498623, 0x193cbcfa, 0x27627545, 0x825cf47a,
+ 0x61bd8ba0, 0xd11e42d1, 0xcead04f4, 0x127ea392, 0x10428db7, 0x8272a972, 0x9270c4a8, 0x127de50b,
+ 0x285ba1c8, 0x3c62f44f, 0x35c0eaa5, 0xe805d231, 0x428929fb, 0xb4fcdf82, 0x4fb66a53, 0x0e7dc15b,
+ 0x1f081fab, 0x108618ae, 0xfcfd086d, 0xf9ff2889, 0x694bcc11, 0x236a5cae, 0x12deca4d, 0x2c3f8cc5,
+ 0xd2d02dfe, 0xf8ef5896, 0xe4cf52da, 0x95155b67, 0x494a488c, 0xb9b6a80c, 0x5c8f82bc, 0x89d36b45,
+ 0x3a609437, 0xec00c9a9, 0x44715253, 0x0a874b49, 0xd773bc40, 0x7c34671c, 0x02717ef6, 0x4feb5536,
+ 0xa2d02fff, 0xd2bf60c4, 0xd43f03c0, 0x50b4ef6d, 0x07478cd1, 0x006e1888, 0xa2e53f55, 0xb9e6d4bc,
+ 0xa2048016, 0x97573833, 0xd7207d67, 0xde0f8f3d, 0x72f87b33, 0xabcc4f33, 0x7688c55d, 0x7b00a6b0,
+ 0x947b0001, 0x570075d2, 0xf9bb88f8, 0x8942019e, 0x4264a5ff, 0x856302e0, 0x72dbd92b, 0xee971b69,
+ 0x6ea22fde, 0x5f08ae2b, 0xaf7a616d, 0xe5c98767, 0xcf1febd2, 0x61efc8c2, 0xf1ac2571, 0xcc8239c2,
+ 0x67214cb8, 0xb1e583d1, 0xb7dc3e62, 0x7f10bdce, 0xf90a5c38, 0x0ff0443d, 0x606e6dc6, 0x60543a49,
+ 0x5727c148, 0x2be98a1d, 0x8ab41738, 0x20e1be24, 0xaf96da0f, 0x68458425, 0x99833be5, 0x600d457d,
+ 0x282f9350, 0x8334b362, 0xd91d1120, 0x2b6d8da0, 0x642b1e31, 0x9c305a00, 0x52bce688, 0x1b03588a,
+ 0xf7baefd5, 0x4142ed9c, 0xa4315c11, 0x83323ec5, 0xdfef4636, 0xa133c501, 0xe9d3531c, 0xee353783
+ },
+ S4 =
+ {
+ 0x9db30420, 0x1fb6e9de, 0xa7be7bef, 0xd273a298, 0x4a4f7bdb, 0x64ad8c57, 0x85510443, 0xfa020ed1,
+ 0x7e287aff, 0xe60fb663, 0x095f35a1, 0x79ebf120, 0xfd059d43, 0x6497b7b1, 0xf3641f63, 0x241e4adf,
+ 0x28147f5f, 0x4fa2b8cd, 0xc9430040, 0x0cc32220, 0xfdd30b30, 0xc0a5374f, 0x1d2d00d9, 0x24147b15,
+ 0xee4d111a, 0x0fca5167, 0x71ff904c, 0x2d195ffe, 0x1a05645f, 0x0c13fefe, 0x081b08ca, 0x05170121,
+ 0x80530100, 0xe83e5efe, 0xac9af4f8, 0x7fe72701, 0xd2b8ee5f, 0x06df4261, 0xbb9e9b8a, 0x7293ea25,
+ 0xce84ffdf, 0xf5718801, 0x3dd64b04, 0xa26f263b, 0x7ed48400, 0x547eebe6, 0x446d4ca0, 0x6cf3d6f5,
+ 0x2649abdf, 0xaea0c7f5, 0x36338cc1, 0x503f7e93, 0xd3772061, 0x11b638e1, 0x72500e03, 0xf80eb2bb,
+ 0xabe0502e, 0xec8d77de, 0x57971e81, 0xe14f6746, 0xc9335400, 0x6920318f, 0x081dbb99, 0xffc304a5,
+ 0x4d351805, 0x7f3d5ce3, 0xa6c866c6, 0x5d5bcca9, 0xdaec6fea, 0x9f926f91, 0x9f46222f, 0x3991467d,
+ 0xa5bf6d8e, 0x1143c44f, 0x43958302, 0xd0214eeb, 0x022083b8, 0x3fb6180c, 0x18f8931e, 0x281658e6,
+ 0x26486e3e, 0x8bd78a70, 0x7477e4c1, 0xb506e07c, 0xf32d0a25, 0x79098b02, 0xe4eabb81, 0x28123b23,
+ 0x69dead38, 0x1574ca16, 0xdf871b62, 0x211c40b7, 0xa51a9ef9, 0x0014377b, 0x041e8ac8, 0x09114003,
+ 0xbd59e4d2, 0xe3d156d5, 0x4fe876d5, 0x2f91a340, 0x557be8de, 0x00eae4a7, 0x0ce5c2ec, 0x4db4bba6,
+ 0xe756bdff, 0xdd3369ac, 0xec17b035, 0x06572327, 0x99afc8b0, 0x56c8c391, 0x6b65811c, 0x5e146119,
+ 0x6e85cb75, 0xbe07c002, 0xc2325577, 0x893ff4ec, 0x5bbfc92d, 0xd0ec3b25, 0xb7801ab7, 0x8d6d3b24,
+ 0x20c763ef, 0xc366a5fc, 0x9c382880, 0x0ace3205, 0xaac9548a, 0xeca1d7c7, 0x041afa32, 0x1d16625a,
+ 0x6701902c, 0x9b757a54, 0x31d477f7, 0x9126b031, 0x36cc6fdb, 0xc70b8b46, 0xd9e66a48, 0x56e55a79,
+ 0x026a4ceb, 0x52437eff, 0x2f8f76b4, 0x0df980a5, 0x8674cde3, 0xedda04eb, 0x17a9be04, 0x2c18f4df,
+ 0xb7747f9d, 0xab2af7b4, 0xefc34d20, 0x2e096b7c, 0x1741a254, 0xe5b6a035, 0x213d42f6, 0x2c1c7c26,
+ 0x61c2f50f, 0x6552daf9, 0xd2c231f8, 0x25130f69, 0xd8167fa2, 0x0418f2c8, 0x001a96a6, 0x0d1526ab,
+ 0x63315c21, 0x5e0a72ec, 0x49bafefd, 0x187908d9, 0x8d0dbd86, 0x311170a7, 0x3e9b640c, 0xcc3e10d7,
+ 0xd5cad3b6, 0x0caec388, 0xf73001e1, 0x6c728aff, 0x71eae2a1, 0x1f9af36e, 0xcfcbd12f, 0xc1de8417,
+ 0xac07be6b, 0xcb44a1d8, 0x8b9b0f56, 0x013988c3, 0xb1c52fca, 0xb4be31cd, 0xd8782806, 0x12a3a4e2,
+ 0x6f7de532, 0x58fd7eb6, 0xd01ee900, 0x24adffc2, 0xf4990fc5, 0x9711aac5, 0x001d7b95, 0x82e5e7d2,
+ 0x109873f6, 0x00613096, 0xc32d9521, 0xada121ff, 0x29908415, 0x7fbb977f, 0xaf9eb3db, 0x29c9ed2a,
+ 0x5ce2a465, 0xa730f32c, 0xd0aa3fe8, 0x8a5cc091, 0xd49e2ce7, 0x0ce454a9, 0xd60acd86, 0x015f1919,
+ 0x77079103, 0xdea03af6, 0x78a8565e, 0xdee356df, 0x21f05cbe, 0x8b75e387, 0xb3c50651, 0xb8a5c3ef,
+ 0xd8eeb6d2, 0xe523be77, 0xc2154529, 0x2f69efdf, 0xafe67afb, 0xf470c4b2, 0xf3e0eb5b, 0xd6cc9876,
+ 0x39e4460c, 0x1fda8538, 0x1987832f, 0xca007367, 0xa99144f8, 0x296b299e, 0x492fc295, 0x9266beab,
+ 0xb5676e69, 0x9bd3ddda, 0xdf7e052f, 0xdb25701c, 0x1b5e51ee, 0xf65324e6, 0x6afce36c, 0x0316cc04,
+ 0x8644213e, 0xb7dc59d0, 0x7965291f, 0xccd6fd43, 0x41823979, 0x932bcdf6, 0xb657c34d, 0x4edfd282,
+ 0x7ae5290c, 0x3cb9536b, 0x851e20fe, 0x9833557e, 0x13ecf0b0, 0xd3ffb372, 0x3f85c5c1, 0x0aef7ed2
+ },
+ S5 =
+ {
+ 0x7ec90c04, 0x2c6e74b9, 0x9b0e66df, 0xa6337911, 0xb86a7fff, 0x1dd358f5, 0x44dd9d44, 0x1731167f,
+ 0x08fbf1fa, 0xe7f511cc, 0xd2051b00, 0x735aba00, 0x2ab722d8, 0x386381cb, 0xacf6243a, 0x69befd7a,
+ 0xe6a2e77f, 0xf0c720cd, 0xc4494816, 0xccf5c180, 0x38851640, 0x15b0a848, 0xe68b18cb, 0x4caadeff,
+ 0x5f480a01, 0x0412b2aa, 0x259814fc, 0x41d0efe2, 0x4e40b48d, 0x248eb6fb, 0x8dba1cfe, 0x41a99b02,
+ 0x1a550a04, 0xba8f65cb, 0x7251f4e7, 0x95a51725, 0xc106ecd7, 0x97a5980a, 0xc539b9aa, 0x4d79fe6a,
+ 0xf2f3f763, 0x68af8040, 0xed0c9e56, 0x11b4958b, 0xe1eb5a88, 0x8709e6b0, 0xd7e07156, 0x4e29fea7,
+ 0x6366e52d, 0x02d1c000, 0xc4ac8e05, 0x9377f571, 0x0c05372a, 0x578535f2, 0x2261be02, 0xd642a0c9,
+ 0xdf13a280, 0x74b55bd2, 0x682199c0, 0xd421e5ec, 0x53fb3ce8, 0xc8adedb3, 0x28a87fc9, 0x3d959981,
+ 0x5c1ff900, 0xfe38d399, 0x0c4eff0b, 0x062407ea, 0xaa2f4fb1, 0x4fb96976, 0x90c79505, 0xb0a8a774,
+ 0xef55a1ff, 0xe59ca2c2, 0xa6b62d27, 0xe66a4263, 0xdf65001f, 0x0ec50966, 0xdfdd55bc, 0x29de0655,
+ 0x911e739a, 0x17af8975, 0x32c7911c, 0x89f89468, 0x0d01e980, 0x524755f4, 0x03b63cc9, 0x0cc844b2,
+ 0xbcf3f0aa, 0x87ac36e9, 0xe53a7426, 0x01b3d82b, 0x1a9e7449, 0x64ee2d7e, 0xcddbb1da, 0x01c94910,
+ 0xb868bf80, 0x0d26f3fd, 0x9342ede7, 0x04a5c284, 0x636737b6, 0x50f5b616, 0xf24766e3, 0x8eca36c1,
+ 0x136e05db, 0xfef18391, 0xfb887a37, 0xd6e7f7d4, 0xc7fb7dc9, 0x3063fcdf, 0xb6f589de, 0xec2941da,
+ 0x26e46695, 0xb7566419, 0xf654efc5, 0xd08d58b7, 0x48925401, 0xc1bacb7f, 0xe5ff550f, 0xb6083049,
+ 0x5bb5d0e8, 0x87d72e5a, 0xab6a6ee1, 0x223a66ce, 0xc62bf3cd, 0x9e0885f9, 0x68cb3e47, 0x086c010f,
+ 0xa21de820, 0xd18b69de, 0xf3f65777, 0xfa02c3f6, 0x407edac3, 0xcbb3d550, 0x1793084d, 0xb0d70eba,
+ 0x0ab378d5, 0xd951fb0c, 0xded7da56, 0x4124bbe4, 0x94ca0b56, 0x0f5755d1, 0xe0e1e56e, 0x6184b5be,
+ 0x580a249f, 0x94f74bc0, 0xe327888e, 0x9f7b5561, 0xc3dc0280, 0x05687715, 0x646c6bd7, 0x44904db3,
+ 0x66b4f0a3, 0xc0f1648a, 0x697ed5af, 0x49e92ff6, 0x309e374f, 0x2cb6356a, 0x85808573, 0x4991f840,
+ 0x76f0ae02, 0x083be84d, 0x28421c9a, 0x44489406, 0x736e4cb8, 0xc1092910, 0x8bc95fc6, 0x7d869cf4,
+ 0x134f616f, 0x2e77118d, 0xb31b2be1, 0xaa90b472, 0x3ca5d717, 0x7d161bba, 0x9cad9010, 0xaf462ba2,
+ 0x9fe459d2, 0x45d34559, 0xd9f2da13, 0xdbc65487, 0xf3e4f94e, 0x176d486f, 0x097c13ea, 0x631da5c7,
+ 0x445f7382, 0x175683f4, 0xcdc66a97, 0x70be0288, 0xb3cdcf72, 0x6e5dd2f3, 0x20936079, 0x459b80a5,
+ 0xbe60e2db, 0xa9c23101, 0xeba5315c, 0x224e42f2, 0x1c5c1572, 0xf6721b2c, 0x1ad2fff3, 0x8c25404e,
+ 0x324ed72f, 0x4067b7fd, 0x0523138e, 0x5ca3bc78, 0xdc0fd66e, 0x75922283, 0x784d6b17, 0x58ebb16e,
+ 0x44094f85, 0x3f481d87, 0xfcfeae7b, 0x77b5ff76, 0x8c2302bf, 0xaaf47556, 0x5f46b02a, 0x2b092801,
+ 0x3d38f5f7, 0x0ca81f36, 0x52af4a8a, 0x66d5e7c0, 0xdf3b0874, 0x95055110, 0x1b5ad7a8, 0xf61ed5ad,
+ 0x6cf6e479, 0x20758184, 0xd0cefa65, 0x88f7be58, 0x4a046826, 0x0ff6f8f3, 0xa09c7f70, 0x5346aba0,
+ 0x5ce96c28, 0xe176eda3, 0x6bac307f, 0x376829d2, 0x85360fa9, 0x17e3fe2a, 0x24b79767, 0xf5a96b20,
+ 0xd6cd2595, 0x68ff1ebf, 0x7555442c, 0xf19f06be, 0xf9e0659a, 0xeeb9491d, 0x34010718, 0xbb30cab8,
+ 0xe822fe15, 0x88570983, 0x750e6249, 0xda627e55, 0x5e76ffa8, 0xb1534546, 0x6d47de08, 0xefe9e7d4
+ },
+ S6 =
+ {
+ 0xf6fa8f9d, 0x2cac6ce1, 0x4ca34867, 0xe2337f7c, 0x95db08e7, 0x016843b4, 0xeced5cbc, 0x325553ac,
+ 0xbf9f0960, 0xdfa1e2ed, 0x83f0579d, 0x63ed86b9, 0x1ab6a6b8, 0xde5ebe39, 0xf38ff732, 0x8989b138,
+ 0x33f14961, 0xc01937bd, 0xf506c6da, 0xe4625e7e, 0xa308ea99, 0x4e23e33c, 0x79cbd7cc, 0x48a14367,
+ 0xa3149619, 0xfec94bd5, 0xa114174a, 0xeaa01866, 0xa084db2d, 0x09a8486f, 0xa888614a, 0x2900af98,
+ 0x01665991, 0xe1992863, 0xc8f30c60, 0x2e78ef3c, 0xd0d51932, 0xcf0fec14, 0xf7ca07d2, 0xd0a82072,
+ 0xfd41197e, 0x9305a6b0, 0xe86be3da, 0x74bed3cd, 0x372da53c, 0x4c7f4448, 0xdab5d440, 0x6dba0ec3,
+ 0x083919a7, 0x9fbaeed9, 0x49dbcfb0, 0x4e670c53, 0x5c3d9c01, 0x64bdb941, 0x2c0e636a, 0xba7dd9cd,
+ 0xea6f7388, 0xe70bc762, 0x35f29adb, 0x5c4cdd8d, 0xf0d48d8c, 0xb88153e2, 0x08a19866, 0x1ae2eac8,
+ 0x284caf89, 0xaa928223, 0x9334be53, 0x3b3a21bf, 0x16434be3, 0x9aea3906, 0xefe8c36e, 0xf890cdd9,
+ 0x80226dae, 0xc340a4a3, 0xdf7e9c09, 0xa694a807, 0x5b7c5ecc, 0x221db3a6, 0x9a69a02f, 0x68818a54,
+ 0xceb2296f, 0x53c0843a, 0xfe893655, 0x25bfe68a, 0xb4628abc, 0xcf222ebf, 0x25ac6f48, 0xa9a99387,
+ 0x53bddb65, 0xe76ffbe7, 0xe967fd78, 0x0ba93563, 0x8e342bc1, 0xe8a11be9, 0x4980740d, 0xc8087dfc,
+ 0x8de4bf99, 0xa11101a0, 0x7fd37975, 0xda5a26c0, 0xe81f994f, 0x9528cd89, 0xfd339fed, 0xb87834bf,
+ 0x5f04456d, 0x22258698, 0xc9c4c83b, 0x2dc156be, 0x4f628daa, 0x57f55ec5, 0xe2220abe, 0xd2916ebf,
+ 0x4ec75b95, 0x24f2c3c0, 0x42d15d99, 0xcd0d7fa0, 0x7b6e27ff, 0xa8dc8af0, 0x7345c106, 0xf41e232f,
+ 0x35162386, 0xe6ea8926, 0x3333b094, 0x157ec6f2, 0x372b74af, 0x692573e4, 0xe9a9d848, 0xf3160289,
+ 0x3a62ef1d, 0xa787e238, 0xf3a5f676, 0x74364853, 0x20951063, 0x4576698d, 0xb6fad407, 0x592af950,
+ 0x36f73523, 0x4cfb6e87, 0x7da4cec0, 0x6c152daa, 0xcb0396a8, 0xc50dfe5d, 0xfcd707ab, 0x0921c42f,
+ 0x89dff0bb, 0x5fe2be78, 0x448f4f33, 0x754613c9, 0x2b05d08d, 0x48b9d585, 0xdc049441, 0xc8098f9b,
+ 0x7dede786, 0xc39a3373, 0x42410005, 0x6a091751, 0x0ef3c8a6, 0x890072d6, 0x28207682, 0xa9a9f7be,
+ 0xbf32679d, 0xd45b5b75, 0xb353fd00, 0xcbb0e358, 0x830f220a, 0x1f8fb214, 0xd372cf08, 0xcc3c4a13,
+ 0x8cf63166, 0x061c87be, 0x88c98f88, 0x6062e397, 0x47cf8e7a, 0xb6c85283, 0x3cc2acfb, 0x3fc06976,
+ 0x4e8f0252, 0x64d8314d, 0xda3870e3, 0x1e665459, 0xc10908f0, 0x513021a5, 0x6c5b68b7, 0x822f8aa0,
+ 0x3007cd3e, 0x74719eef, 0xdc872681, 0x073340d4, 0x7e432fd9, 0x0c5ec241, 0x8809286c, 0xf592d891,
+ 0x08a930f6, 0x957ef305, 0xb7fbffbd, 0xc266e96f, 0x6fe4ac98, 0xb173ecc0, 0xbc60b42a, 0x953498da,
+ 0xfba1ae12, 0x2d4bd736, 0x0f25faab, 0xa4f3fceb, 0xe2969123, 0x257f0c3d, 0x9348af49, 0x361400bc,
+ 0xe8816f4a, 0x3814f200, 0xa3f94043, 0x9c7a54c2, 0xbc704f57, 0xda41e7f9, 0xc25ad33a, 0x54f4a084,
+ 0xb17f5505, 0x59357cbe, 0xedbd15c8, 0x7f97c5ab, 0xba5ac7b5, 0xb6f6deaf, 0x3a479c3a, 0x5302da25,
+ 0x653d7e6a, 0x54268d49, 0x51a477ea, 0x5017d55b, 0xd7d25d88, 0x44136c76, 0x0404a8c8, 0xb8e5a121,
+ 0xb81a928a, 0x60ed5869, 0x97c55b96, 0xeaec991b, 0x29935913, 0x01fdb7f1, 0x088e8dfa, 0x9ab6f6f5,
+ 0x3b4cbf9f, 0x4a5de3ab, 0xe6051d35, 0xa0e1d855, 0xd36b4cf1, 0xf544edeb, 0xb0e93524, 0xbebb8fbd,
+ 0xa2d762cf, 0x49c92f54, 0x38b5f331, 0x7128a454, 0x48392905, 0xa65b1db8, 0x851c97bd, 0xd675cf2f
+ },
+ S7 =
+ {
+ 0x85e04019, 0x332bf567, 0x662dbfff, 0xcfc65693, 0x2a8d7f6f, 0xab9bc912, 0xde6008a1, 0x2028da1f,
+ 0x0227bce7, 0x4d642916, 0x18fac300, 0x50f18b82, 0x2cb2cb11, 0xb232e75c, 0x4b3695f2, 0xb28707de,
+ 0xa05fbcf6, 0xcd4181e9, 0xe150210c, 0xe24ef1bd, 0xb168c381, 0xfde4e789, 0x5c79b0d8, 0x1e8bfd43,
+ 0x4d495001, 0x38be4341, 0x913cee1d, 0x92a79c3f, 0x089766be, 0xbaeeadf4, 0x1286becf, 0xb6eacb19,
+ 0x2660c200, 0x7565bde4, 0x64241f7a, 0x8248dca9, 0xc3b3ad66, 0x28136086, 0x0bd8dfa8, 0x356d1cf2,
+ 0x107789be, 0xb3b2e9ce, 0x0502aa8f, 0x0bc0351e, 0x166bf52a, 0xeb12ff82, 0xe3486911, 0xd34d7516,
+ 0x4e7b3aff, 0x5f43671b, 0x9cf6e037, 0x4981ac83, 0x334266ce, 0x8c9341b7, 0xd0d854c0, 0xcb3a6c88,
+ 0x47bc2829, 0x4725ba37, 0xa66ad22b, 0x7ad61f1e, 0x0c5cbafa, 0x4437f107, 0xb6e79962, 0x42d2d816,
+ 0x0a961288, 0xe1a5c06e, 0x13749e67, 0x72fc081a, 0xb1d139f7, 0xf9583745, 0xcf19df58, 0xbec3f756,
+ 0xc06eba30, 0x07211b24, 0x45c28829, 0xc95e317f, 0xbc8ec511, 0x38bc46e9, 0xc6e6fa14, 0xbae8584a,
+ 0xad4ebc46, 0x468f508b, 0x7829435f, 0xf124183b, 0x821dba9f, 0xaff60ff4, 0xea2c4e6d, 0x16e39264,
+ 0x92544a8b, 0x009b4fc3, 0xaba68ced, 0x9ac96f78, 0x06a5b79a, 0xb2856e6e, 0x1aec3ca9, 0xbe838688,
+ 0x0e0804e9, 0x55f1be56, 0xe7e5363b, 0xb3a1f25d, 0xf7debb85, 0x61fe033c, 0x16746233, 0x3c034c28,
+ 0xda6d0c74, 0x79aac56c, 0x3ce4e1ad, 0x51f0c802, 0x98f8f35a, 0x1626a49f, 0xeed82b29, 0x1d382fe3,
+ 0x0c4fb99a, 0xbb325778, 0x3ec6d97b, 0x6e77a6a9, 0xcb658b5c, 0xd45230c7, 0x2bd1408b, 0x60c03eb7,
+ 0xb9068d78, 0xa33754f4, 0xf430c87d, 0xc8a71302, 0xb96d8c32, 0xebd4e7be, 0xbe8b9d2d, 0x7979fb06,
+ 0xe7225308, 0x8b75cf77, 0x11ef8da4, 0xe083c858, 0x8d6b786f, 0x5a6317a6, 0xfa5cf7a0, 0x5dda0033,
+ 0xf28ebfb0, 0xf5b9c310, 0xa0eac280, 0x08b9767a, 0xa3d9d2b0, 0x79d34217, 0x021a718d, 0x9ac6336a,
+ 0x2711fd60, 0x438050e3, 0x069908a8, 0x3d7fedc4, 0x826d2bef, 0x4eeb8476, 0x488dcf25, 0x36c9d566,
+ 0x28e74e41, 0xc2610aca, 0x3d49a9cf, 0xbae3b9df, 0xb65f8de6, 0x92aeaf64, 0x3ac7d5e6, 0x9ea80509,
+ 0xf22b017d, 0xa4173f70, 0xdd1e16c3, 0x15e0d7f9, 0x50b1b887, 0x2b9f4fd5, 0x625aba82, 0x6a017962,
+ 0x2ec01b9c, 0x15488aa9, 0xd716e740, 0x40055a2c, 0x93d29a22, 0xe32dbf9a, 0x058745b9, 0x3453dc1e,
+ 0xd699296e, 0x496cff6f, 0x1c9f4986, 0xdfe2ed07, 0xb87242d1, 0x19de7eae, 0x053e561a, 0x15ad6f8c,
+ 0x66626c1c, 0x7154c24c, 0xea082b2a, 0x93eb2939, 0x17dcb0f0, 0x58d4f2ae, 0x9ea294fb, 0x52cf564c,
+ 0x9883fe66, 0x2ec40581, 0x763953c3, 0x01d6692e, 0xd3a0c108, 0xa1e7160e, 0xe4f2dfa6, 0x693ed285,
+ 0x74904698, 0x4c2b0edd, 0x4f757656, 0x5d393378, 0xa132234f, 0x3d321c5d, 0xc3f5e194, 0x4b269301,
+ 0xc79f022f, 0x3c997e7e, 0x5e4f9504, 0x3ffafbbd, 0x76f7ad0e, 0x296693f4, 0x3d1fce6f, 0xc61e45be,
+ 0xd3b5ab34, 0xf72bf9b7, 0x1b0434c0, 0x4e72b567, 0x5592a33d, 0xb5229301, 0xcfd2a87f, 0x60aeb767,
+ 0x1814386b, 0x30bcc33d, 0x38a0c07d, 0xfd1606f2, 0xc363519b, 0x589dd390, 0x5479f8e6, 0x1cb8d647,
+ 0x97fd61a9, 0xea7759f4, 0x2d57539d, 0x569a58cf, 0xe84e63ad, 0x462e1b78, 0x6580f87e, 0xf3817914,
+ 0x91da55f4, 0x40a230f3, 0xd1988f35, 0xb6e318d2, 0x3ffa50bc, 0x3d40f021, 0xc3c0bdae, 0x4958c24c,
+ 0x518f36b2, 0x84b1d370, 0x0fedce83, 0x878ddada, 0xf2a279c7, 0x94e01be8, 0x90716f4b, 0x954b8aa3
+ },
+ S8 =
+ {
+ 0xe216300d, 0xbbddfffc, 0xa7ebdabd, 0x35648095, 0x7789f8b7, 0xe6c1121b, 0x0e241600, 0x052ce8b5,
+ 0x11a9cfb0, 0xe5952f11, 0xece7990a, 0x9386d174, 0x2a42931c, 0x76e38111, 0xb12def3a, 0x37ddddfc,
+ 0xde9adeb1, 0x0a0cc32c, 0xbe197029, 0x84a00940, 0xbb243a0f, 0xb4d137cf, 0xb44e79f0, 0x049eedfd,
+ 0x0b15a15d, 0x480d3168, 0x8bbbde5a, 0x669ded42, 0xc7ece831, 0x3f8f95e7, 0x72df191b, 0x7580330d,
+ 0x94074251, 0x5c7dcdfa, 0xabbe6d63, 0xaa402164, 0xb301d40a, 0x02e7d1ca, 0x53571dae, 0x7a3182a2,
+ 0x12a8ddec, 0xfdaa335d, 0x176f43e8, 0x71fb46d4, 0x38129022, 0xce949ad4, 0xb84769ad, 0x965bd862,
+ 0x82f3d055, 0x66fb9767, 0x15b80b4e, 0x1d5b47a0, 0x4cfde06f, 0xc28ec4b8, 0x57e8726e, 0x647a78fc,
+ 0x99865d44, 0x608bd593, 0x6c200e03, 0x39dc5ff6, 0x5d0b00a3, 0xae63aff2, 0x7e8bd632, 0x70108c0c,
+ 0xbbd35049, 0x2998df04, 0x980cf42a, 0x9b6df491, 0x9e7edd53, 0x06918548, 0x58cb7e07, 0x3b74ef2e,
+ 0x522fffb1, 0xd24708cc, 0x1c7e27cd, 0xa4eb215b, 0x3cf1d2e2, 0x19b47a38, 0x424f7618, 0x35856039,
+ 0x9d17dee7, 0x27eb35e6, 0xc9aff67b, 0x36baf5b8, 0x09c467cd, 0xc18910b1, 0xe11dbf7b, 0x06cd1af8,
+ 0x7170c608, 0x2d5e3354, 0xd4de495a, 0x64c6d006, 0xbcc0c62c, 0x3dd00db3, 0x708f8f34, 0x77d51b42,
+ 0x264f620f, 0x24b8d2bf, 0x15c1b79e, 0x46a52564, 0xf8d7e54e, 0x3e378160, 0x7895cda5, 0x859c15a5,
+ 0xe6459788, 0xc37bc75f, 0xdb07ba0c, 0x0676a3ab, 0x7f229b1e, 0x31842e7b, 0x24259fd7, 0xf8bef472,
+ 0x835ffcb8, 0x6df4c1f2, 0x96f5b195, 0xfd0af0fc, 0xb0fe134c, 0xe2506d3d, 0x4f9b12ea, 0xf215f225,
+ 0xa223736f, 0x9fb4c428, 0x25d04979, 0x34c713f8, 0xc4618187, 0xea7a6e98, 0x7cd16efc, 0x1436876c,
+ 0xf1544107, 0xbedeee14, 0x56e9af27, 0xa04aa441, 0x3cf7c899, 0x92ecbae6, 0xdd67016d, 0x151682eb,
+ 0xa842eedf, 0xfdba60b4, 0xf1907b75, 0x20e3030f, 0x24d8c29e, 0xe139673b, 0xefa63fb8, 0x71873054,
+ 0xb6f2cf3b, 0x9f326442, 0xcb15a4cc, 0xb01a4504, 0xf1e47d8d, 0x844a1be5, 0xbae7dfdc, 0x42cbda70,
+ 0xcd7dae0a, 0x57e85b7a, 0xd53f5af6, 0x20cf4d8c, 0xcea4d428, 0x79d130a4, 0x3486ebfb, 0x33d3cddc,
+ 0x77853b53, 0x37effcb5, 0xc5068778, 0xe580b3e6, 0x4e68b8f4, 0xc5c8b37e, 0x0d809ea2, 0x398feb7c,
+ 0x132a4f94, 0x43b7950e, 0x2fee7d1c, 0x223613bd, 0xdd06caa2, 0x37df932b, 0xc4248289, 0xacf3ebc3,
+ 0x5715f6b7, 0xef3478dd, 0xf267616f, 0xc148cbe4, 0x9052815e, 0x5e410fab, 0xb48a2465, 0x2eda7fa4,
+ 0xe87b40e4, 0xe98ea084, 0x5889e9e1, 0xefd390fc, 0xdd07d35b, 0xdb485694, 0x38d7e5b2, 0x57720101,
+ 0x730edebc, 0x5b643113, 0x94917e4f, 0x503c2fba, 0x646f1282, 0x7523d24a, 0xe0779695, 0xf9c17a8f,
+ 0x7a5b2121, 0xd187b896, 0x29263a4d, 0xba510cdf, 0x81f47c9f, 0xad1163ed, 0xea7b5965, 0x1a00726e,
+ 0x11403092, 0x00da6d77, 0x4a0cdd61, 0xad1f4603, 0x605bdfb0, 0x9eedc364, 0x22ebe6a8, 0xcee7d28a,
+ 0xa0e736a0, 0x5564a6b9, 0x10853209, 0xc7eb8f37, 0x2de705ca, 0x8951570f, 0xdf09822b, 0xbd691a6c,
+ 0xaa12e4f2, 0x87451c0f, 0xe0f6a27a, 0x3ada4819, 0x4cf1764f, 0x0d771c2b, 0x67cdb156, 0x350d8384,
+ 0x5938fa0f, 0x42399ef3, 0x36997b07, 0x0e84093d, 0x4aa93e61, 0x8360d87b, 0x1fa98b0c, 0x1149382c,
+ 0xe97625a5, 0x0614d1b7, 0x0e25244b, 0x0c768347, 0x589e8d82, 0x0d2059d1, 0xa466bb1e, 0xf8da0a82,
+ 0x04f19130, 0xba6e4ec0, 0x99265164, 0x1ee7230d, 0x50b2ad80, 0xeaee6801, 0x8db2a283, 0xea8bf59e
+ };
+
+ #endregion
+
+ ///
+ /// Sets the subkeys using the same nomenclatureas described in RFC2144.
+ ///
+ /// The key.
+ private void SetKey(byte[] key)
+ {
+ /*
+ * Determine the key size here, if required
+ *
+ * if keysize <= 80bits, use 12 rounds instead of 16
+ * if keysize < 128bits, pad with 0
+ *
+ * Typical key sizes => 40, 64, 80, 128
+ */
+
+ if (key.Length < 11)
+ {
+ this._rounds = RED_ROUNDS;
+ }
+
+ int[] z = new int[16];
+ int[] x = new int[16];
+
+ uint z03, z47, z8B, zCF;
+ uint x03, x47, x8B, xCF;
+
+ /* copy the key into x */
+ for (int i = 0; i < key.Length; i++)
+ {
+ x[i] = (int)(key[i] & 0xff);
+ }
+
+ /*
+ * This will look different because the selection of
+ * bytes from the input key I've already chosen the
+ * correct int.
+ */
+ x03 = IntsTo32bits(x, 0x0);
+ x47 = IntsTo32bits(x, 0x4);
+ x8B = IntsTo32bits(x, 0x8);
+ xCF = IntsTo32bits(x, 0xC);
+
+ z03 = x03 ^ S5[x[0xD]] ^ S6[x[0xF]] ^ S7[x[0xC]] ^ S8[x[0xE]] ^ S7[x[0x8]];
+
+ Bits32ToInts(z03, z, 0x0);
+ z47 = x8B ^ S5[z[0x0]] ^ S6[z[0x2]] ^ S7[z[0x1]] ^ S8[z[0x3]] ^ S8[x[0xA]];
+ Bits32ToInts(z47, z, 0x4);
+ z8B = xCF ^ S5[z[0x7]] ^ S6[z[0x6]] ^ S7[z[0x5]] ^ S8[z[0x4]] ^ S5[x[0x9]];
+ Bits32ToInts(z8B, z, 0x8);
+ zCF = x47 ^ S5[z[0xA]] ^ S6[z[0x9]] ^ S7[z[0xB]] ^ S8[z[0x8]] ^ S6[x[0xB]];
+ Bits32ToInts(zCF, z, 0xC);
+ this._km[1] = S5[z[0x8]] ^ S6[z[0x9]] ^ S7[z[0x7]] ^ S8[z[0x6]] ^ S5[z[0x2]];
+ this._km[2] = S5[z[0xA]] ^ S6[z[0xB]] ^ S7[z[0x5]] ^ S8[z[0x4]] ^ S6[z[0x6]];
+ this._km[3] = S5[z[0xC]] ^ S6[z[0xD]] ^ S7[z[0x3]] ^ S8[z[0x2]] ^ S7[z[0x9]];
+ this._km[4] = S5[z[0xE]] ^ S6[z[0xF]] ^ S7[z[0x1]] ^ S8[z[0x0]] ^ S8[z[0xC]];
+
+ z03 = IntsTo32bits(z, 0x0);
+ z47 = IntsTo32bits(z, 0x4);
+ z8B = IntsTo32bits(z, 0x8);
+ zCF = IntsTo32bits(z, 0xC);
+ x03 = z8B ^ S5[z[0x5]] ^ S6[z[0x7]] ^ S7[z[0x4]] ^ S8[z[0x6]] ^ S7[z[0x0]];
+ Bits32ToInts(x03, x, 0x0);
+ x47 = z03 ^ S5[x[0x0]] ^ S6[x[0x2]] ^ S7[x[0x1]] ^ S8[x[0x3]] ^ S8[z[0x2]];
+ Bits32ToInts(x47, x, 0x4);
+ x8B = z47 ^ S5[x[0x7]] ^ S6[x[0x6]] ^ S7[x[0x5]] ^ S8[x[0x4]] ^ S5[z[0x1]];
+ Bits32ToInts(x8B, x, 0x8);
+ xCF = zCF ^ S5[x[0xA]] ^ S6[x[0x9]] ^ S7[x[0xB]] ^ S8[x[0x8]] ^ S6[z[0x3]];
+ Bits32ToInts(xCF, x, 0xC);
+ this._km[5] = S5[x[0x3]] ^ S6[x[0x2]] ^ S7[x[0xC]] ^ S8[x[0xD]] ^ S5[x[0x8]];
+ this._km[6] = S5[x[0x1]] ^ S6[x[0x0]] ^ S7[x[0xE]] ^ S8[x[0xF]] ^ S6[x[0xD]];
+ this._km[7] = S5[x[0x7]] ^ S6[x[0x6]] ^ S7[x[0x8]] ^ S8[x[0x9]] ^ S7[x[0x3]];
+ this._km[8] = S5[x[0x5]] ^ S6[x[0x4]] ^ S7[x[0xA]] ^ S8[x[0xB]] ^ S8[x[0x7]];
+
+ x03 = IntsTo32bits(x, 0x0);
+ x47 = IntsTo32bits(x, 0x4);
+ x8B = IntsTo32bits(x, 0x8);
+ xCF = IntsTo32bits(x, 0xC);
+ z03 = x03 ^ S5[x[0xD]] ^ S6[x[0xF]] ^ S7[x[0xC]] ^ S8[x[0xE]] ^ S7[x[0x8]];
+ Bits32ToInts(z03, z, 0x0);
+ z47 = x8B ^ S5[z[0x0]] ^ S6[z[0x2]] ^ S7[z[0x1]] ^ S8[z[0x3]] ^ S8[x[0xA]];
+ Bits32ToInts(z47, z, 0x4);
+ z8B = xCF ^ S5[z[0x7]] ^ S6[z[0x6]] ^ S7[z[0x5]] ^ S8[z[0x4]] ^ S5[x[0x9]];
+ Bits32ToInts(z8B, z, 0x8);
+ zCF = x47 ^ S5[z[0xA]] ^ S6[z[0x9]] ^ S7[z[0xB]] ^ S8[z[0x8]] ^ S6[x[0xB]];
+ Bits32ToInts(zCF, z, 0xC);
+ this._km[9] = S5[z[0x3]] ^ S6[z[0x2]] ^ S7[z[0xC]] ^ S8[z[0xD]] ^ S5[z[0x9]];
+ this._km[10] = S5[z[0x1]] ^ S6[z[0x0]] ^ S7[z[0xE]] ^ S8[z[0xF]] ^ S6[z[0xc]];
+ this._km[11] = S5[z[0x7]] ^ S6[z[0x6]] ^ S7[z[0x8]] ^ S8[z[0x9]] ^ S7[z[0x2]];
+ this._km[12] = S5[z[0x5]] ^ S6[z[0x4]] ^ S7[z[0xA]] ^ S8[z[0xB]] ^ S8[z[0x6]];
+
+ z03 = IntsTo32bits(z, 0x0);
+ z47 = IntsTo32bits(z, 0x4);
+ z8B = IntsTo32bits(z, 0x8);
+ zCF = IntsTo32bits(z, 0xC);
+ x03 = z8B ^ S5[z[0x5]] ^ S6[z[0x7]] ^ S7[z[0x4]] ^ S8[z[0x6]] ^ S7[z[0x0]];
+ Bits32ToInts(x03, x, 0x0);
+ x47 = z03 ^ S5[x[0x0]] ^ S6[x[0x2]] ^ S7[x[0x1]] ^ S8[x[0x3]] ^ S8[z[0x2]];
+ Bits32ToInts(x47, x, 0x4);
+ x8B = z47 ^ S5[x[0x7]] ^ S6[x[0x6]] ^ S7[x[0x5]] ^ S8[x[0x4]] ^ S5[z[0x1]];
+ Bits32ToInts(x8B, x, 0x8);
+ xCF = zCF ^ S5[x[0xA]] ^ S6[x[0x9]] ^ S7[x[0xB]] ^ S8[x[0x8]] ^ S6[z[0x3]];
+ Bits32ToInts(xCF, x, 0xC);
+ this._km[13] = S5[x[0x8]] ^ S6[x[0x9]] ^ S7[x[0x7]] ^ S8[x[0x6]] ^ S5[x[0x3]];
+ this._km[14] = S5[x[0xA]] ^ S6[x[0xB]] ^ S7[x[0x5]] ^ S8[x[0x4]] ^ S6[x[0x7]];
+ this._km[15] = S5[x[0xC]] ^ S6[x[0xD]] ^ S7[x[0x3]] ^ S8[x[0x2]] ^ S7[x[0x8]];
+ this._km[16] = S5[x[0xE]] ^ S6[x[0xF]] ^ S7[x[0x1]] ^ S8[x[0x0]] ^ S8[x[0xD]];
+
+ x03 = IntsTo32bits(x, 0x0);
+ x47 = IntsTo32bits(x, 0x4);
+ x8B = IntsTo32bits(x, 0x8);
+ xCF = IntsTo32bits(x, 0xC);
+ z03 = x03 ^ S5[x[0xD]] ^ S6[x[0xF]] ^ S7[x[0xC]] ^ S8[x[0xE]] ^ S7[x[0x8]];
+ Bits32ToInts(z03, z, 0x0);
+ z47 = x8B ^ S5[z[0x0]] ^ S6[z[0x2]] ^ S7[z[0x1]] ^ S8[z[0x3]] ^ S8[x[0xA]];
+ Bits32ToInts(z47, z, 0x4);
+ z8B = xCF ^ S5[z[0x7]] ^ S6[z[0x6]] ^ S7[z[0x5]] ^ S8[z[0x4]] ^ S5[x[0x9]];
+ Bits32ToInts(z8B, z, 0x8);
+ zCF = x47 ^ S5[z[0xA]] ^ S6[z[0x9]] ^ S7[z[0xB]] ^ S8[z[0x8]] ^ S6[x[0xB]];
+ Bits32ToInts(zCF, z, 0xC);
+ this._kr[1] = (int)((S5[z[0x8]] ^ S6[z[0x9]] ^ S7[z[0x7]] ^ S8[z[0x6]] ^ S5[z[0x2]]) & 0x1f);
+ this._kr[2] = (int)((S5[z[0xA]] ^ S6[z[0xB]] ^ S7[z[0x5]] ^ S8[z[0x4]] ^ S6[z[0x6]]) & 0x1f);
+ this._kr[3] = (int)((S5[z[0xC]] ^ S6[z[0xD]] ^ S7[z[0x3]] ^ S8[z[0x2]] ^ S7[z[0x9]]) & 0x1f);
+ this._kr[4] = (int)((S5[z[0xE]] ^ S6[z[0xF]] ^ S7[z[0x1]] ^ S8[z[0x0]] ^ S8[z[0xC]]) & 0x1f);
+
+ z03 = IntsTo32bits(z, 0x0);
+ z47 = IntsTo32bits(z, 0x4);
+ z8B = IntsTo32bits(z, 0x8);
+ zCF = IntsTo32bits(z, 0xC);
+ x03 = z8B ^ S5[z[0x5]] ^ S6[z[0x7]] ^ S7[z[0x4]] ^ S8[z[0x6]] ^ S7[z[0x0]];
+ Bits32ToInts(x03, x, 0x0);
+ x47 = z03 ^ S5[x[0x0]] ^ S6[x[0x2]] ^ S7[x[0x1]] ^ S8[x[0x3]] ^ S8[z[0x2]];
+ Bits32ToInts(x47, x, 0x4);
+ x8B = z47 ^ S5[x[0x7]] ^ S6[x[0x6]] ^ S7[x[0x5]] ^ S8[x[0x4]] ^ S5[z[0x1]];
+ Bits32ToInts(x8B, x, 0x8);
+ xCF = zCF ^ S5[x[0xA]] ^ S6[x[0x9]] ^ S7[x[0xB]] ^ S8[x[0x8]] ^ S6[z[0x3]];
+ Bits32ToInts(xCF, x, 0xC);
+ this._kr[5] = (int)((S5[x[0x3]] ^ S6[x[0x2]] ^ S7[x[0xC]] ^ S8[x[0xD]] ^ S5[x[0x8]]) & 0x1f);
+ this._kr[6] = (int)((S5[x[0x1]] ^ S6[x[0x0]] ^ S7[x[0xE]] ^ S8[x[0xF]] ^ S6[x[0xD]]) & 0x1f);
+ this._kr[7] = (int)((S5[x[0x7]] ^ S6[x[0x6]] ^ S7[x[0x8]] ^ S8[x[0x9]] ^ S7[x[0x3]]) & 0x1f);
+ this._kr[8] = (int)((S5[x[0x5]] ^ S6[x[0x4]] ^ S7[x[0xA]] ^ S8[x[0xB]] ^ S8[x[0x7]]) & 0x1f);
+
+ x03 = IntsTo32bits(x, 0x0);
+ x47 = IntsTo32bits(x, 0x4);
+ x8B = IntsTo32bits(x, 0x8);
+ xCF = IntsTo32bits(x, 0xC);
+ z03 = x03 ^ S5[x[0xD]] ^ S6[x[0xF]] ^ S7[x[0xC]] ^ S8[x[0xE]] ^ S7[x[0x8]];
+ Bits32ToInts(z03, z, 0x0);
+ z47 = x8B ^ S5[z[0x0]] ^ S6[z[0x2]] ^ S7[z[0x1]] ^ S8[z[0x3]] ^ S8[x[0xA]];
+ Bits32ToInts(z47, z, 0x4);
+ z8B = xCF ^ S5[z[0x7]] ^ S6[z[0x6]] ^ S7[z[0x5]] ^ S8[z[0x4]] ^ S5[x[0x9]];
+ Bits32ToInts(z8B, z, 0x8);
+ zCF = x47 ^ S5[z[0xA]] ^ S6[z[0x9]] ^ S7[z[0xB]] ^ S8[z[0x8]] ^ S6[x[0xB]];
+ Bits32ToInts(zCF, z, 0xC);
+ this._kr[9] = (int)((S5[z[0x3]] ^ S6[z[0x2]] ^ S7[z[0xC]] ^ S8[z[0xD]] ^ S5[z[0x9]]) & 0x1f);
+ this._kr[10] = (int)((S5[z[0x1]] ^ S6[z[0x0]] ^ S7[z[0xE]] ^ S8[z[0xF]] ^ S6[z[0xc]]) & 0x1f);
+ this._kr[11] = (int)((S5[z[0x7]] ^ S6[z[0x6]] ^ S7[z[0x8]] ^ S8[z[0x9]] ^ S7[z[0x2]]) & 0x1f);
+ this._kr[12] = (int)((S5[z[0x5]] ^ S6[z[0x4]] ^ S7[z[0xA]] ^ S8[z[0xB]] ^ S8[z[0x6]]) & 0x1f);
+
+ z03 = IntsTo32bits(z, 0x0);
+ z47 = IntsTo32bits(z, 0x4);
+ z8B = IntsTo32bits(z, 0x8);
+ zCF = IntsTo32bits(z, 0xC);
+ x03 = z8B ^ S5[z[0x5]] ^ S6[z[0x7]] ^ S7[z[0x4]] ^ S8[z[0x6]] ^ S7[z[0x0]];
+ Bits32ToInts(x03, x, 0x0);
+ x47 = z03 ^ S5[x[0x0]] ^ S6[x[0x2]] ^ S7[x[0x1]] ^ S8[x[0x3]] ^ S8[z[0x2]];
+ Bits32ToInts(x47, x, 0x4);
+ x8B = z47 ^ S5[x[0x7]] ^ S6[x[0x6]] ^ S7[x[0x5]] ^ S8[x[0x4]] ^ S5[z[0x1]];
+ Bits32ToInts(x8B, x, 0x8);
+ xCF = zCF ^ S5[x[0xA]] ^ S6[x[0x9]] ^ S7[x[0xB]] ^ S8[x[0x8]] ^ S6[z[0x3]];
+ Bits32ToInts(xCF, x, 0xC);
+ this._kr[13] = (int)((S5[x[0x8]] ^ S6[x[0x9]] ^ S7[x[0x7]] ^ S8[x[0x6]] ^ S5[x[0x3]]) & 0x1f);
+ this._kr[14] = (int)((S5[x[0xA]] ^ S6[x[0xB]] ^ S7[x[0x5]] ^ S8[x[0x4]] ^ S6[x[0x7]]) & 0x1f);
+ this._kr[15] = (int)((S5[x[0xC]] ^ S6[x[0xD]] ^ S7[x[0x3]] ^ S8[x[0x2]] ^ S7[x[0x8]]) & 0x1f);
+ this._kr[16] = (int)((S5[x[0xE]] ^ S6[x[0xF]] ^ S7[x[0x1]] ^ S8[x[0x0]] ^ S8[x[0xD]]) & 0x1f);
+ }
+
+ ///
+ /// The first of the three processing functions for the encryption and decryption.
+ ///
+ /// The input to be processed.
+ /// The mask to be used from Km[n].
+ /// The rotation value to be used.
+ ///
+ private static uint F1(uint D, uint Kmi, int Kri)
+ {
+ uint I = Kmi + D;
+ I = I << Kri | (I >> (32 - Kri));
+ return ((S1[(I >> 24) & 0xff] ^ S2[(I >> 16) & 0xff]) - S3[(I >> 8) & 0xff]) + S4[I & 0xff];
+ }
+
+ ///
+ /// The second of the three processing functions for the encryption and decryption.
+ ///
+ /// The input to be processed.
+ /// The mask to be used from Km[n].
+ /// The rotation value to be used.
+ ///
+ private static uint F2(uint D, uint Kmi, int Kri)
+ {
+ uint I = Kmi ^ D;
+ I = I << Kri | (I >> (32 - Kri));
+ return ((S1[(I >> 24) & 0xff] - S2[(I >> 16) & 0xff]) + S3[(I >> 8) & 0xff]) ^ S4[I & 0xff];
+ }
+
+ ///
+ /// The third of the three processing functions for the encryption and decryption.
+ ///
+ /// The input to be processed.
+ /// The mask to be used from Km[n].
+ /// The rotation value to be used.
+ ///
+ private static uint F3(uint D, uint Kmi, int Kri)
+ {
+ uint I = Kmi - D;
+ I = I << Kri | (I >> (32 - Kri));
+ return ((S1[(I >> 24) & 0xff] + S2[(I >> 16) & 0xff]) ^ S3[(I >> 8) & 0xff]) - S4[I & 0xff];
+ }
+
+ ///
+ /// Does the 16 rounds to encrypt the block.
+ ///
+ /// The LH-32bits of the plaintext block.
+ /// The RH-32bits of the plaintext block.
+ /// The result.
+ private void CastEncipher(uint L0, uint R0, uint[] result)
+ {
+ uint Lp = L0; // the previous value, equiv to L[i-1]
+ uint Rp = R0; // equivalent to R[i-1]
+
+ /*
+ * numbering consistent with paper to make
+ * checking and validating easier
+ */
+ uint Li = L0, Ri = R0;
+
+ for (int i = 1; i <= this._rounds; i++)
+ {
+ Lp = Li;
+ Rp = Ri;
+
+ Li = Rp;
+ switch (i)
+ {
+ case 1:
+ case 4:
+ case 7:
+ case 10:
+ case 13:
+ case 16:
+ Ri = Lp ^ F1(Rp, this._km[i], this._kr[i]);
+ break;
+ case 2:
+ case 5:
+ case 8:
+ case 11:
+ case 14:
+ Ri = Lp ^ F2(Rp, this._km[i], this._kr[i]);
+ break;
+ case 3:
+ case 6:
+ case 9:
+ case 12:
+ case 15:
+ Ri = Lp ^ F3(Rp, this._km[i], this._kr[i]);
+ break;
+ }
+ }
+
+ result[0] = Ri;
+ result[1] = Li;
+ }
+
+ private void CastDecipher(uint L16, uint R16, uint[] result)
+ {
+ uint Lp = L16; // the previous value, equiv to L[i-1]
+ uint Rp = R16; // equivalent to R[i-1]
+
+ /*
+ * numbering consistent with paper to make
+ * checking and validating easier
+ */
+ uint Li = L16, Ri = R16;
+
+ for (int i = this._rounds; i > 0; i--)
+ {
+ Lp = Li;
+ Rp = Ri;
+
+ Li = Rp;
+ switch (i)
+ {
+ case 1:
+ case 4:
+ case 7:
+ case 10:
+ case 13:
+ case 16:
+ Ri = Lp ^ F1(Rp, this._km[i], this._kr[i]);
+ break;
+ case 2:
+ case 5:
+ case 8:
+ case 11:
+ case 14:
+ Ri = Lp ^ F2(Rp, this._km[i], this._kr[i]);
+ break;
+ case 3:
+ case 6:
+ case 9:
+ case 12:
+ case 15:
+ Ri = Lp ^ F3(Rp, this._km[i], this._kr[i]);
+ break;
+ }
+ }
+
+ result[0] = Ri;
+ result[1] = Li;
+ }
+
+ private static void Bits32ToInts(uint inData, int[] b, int offset)
+ {
+ b[offset + 3] = (int)(inData & 0xff);
+ b[offset + 2] = (int)((inData >> 8) & 0xff);
+ b[offset + 1] = (int)((inData >> 16) & 0xff);
+ b[offset] = (int)((inData >> 24) & 0xff);
+ }
+
+ private static uint IntsTo32bits(int[] b, int i)
+ {
+ return (uint)(((b[i] & 0xff) << 24) |
+ ((b[i + 1] & 0xff) << 16) |
+ ((b[i + 2] & 0xff) << 8) |
+ ((b[i + 3] & 0xff)));
+ }
+
+ }
+}
diff --git a/Renci.SshNet/Security/Cryptography/Ciphers/CipherMode.cs b/Renci.SshNet/Security/Cryptography/Ciphers/CipherMode.cs
index 6984f72..a57cb5a 100644
--- a/Renci.SshNet/Security/Cryptography/Ciphers/CipherMode.cs
+++ b/Renci.SshNet/Security/Cryptography/Ciphers/CipherMode.cs
@@ -1,74 +1,71 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace Renci.SshNet.Security.Cryptography.Ciphers
-{
- ///
- /// Base class for cipher mode implementations
- ///
- public abstract class CipherMode
- {
- ///
- /// Gets the cipher.
- ///
- protected BlockCipher Cipher;
-
- ///
- /// Gets the IV vector.
- ///
- protected byte[] IV;
-
- ///
- /// Holds block size of the cipher.
- ///
- protected int _blockSize;
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The iv.
- protected CipherMode(byte[] iv)
- {
- this.IV = iv;
- }
-
- ///
- /// Initializes the specified cipher mode.
- ///
- /// The cipher.
- internal void Init(BlockCipher cipher)
- {
- this.Cipher = cipher;
- this._blockSize = cipher.BlockSize;
- this.IV = this.IV.Take(this._blockSize).ToArray();
- }
-
- ///
- /// Encrypts the specified region of the input byte array and copies the encrypted data to the specified region of the output byte array.
- ///
- /// The input data to encrypt.
- /// The offset into the input byte array from which to begin using data.
- /// The number of bytes in the input byte array to use as data.
- /// The output to which to write encrypted data.
- /// The offset into the output byte array from which to begin writing data.
- ///
- /// The number of bytes encrypted.
- ///
- public abstract int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset);
-
- ///
- /// Decrypts the specified region of the input byte array and copies the decrypted data to the specified region of the output byte array.
- ///
- /// The input data to decrypt.
- /// The offset into the input byte array from which to begin using data.
- /// The number of bytes in the input byte array to use as data.
- /// The output to which to write decrypted data.
- /// The offset into the output byte array from which to begin writing data.
- ///
- /// The number of bytes decrypted.
- ///
- public abstract int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset);
- }
-}
+using System.Linq;
+
+namespace Renci.SshNet.Security.Cryptography.Ciphers
+{
+ ///
+ /// Base class for cipher mode implementations
+ ///
+ public abstract class CipherMode
+ {
+ ///
+ /// Gets the cipher.
+ ///
+ protected BlockCipher Cipher;
+
+ ///
+ /// Gets the IV vector.
+ ///
+ protected byte[] IV;
+
+ ///
+ /// Holds block size of the cipher.
+ ///
+ protected int _blockSize;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The iv.
+ protected CipherMode(byte[] iv)
+ {
+ this.IV = iv;
+ }
+
+ ///
+ /// Initializes the specified cipher mode.
+ ///
+ /// The cipher.
+ internal void Init(BlockCipher cipher)
+ {
+ this.Cipher = cipher;
+ this._blockSize = cipher.BlockSize;
+ this.IV = this.IV.Take(this._blockSize).ToArray();
+ }
+
+ ///
+ /// Encrypts the specified region of the input byte array and copies the encrypted data to the specified region of the output byte array.
+ ///
+ /// The input data to encrypt.
+ /// The offset into the input byte array from which to begin using data.
+ /// The number of bytes in the input byte array to use as data.
+ /// The output to which to write encrypted data.
+ /// The offset into the output byte array from which to begin writing data.
+ ///
+ /// The number of bytes encrypted.
+ ///
+ public abstract int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset);
+
+ ///
+ /// Decrypts the specified region of the input byte array and copies the decrypted data to the specified region of the output byte array.
+ ///
+ /// The input data to decrypt.
+ /// The offset into the input byte array from which to begin using data.
+ /// The number of bytes in the input byte array to use as data.
+ /// The output to which to write decrypted data.
+ /// The offset into the output byte array from which to begin writing data.
+ ///
+ /// The number of bytes decrypted.
+ ///
+ public abstract int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset);
+ }
+}
diff --git a/Renci.SshNet/Security/Cryptography/Ciphers/CipherPadding.cs b/Renci.SshNet/Security/Cryptography/Ciphers/CipherPadding.cs
index 691da9d..c76080d 100644
--- a/Renci.SshNet/Security/Cryptography/Ciphers/CipherPadding.cs
+++ b/Renci.SshNet/Security/Cryptography/Ciphers/CipherPadding.cs
@@ -1,21 +1,16 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace Renci.SshNet.Security.Cryptography.Ciphers
-{
- ///
- /// Base class for cipher padding implementations
- ///
- public abstract class CipherPadding
- {
- ///
- /// Pads specified input to match block size.
- ///
- /// Size of the block.
- /// The input.
- /// Padded data array.
- public abstract byte[] Pad(int blockSize, byte[] input);
- }
-}
+namespace Renci.SshNet.Security.Cryptography.Ciphers
+{
+ ///
+ /// Base class for cipher padding implementations
+ ///
+ public abstract class CipherPadding
+ {
+ ///
+ /// Pads specified input to match block size.
+ ///
+ /// Size of the block.
+ /// The input.
+ /// Padded data array.
+ public abstract byte[] Pad(int blockSize, byte[] input);
+ }
+}
diff --git a/Renci.SshNet/Security/Cryptography/Ciphers/DesCipher.cs b/Renci.SshNet/Security/Cryptography/Ciphers/DesCipher.cs
index fe73139..41ff0cc 100644
--- a/Renci.SshNet/Security/Cryptography/Ciphers/DesCipher.cs
+++ b/Renci.SshNet/Security/Cryptography/Ciphers/DesCipher.cs
@@ -1,487 +1,484 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace Renci.SshNet.Security.Cryptography.Ciphers
-{
- ///
- /// Implements DES cipher algorithm.
- ///
- public class DesCipher : BlockCipher
- {
- private int[] _encryptionKey;
-
- private int[] _decryptionKey;
-
- #region Static tables
-
- private static readonly short[] bytebit =
- {
- 128, 64, 32, 16, 8, 4, 2, 1
- };
-
- private static readonly int[] bigbyte =
- {
- 0x800000, 0x400000, 0x200000, 0x100000,
- 0x80000, 0x40000, 0x20000, 0x10000,
- 0x8000, 0x4000, 0x2000, 0x1000,
- 0x800, 0x400, 0x200, 0x100,
- 0x80, 0x40, 0x20, 0x10,
- 0x8, 0x4, 0x2, 0x1
- };
-
- /*
- * Use the key schedule specified in the Standard (ANSI X3.92-1981).
- */
- private static readonly byte[] pc1 =
- {
- 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17,
- 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35,
- 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
- 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3
- };
-
- private static readonly byte[] totrot =
- {
- 1, 2, 4, 6, 8, 10, 12, 14,
- 15, 17, 19, 21, 23, 25, 27, 28
- };
-
- private static readonly byte[] pc2 =
- {
- 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
- 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
- 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
- 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31
- };
-
- private static readonly uint[] SP1 =
- {
- 0x01010400, 0x00000000, 0x00010000, 0x01010404,
- 0x01010004, 0x00010404, 0x00000004, 0x00010000,
- 0x00000400, 0x01010400, 0x01010404, 0x00000400,
- 0x01000404, 0x01010004, 0x01000000, 0x00000004,
- 0x00000404, 0x01000400, 0x01000400, 0x00010400,
- 0x00010400, 0x01010000, 0x01010000, 0x01000404,
- 0x00010004, 0x01000004, 0x01000004, 0x00010004,
- 0x00000000, 0x00000404, 0x00010404, 0x01000000,
- 0x00010000, 0x01010404, 0x00000004, 0x01010000,
- 0x01010400, 0x01000000, 0x01000000, 0x00000400,
- 0x01010004, 0x00010000, 0x00010400, 0x01000004,
- 0x00000400, 0x00000004, 0x01000404, 0x00010404,
- 0x01010404, 0x00010004, 0x01010000, 0x01000404,
- 0x01000004, 0x00000404, 0x00010404, 0x01010400,
- 0x00000404, 0x01000400, 0x01000400, 0x00000000,
- 0x00010004, 0x00010400, 0x00000000, 0x01010004
- };
-
- private static readonly uint[] SP2 =
- {
- 0x80108020, 0x80008000, 0x00008000, 0x00108020,
- 0x00100000, 0x00000020, 0x80100020, 0x80008020,
- 0x80000020, 0x80108020, 0x80108000, 0x80000000,
- 0x80008000, 0x00100000, 0x00000020, 0x80100020,
- 0x00108000, 0x00100020, 0x80008020, 0x00000000,
- 0x80000000, 0x00008000, 0x00108020, 0x80100000,
- 0x00100020, 0x80000020, 0x00000000, 0x00108000,
- 0x00008020, 0x80108000, 0x80100000, 0x00008020,
- 0x00000000, 0x00108020, 0x80100020, 0x00100000,
- 0x80008020, 0x80100000, 0x80108000, 0x00008000,
- 0x80100000, 0x80008000, 0x00000020, 0x80108020,
- 0x00108020, 0x00000020, 0x00008000, 0x80000000,
- 0x00008020, 0x80108000, 0x00100000, 0x80000020,
- 0x00100020, 0x80008020, 0x80000020, 0x00100020,
- 0x00108000, 0x00000000, 0x80008000, 0x00008020,
- 0x80000000, 0x80100020, 0x80108020, 0x00108000
- };
-
- private static readonly uint[] SP3 =
- {
- 0x00000208, 0x08020200, 0x00000000, 0x08020008,
- 0x08000200, 0x00000000, 0x00020208, 0x08000200,
- 0x00020008, 0x08000008, 0x08000008, 0x00020000,
- 0x08020208, 0x00020008, 0x08020000, 0x00000208,
- 0x08000000, 0x00000008, 0x08020200, 0x00000200,
- 0x00020200, 0x08020000, 0x08020008, 0x00020208,
- 0x08000208, 0x00020200, 0x00020000, 0x08000208,
- 0x00000008, 0x08020208, 0x00000200, 0x08000000,
- 0x08020200, 0x08000000, 0x00020008, 0x00000208,
- 0x00020000, 0x08020200, 0x08000200, 0x00000000,
- 0x00000200, 0x00020008, 0x08020208, 0x08000200,
- 0x08000008, 0x00000200, 0x00000000, 0x08020008,
- 0x08000208, 0x00020000, 0x08000000, 0x08020208,
- 0x00000008, 0x00020208, 0x00020200, 0x08000008,
- 0x08020000, 0x08000208, 0x00000208, 0x08020000,
- 0x00020208, 0x00000008, 0x08020008, 0x00020200
- };
-
- private static readonly uint[] SP4 =
- {
- 0x00802001, 0x00002081, 0x00002081, 0x00000080,
- 0x00802080, 0x00800081, 0x00800001, 0x00002001,
- 0x00000000, 0x00802000, 0x00802000, 0x00802081,
- 0x00000081, 0x00000000, 0x00800080, 0x00800001,
- 0x00000001, 0x00002000, 0x00800000, 0x00802001,
- 0x00000080, 0x00800000, 0x00002001, 0x00002080,
- 0x00800081, 0x00000001, 0x00002080, 0x00800080,
- 0x00002000, 0x00802080, 0x00802081, 0x00000081,
- 0x00800080, 0x00800001, 0x00802000, 0x00802081,
- 0x00000081, 0x00000000, 0x00000000, 0x00802000,
- 0x00002080, 0x00800080, 0x00800081, 0x00000001,
- 0x00802001, 0x00002081, 0x00002081, 0x00000080,
- 0x00802081, 0x00000081, 0x00000001, 0x00002000,
- 0x00800001, 0x00002001, 0x00802080, 0x00800081,
- 0x00002001, 0x00002080, 0x00800000, 0x00802001,
- 0x00000080, 0x00800000, 0x00002000, 0x00802080
- };
-
- private static readonly uint[] SP5 =
- {
- 0x00000100, 0x02080100, 0x02080000, 0x42000100,
- 0x00080000, 0x00000100, 0x40000000, 0x02080000,
- 0x40080100, 0x00080000, 0x02000100, 0x40080100,
- 0x42000100, 0x42080000, 0x00080100, 0x40000000,
- 0x02000000, 0x40080000, 0x40080000, 0x00000000,
- 0x40000100, 0x42080100, 0x42080100, 0x02000100,
- 0x42080000, 0x40000100, 0x00000000, 0x42000000,
- 0x02080100, 0x02000000, 0x42000000, 0x00080100,
- 0x00080000, 0x42000100, 0x00000100, 0x02000000,
- 0x40000000, 0x02080000, 0x42000100, 0x40080100,
- 0x02000100, 0x40000000, 0x42080000, 0x02080100,
- 0x40080100, 0x00000100, 0x02000000, 0x42080000,
- 0x42080100, 0x00080100, 0x42000000, 0x42080100,
- 0x02080000, 0x00000000, 0x40080000, 0x42000000,
- 0x00080100, 0x02000100, 0x40000100, 0x00080000,
- 0x00000000, 0x40080000, 0x02080100, 0x40000100
- };
-
- private static readonly uint[] SP6 =
- {
- 0x20000010, 0x20400000, 0x00004000, 0x20404010,
- 0x20400000, 0x00000010, 0x20404010, 0x00400000,
- 0x20004000, 0x00404010, 0x00400000, 0x20000010,
- 0x00400010, 0x20004000, 0x20000000, 0x00004010,
- 0x00000000, 0x00400010, 0x20004010, 0x00004000,
- 0x00404000, 0x20004010, 0x00000010, 0x20400010,
- 0x20400010, 0x00000000, 0x00404010, 0x20404000,
- 0x00004010, 0x00404000, 0x20404000, 0x20000000,
- 0x20004000, 0x00000010, 0x20400010, 0x00404000,
- 0x20404010, 0x00400000, 0x00004010, 0x20000010,
- 0x00400000, 0x20004000, 0x20000000, 0x00004010,
- 0x20000010, 0x20404010, 0x00404000, 0x20400000,
- 0x00404010, 0x20404000, 0x00000000, 0x20400010,
- 0x00000010, 0x00004000, 0x20400000, 0x00404010,
- 0x00004000, 0x00400010, 0x20004010, 0x00000000,
- 0x20404000, 0x20000000, 0x00400010, 0x20004010
- };
-
- private static readonly uint[] SP7 =
- {
- 0x00200000, 0x04200002, 0x04000802, 0x00000000,
- 0x00000800, 0x04000802, 0x00200802, 0x04200800,
- 0x04200802, 0x00200000, 0x00000000, 0x04000002,
- 0x00000002, 0x04000000, 0x04200002, 0x00000802,
- 0x04000800, 0x00200802, 0x00200002, 0x04000800,
- 0x04000002, 0x04200000, 0x04200800, 0x00200002,
- 0x04200000, 0x00000800, 0x00000802, 0x04200802,
- 0x00200800, 0x00000002, 0x04000000, 0x00200800,
- 0x04000000, 0x00200800, 0x00200000, 0x04000802,
- 0x04000802, 0x04200002, 0x04200002, 0x00000002,
- 0x00200002, 0x04000000, 0x04000800, 0x00200000,
- 0x04200800, 0x00000802, 0x00200802, 0x04200800,
- 0x00000802, 0x04000002, 0x04200802, 0x04200000,
- 0x00200800, 0x00000000, 0x00000002, 0x04200802,
- 0x00000000, 0x00200802, 0x04200000, 0x00000800,
- 0x04000002, 0x04000800, 0x00000800, 0x00200002
- };
-
- private static readonly uint[] SP8 =
- {
- 0x10001040, 0x00001000, 0x00040000, 0x10041040,
- 0x10000000, 0x10001040, 0x00000040, 0x10000000,
- 0x00040040, 0x10040000, 0x10041040, 0x00041000,
- 0x10041000, 0x00041040, 0x00001000, 0x00000040,
- 0x10040000, 0x10000040, 0x10001000, 0x00001040,
- 0x00041000, 0x00040040, 0x10040040, 0x10041000,
- 0x00001040, 0x00000000, 0x00000000, 0x10040040,
- 0x10000040, 0x10001000, 0x00041040, 0x00040000,
- 0x00041040, 0x00040000, 0x10041000, 0x00001000,
- 0x00000040, 0x10040040, 0x00001000, 0x00041040,
- 0x10001000, 0x00000040, 0x10000040, 0x10040000,
- 0x10040040, 0x10000000, 0x00040000, 0x10001040,
- 0x00000000, 0x10041040, 0x00040040, 0x10000040,
- 0x10040000, 0x10001000, 0x10001040, 0x00000000,
- 0x10041040, 0x00041000, 0x00041000, 0x00001040,
- 0x00001040, 0x00040040, 0x10000000, 0x10041000
- };
-
- #endregion
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The key.
- /// The mode.
- /// The padding.
- /// is null.
- public DesCipher(byte[] key, CipherMode mode, CipherPadding padding)
- : base(key, 8, mode, padding)
- {
- }
-
- ///
- /// Encrypts the specified region of the input byte array and copies the encrypted data to the specified region of the output byte array.
- ///
- /// The input data to encrypt.
- /// The offset into the input byte array from which to begin using data.
- /// The number of bytes in the input byte array to use as data.
- /// The output to which to write encrypted data.
- /// The offset into the output byte array from which to begin writing data.
- ///
- /// The number of bytes encrypted.
- ///
- public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
- {
- if ((inputOffset + this.BlockSize) > inputBuffer.Length)
- throw new IndexOutOfRangeException("input buffer too short");
-
- if ((outputOffset + this.BlockSize) > outputBuffer.Length)
- throw new IndexOutOfRangeException("output buffer too short");
-
- if (this._encryptionKey == null)
- {
- this._encryptionKey = GenerateWorkingKey(true, this.Key);
- }
-
- DesCipher.DesFunc(this._encryptionKey, inputBuffer, inputOffset, outputBuffer, outputOffset);
-
- return this.BlockSize;
- }
-
- ///
- /// Decrypts the specified region of the input byte array and copies the decrypted data to the specified region of the output byte array.
- ///
- /// The input data to decrypt.
- /// The offset into the input byte array from which to begin using data.
- /// The number of bytes in the input byte array to use as data.
- /// The output to which to write decrypted data.
- /// The offset into the output byte array from which to begin writing data.
- ///
- /// The number of bytes decrypted.
- ///
- public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
- {
- if ((inputOffset + this.BlockSize) > inputBuffer.Length)
- throw new IndexOutOfRangeException("input buffer too short");
-
- if ((outputOffset + this.BlockSize) > outputBuffer.Length)
- throw new IndexOutOfRangeException("output buffer too short");
-
- if (this._decryptionKey == null)
- {
- this._decryptionKey = GenerateWorkingKey(false, this.Key);
- }
-
- DesCipher.DesFunc(this._decryptionKey, inputBuffer, inputOffset, outputBuffer, outputOffset);
-
- return this.BlockSize;
- }
-
- ///
- /// Generates the working key.
- ///
- /// if set to true [encrypting].
- /// The key.
- /// Generated working key.
- protected int[] GenerateWorkingKey(bool encrypting, byte[] key)
- {
- this.ValidateKey();
-
- int[] newKey = new int[32];
- bool[] pc1m = new bool[56];
- bool[] pcr = new bool[56];
-
- for (int j = 0; j < 56; j++)
- {
- int l = pc1[j];
-
- pc1m[j] = ((key[(uint)l >> 3] & bytebit[l & 07]) != 0);
- }
-
- for (int i = 0; i < 16; i++)
- {
- int l, m, n;
-
- if (encrypting)
- {
- m = i << 1;
- }
- else
- {
- m = (15 - i) << 1;
- }
-
- n = m + 1;
- newKey[m] = newKey[n] = 0;
-
- for (int j = 0; j < 28; j++)
- {
- l = j + totrot[i];
- if (l < 28)
- {
- pcr[j] = pc1m[l];
- }
- else
- {
- pcr[j] = pc1m[l - 28];
- }
- }
-
- for (int j = 28; j < 56; j++)
- {
- l = j + totrot[i];
- if (l < 56)
- {
- pcr[j] = pc1m[l];
- }
- else
- {
- pcr[j] = pc1m[l - 28];
- }
- }
-
- for (int j = 0; j < 24; j++)
- {
- if (pcr[pc2[j]])
- {
- newKey[m] |= bigbyte[j];
- }
-
- if (pcr[pc2[j + 24]])
- {
- newKey[n] |= bigbyte[j];
- }
- }
- }
-
- //
- // store the processed key
- //
- for (int i = 0; i != 32; i += 2)
- {
- int i1, i2;
-
- i1 = newKey[i];
- i2 = newKey[i + 1];
-
- newKey[i] = (int) ((uint)((i1 & 0x00fc0000) << 6) |
- (uint)((i1 & 0x00000fc0) << 10) |
- ((uint)(i2 & 0x00fc0000) >> 10) |
- ((uint)(i2 & 0x00000fc0) >> 6));
-
- newKey[i + 1] = (int)((uint)((i1 & 0x0003f000) << 12) |
- (uint)((i1 & 0x0000003f) << 16) |
- ((uint)(i2 & 0x0003f000) >> 4) |
- (uint)(i2 & 0x0000003f));
- }
-
- return newKey;
- }
-
- ///
- /// Validates the key.
- ///
- protected virtual void ValidateKey()
- {
- var keySize = this.Key.Length * 8;
-
- if (!(keySize == 64))
- throw new ArgumentException(string.Format("KeySize '{0}' is not valid for this algorithm.", keySize));
- }
-
- ///
- /// Performs DES function.
- ///
- /// The w key.
- /// The input.
- /// The in off.
- /// The out bytes.
- /// The out off.
- protected static void DesFunc(int[] wKey, byte[] input, int inOff, byte[] outBytes, int outOff)
- {
- uint left = BigEndianToUInt32(input, inOff);
- uint right = BigEndianToUInt32(input, inOff + 4);
- uint work;
-
- work = ((left >> 4) ^ right) & 0x0f0f0f0f;
- right ^= work;
- left ^= (work << 4);
- work = ((left >> 16) ^ right) & 0x0000ffff;
- right ^= work;
- left ^= (work << 16);
- work = ((right >> 2) ^ left) & 0x33333333;
- left ^= work;
- right ^= (work << 2);
- work = ((right >> 8) ^ left) & 0x00ff00ff;
- left ^= work;
- right ^= (work << 8);
- right = (right << 1) | (right >> 31);
- work = (left ^ right) & 0xaaaaaaaa;
- left ^= work;
- right ^= work;
- left = (left << 1) | (left >> 31);
-
- for (int round = 0; round < 8; round++)
- {
- uint fval;
-
- work = (right << 28) | (right >> 4);
- work ^= (uint)wKey[round * 4 + 0];
- fval = SP7[work & 0x3f];
- fval |= SP5[(work >> 8) & 0x3f];
- fval |= SP3[(work >> 16) & 0x3f];
- fval |= SP1[(work >> 24) & 0x3f];
- work = right ^ (uint)wKey[round * 4 + 1];
- fval |= SP8[work & 0x3f];
- fval |= SP6[(work >> 8) & 0x3f];
- fval |= SP4[(work >> 16) & 0x3f];
- fval |= SP2[(work >> 24) & 0x3f];
- left ^= fval;
- work = (left << 28) | (left >> 4);
- work ^= (uint)wKey[round * 4 + 2];
- fval = SP7[work & 0x3f];
- fval |= SP5[(work >> 8) & 0x3f];
- fval |= SP3[(work >> 16) & 0x3f];
- fval |= SP1[(work >> 24) & 0x3f];
- work = left ^ (uint)wKey[round * 4 + 3];
- fval |= SP8[work & 0x3f];
- fval |= SP6[(work >> 8) & 0x3f];
- fval |= SP4[(work >> 16) & 0x3f];
- fval |= SP2[(work >> 24) & 0x3f];
- right ^= fval;
- }
-
- right = (right << 31) | (right >> 1);
- work = (left ^ right) & 0xaaaaaaaa;
- left ^= work;
- right ^= work;
- left = (left << 31) | (left >> 1);
- work = ((left >> 8) ^ right) & 0x00ff00ff;
- right ^= work;
- left ^= (work << 8);
- work = ((left >> 2) ^ right) & 0x33333333;
- right ^= work;
- left ^= (work << 2);
- work = ((right >> 16) ^ left) & 0x0000ffff;
- left ^= work;
- right ^= (work << 16);
- work = ((right >> 4) ^ left) & 0x0f0f0f0f;
- left ^= work;
- right ^= (work << 4);
-
- UInt32ToBigEndian(right, outBytes, outOff);
- UInt32ToBigEndian(left, outBytes, outOff + 4);
- }
- }
-}
+using System;
+
+namespace Renci.SshNet.Security.Cryptography.Ciphers
+{
+ ///
+ /// Implements DES cipher algorithm.
+ ///
+ public class DesCipher : BlockCipher
+ {
+ private int[] _encryptionKey;
+
+ private int[] _decryptionKey;
+
+ #region Static tables
+
+ private static readonly short[] bytebit =
+ {
+ 128, 64, 32, 16, 8, 4, 2, 1
+ };
+
+ private static readonly int[] bigbyte =
+ {
+ 0x800000, 0x400000, 0x200000, 0x100000,
+ 0x80000, 0x40000, 0x20000, 0x10000,
+ 0x8000, 0x4000, 0x2000, 0x1000,
+ 0x800, 0x400, 0x200, 0x100,
+ 0x80, 0x40, 0x20, 0x10,
+ 0x8, 0x4, 0x2, 0x1
+ };
+
+ /*
+ * Use the key schedule specified in the Standard (ANSI X3.92-1981).
+ */
+ private static readonly byte[] pc1 =
+ {
+ 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17,
+ 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35,
+ 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
+ 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3
+ };
+
+ private static readonly byte[] totrot =
+ {
+ 1, 2, 4, 6, 8, 10, 12, 14,
+ 15, 17, 19, 21, 23, 25, 27, 28
+ };
+
+ private static readonly byte[] pc2 =
+ {
+ 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
+ 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
+ 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
+ 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31
+ };
+
+ private static readonly uint[] SP1 =
+ {
+ 0x01010400, 0x00000000, 0x00010000, 0x01010404,
+ 0x01010004, 0x00010404, 0x00000004, 0x00010000,
+ 0x00000400, 0x01010400, 0x01010404, 0x00000400,
+ 0x01000404, 0x01010004, 0x01000000, 0x00000004,
+ 0x00000404, 0x01000400, 0x01000400, 0x00010400,
+ 0x00010400, 0x01010000, 0x01010000, 0x01000404,
+ 0x00010004, 0x01000004, 0x01000004, 0x00010004,
+ 0x00000000, 0x00000404, 0x00010404, 0x01000000,
+ 0x00010000, 0x01010404, 0x00000004, 0x01010000,
+ 0x01010400, 0x01000000, 0x01000000, 0x00000400,
+ 0x01010004, 0x00010000, 0x00010400, 0x01000004,
+ 0x00000400, 0x00000004, 0x01000404, 0x00010404,
+ 0x01010404, 0x00010004, 0x01010000, 0x01000404,
+ 0x01000004, 0x00000404, 0x00010404, 0x01010400,
+ 0x00000404, 0x01000400, 0x01000400, 0x00000000,
+ 0x00010004, 0x00010400, 0x00000000, 0x01010004
+ };
+
+ private static readonly uint[] SP2 =
+ {
+ 0x80108020, 0x80008000, 0x00008000, 0x00108020,
+ 0x00100000, 0x00000020, 0x80100020, 0x80008020,
+ 0x80000020, 0x80108020, 0x80108000, 0x80000000,
+ 0x80008000, 0x00100000, 0x00000020, 0x80100020,
+ 0x00108000, 0x00100020, 0x80008020, 0x00000000,
+ 0x80000000, 0x00008000, 0x00108020, 0x80100000,
+ 0x00100020, 0x80000020, 0x00000000, 0x00108000,
+ 0x00008020, 0x80108000, 0x80100000, 0x00008020,
+ 0x00000000, 0x00108020, 0x80100020, 0x00100000,
+ 0x80008020, 0x80100000, 0x80108000, 0x00008000,
+ 0x80100000, 0x80008000, 0x00000020, 0x80108020,
+ 0x00108020, 0x00000020, 0x00008000, 0x80000000,
+ 0x00008020, 0x80108000, 0x00100000, 0x80000020,
+ 0x00100020, 0x80008020, 0x80000020, 0x00100020,
+ 0x00108000, 0x00000000, 0x80008000, 0x00008020,
+ 0x80000000, 0x80100020, 0x80108020, 0x00108000
+ };
+
+ private static readonly uint[] SP3 =
+ {
+ 0x00000208, 0x08020200, 0x00000000, 0x08020008,
+ 0x08000200, 0x00000000, 0x00020208, 0x08000200,
+ 0x00020008, 0x08000008, 0x08000008, 0x00020000,
+ 0x08020208, 0x00020008, 0x08020000, 0x00000208,
+ 0x08000000, 0x00000008, 0x08020200, 0x00000200,
+ 0x00020200, 0x08020000, 0x08020008, 0x00020208,
+ 0x08000208, 0x00020200, 0x00020000, 0x08000208,
+ 0x00000008, 0x08020208, 0x00000200, 0x08000000,
+ 0x08020200, 0x08000000, 0x00020008, 0x00000208,
+ 0x00020000, 0x08020200, 0x08000200, 0x00000000,
+ 0x00000200, 0x00020008, 0x08020208, 0x08000200,
+ 0x08000008, 0x00000200, 0x00000000, 0x08020008,
+ 0x08000208, 0x00020000, 0x08000000, 0x08020208,
+ 0x00000008, 0x00020208, 0x00020200, 0x08000008,
+ 0x08020000, 0x08000208, 0x00000208, 0x08020000,
+ 0x00020208, 0x00000008, 0x08020008, 0x00020200
+ };
+
+ private static readonly uint[] SP4 =
+ {
+ 0x00802001, 0x00002081, 0x00002081, 0x00000080,
+ 0x00802080, 0x00800081, 0x00800001, 0x00002001,
+ 0x00000000, 0x00802000, 0x00802000, 0x00802081,
+ 0x00000081, 0x00000000, 0x00800080, 0x00800001,
+ 0x00000001, 0x00002000, 0x00800000, 0x00802001,
+ 0x00000080, 0x00800000, 0x00002001, 0x00002080,
+ 0x00800081, 0x00000001, 0x00002080, 0x00800080,
+ 0x00002000, 0x00802080, 0x00802081, 0x00000081,
+ 0x00800080, 0x00800001, 0x00802000, 0x00802081,
+ 0x00000081, 0x00000000, 0x00000000, 0x00802000,
+ 0x00002080, 0x00800080, 0x00800081, 0x00000001,
+ 0x00802001, 0x00002081, 0x00002081, 0x00000080,
+ 0x00802081, 0x00000081, 0x00000001, 0x00002000,
+ 0x00800001, 0x00002001, 0x00802080, 0x00800081,
+ 0x00002001, 0x00002080, 0x00800000, 0x00802001,
+ 0x00000080, 0x00800000, 0x00002000, 0x00802080
+ };
+
+ private static readonly uint[] SP5 =
+ {
+ 0x00000100, 0x02080100, 0x02080000, 0x42000100,
+ 0x00080000, 0x00000100, 0x40000000, 0x02080000,
+ 0x40080100, 0x00080000, 0x02000100, 0x40080100,
+ 0x42000100, 0x42080000, 0x00080100, 0x40000000,
+ 0x02000000, 0x40080000, 0x40080000, 0x00000000,
+ 0x40000100, 0x42080100, 0x42080100, 0x02000100,
+ 0x42080000, 0x40000100, 0x00000000, 0x42000000,
+ 0x02080100, 0x02000000, 0x42000000, 0x00080100,
+ 0x00080000, 0x42000100, 0x00000100, 0x02000000,
+ 0x40000000, 0x02080000, 0x42000100, 0x40080100,
+ 0x02000100, 0x40000000, 0x42080000, 0x02080100,
+ 0x40080100, 0x00000100, 0x02000000, 0x42080000,
+ 0x42080100, 0x00080100, 0x42000000, 0x42080100,
+ 0x02080000, 0x00000000, 0x40080000, 0x42000000,
+ 0x00080100, 0x02000100, 0x40000100, 0x00080000,
+ 0x00000000, 0x40080000, 0x02080100, 0x40000100
+ };
+
+ private static readonly uint[] SP6 =
+ {
+ 0x20000010, 0x20400000, 0x00004000, 0x20404010,
+ 0x20400000, 0x00000010, 0x20404010, 0x00400000,
+ 0x20004000, 0x00404010, 0x00400000, 0x20000010,
+ 0x00400010, 0x20004000, 0x20000000, 0x00004010,
+ 0x00000000, 0x00400010, 0x20004010, 0x00004000,
+ 0x00404000, 0x20004010, 0x00000010, 0x20400010,
+ 0x20400010, 0x00000000, 0x00404010, 0x20404000,
+ 0x00004010, 0x00404000, 0x20404000, 0x20000000,
+ 0x20004000, 0x00000010, 0x20400010, 0x00404000,
+ 0x20404010, 0x00400000, 0x00004010, 0x20000010,
+ 0x00400000, 0x20004000, 0x20000000, 0x00004010,
+ 0x20000010, 0x20404010, 0x00404000, 0x20400000,
+ 0x00404010, 0x20404000, 0x00000000, 0x20400010,
+ 0x00000010, 0x00004000, 0x20400000, 0x00404010,
+ 0x00004000, 0x00400010, 0x20004010, 0x00000000,
+ 0x20404000, 0x20000000, 0x00400010, 0x20004010
+ };
+
+ private static readonly uint[] SP7 =
+ {
+ 0x00200000, 0x04200002, 0x04000802, 0x00000000,
+ 0x00000800, 0x04000802, 0x00200802, 0x04200800,
+ 0x04200802, 0x00200000, 0x00000000, 0x04000002,
+ 0x00000002, 0x04000000, 0x04200002, 0x00000802,
+ 0x04000800, 0x00200802, 0x00200002, 0x04000800,
+ 0x04000002, 0x04200000, 0x04200800, 0x00200002,
+ 0x04200000, 0x00000800, 0x00000802, 0x04200802,
+ 0x00200800, 0x00000002, 0x04000000, 0x00200800,
+ 0x04000000, 0x00200800, 0x00200000, 0x04000802,
+ 0x04000802, 0x04200002, 0x04200002, 0x00000002,
+ 0x00200002, 0x04000000, 0x04000800, 0x00200000,
+ 0x04200800, 0x00000802, 0x00200802, 0x04200800,
+ 0x00000802, 0x04000002, 0x04200802, 0x04200000,
+ 0x00200800, 0x00000000, 0x00000002, 0x04200802,
+ 0x00000000, 0x00200802, 0x04200000, 0x00000800,
+ 0x04000002, 0x04000800, 0x00000800, 0x00200002
+ };
+
+ private static readonly uint[] SP8 =
+ {
+ 0x10001040, 0x00001000, 0x00040000, 0x10041040,
+ 0x10000000, 0x10001040, 0x00000040, 0x10000000,
+ 0x00040040, 0x10040000, 0x10041040, 0x00041000,
+ 0x10041000, 0x00041040, 0x00001000, 0x00000040,
+ 0x10040000, 0x10000040, 0x10001000, 0x00001040,
+ 0x00041000, 0x00040040, 0x10040040, 0x10041000,
+ 0x00001040, 0x00000000, 0x00000000, 0x10040040,
+ 0x10000040, 0x10001000, 0x00041040, 0x00040000,
+ 0x00041040, 0x00040000, 0x10041000, 0x00001000,
+ 0x00000040, 0x10040040, 0x00001000, 0x00041040,
+ 0x10001000, 0x00000040, 0x10000040, 0x10040000,
+ 0x10040040, 0x10000000, 0x00040000, 0x10001040,
+ 0x00000000, 0x10041040, 0x00040040, 0x10000040,
+ 0x10040000, 0x10001000, 0x10001040, 0x00000000,
+ 0x10041040, 0x00041000, 0x00041000, 0x00001040,
+ 0x00001040, 0x00040040, 0x10000000, 0x10041000
+ };
+
+ #endregion
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The key.
+ /// The mode.
+ /// The padding.
+ /// is null.
+ public DesCipher(byte[] key, CipherMode mode, CipherPadding padding)
+ : base(key, 8, mode, padding)
+ {
+ }
+
+ ///
+ /// Encrypts the specified region of the input byte array and copies the encrypted data to the specified region of the output byte array.
+ ///
+ /// The input data to encrypt.
+ /// The offset into the input byte array from which to begin using data.
+ /// The number of bytes in the input byte array to use as data.
+ /// The output to which to write encrypted data.
+ /// The offset into the output byte array from which to begin writing data.
+ ///
+ /// The number of bytes encrypted.
+ ///
+ public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
+ {
+ if ((inputOffset + this.BlockSize) > inputBuffer.Length)
+ throw new IndexOutOfRangeException("input buffer too short");
+
+ if ((outputOffset + this.BlockSize) > outputBuffer.Length)
+ throw new IndexOutOfRangeException("output buffer too short");
+
+ if (this._encryptionKey == null)
+ {
+ this._encryptionKey = GenerateWorkingKey(true, this.Key);
+ }
+
+ DesFunc(this._encryptionKey, inputBuffer, inputOffset, outputBuffer, outputOffset);
+
+ return this.BlockSize;
+ }
+
+ ///
+ /// Decrypts the specified region of the input byte array and copies the decrypted data to the specified region of the output byte array.
+ ///
+ /// The input data to decrypt.
+ /// The offset into the input byte array from which to begin using data.
+ /// The number of bytes in the input byte array to use as data.
+ /// The output to which to write decrypted data.
+ /// The offset into the output byte array from which to begin writing data.
+ ///
+ /// The number of bytes decrypted.
+ ///
+ public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
+ {
+ if ((inputOffset + this.BlockSize) > inputBuffer.Length)
+ throw new IndexOutOfRangeException("input buffer too short");
+
+ if ((outputOffset + this.BlockSize) > outputBuffer.Length)
+ throw new IndexOutOfRangeException("output buffer too short");
+
+ if (this._decryptionKey == null)
+ {
+ this._decryptionKey = GenerateWorkingKey(false, this.Key);
+ }
+
+ DesFunc(this._decryptionKey, inputBuffer, inputOffset, outputBuffer, outputOffset);
+
+ return this.BlockSize;
+ }
+
+ ///
+ /// Generates the working key.
+ ///
+ /// if set to true [encrypting].
+ /// The key.
+ /// Generated working key.
+ protected int[] GenerateWorkingKey(bool encrypting, byte[] key)
+ {
+ this.ValidateKey();
+
+ int[] newKey = new int[32];
+ bool[] pc1m = new bool[56];
+ bool[] pcr = new bool[56];
+
+ for (int j = 0; j < 56; j++)
+ {
+ int l = pc1[j];
+
+ pc1m[j] = ((key[(uint)l >> 3] & bytebit[l & 07]) != 0);
+ }
+
+ for (int i = 0; i < 16; i++)
+ {
+ int l, m, n;
+
+ if (encrypting)
+ {
+ m = i << 1;
+ }
+ else
+ {
+ m = (15 - i) << 1;
+ }
+
+ n = m + 1;
+ newKey[m] = newKey[n] = 0;
+
+ for (int j = 0; j < 28; j++)
+ {
+ l = j + totrot[i];
+ if (l < 28)
+ {
+ pcr[j] = pc1m[l];
+ }
+ else
+ {
+ pcr[j] = pc1m[l - 28];
+ }
+ }
+
+ for (int j = 28; j < 56; j++)
+ {
+ l = j + totrot[i];
+ if (l < 56)
+ {
+ pcr[j] = pc1m[l];
+ }
+ else
+ {
+ pcr[j] = pc1m[l - 28];
+ }
+ }
+
+ for (int j = 0; j < 24; j++)
+ {
+ if (pcr[pc2[j]])
+ {
+ newKey[m] |= bigbyte[j];
+ }
+
+ if (pcr[pc2[j + 24]])
+ {
+ newKey[n] |= bigbyte[j];
+ }
+ }
+ }
+
+ //
+ // store the processed key
+ //
+ for (int i = 0; i != 32; i += 2)
+ {
+ int i1, i2;
+
+ i1 = newKey[i];
+ i2 = newKey[i + 1];
+
+ newKey[i] = (int) ((uint)((i1 & 0x00fc0000) << 6) |
+ (uint)((i1 & 0x00000fc0) << 10) |
+ ((uint)(i2 & 0x00fc0000) >> 10) |
+ ((uint)(i2 & 0x00000fc0) >> 6));
+
+ newKey[i + 1] = (int)((uint)((i1 & 0x0003f000) << 12) |
+ (uint)((i1 & 0x0000003f) << 16) |
+ ((uint)(i2 & 0x0003f000) >> 4) |
+ (uint)(i2 & 0x0000003f));
+ }
+
+ return newKey;
+ }
+
+ ///
+ /// Validates the key.
+ ///
+ protected virtual void ValidateKey()
+ {
+ var keySize = this.Key.Length * 8;
+
+ if (!(keySize == 64))
+ throw new ArgumentException(string.Format("KeySize '{0}' is not valid for this algorithm.", keySize));
+ }
+
+ ///
+ /// Performs DES function.
+ ///
+ /// The w key.
+ /// The input.
+ /// The in off.
+ /// The out bytes.
+ /// The out off.
+ protected static void DesFunc(int[] wKey, byte[] input, int inOff, byte[] outBytes, int outOff)
+ {
+ uint left = BigEndianToUInt32(input, inOff);
+ uint right = BigEndianToUInt32(input, inOff + 4);
+ uint work;
+
+ work = ((left >> 4) ^ right) & 0x0f0f0f0f;
+ right ^= work;
+ left ^= (work << 4);
+ work = ((left >> 16) ^ right) & 0x0000ffff;
+ right ^= work;
+ left ^= (work << 16);
+ work = ((right >> 2) ^ left) & 0x33333333;
+ left ^= work;
+ right ^= (work << 2);
+ work = ((right >> 8) ^ left) & 0x00ff00ff;
+ left ^= work;
+ right ^= (work << 8);
+ right = (right << 1) | (right >> 31);
+ work = (left ^ right) & 0xaaaaaaaa;
+ left ^= work;
+ right ^= work;
+ left = (left << 1) | (left >> 31);
+
+ for (int round = 0; round < 8; round++)
+ {
+ uint fval;
+
+ work = (right << 28) | (right >> 4);
+ work ^= (uint)wKey[round * 4 + 0];
+ fval = SP7[work & 0x3f];
+ fval |= SP5[(work >> 8) & 0x3f];
+ fval |= SP3[(work >> 16) & 0x3f];
+ fval |= SP1[(work >> 24) & 0x3f];
+ work = right ^ (uint)wKey[round * 4 + 1];
+ fval |= SP8[work & 0x3f];
+ fval |= SP6[(work >> 8) & 0x3f];
+ fval |= SP4[(work >> 16) & 0x3f];
+ fval |= SP2[(work >> 24) & 0x3f];
+ left ^= fval;
+ work = (left << 28) | (left >> 4);
+ work ^= (uint)wKey[round * 4 + 2];
+ fval = SP7[work & 0x3f];
+ fval |= SP5[(work >> 8) & 0x3f];
+ fval |= SP3[(work >> 16) & 0x3f];
+ fval |= SP1[(work >> 24) & 0x3f];
+ work = left ^ (uint)wKey[round * 4 + 3];
+ fval |= SP8[work & 0x3f];
+ fval |= SP6[(work >> 8) & 0x3f];
+ fval |= SP4[(work >> 16) & 0x3f];
+ fval |= SP2[(work >> 24) & 0x3f];
+ right ^= fval;
+ }
+
+ right = (right << 31) | (right >> 1);
+ work = (left ^ right) & 0xaaaaaaaa;
+ left ^= work;
+ right ^= work;
+ left = (left << 31) | (left >> 1);
+ work = ((left >> 8) ^ right) & 0x00ff00ff;
+ right ^= work;
+ left ^= (work << 8);
+ work = ((left >> 2) ^ right) & 0x33333333;
+ right ^= work;
+ left ^= (work << 2);
+ work = ((right >> 16) ^ left) & 0x0000ffff;
+ left ^= work;
+ right ^= (work << 16);
+ work = ((right >> 4) ^ left) & 0x0f0f0f0f;
+ left ^= work;
+ right ^= (work << 4);
+
+ UInt32ToBigEndian(right, outBytes, outOff);
+ UInt32ToBigEndian(left, outBytes, outOff + 4);
+ }
+ }
+}
diff --git a/Renci.SshNet/Security/Cryptography/Ciphers/Modes/CbcCipherMode.cs b/Renci.SshNet/Security/Cryptography/Ciphers/Modes/CbcCipherMode.cs
index ecb544e..fff0ba9 100644
--- a/Renci.SshNet/Security/Cryptography/Ciphers/Modes/CbcCipherMode.cs
+++ b/Renci.SshNet/Security/Cryptography/Ciphers/Modes/CbcCipherMode.cs
@@ -1,92 +1,89 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Globalization;
-
-namespace Renci.SshNet.Security.Cryptography.Ciphers.Modes
-{
- ///
- /// Implements CBC cipher mode
- ///
- public class CbcCipherMode : CipherMode
- {
- ///
- /// Initializes a new instance of the class.
- ///
- /// The iv.
- public CbcCipherMode(byte[] iv)
- : base(iv)
- {
- }
-
- ///
- /// Encrypts the specified region of the input byte array and copies the encrypted data to the specified region of the output byte array.
- ///
- /// The input data to encrypt.
- /// The offset into the input byte array from which to begin using data.
- /// The number of bytes in the input byte array to use as data.
- /// The output to which to write encrypted data.
- /// The offset into the output byte array from which to begin writing data.
- ///
- /// The number of bytes encrypted.
- ///
- public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
- {
- if (inputBuffer.Length - inputOffset < this._blockSize)
- throw new ArgumentException("Invalid input buffer");
-
- if (outputBuffer.Length - outputOffset < this._blockSize)
- throw new ArgumentException("Invalid output buffer");
-
- if (inputCount != this._blockSize)
- throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this._blockSize));
-
- for (int i = 0; i < this._blockSize; i++)
- {
- this.IV[i] ^= inputBuffer[inputOffset + i];
- }
-
- this.Cipher.EncryptBlock(this.IV, 0, inputCount, outputBuffer, outputOffset);
-
- Buffer.BlockCopy(outputBuffer, outputOffset, this.IV, 0, this.IV.Length);
-
-
- return this._blockSize;
- }
-
- ///
- /// Decrypts the specified region of the input byte array and copies the decrypted data to the specified region of the output byte array.
- ///
- /// The input data to decrypt.
- /// The offset into the input byte array from which to begin using data.
- /// The number of bytes in the input byte array to use as data.
- /// The output to which to write decrypted data.
- /// The offset into the output byte array from which to begin writing data.
- ///
- /// The number of bytes decrypted.
- ///
- public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
- {
- if (inputBuffer.Length - inputOffset < this._blockSize)
- throw new ArgumentException("Invalid input buffer");
-
- if (outputBuffer.Length - outputOffset < this._blockSize)
- throw new ArgumentException("Invalid output buffer");
-
- if (inputCount != this._blockSize)
- throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this._blockSize));
-
- this.Cipher.DecryptBlock(inputBuffer, inputOffset, inputCount, outputBuffer, outputOffset);
-
- for (int i = 0; i < this._blockSize; i++)
- {
- outputBuffer[outputOffset + i] ^= this.IV[i];
- }
-
- Buffer.BlockCopy(inputBuffer, inputOffset, this.IV, 0, this.IV.Length);
-
- return this._blockSize;
- }
- }
-}
+using System;
+using System.Globalization;
+
+namespace Renci.SshNet.Security.Cryptography.Ciphers.Modes
+{
+ ///
+ /// Implements CBC cipher mode
+ ///
+ public class CbcCipherMode : CipherMode
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The iv.
+ public CbcCipherMode(byte[] iv)
+ : base(iv)
+ {
+ }
+
+ ///
+ /// Encrypts the specified region of the input byte array and copies the encrypted data to the specified region of the output byte array.
+ ///
+ /// The input data to encrypt.
+ /// The offset into the input byte array from which to begin using data.
+ /// The number of bytes in the input byte array to use as data.
+ /// The output to which to write encrypted data.
+ /// The offset into the output byte array from which to begin writing data.
+ ///
+ /// The number of bytes encrypted.
+ ///
+ public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
+ {
+ if (inputBuffer.Length - inputOffset < this._blockSize)
+ throw new ArgumentException("Invalid input buffer");
+
+ if (outputBuffer.Length - outputOffset < this._blockSize)
+ throw new ArgumentException("Invalid output buffer");
+
+ if (inputCount != this._blockSize)
+ throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this._blockSize));
+
+ for (int i = 0; i < this._blockSize; i++)
+ {
+ this.IV[i] ^= inputBuffer[inputOffset + i];
+ }
+
+ this.Cipher.EncryptBlock(this.IV, 0, inputCount, outputBuffer, outputOffset);
+
+ Buffer.BlockCopy(outputBuffer, outputOffset, this.IV, 0, this.IV.Length);
+
+
+ return this._blockSize;
+ }
+
+ ///
+ /// Decrypts the specified region of the input byte array and copies the decrypted data to the specified region of the output byte array.
+ ///
+ /// The input data to decrypt.
+ /// The offset into the input byte array from which to begin using data.
+ /// The number of bytes in the input byte array to use as data.
+ /// The output to which to write decrypted data.
+ /// The offset into the output byte array from which to begin writing data.
+ ///
+ /// The number of bytes decrypted.
+ ///
+ public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
+ {
+ if (inputBuffer.Length - inputOffset < this._blockSize)
+ throw new ArgumentException("Invalid input buffer");
+
+ if (outputBuffer.Length - outputOffset < this._blockSize)
+ throw new ArgumentException("Invalid output buffer");
+
+ if (inputCount != this._blockSize)
+ throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this._blockSize));
+
+ this.Cipher.DecryptBlock(inputBuffer, inputOffset, inputCount, outputBuffer, outputOffset);
+
+ for (int i = 0; i < this._blockSize; i++)
+ {
+ outputBuffer[outputOffset + i] ^= this.IV[i];
+ }
+
+ Buffer.BlockCopy(inputBuffer, inputOffset, this.IV, 0, this.IV.Length);
+
+ return this._blockSize;
+ }
+ }
+}
diff --git a/Renci.SshNet/Security/Cryptography/Ciphers/Modes/CfbCipherMode.cs b/Renci.SshNet/Security/Cryptography/Ciphers/Modes/CfbCipherMode.cs
index c40937c..71bfca9 100644
--- a/Renci.SshNet/Security/Cryptography/Ciphers/Modes/CfbCipherMode.cs
+++ b/Renci.SshNet/Security/Cryptography/Ciphers/Modes/CfbCipherMode.cs
@@ -1,96 +1,93 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Globalization;
-
-namespace Renci.SshNet.Security.Cryptography.Ciphers.Modes
-{
- ///
- /// Implements CFB cipher mode
- ///
- public class CfbCipherMode : CipherMode
- {
- private readonly byte[] _ivOutput;
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The iv.
- public CfbCipherMode(byte[] iv)
- : base(iv)
- {
- this._ivOutput = new byte[iv.Length];
- }
-
- ///
- /// Encrypts the specified region of the input byte array and copies the encrypted data to the specified region of the output byte array.
- ///
- /// The input data to encrypt.
- /// The offset into the input byte array from which to begin using data.
- /// The number of bytes in the input byte array to use as data.
- /// The output to which to write encrypted data.
- /// The offset into the output byte array from which to begin writing data.
- ///
- /// The number of bytes encrypted.
- ///
- public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
- {
- if (inputBuffer.Length - inputOffset < this._blockSize)
- throw new ArgumentException("Invalid input buffer");
-
- if (outputBuffer.Length - outputOffset < this._blockSize)
- throw new ArgumentException("Invalid output buffer");
-
- if (inputCount != this._blockSize)
- throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this._blockSize));
-
- this.Cipher.EncryptBlock(this.IV, 0, this.IV.Length, this._ivOutput, 0);
-
- for (int i = 0; i < this._blockSize; i++)
- {
- outputBuffer[outputOffset + i] = (byte)(this._ivOutput[i] ^ inputBuffer[inputOffset + i]);
- }
-
- Buffer.BlockCopy(this.IV, this._blockSize, this.IV, 0, this.IV.Length - this._blockSize);
- Buffer.BlockCopy(outputBuffer, outputOffset, this.IV, this.IV.Length - this._blockSize, this._blockSize);
-
- return this._blockSize;
- }
-
- ///
- /// Decrypts the specified region of the input byte array and copies the decrypted data to the specified region of the output byte array.
- ///
- /// The input data to decrypt.
- /// The offset into the input byte array from which to begin using data.
- /// The number of bytes in the input byte array to use as data.
- /// The output to which to write decrypted data.
- /// The offset into the output byte array from which to begin writing data.
- ///
- /// The number of bytes decrypted.
- ///
- public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
- {
- if (inputBuffer.Length - inputOffset < this._blockSize)
- throw new ArgumentException("Invalid input buffer");
-
- if (outputBuffer.Length - outputOffset < this._blockSize)
- throw new ArgumentException("Invalid output buffer");
-
- if (inputCount != this._blockSize)
- throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this._blockSize));
-
- this.Cipher.EncryptBlock(this.IV, 0, this.IV.Length, this._ivOutput, 0);
-
- Buffer.BlockCopy(this.IV, this._blockSize, this.IV, 0, this.IV.Length - this._blockSize);
- Buffer.BlockCopy(inputBuffer, inputOffset, this.IV, this.IV.Length - this._blockSize, this._blockSize);
-
- for (int i = 0; i < this._blockSize; i++)
- {
- outputBuffer[outputOffset + i] = (byte)(this._ivOutput[i] ^ inputBuffer[inputOffset + i]);
- }
-
- return this._blockSize;
- }
- }
-}
+using System;
+using System.Globalization;
+
+namespace Renci.SshNet.Security.Cryptography.Ciphers.Modes
+{
+ ///
+ /// Implements CFB cipher mode
+ ///
+ public class CfbCipherMode : CipherMode
+ {
+ private readonly byte[] _ivOutput;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The iv.
+ public CfbCipherMode(byte[] iv)
+ : base(iv)
+ {
+ this._ivOutput = new byte[iv.Length];
+ }
+
+ ///
+ /// Encrypts the specified region of the input byte array and copies the encrypted data to the specified region of the output byte array.
+ ///
+ /// The input data to encrypt.
+ /// The offset into the input byte array from which to begin using data.
+ /// The number of bytes in the input byte array to use as data.
+ /// The output to which to write encrypted data.
+ /// The offset into the output byte array from which to begin writing data.
+ ///
+ /// The number of bytes encrypted.
+ ///
+ public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
+ {
+ if (inputBuffer.Length - inputOffset < this._blockSize)
+ throw new ArgumentException("Invalid input buffer");
+
+ if (outputBuffer.Length - outputOffset < this._blockSize)
+ throw new ArgumentException("Invalid output buffer");
+
+ if (inputCount != this._blockSize)
+ throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this._blockSize));
+
+ this.Cipher.EncryptBlock(this.IV, 0, this.IV.Length, this._ivOutput, 0);
+
+ for (int i = 0; i < this._blockSize; i++)
+ {
+ outputBuffer[outputOffset + i] = (byte)(this._ivOutput[i] ^ inputBuffer[inputOffset + i]);
+ }
+
+ Buffer.BlockCopy(this.IV, this._blockSize, this.IV, 0, this.IV.Length - this._blockSize);
+ Buffer.BlockCopy(outputBuffer, outputOffset, this.IV, this.IV.Length - this._blockSize, this._blockSize);
+
+ return this._blockSize;
+ }
+
+ ///
+ /// Decrypts the specified region of the input byte array and copies the decrypted data to the specified region of the output byte array.
+ ///
+ /// The input data to decrypt.
+ /// The offset into the input byte array from which to begin using data.
+ /// The number of bytes in the input byte array to use as data.
+ /// The output to which to write decrypted data.
+ /// The offset into the output byte array from which to begin writing data.
+ ///
+ /// The number of bytes decrypted.
+ ///
+ public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
+ {
+ if (inputBuffer.Length - inputOffset < this._blockSize)
+ throw new ArgumentException("Invalid input buffer");
+
+ if (outputBuffer.Length - outputOffset < this._blockSize)
+ throw new ArgumentException("Invalid output buffer");
+
+ if (inputCount != this._blockSize)
+ throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this._blockSize));
+
+ this.Cipher.EncryptBlock(this.IV, 0, this.IV.Length, this._ivOutput, 0);
+
+ Buffer.BlockCopy(this.IV, this._blockSize, this.IV, 0, this.IV.Length - this._blockSize);
+ Buffer.BlockCopy(inputBuffer, inputOffset, this.IV, this.IV.Length - this._blockSize, this._blockSize);
+
+ for (int i = 0; i < this._blockSize; i++)
+ {
+ outputBuffer[outputOffset + i] = (byte)(this._ivOutput[i] ^ inputBuffer[inputOffset + i]);
+ }
+
+ return this._blockSize;
+ }
+ }
+}
diff --git a/Renci.SshNet/Security/Cryptography/Ciphers/Modes/CtrCipherMode.cs b/Renci.SshNet/Security/Cryptography/Ciphers/Modes/CtrCipherMode.cs
index 2f8f7c8..b51fdef 100644
--- a/Renci.SshNet/Security/Cryptography/Ciphers/Modes/CtrCipherMode.cs
+++ b/Renci.SshNet/Security/Cryptography/Ciphers/Modes/CtrCipherMode.cs
@@ -1,96 +1,93 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Globalization;
-
-namespace Renci.SshNet.Security.Cryptography.Ciphers.Modes
-{
- ///
- /// Implements CTR cipher mode
- ///
- public class CtrCipherMode : CipherMode
- {
- private readonly byte[] _ivOutput;
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The iv.
- public CtrCipherMode(byte[] iv)
- : base(iv)
- {
- this._ivOutput = new byte[iv.Length];
- }
-
- ///
- /// Encrypts the specified region of the input byte array and copies the encrypted data to the specified region of the output byte array.
- ///
- /// The input data to encrypt.
- /// The offset into the input byte array from which to begin using data.
- /// The number of bytes in the input byte array to use as data.
- /// The output to which to write encrypted data.
- /// The offset into the output byte array from which to begin writing data.
- ///
- /// The number of bytes encrypted.
- ///
- public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
- {
- if (inputBuffer.Length - inputOffset < this._blockSize)
- throw new ArgumentException("Invalid input buffer");
-
- if (outputBuffer.Length - outputOffset < this._blockSize)
- throw new ArgumentException("Invalid output buffer");
-
- if (inputCount != this._blockSize)
- throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this._blockSize));
-
- this.Cipher.EncryptBlock(this.IV, 0, this.IV.Length, this._ivOutput, 0);
-
- for (int i = 0; i < this._blockSize; i++)
- {
- outputBuffer[outputOffset + i] = (byte)(this._ivOutput[i] ^ inputBuffer[inputOffset + i]);
- }
-
- int j = this.IV.Length;
- while (--j >= 0 && ++this.IV[j] == 0) ;
-
- return this._blockSize;
- }
-
- ///
- /// Decrypts the specified region of the input byte array and copies the decrypted data to the specified region of the output byte array.
- ///
- /// The input data to decrypt.
- /// The offset into the input byte array from which to begin using data.
- /// The number of bytes in the input byte array to use as data.
- /// The output to which to write decrypted data.
- /// The offset into the output byte array from which to begin writing data.
- ///
- /// The number of bytes decrypted.
- ///
- public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
- {
- if (inputBuffer.Length - inputOffset < this._blockSize)
- throw new ArgumentException("Invalid input buffer");
-
- if (outputBuffer.Length - outputOffset < this._blockSize)
- throw new ArgumentException("Invalid output buffer");
-
- if (inputCount != this._blockSize)
- throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this._blockSize));
-
- this.Cipher.EncryptBlock(this.IV, 0, this.IV.Length, this._ivOutput, 0);
-
- for (int i = 0; i < this._blockSize; i++)
- {
- outputBuffer[outputOffset + i] = (byte)(this._ivOutput[i] ^ inputBuffer[inputOffset + i]);
- }
-
- int j = this.IV.Length;
- while (--j >= 0 && ++this.IV[j] == 0) ;
-
- return this._blockSize;
- }
- }
-}
+using System;
+using System.Globalization;
+
+namespace Renci.SshNet.Security.Cryptography.Ciphers.Modes
+{
+ ///
+ /// Implements CTR cipher mode
+ ///
+ public class CtrCipherMode : CipherMode
+ {
+ private readonly byte[] _ivOutput;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The iv.
+ public CtrCipherMode(byte[] iv)
+ : base(iv)
+ {
+ this._ivOutput = new byte[iv.Length];
+ }
+
+ ///
+ /// Encrypts the specified region of the input byte array and copies the encrypted data to the specified region of the output byte array.
+ ///
+ /// The input data to encrypt.
+ /// The offset into the input byte array from which to begin using data.
+ /// The number of bytes in the input byte array to use as data.
+ /// The output to which to write encrypted data.
+ /// The offset into the output byte array from which to begin writing data.
+ ///
+ /// The number of bytes encrypted.
+ ///
+ public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
+ {
+ if (inputBuffer.Length - inputOffset < this._blockSize)
+ throw new ArgumentException("Invalid input buffer");
+
+ if (outputBuffer.Length - outputOffset < this._blockSize)
+ throw new ArgumentException("Invalid output buffer");
+
+ if (inputCount != this._blockSize)
+ throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this._blockSize));
+
+ this.Cipher.EncryptBlock(this.IV, 0, this.IV.Length, this._ivOutput, 0);
+
+ for (int i = 0; i < this._blockSize; i++)
+ {
+ outputBuffer[outputOffset + i] = (byte)(this._ivOutput[i] ^ inputBuffer[inputOffset + i]);
+ }
+
+ int j = this.IV.Length;
+ while (--j >= 0 && ++this.IV[j] == 0) ;
+
+ return this._blockSize;
+ }
+
+ ///
+ /// Decrypts the specified region of the input byte array and copies the decrypted data to the specified region of the output byte array.
+ ///
+ /// The input data to decrypt.
+ /// The offset into the input byte array from which to begin using data.
+ /// The number of bytes in the input byte array to use as data.
+ /// The output to which to write decrypted data.
+ /// The offset into the output byte array from which to begin writing data.
+ ///
+ /// The number of bytes decrypted.
+ ///
+ public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
+ {
+ if (inputBuffer.Length - inputOffset < this._blockSize)
+ throw new ArgumentException("Invalid input buffer");
+
+ if (outputBuffer.Length - outputOffset < this._blockSize)
+ throw new ArgumentException("Invalid output buffer");
+
+ if (inputCount != this._blockSize)
+ throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this._blockSize));
+
+ this.Cipher.EncryptBlock(this.IV, 0, this.IV.Length, this._ivOutput, 0);
+
+ for (int i = 0; i < this._blockSize; i++)
+ {
+ outputBuffer[outputOffset + i] = (byte)(this._ivOutput[i] ^ inputBuffer[inputOffset + i]);
+ }
+
+ int j = this.IV.Length;
+ while (--j >= 0 && ++this.IV[j] == 0) ;
+
+ return this._blockSize;
+ }
+ }
+}
diff --git a/Renci.SshNet/Security/Cryptography/Ciphers/Modes/OfbCipherMode.cs b/Renci.SshNet/Security/Cryptography/Ciphers/Modes/OfbCipherMode.cs
index 9ed7621..be320e5 100644
--- a/Renci.SshNet/Security/Cryptography/Ciphers/Modes/OfbCipherMode.cs
+++ b/Renci.SshNet/Security/Cryptography/Ciphers/Modes/OfbCipherMode.cs
@@ -1,99 +1,95 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Renci.SshNet.Security.Cryptography.Ciphers;
-using System.Globalization;
-
-namespace Renci.SshNet.Security.Cryptography.Ciphers.Modes
-{
- ///
- /// Implements OFB cipher mode
- ///
- public class OfbCipherMode : CipherMode
- {
- private readonly byte[] _ivOutput;
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The iv.
- public OfbCipherMode(byte[] iv)
- : base(iv)
- {
- this._ivOutput = new byte[iv.Length];
- }
-
- ///
- /// Encrypts the specified region of the input byte array and copies the encrypted data to the specified region of the output byte array.
- ///
- /// The input data to encrypt.
- /// The offset into the input byte array from which to begin using data.
- /// The number of bytes in the input byte array to use as data.
- /// The output to which to write encrypted data.
- /// The offset into the output byte array from which to begin writing data.
- ///
- /// The number of bytes encrypted.
- ///
- public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
- {
- if (inputBuffer.Length - inputOffset < this._blockSize)
- throw new ArgumentException("Invalid input buffer");
-
- if (outputBuffer.Length - outputOffset < this._blockSize)
- throw new ArgumentException("Invalid output buffer");
-
- if (inputCount != this._blockSize)
- throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this._blockSize));
-
- this.Cipher.EncryptBlock(this.IV, 0, this.IV.Length, this._ivOutput, 0);
-
- for (int i = 0; i < this._blockSize; i++)
- {
- outputBuffer[outputOffset + i] = (byte)(this._ivOutput[i] ^ inputBuffer[inputOffset + i]);
- }
-
- Buffer.BlockCopy(this.IV, this._blockSize, this.IV, 0, this.IV.Length - this._blockSize);
- Buffer.BlockCopy(outputBuffer, outputOffset, this.IV, this.IV.Length - this._blockSize, this._blockSize);
-
- return this._blockSize;
- }
-
- ///
- /// Decrypts the specified region of the input byte array and copies the decrypted data to the specified region of the output byte array.
- ///
- /// The input data to decrypt.
- /// The offset into the input byte array from which to begin using data.
- /// The number of bytes in the input byte array to use as data.
- /// The output to which to write decrypted data.
- /// The offset into the output byte array from which to begin writing data.
- ///
- /// The number of bytes decrypted.
- ///
- public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
- {
- if (inputBuffer.Length - inputOffset < this._blockSize)
- throw new ArgumentException("Invalid input buffer");
-
- if (outputBuffer.Length - outputOffset < this._blockSize)
- throw new ArgumentException("Invalid output buffer");
-
- if (inputCount != this._blockSize)
- throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this._blockSize));
-
- this.Cipher.EncryptBlock(this.IV, 0, this.IV.Length, this._ivOutput, 0);
-
- for (int i = 0; i < this._blockSize; i++)
- {
- outputBuffer[outputOffset + i] = (byte)(this._ivOutput[i] ^ inputBuffer[inputOffset + i]);
- }
-
- Buffer.BlockCopy(this.IV, this._blockSize, this.IV, 0, this.IV.Length - this._blockSize);
- Buffer.BlockCopy(outputBuffer, outputOffset, this.IV, this.IV.Length - this._blockSize, this._blockSize);
-
- return this._blockSize;
- }
-
-
- }
-}
+using System;
+using System.Globalization;
+
+namespace Renci.SshNet.Security.Cryptography.Ciphers.Modes
+{
+ ///
+ /// Implements OFB cipher mode
+ ///
+ public class OfbCipherMode : CipherMode
+ {
+ private readonly byte[] _ivOutput;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The iv.
+ public OfbCipherMode(byte[] iv)
+ : base(iv)
+ {
+ this._ivOutput = new byte[iv.Length];
+ }
+
+ ///
+ /// Encrypts the specified region of the input byte array and copies the encrypted data to the specified region of the output byte array.
+ ///
+ /// The input data to encrypt.
+ /// The offset into the input byte array from which to begin using data.
+ /// The number of bytes in the input byte array to use as data.
+ /// The output to which to write encrypted data.
+ /// The offset into the output byte array from which to begin writing data.
+ ///
+ /// The number of bytes encrypted.
+ ///
+ public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
+ {
+ if (inputBuffer.Length - inputOffset < this._blockSize)
+ throw new ArgumentException("Invalid input buffer");
+
+ if (outputBuffer.Length - outputOffset < this._blockSize)
+ throw new ArgumentException("Invalid output buffer");
+
+ if (inputCount != this._blockSize)
+ throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this._blockSize));
+
+ this.Cipher.EncryptBlock(this.IV, 0, this.IV.Length, this._ivOutput, 0);
+
+ for (int i = 0; i < this._blockSize; i++)
+ {
+ outputBuffer[outputOffset + i] = (byte)(this._ivOutput[i] ^ inputBuffer[inputOffset + i]);
+ }
+
+ Buffer.BlockCopy(this.IV, this._blockSize, this.IV, 0, this.IV.Length - this._blockSize);
+ Buffer.BlockCopy(outputBuffer, outputOffset, this.IV, this.IV.Length - this._blockSize, this._blockSize);
+
+ return this._blockSize;
+ }
+
+ ///
+ /// Decrypts the specified region of the input byte array and copies the decrypted data to the specified region of the output byte array.
+ ///
+ /// The input data to decrypt.
+ /// The offset into the input byte array from which to begin using data.
+ /// The number of bytes in the input byte array to use as data.
+ /// The output to which to write decrypted data.
+ /// The offset into the output byte array from which to begin writing data.
+ ///
+ /// The number of bytes decrypted.
+ ///
+ public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
+ {
+ if (inputBuffer.Length - inputOffset < this._blockSize)
+ throw new ArgumentException("Invalid input buffer");
+
+ if (outputBuffer.Length - outputOffset < this._blockSize)
+ throw new ArgumentException("Invalid output buffer");
+
+ if (inputCount != this._blockSize)
+ throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "inputCount must be {0}.", this._blockSize));
+
+ this.Cipher.EncryptBlock(this.IV, 0, this.IV.Length, this._ivOutput, 0);
+
+ for (int i = 0; i < this._blockSize; i++)
+ {
+ outputBuffer[outputOffset + i] = (byte)(this._ivOutput[i] ^ inputBuffer[inputOffset + i]);
+ }
+
+ Buffer.BlockCopy(this.IV, this._blockSize, this.IV, 0, this.IV.Length - this._blockSize);
+ Buffer.BlockCopy(outputBuffer, outputOffset, this.IV, this.IV.Length - this._blockSize, this._blockSize);
+
+ return this._blockSize;
+ }
+
+
+ }
+}
diff --git a/Renci.SshNet/Security/Cryptography/Ciphers/Paddings/PKCS5Padding.cs b/Renci.SshNet/Security/Cryptography/Ciphers/Paddings/PKCS5Padding.cs
index fc624be..e83f444 100644
--- a/Renci.SshNet/Security/Cryptography/Ciphers/Paddings/PKCS5Padding.cs
+++ b/Renci.SshNet/Security/Cryptography/Ciphers/Paddings/PKCS5Padding.cs
@@ -1,35 +1,32 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace Renci.SshNet.Security.Cryptography.Ciphers.Paddings
-{
- ///
- /// Implements PKCS5 cipher padding
- ///
- public class PKCS5Padding : CipherPadding
- {
- ///
- /// Transforms the specified input.
- ///
- /// Size of the block.
- /// The input.
- ///
- /// Padded data array.
- ///
- public override byte[] Pad(int blockSize, byte[] input)
- {
- var numOfPaddedBytes = blockSize - (input.Length % blockSize);
-
- var output = new byte[input.Length + numOfPaddedBytes];
- Buffer.BlockCopy(input, 0, output, 0, input.Length);
- for (int i = 0; i < numOfPaddedBytes; i++)
- {
- output[input.Length + i] = (byte)numOfPaddedBytes;
- }
-
- return output;
- }
- }
-}
+using System;
+
+namespace Renci.SshNet.Security.Cryptography.Ciphers.Paddings
+{
+ ///
+ /// Implements PKCS5 cipher padding
+ ///
+ public class PKCS5Padding : CipherPadding
+ {
+ ///
+ /// Transforms the specified input.
+ ///
+ /// Size of the block.
+ /// The input.
+ ///
+ /// Padded data array.
+ ///
+ public override byte[] Pad(int blockSize, byte[] input)
+ {
+ var numOfPaddedBytes = blockSize - (input.Length % blockSize);
+
+ var output = new byte[input.Length + numOfPaddedBytes];
+ Buffer.BlockCopy(input, 0, output, 0, input.Length);
+ for (int i = 0; i < numOfPaddedBytes; i++)
+ {
+ output[input.Length + i] = (byte)numOfPaddedBytes;
+ }
+
+ return output;
+ }
+ }
+}
diff --git a/Renci.SshNet/Security/Cryptography/Ciphers/Paddings/PKCS7Padding.cs b/Renci.SshNet/Security/Cryptography/Ciphers/Paddings/PKCS7Padding.cs
index 578edf0..372ab3f 100644
--- a/Renci.SshNet/Security/Cryptography/Ciphers/Paddings/PKCS7Padding.cs
+++ b/Renci.SshNet/Security/Cryptography/Ciphers/Paddings/PKCS7Padding.cs
@@ -1,35 +1,32 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace Renci.SshNet.Security.Cryptography.Ciphers.Paddings
-{
- ///
- /// Implements PKCS7 cipher padding
- ///
- public class PKCS7Padding : CipherPadding
- {
- ///
- /// Transforms the specified input.
- ///
- /// Size of the block.
- /// The input.
- ///
- /// Padded data array.
- ///
- public override byte[] Pad(int blockSize, byte[] input)
- {
- var numOfPaddedBytes = blockSize - (input.Length % blockSize);
-
- var output = new byte[input.Length + numOfPaddedBytes];
- Buffer.BlockCopy(input, 0, output, 0, input.Length);
- for (int i = 0; i < numOfPaddedBytes; i++)
- {
- output[input.Length + i] = output[input.Length - 1];
- }
-
- return output;
- }
- }
-}
+using System;
+
+namespace Renci.SshNet.Security.Cryptography.Ciphers.Paddings
+{
+ ///
+ /// Implements PKCS7 cipher padding
+ ///
+ public class PKCS7Padding : CipherPadding
+ {
+ ///
+ /// Transforms the specified input.
+ ///
+ /// Size of the block.
+ /// The input.
+ ///
+ /// Padded data array.
+ ///
+ public override byte[] Pad(int blockSize, byte[] input)
+ {
+ var numOfPaddedBytes = blockSize - (input.Length % blockSize);
+
+ var output = new byte[input.Length + numOfPaddedBytes];
+ Buffer.BlockCopy(input, 0, output, 0, input.Length);
+ for (int i = 0; i < numOfPaddedBytes; i++)
+ {
+ output[input.Length + i] = (byte)numOfPaddedBytes;
+ }
+
+ return output;
+ }
+ }
+}
diff --git a/Renci.SshNet/Security/Cryptography/Ciphers/RsaCipher.cs b/Renci.SshNet/Security/Cryptography/Ciphers/RsaCipher.cs
index 7a9bab2..c80b135 100644
--- a/Renci.SshNet/Security/Cryptography/Ciphers/RsaCipher.cs
+++ b/Renci.SshNet/Security/Cryptography/Ciphers/RsaCipher.cs
@@ -1,133 +1,130 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Security.Cryptography;
-using Renci.SshNet.Common;
-
-namespace Renci.SshNet.Security.Cryptography.Ciphers
-{
- ///
- /// Implements RSA cipher algorithm.
- ///
- public class RsaCipher : AsymmetricCipher
- {
- private bool _isPrivate;
-
- private RsaKey _key;
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The RSA key.
- public RsaCipher(RsaKey key)
- {
- if (key == null)
- throw new ArgumentNullException("key");
-
- this._key = key;
-
- this._isPrivate = !this._key.D.IsZero;
- }
-
- ///
- /// Encrypts the specified data.
- ///
- /// The data.
- /// Encrypted data.
- public override byte[] Encrypt(byte[] data)
- {
- // Calculate signature
- var bitLength = this._key.Modulus.BitLength;
-
- var paddedBlock = new byte[bitLength / 8 + (bitLength % 8 > 0 ? 1 : 0) - 1];
-
- paddedBlock[0] = 0x01;
- for (int i = 1; i < paddedBlock.Length - data.Length - 1; i++)
- {
- paddedBlock[i] = 0xFF;
- }
-
- Buffer.BlockCopy(data, 0, paddedBlock, paddedBlock.Length - data.Length, data.Length);
-
- return this.Transform(paddedBlock);
- }
-
- ///
- /// Decrypts the specified data.
- ///
- /// The data.
- ///
- /// Decrypted data.
- ///
- /// Only block type 01 or 02 are supported.
- /// Thrown when decrypted block type is not supported.
- public override byte[] Decrypt(byte[] data)
- {
- var paddedBlock = this.Transform(data);
-
- if (paddedBlock[0] != 1 && paddedBlock[0] != 2)
- throw new NotSupportedException("Only block type 01 or 02 are supported.");
-
- var position = 1;
- while (position < paddedBlock.Length && paddedBlock[position] != 0)
- position++;
- position++;
-
- var result = new byte[paddedBlock.Length - position];
-
- Buffer.BlockCopy(paddedBlock, position, result, 0, result.Length);
-
- return result;
- }
-
- private byte[] Transform(byte[] data)
- {
- var bytes = new List(data.Reverse());
- bytes.Add(0);
-
- var input = new BigInteger(bytes.ToArray());
-
- BigInteger result;
-
- if (this._isPrivate)
- {
- BigInteger random = BigInteger.One;
-
- var max = this._key.Modulus - 1;
-
- var bitLength = this._key.Modulus.BitLength;
-
- if (max < BigInteger.One)
- throw new SshException("Invalid RSA key.");
-
- while (random <= BigInteger.One || random >= max)
- {
- random = BigInteger.Random(bitLength);
- }
-
- BigInteger blindedInput = BigInteger.PositiveMod((BigInteger.ModPow(random, this._key.Exponent, this._key.Modulus) * input), this._key.Modulus);
-
- // mP = ((input Mod p) ^ dP)) Mod p
- var mP = BigInteger.ModPow((blindedInput % this._key.P), this._key.DP, this._key.P);
-
- // mQ = ((input Mod q) ^ dQ)) Mod q
- var mQ = BigInteger.ModPow((blindedInput % this._key.Q), this._key.DQ, this._key.Q);
-
- var h = BigInteger.PositiveMod(((mP - mQ) * this._key.InverseQ), this._key.P);
-
- var m = h * this._key.Q + mQ;
-
- BigInteger rInv = BigInteger.ModInverse(random, this._key.Modulus);
-
- result = BigInteger.PositiveMod((m * rInv), this._key.Modulus);
- }
- else
- {
- result = BigInteger.ModPow(input, this._key.Exponent, this._key.Modulus);
- }
-
- return result.ToByteArray().Reverse().ToArray();
- }
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using Renci.SshNet.Common;
+
+namespace Renci.SshNet.Security.Cryptography.Ciphers
+{
+ ///
+ /// Implements RSA cipher algorithm.
+ ///
+ public class RsaCipher : AsymmetricCipher
+ {
+ private readonly bool _isPrivate;
+
+ private readonly RsaKey _key;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The RSA key.
+ public RsaCipher(RsaKey key)
+ {
+ if (key == null)
+ throw new ArgumentNullException("key");
+
+ this._key = key;
+ this._isPrivate = !this._key.D.IsZero;
+ }
+
+ ///
+ /// Encrypts the specified data.
+ ///
+ /// The data.
+ /// Encrypted data.
+ public override byte[] Encrypt(byte[] data)
+ {
+ // Calculate signature
+ var bitLength = this._key.Modulus.BitLength;
+
+ var paddedBlock = new byte[bitLength / 8 + (bitLength % 8 > 0 ? 1 : 0) - 1];
+
+ paddedBlock[0] = 0x01;
+ for (int i = 1; i < paddedBlock.Length - data.Length - 1; i++)
+ {
+ paddedBlock[i] = 0xFF;
+ }
+
+ Buffer.BlockCopy(data, 0, paddedBlock, paddedBlock.Length - data.Length, data.Length);
+
+ return this.Transform(paddedBlock);
+ }
+
+ ///
+ /// Decrypts the specified data.
+ ///
+ /// The data.
+ ///
+ /// Decrypted data.
+ ///
+ /// Only block type 01 or 02 are supported.
+ /// Thrown when decrypted block type is not supported.
+ public override byte[] Decrypt(byte[] data)
+ {
+ var paddedBlock = this.Transform(data);
+
+ if (paddedBlock[0] != 1 && paddedBlock[0] != 2)
+ throw new NotSupportedException("Only block type 01 or 02 are supported.");
+
+ var position = 1;
+ while (position < paddedBlock.Length && paddedBlock[position] != 0)
+ position++;
+ position++;
+
+ var result = new byte[paddedBlock.Length - position];
+
+ Buffer.BlockCopy(paddedBlock, position, result, 0, result.Length);
+
+ return result;
+ }
+
+ private byte[] Transform(byte[] data)
+ {
+ var bytes = new List(data.Reverse());
+ bytes.Add(0);
+
+ var input = new BigInteger(bytes.ToArray());
+
+ BigInteger result;
+
+ if (this._isPrivate)
+ {
+ BigInteger random = BigInteger.One;
+
+ var max = this._key.Modulus - 1;
+
+ var bitLength = this._key.Modulus.BitLength;
+
+ if (max < BigInteger.One)
+ throw new SshException("Invalid RSA key.");
+
+ while (random <= BigInteger.One || random >= max)
+ {
+ random = BigInteger.Random(bitLength);
+ }
+
+ BigInteger blindedInput = BigInteger.PositiveMod((BigInteger.ModPow(random, this._key.Exponent, this._key.Modulus) * input), this._key.Modulus);
+
+ // mP = ((input Mod p) ^ dP)) Mod p
+ var mP = BigInteger.ModPow((blindedInput % this._key.P), this._key.DP, this._key.P);
+
+ // mQ = ((input Mod q) ^ dQ)) Mod q
+ var mQ = BigInteger.ModPow((blindedInput % this._key.Q), this._key.DQ, this._key.Q);
+
+ var h = BigInteger.PositiveMod(((mP - mQ) * this._key.InverseQ), this._key.P);
+
+ var m = h * this._key.Q + mQ;
+
+ BigInteger rInv = BigInteger.ModInverse(random, this._key.Modulus);
+
+ result = BigInteger.PositiveMod((m * rInv), this._key.Modulus);
+ }
+ else
+ {
+ result = BigInteger.ModPow(input, this._key.Exponent, this._key.Modulus);
+ }
+
+ return result.ToByteArray().Reverse().ToArray();
+ }
+ }
+}
diff --git a/Renci.SshNet/Security/Cryptography/Ciphers/SerpentCipher.cs b/Renci.SshNet/Security/Cryptography/Ciphers/SerpentCipher.cs
index 810d995..5f58320 100644
--- a/Renci.SshNet/Security/Cryptography/Ciphers/SerpentCipher.cs
+++ b/Renci.SshNet/Security/Cryptography/Ciphers/SerpentCipher.cs
@@ -1,772 +1,769 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace Renci.SshNet.Security.Cryptography.Ciphers
-{
- ///
- /// Implements Serpent cipher algorithm.
- ///
- public sealed class SerpentCipher : BlockCipher
- {
- private static readonly int ROUNDS = 32;
-
- private static readonly int PHI = unchecked((int)0x9E3779B9); // (Sqrt(5) - 1) * 2**31
-
- private int[] _workingKey;
-
- private int _x0, _x1, _x2, _x3; // registers
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The key.
- /// The mode.
- /// The padding.
- /// is null.
- /// Keysize is not valid for this algorithm.
- public SerpentCipher(byte[] key, CipherMode mode, CipherPadding padding)
- : base(key, 16, mode, padding)
- {
- var keySize = key.Length * 8;
-
- if (!(keySize == 128 || keySize == 192 || keySize == 256))
- throw new ArgumentException(string.Format("KeySize '{0}' is not valid for this algorithm.", keySize));
-
- this._workingKey = this.MakeWorkingKey(key);
- }
-
- ///
- /// Encrypts the specified region of the input byte array and copies the encrypted data to the specified region of the output byte array.
- ///
- /// The input data to encrypt.
- /// The offset into the input byte array from which to begin using data.
- /// The number of bytes in the input byte array to use as data.
- /// The output to which to write encrypted data.
- /// The offset into the output byte array from which to begin writing data.
- ///
- /// The number of bytes encrypted.
- ///
- public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
- {
- if (inputCount != this.BlockSize)
- throw new ArgumentException("inputCount");
-
- this._x3 = BytesToWord(inputBuffer, inputOffset);
- this._x2 = BytesToWord(inputBuffer, inputOffset + 4);
- this._x1 = BytesToWord(inputBuffer, inputOffset + 8);
- this._x0 = BytesToWord(inputBuffer, inputOffset + 12);
-
- Sb0(this._workingKey[0] ^ this._x0, this._workingKey[1] ^ this._x1, this._workingKey[2] ^ this._x2, this._workingKey[3] ^ this._x3); LT();
- Sb1(this._workingKey[4] ^ this._x0, this._workingKey[5] ^ this._x1, this._workingKey[6] ^ this._x2, this._workingKey[7] ^ this._x3); LT();
- Sb2(this._workingKey[8] ^ this._x0, this._workingKey[9] ^ this._x1, this._workingKey[10] ^ this._x2, this._workingKey[11] ^ this._x3); LT();
- Sb3(this._workingKey[12] ^ this._x0, this._workingKey[13] ^ this._x1, this._workingKey[14] ^ this._x2, this._workingKey[15] ^ this._x3); LT();
- Sb4(this._workingKey[16] ^ this._x0, this._workingKey[17] ^ this._x1, this._workingKey[18] ^ this._x2, this._workingKey[19] ^ this._x3); LT();
- Sb5(this._workingKey[20] ^ this._x0, this._workingKey[21] ^ this._x1, this._workingKey[22] ^ this._x2, this._workingKey[23] ^ this._x3); LT();
- Sb6(this._workingKey[24] ^ this._x0, this._workingKey[25] ^ this._x1, this._workingKey[26] ^ this._x2, this._workingKey[27] ^ this._x3); LT();
- Sb7(this._workingKey[28] ^ this._x0, this._workingKey[29] ^ this._x1, this._workingKey[30] ^ this._x2, this._workingKey[31] ^ this._x3); LT();
- Sb0(this._workingKey[32] ^ this._x0, this._workingKey[33] ^ this._x1, this._workingKey[34] ^ this._x2, this._workingKey[35] ^ this._x3); LT();
- Sb1(this._workingKey[36] ^ this._x0, this._workingKey[37] ^ this._x1, this._workingKey[38] ^ this._x2, this._workingKey[39] ^ this._x3); LT();
- Sb2(this._workingKey[40] ^ this._x0, this._workingKey[41] ^ this._x1, this._workingKey[42] ^ this._x2, this._workingKey[43] ^ this._x3); LT();
- Sb3(this._workingKey[44] ^ this._x0, this._workingKey[45] ^ this._x1, this._workingKey[46] ^ this._x2, this._workingKey[47] ^ this._x3); LT();
- Sb4(this._workingKey[48] ^ this._x0, this._workingKey[49] ^ this._x1, this._workingKey[50] ^ this._x2, this._workingKey[51] ^ this._x3); LT();
- Sb5(this._workingKey[52] ^ this._x0, this._workingKey[53] ^ this._x1, this._workingKey[54] ^ this._x2, this._workingKey[55] ^ this._x3); LT();
- Sb6(this._workingKey[56] ^ this._x0, this._workingKey[57] ^ this._x1, this._workingKey[58] ^ this._x2, this._workingKey[59] ^ this._x3); LT();
- Sb7(this._workingKey[60] ^ this._x0, this._workingKey[61] ^ this._x1, this._workingKey[62] ^ this._x2, this._workingKey[63] ^ this._x3); LT();
- Sb0(this._workingKey[64] ^ this._x0, this._workingKey[65] ^ this._x1, this._workingKey[66] ^ this._x2, this._workingKey[67] ^ this._x3); LT();
- Sb1(this._workingKey[68] ^ this._x0, this._workingKey[69] ^ this._x1, this._workingKey[70] ^ this._x2, this._workingKey[71] ^ this._x3); LT();
- Sb2(this._workingKey[72] ^ this._x0, this._workingKey[73] ^ this._x1, this._workingKey[74] ^ this._x2, this._workingKey[75] ^ this._x3); LT();
- Sb3(this._workingKey[76] ^ this._x0, this._workingKey[77] ^ this._x1, this._workingKey[78] ^ this._x2, this._workingKey[79] ^ this._x3); LT();
- Sb4(this._workingKey[80] ^ this._x0, this._workingKey[81] ^ this._x1, this._workingKey[82] ^ this._x2, this._workingKey[83] ^ this._x3); LT();
- Sb5(this._workingKey[84] ^ this._x0, this._workingKey[85] ^ this._x1, this._workingKey[86] ^ this._x2, this._workingKey[87] ^ this._x3); LT();
- Sb6(this._workingKey[88] ^ this._x0, this._workingKey[89] ^ this._x1, this._workingKey[90] ^ this._x2, this._workingKey[91] ^ this._x3); LT();
- Sb7(this._workingKey[92] ^ this._x0, this._workingKey[93] ^ this._x1, this._workingKey[94] ^ this._x2, this._workingKey[95] ^ this._x3); LT();
- Sb0(this._workingKey[96] ^ this._x0, this._workingKey[97] ^ this._x1, this._workingKey[98] ^ this._x2, this._workingKey[99] ^ this._x3); LT();
- Sb1(this._workingKey[100] ^ this._x0, this._workingKey[101] ^ this._x1, this._workingKey[102] ^ this._x2, this._workingKey[103] ^ this._x3); LT();
- Sb2(this._workingKey[104] ^ this._x0, this._workingKey[105] ^ this._x1, this._workingKey[106] ^ this._x2, this._workingKey[107] ^ this._x3); LT();
- Sb3(this._workingKey[108] ^ this._x0, this._workingKey[109] ^ this._x1, this._workingKey[110] ^ this._x2, this._workingKey[111] ^ this._x3); LT();
- Sb4(this._workingKey[112] ^ this._x0, this._workingKey[113] ^ this._x1, this._workingKey[114] ^ this._x2, this._workingKey[115] ^ this._x3); LT();
- Sb5(this._workingKey[116] ^ this._x0, this._workingKey[117] ^ this._x1, this._workingKey[118] ^ this._x2, this._workingKey[119] ^ this._x3); LT();
- Sb6(this._workingKey[120] ^ this._x0, this._workingKey[121] ^ this._x1, this._workingKey[122] ^ this._x2, this._workingKey[123] ^ this._x3); LT();
- Sb7(this._workingKey[124] ^ this._x0, this._workingKey[125] ^ this._x1, this._workingKey[126] ^ this._x2, this._workingKey[127] ^ this._x3);
-
- WordToBytes(this._workingKey[131] ^ this._x3, outputBuffer, outputOffset);
- WordToBytes(this._workingKey[130] ^ this._x2, outputBuffer, outputOffset + 4);
- WordToBytes(this._workingKey[129] ^ this._x1, outputBuffer, outputOffset + 8);
- WordToBytes(this._workingKey[128] ^ this._x0, outputBuffer, outputOffset + 12);
-
- return this.BlockSize;
- }
-
- ///
- /// Decrypts the specified region of the input byte array and copies the decrypted data to the specified region of the output byte array.
- ///
- /// The input data to decrypt.
- /// The offset into the input byte array from which to begin using data.
- /// The number of bytes in the input byte array to use as data.
- /// The output to which to write decrypted data.
- /// The offset into the output byte array from which to begin writing data.
- ///
- /// The number of bytes decrypted.
- ///
- public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
- {
- if (inputCount != this.BlockSize)
- throw new ArgumentException("inputCount");
-
- this._x3 = this._workingKey[131] ^ BytesToWord(inputBuffer, inputOffset);
- this._x2 = this._workingKey[130] ^ BytesToWord(inputBuffer, inputOffset + 4);
- this._x1 = this._workingKey[129] ^ BytesToWord(inputBuffer, inputOffset + 8);
- this._x0 = this._workingKey[128] ^ BytesToWord(inputBuffer, inputOffset + 12);
-
- Ib7(this._x0, this._x1, this._x2, this._x3);
- this._x0 ^= this._workingKey[124]; this._x1 ^= this._workingKey[125]; this._x2 ^= this._workingKey[126]; this._x3 ^= this._workingKey[127];
- InverseLT(); Ib6(this._x0, this._x1, this._x2, this._x3);
- this._x0 ^= this._workingKey[120]; this._x1 ^= this._workingKey[121]; this._x2 ^= this._workingKey[122]; this._x3 ^= this._workingKey[123];
- InverseLT(); Ib5(this._x0, this._x1, this._x2, this._x3);
- this._x0 ^= this._workingKey[116]; this._x1 ^= this._workingKey[117]; this._x2 ^= this._workingKey[118]; this._x3 ^= this._workingKey[119];
- InverseLT(); Ib4(this._x0, this._x1, this._x2, this._x3);
- this._x0 ^= this._workingKey[112]; this._x1 ^= this._workingKey[113]; this._x2 ^= this._workingKey[114]; this._x3 ^= this._workingKey[115];
- InverseLT(); Ib3(this._x0, this._x1, this._x2, this._x3);
- this._x0 ^= this._workingKey[108]; this._x1 ^= this._workingKey[109]; this._x2 ^= this._workingKey[110]; this._x3 ^= this._workingKey[111];
- InverseLT(); Ib2(this._x0, this._x1, this._x2, this._x3);
- this._x0 ^= this._workingKey[104]; this._x1 ^= this._workingKey[105]; this._x2 ^= this._workingKey[106]; this._x3 ^= this._workingKey[107];
- InverseLT(); Ib1(this._x0, this._x1, this._x2, this._x3);
- this._x0 ^= this._workingKey[100]; this._x1 ^= this._workingKey[101]; this._x2 ^= this._workingKey[102]; this._x3 ^= this._workingKey[103];
- InverseLT(); Ib0(this._x0, this._x1, this._x2, this._x3);
- this._x0 ^= this._workingKey[96]; this._x1 ^= this._workingKey[97]; this._x2 ^= this._workingKey[98]; this._x3 ^= this._workingKey[99];
- InverseLT(); Ib7(this._x0, this._x1, this._x2, this._x3);
- this._x0 ^= this._workingKey[92]; this._x1 ^= this._workingKey[93]; this._x2 ^= this._workingKey[94]; this._x3 ^= this._workingKey[95];
- InverseLT(); Ib6(this._x0, this._x1, this._x2, this._x3);
- this._x0 ^= this._workingKey[88]; this._x1 ^= this._workingKey[89]; this._x2 ^= this._workingKey[90]; this._x3 ^= this._workingKey[91];
- InverseLT(); Ib5(this._x0, this._x1, this._x2, this._x3);
- this._x0 ^= this._workingKey[84]; this._x1 ^= this._workingKey[85]; this._x2 ^= this._workingKey[86]; this._x3 ^= this._workingKey[87];
- InverseLT(); Ib4(this._x0, this._x1, this._x2, this._x3);
- this._x0 ^= this._workingKey[80]; this._x1 ^= this._workingKey[81]; this._x2 ^= this._workingKey[82]; this._x3 ^= this._workingKey[83];
- InverseLT(); Ib3(this._x0, this._x1, this._x2, this._x3);
- this._x0 ^= this._workingKey[76]; this._x1 ^= this._workingKey[77]; this._x2 ^= this._workingKey[78]; this._x3 ^= this._workingKey[79];
- InverseLT(); Ib2(this._x0, this._x1, this._x2, this._x3);
- this._x0 ^= this._workingKey[72]; this._x1 ^= this._workingKey[73]; this._x2 ^= this._workingKey[74]; this._x3 ^= this._workingKey[75];
- InverseLT(); Ib1(this._x0, this._x1, this._x2, this._x3);
- this._x0 ^= this._workingKey[68]; this._x1 ^= this._workingKey[69]; this._x2 ^= this._workingKey[70]; this._x3 ^= this._workingKey[71];
- InverseLT(); Ib0(this._x0, this._x1, this._x2, this._x3);
- this._x0 ^= this._workingKey[64]; this._x1 ^= this._workingKey[65]; this._x2 ^= this._workingKey[66]; this._x3 ^= this._workingKey[67];
- InverseLT(); Ib7(this._x0, this._x1, this._x2, this._x3);
- this._x0 ^= this._workingKey[60]; this._x1 ^= this._workingKey[61]; this._x2 ^= this._workingKey[62]; this._x3 ^= this._workingKey[63];
- InverseLT(); Ib6(this._x0, this._x1, this._x2, this._x3);
- this._x0 ^= this._workingKey[56]; this._x1 ^= this._workingKey[57]; this._x2 ^= this._workingKey[58]; this._x3 ^= this._workingKey[59];
- InverseLT(); Ib5(this._x0, this._x1, this._x2, this._x3);
- this._x0 ^= this._workingKey[52]; this._x1 ^= this._workingKey[53]; this._x2 ^= this._workingKey[54]; this._x3 ^= this._workingKey[55];
- InverseLT(); Ib4(this._x0, this._x1, this._x2, this._x3);
- this._x0 ^= this._workingKey[48]; this._x1 ^= this._workingKey[49]; this._x2 ^= this._workingKey[50]; this._x3 ^= this._workingKey[51];
- InverseLT(); Ib3(this._x0, this._x1, this._x2, this._x3);
- this._x0 ^= this._workingKey[44]; this._x1 ^= this._workingKey[45]; this._x2 ^= this._workingKey[46]; this._x3 ^= this._workingKey[47];
- InverseLT(); Ib2(this._x0, this._x1, this._x2, this._x3);
- this._x0 ^= this._workingKey[40]; this._x1 ^= this._workingKey[41]; this._x2 ^= this._workingKey[42]; this._x3 ^= this._workingKey[43];
- InverseLT(); Ib1(this._x0, this._x1, this._x2, this._x3);
- this._x0 ^= this._workingKey[36]; this._x1 ^= this._workingKey[37]; this._x2 ^= this._workingKey[38]; this._x3 ^= this._workingKey[39];
- InverseLT(); Ib0(this._x0, this._x1, this._x2, this._x3);
- this._x0 ^= this._workingKey[32]; this._x1 ^= this._workingKey[33]; this._x2 ^= this._workingKey[34]; this._x3 ^= this._workingKey[35];
- InverseLT(); Ib7(this._x0, this._x1, this._x2, this._x3);
- this._x0 ^= this._workingKey[28]; this._x1 ^= this._workingKey[29]; this._x2 ^= this._workingKey[30]; this._x3 ^= this._workingKey[31];
- InverseLT(); Ib6(this._x0, this._x1, this._x2, this._x3);
- this._x0 ^= this._workingKey[24]; this._x1 ^= this._workingKey[25]; this._x2 ^= this._workingKey[26]; this._x3 ^= this._workingKey[27];
- InverseLT(); Ib5(this._x0, this._x1, this._x2, this._x3);
- this._x0 ^= this._workingKey[20]; this._x1 ^= this._workingKey[21]; this._x2 ^= this._workingKey[22]; this._x3 ^= this._workingKey[23];
- InverseLT(); Ib4(this._x0, this._x1, this._x2, this._x3);
- this._x0 ^= this._workingKey[16]; this._x1 ^= this._workingKey[17]; this._x2 ^= this._workingKey[18]; this._x3 ^= this._workingKey[19];
- InverseLT(); Ib3(this._x0, this._x1, this._x2, this._x3);
- this._x0 ^= this._workingKey[12]; this._x1 ^= this._workingKey[13]; this._x2 ^= this._workingKey[14]; this._x3 ^= this._workingKey[15];
- InverseLT(); Ib2(this._x0, this._x1, this._x2, this._x3);
- this._x0 ^= this._workingKey[8]; this._x1 ^= this._workingKey[9]; this._x2 ^= this._workingKey[10]; this._x3 ^= this._workingKey[11];
- InverseLT(); Ib1(this._x0, this._x1, this._x2, this._x3);
- this._x0 ^= this._workingKey[4]; this._x1 ^= this._workingKey[5]; this._x2 ^= this._workingKey[6]; this._x3 ^= this._workingKey[7];
- InverseLT(); Ib0(this._x0, this._x1, this._x2, this._x3);
-
- WordToBytes(this._x3 ^ this._workingKey[3], outputBuffer, outputOffset);
- WordToBytes(this._x2 ^ this._workingKey[2], outputBuffer, outputOffset + 4);
- WordToBytes(this._x1 ^ this._workingKey[1], outputBuffer, outputOffset + 8);
- WordToBytes(this._x0 ^ this._workingKey[0], outputBuffer, outputOffset + 12);
-
- return this.BlockSize;
- }
-
- /**
- * Expand a user-supplied key material into a session key.
- *
- * @param key The user-key bytes (multiples of 4) to use.
- * @exception ArgumentException
- */
- private int[] MakeWorkingKey(byte[] key)
- {
- //
- // pad key to 256 bits
- //
- int[] kPad = new int[16];
- int off = 0;
- int length = 0;
-
- for (off = key.Length - 4; off > 0; off -= 4)
- {
- kPad[length++] = BytesToWord(key, off);
- }
-
- if (off == 0)
- {
- kPad[length++] = BytesToWord(key, 0);
- if (length < 8)
- {
- kPad[length] = 1;
- }
- }
- else
- {
- throw new ArgumentException("key must be a multiple of 4 bytes");
- }
-
- //
- // expand the padded key up to 33 x 128 bits of key material
- //
- int amount = (ROUNDS + 1) * 4;
- int[] w = new int[amount];
-
- //
- // compute w0 to w7 from w-8 to w-1
- //
- for (int i = 8; i < 16; i++)
- {
- kPad[i] = RotateLeft(kPad[i - 8] ^ kPad[i - 5] ^ kPad[i - 3] ^ kPad[i - 1] ^ PHI ^ (i - 8), 11);
- }
-
- Buffer.BlockCopy(kPad, 8, w, 0, 8);
-
- //
- // compute w8 to w136
- //
- for (int i = 8; i < amount; i++)
- {
- w[i] = RotateLeft(w[i - 8] ^ w[i - 5] ^ w[i - 3] ^ w[i - 1] ^ PHI ^ i, 11);
- }
-
- //
- // create the working keys by processing w with the Sbox and IP
- //
- Sb3(w[0], w[1], w[2], w[3]);
- w[0] = this._x0; w[1] = this._x1; w[2] = this._x2; w[3] = this._x3;
- Sb2(w[4], w[5], w[6], w[7]);
- w[4] = this._x0; w[5] = this._x1; w[6] = this._x2; w[7] = this._x3;
- Sb1(w[8], w[9], w[10], w[11]);
- w[8] = this._x0; w[9] = this._x1; w[10] = this._x2; w[11] = this._x3;
- Sb0(w[12], w[13], w[14], w[15]);
- w[12] = this._x0; w[13] = this._x1; w[14] = this._x2; w[15] = this._x3;
- Sb7(w[16], w[17], w[18], w[19]);
- w[16] = this._x0; w[17] = this._x1; w[18] = this._x2; w[19] = this._x3;
- Sb6(w[20], w[21], w[22], w[23]);
- w[20] = this._x0; w[21] = this._x1; w[22] = this._x2; w[23] = this._x3;
- Sb5(w[24], w[25], w[26], w[27]);
- w[24] = this._x0; w[25] = this._x1; w[26] = this._x2; w[27] = this._x3;
- Sb4(w[28], w[29], w[30], w[31]);
- w[28] = this._x0; w[29] = this._x1; w[30] = this._x2; w[31] = this._x3;
- Sb3(w[32], w[33], w[34], w[35]);
- w[32] = this._x0; w[33] = this._x1; w[34] = this._x2; w[35] = this._x3;
- Sb2(w[36], w[37], w[38], w[39]);
- w[36] = this._x0; w[37] = this._x1; w[38] = this._x2; w[39] = this._x3;
- Sb1(w[40], w[41], w[42], w[43]);
- w[40] = this._x0; w[41] = this._x1; w[42] = this._x2; w[43] = this._x3;
- Sb0(w[44], w[45], w[46], w[47]);
- w[44] = this._x0; w[45] = this._x1; w[46] = this._x2; w[47] = this._x3;
- Sb7(w[48], w[49], w[50], w[51]);
- w[48] = this._x0; w[49] = this._x1; w[50] = this._x2; w[51] = this._x3;
- Sb6(w[52], w[53], w[54], w[55]);
- w[52] = this._x0; w[53] = this._x1; w[54] = this._x2; w[55] = this._x3;
- Sb5(w[56], w[57], w[58], w[59]);
- w[56] = this._x0; w[57] = this._x1; w[58] = this._x2; w[59] = this._x3;
- Sb4(w[60], w[61], w[62], w[63]);
- w[60] = this._x0; w[61] = this._x1; w[62] = this._x2; w[63] = this._x3;
- Sb3(w[64], w[65], w[66], w[67]);
- w[64] = this._x0; w[65] = this._x1; w[66] = this._x2; w[67] = this._x3;
- Sb2(w[68], w[69], w[70], w[71]);
- w[68] = this._x0; w[69] = this._x1; w[70] = this._x2; w[71] = this._x3;
- Sb1(w[72], w[73], w[74], w[75]);
- w[72] = this._x0; w[73] = this._x1; w[74] = this._x2; w[75] = this._x3;
- Sb0(w[76], w[77], w[78], w[79]);
- w[76] = this._x0; w[77] = this._x1; w[78] = this._x2; w[79] = this._x3;
- Sb7(w[80], w[81], w[82], w[83]);
- w[80] = this._x0; w[81] = this._x1; w[82] = this._x2; w[83] = this._x3;
- Sb6(w[84], w[85], w[86], w[87]);
- w[84] = this._x0; w[85] = this._x1; w[86] = this._x2; w[87] = this._x3;
- Sb5(w[88], w[89], w[90], w[91]);
- w[88] = this._x0; w[89] = this._x1; w[90] = this._x2; w[91] = this._x3;
- Sb4(w[92], w[93], w[94], w[95]);
- w[92] = this._x0; w[93] = this._x1; w[94] = this._x2; w[95] = this._x3;
- Sb3(w[96], w[97], w[98], w[99]);
- w[96] = this._x0; w[97] = this._x1; w[98] = this._x2; w[99] = this._x3;
- Sb2(w[100], w[101], w[102], w[103]);
- w[100] = this._x0; w[101] = this._x1; w[102] = this._x2; w[103] = this._x3;
- Sb1(w[104], w[105], w[106], w[107]);
- w[104] = this._x0; w[105] = this._x1; w[106] = this._x2; w[107] = this._x3;
- Sb0(w[108], w[109], w[110], w[111]);
- w[108] = this._x0; w[109] = this._x1; w[110] = this._x2; w[111] = this._x3;
- Sb7(w[112], w[113], w[114], w[115]);
- w[112] = this._x0; w[113] = this._x1; w[114] = this._x2; w[115] = this._x3;
- Sb6(w[116], w[117], w[118], w[119]);
- w[116] = this._x0; w[117] = this._x1; w[118] = this._x2; w[119] = this._x3;
- Sb5(w[120], w[121], w[122], w[123]);
- w[120] = this._x0; w[121] = this._x1; w[122] = this._x2; w[123] = this._x3;
- Sb4(w[124], w[125], w[126], w[127]);
- w[124] = this._x0; w[125] = this._x1; w[126] = this._x2; w[127] = this._x3;
- Sb3(w[128], w[129], w[130], w[131]);
- w[128] = this._x0; w[129] = this._x1; w[130] = this._x2; w[131] = this._x3;
-
- return w;
- }
-
- private static int RotateLeft(int x, int bits)
- {
- return ((x << bits) | (int)((uint)x >> (32 - bits)));
- }
-
- private static int RotateRight(int x, int bits)
- {
- return ((int)((uint)x >> bits) | (x << (32 - bits)));
- }
-
- private static int BytesToWord(byte[] src, int srcOff)
- {
- return (((src[srcOff] & 0xff) << 24) | ((src[srcOff + 1] & 0xff) << 16) |
- ((src[srcOff + 2] & 0xff) << 8) | ((src[srcOff + 3] & 0xff)));
- }
-
- private static void WordToBytes(int word, byte[] dst, int dstOff)
- {
- dst[dstOff + 3] = (byte)(word);
- dst[dstOff + 2] = (byte)((uint)word >> 8);
- dst[dstOff + 1] = (byte)((uint)word >> 16);
- dst[dstOff] = (byte)((uint)word >> 24);
- }
-
- /*
- * The sboxes below are based on the work of Brian Gladman and
- * Sam Simpson, whose original notice appears below.
- *
- * For further details see:
- * http://fp.gladman.plus.com/cryptography_technology/serpent/
- *
- */
-
- /* Partially optimised Serpent S Box bool functions derived */
- /* using a recursive descent analyser but without a full search */
- /* of all subtrees. This set of S boxes is the result of work */
- /* by Sam Simpson and Brian Gladman using the spare time on a */
- /* cluster of high capacity servers to search for S boxes with */
- /* this customised search engine. There are now an average of */
- /* 15.375 terms per S box. */
- /* */
- /* Copyright: Dr B. R Gladman (gladman@seven77.demon.co.uk) */
- /* and Sam Simpson (s.simpson@mia.co.uk) */
- /* 17th December 1998 */
- /* */
- /* We hereby give permission for information in this file to be */
- /* used freely subject only to acknowledgement of its origin. */
-
- ///
- /// S0 - { 3, 8,15, 1,10, 6, 5,11,14,13, 4, 2, 7, 0, 9,12 } - 15 terms.
- ///
- /// A.
- /// The b.
- /// The c.
- /// The d.
- private void Sb0(int a, int b, int c, int d)
- {
- int t1 = a ^ d;
- int t3 = c ^ t1;
- int t4 = b ^ t3;
- this._x3 = (a & d) ^ t4;
- int t7 = a ^ (b & t1);
- this._x2 = t4 ^ (c | t7);
- int t12 = this._x3 & (t3 ^ t7);
- this._x1 = (~t3) ^ t12;
- this._x0 = t12 ^ (~t7);
- }
-
- ///
- /// InvSO - {13, 3,11, 0,10, 6, 5,12, 1,14, 4, 7,15, 9, 8, 2 } - 15 terms.
- ///
- /// A.
- /// The b.
- /// The c.
- /// The d.
- private void Ib0(int a, int b, int c, int d)
- {
- int t1 = ~a;
- int t2 = a ^ b;
- int t4 = d ^ (t1 | t2);
- int t5 = c ^ t4;
- this._x2 = t2 ^ t5;
- int t8 = t1 ^ (d & t2);
- this._x1 = t4 ^ (this._x2 & t8);
- this._x3 = (a & t4) ^ (t5 | this._x1);
- this._x0 = this._x3 ^ (t5 ^ t8);
- }
-
- ///
- /// S1 - {15,12, 2, 7, 9, 0, 5,10, 1,11,14, 8, 6,13, 3, 4 } - 14 terms.
- ///
- /// A.
- /// The b.
- /// The c.
- /// The d.
- private void Sb1(int a, int b, int c, int d)
- {
- int t2 = b ^ (~a);
- int t5 = c ^ (a | t2);
- this._x2 = d ^ t5;
- int t7 = b ^ (d | t2);
- int t8 = t2 ^ this._x2;
- this._x3 = t8 ^ (t5 & t7);
- int t11 = t5 ^ t7;
- this._x1 = this._x3 ^ t11;
- this._x0 = t5 ^ (t8 & t11);
- }
-
- ///
- /// InvS1 - { 5, 8, 2,14,15, 6,12, 3,11, 4, 7, 9, 1,13,10, 0 } - 14 steps.
- ///
- /// A.
- /// The b.
- /// The c.
- /// The d.
- private void Ib1(int a, int b, int c, int d)
- {
- int t1 = b ^ d;
- int t3 = a ^ (b & t1);
- int t4 = t1 ^ t3;
- this._x3 = c ^ t4;
- int t7 = b ^ (t1 & t3);
- int t8 = this._x3 | t7;
- this._x1 = t3 ^ t8;
- int t10 = ~this._x1;
- int t11 = this._x3 ^ t7;
- this._x0 = t10 ^ t11;
- this._x2 = t4 ^ (t10 | t11);
- }
-
- ///
- /// S2 - { 8, 6, 7, 9, 3,12,10,15,13, 1,14, 4, 0,11, 5, 2 } - 16 terms.
- ///
- /// A.
- /// The b.
- /// The c.
- /// The d.
- private void Sb2(int a, int b, int c, int d)
- {
- int t1 = ~a;
- int t2 = b ^ d;
- int t3 = c & t1;
- this._x0 = t2 ^ t3;
- int t5 = c ^ t1;
- int t6 = c ^ this._x0;
- int t7 = b & t6;
- this._x3 = t5 ^ t7;
- this._x2 = a ^ ((d | t7) & (this._x0 | t5));
- this._x1 = (t2 ^ this._x3) ^ (this._x2 ^ (d | t1));
- }
-
- ///
- /// InvS2 - {12, 9,15, 4,11,14, 1, 2, 0, 3, 6,13, 5, 8,10, 7 } - 16 steps.
- ///
- /// A.
- /// The b.
- /// The c.
- /// The d.
- private void Ib2(int a, int b, int c, int d)
- {
- int t1 = b ^ d;
- int t2 = ~t1;
- int t3 = a ^ c;
- int t4 = c ^ t1;
- int t5 = b & t4;
- this._x0 = t3 ^ t5;
- int t7 = a | t2;
- int t8 = d ^ t7;
- int t9 = t3 | t8;
- this._x3 = t1 ^ t9;
- int t11 = ~t4;
- int t12 = this._x0 | this._x3;
- this._x1 = t11 ^ t12;
- this._x2 = (d & t11) ^ (t3 ^ t12);
- }
-
- ///
- /// S3 - { 0,15,11, 8,12, 9, 6, 3,13, 1, 2, 4,10, 7, 5,14 } - 16 terms.
- ///
- /// A.
- /// The b.
- /// The c.
- /// The d.
- private void Sb3(int a, int b, int c, int d)
- {
- int t1 = a ^ b;
- int t2 = a & c;
- int t3 = a | d;
- int t4 = c ^ d;
- int t5 = t1 & t3;
- int t6 = t2 | t5;
- this._x2 = t4 ^ t6;
- int t8 = b ^ t3;
- int t9 = t6 ^ t8;
- int t10 = t4 & t9;
- this._x0 = t1 ^ t10;
- int t12 = this._x2 & this._x0;
- this._x1 = t9 ^ t12;
- this._x3 = (b | d) ^ (t4 ^ t12);
- }
-
- ///
- /// InvS3 - { 0, 9,10, 7,11,14, 6,13, 3, 5,12, 2, 4, 8,15, 1 } - 15 terms
- ///
- /// A.
- /// The b.
- /// The c.
- /// The d.
- private void Ib3(int a, int b, int c, int d)
- {
- int t1 = a | b;
- int t2 = b ^ c;
- int t3 = b & t2;
- int t4 = a ^ t3;
- int t5 = c ^ t4;
- int t6 = d | t4;
- this._x0 = t2 ^ t6;
- int t8 = t2 | t6;
- int t9 = d ^ t8;
- this._x2 = t5 ^ t9;
- int t11 = t1 ^ t9;
- int t12 = this._x0 & t11;
- this._x3 = t4 ^ t12;
- this._x1 = this._x3 ^ (this._x0 ^ t11);
- }
-
- ///
- /// S4 - { 1,15, 8, 3,12, 0,11, 6, 2, 5, 4,10, 9,14, 7,13 } - 15 terms.
- ///
- /// A.
- /// The b.
- /// The c.
- /// The d.
- private void Sb4(int a, int b, int c, int d)
- {
- int t1 = a ^ d;
- int t2 = d & t1;
- int t3 = c ^ t2;
- int t4 = b | t3;
- this._x3 = t1 ^ t4;
- int t6 = ~b;
- int t7 = t1 | t6;
- this._x0 = t3 ^ t7;
- int t9 = a & this._x0;
- int t10 = t1 ^ t6;
- int t11 = t4 & t10;
- this._x2 = t9 ^ t11;
- this._x1 = (a ^ t3) ^ (t10 & this._x2);
- }
-
- ///
- /// InvS4 - { 5, 0, 8, 3,10, 9, 7,14, 2,12,11, 6, 4,15,13, 1 } - 15 terms.
- ///
- /// A.
- /// The b.
- /// The c.
- /// The d.
- private void Ib4(int a, int b, int c, int d)
- {
- int t1 = c | d;
- int t2 = a & t1;
- int t3 = b ^ t2;
- int t4 = a & t3;
- int t5 = c ^ t4;
- this._x1 = d ^ t5;
- int t7 = ~a;
- int t8 = t5 & this._x1;
- this._x3 = t3 ^ t8;
- int t10 = this._x1 | t7;
- int t11 = d ^ t10;
- this._x0 = this._x3 ^ t11;
- this._x2 = (t3 & t11) ^ (this._x1 ^ t7);
- }
-
- ///
- /// S5 - {15, 5, 2,11, 4,10, 9,12, 0, 3,14, 8,13, 6, 7, 1 } - 16 terms.
- ///
- /// A.
- /// The b.
- /// The c.
- /// The d.
- private void Sb5(int a, int b, int c, int d)
- {
- int t1 = ~a;
- int t2 = a ^ b;
- int t3 = a ^ d;
- int t4 = c ^ t1;
- int t5 = t2 | t3;
- this._x0 = t4 ^ t5;
- int t7 = d & this._x0;
- int t8 = t2 ^ this._x0;
- this._x1 = t7 ^ t8;
- int t10 = t1 | this._x0;
- int t11 = t2 | t7;
- int t12 = t3 ^ t10;
- this._x2 = t11 ^ t12;
- this._x3 = (b ^ t7) ^ (this._x1 & t12);
- }
-
- ///
- /// InvS5 - { 8,15, 2, 9, 4, 1,13,14,11, 6, 5, 3, 7,12,10, 0 } - 16 terms.
- ///
- /// A.
- /// The b.
- /// The c.
- /// The d.
- private void Ib5(int a, int b, int c, int d)
- {
- int t1 = ~c;
- int t2 = b & t1;
- int t3 = d ^ t2;
- int t4 = a & t3;
- int t5 = b ^ t1;
- this._x3 = t4 ^ t5;
- int t7 = b | this._x3;
- int t8 = a & t7;
- this._x1 = t3 ^ t8;
- int t10 = a | d;
- int t11 = t1 ^ t7;
- this._x0 = t10 ^ t11;
- this._x2 = (b & t10) ^ (t4 | (a ^ c));
- }
-
- ///
- /// S6 - { 7, 2,12, 5, 8, 4, 6,11,14, 9, 1,15,13, 3,10, 0 } - 15 terms.
- ///
- /// A.
- /// The b.
- /// The c.
- /// The d.
- private void Sb6(int a, int b, int c, int d)
- {
- int t1 = ~a;
- int t2 = a ^ d;
- int t3 = b ^ t2;
- int t4 = t1 | t2;
- int t5 = c ^ t4;
- this._x1 = b ^ t5;
- int t7 = t2 | this._x1;
- int t8 = d ^ t7;
- int t9 = t5 & t8;
- this._x2 = t3 ^ t9;
- int t11 = t5 ^ t8;
- this._x0 = this._x2 ^ t11;
- this._x3 = (~t5) ^ (t3 & t11);
- }
-
- ///
- /// InvS6 - {15,10, 1,13, 5, 3, 6, 0, 4, 9,14, 7, 2,12, 8,11 } - 15 terms.
- ///
- /// A.
- /// The b.
- /// The c.
- /// The d.
- private void Ib6(int a, int b, int c, int d)
- {
- int t1 = ~a;
- int t2 = a ^ b;
- int t3 = c ^ t2;
- int t4 = c | t1;
- int t5 = d ^ t4;
- this._x1 = t3 ^ t5;
- int t7 = t3 & t5;
- int t8 = t2 ^ t7;
- int t9 = b | t8;
- this._x3 = t5 ^ t9;
- int t11 = b | this._x3;
- this._x0 = t8 ^ t11;
- this._x2 = (d & t1) ^ (t3 ^ t11);
- }
-
- ///
- /// S7 - { 1,13,15, 0,14, 8, 2,11, 7, 4,12,10, 9, 3, 5, 6 } - 16 terms.
- ///
- /// A.
- /// The b.
- /// The c.
- /// The d.
- private void Sb7(int a, int b, int c, int d)
- {
- int t1 = b ^ c;
- int t2 = c & t1;
- int t3 = d ^ t2;
- int t4 = a ^ t3;
- int t5 = d | t1;
- int t6 = t4 & t5;
- this._x1 = b ^ t6;
- int t8 = t3 | this._x1;
- int t9 = a & t4;
- this._x3 = t1 ^ t9;
- int t11 = t4 ^ t8;
- int t12 = this._x3 & t11;
- this._x2 = t3 ^ t12;
- this._x0 = (~t11) ^ (this._x3 & this._x2);
- }
-
- ///
- /// InvS7 - { 3, 0, 6,13, 9,14,15, 8, 5,12,11, 7,10, 1, 4, 2 } - 17 terms.
- ///
- /// A.
- /// The b.
- /// The c.
- /// The d.
- private void Ib7(int a, int b, int c, int d)
- {
- int t3 = c | (a & b);
- int t4 = d & (a | b);
- this._x3 = t3 ^ t4;
- int t6 = ~d;
- int t7 = b ^ t4;
- int t9 = t7 | (this._x3 ^ t6);
- this._x1 = a ^ t9;
- this._x0 = (c ^ t7) ^ (d | this._x1);
- this._x2 = (t3 ^ this._x1) ^ (this._x0 ^ (a & this._x3));
- }
-
- ///
- /// Apply the linear transformation to the register set.
- ///
- private void LT()
- {
- int x0 = RotateLeft(this._x0, 13);
- int x2 = RotateLeft(this._x2, 3);
- int x1 = this._x1 ^ x0 ^ x2;
- int x3 = this._x3 ^ x2 ^ x0 << 3;
-
- this._x1 = RotateLeft(x1, 1);
- this._x3 = RotateLeft(x3, 7);
- this._x0 = RotateLeft(x0 ^ this._x1 ^ this._x3, 5);
- this._x2 = RotateLeft(x2 ^ this._x3 ^ (this._x1 << 7), 22);
- }
-
- ///
- /// Apply the inverse of the linear transformation to the register set.
- ///
- private void InverseLT()
- {
- int x2 = RotateRight(this._x2, 22) ^ this._x3 ^ (this._x1 << 7);
- int x0 = RotateRight(this._x0, 5) ^ this._x1 ^ this._x3;
- int x3 = RotateRight(this._x3, 7);
- int x1 = RotateRight(this._x1, 1);
- this._x3 = x3 ^ x2 ^ x0 << 3;
- this._x1 = x1 ^ x0 ^ x2;
- this._x2 = RotateRight(x2, 3);
- this._x0 = RotateRight(x0, 13);
- }
- }
-}
+using System;
+
+namespace Renci.SshNet.Security.Cryptography.Ciphers
+{
+ ///
+ /// Implements Serpent cipher algorithm.
+ ///
+ public sealed class SerpentCipher : BlockCipher
+ {
+ private const int ROUNDS = 32;
+
+ private const int PHI = unchecked((int) 0x9E3779B9); // (Sqrt(5) - 1) * 2**31
+
+ private readonly int[] _workingKey;
+
+ private int _x0, _x1, _x2, _x3; // registers
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The key.
+ /// The mode.
+ /// The padding.
+ /// is null.
+ /// Keysize is not valid for this algorithm.
+ public SerpentCipher(byte[] key, CipherMode mode, CipherPadding padding)
+ : base(key, 16, mode, padding)
+ {
+ var keySize = key.Length * 8;
+
+ if (!(keySize == 128 || keySize == 192 || keySize == 256))
+ throw new ArgumentException(string.Format("KeySize '{0}' is not valid for this algorithm.", keySize));
+
+ this._workingKey = this.MakeWorkingKey(key);
+ }
+
+ ///
+ /// Encrypts the specified region of the input byte array and copies the encrypted data to the specified region of the output byte array.
+ ///
+ /// The input data to encrypt.
+ /// The offset into the input byte array from which to begin using data.
+ /// The number of bytes in the input byte array to use as data.
+ /// The output to which to write encrypted data.
+ /// The offset into the output byte array from which to begin writing data.
+ ///
+ /// The number of bytes encrypted.
+ ///
+ public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
+ {
+ if (inputCount != this.BlockSize)
+ throw new ArgumentException("inputCount");
+
+ this._x3 = BytesToWord(inputBuffer, inputOffset);
+ this._x2 = BytesToWord(inputBuffer, inputOffset + 4);
+ this._x1 = BytesToWord(inputBuffer, inputOffset + 8);
+ this._x0 = BytesToWord(inputBuffer, inputOffset + 12);
+
+ Sb0(this._workingKey[0] ^ this._x0, this._workingKey[1] ^ this._x1, this._workingKey[2] ^ this._x2, this._workingKey[3] ^ this._x3); LT();
+ Sb1(this._workingKey[4] ^ this._x0, this._workingKey[5] ^ this._x1, this._workingKey[6] ^ this._x2, this._workingKey[7] ^ this._x3); LT();
+ Sb2(this._workingKey[8] ^ this._x0, this._workingKey[9] ^ this._x1, this._workingKey[10] ^ this._x2, this._workingKey[11] ^ this._x3); LT();
+ Sb3(this._workingKey[12] ^ this._x0, this._workingKey[13] ^ this._x1, this._workingKey[14] ^ this._x2, this._workingKey[15] ^ this._x3); LT();
+ Sb4(this._workingKey[16] ^ this._x0, this._workingKey[17] ^ this._x1, this._workingKey[18] ^ this._x2, this._workingKey[19] ^ this._x3); LT();
+ Sb5(this._workingKey[20] ^ this._x0, this._workingKey[21] ^ this._x1, this._workingKey[22] ^ this._x2, this._workingKey[23] ^ this._x3); LT();
+ Sb6(this._workingKey[24] ^ this._x0, this._workingKey[25] ^ this._x1, this._workingKey[26] ^ this._x2, this._workingKey[27] ^ this._x3); LT();
+ Sb7(this._workingKey[28] ^ this._x0, this._workingKey[29] ^ this._x1, this._workingKey[30] ^ this._x2, this._workingKey[31] ^ this._x3); LT();
+ Sb0(this._workingKey[32] ^ this._x0, this._workingKey[33] ^ this._x1, this._workingKey[34] ^ this._x2, this._workingKey[35] ^ this._x3); LT();
+ Sb1(this._workingKey[36] ^ this._x0, this._workingKey[37] ^ this._x1, this._workingKey[38] ^ this._x2, this._workingKey[39] ^ this._x3); LT();
+ Sb2(this._workingKey[40] ^ this._x0, this._workingKey[41] ^ this._x1, this._workingKey[42] ^ this._x2, this._workingKey[43] ^ this._x3); LT();
+ Sb3(this._workingKey[44] ^ this._x0, this._workingKey[45] ^ this._x1, this._workingKey[46] ^ this._x2, this._workingKey[47] ^ this._x3); LT();
+ Sb4(this._workingKey[48] ^ this._x0, this._workingKey[49] ^ this._x1, this._workingKey[50] ^ this._x2, this._workingKey[51] ^ this._x3); LT();
+ Sb5(this._workingKey[52] ^ this._x0, this._workingKey[53] ^ this._x1, this._workingKey[54] ^ this._x2, this._workingKey[55] ^ this._x3); LT();
+ Sb6(this._workingKey[56] ^ this._x0, this._workingKey[57] ^ this._x1, this._workingKey[58] ^ this._x2, this._workingKey[59] ^ this._x3); LT();
+ Sb7(this._workingKey[60] ^ this._x0, this._workingKey[61] ^ this._x1, this._workingKey[62] ^ this._x2, this._workingKey[63] ^ this._x3); LT();
+ Sb0(this._workingKey[64] ^ this._x0, this._workingKey[65] ^ this._x1, this._workingKey[66] ^ this._x2, this._workingKey[67] ^ this._x3); LT();
+ Sb1(this._workingKey[68] ^ this._x0, this._workingKey[69] ^ this._x1, this._workingKey[70] ^ this._x2, this._workingKey[71] ^ this._x3); LT();
+ Sb2(this._workingKey[72] ^ this._x0, this._workingKey[73] ^ this._x1, this._workingKey[74] ^ this._x2, this._workingKey[75] ^ this._x3); LT();
+ Sb3(this._workingKey[76] ^ this._x0, this._workingKey[77] ^ this._x1, this._workingKey[78] ^ this._x2, this._workingKey[79] ^ this._x3); LT();
+ Sb4(this._workingKey[80] ^ this._x0, this._workingKey[81] ^ this._x1, this._workingKey[82] ^ this._x2, this._workingKey[83] ^ this._x3); LT();
+ Sb5(this._workingKey[84] ^ this._x0, this._workingKey[85] ^ this._x1, this._workingKey[86] ^ this._x2, this._workingKey[87] ^ this._x3); LT();
+ Sb6(this._workingKey[88] ^ this._x0, this._workingKey[89] ^ this._x1, this._workingKey[90] ^ this._x2, this._workingKey[91] ^ this._x3); LT();
+ Sb7(this._workingKey[92] ^ this._x0, this._workingKey[93] ^ this._x1, this._workingKey[94] ^ this._x2, this._workingKey[95] ^ this._x3); LT();
+ Sb0(this._workingKey[96] ^ this._x0, this._workingKey[97] ^ this._x1, this._workingKey[98] ^ this._x2, this._workingKey[99] ^ this._x3); LT();
+ Sb1(this._workingKey[100] ^ this._x0, this._workingKey[101] ^ this._x1, this._workingKey[102] ^ this._x2, this._workingKey[103] ^ this._x3); LT();
+ Sb2(this._workingKey[104] ^ this._x0, this._workingKey[105] ^ this._x1, this._workingKey[106] ^ this._x2, this._workingKey[107] ^ this._x3); LT();
+ Sb3(this._workingKey[108] ^ this._x0, this._workingKey[109] ^ this._x1, this._workingKey[110] ^ this._x2, this._workingKey[111] ^ this._x3); LT();
+ Sb4(this._workingKey[112] ^ this._x0, this._workingKey[113] ^ this._x1, this._workingKey[114] ^ this._x2, this._workingKey[115] ^ this._x3); LT();
+ Sb5(this._workingKey[116] ^ this._x0, this._workingKey[117] ^ this._x1, this._workingKey[118] ^ this._x2, this._workingKey[119] ^ this._x3); LT();
+ Sb6(this._workingKey[120] ^ this._x0, this._workingKey[121] ^ this._x1, this._workingKey[122] ^ this._x2, this._workingKey[123] ^ this._x3); LT();
+ Sb7(this._workingKey[124] ^ this._x0, this._workingKey[125] ^ this._x1, this._workingKey[126] ^ this._x2, this._workingKey[127] ^ this._x3);
+
+ WordToBytes(this._workingKey[131] ^ this._x3, outputBuffer, outputOffset);
+ WordToBytes(this._workingKey[130] ^ this._x2, outputBuffer, outputOffset + 4);
+ WordToBytes(this._workingKey[129] ^ this._x1, outputBuffer, outputOffset + 8);
+ WordToBytes(this._workingKey[128] ^ this._x0, outputBuffer, outputOffset + 12);
+
+ return this.BlockSize;
+ }
+
+ ///
+ /// Decrypts the specified region of the input byte array and copies the decrypted data to the specified region of the output byte array.
+ ///
+ /// The input data to decrypt.
+ /// The offset into the input byte array from which to begin using data.
+ /// The number of bytes in the input byte array to use as data.
+ /// The output to which to write decrypted data.
+ /// The offset into the output byte array from which to begin writing data.
+ ///
+ /// The number of bytes decrypted.
+ ///
+ public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
+ {
+ if (inputCount != this.BlockSize)
+ throw new ArgumentException("inputCount");
+
+ this._x3 = this._workingKey[131] ^ BytesToWord(inputBuffer, inputOffset);
+ this._x2 = this._workingKey[130] ^ BytesToWord(inputBuffer, inputOffset + 4);
+ this._x1 = this._workingKey[129] ^ BytesToWord(inputBuffer, inputOffset + 8);
+ this._x0 = this._workingKey[128] ^ BytesToWord(inputBuffer, inputOffset + 12);
+
+ Ib7(this._x0, this._x1, this._x2, this._x3);
+ this._x0 ^= this._workingKey[124]; this._x1 ^= this._workingKey[125]; this._x2 ^= this._workingKey[126]; this._x3 ^= this._workingKey[127];
+ InverseLT(); Ib6(this._x0, this._x1, this._x2, this._x3);
+ this._x0 ^= this._workingKey[120]; this._x1 ^= this._workingKey[121]; this._x2 ^= this._workingKey[122]; this._x3 ^= this._workingKey[123];
+ InverseLT(); Ib5(this._x0, this._x1, this._x2, this._x3);
+ this._x0 ^= this._workingKey[116]; this._x1 ^= this._workingKey[117]; this._x2 ^= this._workingKey[118]; this._x3 ^= this._workingKey[119];
+ InverseLT(); Ib4(this._x0, this._x1, this._x2, this._x3);
+ this._x0 ^= this._workingKey[112]; this._x1 ^= this._workingKey[113]; this._x2 ^= this._workingKey[114]; this._x3 ^= this._workingKey[115];
+ InverseLT(); Ib3(this._x0, this._x1, this._x2, this._x3);
+ this._x0 ^= this._workingKey[108]; this._x1 ^= this._workingKey[109]; this._x2 ^= this._workingKey[110]; this._x3 ^= this._workingKey[111];
+ InverseLT(); Ib2(this._x0, this._x1, this._x2, this._x3);
+ this._x0 ^= this._workingKey[104]; this._x1 ^= this._workingKey[105]; this._x2 ^= this._workingKey[106]; this._x3 ^= this._workingKey[107];
+ InverseLT(); Ib1(this._x0, this._x1, this._x2, this._x3);
+ this._x0 ^= this._workingKey[100]; this._x1 ^= this._workingKey[101]; this._x2 ^= this._workingKey[102]; this._x3 ^= this._workingKey[103];
+ InverseLT(); Ib0(this._x0, this._x1, this._x2, this._x3);
+ this._x0 ^= this._workingKey[96]; this._x1 ^= this._workingKey[97]; this._x2 ^= this._workingKey[98]; this._x3 ^= this._workingKey[99];
+ InverseLT(); Ib7(this._x0, this._x1, this._x2, this._x3);
+ this._x0 ^= this._workingKey[92]; this._x1 ^= this._workingKey[93]; this._x2 ^= this._workingKey[94]; this._x3 ^= this._workingKey[95];
+ InverseLT(); Ib6(this._x0, this._x1, this._x2, this._x3);
+ this._x0 ^= this._workingKey[88]; this._x1 ^= this._workingKey[89]; this._x2 ^= this._workingKey[90]; this._x3 ^= this._workingKey[91];
+ InverseLT(); Ib5(this._x0, this._x1, this._x2, this._x3);
+ this._x0 ^= this._workingKey[84]; this._x1 ^= this._workingKey[85]; this._x2 ^= this._workingKey[86]; this._x3 ^= this._workingKey[87];
+ InverseLT(); Ib4(this._x0, this._x1, this._x2, this._x3);
+ this._x0 ^= this._workingKey[80]; this._x1 ^= this._workingKey[81]; this._x2 ^= this._workingKey[82]; this._x3 ^= this._workingKey[83];
+ InverseLT(); Ib3(this._x0, this._x1, this._x2, this._x3);
+ this._x0 ^= this._workingKey[76]; this._x1 ^= this._workingKey[77]; this._x2 ^= this._workingKey[78]; this._x3 ^= this._workingKey[79];
+ InverseLT(); Ib2(this._x0, this._x1, this._x2, this._x3);
+ this._x0 ^= this._workingKey[72]; this._x1 ^= this._workingKey[73]; this._x2 ^= this._workingKey[74]; this._x3 ^= this._workingKey[75];
+ InverseLT(); Ib1(this._x0, this._x1, this._x2, this._x3);
+ this._x0 ^= this._workingKey[68]; this._x1 ^= this._workingKey[69]; this._x2 ^= this._workingKey[70]; this._x3 ^= this._workingKey[71];
+ InverseLT(); Ib0(this._x0, this._x1, this._x2, this._x3);
+ this._x0 ^= this._workingKey[64]; this._x1 ^= this._workingKey[65]; this._x2 ^= this._workingKey[66]; this._x3 ^= this._workingKey[67];
+ InverseLT(); Ib7(this._x0, this._x1, this._x2, this._x3);
+ this._x0 ^= this._workingKey[60]; this._x1 ^= this._workingKey[61]; this._x2 ^= this._workingKey[62]; this._x3 ^= this._workingKey[63];
+ InverseLT(); Ib6(this._x0, this._x1, this._x2, this._x3);
+ this._x0 ^= this._workingKey[56]; this._x1 ^= this._workingKey[57]; this._x2 ^= this._workingKey[58]; this._x3 ^= this._workingKey[59];
+ InverseLT(); Ib5(this._x0, this._x1, this._x2, this._x3);
+ this._x0 ^= this._workingKey[52]; this._x1 ^= this._workingKey[53]; this._x2 ^= this._workingKey[54]; this._x3 ^= this._workingKey[55];
+ InverseLT(); Ib4(this._x0, this._x1, this._x2, this._x3);
+ this._x0 ^= this._workingKey[48]; this._x1 ^= this._workingKey[49]; this._x2 ^= this._workingKey[50]; this._x3 ^= this._workingKey[51];
+ InverseLT(); Ib3(this._x0, this._x1, this._x2, this._x3);
+ this._x0 ^= this._workingKey[44]; this._x1 ^= this._workingKey[45]; this._x2 ^= this._workingKey[46]; this._x3 ^= this._workingKey[47];
+ InverseLT(); Ib2(this._x0, this._x1, this._x2, this._x3);
+ this._x0 ^= this._workingKey[40]; this._x1 ^= this._workingKey[41]; this._x2 ^= this._workingKey[42]; this._x3 ^= this._workingKey[43];
+ InverseLT(); Ib1(this._x0, this._x1, this._x2, this._x3);
+ this._x0 ^= this._workingKey[36]; this._x1 ^= this._workingKey[37]; this._x2 ^= this._workingKey[38]; this._x3 ^= this._workingKey[39];
+ InverseLT(); Ib0(this._x0, this._x1, this._x2, this._x3);
+ this._x0 ^= this._workingKey[32]; this._x1 ^= this._workingKey[33]; this._x2 ^= this._workingKey[34]; this._x3 ^= this._workingKey[35];
+ InverseLT(); Ib7(this._x0, this._x1, this._x2, this._x3);
+ this._x0 ^= this._workingKey[28]; this._x1 ^= this._workingKey[29]; this._x2 ^= this._workingKey[30]; this._x3 ^= this._workingKey[31];
+ InverseLT(); Ib6(this._x0, this._x1, this._x2, this._x3);
+ this._x0 ^= this._workingKey[24]; this._x1 ^= this._workingKey[25]; this._x2 ^= this._workingKey[26]; this._x3 ^= this._workingKey[27];
+ InverseLT(); Ib5(this._x0, this._x1, this._x2, this._x3);
+ this._x0 ^= this._workingKey[20]; this._x1 ^= this._workingKey[21]; this._x2 ^= this._workingKey[22]; this._x3 ^= this._workingKey[23];
+ InverseLT(); Ib4(this._x0, this._x1, this._x2, this._x3);
+ this._x0 ^= this._workingKey[16]; this._x1 ^= this._workingKey[17]; this._x2 ^= this._workingKey[18]; this._x3 ^= this._workingKey[19];
+ InverseLT(); Ib3(this._x0, this._x1, this._x2, this._x3);
+ this._x0 ^= this._workingKey[12]; this._x1 ^= this._workingKey[13]; this._x2 ^= this._workingKey[14]; this._x3 ^= this._workingKey[15];
+ InverseLT(); Ib2(this._x0, this._x1, this._x2, this._x3);
+ this._x0 ^= this._workingKey[8]; this._x1 ^= this._workingKey[9]; this._x2 ^= this._workingKey[10]; this._x3 ^= this._workingKey[11];
+ InverseLT(); Ib1(this._x0, this._x1, this._x2, this._x3);
+ this._x0 ^= this._workingKey[4]; this._x1 ^= this._workingKey[5]; this._x2 ^= this._workingKey[6]; this._x3 ^= this._workingKey[7];
+ InverseLT(); Ib0(this._x0, this._x1, this._x2, this._x3);
+
+ WordToBytes(this._x3 ^ this._workingKey[3], outputBuffer, outputOffset);
+ WordToBytes(this._x2 ^ this._workingKey[2], outputBuffer, outputOffset + 4);
+ WordToBytes(this._x1 ^ this._workingKey[1], outputBuffer, outputOffset + 8);
+ WordToBytes(this._x0 ^ this._workingKey[0], outputBuffer, outputOffset + 12);
+
+ return this.BlockSize;
+ }
+
+ /**
+ * Expand a user-supplied key material into a session key.
+ *
+ * @param key The user-key bytes (multiples of 4) to use.
+ * @exception ArgumentException
+ */
+ private int[] MakeWorkingKey(byte[] key)
+ {
+ //
+ // pad key to 256 bits
+ //
+ int[] kPad = new int[16];
+ int off;
+ int length = 0;
+
+ for (off = key.Length - 4; off > 0; off -= 4)
+ {
+ kPad[length++] = BytesToWord(key, off);
+ }
+
+ if (off == 0)
+ {
+ kPad[length++] = BytesToWord(key, 0);
+ if (length < 8)
+ {
+ kPad[length] = 1;
+ }
+ }
+ else
+ {
+ throw new ArgumentException("key must be a multiple of 4 bytes");
+ }
+
+ //
+ // expand the padded key up to 33 x 128 bits of key material
+ //
+ int amount = (ROUNDS + 1) * 4;
+ int[] w = new int[amount];
+
+ //
+ // compute w0 to w7 from w-8 to w-1
+ //
+ for (int i = 8; i < 16; i++)
+ {
+ kPad[i] = RotateLeft(kPad[i - 8] ^ kPad[i - 5] ^ kPad[i - 3] ^ kPad[i - 1] ^ PHI ^ (i - 8), 11);
+ }
+
+ Buffer.BlockCopy(kPad, 8, w, 0, 8);
+
+ //
+ // compute w8 to w136
+ //
+ for (int i = 8; i < amount; i++)
+ {
+ w[i] = RotateLeft(w[i - 8] ^ w[i - 5] ^ w[i - 3] ^ w[i - 1] ^ PHI ^ i, 11);
+ }
+
+ //
+ // create the working keys by processing w with the Sbox and IP
+ //
+ Sb3(w[0], w[1], w[2], w[3]);
+ w[0] = this._x0; w[1] = this._x1; w[2] = this._x2; w[3] = this._x3;
+ Sb2(w[4], w[5], w[6], w[7]);
+ w[4] = this._x0; w[5] = this._x1; w[6] = this._x2; w[7] = this._x3;
+ Sb1(w[8], w[9], w[10], w[11]);
+ w[8] = this._x0; w[9] = this._x1; w[10] = this._x2; w[11] = this._x3;
+ Sb0(w[12], w[13], w[14], w[15]);
+ w[12] = this._x0; w[13] = this._x1; w[14] = this._x2; w[15] = this._x3;
+ Sb7(w[16], w[17], w[18], w[19]);
+ w[16] = this._x0; w[17] = this._x1; w[18] = this._x2; w[19] = this._x3;
+ Sb6(w[20], w[21], w[22], w[23]);
+ w[20] = this._x0; w[21] = this._x1; w[22] = this._x2; w[23] = this._x3;
+ Sb5(w[24], w[25], w[26], w[27]);
+ w[24] = this._x0; w[25] = this._x1; w[26] = this._x2; w[27] = this._x3;
+ Sb4(w[28], w[29], w[30], w[31]);
+ w[28] = this._x0; w[29] = this._x1; w[30] = this._x2; w[31] = this._x3;
+ Sb3(w[32], w[33], w[34], w[35]);
+ w[32] = this._x0; w[33] = this._x1; w[34] = this._x2; w[35] = this._x3;
+ Sb2(w[36], w[37], w[38], w[39]);
+ w[36] = this._x0; w[37] = this._x1; w[38] = this._x2; w[39] = this._x3;
+ Sb1(w[40], w[41], w[42], w[43]);
+ w[40] = this._x0; w[41] = this._x1; w[42] = this._x2; w[43] = this._x3;
+ Sb0(w[44], w[45], w[46], w[47]);
+ w[44] = this._x0; w[45] = this._x1; w[46] = this._x2; w[47] = this._x3;
+ Sb7(w[48], w[49], w[50], w[51]);
+ w[48] = this._x0; w[49] = this._x1; w[50] = this._x2; w[51] = this._x3;
+ Sb6(w[52], w[53], w[54], w[55]);
+ w[52] = this._x0; w[53] = this._x1; w[54] = this._x2; w[55] = this._x3;
+ Sb5(w[56], w[57], w[58], w[59]);
+ w[56] = this._x0; w[57] = this._x1; w[58] = this._x2; w[59] = this._x3;
+ Sb4(w[60], w[61], w[62], w[63]);
+ w[60] = this._x0; w[61] = this._x1; w[62] = this._x2; w[63] = this._x3;
+ Sb3(w[64], w[65], w[66], w[67]);
+ w[64] = this._x0; w[65] = this._x1; w[66] = this._x2; w[67] = this._x3;
+ Sb2(w[68], w[69], w[70], w[71]);
+ w[68] = this._x0; w[69] = this._x1; w[70] = this._x2; w[71] = this._x3;
+ Sb1(w[72], w[73], w[74], w[75]);
+ w[72] = this._x0; w[73] = this._x1; w[74] = this._x2; w[75] = this._x3;
+ Sb0(w[76], w[77], w[78], w[79]);
+ w[76] = this._x0; w[77] = this._x1; w[78] = this._x2; w[79] = this._x3;
+ Sb7(w[80], w[81], w[82], w[83]);
+ w[80] = this._x0; w[81] = this._x1; w[82] = this._x2; w[83] = this._x3;
+ Sb6(w[84], w[85], w[86], w[87]);
+ w[84] = this._x0; w[85] = this._x1; w[86] = this._x2; w[87] = this._x3;
+ Sb5(w[88], w[89], w[90], w[91]);
+ w[88] = this._x0; w[89] = this._x1; w[90] = this._x2; w[91] = this._x3;
+ Sb4(w[92], w[93], w[94], w[95]);
+ w[92] = this._x0; w[93] = this._x1; w[94] = this._x2; w[95] = this._x3;
+ Sb3(w[96], w[97], w[98], w[99]);
+ w[96] = this._x0; w[97] = this._x1; w[98] = this._x2; w[99] = this._x3;
+ Sb2(w[100], w[101], w[102], w[103]);
+ w[100] = this._x0; w[101] = this._x1; w[102] = this._x2; w[103] = this._x3;
+ Sb1(w[104], w[105], w[106], w[107]);
+ w[104] = this._x0; w[105] = this._x1; w[106] = this._x2; w[107] = this._x3;
+ Sb0(w[108], w[109], w[110], w[111]);
+ w[108] = this._x0; w[109] = this._x1; w[110] = this._x2; w[111] = this._x3;
+ Sb7(w[112], w[113], w[114], w[115]);
+ w[112] = this._x0; w[113] = this._x1; w[114] = this._x2; w[115] = this._x3;
+ Sb6(w[116], w[117], w[118], w[119]);
+ w[116] = this._x0; w[117] = this._x1; w[118] = this._x2; w[119] = this._x3;
+ Sb5(w[120], w[121], w[122], w[123]);
+ w[120] = this._x0; w[121] = this._x1; w[122] = this._x2; w[123] = this._x3;
+ Sb4(w[124], w[125], w[126], w[127]);
+ w[124] = this._x0; w[125] = this._x1; w[126] = this._x2; w[127] = this._x3;
+ Sb3(w[128], w[129], w[130], w[131]);
+ w[128] = this._x0; w[129] = this._x1; w[130] = this._x2; w[131] = this._x3;
+
+ return w;
+ }
+
+ private static int RotateLeft(int x, int bits)
+ {
+ return ((x << bits) | (int)((uint)x >> (32 - bits)));
+ }
+
+ private static int RotateRight(int x, int bits)
+ {
+ return ((int)((uint)x >> bits) | (x << (32 - bits)));
+ }
+
+ private static int BytesToWord(byte[] src, int srcOff)
+ {
+ return (((src[srcOff] & 0xff) << 24) | ((src[srcOff + 1] & 0xff) << 16) |
+ ((src[srcOff + 2] & 0xff) << 8) | ((src[srcOff + 3] & 0xff)));
+ }
+
+ private static void WordToBytes(int word, byte[] dst, int dstOff)
+ {
+ dst[dstOff + 3] = (byte)(word);
+ dst[dstOff + 2] = (byte)((uint)word >> 8);
+ dst[dstOff + 1] = (byte)((uint)word >> 16);
+ dst[dstOff] = (byte)((uint)word >> 24);
+ }
+
+ /*
+ * The sboxes below are based on the work of Brian Gladman and
+ * Sam Simpson, whose original notice appears below.
+ *
+ * For further details see:
+ * http://fp.gladman.plus.com/cryptography_technology/serpent/
+ *
+ */
+
+ /* Partially optimised Serpent S Box bool functions derived */
+ /* using a recursive descent analyser but without a full search */
+ /* of all subtrees. This set of S boxes is the result of work */
+ /* by Sam Simpson and Brian Gladman using the spare time on a */
+ /* cluster of high capacity servers to search for S boxes with */
+ /* this customised search engine. There are now an average of */
+ /* 15.375 terms per S box. */
+ /* */
+ /* Copyright: Dr B. R Gladman (gladman@seven77.demon.co.uk) */
+ /* and Sam Simpson (s.simpson@mia.co.uk) */
+ /* 17th December 1998 */
+ /* */
+ /* We hereby give permission for information in this file to be */
+ /* used freely subject only to acknowledgement of its origin. */
+
+ ///
+ /// S0 - { 3, 8,15, 1,10, 6, 5,11,14,13, 4, 2, 7, 0, 9,12 } - 15 terms.
+ ///
+ /// A.
+ /// The b.
+ /// The c.
+ /// The d.
+ private void Sb0(int a, int b, int c, int d)
+ {
+ int t1 = a ^ d;
+ int t3 = c ^ t1;
+ int t4 = b ^ t3;
+ this._x3 = (a & d) ^ t4;
+ int t7 = a ^ (b & t1);
+ this._x2 = t4 ^ (c | t7);
+ int t12 = this._x3 & (t3 ^ t7);
+ this._x1 = (~t3) ^ t12;
+ this._x0 = t12 ^ (~t7);
+ }
+
+ ///
+ /// InvSO - {13, 3,11, 0,10, 6, 5,12, 1,14, 4, 7,15, 9, 8, 2 } - 15 terms.
+ ///
+ /// A.
+ /// The b.
+ /// The c.
+ /// The d.
+ private void Ib0(int a, int b, int c, int d)
+ {
+ int t1 = ~a;
+ int t2 = a ^ b;
+ int t4 = d ^ (t1 | t2);
+ int t5 = c ^ t4;
+ this._x2 = t2 ^ t5;
+ int t8 = t1 ^ (d & t2);
+ this._x1 = t4 ^ (this._x2 & t8);
+ this._x3 = (a & t4) ^ (t5 | this._x1);
+ this._x0 = this._x3 ^ (t5 ^ t8);
+ }
+
+ ///
+ /// S1 - {15,12, 2, 7, 9, 0, 5,10, 1,11,14, 8, 6,13, 3, 4 } - 14 terms.
+ ///
+ /// A.
+ /// The b.
+ /// The c.
+ /// The d.
+ private void Sb1(int a, int b, int c, int d)
+ {
+ int t2 = b ^ (~a);
+ int t5 = c ^ (a | t2);
+ this._x2 = d ^ t5;
+ int t7 = b ^ (d | t2);
+ int t8 = t2 ^ this._x2;
+ this._x3 = t8 ^ (t5 & t7);
+ int t11 = t5 ^ t7;
+ this._x1 = this._x3 ^ t11;
+ this._x0 = t5 ^ (t8 & t11);
+ }
+
+ ///
+ /// InvS1 - { 5, 8, 2,14,15, 6,12, 3,11, 4, 7, 9, 1,13,10, 0 } - 14 steps.
+ ///
+ /// A.
+ /// The b.
+ /// The c.
+ /// The d.
+ private void Ib1(int a, int b, int c, int d)
+ {
+ int t1 = b ^ d;
+ int t3 = a ^ (b & t1);
+ int t4 = t1 ^ t3;
+ this._x3 = c ^ t4;
+ int t7 = b ^ (t1 & t3);
+ int t8 = this._x3 | t7;
+ this._x1 = t3 ^ t8;
+ int t10 = ~this._x1;
+ int t11 = this._x3 ^ t7;
+ this._x0 = t10 ^ t11;
+ this._x2 = t4 ^ (t10 | t11);
+ }
+
+ ///
+ /// S2 - { 8, 6, 7, 9, 3,12,10,15,13, 1,14, 4, 0,11, 5, 2 } - 16 terms.
+ ///
+ /// A.
+ /// The b.
+ /// The c.
+ /// The d.
+ private void Sb2(int a, int b, int c, int d)
+ {
+ int t1 = ~a;
+ int t2 = b ^ d;
+ int t3 = c & t1;
+ this._x0 = t2 ^ t3;
+ int t5 = c ^ t1;
+ int t6 = c ^ this._x0;
+ int t7 = b & t6;
+ this._x3 = t5 ^ t7;
+ this._x2 = a ^ ((d | t7) & (this._x0 | t5));
+ this._x1 = (t2 ^ this._x3) ^ (this._x2 ^ (d | t1));
+ }
+
+ ///
+ /// InvS2 - {12, 9,15, 4,11,14, 1, 2, 0, 3, 6,13, 5, 8,10, 7 } - 16 steps.
+ ///
+ /// A.
+ /// The b.
+ /// The c.
+ /// The d.
+ private void Ib2(int a, int b, int c, int d)
+ {
+ int t1 = b ^ d;
+ int t2 = ~t1;
+ int t3 = a ^ c;
+ int t4 = c ^ t1;
+ int t5 = b & t4;
+ this._x0 = t3 ^ t5;
+ int t7 = a | t2;
+ int t8 = d ^ t7;
+ int t9 = t3 | t8;
+ this._x3 = t1 ^ t9;
+ int t11 = ~t4;
+ int t12 = this._x0 | this._x3;
+ this._x1 = t11 ^ t12;
+ this._x2 = (d & t11) ^ (t3 ^ t12);
+ }
+
+ ///
+ /// S3 - { 0,15,11, 8,12, 9, 6, 3,13, 1, 2, 4,10, 7, 5,14 } - 16 terms.
+ ///
+ /// A.
+ /// The b.
+ /// The c.
+ /// The d.
+ private void Sb3(int a, int b, int c, int d)
+ {
+ int t1 = a ^ b;
+ int t2 = a & c;
+ int t3 = a | d;
+ int t4 = c ^ d;
+ int t5 = t1 & t3;
+ int t6 = t2 | t5;
+ this._x2 = t4 ^ t6;
+ int t8 = b ^ t3;
+ int t9 = t6 ^ t8;
+ int t10 = t4 & t9;
+ this._x0 = t1 ^ t10;
+ int t12 = this._x2 & this._x0;
+ this._x1 = t9 ^ t12;
+ this._x3 = (b | d) ^ (t4 ^ t12);
+ }
+
+ ///
+ /// InvS3 - { 0, 9,10, 7,11,14, 6,13, 3, 5,12, 2, 4, 8,15, 1 } - 15 terms
+ ///
+ /// A.
+ /// The b.
+ /// The c.
+ /// The d.
+ private void Ib3(int a, int b, int c, int d)
+ {
+ int t1 = a | b;
+ int t2 = b ^ c;
+ int t3 = b & t2;
+ int t4 = a ^ t3;
+ int t5 = c ^ t4;
+ int t6 = d | t4;
+ this._x0 = t2 ^ t6;
+ int t8 = t2 | t6;
+ int t9 = d ^ t8;
+ this._x2 = t5 ^ t9;
+ int t11 = t1 ^ t9;
+ int t12 = this._x0 & t11;
+ this._x3 = t4 ^ t12;
+ this._x1 = this._x3 ^ (this._x0 ^ t11);
+ }
+
+ ///
+ /// S4 - { 1,15, 8, 3,12, 0,11, 6, 2, 5, 4,10, 9,14, 7,13 } - 15 terms.
+ ///
+ /// A.
+ /// The b.
+ /// The c.
+ /// The d.
+ private void Sb4(int a, int b, int c, int d)
+ {
+ int t1 = a ^ d;
+ int t2 = d & t1;
+ int t3 = c ^ t2;
+ int t4 = b | t3;
+ this._x3 = t1 ^ t4;
+ int t6 = ~b;
+ int t7 = t1 | t6;
+ this._x0 = t3 ^ t7;
+ int t9 = a & this._x0;
+ int t10 = t1 ^ t6;
+ int t11 = t4 & t10;
+ this._x2 = t9 ^ t11;
+ this._x1 = (a ^ t3) ^ (t10 & this._x2);
+ }
+
+ ///
+ /// InvS4 - { 5, 0, 8, 3,10, 9, 7,14, 2,12,11, 6, 4,15,13, 1 } - 15 terms.
+ ///
+ /// A.
+ /// The b.
+ /// The c.
+ /// The d.
+ private void Ib4(int a, int b, int c, int d)
+ {
+ int t1 = c | d;
+ int t2 = a & t1;
+ int t3 = b ^ t2;
+ int t4 = a & t3;
+ int t5 = c ^ t4;
+ this._x1 = d ^ t5;
+ int t7 = ~a;
+ int t8 = t5 & this._x1;
+ this._x3 = t3 ^ t8;
+ int t10 = this._x1 | t7;
+ int t11 = d ^ t10;
+ this._x0 = this._x3 ^ t11;
+ this._x2 = (t3 & t11) ^ (this._x1 ^ t7);
+ }
+
+ ///
+ /// S5 - {15, 5, 2,11, 4,10, 9,12, 0, 3,14, 8,13, 6, 7, 1 } - 16 terms.
+ ///
+ /// A.
+ /// The b.
+ /// The c.
+ /// The d.
+ private void Sb5(int a, int b, int c, int d)
+ {
+ int t1 = ~a;
+ int t2 = a ^ b;
+ int t3 = a ^ d;
+ int t4 = c ^ t1;
+ int t5 = t2 | t3;
+ this._x0 = t4 ^ t5;
+ int t7 = d & this._x0;
+ int t8 = t2 ^ this._x0;
+ this._x1 = t7 ^ t8;
+ int t10 = t1 | this._x0;
+ int t11 = t2 | t7;
+ int t12 = t3 ^ t10;
+ this._x2 = t11 ^ t12;
+ this._x3 = (b ^ t7) ^ (this._x1 & t12);
+ }
+
+ ///
+ /// InvS5 - { 8,15, 2, 9, 4, 1,13,14,11, 6, 5, 3, 7,12,10, 0 } - 16 terms.
+ ///
+ /// A.
+ /// The b.
+ /// The c.
+ /// The d.
+ private void Ib5(int a, int b, int c, int d)
+ {
+ int t1 = ~c;
+ int t2 = b & t1;
+ int t3 = d ^ t2;
+ int t4 = a & t3;
+ int t5 = b ^ t1;
+ this._x3 = t4 ^ t5;
+ int t7 = b | this._x3;
+ int t8 = a & t7;
+ this._x1 = t3 ^ t8;
+ int t10 = a | d;
+ int t11 = t1 ^ t7;
+ this._x0 = t10 ^ t11;
+ this._x2 = (b & t10) ^ (t4 | (a ^ c));
+ }
+
+ ///
+ /// S6 - { 7, 2,12, 5, 8, 4, 6,11,14, 9, 1,15,13, 3,10, 0 } - 15 terms.
+ ///
+ /// A.
+ /// The b.
+ /// The c.
+ /// The d.
+ private void Sb6(int a, int b, int c, int d)
+ {
+ int t1 = ~a;
+ int t2 = a ^ d;
+ int t3 = b ^ t2;
+ int t4 = t1 | t2;
+ int t5 = c ^ t4;
+ this._x1 = b ^ t5;
+ int t7 = t2 | this._x1;
+ int t8 = d ^ t7;
+ int t9 = t5 & t8;
+ this._x2 = t3 ^ t9;
+ int t11 = t5 ^ t8;
+ this._x0 = this._x2 ^ t11;
+ this._x3 = (~t5) ^ (t3 & t11);
+ }
+
+ ///
+ /// InvS6 - {15,10, 1,13, 5, 3, 6, 0, 4, 9,14, 7, 2,12, 8,11 } - 15 terms.
+ ///
+ /// A.
+ /// The b.
+ /// The c.
+ /// The d.
+ private void Ib6(int a, int b, int c, int d)
+ {
+ int t1 = ~a;
+ int t2 = a ^ b;
+ int t3 = c ^ t2;
+ int t4 = c | t1;
+ int t5 = d ^ t4;
+ this._x1 = t3 ^ t5;
+ int t7 = t3 & t5;
+ int t8 = t2 ^ t7;
+ int t9 = b | t8;
+ this._x3 = t5 ^ t9;
+ int t11 = b | this._x3;
+ this._x0 = t8 ^ t11;
+ this._x2 = (d & t1) ^ (t3 ^ t11);
+ }
+
+ ///
+ /// S7 - { 1,13,15, 0,14, 8, 2,11, 7, 4,12,10, 9, 3, 5, 6 } - 16 terms.
+ ///
+ /// A.
+ /// The b.
+ /// The c.
+ /// The d.
+ private void Sb7(int a, int b, int c, int d)
+ {
+ int t1 = b ^ c;
+ int t2 = c & t1;
+ int t3 = d ^ t2;
+ int t4 = a ^ t3;
+ int t5 = d | t1;
+ int t6 = t4 & t5;
+ this._x1 = b ^ t6;
+ int t8 = t3 | this._x1;
+ int t9 = a & t4;
+ this._x3 = t1 ^ t9;
+ int t11 = t4 ^ t8;
+ int t12 = this._x3 & t11;
+ this._x2 = t3 ^ t12;
+ this._x0 = (~t11) ^ (this._x3 & this._x2);
+ }
+
+ ///
+ /// InvS7 - { 3, 0, 6,13, 9,14,15, 8, 5,12,11, 7,10, 1, 4, 2 } - 17 terms.
+ ///
+ /// A.
+ /// The b.
+ /// The c.
+ /// The d.
+ private void Ib7(int a, int b, int c, int d)
+ {
+ int t3 = c | (a & b);
+ int t4 = d & (a | b);
+ this._x3 = t3 ^ t4;
+ int t6 = ~d;
+ int t7 = b ^ t4;
+ int t9 = t7 | (this._x3 ^ t6);
+ this._x1 = a ^ t9;
+ this._x0 = (c ^ t7) ^ (d | this._x1);
+ this._x2 = (t3 ^ this._x1) ^ (this._x0 ^ (a & this._x3));
+ }
+
+ ///
+ /// Apply the linear transformation to the register set.
+ ///
+ private void LT()
+ {
+ int x0 = RotateLeft(this._x0, 13);
+ int x2 = RotateLeft(this._x2, 3);
+ int x1 = this._x1 ^ x0 ^ x2;
+ int x3 = this._x3 ^ x2 ^ x0 << 3;
+
+ this._x1 = RotateLeft(x1, 1);
+ this._x3 = RotateLeft(x3, 7);
+ this._x0 = RotateLeft(x0 ^ this._x1 ^ this._x3, 5);
+ this._x2 = RotateLeft(x2 ^ this._x3 ^ (this._x1 << 7), 22);
+ }
+
+ ///
+ /// Apply the inverse of the linear transformation to the register set.
+ ///
+ private void InverseLT()
+ {
+ int x2 = RotateRight(this._x2, 22) ^ this._x3 ^ (this._x1 << 7);
+ int x0 = RotateRight(this._x0, 5) ^ this._x1 ^ this._x3;
+ int x3 = RotateRight(this._x3, 7);
+ int x1 = RotateRight(this._x1, 1);
+ this._x3 = x3 ^ x2 ^ x0 << 3;
+ this._x1 = x1 ^ x0 ^ x2;
+ this._x2 = RotateRight(x2, 3);
+ this._x0 = RotateRight(x0, 13);
+ }
+ }
+}
diff --git a/Renci.SshNet/Security/Cryptography/Ciphers/TripleDesCipher.cs b/Renci.SshNet/Security/Cryptography/Ciphers/TripleDesCipher.cs
index 25ca07f..6bd2d51 100644
--- a/Renci.SshNet/Security/Cryptography/Ciphers/TripleDesCipher.cs
+++ b/Renci.SshNet/Security/Cryptography/Ciphers/TripleDesCipher.cs
@@ -1,153 +1,150 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace Renci.SshNet.Security.Cryptography.Ciphers
-{
- ///
- /// Implements 3DES cipher algorithm.
- ///
- public sealed class TripleDesCipher : DesCipher
- {
- private int[] _encryptionKey1;
-
- private int[] _encryptionKey2;
-
- private int[] _encryptionKey3;
-
- private int[] _decryptionKey1;
-
- private int[] _decryptionKey2;
-
- private int[] _decryptionKey3;
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The key.
- /// The mode.
- /// The padding.
- /// is null.
- public TripleDesCipher(byte[] key, CipherMode mode, CipherPadding padding)
- : base(key, mode, padding)
- {
- }
-
- ///
- /// Encrypts the specified region of the input byte array and copies the encrypted data to the specified region of the output byte array.
- ///
- /// The input data to encrypt.
- /// The offset into the input byte array from which to begin using data.
- /// The number of bytes in the input byte array to use as data.
- /// The output to which to write encrypted data.
- /// The offset into the output byte array from which to begin writing data.
- ///
- /// The number of bytes encrypted.
- ///
- public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
- {
- if ((inputOffset + this.BlockSize) > inputBuffer.Length)
- throw new IndexOutOfRangeException("input buffer too short");
-
- if ((outputOffset + this.BlockSize) > outputBuffer.Length)
- throw new IndexOutOfRangeException("output buffer too short");
-
- if (this._encryptionKey1 == null || this._encryptionKey2 == null || this._encryptionKey3 == null)
- {
- var part1 = new byte[8];
- var part2 = new byte[8];
-
- Buffer.BlockCopy(this.Key, 0, part1, 0, 8);
- Buffer.BlockCopy(this.Key, 8, part2, 0, 8);
-
- this._encryptionKey1 = this.GenerateWorkingKey(true, part1);
-
- this._encryptionKey2 = this.GenerateWorkingKey(false, part2);
-
- if (this.Key.Length == 24)
- {
- var part3 = new byte[8];
- Buffer.BlockCopy(this.Key, 16, part3, 0, 8);
-
- this._encryptionKey3 = this.GenerateWorkingKey(true, part3);
- }
- else
- {
- this._encryptionKey3 = this._encryptionKey1;
- }
- }
-
- byte[] temp = new byte[this.BlockSize];
-
- DesCipher.DesFunc(this._encryptionKey1, inputBuffer, inputOffset, temp, 0);
- DesCipher.DesFunc(this._encryptionKey2, temp, 0, temp, 0);
- DesCipher.DesFunc(this._encryptionKey3, temp, 0, outputBuffer, outputOffset);
-
- return this.BlockSize;
- }
-
- ///
- /// Decrypts the specified region of the input byte array and copies the decrypted data to the specified region of the output byte array.
- ///
- /// The input data to decrypt.
- /// The offset into the input byte array from which to begin using data.
- /// The number of bytes in the input byte array to use as data.
- /// The output to which to write decrypted data.
- /// The offset into the output byte array from which to begin writing data.
- ///
- /// The number of bytes decrypted.
- ///
- public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
- {
- if ((inputOffset + this.BlockSize) > inputBuffer.Length)
- throw new IndexOutOfRangeException("input buffer too short");
-
- if ((outputOffset + this.BlockSize) > outputBuffer.Length)
- throw new IndexOutOfRangeException("output buffer too short");
-
- if (this._decryptionKey1 == null || this._decryptionKey2 == null || this._decryptionKey3 == null)
- {
- var part1 = new byte[8];
- var part2 = new byte[8];
-
- Buffer.BlockCopy(this.Key, 0, part1, 0, 8);
- Buffer.BlockCopy(this.Key, 8, part2, 0, 8);
-
- this._decryptionKey1 = this.GenerateWorkingKey(false, part1);
- this._decryptionKey2 = this.GenerateWorkingKey(true, part2);
-
- if (this.Key.Length == 24)
- {
- var part3 = new byte[8];
- Buffer.BlockCopy(this.Key, 16, part3, 0, 8);
-
- this._decryptionKey3 = this.GenerateWorkingKey(false, part3);
- }
- else
- {
- this._decryptionKey3 = this._decryptionKey1;
- }
- }
-
- byte[] temp = new byte[this.BlockSize];
-
- DesCipher.DesFunc(this._decryptionKey3, inputBuffer, inputOffset, temp, 0);
- DesCipher.DesFunc(this._decryptionKey2, temp, 0, temp, 0);
- DesCipher.DesFunc(this._decryptionKey1, temp, 0, outputBuffer, outputOffset);
-
- return this.BlockSize;
- }
-
- ///
- /// Validates the key.
- ///
- protected override void ValidateKey()
- {
- var keySize = this.Key.Length * 8;
-
- if (!(keySize == 128 || keySize == 128 + 64))
- throw new ArgumentException(string.Format("KeySize '{0}' is not valid for this algorithm.", keySize));
- }
- }
-}
+using System;
+
+namespace Renci.SshNet.Security.Cryptography.Ciphers
+{
+ ///
+ /// Implements 3DES cipher algorithm.
+ ///
+ public sealed class TripleDesCipher : DesCipher
+ {
+ private int[] _encryptionKey1;
+
+ private int[] _encryptionKey2;
+
+ private int[] _encryptionKey3;
+
+ private int[] _decryptionKey1;
+
+ private int[] _decryptionKey2;
+
+ private int[] _decryptionKey3;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The key.
+ /// The mode.
+ /// The padding.
+ /// is null.
+ public TripleDesCipher(byte[] key, CipherMode mode, CipherPadding padding)
+ : base(key, mode, padding)
+ {
+ }
+
+ ///
+ /// Encrypts the specified region of the input byte array and copies the encrypted data to the specified region of the output byte array.
+ ///
+ /// The input data to encrypt.
+ /// The offset into the input byte array from which to begin using data.
+ /// The number of bytes in the input byte array to use as data.
+ /// The output to which to write encrypted data.
+ /// The offset into the output byte array from which to begin writing data.
+ ///
+ /// The number of bytes encrypted.
+ ///
+ public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
+ {
+ if ((inputOffset + this.BlockSize) > inputBuffer.Length)
+ throw new IndexOutOfRangeException("input buffer too short");
+
+ if ((outputOffset + this.BlockSize) > outputBuffer.Length)
+ throw new IndexOutOfRangeException("output buffer too short");
+
+ if (this._encryptionKey1 == null || this._encryptionKey2 == null || this._encryptionKey3 == null)
+ {
+ var part1 = new byte[8];
+ var part2 = new byte[8];
+
+ Buffer.BlockCopy(this.Key, 0, part1, 0, 8);
+ Buffer.BlockCopy(this.Key, 8, part2, 0, 8);
+
+ this._encryptionKey1 = this.GenerateWorkingKey(true, part1);
+
+ this._encryptionKey2 = this.GenerateWorkingKey(false, part2);
+
+ if (this.Key.Length == 24)
+ {
+ var part3 = new byte[8];
+ Buffer.BlockCopy(this.Key, 16, part3, 0, 8);
+
+ this._encryptionKey3 = this.GenerateWorkingKey(true, part3);
+ }
+ else
+ {
+ this._encryptionKey3 = this._encryptionKey1;
+ }
+ }
+
+ byte[] temp = new byte[this.BlockSize];
+
+ DesCipher.DesFunc(this._encryptionKey1, inputBuffer, inputOffset, temp, 0);
+ DesCipher.DesFunc(this._encryptionKey2, temp, 0, temp, 0);
+ DesCipher.DesFunc(this._encryptionKey3, temp, 0, outputBuffer, outputOffset);
+
+ return this.BlockSize;
+ }
+
+ ///
+ /// Decrypts the specified region of the input byte array and copies the decrypted data to the specified region of the output byte array.
+ ///
+ /// The input data to decrypt.
+ /// The offset into the input byte array from which to begin using data.
+ /// The number of bytes in the input byte array to use as data.
+ /// The output to which to write decrypted data.
+ /// The offset into the output byte array from which to begin writing data.
+ ///
+ /// The number of bytes decrypted.
+ ///
+ public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
+ {
+ if ((inputOffset + this.BlockSize) > inputBuffer.Length)
+ throw new IndexOutOfRangeException("input buffer too short");
+
+ if ((outputOffset + this.BlockSize) > outputBuffer.Length)
+ throw new IndexOutOfRangeException("output buffer too short");
+
+ if (this._decryptionKey1 == null || this._decryptionKey2 == null || this._decryptionKey3 == null)
+ {
+ var part1 = new byte[8];
+ var part2 = new byte[8];
+
+ Buffer.BlockCopy(this.Key, 0, part1, 0, 8);
+ Buffer.BlockCopy(this.Key, 8, part2, 0, 8);
+
+ this._decryptionKey1 = this.GenerateWorkingKey(false, part1);
+ this._decryptionKey2 = this.GenerateWorkingKey(true, part2);
+
+ if (this.Key.Length == 24)
+ {
+ var part3 = new byte[8];
+ Buffer.BlockCopy(this.Key, 16, part3, 0, 8);
+
+ this._decryptionKey3 = this.GenerateWorkingKey(false, part3);
+ }
+ else
+ {
+ this._decryptionKey3 = this._decryptionKey1;
+ }
+ }
+
+ byte[] temp = new byte[this.BlockSize];
+
+ DesCipher.DesFunc(this._decryptionKey3, inputBuffer, inputOffset, temp, 0);
+ DesCipher.DesFunc(this._decryptionKey2, temp, 0, temp, 0);
+ DesCipher.DesFunc(this._decryptionKey1, temp, 0, outputBuffer, outputOffset);
+
+ return this.BlockSize;
+ }
+
+ ///
+ /// Validates the key.
+ ///
+ protected override void ValidateKey()
+ {
+ var keySize = this.Key.Length * 8;
+
+ if (!(keySize == 128 || keySize == 128 + 64))
+ throw new ArgumentException(string.Format("KeySize '{0}' is not valid for this algorithm.", keySize));
+ }
+ }
+}
diff --git a/Renci.SshNet/Security/Cryptography/Ciphers/TwofishCipher.cs b/Renci.SshNet/Security/Cryptography/Ciphers/TwofishCipher.cs
index fac38e4..04bfb9f 100644
--- a/Renci.SshNet/Security/Cryptography/Ciphers/TwofishCipher.cs
+++ b/Renci.SshNet/Security/Cryptography/Ciphers/TwofishCipher.cs
@@ -1,617 +1,614 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace Renci.SshNet.Security.Cryptography.Ciphers
-{
- ///
- /// Implements Twofish cipher algorithm
- ///
- public sealed class TwofishCipher : BlockCipher
- {
- ///
- /// Initializes a new instance of the class.
- ///
- /// The key.
- /// The mode.
- /// The padding.
- /// is null.
- /// Keysize is not valid for this algorithm.
- public TwofishCipher(byte[] key, CipherMode mode, CipherPadding padding)
- : base(key, 16, mode, padding)
- {
- var keySize = key.Length * 8;
-
- if (!(keySize == 128 || keySize == 192 || keySize == 256))
- throw new ArgumentException(string.Format("KeySize '{0}' is not valid for this algorithm.", keySize));
-
- // TODO: Refactor this algorithm
-
- // calculate the MDS matrix
- int[] m1 = new int[2];
- int[] mX = new int[2];
- int[] mY = new int[2];
- int j;
-
- for (int i = 0; i < MAX_KEY_BITS; i++)
- {
- j = P[0 + i] & 0xff;
- m1[0] = j;
- mX[0] = Mx_X(j) & 0xff;
- mY[0] = Mx_Y(j) & 0xff;
-
- j = P[(1 * 256) + i] & 0xff;
- m1[1] = j;
- mX[1] = Mx_X(j) & 0xff;
- mY[1] = Mx_Y(j) & 0xff;
-
- gMDS0[i] = m1[P_00] | mX[P_00] << 8 | mY[P_00] << 16 | mY[P_00] << 24;
-
- gMDS1[i] = mY[P_10] | mY[P_10] << 8 | mX[P_10] << 16 | m1[P_10] << 24;
-
- gMDS2[i] = mX[P_20] | mY[P_20] << 8 | m1[P_20] << 16 | mY[P_20] << 24;
-
- gMDS3[i] = mX[P_30] | m1[P_30] << 8 | mY[P_30] << 16 | mX[P_30] << 24;
- }
-
- this.k64Cnt = key.Length / 8; // pre-padded ?
- this.SetKey(key);
- }
-
- ///
- /// Encrypts the specified region of the input byte array and copies the encrypted data to the specified region of the output byte array.
- ///
- /// The input data to encrypt.
- /// The offset into the input byte array from which to begin using data.
- /// The number of bytes in the input byte array to use as data.
- /// The output to which to write encrypted data.
- /// The offset into the output byte array from which to begin writing data.
- ///
- /// The number of bytes encrypted.
- ///
- public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
- {
- int x0 = BytesTo32Bits(inputBuffer, inputOffset) ^ gSubKeys[INPUT_WHITEN];
- int x1 = BytesTo32Bits(inputBuffer, inputOffset + 4) ^ gSubKeys[INPUT_WHITEN + 1];
- int x2 = BytesTo32Bits(inputBuffer, inputOffset + 8) ^ gSubKeys[INPUT_WHITEN + 2];
- int x3 = BytesTo32Bits(inputBuffer, inputOffset + 12) ^ gSubKeys[INPUT_WHITEN + 3];
-
- int k = ROUND_SUBKEYS;
- int t0, t1;
- for (int r = 0; r < ROUNDS; r += 2)
- {
- t0 = Fe32_0(gSBox, x0);
- t1 = Fe32_3(gSBox, x1);
- x2 ^= t0 + t1 + gSubKeys[k++];
- x2 = (int)((uint)x2 >> 1) | x2 << 31;
- x3 = (x3 << 1 | (int)((uint)x3 >> 31)) ^ (t0 + 2 * t1 + gSubKeys[k++]);
-
- t0 = Fe32_0(gSBox, x2);
- t1 = Fe32_3(gSBox, x3);
- x0 ^= t0 + t1 + gSubKeys[k++];
- x0 = (int)((uint)x0 >> 1) | x0 << 31;
- x1 = (x1 << 1 | (int)((uint)x1 >> 31)) ^ (t0 + 2 * t1 + gSubKeys[k++]);
- }
-
- Bits32ToBytes(x2 ^ gSubKeys[OUTPUT_WHITEN], outputBuffer, outputOffset);
- Bits32ToBytes(x3 ^ gSubKeys[OUTPUT_WHITEN + 1], outputBuffer, outputOffset + 4);
- Bits32ToBytes(x0 ^ gSubKeys[OUTPUT_WHITEN + 2], outputBuffer, outputOffset + 8);
- Bits32ToBytes(x1 ^ gSubKeys[OUTPUT_WHITEN + 3], outputBuffer, outputOffset + 12);
-
- return this.BlockSize;
- }
-
- ///
- /// Decrypts the specified region of the input byte array and copies the decrypted data to the specified region of the output byte array.
- ///
- /// The input data to decrypt.
- /// The offset into the input byte array from which to begin using data.
- /// The number of bytes in the input byte array to use as data.
- /// The output to which to write decrypted data.
- /// The offset into the output byte array from which to begin writing data.
- ///
- /// The number of bytes decrypted.
- ///
- public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
- {
- int x2 = BytesTo32Bits(inputBuffer, inputOffset) ^ gSubKeys[OUTPUT_WHITEN];
- int x3 = BytesTo32Bits(inputBuffer, inputOffset + 4) ^ gSubKeys[OUTPUT_WHITEN + 1];
- int x0 = BytesTo32Bits(inputBuffer, inputOffset + 8) ^ gSubKeys[OUTPUT_WHITEN + 2];
- int x1 = BytesTo32Bits(inputBuffer, inputOffset + 12) ^ gSubKeys[OUTPUT_WHITEN + 3];
-
- int k = ROUND_SUBKEYS + 2 * ROUNDS - 1;
- int t0, t1;
- for (int r = 0; r < ROUNDS; r += 2)
- {
- t0 = Fe32_0(gSBox, x2);
- t1 = Fe32_3(gSBox, x3);
- x1 ^= t0 + 2 * t1 + gSubKeys[k--];
- x0 = (x0 << 1 | (int)((uint)x0 >> 31)) ^ (t0 + t1 + gSubKeys[k--]);
- x1 = (int)((uint)x1 >> 1) | x1 << 31;
-
- t0 = Fe32_0(gSBox, x0);
- t1 = Fe32_3(gSBox, x1);
- x3 ^= t0 + 2 * t1 + gSubKeys[k--];
- x2 = (x2 << 1 | (int)((uint)x2 >> 31)) ^ (t0 + t1 + gSubKeys[k--]);
- x3 = (int)((uint)x3 >> 1) | x3 << 31;
- }
-
- Bits32ToBytes(x0 ^ gSubKeys[INPUT_WHITEN], outputBuffer, outputOffset);
- Bits32ToBytes(x1 ^ gSubKeys[INPUT_WHITEN + 1], outputBuffer, outputOffset + 4);
- Bits32ToBytes(x2 ^ gSubKeys[INPUT_WHITEN + 2], outputBuffer, outputOffset + 8);
- Bits32ToBytes(x3 ^ gSubKeys[INPUT_WHITEN + 3], outputBuffer, outputOffset + 12);
-
- return this.BlockSize;
- }
-
- #region Static Definition Tables
-
- private static readonly byte[] P = {
- //{ // p0
- (byte) 0xA9, (byte) 0x67, (byte) 0xB3, (byte) 0xE8,
- (byte) 0x04, (byte) 0xFD, (byte) 0xA3, (byte) 0x76,
- (byte) 0x9A, (byte) 0x92, (byte) 0x80, (byte) 0x78,
- (byte) 0xE4, (byte) 0xDD, (byte) 0xD1, (byte) 0x38,
- (byte) 0x0D, (byte) 0xC6, (byte) 0x35, (byte) 0x98,
- (byte) 0x18, (byte) 0xF7, (byte) 0xEC, (byte) 0x6C,
- (byte) 0x43, (byte) 0x75, (byte) 0x37, (byte) 0x26,
- (byte) 0xFA, (byte) 0x13, (byte) 0x94, (byte) 0x48,
- (byte) 0xF2, (byte) 0xD0, (byte) 0x8B, (byte) 0x30,
- (byte) 0x84, (byte) 0x54, (byte) 0xDF, (byte) 0x23,
- (byte) 0x19, (byte) 0x5B, (byte) 0x3D, (byte) 0x59,
- (byte) 0xF3, (byte) 0xAE, (byte) 0xA2, (byte) 0x82,
- (byte) 0x63, (byte) 0x01, (byte) 0x83, (byte) 0x2E,
- (byte) 0xD9, (byte) 0x51, (byte) 0x9B, (byte) 0x7C,
- (byte) 0xA6, (byte) 0xEB, (byte) 0xA5, (byte) 0xBE,
- (byte) 0x16, (byte) 0x0C, (byte) 0xE3, (byte) 0x61,
- (byte) 0xC0, (byte) 0x8C, (byte) 0x3A, (byte) 0xF5,
- (byte) 0x73, (byte) 0x2C, (byte) 0x25, (byte) 0x0B,
- (byte) 0xBB, (byte) 0x4E, (byte) 0x89, (byte) 0x6B,
- (byte) 0x53, (byte) 0x6A, (byte) 0xB4, (byte) 0xF1,
- (byte) 0xE1, (byte) 0xE6, (byte) 0xBD, (byte) 0x45,
- (byte) 0xE2, (byte) 0xF4, (byte) 0xB6, (byte) 0x66,
- (byte) 0xCC, (byte) 0x95, (byte) 0x03, (byte) 0x56,
- (byte) 0xD4, (byte) 0x1C, (byte) 0x1E, (byte) 0xD7,
- (byte) 0xFB, (byte) 0xC3, (byte) 0x8E, (byte) 0xB5,
- (byte) 0xE9, (byte) 0xCF, (byte) 0xBF, (byte) 0xBA,
- (byte) 0xEA, (byte) 0x77, (byte) 0x39, (byte) 0xAF,
- (byte) 0x33, (byte) 0xC9, (byte) 0x62, (byte) 0x71,
- (byte) 0x81, (byte) 0x79, (byte) 0x09, (byte) 0xAD,
- (byte) 0x24, (byte) 0xCD, (byte) 0xF9, (byte) 0xD8,
- (byte) 0xE5, (byte) 0xC5, (byte) 0xB9, (byte) 0x4D,
- (byte) 0x44, (byte) 0x08, (byte) 0x86, (byte) 0xE7,
- (byte) 0xA1, (byte) 0x1D, (byte) 0xAA, (byte) 0xED,
- (byte) 0x06, (byte) 0x70, (byte) 0xB2, (byte) 0xD2,
- (byte) 0x41, (byte) 0x7B, (byte) 0xA0, (byte) 0x11,
- (byte) 0x31, (byte) 0xC2, (byte) 0x27, (byte) 0x90,
- (byte) 0x20, (byte) 0xF6, (byte) 0x60, (byte) 0xFF,
- (byte) 0x96, (byte) 0x5C, (byte) 0xB1, (byte) 0xAB,
- (byte) 0x9E, (byte) 0x9C, (byte) 0x52, (byte) 0x1B,
- (byte) 0x5F, (byte) 0x93, (byte) 0x0A, (byte) 0xEF,
- (byte) 0x91, (byte) 0x85, (byte) 0x49, (byte) 0xEE,
- (byte) 0x2D, (byte) 0x4F, (byte) 0x8F, (byte) 0x3B,
- (byte) 0x47, (byte) 0x87, (byte) 0x6D, (byte) 0x46,
- (byte) 0xD6, (byte) 0x3E, (byte) 0x69, (byte) 0x64,
- (byte) 0x2A, (byte) 0xCE, (byte) 0xCB, (byte) 0x2F,
- (byte) 0xFC, (byte) 0x97, (byte) 0x05, (byte) 0x7A,
- (byte) 0xAC, (byte) 0x7F, (byte) 0xD5, (byte) 0x1A,
- (byte) 0x4B, (byte) 0x0E, (byte) 0xA7, (byte) 0x5A,
- (byte) 0x28, (byte) 0x14, (byte) 0x3F, (byte) 0x29,
- (byte) 0x88, (byte) 0x3C, (byte) 0x4C, (byte) 0x02,
- (byte) 0xB8, (byte) 0xDA, (byte) 0xB0, (byte) 0x17,
- (byte) 0x55, (byte) 0x1F, (byte) 0x8A, (byte) 0x7D,
- (byte) 0x57, (byte) 0xC7, (byte) 0x8D, (byte) 0x74,
- (byte) 0xB7, (byte) 0xC4, (byte) 0x9F, (byte) 0x72,
- (byte) 0x7E, (byte) 0x15, (byte) 0x22, (byte) 0x12,
- (byte) 0x58, (byte) 0x07, (byte) 0x99, (byte) 0x34,
- (byte) 0x6E, (byte) 0x50, (byte) 0xDE, (byte) 0x68,
- (byte) 0x65, (byte) 0xBC, (byte) 0xDB, (byte) 0xF8,
- (byte) 0xC8, (byte) 0xA8, (byte) 0x2B, (byte) 0x40,
- (byte) 0xDC, (byte) 0xFE, (byte) 0x32, (byte) 0xA4,
- (byte) 0xCA, (byte) 0x10, (byte) 0x21, (byte) 0xF0,
- (byte) 0xD3, (byte) 0x5D, (byte) 0x0F, (byte) 0x00,
- (byte) 0x6F, (byte) 0x9D, (byte) 0x36, (byte) 0x42,
- (byte) 0x4A, (byte) 0x5E, (byte) 0xC1, (byte) 0xE0,
- // },
- //{ // p1
- (byte) 0x75, (byte) 0xF3, (byte) 0xC6, (byte) 0xF4,
- (byte) 0xDB, (byte) 0x7B, (byte) 0xFB, (byte) 0xC8,
- (byte) 0x4A, (byte) 0xD3, (byte) 0xE6, (byte) 0x6B,
- (byte) 0x45, (byte) 0x7D, (byte) 0xE8, (byte) 0x4B,
- (byte) 0xD6, (byte) 0x32, (byte) 0xD8, (byte) 0xFD,
- (byte) 0x37, (byte) 0x71, (byte) 0xF1, (byte) 0xE1,
- (byte) 0x30, (byte) 0x0F, (byte) 0xF8, (byte) 0x1B,
- (byte) 0x87, (byte) 0xFA, (byte) 0x06, (byte) 0x3F,
- (byte) 0x5E, (byte) 0xBA, (byte) 0xAE, (byte) 0x5B,
- (byte) 0x8A, (byte) 0x00, (byte) 0xBC, (byte) 0x9D,
- (byte) 0x6D, (byte) 0xC1, (byte) 0xB1, (byte) 0x0E,
- (byte) 0x80, (byte) 0x5D, (byte) 0xD2, (byte) 0xD5,
- (byte) 0xA0, (byte) 0x84, (byte) 0x07, (byte) 0x14,
- (byte) 0xB5, (byte) 0x90, (byte) 0x2C, (byte) 0xA3,
- (byte) 0xB2, (byte) 0x73, (byte) 0x4C, (byte) 0x54,
- (byte) 0x92, (byte) 0x74, (byte) 0x36, (byte) 0x51,
- (byte) 0x38, (byte) 0xB0, (byte) 0xBD, (byte) 0x5A,
- (byte) 0xFC, (byte) 0x60, (byte) 0x62, (byte) 0x96,
- (byte) 0x6C, (byte) 0x42, (byte) 0xF7, (byte) 0x10,
- (byte) 0x7C, (byte) 0x28, (byte) 0x27, (byte) 0x8C,
- (byte) 0x13, (byte) 0x95, (byte) 0x9C, (byte) 0xC7,
- (byte) 0x24, (byte) 0x46, (byte) 0x3B, (byte) 0x70,
- (byte) 0xCA, (byte) 0xE3, (byte) 0x85, (byte) 0xCB,
- (byte) 0x11, (byte) 0xD0, (byte) 0x93, (byte) 0xB8,
- (byte) 0xA6, (byte) 0x83, (byte) 0x20, (byte) 0xFF,
- (byte) 0x9F, (byte) 0x77, (byte) 0xC3, (byte) 0xCC,
- (byte) 0x03, (byte) 0x6F, (byte) 0x08, (byte) 0xBF,
- (byte) 0x40, (byte) 0xE7, (byte) 0x2B, (byte) 0xE2,
- (byte) 0x79, (byte) 0x0C, (byte) 0xAA, (byte) 0x82,
- (byte) 0x41, (byte) 0x3A, (byte) 0xEA, (byte) 0xB9,
- (byte) 0xE4, (byte) 0x9A, (byte) 0xA4, (byte) 0x97,
- (byte) 0x7E, (byte) 0xDA, (byte) 0x7A, (byte) 0x17,
- (byte) 0x66, (byte) 0x94, (byte) 0xA1, (byte) 0x1D,
- (byte) 0x3D, (byte) 0xF0, (byte) 0xDE, (byte) 0xB3,
- (byte) 0x0B, (byte) 0x72, (byte) 0xA7, (byte) 0x1C,
- (byte) 0xEF, (byte) 0xD1, (byte) 0x53, (byte) 0x3E,
- (byte) 0x8F, (byte) 0x33, (byte) 0x26, (byte) 0x5F,
- (byte) 0xEC, (byte) 0x76, (byte) 0x2A, (byte) 0x49,
- (byte) 0x81, (byte) 0x88, (byte) 0xEE, (byte) 0x21,
- (byte) 0xC4, (byte) 0x1A, (byte) 0xEB, (byte) 0xD9,
- (byte) 0xC5, (byte) 0x39, (byte) 0x99, (byte) 0xCD,
- (byte) 0xAD, (byte) 0x31, (byte) 0x8B, (byte) 0x01,
- (byte) 0x18, (byte) 0x23, (byte) 0xDD, (byte) 0x1F,
- (byte) 0x4E, (byte) 0x2D, (byte) 0xF9, (byte) 0x48,
- (byte) 0x4F, (byte) 0xF2, (byte) 0x65, (byte) 0x8E,
- (byte) 0x78, (byte) 0x5C, (byte) 0x58, (byte) 0x19,
- (byte) 0x8D, (byte) 0xE5, (byte) 0x98, (byte) 0x57,
- (byte) 0x67, (byte) 0x7F, (byte) 0x05, (byte) 0x64,
- (byte) 0xAF, (byte) 0x63, (byte) 0xB6, (byte) 0xFE,
- (byte) 0xF5, (byte) 0xB7, (byte) 0x3C, (byte) 0xA5,
- (byte) 0xCE, (byte) 0xE9, (byte) 0x68, (byte) 0x44,
- (byte) 0xE0, (byte) 0x4D, (byte) 0x43, (byte) 0x69,
- (byte) 0x29, (byte) 0x2E, (byte) 0xAC, (byte) 0x15,
- (byte) 0x59, (byte) 0xA8, (byte) 0x0A, (byte) 0x9E,
- (byte) 0x6E, (byte) 0x47, (byte) 0xDF, (byte) 0x34,
- (byte) 0x35, (byte) 0x6A, (byte) 0xCF, (byte) 0xDC,
- (byte) 0x22, (byte) 0xC9, (byte) 0xC0, (byte) 0x9B,
- (byte) 0x89, (byte) 0xD4, (byte) 0xED, (byte) 0xAB,
- (byte) 0x12, (byte) 0xA2, (byte) 0x0D, (byte) 0x52,
- (byte) 0xBB, (byte) 0x02, (byte) 0x2F, (byte) 0xA9,
- (byte) 0xD7, (byte) 0x61, (byte) 0x1E, (byte) 0xB4,
- (byte) 0x50, (byte) 0x04, (byte) 0xF6, (byte) 0xC2,
- (byte) 0x16, (byte) 0x25, (byte) 0x86, (byte) 0x56,
- (byte) 0x55, (byte) 0x09, (byte) 0xBE, (byte) 0x91
- //}
- };
-
- #endregion
-
- /**
- * Define the fixed p0/p1 permutations used in keyed S-box lookup.
- * By changing the following constant definitions, the S-boxes will
- * automatically Get changed in the Twofish engine.
- */
- private const int P_00 = 1;
- private const int P_01 = 0;
- private const int P_02 = 0;
- private const int P_03 = P_01 ^ 1;
- private const int P_04 = 1;
-
- private const int P_10 = 0;
- private const int P_11 = 0;
- private const int P_12 = 1;
- private const int P_13 = P_11 ^ 1;
- private const int P_14 = 0;
-
- private const int P_20 = 1;
- private const int P_21 = 1;
- private const int P_22 = 0;
- private const int P_23 = P_21 ^ 1;
- private const int P_24 = 0;
-
- private const int P_30 = 0;
- private const int P_31 = 1;
- private const int P_32 = 1;
- private const int P_33 = P_31 ^ 1;
- private const int P_34 = 1;
-
- /* Primitive polynomial for GF(256) */
- private const int GF256_FDBK = 0x169;
- private const int GF256_FDBK_2 = GF256_FDBK / 2;
- private const int GF256_FDBK_4 = GF256_FDBK / 4;
-
- private const int RS_GF_FDBK = 0x14D; // field generator
-
- //====================================
- // Useful constants
- //====================================
-
- private const int ROUNDS = 16;
- private const int MAX_ROUNDS = 16; // bytes = 128 bits
- private const int MAX_KEY_BITS = 256;
-
- private const int INPUT_WHITEN = 0;
- private const int OUTPUT_WHITEN = INPUT_WHITEN + 16 / 4; // 4
- private const int ROUND_SUBKEYS = OUTPUT_WHITEN + 16 / 4;// 8
-
- private const int TOTAL_SUBKEYS = ROUND_SUBKEYS + 2 * MAX_ROUNDS;// 40
-
- private const int SK_STEP = 0x02020202;
- private const int SK_BUMP = 0x01010101;
- private const int SK_ROTL = 9;
-
- private int[] gMDS0 = new int[MAX_KEY_BITS];
- private int[] gMDS1 = new int[MAX_KEY_BITS];
- private int[] gMDS2 = new int[MAX_KEY_BITS];
- private int[] gMDS3 = new int[MAX_KEY_BITS];
-
- /**
- * gSubKeys[] and gSBox[] are eventually used in the
- * encryption and decryption methods.
- */
- private int[] gSubKeys;
- private int[] gSBox;
-
- private int k64Cnt;
-
- private void SetKey(byte[] key)
- {
- int[] k32e = new int[MAX_KEY_BITS / 64]; // 4
- int[] k32o = new int[MAX_KEY_BITS / 64]; // 4
-
- int[] sBoxKeys = new int[MAX_KEY_BITS / 64]; // 4
- gSubKeys = new int[TOTAL_SUBKEYS];
-
- if (k64Cnt < 1)
- {
- throw new ArgumentException("Key size less than 64 bits");
- }
-
- if (k64Cnt > 4)
- {
- throw new ArgumentException("Key size larger than 256 bits");
- }
-
- /*
- * k64Cnt is the number of 8 byte blocks (64 chunks)
- * that are in the input key. The input key is a
- * maximum of 32 bytes ( 256 bits ), so the range
- * for k64Cnt is 1..4
- */
- for (int i = 0, p = 0; i < k64Cnt; i++)
- {
- p = i * 8;
-
- k32e[i] = BytesTo32Bits(key, p);
- k32o[i] = BytesTo32Bits(key, p + 4);
-
- sBoxKeys[k64Cnt - 1 - i] = RS_MDS_Encode(k32e[i], k32o[i]);
- }
-
- int q, A, B;
- for (int i = 0; i < TOTAL_SUBKEYS / 2; i++)
- {
- q = i * SK_STEP;
- A = F32(q, k32e);
- B = F32(q + SK_BUMP, k32o);
- B = B << 8 | (int)((uint)B >> 24);
- A += B;
- gSubKeys[i * 2] = A;
- A += B;
- gSubKeys[i * 2 + 1] = A << SK_ROTL | (int)((uint)A >> (32 - SK_ROTL));
- }
-
- /*
- * fully expand the table for speed
- */
- int k0 = sBoxKeys[0];
- int k1 = sBoxKeys[1];
- int k2 = sBoxKeys[2];
- int k3 = sBoxKeys[3];
- int b0, b1, b2, b3;
- gSBox = new int[4 * MAX_KEY_BITS];
- for (int i = 0; i < MAX_KEY_BITS; i++)
- {
- b0 = b1 = b2 = b3 = i;
- switch (k64Cnt & 3)
- {
- case 1:
- gSBox[i * 2] = gMDS0[(P[P_01 * 256 + b0] & 0xff) ^ M_b0(k0)];
- gSBox[i * 2 + 1] = gMDS1[(P[P_11 * 256 + b1] & 0xff) ^ M_b1(k0)];
- gSBox[i * 2 + 0x200] = gMDS2[(P[P_21 * 256 + b2] & 0xff) ^ M_b2(k0)];
- gSBox[i * 2 + 0x201] = gMDS3[(P[P_31 * 256 + b3] & 0xff) ^ M_b3(k0)];
- break;
- case 0: /* 256 bits of key */
- b0 = (P[P_04 * 256 + b0] & 0xff) ^ M_b0(k3);
- b1 = (P[P_14 * 256 + b1] & 0xff) ^ M_b1(k3);
- b2 = (P[P_24 * 256 + b2] & 0xff) ^ M_b2(k3);
- b3 = (P[P_34 * 256 + b3] & 0xff) ^ M_b3(k3);
- goto case 3;
- case 3:
- b0 = (P[P_03 * 256 + b0] & 0xff) ^ M_b0(k2);
- b1 = (P[P_13 * 256 + b1] & 0xff) ^ M_b1(k2);
- b2 = (P[P_23 * 256 + b2] & 0xff) ^ M_b2(k2);
- b3 = (P[P_33 * 256 + b3] & 0xff) ^ M_b3(k2);
- goto case 2;
- case 2:
- gSBox[i * 2] = gMDS0[(P[P_01 * 256 + (P[P_02 * 256 + b0] & 0xff) ^ M_b0(k1)] & 0xff) ^ M_b0(k0)];
- gSBox[i * 2 + 1] = gMDS1[(P[P_11 * 256 + (P[P_12 * 256 + b1] & 0xff) ^ M_b1(k1)] & 0xff) ^ M_b1(k0)];
- gSBox[i * 2 + 0x200] = gMDS2[(P[P_21 * 256 + (P[P_22 * 256 + b2] & 0xff) ^ M_b2(k1)] & 0xff) ^ M_b2(k0)];
- gSBox[i * 2 + 0x201] = gMDS3[(P[P_31 * 256 + (P[P_32 * 256 + b3] & 0xff) ^ M_b3(k1)] & 0xff) ^ M_b3(k0)];
- break;
- }
- }
-
- /*
- * the function exits having setup the gSBox with the
- * input key material.
- */
- }
-
- /*
- * TODO: This can be optimised and made cleaner by combining
- * the functionality in this function and applying it appropriately
- * to the creation of the subkeys during key setup.
- */
- private int F32(int x, int[] k32)
- {
- int b0 = M_b0(x);
- int b1 = M_b1(x);
- int b2 = M_b2(x);
- int b3 = M_b3(x);
- int k0 = k32[0];
- int k1 = k32[1];
- int k2 = k32[2];
- int k3 = k32[3];
-
- int result = 0;
- switch (k64Cnt & 3)
- {
- case 1:
- result = gMDS0[(P[P_01 * 256 + b0] & 0xff) ^ M_b0(k0)] ^
- gMDS1[(P[P_11 * 256 + b1] & 0xff) ^ M_b1(k0)] ^
- gMDS2[(P[P_21 * 256 + b2] & 0xff) ^ M_b2(k0)] ^
- gMDS3[(P[P_31 * 256 + b3] & 0xff) ^ M_b3(k0)];
- break;
- case 0: /* 256 bits of key */
- b0 = (P[P_04 * 256 + b0] & 0xff) ^ M_b0(k3);
- b1 = (P[P_14 * 256 + b1] & 0xff) ^ M_b1(k3);
- b2 = (P[P_24 * 256 + b2] & 0xff) ^ M_b2(k3);
- b3 = (P[P_34 * 256 + b3] & 0xff) ^ M_b3(k3);
- goto case 3;
- case 3:
- b0 = (P[P_03 * 256 + b0] & 0xff) ^ M_b0(k2);
- b1 = (P[P_13 * 256 + b1] & 0xff) ^ M_b1(k2);
- b2 = (P[P_23 * 256 + b2] & 0xff) ^ M_b2(k2);
- b3 = (P[P_33 * 256 + b3] & 0xff) ^ M_b3(k2);
- goto case 2;
- case 2:
- result =
- gMDS0[(P[P_01 * 256 + (P[P_02 * 256 + b0] & 0xff) ^ M_b0(k1)] & 0xff) ^ M_b0(k0)] ^
- gMDS1[(P[P_11 * 256 + (P[P_12 * 256 + b1] & 0xff) ^ M_b1(k1)] & 0xff) ^ M_b1(k0)] ^
- gMDS2[(P[P_21 * 256 + (P[P_22 * 256 + b2] & 0xff) ^ M_b2(k1)] & 0xff) ^ M_b2(k0)] ^
- gMDS3[(P[P_31 * 256 + (P[P_32 * 256 + b3] & 0xff) ^ M_b3(k1)] & 0xff) ^ M_b3(k0)];
- break;
- }
- return result;
- }
-
- /**
- * Use (12, 8) Reed-Solomon code over GF(256) to produce
- * a key S-box 32-bit entity from 2 key material 32-bit
- * entities.
- *
- * @param k0 first 32-bit entity
- * @param k1 second 32-bit entity
- * @return Remainder polynomial Generated using RS code
- */
- private static int RS_MDS_Encode(int k0, int k1)
- {
- int r = k1;
- // shift 1 byte at a time
- r = RS_rem(r);
- r = RS_rem(r);
- r = RS_rem(r);
- r = RS_rem(r);
- r ^= k0;
- r = RS_rem(r);
- r = RS_rem(r);
- r = RS_rem(r);
- r = RS_rem(r);
-
- return r;
- }
-
- /**
- * Reed-Solomon code parameters: (12,8) reversible code:
- *
- *
- * G(x) = x^4 + (a+1/a)x^3 + ax^2 + (a+1/a)x + 1
- *
- * where a = primitive root of field generator 0x14D
- *
- */
- private static int RS_rem(int x)
- {
- int b = (int)(((uint)x >> 24) & 0xff);
- int g2 = ((b << 1) ^
- ((b & 0x80) != 0 ? RS_GF_FDBK : 0)) & 0xff;
- int g3 = ((int)((uint)b >> 1) ^
- ((b & 0x01) != 0 ? (int)((uint)RS_GF_FDBK >> 1) : 0)) ^ g2;
- return ((x << 8) ^ (g3 << 24) ^ (g2 << 16) ^ (g3 << 8) ^ b);
- }
-
- private static int LFSR1(int x)
- {
- return (x >> 1) ^
- (((x & 0x01) != 0) ? GF256_FDBK_2 : 0);
- }
-
- private static int LFSR2(int x)
- {
- return (x >> 2) ^
- (((x & 0x02) != 0) ? GF256_FDBK_2 : 0) ^
- (((x & 0x01) != 0) ? GF256_FDBK_4 : 0);
- }
-
- private static int Mx_X(int x)
- {
- return x ^ LFSR2(x);
- } // 5B
-
- private static int Mx_Y(int x)
- {
- return x ^ LFSR1(x) ^ LFSR2(x);
- } // EF
-
- private static int M_b0(int x)
- {
- return x & 0xff;
- }
-
- private static int M_b1(int x)
- {
- return (int)((uint)x >> 8) & 0xff;
- }
-
- private static int M_b2(int x)
- {
- return (int)((uint)x >> 16) & 0xff;
- }
-
- private static int M_b3(int x)
- {
- return (int)((uint)x >> 24) & 0xff;
- }
-
- private static int Fe32_0(int[] gSBox1, int x)
- {
- return gSBox1[0x000 + 2 * (x & 0xff)] ^
- gSBox1[0x001 + 2 * ((int)((uint)x >> 8) & 0xff)] ^
- gSBox1[0x200 + 2 * ((int)((uint)x >> 16) & 0xff)] ^
- gSBox1[0x201 + 2 * ((int)((uint)x >> 24) & 0xff)];
- }
-
- private static int Fe32_3(int[] gSBox1, int x)
- {
- return gSBox1[0x000 + 2 * ((int)((uint)x >> 24) & 0xff)] ^
- gSBox1[0x001 + 2 * (x & 0xff)] ^
- gSBox1[0x200 + 2 * ((int)((uint)x >> 8) & 0xff)] ^
- gSBox1[0x201 + 2 * ((int)((uint)x >> 16) & 0xff)];
- }
-
- private static int BytesTo32Bits(byte[] b, int p)
- {
- return ((b[p] & 0xff)) |
- ((b[p + 1] & 0xff) << 8) |
- ((b[p + 2] & 0xff) << 16) |
- ((b[p + 3] & 0xff) << 24);
- }
-
- private static void Bits32ToBytes(int inData, byte[] b, int offset)
- {
- b[offset] = (byte)inData;
- b[offset + 1] = (byte)(inData >> 8);
- b[offset + 2] = (byte)(inData >> 16);
- b[offset + 3] = (byte)(inData >> 24);
- }
- }
-}
+using System;
+
+namespace Renci.SshNet.Security.Cryptography.Ciphers
+{
+ ///
+ /// Implements Twofish cipher algorithm
+ ///
+ public sealed class TwofishCipher : BlockCipher
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The key.
+ /// The mode.
+ /// The padding.
+ /// is null.
+ /// Keysize is not valid for this algorithm.
+ public TwofishCipher(byte[] key, CipherMode mode, CipherPadding padding)
+ : base(key, 16, mode, padding)
+ {
+ var keySize = key.Length * 8;
+
+ if (!(keySize == 128 || keySize == 192 || keySize == 256))
+ throw new ArgumentException(string.Format("KeySize '{0}' is not valid for this algorithm.", keySize));
+
+ // TODO: Refactor this algorithm
+
+ // calculate the MDS matrix
+ int[] m1 = new int[2];
+ int[] mX = new int[2];
+ int[] mY = new int[2];
+ int j;
+
+ for (int i = 0; i < MAX_KEY_BITS; i++)
+ {
+ j = P[0 + i] & 0xff;
+ m1[0] = j;
+ mX[0] = Mx_X(j) & 0xff;
+ mY[0] = Mx_Y(j) & 0xff;
+
+ j = P[(1 * 256) + i] & 0xff;
+ m1[1] = j;
+ mX[1] = Mx_X(j) & 0xff;
+ mY[1] = Mx_Y(j) & 0xff;
+
+ gMDS0[i] = m1[P_00] | mX[P_00] << 8 | mY[P_00] << 16 | mY[P_00] << 24;
+
+ gMDS1[i] = mY[P_10] | mY[P_10] << 8 | mX[P_10] << 16 | m1[P_10] << 24;
+
+ gMDS2[i] = mX[P_20] | mY[P_20] << 8 | m1[P_20] << 16 | mY[P_20] << 24;
+
+ gMDS3[i] = mX[P_30] | m1[P_30] << 8 | mY[P_30] << 16 | mX[P_30] << 24;
+ }
+
+ this.k64Cnt = key.Length / 8; // pre-padded ?
+ this.SetKey(key);
+ }
+
+ ///
+ /// Encrypts the specified region of the input byte array and copies the encrypted data to the specified region of the output byte array.
+ ///
+ /// The input data to encrypt.
+ /// The offset into the input byte array from which to begin using data.
+ /// The number of bytes in the input byte array to use as data.
+ /// The output to which to write encrypted data.
+ /// The offset into the output byte array from which to begin writing data.
+ ///
+ /// The number of bytes encrypted.
+ ///
+ public override int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
+ {
+ int x0 = BytesTo32Bits(inputBuffer, inputOffset) ^ gSubKeys[INPUT_WHITEN];
+ int x1 = BytesTo32Bits(inputBuffer, inputOffset + 4) ^ gSubKeys[INPUT_WHITEN + 1];
+ int x2 = BytesTo32Bits(inputBuffer, inputOffset + 8) ^ gSubKeys[INPUT_WHITEN + 2];
+ int x3 = BytesTo32Bits(inputBuffer, inputOffset + 12) ^ gSubKeys[INPUT_WHITEN + 3];
+
+ int k = ROUND_SUBKEYS;
+ int t0, t1;
+ for (int r = 0; r < ROUNDS; r += 2)
+ {
+ t0 = Fe32_0(gSBox, x0);
+ t1 = Fe32_3(gSBox, x1);
+ x2 ^= t0 + t1 + gSubKeys[k++];
+ x2 = (int)((uint)x2 >> 1) | x2 << 31;
+ x3 = (x3 << 1 | (int)((uint)x3 >> 31)) ^ (t0 + 2 * t1 + gSubKeys[k++]);
+
+ t0 = Fe32_0(gSBox, x2);
+ t1 = Fe32_3(gSBox, x3);
+ x0 ^= t0 + t1 + gSubKeys[k++];
+ x0 = (int)((uint)x0 >> 1) | x0 << 31;
+ x1 = (x1 << 1 | (int)((uint)x1 >> 31)) ^ (t0 + 2 * t1 + gSubKeys[k++]);
+ }
+
+ Bits32ToBytes(x2 ^ gSubKeys[OUTPUT_WHITEN], outputBuffer, outputOffset);
+ Bits32ToBytes(x3 ^ gSubKeys[OUTPUT_WHITEN + 1], outputBuffer, outputOffset + 4);
+ Bits32ToBytes(x0 ^ gSubKeys[OUTPUT_WHITEN + 2], outputBuffer, outputOffset + 8);
+ Bits32ToBytes(x1 ^ gSubKeys[OUTPUT_WHITEN + 3], outputBuffer, outputOffset + 12);
+
+ return this.BlockSize;
+ }
+
+ ///
+ /// Decrypts the specified region of the input byte array and copies the decrypted data to the specified region of the output byte array.
+ ///
+ /// The input data to decrypt.
+ /// The offset into the input byte array from which to begin using data.
+ /// The number of bytes in the input byte array to use as data.
+ /// The output to which to write decrypted data.
+ /// The offset into the output byte array from which to begin writing data.
+ ///
+ /// The number of bytes decrypted.
+ ///
+ public override int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
+ {
+ int x2 = BytesTo32Bits(inputBuffer, inputOffset) ^ gSubKeys[OUTPUT_WHITEN];
+ int x3 = BytesTo32Bits(inputBuffer, inputOffset + 4) ^ gSubKeys[OUTPUT_WHITEN + 1];
+ int x0 = BytesTo32Bits(inputBuffer, inputOffset + 8) ^ gSubKeys[OUTPUT_WHITEN + 2];
+ int x1 = BytesTo32Bits(inputBuffer, inputOffset + 12) ^ gSubKeys[OUTPUT_WHITEN + 3];
+
+ int k = ROUND_SUBKEYS + 2 * ROUNDS - 1;
+ int t0, t1;
+ for (int r = 0; r < ROUNDS; r += 2)
+ {
+ t0 = Fe32_0(gSBox, x2);
+ t1 = Fe32_3(gSBox, x3);
+ x1 ^= t0 + 2 * t1 + gSubKeys[k--];
+ x0 = (x0 << 1 | (int)((uint)x0 >> 31)) ^ (t0 + t1 + gSubKeys[k--]);
+ x1 = (int)((uint)x1 >> 1) | x1 << 31;
+
+ t0 = Fe32_0(gSBox, x0);
+ t1 = Fe32_3(gSBox, x1);
+ x3 ^= t0 + 2 * t1 + gSubKeys[k--];
+ x2 = (x2 << 1 | (int)((uint)x2 >> 31)) ^ (t0 + t1 + gSubKeys[k--]);
+ x3 = (int)((uint)x3 >> 1) | x3 << 31;
+ }
+
+ Bits32ToBytes(x0 ^ gSubKeys[INPUT_WHITEN], outputBuffer, outputOffset);
+ Bits32ToBytes(x1 ^ gSubKeys[INPUT_WHITEN + 1], outputBuffer, outputOffset + 4);
+ Bits32ToBytes(x2 ^ gSubKeys[INPUT_WHITEN + 2], outputBuffer, outputOffset + 8);
+ Bits32ToBytes(x3 ^ gSubKeys[INPUT_WHITEN + 3], outputBuffer, outputOffset + 12);
+
+ return this.BlockSize;
+ }
+
+ #region Static Definition Tables
+
+ private static readonly byte[] P = {
+ //{ // p0
+ (byte) 0xA9, (byte) 0x67, (byte) 0xB3, (byte) 0xE8,
+ (byte) 0x04, (byte) 0xFD, (byte) 0xA3, (byte) 0x76,
+ (byte) 0x9A, (byte) 0x92, (byte) 0x80, (byte) 0x78,
+ (byte) 0xE4, (byte) 0xDD, (byte) 0xD1, (byte) 0x38,
+ (byte) 0x0D, (byte) 0xC6, (byte) 0x35, (byte) 0x98,
+ (byte) 0x18, (byte) 0xF7, (byte) 0xEC, (byte) 0x6C,
+ (byte) 0x43, (byte) 0x75, (byte) 0x37, (byte) 0x26,
+ (byte) 0xFA, (byte) 0x13, (byte) 0x94, (byte) 0x48,
+ (byte) 0xF2, (byte) 0xD0, (byte) 0x8B, (byte) 0x30,
+ (byte) 0x84, (byte) 0x54, (byte) 0xDF, (byte) 0x23,
+ (byte) 0x19, (byte) 0x5B, (byte) 0x3D, (byte) 0x59,
+ (byte) 0xF3, (byte) 0xAE, (byte) 0xA2, (byte) 0x82,
+ (byte) 0x63, (byte) 0x01, (byte) 0x83, (byte) 0x2E,
+ (byte) 0xD9, (byte) 0x51, (byte) 0x9B, (byte) 0x7C,
+ (byte) 0xA6, (byte) 0xEB, (byte) 0xA5, (byte) 0xBE,
+ (byte) 0x16, (byte) 0x0C, (byte) 0xE3, (byte) 0x61,
+ (byte) 0xC0, (byte) 0x8C, (byte) 0x3A, (byte) 0xF5,
+ (byte) 0x73, (byte) 0x2C, (byte) 0x25, (byte) 0x0B,
+ (byte) 0xBB, (byte) 0x4E, (byte) 0x89, (byte) 0x6B,
+ (byte) 0x53, (byte) 0x6A, (byte) 0xB4, (byte) 0xF1,
+ (byte) 0xE1, (byte) 0xE6, (byte) 0xBD, (byte) 0x45,
+ (byte) 0xE2, (byte) 0xF4, (byte) 0xB6, (byte) 0x66,
+ (byte) 0xCC, (byte) 0x95, (byte) 0x03, (byte) 0x56,
+ (byte) 0xD4, (byte) 0x1C, (byte) 0x1E, (byte) 0xD7,
+ (byte) 0xFB, (byte) 0xC3, (byte) 0x8E, (byte) 0xB5,
+ (byte) 0xE9, (byte) 0xCF, (byte) 0xBF, (byte) 0xBA,
+ (byte) 0xEA, (byte) 0x77, (byte) 0x39, (byte) 0xAF,
+ (byte) 0x33, (byte) 0xC9, (byte) 0x62, (byte) 0x71,
+ (byte) 0x81, (byte) 0x79, (byte) 0x09, (byte) 0xAD,
+ (byte) 0x24, (byte) 0xCD, (byte) 0xF9, (byte) 0xD8,
+ (byte) 0xE5, (byte) 0xC5, (byte) 0xB9, (byte) 0x4D,
+ (byte) 0x44, (byte) 0x08, (byte) 0x86, (byte) 0xE7,
+ (byte) 0xA1, (byte) 0x1D, (byte) 0xAA, (byte) 0xED,
+ (byte) 0x06, (byte) 0x70, (byte) 0xB2, (byte) 0xD2,
+ (byte) 0x41, (byte) 0x7B, (byte) 0xA0, (byte) 0x11,
+ (byte) 0x31, (byte) 0xC2, (byte) 0x27, (byte) 0x90,
+ (byte) 0x20, (byte) 0xF6, (byte) 0x60, (byte) 0xFF,
+ (byte) 0x96, (byte) 0x5C, (byte) 0xB1, (byte) 0xAB,
+ (byte) 0x9E, (byte) 0x9C, (byte) 0x52, (byte) 0x1B,
+ (byte) 0x5F, (byte) 0x93, (byte) 0x0A, (byte) 0xEF,
+ (byte) 0x91, (byte) 0x85, (byte) 0x49, (byte) 0xEE,
+ (byte) 0x2D, (byte) 0x4F, (byte) 0x8F, (byte) 0x3B,
+ (byte) 0x47, (byte) 0x87, (byte) 0x6D, (byte) 0x46,
+ (byte) 0xD6, (byte) 0x3E, (byte) 0x69, (byte) 0x64,
+ (byte) 0x2A, (byte) 0xCE, (byte) 0xCB, (byte) 0x2F,
+ (byte) 0xFC, (byte) 0x97, (byte) 0x05, (byte) 0x7A,
+ (byte) 0xAC, (byte) 0x7F, (byte) 0xD5, (byte) 0x1A,
+ (byte) 0x4B, (byte) 0x0E, (byte) 0xA7, (byte) 0x5A,
+ (byte) 0x28, (byte) 0x14, (byte) 0x3F, (byte) 0x29,
+ (byte) 0x88, (byte) 0x3C, (byte) 0x4C, (byte) 0x02,
+ (byte) 0xB8, (byte) 0xDA, (byte) 0xB0, (byte) 0x17,
+ (byte) 0x55, (byte) 0x1F, (byte) 0x8A, (byte) 0x7D,
+ (byte) 0x57, (byte) 0xC7, (byte) 0x8D, (byte) 0x74,
+ (byte) 0xB7, (byte) 0xC4, (byte) 0x9F, (byte) 0x72,
+ (byte) 0x7E, (byte) 0x15, (byte) 0x22, (byte) 0x12,
+ (byte) 0x58, (byte) 0x07, (byte) 0x99, (byte) 0x34,
+ (byte) 0x6E, (byte) 0x50, (byte) 0xDE, (byte) 0x68,
+ (byte) 0x65, (byte) 0xBC, (byte) 0xDB, (byte) 0xF8,
+ (byte) 0xC8, (byte) 0xA8, (byte) 0x2B, (byte) 0x40,
+ (byte) 0xDC, (byte) 0xFE, (byte) 0x32, (byte) 0xA4,
+ (byte) 0xCA, (byte) 0x10, (byte) 0x21, (byte) 0xF0,
+ (byte) 0xD3, (byte) 0x5D, (byte) 0x0F, (byte) 0x00,
+ (byte) 0x6F, (byte) 0x9D, (byte) 0x36, (byte) 0x42,
+ (byte) 0x4A, (byte) 0x5E, (byte) 0xC1, (byte) 0xE0,
+ // },
+ //{ // p1
+ (byte) 0x75, (byte) 0xF3, (byte) 0xC6, (byte) 0xF4,
+ (byte) 0xDB, (byte) 0x7B, (byte) 0xFB, (byte) 0xC8,
+ (byte) 0x4A, (byte) 0xD3, (byte) 0xE6, (byte) 0x6B,
+ (byte) 0x45, (byte) 0x7D, (byte) 0xE8, (byte) 0x4B,
+ (byte) 0xD6, (byte) 0x32, (byte) 0xD8, (byte) 0xFD,
+ (byte) 0x37, (byte) 0x71, (byte) 0xF1, (byte) 0xE1,
+ (byte) 0x30, (byte) 0x0F, (byte) 0xF8, (byte) 0x1B,
+ (byte) 0x87, (byte) 0xFA, (byte) 0x06, (byte) 0x3F,
+ (byte) 0x5E, (byte) 0xBA, (byte) 0xAE, (byte) 0x5B,
+ (byte) 0x8A, (byte) 0x00, (byte) 0xBC, (byte) 0x9D,
+ (byte) 0x6D, (byte) 0xC1, (byte) 0xB1, (byte) 0x0E,
+ (byte) 0x80, (byte) 0x5D, (byte) 0xD2, (byte) 0xD5,
+ (byte) 0xA0, (byte) 0x84, (byte) 0x07, (byte) 0x14,
+ (byte) 0xB5, (byte) 0x90, (byte) 0x2C, (byte) 0xA3,
+ (byte) 0xB2, (byte) 0x73, (byte) 0x4C, (byte) 0x54,
+ (byte) 0x92, (byte) 0x74, (byte) 0x36, (byte) 0x51,
+ (byte) 0x38, (byte) 0xB0, (byte) 0xBD, (byte) 0x5A,
+ (byte) 0xFC, (byte) 0x60, (byte) 0x62, (byte) 0x96,
+ (byte) 0x6C, (byte) 0x42, (byte) 0xF7, (byte) 0x10,
+ (byte) 0x7C, (byte) 0x28, (byte) 0x27, (byte) 0x8C,
+ (byte) 0x13, (byte) 0x95, (byte) 0x9C, (byte) 0xC7,
+ (byte) 0x24, (byte) 0x46, (byte) 0x3B, (byte) 0x70,
+ (byte) 0xCA, (byte) 0xE3, (byte) 0x85, (byte) 0xCB,
+ (byte) 0x11, (byte) 0xD0, (byte) 0x93, (byte) 0xB8,
+ (byte) 0xA6, (byte) 0x83, (byte) 0x20, (byte) 0xFF,
+ (byte) 0x9F, (byte) 0x77, (byte) 0xC3, (byte) 0xCC,
+ (byte) 0x03, (byte) 0x6F, (byte) 0x08, (byte) 0xBF,
+ (byte) 0x40, (byte) 0xE7, (byte) 0x2B, (byte) 0xE2,
+ (byte) 0x79, (byte) 0x0C, (byte) 0xAA, (byte) 0x82,
+ (byte) 0x41, (byte) 0x3A, (byte) 0xEA, (byte) 0xB9,
+ (byte) 0xE4, (byte) 0x9A, (byte) 0xA4, (byte) 0x97,
+ (byte) 0x7E, (byte) 0xDA, (byte) 0x7A, (byte) 0x17,
+ (byte) 0x66, (byte) 0x94, (byte) 0xA1, (byte) 0x1D,
+ (byte) 0x3D, (byte) 0xF0, (byte) 0xDE, (byte) 0xB3,
+ (byte) 0x0B, (byte) 0x72, (byte) 0xA7, (byte) 0x1C,
+ (byte) 0xEF, (byte) 0xD1, (byte) 0x53, (byte) 0x3E,
+ (byte) 0x8F, (byte) 0x33, (byte) 0x26, (byte) 0x5F,
+ (byte) 0xEC, (byte) 0x76, (byte) 0x2A, (byte) 0x49,
+ (byte) 0x81, (byte) 0x88, (byte) 0xEE, (byte) 0x21,
+ (byte) 0xC4, (byte) 0x1A, (byte) 0xEB, (byte) 0xD9,
+ (byte) 0xC5, (byte) 0x39, (byte) 0x99, (byte) 0xCD,
+ (byte) 0xAD, (byte) 0x31, (byte) 0x8B, (byte) 0x01,
+ (byte) 0x18, (byte) 0x23, (byte) 0xDD, (byte) 0x1F,
+ (byte) 0x4E, (byte) 0x2D, (byte) 0xF9, (byte) 0x48,
+ (byte) 0x4F, (byte) 0xF2, (byte) 0x65, (byte) 0x8E,
+ (byte) 0x78, (byte) 0x5C, (byte) 0x58, (byte) 0x19,
+ (byte) 0x8D, (byte) 0xE5, (byte) 0x98, (byte) 0x57,
+ (byte) 0x67, (byte) 0x7F, (byte) 0x05, (byte) 0x64,
+ (byte) 0xAF, (byte) 0x63, (byte) 0xB6, (byte) 0xFE,
+ (byte) 0xF5, (byte) 0xB7, (byte) 0x3C, (byte) 0xA5,
+ (byte) 0xCE, (byte) 0xE9, (byte) 0x68, (byte) 0x44,
+ (byte) 0xE0, (byte) 0x4D, (byte) 0x43, (byte) 0x69,
+ (byte) 0x29, (byte) 0x2E, (byte) 0xAC, (byte) 0x15,
+ (byte) 0x59, (byte) 0xA8, (byte) 0x0A, (byte) 0x9E,
+ (byte) 0x6E, (byte) 0x47, (byte) 0xDF, (byte) 0x34,
+ (byte) 0x35, (byte) 0x6A, (byte) 0xCF, (byte) 0xDC,
+ (byte) 0x22, (byte) 0xC9, (byte) 0xC0, (byte) 0x9B,
+ (byte) 0x89, (byte) 0xD4, (byte) 0xED, (byte) 0xAB,
+ (byte) 0x12, (byte) 0xA2, (byte) 0x0D, (byte) 0x52,
+ (byte) 0xBB, (byte) 0x02, (byte) 0x2F, (byte) 0xA9,
+ (byte) 0xD7, (byte) 0x61, (byte) 0x1E, (byte) 0xB4,
+ (byte) 0x50, (byte) 0x04, (byte) 0xF6, (byte) 0xC2,
+ (byte) 0x16, (byte) 0x25, (byte) 0x86, (byte) 0x56,
+ (byte) 0x55, (byte) 0x09, (byte) 0xBE, (byte) 0x91
+ //}
+ };
+
+ #endregion
+
+ /**
+ * Define the fixed p0/p1 permutations used in keyed S-box lookup.
+ * By changing the following constant definitions, the S-boxes will
+ * automatically Get changed in the Twofish engine.
+ */
+ private const int P_00 = 1;
+ private const int P_01 = 0;
+ private const int P_02 = 0;
+ private const int P_03 = P_01 ^ 1;
+ private const int P_04 = 1;
+
+ private const int P_10 = 0;
+ private const int P_11 = 0;
+ private const int P_12 = 1;
+ private const int P_13 = P_11 ^ 1;
+ private const int P_14 = 0;
+
+ private const int P_20 = 1;
+ private const int P_21 = 1;
+ private const int P_22 = 0;
+ private const int P_23 = P_21 ^ 1;
+ private const int P_24 = 0;
+
+ private const int P_30 = 0;
+ private const int P_31 = 1;
+ private const int P_32 = 1;
+ private const int P_33 = P_31 ^ 1;
+ private const int P_34 = 1;
+
+ /* Primitive polynomial for GF(256) */
+ private const int GF256_FDBK = 0x169;
+ private const int GF256_FDBK_2 = GF256_FDBK / 2;
+ private const int GF256_FDBK_4 = GF256_FDBK / 4;
+
+ private const int RS_GF_FDBK = 0x14D; // field generator
+
+ //====================================
+ // Useful constants
+ //====================================
+
+ private const int ROUNDS = 16;
+ private const int MAX_ROUNDS = 16; // bytes = 128 bits
+ private const int MAX_KEY_BITS = 256;
+
+ private const int INPUT_WHITEN = 0;
+ private const int OUTPUT_WHITEN = INPUT_WHITEN + 16 / 4; // 4
+ private const int ROUND_SUBKEYS = OUTPUT_WHITEN + 16 / 4;// 8
+
+ private const int TOTAL_SUBKEYS = ROUND_SUBKEYS + 2 * MAX_ROUNDS;// 40
+
+ private const int SK_STEP = 0x02020202;
+ private const int SK_BUMP = 0x01010101;
+ private const int SK_ROTL = 9;
+
+ private readonly int[] gMDS0 = new int[MAX_KEY_BITS];
+ private readonly int[] gMDS1 = new int[MAX_KEY_BITS];
+ private readonly int[] gMDS2 = new int[MAX_KEY_BITS];
+ private readonly int[] gMDS3 = new int[MAX_KEY_BITS];
+
+ /**
+ * gSubKeys[] and gSBox[] are eventually used in the
+ * encryption and decryption methods.
+ */
+ private int[] gSubKeys;
+ private int[] gSBox;
+
+ private int k64Cnt;
+
+ private void SetKey(byte[] key)
+ {
+ int[] k32e = new int[MAX_KEY_BITS / 64]; // 4
+ int[] k32o = new int[MAX_KEY_BITS / 64]; // 4
+
+ int[] sBoxKeys = new int[MAX_KEY_BITS / 64]; // 4
+ gSubKeys = new int[TOTAL_SUBKEYS];
+
+ if (k64Cnt < 1)
+ {
+ throw new ArgumentException("Key size less than 64 bits");
+ }
+
+ if (k64Cnt > 4)
+ {
+ throw new ArgumentException("Key size larger than 256 bits");
+ }
+
+ /*
+ * k64Cnt is the number of 8 byte blocks (64 chunks)
+ * that are in the input key. The input key is a
+ * maximum of 32 bytes ( 256 bits ), so the range
+ * for k64Cnt is 1..4
+ */
+ for (int i = 0; i < k64Cnt; i++)
+ {
+ var p = i * 8;
+
+ k32e[i] = BytesTo32Bits(key, p);
+ k32o[i] = BytesTo32Bits(key, p + 4);
+
+ sBoxKeys[k64Cnt - 1 - i] = RS_MDS_Encode(k32e[i], k32o[i]);
+ }
+
+ int q, A, B;
+ for (int i = 0; i < TOTAL_SUBKEYS / 2; i++)
+ {
+ q = i * SK_STEP;
+ A = F32(q, k32e);
+ B = F32(q + SK_BUMP, k32o);
+ B = B << 8 | (int)((uint)B >> 24);
+ A += B;
+ gSubKeys[i * 2] = A;
+ A += B;
+ gSubKeys[i * 2 + 1] = A << SK_ROTL | (int)((uint)A >> (32 - SK_ROTL));
+ }
+
+ /*
+ * fully expand the table for speed
+ */
+ int k0 = sBoxKeys[0];
+ int k1 = sBoxKeys[1];
+ int k2 = sBoxKeys[2];
+ int k3 = sBoxKeys[3];
+ int b0, b1, b2, b3;
+ gSBox = new int[4 * MAX_KEY_BITS];
+ for (int i = 0; i < MAX_KEY_BITS; i++)
+ {
+ b0 = b1 = b2 = b3 = i;
+ switch (k64Cnt & 3)
+ {
+ case 1:
+ gSBox[i * 2] = gMDS0[(P[P_01 * 256 + b0] & 0xff) ^ M_b0(k0)];
+ gSBox[i * 2 + 1] = gMDS1[(P[P_11 * 256 + b1] & 0xff) ^ M_b1(k0)];
+ gSBox[i * 2 + 0x200] = gMDS2[(P[P_21 * 256 + b2] & 0xff) ^ M_b2(k0)];
+ gSBox[i * 2 + 0x201] = gMDS3[(P[P_31 * 256 + b3] & 0xff) ^ M_b3(k0)];
+ break;
+ case 0: /* 256 bits of key */
+ b0 = (P[P_04 * 256 + b0] & 0xff) ^ M_b0(k3);
+ b1 = (P[P_14 * 256 + b1] & 0xff) ^ M_b1(k3);
+ b2 = (P[P_24 * 256 + b2] & 0xff) ^ M_b2(k3);
+ b3 = (P[P_34 * 256 + b3] & 0xff) ^ M_b3(k3);
+ goto case 3;
+ case 3:
+ b0 = (P[P_03 * 256 + b0] & 0xff) ^ M_b0(k2);
+ b1 = (P[P_13 * 256 + b1] & 0xff) ^ M_b1(k2);
+ b2 = (P[P_23 * 256 + b2] & 0xff) ^ M_b2(k2);
+ b3 = (P[P_33 * 256 + b3] & 0xff) ^ M_b3(k2);
+ goto case 2;
+ case 2:
+ gSBox[i * 2] = gMDS0[(P[P_01 * 256 + (P[P_02 * 256 + b0] & 0xff) ^ M_b0(k1)] & 0xff) ^ M_b0(k0)];
+ gSBox[i * 2 + 1] = gMDS1[(P[P_11 * 256 + (P[P_12 * 256 + b1] & 0xff) ^ M_b1(k1)] & 0xff) ^ M_b1(k0)];
+ gSBox[i * 2 + 0x200] = gMDS2[(P[P_21 * 256 + (P[P_22 * 256 + b2] & 0xff) ^ M_b2(k1)] & 0xff) ^ M_b2(k0)];
+ gSBox[i * 2 + 0x201] = gMDS3[(P[P_31 * 256 + (P[P_32 * 256 + b3] & 0xff) ^ M_b3(k1)] & 0xff) ^ M_b3(k0)];
+ break;
+ }
+ }
+
+ /*
+ * the function exits having setup the gSBox with the
+ * input key material.
+ */
+ }
+
+ /*
+ * TODO: This can be optimised and made cleaner by combining
+ * the functionality in this function and applying it appropriately
+ * to the creation of the subkeys during key setup.
+ */
+ private int F32(int x, int[] k32)
+ {
+ int b0 = M_b0(x);
+ int b1 = M_b1(x);
+ int b2 = M_b2(x);
+ int b3 = M_b3(x);
+ int k0 = k32[0];
+ int k1 = k32[1];
+ int k2 = k32[2];
+ int k3 = k32[3];
+
+ int result = 0;
+ switch (k64Cnt & 3)
+ {
+ case 1:
+ result = gMDS0[(P[P_01 * 256 + b0] & 0xff) ^ M_b0(k0)] ^
+ gMDS1[(P[P_11 * 256 + b1] & 0xff) ^ M_b1(k0)] ^
+ gMDS2[(P[P_21 * 256 + b2] & 0xff) ^ M_b2(k0)] ^
+ gMDS3[(P[P_31 * 256 + b3] & 0xff) ^ M_b3(k0)];
+ break;
+ case 0: /* 256 bits of key */
+ b0 = (P[P_04 * 256 + b0] & 0xff) ^ M_b0(k3);
+ b1 = (P[P_14 * 256 + b1] & 0xff) ^ M_b1(k3);
+ b2 = (P[P_24 * 256 + b2] & 0xff) ^ M_b2(k3);
+ b3 = (P[P_34 * 256 + b3] & 0xff) ^ M_b3(k3);
+ goto case 3;
+ case 3:
+ b0 = (P[P_03 * 256 + b0] & 0xff) ^ M_b0(k2);
+ b1 = (P[P_13 * 256 + b1] & 0xff) ^ M_b1(k2);
+ b2 = (P[P_23 * 256 + b2] & 0xff) ^ M_b2(k2);
+ b3 = (P[P_33 * 256 + b3] & 0xff) ^ M_b3(k2);
+ goto case 2;
+ case 2:
+ result =
+ gMDS0[(P[P_01 * 256 + (P[P_02 * 256 + b0] & 0xff) ^ M_b0(k1)] & 0xff) ^ M_b0(k0)] ^
+ gMDS1[(P[P_11 * 256 + (P[P_12 * 256 + b1] & 0xff) ^ M_b1(k1)] & 0xff) ^ M_b1(k0)] ^
+ gMDS2[(P[P_21 * 256 + (P[P_22 * 256 + b2] & 0xff) ^ M_b2(k1)] & 0xff) ^ M_b2(k0)] ^
+ gMDS3[(P[P_31 * 256 + (P[P_32 * 256 + b3] & 0xff) ^ M_b3(k1)] & 0xff) ^ M_b3(k0)];
+ break;
+ }
+ return result;
+ }
+
+ /**
+ * Use (12, 8) Reed-Solomon code over GF(256) to produce
+ * a key S-box 32-bit entity from 2 key material 32-bit
+ * entities.
+ *
+ * @param k0 first 32-bit entity
+ * @param k1 second 32-bit entity
+ * @return Remainder polynomial Generated using RS code
+ */
+ private static int RS_MDS_Encode(int k0, int k1)
+ {
+ int r = k1;
+ // shift 1 byte at a time
+ r = RS_rem(r);
+ r = RS_rem(r);
+ r = RS_rem(r);
+ r = RS_rem(r);
+ r ^= k0;
+ r = RS_rem(r);
+ r = RS_rem(r);
+ r = RS_rem(r);
+ r = RS_rem(r);
+
+ return r;
+ }
+
+ /**
+ * Reed-Solomon code parameters: (12,8) reversible code:
+ *
+ *
+ * G(x) = x^4 + (a+1/a)x^3 + ax^2 + (a+1/a)x + 1
+ *
+ * where a = primitive root of field generator 0x14D
+ *
+ */
+ private static int RS_rem(int x)
+ {
+ int b = (int)(((uint)x >> 24) & 0xff);
+ int g2 = ((b << 1) ^
+ ((b & 0x80) != 0 ? RS_GF_FDBK : 0)) & 0xff;
+ int g3 = ((int)((uint)b >> 1) ^
+ ((b & 0x01) != 0 ? (int)((uint)RS_GF_FDBK >> 1) : 0)) ^ g2;
+ return ((x << 8) ^ (g3 << 24) ^ (g2 << 16) ^ (g3 << 8) ^ b);
+ }
+
+ private static int LFSR1(int x)
+ {
+ return (x >> 1) ^
+ (((x & 0x01) != 0) ? GF256_FDBK_2 : 0);
+ }
+
+ private static int LFSR2(int x)
+ {
+ return (x >> 2) ^
+ (((x & 0x02) != 0) ? GF256_FDBK_2 : 0) ^
+ (((x & 0x01) != 0) ? GF256_FDBK_4 : 0);
+ }
+
+ private static int Mx_X(int x)
+ {
+ return x ^ LFSR2(x);
+ } // 5B
+
+ private static int Mx_Y(int x)
+ {
+ return x ^ LFSR1(x) ^ LFSR2(x);
+ } // EF
+
+ private static int M_b0(int x)
+ {
+ return x & 0xff;
+ }
+
+ private static int M_b1(int x)
+ {
+ return (int)((uint)x >> 8) & 0xff;
+ }
+
+ private static int M_b2(int x)
+ {
+ return (int)((uint)x >> 16) & 0xff;
+ }
+
+ private static int M_b3(int x)
+ {
+ return (int)((uint)x >> 24) & 0xff;
+ }
+
+ private static int Fe32_0(int[] gSBox1, int x)
+ {
+ return gSBox1[0x000 + 2 * (x & 0xff)] ^
+ gSBox1[0x001 + 2 * ((int)((uint)x >> 8) & 0xff)] ^
+ gSBox1[0x200 + 2 * ((int)((uint)x >> 16) & 0xff)] ^
+ gSBox1[0x201 + 2 * ((int)((uint)x >> 24) & 0xff)];
+ }
+
+ private static int Fe32_3(int[] gSBox1, int x)
+ {
+ return gSBox1[0x000 + 2 * ((int)((uint)x >> 24) & 0xff)] ^
+ gSBox1[0x001 + 2 * (x & 0xff)] ^
+ gSBox1[0x200 + 2 * ((int)((uint)x >> 8) & 0xff)] ^
+ gSBox1[0x201 + 2 * ((int)((uint)x >> 16) & 0xff)];
+ }
+
+ private static int BytesTo32Bits(byte[] b, int p)
+ {
+ return ((b[p] & 0xff)) |
+ ((b[p + 1] & 0xff) << 8) |
+ ((b[p + 2] & 0xff) << 16) |
+ ((b[p + 3] & 0xff) << 24);
+ }
+
+ private static void Bits32ToBytes(int inData, byte[] b, int offset)
+ {
+ b[offset] = (byte)inData;
+ b[offset + 1] = (byte)(inData >> 8);
+ b[offset + 2] = (byte)(inData >> 16);
+ b[offset + 3] = (byte)(inData >> 24);
+ }
+ }
+}
diff --git a/Renci.SshNet/Security/Cryptography/DigitalSignature.cs b/Renci.SshNet/Security/Cryptography/DigitalSignature.cs
index c49b1c0..e0a4e40 100644
--- a/Renci.SshNet/Security/Cryptography/DigitalSignature.cs
+++ b/Renci.SshNet/Security/Cryptography/DigitalSignature.cs
@@ -1,29 +1,23 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Security.Cryptography;
-
-namespace Renci.SshNet.Security.Cryptography
-{
- ///
- /// Base class for signature implementations
- ///
- public abstract class DigitalSignature
- {
- ///
- /// Verifies the signature.
- ///
- /// The input.
- /// The signature.
- /// True if signature was successfully verified; otherwise false.
- public abstract bool Verify(byte[] input, byte[] signature);
-
- ///
- /// Creates the signature.
- ///
- /// The input.
- /// Signed input data.
- public abstract byte[] Sign(byte[] input);
- }
-}
+namespace Renci.SshNet.Security.Cryptography
+{
+ ///
+ /// Base class for signature implementations
+ ///
+ public abstract class DigitalSignature
+ {
+ ///
+ /// Verifies the signature.
+ ///
+ /// The input.
+ /// The signature.
+ /// True if signature was successfully verified; otherwise false.
+ public abstract bool Verify(byte[] input, byte[] signature);
+
+ ///
+ /// Creates the signature.
+ ///
+ /// The input.
+ /// Signed input data.
+ public abstract byte[] Sign(byte[] input);
+ }
+}
diff --git a/Renci.SshNet/Security/Cryptography/DsaDigitalSignature.cs b/Renci.SshNet/Security/Cryptography/DsaDigitalSignature.cs
index 8e98442..a9b47fc 100644
--- a/Renci.SshNet/Security/Cryptography/DsaDigitalSignature.cs
+++ b/Renci.SshNet/Security/Cryptography/DsaDigitalSignature.cs
@@ -1,200 +1,206 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Security.Cryptography;
-using Renci.SshNet.Common;
-using System.Globalization;
-
-namespace Renci.SshNet.Security.Cryptography
-{
- ///
- /// Implements DSA digital signature algorithm.
- ///
- public class DsaDigitalSignature : DigitalSignature, IDisposable
- {
- private HashAlgorithm _hash;
-
- private DsaKey _key;
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The DSA key.
- /// key
- public DsaDigitalSignature(DsaKey key)
- {
- if (key == null)
- throw new ArgumentNullException("key");
-
- this._key = key;
-
- this._hash = new SHA1Hash();
- }
-
- ///
- /// Verifies the signature.
- ///
- /// The input.
- /// The signature.
- ///
- /// True if signature was successfully verified; otherwise false.
- ///
- /// Invalid signature.
- public override bool Verify(byte[] input, byte[] signature)
- {
- var hashInput = this._hash.ComputeHash(input);
-
- BigInteger hm = new BigInteger(hashInput.Reverse().Concat(new byte[] { 0 }).ToArray());
-
- if (signature.Length != 40)
- throw new InvalidOperationException("Invalid signature.");
-
- // Extract r and s numbers from the signature
- var rBytes = new byte[21];
- var sBytes = new byte[21];
-
- for (int i = 0, j = 20; i < 20; i++, j--)
- {
- rBytes[i] = signature[j - 1];
- sBytes[i] = signature[j + 20 - 1];
- }
-
- BigInteger r = new BigInteger(rBytes);
- BigInteger s = new BigInteger(sBytes);
-
- // Reject the signature if 0 < r < q or 0 < s < q is not satisfied.
- if (r <= 0 || r >= this._key.Q)
- return false;
-
- if (s <= 0 || s >= this._key.Q)
- return false;
-
- // Calculate w = s−1 mod q
- BigInteger w = BigInteger.ModInverse(s, this._key.Q);
-
- // Calculate u1 = H(m)·w mod q
- BigInteger u1 = hm * w % this._key.Q;
-
- // Calculate u2 = r * w mod q
- BigInteger u2 = r * w % this._key.Q;
-
- u1 = BigInteger.ModPow(this._key.G, u1, this._key.P);
- u2 = BigInteger.ModPow(this._key.Y, u2, this._key.P);
-
- // Calculate v = ((g pow u1 * y pow u2) mod p) mod q
- BigInteger v = ((u1 * u2) % this._key.P) % this._key.Q;
-
- // The signature is valid if v = r
- return v == r;
- }
-
- ///
- /// Creates the signature.
- ///
- /// The input.
- ///
- /// Signed input data.
- ///
- /// Invalid DSA key.
- public override byte[] Sign(byte[] input)
- {
- var hashInput = this._hash.ComputeHash(input);
-
- BigInteger m = new BigInteger(hashInput.Reverse().Concat(new byte[] { 0 }).ToArray());
-
- BigInteger s = BigInteger.Zero;
- BigInteger r = BigInteger.Zero;
-
- do
- {
- BigInteger k = BigInteger.Zero;
-
- do
- {
- // Generate a random per-message value k where 0 < k < q
- var bitLength = this._key.Q.BitLength;
-
- if (this._key.Q < BigInteger.Zero)
- throw new SshException("Invalid DSA key.");
-
- while (k <= 0 || k >= this._key.Q)
- {
- k = BigInteger.Random(bitLength);
- }
-
- // Calculate r = ((g pow k) mod p) mod q
- r = BigInteger.ModPow(this._key.G, k, this._key.P) % this._key.Q;
-
- // In the unlikely case that r = 0, start again with a different random k
- } while (r.IsZero);
-
-
- // Calculate s = ((k pow −1)(H(m) + x*r)) mod q
- k = (BigInteger.ModInverse(k, this._key.Q) * (m + this._key.X * r));
-
- s = k % this._key.Q;
-
- // In the unlikely case that s = 0, start again with a different random k
- } while (s.IsZero);
-
- // The signature is (r, s)
- return r.ToByteArray().Reverse().TrimLeadingZero().Concat(s.ToByteArray().Reverse().TrimLeadingZero()).ToArray();
- }
-
- #region IDisposable Members
-
- private bool _isDisposed = false;
-
- ///
- /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged ResourceMessages.
- ///
- public void Dispose()
- {
- Dispose(true);
-
- GC.SuppressFinalize(this);
- }
-
- ///
- /// Releases unmanaged and - optionally - managed resources
- ///
- /// true to release both managed and unmanaged resources; false to release only unmanaged ResourceMessages.
- 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._hash != null)
- {
- this._hash.Clear();
- this._hash = null;
- }
- }
-
- // Note disposing has been done.
- this._isDisposed = true;
- }
- }
-
- ///
- /// Releases unmanaged resources and performs other cleanup operations before the
- /// is reclaimed by garbage collection.
- ///
- ~DsaDigitalSignature()
- {
- // Do not re-create Dispose clean-up code here.
- // Calling Dispose(false) is optimal in terms of
- // readability and maintainability.
- Dispose(false);
- }
-
- #endregion
-
- }
-}
+using System;
+using System.Linq;
+using System.Security.Cryptography;
+using Renci.SshNet.Common;
+
+namespace Renci.SshNet.Security.Cryptography
+{
+ ///
+ /// Implements DSA digital signature algorithm.
+ ///
+ public class DsaDigitalSignature : DigitalSignature, IDisposable
+ {
+ private HashAlgorithm _hash;
+
+ private readonly DsaKey _key;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The DSA key.
+ /// key
+ public DsaDigitalSignature(DsaKey key)
+ {
+ if (key == null)
+ throw new ArgumentNullException("key");
+
+ this._key = key;
+
+ this._hash = new SHA1Hash();
+ }
+
+ ///
+ /// Verifies the signature.
+ ///
+ /// The input.
+ /// The signature.
+ ///
+ /// True if signature was successfully verified; otherwise false.
+ ///
+ /// Invalid signature.
+ public override bool Verify(byte[] input, byte[] signature)
+ {
+ var hashInput = this._hash.ComputeHash(input);
+
+ BigInteger hm = new BigInteger(hashInput.Reverse().Concat(new byte[] { 0 }).ToArray());
+
+ if (signature.Length != 40)
+ throw new InvalidOperationException("Invalid signature.");
+
+ // Extract r and s numbers from the signature
+ var rBytes = new byte[21];
+ var sBytes = new byte[21];
+
+ for (int i = 0, j = 20; i < 20; i++, j--)
+ {
+ rBytes[i] = signature[j - 1];
+ sBytes[i] = signature[j + 20 - 1];
+ }
+
+ BigInteger r = new BigInteger(rBytes);
+ BigInteger s = new BigInteger(sBytes);
+
+ // Reject the signature if 0 < r < q or 0 < s < q is not satisfied.
+ if (r <= 0 || r >= this._key.Q)
+ return false;
+
+ if (s <= 0 || s >= this._key.Q)
+ return false;
+
+ // Calculate w = s−1 mod q
+ BigInteger w = BigInteger.ModInverse(s, this._key.Q);
+
+ // Calculate u1 = H(m)·w mod q
+ BigInteger u1 = hm * w % this._key.Q;
+
+ // Calculate u2 = r * w mod q
+ BigInteger u2 = r * w % this._key.Q;
+
+ u1 = BigInteger.ModPow(this._key.G, u1, this._key.P);
+ u2 = BigInteger.ModPow(this._key.Y, u2, this._key.P);
+
+ // Calculate v = ((g pow u1 * y pow u2) mod p) mod q
+ BigInteger v = ((u1 * u2) % this._key.P) % this._key.Q;
+
+ // The signature is valid if v = r
+ return v == r;
+ }
+
+ ///
+ /// Creates the signature.
+ ///
+ /// The input.
+ ///
+ /// Signed input data.
+ ///
+ /// Invalid DSA key.
+ public override byte[] Sign(byte[] input)
+ {
+ var hashInput = this._hash.ComputeHash(input);
+
+ BigInteger m = new BigInteger(hashInput.Reverse().Concat(new byte[] { 0 }).ToArray());
+
+ BigInteger s;
+ BigInteger r;
+
+ do
+ {
+ BigInteger k = BigInteger.Zero;
+
+ do
+ {
+ // Generate a random per-message value k where 0 < k < q
+ var bitLength = this._key.Q.BitLength;
+
+ if (this._key.Q < BigInteger.Zero)
+ throw new SshException("Invalid DSA key.");
+
+ while (k <= 0 || k >= this._key.Q)
+ {
+ k = BigInteger.Random(bitLength);
+ }
+
+ // Calculate r = ((g pow k) mod p) mod q
+ r = BigInteger.ModPow(this._key.G, k, this._key.P) % this._key.Q;
+
+ // In the unlikely case that r = 0, start again with a different random k
+ } while (r.IsZero);
+
+
+ // Calculate s = ((k pow −1)(H(m) + x*r)) mod q
+ k = (BigInteger.ModInverse(k, this._key.Q) * (m + this._key.X * r));
+
+ s = k % this._key.Q;
+
+ // In the unlikely case that s = 0, start again with a different random k
+ } while (s.IsZero);
+
+ // The signature is (r, s)
+ var signature = new byte[40];
+
+ // issue #1918: pad part with zero's on the left if length is less than 20
+ var rBytes = r.ToByteArray().Reverse().TrimLeadingZero().ToArray();
+ Array.Copy(rBytes, 0, signature, 20 - rBytes.Length, rBytes.Length);
+
+ // issue #1918: pad part with zero's on the left if length is less than 20
+ var sBytes = s.ToByteArray().Reverse().TrimLeadingZero().ToArray();
+ Array.Copy(sBytes, 0, signature, 40 - sBytes.Length, sBytes.Length);
+
+ return signature;
+ }
+
+ #region IDisposable Members
+
+ private bool _isDisposed;
+
+ ///
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged ResourceMessages.
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Releases unmanaged and - optionally - managed resources
+ ///
+ /// true to release both managed and unmanaged resources; false to release only unmanaged ResourceMessages.
+ 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._hash != null)
+ {
+ this._hash.Clear();
+ this._hash = null;
+ }
+ }
+
+ // Note disposing has been done.
+ this._isDisposed = true;
+ }
+ }
+
+ ///
+ /// Releases unmanaged resources and performs other cleanup operations before the
+ /// is reclaimed by garbage collection.
+ ///
+ ~DsaDigitalSignature()
+ {
+ // Do not re-create Dispose clean-up code here.
+ // Calling Dispose(false) is optimal in terms of
+ // readability and maintainability.
+ Dispose(false);
+ }
+
+ #endregion
+ }
+}
diff --git a/Renci.SshNet/Security/Cryptography/DsaKey.cs b/Renci.SshNet/Security/Cryptography/DsaKey.cs
index 5abd074..b8565ae 100644
--- a/Renci.SshNet/Security/Cryptography/DsaKey.cs
+++ b/Renci.SshNet/Security/Cryptography/DsaKey.cs
@@ -1,213 +1,209 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Renci.SshNet.Common;
-using Renci.SshNet.Security.Cryptography;
-
-namespace Renci.SshNet.Security
-{
- ///
- /// Contains DSA private and public key
- ///
- public class DsaKey : Key, IDisposable
- {
- ///
- /// Gets the P.
- ///
- public BigInteger P
- {
- get
- {
- return this._privateKey[0];
- }
- }
-
- ///
- /// Gets the Q.
- ///
- public BigInteger Q
- {
- get
- {
- return this._privateKey[1];
- }
- }
-
- ///
- /// Gets the G.
- ///
- public BigInteger G
- {
- get
- {
- return this._privateKey[2];
- }
- }
-
- ///
- /// Gets public key Y.
- ///
- public BigInteger Y
- {
- get
- {
- return this._privateKey[3];
- }
- }
-
- ///
- /// Gets private key X.
- ///
- public BigInteger X
- {
- get
- {
- return this._privateKey[4];
- }
- }
-
- ///
- /// Gets the length of the key.
- ///
- ///
- /// The length of the key.
- ///
- public override int KeyLength
- {
- get
- {
- return this.P.BitLength;
- }
- }
-
- private DsaDigitalSignature _digitalSignature;
- ///
- /// Gets the digital signature.
- ///
- protected override DigitalSignature DigitalSignature
- {
- get
- {
- if (this._digitalSignature == null)
- {
- this._digitalSignature = new DsaDigitalSignature(this);
- }
- return this._digitalSignature;
- }
- }
-
- ///
- /// Gets or sets the public.
- ///
- ///
- /// The public.
- ///
- public override BigInteger[] Public
- {
- get
- {
- return new BigInteger[] { this.P, this.Q, this.G, this.Y };
- }
- set
- {
- if (value.Length != 4)
- throw new InvalidOperationException("Invalid public key.");
-
- this._privateKey = value;
- }
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- public DsaKey()
- : base()
- {
- this._privateKey = new BigInteger[5];
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// DER encoded private key data.
- public DsaKey(byte[] data)
- : base(data)
- {
- if (this._privateKey.Length != 5)
- throw new InvalidOperationException("Invalid private key.");
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The p.
- /// The q.
- /// The g.
- /// The y.
- /// The x.
- public DsaKey(BigInteger p, BigInteger q, BigInteger g, BigInteger y, BigInteger x)
- {
- this._privateKey = new BigInteger[5];
- this._privateKey[0] = p;
- this._privateKey[1] = q;
- this._privateKey[2] = g;
- this._privateKey[3] = y;
- this._privateKey[4] = x;
- }
-
- #region IDisposable Members
-
- private bool _isDisposed = false;
-
- ///
- /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged ResourceMessages.
- ///
- public void Dispose()
- {
- Dispose(true);
-
- GC.SuppressFinalize(this);
- }
-
- ///
- /// Releases unmanaged and - optionally - managed resources
- ///
- /// true to release both managed and unmanaged resources; false to release only unmanaged ResourceMessages.
- 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._digitalSignature != null)
- {
- this._digitalSignature.Dispose();
- this._digitalSignature = null;
- }
- }
-
- // Note disposing has been done.
- this._isDisposed = true;
- }
- }
-
- ///
- /// Releases unmanaged resources and performs other cleanup operations before the
- /// is reclaimed by garbage collection.
- ///
- ~DsaKey()
- {
- // Do not re-create Dispose clean-up code here.
- // Calling Dispose(false) is optimal in terms of
- // readability and maintainability.
- Dispose(false);
- }
-
- #endregion
- }
-}
+using System;
+using Renci.SshNet.Common;
+using Renci.SshNet.Security.Cryptography;
+
+namespace Renci.SshNet.Security
+{
+ ///
+ /// Contains DSA private and public key
+ ///
+ public class DsaKey : Key, IDisposable
+ {
+ ///
+ /// Gets the P.
+ ///
+ public BigInteger P
+ {
+ get
+ {
+ return this._privateKey[0];
+ }
+ }
+
+ ///
+ /// Gets the Q.
+ ///
+ public BigInteger Q
+ {
+ get
+ {
+ return this._privateKey[1];
+ }
+ }
+
+ ///
+ /// Gets the G.
+ ///
+ public BigInteger G
+ {
+ get
+ {
+ return this._privateKey[2];
+ }
+ }
+
+ ///
+ /// Gets public key Y.
+ ///
+ public BigInteger Y
+ {
+ get
+ {
+ return this._privateKey[3];
+ }
+ }
+
+ ///
+ /// Gets private key X.
+ ///
+ public BigInteger X
+ {
+ get
+ {
+ return this._privateKey[4];
+ }
+ }
+
+ ///
+ /// Gets the length of the key.
+ ///
+ ///
+ /// The length of the key.
+ ///
+ public override int KeyLength
+ {
+ get
+ {
+ return this.P.BitLength;
+ }
+ }
+
+ private DsaDigitalSignature _digitalSignature;
+ ///
+ /// Gets the digital signature.
+ ///
+ protected override DigitalSignature DigitalSignature
+ {
+ get
+ {
+ if (this._digitalSignature == null)
+ {
+ this._digitalSignature = new DsaDigitalSignature(this);
+ }
+ return this._digitalSignature;
+ }
+ }
+
+ ///
+ /// Gets or sets the public.
+ ///
+ ///
+ /// The public.
+ ///
+ public override BigInteger[] Public
+ {
+ get
+ {
+ return new BigInteger[] { this.P, this.Q, this.G, this.Y };
+ }
+ set
+ {
+ if (value.Length != 4)
+ throw new InvalidOperationException("Invalid public key.");
+
+ this._privateKey = value;
+ }
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public DsaKey()
+ {
+ this._privateKey = new BigInteger[5];
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// DER encoded private key data.
+ public DsaKey(byte[] data)
+ : base(data)
+ {
+ if (this._privateKey.Length != 5)
+ throw new InvalidOperationException("Invalid private key.");
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The p.
+ /// The q.
+ /// The g.
+ /// The y.
+ /// The x.
+ public DsaKey(BigInteger p, BigInteger q, BigInteger g, BigInteger y, BigInteger x)
+ {
+ this._privateKey = new BigInteger[5];
+ this._privateKey[0] = p;
+ this._privateKey[1] = q;
+ this._privateKey[2] = g;
+ this._privateKey[3] = y;
+ this._privateKey[4] = x;
+ }
+
+ #region IDisposable Members
+
+ private bool _isDisposed;
+
+ ///
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged ResourceMessages.
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Releases unmanaged and - optionally - managed resources
+ ///
+ /// true to release both managed and unmanaged resources; false to release only unmanaged ResourceMessages.
+ 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._digitalSignature != null)
+ {
+ this._digitalSignature.Dispose();
+ this._digitalSignature = null;
+ }
+ }
+
+ // Note disposing has been done.
+ this._isDisposed = true;
+ }
+ }
+
+ ///
+ /// Releases unmanaged resources and performs other cleanup operations before the
+ /// is reclaimed by garbage collection.
+ ///
+ ~DsaKey()
+ {
+ // Do not re-create Dispose clean-up code here.
+ // Calling Dispose(false) is optimal in terms of
+ // readability and maintainability.
+ Dispose(false);
+ }
+
+ #endregion
+ }
+}
diff --git a/Renci.SshNet/Security/Cryptography/HMAC.cs b/Renci.SshNet/Security/Cryptography/HMAC.cs
index c93131c..e5941f6 100644
--- a/Renci.SshNet/Security/Cryptography/HMAC.cs
+++ b/Renci.SshNet/Security/Cryptography/HMAC.cs
@@ -1,170 +1,171 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Security.Cryptography;
-
-namespace Renci.SshNet.Security.Cryptography
-{
- ///
- /// Provides HMAC algorithm implementation.
- ///
- /// Class that implements .
- public class HMac : KeyedHashAlgorithm where T : HashAlgorithm, new()
- {
- private HashAlgorithm _hash;
- //private bool _isHashing;
- private byte[] _innerPadding;
- private byte[] _outerPadding;
-
- ///
- /// Gets the size of the block.
- ///
- ///
- /// The size of the block.
- ///
- protected int BlockSize
- {
- get
- {
- return this._hash.InputBlockSize;
- }
- }
-
- private HMac()
- {
- // Create the hash algorithms.
- this._hash = new T();
- this.HashSizeValue = this._hash.HashSize;
- }
-
- ///
- /// Rfc 2104.
- ///
- /// The key.
- public HMac(byte[] key, int hashSizeValue)
- : this(key)
- {
- this.HashSizeValue = hashSizeValue;
- }
-
- public HMac(byte[] key)
- : this()
- {
- base.KeyValue = key;
-
- this.InternalInitialize();
- }
-
-
- ///
- /// Gets or sets the key to use in the hash algorithm.
- ///
- /// The key to use in the hash algorithm.
- public override byte[] Key
- {
- get
- {
- return (byte[])base.KeyValue.Clone();
- }
- set
- {
- this.SetKey(value);
- }
- }
-
- ///
- /// Initializes an implementation of the class.
- ///
- public override void Initialize()
- {
- this.InternalInitialize();
- }
-
- ///
- /// Hashes the core.
- ///
- /// The RGB.
- /// The ib.
- /// The cb.
- protected override void HashCore(byte[] rgb, int ib, int cb)
- {
- this._hash.TransformBlock(rgb, ib, cb, rgb, ib);
- }
-
- ///
- /// Finalizes the hash computation after the last data is processed by the cryptographic stream object.
- ///
- ///
- /// The computed hash code.
- ///
- protected override byte[] HashFinal()
- {
- // Finalize the original hash.
- this._hash.TransformFinalBlock(new byte[0], 0, 0);
-
- var hashValue = this._hash.Hash;
-
- // Write the outer array.
- this._hash.TransformBlock(this._outerPadding, 0, this.BlockSize, this._outerPadding, 0);
-
- // Write the inner hash and finalize the hash.
- this._hash.TransformFinalBlock(hashValue, 0, hashValue.Length);
-
- return this._hash.Hash.Take(this.HashSize / 8).ToArray();
- }
-
- private void InternalInitialize()
- {
- this.SetKey(base.KeyValue);
- }
-
- private void SetKey(byte[] value)
- {
- this._hash.Initialize();
-
- if (value.Length > this.BlockSize)
- {
- this.KeyValue = this._hash.ComputeHash(value);
- // No need to call Initialize, ComputeHash does it automatically.
- }
- else
- {
- this.KeyValue = value.Clone() as byte[];
- }
-
- this._innerPadding = new byte[this.BlockSize];
- this._outerPadding = new byte[this.BlockSize];
-
- // Compute inner and outer padding.
- int i = 0;
- for (i = 0; i < this.KeyValue.Length; i++)
- {
- this._innerPadding[i] = (byte)(0x36 ^ this.KeyValue[i]);
- this._outerPadding[i] = (byte)(0x5C ^ this.KeyValue[i]);
- }
- for (i = this.KeyValue.Length; i < this.BlockSize; i++)
- {
- this._innerPadding[i] = 0x36;
- this._outerPadding[i] = 0x5C;
- }
-
- this._hash.TransformBlock(this._innerPadding, 0, this.BlockSize, this._innerPadding, 0);
- }
-
- ///
- /// Releases unmanaged and - optionally - managed resources
- ///
- /// true to release both managed and unmanaged resources; false to release only unmanaged ResourceMessages.
- protected override void Dispose(bool disposing)
- {
- base.Dispose(disposing);
-
- if (this._hash != null)
- {
- this._hash.Clear();
- this._hash = null;
- }
- }
- }
-}
+using System.Linq;
+using System.Security.Cryptography;
+
+namespace Renci.SshNet.Security.Cryptography
+{
+ ///
+ /// Provides HMAC algorithm implementation.
+ ///
+ /// Class that implements .
+ public class HMac : KeyedHashAlgorithm where T : HashAlgorithm, new()
+ {
+ private HashAlgorithm _hash;
+ //private bool _isHashing;
+ private byte[] _innerPadding;
+ private byte[] _outerPadding;
+
+ ///
+ /// Gets the size of the block.
+ ///
+ ///
+ /// The size of the block.
+ ///
+ protected int BlockSize
+ {
+ get
+ {
+ return this._hash.InputBlockSize;
+ }
+ }
+
+ private HMac()
+ {
+ // Create the hash algorithms.
+ this._hash = new T();
+ this.HashSizeValue = this._hash.HashSize;
+ }
+
+ ///
+ /// Rfc 2104.
+ ///
+ /// The key.
+ /// The size, in bits, of the computed hash code.
+ public HMac(byte[] key, int hashSizeValue)
+ : this(key)
+ {
+ this.HashSizeValue = hashSizeValue;
+ }
+
+ ///
+ /// Rfc 2104.
+ ///
+ /// The key.
+ public HMac(byte[] key)
+ : this()
+ {
+ base.KeyValue = key;
+
+ this.InternalInitialize();
+ }
+
+
+ ///
+ /// Gets or sets the key to use in the hash algorithm.
+ ///
+ /// The key to use in the hash algorithm.
+ public override byte[] Key
+ {
+ get
+ {
+ return (byte[])base.KeyValue.Clone();
+ }
+ set
+ {
+ this.SetKey(value);
+ }
+ }
+
+ ///
+ /// Initializes an implementation of the class.
+ ///
+ public override void Initialize()
+ {
+ this.InternalInitialize();
+ }
+
+ ///
+ /// Hashes the core.
+ ///
+ /// The RGB.
+ /// The ib.
+ /// The cb.
+ protected override void HashCore(byte[] rgb, int ib, int cb)
+ {
+ this._hash.TransformBlock(rgb, ib, cb, rgb, ib);
+ }
+
+ ///
+ /// Finalizes the hash computation after the last data is processed by the cryptographic stream object.
+ ///
+ ///
+ /// The computed hash code.
+ ///
+ protected override byte[] HashFinal()
+ {
+ // Finalize the original hash.
+ this._hash.TransformFinalBlock(new byte[0], 0, 0);
+
+ var hashValue = this._hash.Hash;
+
+ // Write the outer array.
+ this._hash.TransformBlock(this._outerPadding, 0, this.BlockSize, this._outerPadding, 0);
+
+ // Write the inner hash and finalize the hash.
+ this._hash.TransformFinalBlock(hashValue, 0, hashValue.Length);
+
+ return this._hash.Hash.Take(this.HashSize / 8).ToArray();
+ }
+
+ private void InternalInitialize()
+ {
+ this.SetKey(base.KeyValue);
+ }
+
+ private void SetKey(byte[] value)
+ {
+ this._hash.Initialize();
+
+ if (value.Length > this.BlockSize)
+ {
+ this.KeyValue = this._hash.ComputeHash(value);
+ // No need to call Initialize, ComputeHash does it automatically.
+ }
+ else
+ {
+ this.KeyValue = (byte[]) value.Clone();
+ }
+
+ this._innerPadding = new byte[this.BlockSize];
+ this._outerPadding = new byte[this.BlockSize];
+
+ // Compute inner and outer padding.
+ for (var i = 0; i < this.KeyValue.Length; i++)
+ {
+ this._innerPadding[i] = (byte)(0x36 ^ this.KeyValue[i]);
+ this._outerPadding[i] = (byte)(0x5C ^ this.KeyValue[i]);
+ }
+ for (var i = this.KeyValue.Length; i < this.BlockSize; i++)
+ {
+ this._innerPadding[i] = 0x36;
+ this._outerPadding[i] = 0x5C;
+ }
+
+ this._hash.TransformBlock(this._innerPadding, 0, this.BlockSize, this._innerPadding, 0);
+ }
+
+ ///
+ /// Releases unmanaged and - optionally - managed resources
+ ///
+ /// true to release both managed and unmanaged resources; false to release only unmanaged ResourceMessages.
+ protected override void Dispose(bool disposing)
+ {
+ base.Dispose(disposing);
+
+ if (this._hash != null)
+ {
+ this._hash.Clear();
+ this._hash = null;
+ }
+ }
+ }
+}
diff --git a/Renci.SshNet/Security/Cryptography/Hashes/MD5Hash.cs b/Renci.SshNet/Security/Cryptography/Hashes/MD5Hash.cs
index 48f103c..95dfb12 100644
--- a/Renci.SshNet/Security/Cryptography/Hashes/MD5Hash.cs
+++ b/Renci.SshNet/Security/Cryptography/Hashes/MD5Hash.cs
@@ -1,390 +1,385 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Security.Cryptography;
-
-namespace Renci.SshNet.Security.Cryptography
-{
- ///
- /// MD5 algorithm implementation
- ///
- public sealed class MD5Hash : HashAlgorithm
- {
- private byte[] _buffer = new byte[4];
- private int _bufferOffset;
- private long _byteCount;
- private int H1, H2, H3, H4; // IV's
- private int[] _hashValue = new int[16];
- private int _offset;
-
- ///
- /// Gets the size, in bits, of the computed hash code.
- ///
- /// The size, in bits, of the computed hash code.
- public override int HashSize
- {
- get
- {
- return 128;
- }
- }
-
- ///
- /// Gets the input block size.
- ///
- /// The input block size.
- public override int InputBlockSize
- {
- get
- {
- return 64;
- }
- }
-
- ///
- /// Gets the output block size.
- ///
- /// The output block size.
- public override int OutputBlockSize
- {
- get
- {
- return 64;
- }
- }
-
- ///
- /// Gets a value indicating whether the current transform can be reused.
- ///
- /// Always true.
- public override bool CanReuseTransform
- {
- get
- {
- return true;
- }
- }
-
- ///
- /// Gets a value indicating whether multiple blocks can be transformed.
- ///
- /// true if multiple blocks can be transformed; otherwise, false.
- public override bool CanTransformMultipleBlocks
- {
- get
- {
- return true;
- }
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- public MD5Hash()
- {
- this.InternalInitialize();
- }
-
- ///
- /// Routes data written to the object into the hash algorithm for computing the hash.
- ///
- /// The input to compute the hash code for.
- /// The offset into the byte array from which to begin using data.
- /// The number of bytes in the byte array to use as data.
- protected override void HashCore(byte[] array, int ibStart, int cbSize)
- {
- // Fill the current word
- while ((this._bufferOffset != 0) && (cbSize > 0))
- {
- this.Update(array[ibStart]);
- ibStart++;
- cbSize--;
- }
-
- // Process whole words.
- while (cbSize > this._buffer.Length)
- {
- this.ProcessWord(array, ibStart);
-
- ibStart += this._buffer.Length;
- cbSize -= this._buffer.Length;
- this._byteCount += this._buffer.Length;
- }
-
- // Load in the remainder.
- while (cbSize > 0)
- {
- this.Update(array[ibStart]);
-
- ibStart++;
- cbSize--;
- }
- }
-
- ///
- /// Finalizes the hash computation after the last data is processed by the cryptographic stream object.
- ///
- ///
- /// The computed hash code.
- ///
- protected override byte[] HashFinal()
- {
- long bitLength = (this._byteCount << 3);
-
- // Add the pad bytes.
- this.Update((byte)128);
-
- while (this._bufferOffset != 0)
- this.Update((byte)0);
-
- if (this._offset > 14)
- {
- this.ProcessBlock();
- }
-
- this._hashValue[14] = (int)(bitLength & 0xffffffff);
- this._hashValue[15] = (int)((ulong)bitLength >> 32);
-
- this.ProcessBlock();
-
- var output = new byte[16];
-
- this.UnpackWord(H1, output, 0);
- this.UnpackWord(H2, output, 0 + 4);
- this.UnpackWord(H3, output, 0 + 8);
- this.UnpackWord(H4, output, 0 + 12);
-
- this.Initialize();
-
- return output;
- }
-
- ///
- /// Initializes an implementation of the class.
- ///
- public override void Initialize()
- {
- this.InternalInitialize();
- }
-
- private void InternalInitialize()
- {
- var i = 0;
- this._byteCount = 0;
- this._bufferOffset = 0;
- for (i = 0; i < 4; i++)
- {
- this._buffer[i] = 0;
- }
-
- H1 = unchecked((int)0x67452301);
- H2 = unchecked((int)0xefcdab89);
- H3 = unchecked((int)0x98badcfe);
- H4 = unchecked((int)0x10325476);
-
- this._offset = 0;
- for (i = 0; i != this._hashValue.Length; i++)
- {
- this._hashValue[i] = 0;
- }
- }
-
- private void Update(byte input)
- {
- this._buffer[this._bufferOffset++] = input;
-
- if (this._bufferOffset == this._buffer.Length)
- {
- this.ProcessWord(this._buffer, 0);
- this._bufferOffset = 0;
- }
-
- this._byteCount++;
- }
-
- private void ProcessWord(byte[] input, int inOff)
- {
- this._hashValue[this._offset++] = (input[inOff] & 0xff) | ((input[inOff + 1] & 0xff) << 8)
- | ((input[inOff + 2] & 0xff) << 16) | ((input[inOff + 3] & 0xff) << 24);
-
- if (this._offset == 16)
- {
- ProcessBlock();
- }
- }
-
- private void UnpackWord(int word, byte[] outBytes, int outOff)
- {
- outBytes[outOff] = (byte)word;
- outBytes[outOff + 1] = (byte)((uint)word >> 8);
- outBytes[outOff + 2] = (byte)((uint)word >> 16);
- outBytes[outOff + 3] = (byte)((uint)word >> 24);
- }
-
- //
- // round 1 left rotates
- //
- private static readonly int S11 = 7;
- private static readonly int S12 = 12;
- private static readonly int S13 = 17;
- private static readonly int S14 = 22;
-
- //
- // round 2 left rotates
- //
- private static readonly int S21 = 5;
- private static readonly int S22 = 9;
- private static readonly int S23 = 14;
- private static readonly int S24 = 20;
-
- //
- // round 3 left rotates
- //
- private static readonly int S31 = 4;
- private static readonly int S32 = 11;
- private static readonly int S33 = 16;
- private static readonly int S34 = 23;
-
- //
- // round 4 left rotates
- //
- private static readonly int S41 = 6;
- private static readonly int S42 = 10;
- private static readonly int S43 = 15;
- private static readonly int S44 = 21;
-
- /*
- * rotate int x left n bits.
- */
- private static int RotateLeft(int x, int n)
- {
- return (x << n) | (int)((uint)x >> (32 - n));
- }
-
- /*
- * F, G, H and I are the basic MD5 functions.
- */
- private static int F(int u, int v, int w)
- {
- return (u & v) | (~u & w);
- }
-
- private static int G(int u, int v, int w)
- {
- return (u & w) | (v & ~w);
- }
-
- private static int H(int u, int v, int w)
- {
- return u ^ v ^ w;
- }
-
- private static int K(int u, int v, int w)
- {
- return v ^ (u | ~w);
- }
-
- private void ProcessBlock()
- {
- int a = H1;
- int b = H2;
- int c = H3;
- int d = H4;
-
- //
- // Round 1 - F cycle, 16 times.
- //
- a = RotateLeft((a + F(b, c, d) + this._hashValue[0] + unchecked((int)0xd76aa478)), S11) + b;
- d = RotateLeft((d + F(a, b, c) + this._hashValue[1] + unchecked((int)0xe8c7b756)), S12) + a;
- c = RotateLeft((c + F(d, a, b) + this._hashValue[2] + unchecked((int)0x242070db)), S13) + d;
- b = RotateLeft((b + F(c, d, a) + this._hashValue[3] + unchecked((int)0xc1bdceee)), S14) + c;
- a = RotateLeft((a + F(b, c, d) + this._hashValue[4] + unchecked((int)0xf57c0faf)), S11) + b;
- d = RotateLeft((d + F(a, b, c) + this._hashValue[5] + unchecked((int)0x4787c62a)), S12) + a;
- c = RotateLeft((c + F(d, a, b) + this._hashValue[6] + unchecked((int)0xa8304613)), S13) + d;
- b = RotateLeft((b + F(c, d, a) + this._hashValue[7] + unchecked((int)0xfd469501)), S14) + c;
- a = RotateLeft((a + F(b, c, d) + this._hashValue[8] + unchecked((int)0x698098d8)), S11) + b;
- d = RotateLeft((d + F(a, b, c) + this._hashValue[9] + unchecked((int)0x8b44f7af)), S12) + a;
- c = RotateLeft((c + F(d, a, b) + this._hashValue[10] + unchecked((int)0xffff5bb1)), S13) + d;
- b = RotateLeft((b + F(c, d, a) + this._hashValue[11] + unchecked((int)0x895cd7be)), S14) + c;
- a = RotateLeft((a + F(b, c, d) + this._hashValue[12] + unchecked((int)0x6b901122)), S11) + b;
- d = RotateLeft((d + F(a, b, c) + this._hashValue[13] + unchecked((int)0xfd987193)), S12) + a;
- c = RotateLeft((c + F(d, a, b) + this._hashValue[14] + unchecked((int)0xa679438e)), S13) + d;
- b = RotateLeft((b + F(c, d, a) + this._hashValue[15] + unchecked((int)0x49b40821)), S14) + c;
-
- //
- // Round 2 - G cycle, 16 times.
- //
- a = RotateLeft((a + G(b, c, d) + this._hashValue[1] + unchecked((int)0xf61e2562)), S21) + b;
- d = RotateLeft((d + G(a, b, c) + this._hashValue[6] + unchecked((int)0xc040b340)), S22) + a;
- c = RotateLeft((c + G(d, a, b) + this._hashValue[11] + unchecked((int)0x265e5a51)), S23) + d;
- b = RotateLeft((b + G(c, d, a) + this._hashValue[0] + unchecked((int)0xe9b6c7aa)), S24) + c;
- a = RotateLeft((a + G(b, c, d) + this._hashValue[5] + unchecked((int)0xd62f105d)), S21) + b;
- d = RotateLeft((d + G(a, b, c) + this._hashValue[10] + unchecked((int)0x02441453)), S22) + a;
- c = RotateLeft((c + G(d, a, b) + this._hashValue[15] + unchecked((int)0xd8a1e681)), S23) + d;
- b = RotateLeft((b + G(c, d, a) + this._hashValue[4] + unchecked((int)0xe7d3fbc8)), S24) + c;
- a = RotateLeft((a + G(b, c, d) + this._hashValue[9] + unchecked((int)0x21e1cde6)), S21) + b;
- d = RotateLeft((d + G(a, b, c) + this._hashValue[14] + unchecked((int)0xc33707d6)), S22) + a;
- c = RotateLeft((c + G(d, a, b) + this._hashValue[3] + unchecked((int)0xf4d50d87)), S23) + d;
- b = RotateLeft((b + G(c, d, a) + this._hashValue[8] + unchecked((int)0x455a14ed)), S24) + c;
- a = RotateLeft((a + G(b, c, d) + this._hashValue[13] + unchecked((int)0xa9e3e905)), S21) + b;
- d = RotateLeft((d + G(a, b, c) + this._hashValue[2] + unchecked((int)0xfcefa3f8)), S22) + a;
- c = RotateLeft((c + G(d, a, b) + this._hashValue[7] + unchecked((int)0x676f02d9)), S23) + d;
- b = RotateLeft((b + G(c, d, a) + this._hashValue[12] + unchecked((int)0x8d2a4c8a)), S24) + c;
-
- //
- // Round 3 - H cycle, 16 times.
- //
- a = RotateLeft((a + H(b, c, d) + this._hashValue[5] + unchecked((int)0xfffa3942)), S31) + b;
- d = RotateLeft((d + H(a, b, c) + this._hashValue[8] + unchecked((int)0x8771f681)), S32) + a;
- c = RotateLeft((c + H(d, a, b) + this._hashValue[11] + unchecked((int)0x6d9d6122)), S33) + d;
- b = RotateLeft((b + H(c, d, a) + this._hashValue[14] + unchecked((int)0xfde5380c)), S34) + c;
- a = RotateLeft((a + H(b, c, d) + this._hashValue[1] + unchecked((int)0xa4beea44)), S31) + b;
- d = RotateLeft((d + H(a, b, c) + this._hashValue[4] + unchecked((int)0x4bdecfa9)), S32) + a;
- c = RotateLeft((c + H(d, a, b) + this._hashValue[7] + unchecked((int)0xf6bb4b60)), S33) + d;
- b = RotateLeft((b + H(c, d, a) + this._hashValue[10] + unchecked((int)0xbebfbc70)), S34) + c;
- a = RotateLeft((a + H(b, c, d) + this._hashValue[13] + unchecked((int)0x289b7ec6)), S31) + b;
- d = RotateLeft((d + H(a, b, c) + this._hashValue[0] + unchecked((int)0xeaa127fa)), S32) + a;
- c = RotateLeft((c + H(d, a, b) + this._hashValue[3] + unchecked((int)0xd4ef3085)), S33) + d;
- b = RotateLeft((b + H(c, d, a) + this._hashValue[6] + unchecked((int)0x04881d05)), S34) + c;
- a = RotateLeft((a + H(b, c, d) + this._hashValue[9] + unchecked((int)0xd9d4d039)), S31) + b;
- d = RotateLeft((d + H(a, b, c) + this._hashValue[12] + unchecked((int)0xe6db99e5)), S32) + a;
- c = RotateLeft((c + H(d, a, b) + this._hashValue[15] + unchecked((int)0x1fa27cf8)), S33) + d;
- b = RotateLeft((b + H(c, d, a) + this._hashValue[2] + unchecked((int)0xc4ac5665)), S34) + c;
-
- //
- // Round 4 - K cycle, 16 times.
- //
- a = RotateLeft((a + K(b, c, d) + this._hashValue[0] + unchecked((int)0xf4292244)), S41) + b;
- d = RotateLeft((d + K(a, b, c) + this._hashValue[7] + unchecked((int)0x432aff97)), S42) + a;
- c = RotateLeft((c + K(d, a, b) + this._hashValue[14] + unchecked((int)0xab9423a7)), S43) + d;
- b = RotateLeft((b + K(c, d, a) + this._hashValue[5] + unchecked((int)0xfc93a039)), S44) + c;
- a = RotateLeft((a + K(b, c, d) + this._hashValue[12] + unchecked((int)0x655b59c3)), S41) + b;
- d = RotateLeft((d + K(a, b, c) + this._hashValue[3] + unchecked((int)0x8f0ccc92)), S42) + a;
- c = RotateLeft((c + K(d, a, b) + this._hashValue[10] + unchecked((int)0xffeff47d)), S43) + d;
- b = RotateLeft((b + K(c, d, a) + this._hashValue[1] + unchecked((int)0x85845dd1)), S44) + c;
- a = RotateLeft((a + K(b, c, d) + this._hashValue[8] + unchecked((int)0x6fa87e4f)), S41) + b;
- d = RotateLeft((d + K(a, b, c) + this._hashValue[15] + unchecked((int)0xfe2ce6e0)), S42) + a;
- c = RotateLeft((c + K(d, a, b) + this._hashValue[6] + unchecked((int)0xa3014314)), S43) + d;
- b = RotateLeft((b + K(c, d, a) + this._hashValue[13] + unchecked((int)0x4e0811a1)), S44) + c;
- a = RotateLeft((a + K(b, c, d) + this._hashValue[4] + unchecked((int)0xf7537e82)), S41) + b;
- d = RotateLeft((d + K(a, b, c) + this._hashValue[11] + unchecked((int)0xbd3af235)), S42) + a;
- c = RotateLeft((c + K(d, a, b) + this._hashValue[2] + unchecked((int)0x2ad7d2bb)), S43) + d;
- b = RotateLeft((b + K(c, d, a) + this._hashValue[9] + unchecked((int)0xeb86d391)), S44) + c;
-
- H1 += a;
- H2 += b;
- H3 += c;
- H4 += d;
-
- //
- // reset the offset and clean out the word buffer.
- //
- this._offset = 0;
- for (int i = 0; i != this._hashValue.Length; i++)
- {
- this._hashValue[i] = 0;
- }
- }
- }
-}
+using System.Security.Cryptography;
+
+namespace Renci.SshNet.Security.Cryptography
+{
+ ///
+ /// MD5 algorithm implementation
+ ///
+ public sealed class MD5Hash : HashAlgorithm
+ {
+ private readonly byte[] _buffer = new byte[4];
+ private int _bufferOffset;
+ private long _byteCount;
+ private int H1, H2, H3, H4; // IV's
+ private readonly int[] _hashValue = new int[16];
+ private int _offset;
+
+ ///
+ /// Gets the size, in bits, of the computed hash code.
+ ///
+ /// The size, in bits, of the computed hash code.
+ public override int HashSize
+ {
+ get
+ {
+ return 128;
+ }
+ }
+
+ ///
+ /// Gets the input block size.
+ ///
+ /// The input block size.
+ public override int InputBlockSize
+ {
+ get
+ {
+ return 64;
+ }
+ }
+
+ ///
+ /// Gets the output block size.
+ ///
+ /// The output block size.
+ public override int OutputBlockSize
+ {
+ get
+ {
+ return 64;
+ }
+ }
+
+ ///
+ /// Gets a value indicating whether the current transform can be reused.
+ ///
+ /// Always true.
+ public override bool CanReuseTransform
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ ///
+ /// Gets a value indicating whether multiple blocks can be transformed.
+ ///
+ /// true if multiple blocks can be transformed; otherwise, false.
+ public override bool CanTransformMultipleBlocks
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public MD5Hash()
+ {
+ this.InternalInitialize();
+ }
+
+ ///
+ /// Routes data written to the object into the hash algorithm for computing the hash.
+ ///
+ /// The input to compute the hash code for.
+ /// The offset into the byte array from which to begin using data.
+ /// The number of bytes in the byte array to use as data.
+ protected override void HashCore(byte[] array, int ibStart, int cbSize)
+ {
+ // Fill the current word
+ while ((this._bufferOffset != 0) && (cbSize > 0))
+ {
+ this.Update(array[ibStart]);
+ ibStart++;
+ cbSize--;
+ }
+
+ // Process whole words.
+ while (cbSize > this._buffer.Length)
+ {
+ this.ProcessWord(array, ibStart);
+
+ ibStart += this._buffer.Length;
+ cbSize -= this._buffer.Length;
+ this._byteCount += this._buffer.Length;
+ }
+
+ // Load in the remainder.
+ while (cbSize > 0)
+ {
+ this.Update(array[ibStart]);
+
+ ibStart++;
+ cbSize--;
+ }
+ }
+
+ ///
+ /// Finalizes the hash computation after the last data is processed by the cryptographic stream object.
+ ///
+ ///
+ /// The computed hash code.
+ ///
+ protected override byte[] HashFinal()
+ {
+ long bitLength = (this._byteCount << 3);
+
+ // Add the pad bytes.
+ this.Update((byte)128);
+
+ while (this._bufferOffset != 0)
+ this.Update((byte)0);
+
+ if (this._offset > 14)
+ {
+ this.ProcessBlock();
+ }
+
+ this._hashValue[14] = (int)(bitLength & 0xffffffff);
+ this._hashValue[15] = (int)((ulong)bitLength >> 32);
+
+ this.ProcessBlock();
+
+ var output = new byte[16];
+
+ this.UnpackWord(H1, output, 0);
+ this.UnpackWord(H2, output, 0 + 4);
+ this.UnpackWord(H3, output, 0 + 8);
+ this.UnpackWord(H4, output, 0 + 12);
+
+ this.Initialize();
+
+ return output;
+ }
+
+ ///
+ /// Initializes an implementation of the class.
+ ///
+ public override void Initialize()
+ {
+ this.InternalInitialize();
+ }
+
+ private void InternalInitialize()
+ {
+ this._byteCount = 0;
+ this._bufferOffset = 0;
+ for (var i = 0; i < 4; i++)
+ {
+ this._buffer[i] = 0;
+ }
+
+ H1 = unchecked((int)0x67452301);
+ H2 = unchecked((int)0xefcdab89);
+ H3 = unchecked((int)0x98badcfe);
+ H4 = unchecked((int)0x10325476);
+
+ this._offset = 0;
+ for (var i = 0; i != this._hashValue.Length; i++)
+ {
+ this._hashValue[i] = 0;
+ }
+ }
+
+ private void Update(byte input)
+ {
+ this._buffer[this._bufferOffset++] = input;
+
+ if (this._bufferOffset == this._buffer.Length)
+ {
+ this.ProcessWord(this._buffer, 0);
+ this._bufferOffset = 0;
+ }
+
+ this._byteCount++;
+ }
+
+ private void ProcessWord(byte[] input, int inOff)
+ {
+ this._hashValue[this._offset++] = (input[inOff] & 0xff) | ((input[inOff + 1] & 0xff) << 8)
+ | ((input[inOff + 2] & 0xff) << 16) | ((input[inOff + 3] & 0xff) << 24);
+
+ if (this._offset == 16)
+ {
+ ProcessBlock();
+ }
+ }
+
+ private void UnpackWord(int word, byte[] outBytes, int outOff)
+ {
+ outBytes[outOff] = (byte)word;
+ outBytes[outOff + 1] = (byte)((uint)word >> 8);
+ outBytes[outOff + 2] = (byte)((uint)word >> 16);
+ outBytes[outOff + 3] = (byte)((uint)word >> 24);
+ }
+
+ //
+ // round 1 left rotates
+ //
+ private const int S11 = 7;
+ private const int S12 = 12;
+ private const int S13 = 17;
+ private const int S14 = 22;
+
+ //
+ // round 2 left rotates
+ //
+ private const int S21 = 5;
+ private const int S22 = 9;
+ private const int S23 = 14;
+ private const int S24 = 20;
+
+ //
+ // round 3 left rotates
+ //
+ private const int S31 = 4;
+ private const int S32 = 11;
+ private const int S33 = 16;
+ private const int S34 = 23;
+
+ //
+ // round 4 left rotates
+ //
+ private const int S41 = 6;
+ private const int S42 = 10;
+ private const int S43 = 15;
+ private const int S44 = 21;
+
+ /*
+ * rotate int x left n bits.
+ */
+ private static int RotateLeft(int x, int n)
+ {
+ return (x << n) | (int)((uint)x >> (32 - n));
+ }
+
+ /*
+ * F, G, H and I are the basic MD5 functions.
+ */
+ private static int F(int u, int v, int w)
+ {
+ return (u & v) | (~u & w);
+ }
+
+ private static int G(int u, int v, int w)
+ {
+ return (u & w) | (v & ~w);
+ }
+
+ private static int H(int u, int v, int w)
+ {
+ return u ^ v ^ w;
+ }
+
+ private static int K(int u, int v, int w)
+ {
+ return v ^ (u | ~w);
+ }
+
+ private void ProcessBlock()
+ {
+ int a = H1;
+ int b = H2;
+ int c = H3;
+ int d = H4;
+
+ //
+ // Round 1 - F cycle, 16 times.
+ //
+ a = RotateLeft((a + F(b, c, d) + this._hashValue[0] + unchecked((int)0xd76aa478)), S11) + b;
+ d = RotateLeft((d + F(a, b, c) + this._hashValue[1] + unchecked((int)0xe8c7b756)), S12) + a;
+ c = RotateLeft((c + F(d, a, b) + this._hashValue[2] + unchecked((int)0x242070db)), S13) + d;
+ b = RotateLeft((b + F(c, d, a) + this._hashValue[3] + unchecked((int)0xc1bdceee)), S14) + c;
+ a = RotateLeft((a + F(b, c, d) + this._hashValue[4] + unchecked((int)0xf57c0faf)), S11) + b;
+ d = RotateLeft((d + F(a, b, c) + this._hashValue[5] + unchecked((int)0x4787c62a)), S12) + a;
+ c = RotateLeft((c + F(d, a, b) + this._hashValue[6] + unchecked((int)0xa8304613)), S13) + d;
+ b = RotateLeft((b + F(c, d, a) + this._hashValue[7] + unchecked((int)0xfd469501)), S14) + c;
+ a = RotateLeft((a + F(b, c, d) + this._hashValue[8] + unchecked((int)0x698098d8)), S11) + b;
+ d = RotateLeft((d + F(a, b, c) + this._hashValue[9] + unchecked((int)0x8b44f7af)), S12) + a;
+ c = RotateLeft((c + F(d, a, b) + this._hashValue[10] + unchecked((int)0xffff5bb1)), S13) + d;
+ b = RotateLeft((b + F(c, d, a) + this._hashValue[11] + unchecked((int)0x895cd7be)), S14) + c;
+ a = RotateLeft((a + F(b, c, d) + this._hashValue[12] + unchecked((int)0x6b901122)), S11) + b;
+ d = RotateLeft((d + F(a, b, c) + this._hashValue[13] + unchecked((int)0xfd987193)), S12) + a;
+ c = RotateLeft((c + F(d, a, b) + this._hashValue[14] + unchecked((int)0xa679438e)), S13) + d;
+ b = RotateLeft((b + F(c, d, a) + this._hashValue[15] + unchecked((int)0x49b40821)), S14) + c;
+
+ //
+ // Round 2 - G cycle, 16 times.
+ //
+ a = RotateLeft((a + G(b, c, d) + this._hashValue[1] + unchecked((int)0xf61e2562)), S21) + b;
+ d = RotateLeft((d + G(a, b, c) + this._hashValue[6] + unchecked((int)0xc040b340)), S22) + a;
+ c = RotateLeft((c + G(d, a, b) + this._hashValue[11] + unchecked((int)0x265e5a51)), S23) + d;
+ b = RotateLeft((b + G(c, d, a) + this._hashValue[0] + unchecked((int)0xe9b6c7aa)), S24) + c;
+ a = RotateLeft((a + G(b, c, d) + this._hashValue[5] + unchecked((int)0xd62f105d)), S21) + b;
+ d = RotateLeft((d + G(a, b, c) + this._hashValue[10] + unchecked((int)0x02441453)), S22) + a;
+ c = RotateLeft((c + G(d, a, b) + this._hashValue[15] + unchecked((int)0xd8a1e681)), S23) + d;
+ b = RotateLeft((b + G(c, d, a) + this._hashValue[4] + unchecked((int)0xe7d3fbc8)), S24) + c;
+ a = RotateLeft((a + G(b, c, d) + this._hashValue[9] + unchecked((int)0x21e1cde6)), S21) + b;
+ d = RotateLeft((d + G(a, b, c) + this._hashValue[14] + unchecked((int)0xc33707d6)), S22) + a;
+ c = RotateLeft((c + G(d, a, b) + this._hashValue[3] + unchecked((int)0xf4d50d87)), S23) + d;
+ b = RotateLeft((b + G(c, d, a) + this._hashValue[8] + unchecked((int)0x455a14ed)), S24) + c;
+ a = RotateLeft((a + G(b, c, d) + this._hashValue[13] + unchecked((int)0xa9e3e905)), S21) + b;
+ d = RotateLeft((d + G(a, b, c) + this._hashValue[2] + unchecked((int)0xfcefa3f8)), S22) + a;
+ c = RotateLeft((c + G(d, a, b) + this._hashValue[7] + unchecked((int)0x676f02d9)), S23) + d;
+ b = RotateLeft((b + G(c, d, a) + this._hashValue[12] + unchecked((int)0x8d2a4c8a)), S24) + c;
+
+ //
+ // Round 3 - H cycle, 16 times.
+ //
+ a = RotateLeft((a + H(b, c, d) + this._hashValue[5] + unchecked((int)0xfffa3942)), S31) + b;
+ d = RotateLeft((d + H(a, b, c) + this._hashValue[8] + unchecked((int)0x8771f681)), S32) + a;
+ c = RotateLeft((c + H(d, a, b) + this._hashValue[11] + unchecked((int)0x6d9d6122)), S33) + d;
+ b = RotateLeft((b + H(c, d, a) + this._hashValue[14] + unchecked((int)0xfde5380c)), S34) + c;
+ a = RotateLeft((a + H(b, c, d) + this._hashValue[1] + unchecked((int)0xa4beea44)), S31) + b;
+ d = RotateLeft((d + H(a, b, c) + this._hashValue[4] + unchecked((int)0x4bdecfa9)), S32) + a;
+ c = RotateLeft((c + H(d, a, b) + this._hashValue[7] + unchecked((int)0xf6bb4b60)), S33) + d;
+ b = RotateLeft((b + H(c, d, a) + this._hashValue[10] + unchecked((int)0xbebfbc70)), S34) + c;
+ a = RotateLeft((a + H(b, c, d) + this._hashValue[13] + unchecked((int)0x289b7ec6)), S31) + b;
+ d = RotateLeft((d + H(a, b, c) + this._hashValue[0] + unchecked((int)0xeaa127fa)), S32) + a;
+ c = RotateLeft((c + H(d, a, b) + this._hashValue[3] + unchecked((int)0xd4ef3085)), S33) + d;
+ b = RotateLeft((b + H(c, d, a) + this._hashValue[6] + unchecked((int)0x04881d05)), S34) + c;
+ a = RotateLeft((a + H(b, c, d) + this._hashValue[9] + unchecked((int)0xd9d4d039)), S31) + b;
+ d = RotateLeft((d + H(a, b, c) + this._hashValue[12] + unchecked((int)0xe6db99e5)), S32) + a;
+ c = RotateLeft((c + H(d, a, b) + this._hashValue[15] + unchecked((int)0x1fa27cf8)), S33) + d;
+ b = RotateLeft((b + H(c, d, a) + this._hashValue[2] + unchecked((int)0xc4ac5665)), S34) + c;
+
+ //
+ // Round 4 - K cycle, 16 times.
+ //
+ a = RotateLeft((a + K(b, c, d) + this._hashValue[0] + unchecked((int)0xf4292244)), S41) + b;
+ d = RotateLeft((d + K(a, b, c) + this._hashValue[7] + unchecked((int)0x432aff97)), S42) + a;
+ c = RotateLeft((c + K(d, a, b) + this._hashValue[14] + unchecked((int)0xab9423a7)), S43) + d;
+ b = RotateLeft((b + K(c, d, a) + this._hashValue[5] + unchecked((int)0xfc93a039)), S44) + c;
+ a = RotateLeft((a + K(b, c, d) + this._hashValue[12] + unchecked((int)0x655b59c3)), S41) + b;
+ d = RotateLeft((d + K(a, b, c) + this._hashValue[3] + unchecked((int)0x8f0ccc92)), S42) + a;
+ c = RotateLeft((c + K(d, a, b) + this._hashValue[10] + unchecked((int)0xffeff47d)), S43) + d;
+ b = RotateLeft((b + K(c, d, a) + this._hashValue[1] + unchecked((int)0x85845dd1)), S44) + c;
+ a = RotateLeft((a + K(b, c, d) + this._hashValue[8] + unchecked((int)0x6fa87e4f)), S41) + b;
+ d = RotateLeft((d + K(a, b, c) + this._hashValue[15] + unchecked((int)0xfe2ce6e0)), S42) + a;
+ c = RotateLeft((c + K(d, a, b) + this._hashValue[6] + unchecked((int)0xa3014314)), S43) + d;
+ b = RotateLeft((b + K(c, d, a) + this._hashValue[13] + unchecked((int)0x4e0811a1)), S44) + c;
+ a = RotateLeft((a + K(b, c, d) + this._hashValue[4] + unchecked((int)0xf7537e82)), S41) + b;
+ d = RotateLeft((d + K(a, b, c) + this._hashValue[11] + unchecked((int)0xbd3af235)), S42) + a;
+ c = RotateLeft((c + K(d, a, b) + this._hashValue[2] + unchecked((int)0x2ad7d2bb)), S43) + d;
+ b = RotateLeft((b + K(c, d, a) + this._hashValue[9] + unchecked((int)0xeb86d391)), S44) + c;
+
+ H1 += a;
+ H2 += b;
+ H3 += c;
+ H4 += d;
+
+ //
+ // reset the offset and clean out the word buffer.
+ //
+ this._offset = 0;
+ for (int i = 0; i != this._hashValue.Length; i++)
+ {
+ this._hashValue[i] = 0;
+ }
+ }
+ }
+}
diff --git a/Renci.SshNet/Security/Cryptography/Hashes/RIPEMD160Hash.cs b/Renci.SshNet/Security/Cryptography/Hashes/RIPEMD160Hash.cs
index 64e15d2..def23f7 100644
--- a/Renci.SshNet/Security/Cryptography/Hashes/RIPEMD160Hash.cs
+++ b/Renci.SshNet/Security/Cryptography/Hashes/RIPEMD160Hash.cs
@@ -1,522 +1,518 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Security.Cryptography;
-using System.Text;
-
-namespace Renci.SshNet.Security.Cryptography
-{
- ///
- ///
- ///
- public sealed class RIPEMD160Hash : HashAlgorithm
- {
- private const int DIGEST_SIZE = 20;
-
- private byte[] _buffer;
- private int _bufferOffset;
- private long _byteCount;
- private int _offset;
- private int H0, H1, H2, H3, H4; // IV's
- private int[] X = new int[16];
-
- ///
- /// Gets the size, in bits, of the computed hash code.
- ///
- /// The size, in bits, of the computed hash code.
- public override int HashSize
- {
- get
- {
- return DIGEST_SIZE * 8;
- }
- }
-
- ///
- /// Gets the input block size.
- ///
- /// The input block size.
- public override int InputBlockSize
- {
- get
- {
- return 64;
- }
- }
-
- ///
- /// Gets the output block size.
- ///
- /// The output block size.
- public override int OutputBlockSize
- {
- get
- {
- return 64;
- }
- }
-
- ///
- /// Gets a value indicating whether the current transform can be reused.
- ///
- /// Always true.
- public override bool CanReuseTransform
- {
- get
- {
- return true;
- }
- }
-
- ///
- /// Gets a value indicating whether multiple blocks can be transformed.
- ///
- /// true if multiple blocks can be transformed; otherwise, false.
- public override bool CanTransformMultipleBlocks
- {
- get
- {
- return true;
- }
- }
-
- protected override void HashCore(byte[] array, int ibStart, int cbSize)
- {
- //
- // fill the current word
- //
- while ((this._bufferOffset != 0) && (cbSize > 0))
- {
- this.Update(array[ibStart]);
- ibStart++;
- cbSize--;
- }
-
- //
- // process whole words.
- //
- while (cbSize > this._buffer.Length)
- {
- this.ProcessWord(array, ibStart);
-
- ibStart += this._buffer.Length;
- cbSize -= this._buffer.Length;
- this._byteCount += this._buffer.Length;
- }
-
- //
- // load in the remainder.
- //
- while (cbSize > 0)
- {
- this.Update(array[ibStart]);
-
- ibStart++;
- cbSize--;
- }
- }
-
- protected override byte[] HashFinal()
- {
- var output = new byte[DIGEST_SIZE];
- long bitLength = (this._byteCount << 3);
-
- //
- // add the pad bytes.
- //
- this.Update((byte)128);
-
- while (this._bufferOffset != 0)
- Update((byte)0);
- ProcessLength(bitLength);
- ProcessBlock();
-
- UnpackWord(H0, output, 0);
- UnpackWord(H1, output, 4);
- UnpackWord(H2, output, 8);
- UnpackWord(H3, output, 12);
- UnpackWord(H4, output, 16);
-
- this.InternalInitialize();
-
- return output;
- }
-
- ///
- /// Initializes an implementation of the class.
- ///
- public override void Initialize()
- {
- this.InternalInitialize();
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- public RIPEMD160Hash()
- {
- this._buffer = new byte[4];
- this.InternalInitialize();
- }
-
- private void ProcessWord(byte[] input, int inOff)
- {
- this.X[this._offset++] = (input[inOff] & 0xff) | ((input[inOff + 1] & 0xff) << 8)
- | ((input[inOff + 2] & 0xff) << 16) | ((input[inOff + 3] & 0xff) << 24);
-
- if (this._offset == 16)
- {
- ProcessBlock();
- }
- }
-
- private void ProcessLength(long bitLength)
- {
- if (this._offset > 14)
- {
- ProcessBlock();
- }
-
- this.X[14] = (int)(bitLength & 0xffffffff);
- this.X[15] = (int)((ulong)bitLength >> 32);
- }
-
- private void UnpackWord(int word, byte[] outBytes, int outOff)
- {
- outBytes[outOff] = (byte)word;
- outBytes[outOff + 1] = (byte)((uint)word >> 8);
- outBytes[outOff + 2] = (byte)((uint)word >> 16);
- outBytes[outOff + 3] = (byte)((uint)word >> 24);
- }
-
- private void Update(byte input)
- {
- this._buffer[this._bufferOffset++] = input;
-
- if (this._bufferOffset == this._buffer.Length)
- {
- ProcessWord(this._buffer, 0);
- this._bufferOffset = 0;
- }
-
- this._byteCount++;
- }
-
- ///
- /// Reset the chaining variables to the IV values.
- ///
- private void InternalInitialize()
- {
- this._byteCount = 0;
- this._bufferOffset = 0;
- for (int i = 0; i < _buffer.Length; i++)
- {
- this._buffer[i] = 0;
- }
-
- H0 = unchecked((int)0x67452301);
- H1 = unchecked((int)0xefcdab89);
- H2 = unchecked((int)0x98badcfe);
- H3 = unchecked((int)0x10325476);
- H4 = unchecked((int)0xc3d2e1f0);
-
- this._offset = 0;
-
- for (int i = 0; i != X.Length; i++)
- {
- this.X[i] = 0;
- }
- }
-
- private int RL(int x, int n)
- {
- return (x << n) | (int)((uint)x >> (32 - n));
- }
-
- ///
- /// Rounds 0-15
- ///
- /// The x.
- /// The y.
- /// The z.
- ///
- private int F1(int x, int y, int z)
- {
- return x ^ y ^ z;
- }
-
- ///
- /// Rounds 16-31
- ///
- /// The x.
- /// The y.
- /// The z.
- ///
- private int F2(int x, int y, int z)
- {
- return (x & y) | (~x & z);
- }
-
- ///
- /// ounds 32-47
- ///
- /// The x.
- /// The y.
- /// The z.
- ///
- private int F3(int x, int y, int z)
- {
- return (x | ~y) ^ z;
- }
-
- ///
- /// Rounds 48-63
- ///
- /// The x.
- /// The y.
- /// The z.
- ///
- private int F4(int x, int y, int z)
- {
- return (x & z) | (y & ~z);
- }
-
- ///
- /// ounds 64-79
- ///
- /// The x.
- /// The y.
- /// The z.
- ///
- private int F5(int x, int y, int z)
- {
- return x ^ (y | ~z);
- }
-
- private void ProcessBlock()
- {
- int a, aa;
- int b, bb;
- int c, cc;
- int d, dd;
- int e, ee;
-
- a = aa = H0;
- b = bb = H1;
- c = cc = H2;
- d = dd = H3;
- e = ee = H4;
-
- //
- // Rounds 1 - 16
- //
- // left
- a = RL(a + F1(b, c, d) + this.X[0], 11) + e; c = RL(c, 10);
- e = RL(e + F1(a, b, c) + this.X[1], 14) + d; b = RL(b, 10);
- d = RL(d + F1(e, a, b) + this.X[2], 15) + c; a = RL(a, 10);
- c = RL(c + F1(d, e, a) + this.X[3], 12) + b; e = RL(e, 10);
- b = RL(b + F1(c, d, e) + this.X[4], 5) + a; d = RL(d, 10);
- a = RL(a + F1(b, c, d) + this.X[5], 8) + e; c = RL(c, 10);
- e = RL(e + F1(a, b, c) + this.X[6], 7) + d; b = RL(b, 10);
- d = RL(d + F1(e, a, b) + this.X[7], 9) + c; a = RL(a, 10);
- c = RL(c + F1(d, e, a) + this.X[8], 11) + b; e = RL(e, 10);
- b = RL(b + F1(c, d, e) + this.X[9], 13) + a; d = RL(d, 10);
- a = RL(a + F1(b, c, d) + this.X[10], 14) + e; c = RL(c, 10);
- e = RL(e + F1(a, b, c) + this.X[11], 15) + d; b = RL(b, 10);
- d = RL(d + F1(e, a, b) + this.X[12], 6) + c; a = RL(a, 10);
- c = RL(c + F1(d, e, a) + this.X[13], 7) + b; e = RL(e, 10);
- b = RL(b + F1(c, d, e) + this.X[14], 9) + a; d = RL(d, 10);
- a = RL(a + F1(b, c, d) + this.X[15], 8) + e; c = RL(c, 10);
-
- // right
- aa = RL(aa + F5(bb, cc, dd) + this.X[5] + unchecked((int)0x50a28be6), 8) + ee; cc = RL(cc, 10);
- ee = RL(ee + F5(aa, bb, cc) + this.X[14] + unchecked((int)0x50a28be6), 9) + dd; bb = RL(bb, 10);
- dd = RL(dd + F5(ee, aa, bb) + this.X[7] + unchecked((int)0x50a28be6), 9) + cc; aa = RL(aa, 10);
- cc = RL(cc + F5(dd, ee, aa) + this.X[0] + unchecked((int)0x50a28be6), 11) + bb; ee = RL(ee, 10);
- bb = RL(bb + F5(cc, dd, ee) + this.X[9] + unchecked((int)0x50a28be6), 13) + aa; dd = RL(dd, 10);
- aa = RL(aa + F5(bb, cc, dd) + this.X[2] + unchecked((int)0x50a28be6), 15) + ee; cc = RL(cc, 10);
- ee = RL(ee + F5(aa, bb, cc) + this.X[11] + unchecked((int)0x50a28be6), 15) + dd; bb = RL(bb, 10);
- dd = RL(dd + F5(ee, aa, bb) + this.X[4] + unchecked((int)0x50a28be6), 5) + cc; aa = RL(aa, 10);
- cc = RL(cc + F5(dd, ee, aa) + this.X[13] + unchecked((int)0x50a28be6), 7) + bb; ee = RL(ee, 10);
- bb = RL(bb + F5(cc, dd, ee) + this.X[6] + unchecked((int)0x50a28be6), 7) + aa; dd = RL(dd, 10);
- aa = RL(aa + F5(bb, cc, dd) + this.X[15] + unchecked((int)0x50a28be6), 8) + ee; cc = RL(cc, 10);
- ee = RL(ee + F5(aa, bb, cc) + this.X[8] + unchecked((int)0x50a28be6), 11) + dd; bb = RL(bb, 10);
- dd = RL(dd + F5(ee, aa, bb) + this.X[1] + unchecked((int)0x50a28be6), 14) + cc; aa = RL(aa, 10);
- cc = RL(cc + F5(dd, ee, aa) + this.X[10] + unchecked((int)0x50a28be6), 14) + bb; ee = RL(ee, 10);
- bb = RL(bb + F5(cc, dd, ee) + this.X[3] + unchecked((int)0x50a28be6), 12) + aa; dd = RL(dd, 10);
- aa = RL(aa + F5(bb, cc, dd) + this.X[12] + unchecked((int)0x50a28be6), 6) + ee; cc = RL(cc, 10);
-
- //
- // Rounds 16-31
- //
- // left
- e = RL(e + F2(a, b, c) + this.X[7] + unchecked((int)0x5a827999), 7) + d; b = RL(b, 10);
- d = RL(d + F2(e, a, b) + this.X[4] + unchecked((int)0x5a827999), 6) + c; a = RL(a, 10);
- c = RL(c + F2(d, e, a) + this.X[13] + unchecked((int)0x5a827999), 8) + b; e = RL(e, 10);
- b = RL(b + F2(c, d, e) + this.X[1] + unchecked((int)0x5a827999), 13) + a; d = RL(d, 10);
- a = RL(a + F2(b, c, d) + this.X[10] + unchecked((int)0x5a827999), 11) + e; c = RL(c, 10);
- e = RL(e + F2(a, b, c) + this.X[6] + unchecked((int)0x5a827999), 9) + d; b = RL(b, 10);
- d = RL(d + F2(e, a, b) + this.X[15] + unchecked((int)0x5a827999), 7) + c; a = RL(a, 10);
- c = RL(c + F2(d, e, a) + this.X[3] + unchecked((int)0x5a827999), 15) + b; e = RL(e, 10);
- b = RL(b + F2(c, d, e) + this.X[12] + unchecked((int)0x5a827999), 7) + a; d = RL(d, 10);
- a = RL(a + F2(b, c, d) + this.X[0] + unchecked((int)0x5a827999), 12) + e; c = RL(c, 10);
- e = RL(e + F2(a, b, c) + this.X[9] + unchecked((int)0x5a827999), 15) + d; b = RL(b, 10);
- d = RL(d + F2(e, a, b) + this.X[5] + unchecked((int)0x5a827999), 9) + c; a = RL(a, 10);
- c = RL(c + F2(d, e, a) + this.X[2] + unchecked((int)0x5a827999), 11) + b; e = RL(e, 10);
- b = RL(b + F2(c, d, e) + this.X[14] + unchecked((int)0x5a827999), 7) + a; d = RL(d, 10);
- a = RL(a + F2(b, c, d) + this.X[11] + unchecked((int)0x5a827999), 13) + e; c = RL(c, 10);
- e = RL(e + F2(a, b, c) + this.X[8] + unchecked((int)0x5a827999), 12) + d; b = RL(b, 10);
-
- // right
- ee = RL(ee + F4(aa, bb, cc) + this.X[6] + unchecked((int)0x5c4dd124), 9) + dd; bb = RL(bb, 10);
- dd = RL(dd + F4(ee, aa, bb) + this.X[11] + unchecked((int)0x5c4dd124), 13) + cc; aa = RL(aa, 10);
- cc = RL(cc + F4(dd, ee, aa) + this.X[3] + unchecked((int)0x5c4dd124), 15) + bb; ee = RL(ee, 10);
- bb = RL(bb + F4(cc, dd, ee) + this.X[7] + unchecked((int)0x5c4dd124), 7) + aa; dd = RL(dd, 10);
- aa = RL(aa + F4(bb, cc, dd) + this.X[0] + unchecked((int)0x5c4dd124), 12) + ee; cc = RL(cc, 10);
- ee = RL(ee + F4(aa, bb, cc) + this.X[13] + unchecked((int)0x5c4dd124), 8) + dd; bb = RL(bb, 10);
- dd = RL(dd + F4(ee, aa, bb) + this.X[5] + unchecked((int)0x5c4dd124), 9) + cc; aa = RL(aa, 10);
- cc = RL(cc + F4(dd, ee, aa) + this.X[10] + unchecked((int)0x5c4dd124), 11) + bb; ee = RL(ee, 10);
- bb = RL(bb + F4(cc, dd, ee) + this.X[14] + unchecked((int)0x5c4dd124), 7) + aa; dd = RL(dd, 10);
- aa = RL(aa + F4(bb, cc, dd) + this.X[15] + unchecked((int)0x5c4dd124), 7) + ee; cc = RL(cc, 10);
- ee = RL(ee + F4(aa, bb, cc) + this.X[8] + unchecked((int)0x5c4dd124), 12) + dd; bb = RL(bb, 10);
- dd = RL(dd + F4(ee, aa, bb) + this.X[12] + unchecked((int)0x5c4dd124), 7) + cc; aa = RL(aa, 10);
- cc = RL(cc + F4(dd, ee, aa) + this.X[4] + unchecked((int)0x5c4dd124), 6) + bb; ee = RL(ee, 10);
- bb = RL(bb + F4(cc, dd, ee) + this.X[9] + unchecked((int)0x5c4dd124), 15) + aa; dd = RL(dd, 10);
- aa = RL(aa + F4(bb, cc, dd) + this.X[1] + unchecked((int)0x5c4dd124), 13) + ee; cc = RL(cc, 10);
- ee = RL(ee + F4(aa, bb, cc) + this.X[2] + unchecked((int)0x5c4dd124), 11) + dd; bb = RL(bb, 10);
-
- //
- // Rounds 32-47
- //
- // left
- d = RL(d + F3(e, a, b) + this.X[3] + unchecked((int)0x6ed9eba1), 11) + c; a = RL(a, 10);
- c = RL(c + F3(d, e, a) + this.X[10] + unchecked((int)0x6ed9eba1), 13) + b; e = RL(e, 10);
- b = RL(b + F3(c, d, e) + this.X[14] + unchecked((int)0x6ed9eba1), 6) + a; d = RL(d, 10);
- a = RL(a + F3(b, c, d) + this.X[4] + unchecked((int)0x6ed9eba1), 7) + e; c = RL(c, 10);
- e = RL(e + F3(a, b, c) + this.X[9] + unchecked((int)0x6ed9eba1), 14) + d; b = RL(b, 10);
- d = RL(d + F3(e, a, b) + this.X[15] + unchecked((int)0x6ed9eba1), 9) + c; a = RL(a, 10);
- c = RL(c + F3(d, e, a) + this.X[8] + unchecked((int)0x6ed9eba1), 13) + b; e = RL(e, 10);
- b = RL(b + F3(c, d, e) + this.X[1] + unchecked((int)0x6ed9eba1), 15) + a; d = RL(d, 10);
- a = RL(a + F3(b, c, d) + this.X[2] + unchecked((int)0x6ed9eba1), 14) + e; c = RL(c, 10);
- e = RL(e + F3(a, b, c) + this.X[7] + unchecked((int)0x6ed9eba1), 8) + d; b = RL(b, 10);
- d = RL(d + F3(e, a, b) + this.X[0] + unchecked((int)0x6ed9eba1), 13) + c; a = RL(a, 10);
- c = RL(c + F3(d, e, a) + this.X[6] + unchecked((int)0x6ed9eba1), 6) + b; e = RL(e, 10);
- b = RL(b + F3(c, d, e) + this.X[13] + unchecked((int)0x6ed9eba1), 5) + a; d = RL(d, 10);
- a = RL(a + F3(b, c, d) + this.X[11] + unchecked((int)0x6ed9eba1), 12) + e; c = RL(c, 10);
- e = RL(e + F3(a, b, c) + this.X[5] + unchecked((int)0x6ed9eba1), 7) + d; b = RL(b, 10);
- d = RL(d + F3(e, a, b) + this.X[12] + unchecked((int)0x6ed9eba1), 5) + c; a = RL(a, 10);
-
- // right
- dd = RL(dd + F3(ee, aa, bb) + this.X[15] + unchecked((int)0x6d703ef3), 9) + cc; aa = RL(aa, 10);
- cc = RL(cc + F3(dd, ee, aa) + this.X[5] + unchecked((int)0x6d703ef3), 7) + bb; ee = RL(ee, 10);
- bb = RL(bb + F3(cc, dd, ee) + this.X[1] + unchecked((int)0x6d703ef3), 15) + aa; dd = RL(dd, 10);
- aa = RL(aa + F3(bb, cc, dd) + this.X[3] + unchecked((int)0x6d703ef3), 11) + ee; cc = RL(cc, 10);
- ee = RL(ee + F3(aa, bb, cc) + this.X[7] + unchecked((int)0x6d703ef3), 8) + dd; bb = RL(bb, 10);
- dd = RL(dd + F3(ee, aa, bb) + this.X[14] + unchecked((int)0x6d703ef3), 6) + cc; aa = RL(aa, 10);
- cc = RL(cc + F3(dd, ee, aa) + this.X[6] + unchecked((int)0x6d703ef3), 6) + bb; ee = RL(ee, 10);
- bb = RL(bb + F3(cc, dd, ee) + this.X[9] + unchecked((int)0x6d703ef3), 14) + aa; dd = RL(dd, 10);
- aa = RL(aa + F3(bb, cc, dd) + this.X[11] + unchecked((int)0x6d703ef3), 12) + ee; cc = RL(cc, 10);
- ee = RL(ee + F3(aa, bb, cc) + this.X[8] + unchecked((int)0x6d703ef3), 13) + dd; bb = RL(bb, 10);
- dd = RL(dd + F3(ee, aa, bb) + this.X[12] + unchecked((int)0x6d703ef3), 5) + cc; aa = RL(aa, 10);
- cc = RL(cc + F3(dd, ee, aa) + this.X[2] + unchecked((int)0x6d703ef3), 14) + bb; ee = RL(ee, 10);
- bb = RL(bb + F3(cc, dd, ee) + this.X[10] + unchecked((int)0x6d703ef3), 13) + aa; dd = RL(dd, 10);
- aa = RL(aa + F3(bb, cc, dd) + this.X[0] + unchecked((int)0x6d703ef3), 13) + ee; cc = RL(cc, 10);
- ee = RL(ee + F3(aa, bb, cc) + this.X[4] + unchecked((int)0x6d703ef3), 7) + dd; bb = RL(bb, 10);
- dd = RL(dd + F3(ee, aa, bb) + this.X[13] + unchecked((int)0x6d703ef3), 5) + cc; aa = RL(aa, 10);
-
- //
- // Rounds 48-63
- //
- // left
- c = RL(c + F4(d, e, a) + this.X[1] + unchecked((int)0x8f1bbcdc), 11) + b; e = RL(e, 10);
- b = RL(b + F4(c, d, e) + this.X[9] + unchecked((int)0x8f1bbcdc), 12) + a; d = RL(d, 10);
- a = RL(a + F4(b, c, d) + this.X[11] + unchecked((int)0x8f1bbcdc), 14) + e; c = RL(c, 10);
- e = RL(e + F4(a, b, c) + this.X[10] + unchecked((int)0x8f1bbcdc), 15) + d; b = RL(b, 10);
- d = RL(d + F4(e, a, b) + this.X[0] + unchecked((int)0x8f1bbcdc), 14) + c; a = RL(a, 10);
- c = RL(c + F4(d, e, a) + this.X[8] + unchecked((int)0x8f1bbcdc), 15) + b; e = RL(e, 10);
- b = RL(b + F4(c, d, e) + this.X[12] + unchecked((int)0x8f1bbcdc), 9) + a; d = RL(d, 10);
- a = RL(a + F4(b, c, d) + this.X[4] + unchecked((int)0x8f1bbcdc), 8) + e; c = RL(c, 10);
- e = RL(e + F4(a, b, c) + this.X[13] + unchecked((int)0x8f1bbcdc), 9) + d; b = RL(b, 10);
- d = RL(d + F4(e, a, b) + this.X[3] + unchecked((int)0x8f1bbcdc), 14) + c; a = RL(a, 10);
- c = RL(c + F4(d, e, a) + this.X[7] + unchecked((int)0x8f1bbcdc), 5) + b; e = RL(e, 10);
- b = RL(b + F4(c, d, e) + this.X[15] + unchecked((int)0x8f1bbcdc), 6) + a; d = RL(d, 10);
- a = RL(a + F4(b, c, d) + this.X[14] + unchecked((int)0x8f1bbcdc), 8) + e; c = RL(c, 10);
- e = RL(e + F4(a, b, c) + this.X[5] + unchecked((int)0x8f1bbcdc), 6) + d; b = RL(b, 10);
- d = RL(d + F4(e, a, b) + this.X[6] + unchecked((int)0x8f1bbcdc), 5) + c; a = RL(a, 10);
- c = RL(c + F4(d, e, a) + this.X[2] + unchecked((int)0x8f1bbcdc), 12) + b; e = RL(e, 10);
-
- // right
- cc = RL(cc + F2(dd, ee, aa) + this.X[8] + unchecked((int)0x7a6d76e9), 15) + bb; ee = RL(ee, 10);
- bb = RL(bb + F2(cc, dd, ee) + this.X[6] + unchecked((int)0x7a6d76e9), 5) + aa; dd = RL(dd, 10);
- aa = RL(aa + F2(bb, cc, dd) + this.X[4] + unchecked((int)0x7a6d76e9), 8) + ee; cc = RL(cc, 10);
- ee = RL(ee + F2(aa, bb, cc) + this.X[1] + unchecked((int)0x7a6d76e9), 11) + dd; bb = RL(bb, 10);
- dd = RL(dd + F2(ee, aa, bb) + this.X[3] + unchecked((int)0x7a6d76e9), 14) + cc; aa = RL(aa, 10);
- cc = RL(cc + F2(dd, ee, aa) + this.X[11] + unchecked((int)0x7a6d76e9), 14) + bb; ee = RL(ee, 10);
- bb = RL(bb + F2(cc, dd, ee) + this.X[15] + unchecked((int)0x7a6d76e9), 6) + aa; dd = RL(dd, 10);
- aa = RL(aa + F2(bb, cc, dd) + this.X[0] + unchecked((int)0x7a6d76e9), 14) + ee; cc = RL(cc, 10);
- ee = RL(ee + F2(aa, bb, cc) + this.X[5] + unchecked((int)0x7a6d76e9), 6) + dd; bb = RL(bb, 10);
- dd = RL(dd + F2(ee, aa, bb) + this.X[12] + unchecked((int)0x7a6d76e9), 9) + cc; aa = RL(aa, 10);
- cc = RL(cc + F2(dd, ee, aa) + this.X[2] + unchecked((int)0x7a6d76e9), 12) + bb; ee = RL(ee, 10);
- bb = RL(bb + F2(cc, dd, ee) + this.X[13] + unchecked((int)0x7a6d76e9), 9) + aa; dd = RL(dd, 10);
- aa = RL(aa + F2(bb, cc, dd) + this.X[9] + unchecked((int)0x7a6d76e9), 12) + ee; cc = RL(cc, 10);
- ee = RL(ee + F2(aa, bb, cc) + this.X[7] + unchecked((int)0x7a6d76e9), 5) + dd; bb = RL(bb, 10);
- dd = RL(dd + F2(ee, aa, bb) + this.X[10] + unchecked((int)0x7a6d76e9), 15) + cc; aa = RL(aa, 10);
- cc = RL(cc + F2(dd, ee, aa) + this.X[14] + unchecked((int)0x7a6d76e9), 8) + bb; ee = RL(ee, 10);
-
- //
- // Rounds 64-79
- //
- // left
- b = RL(b + F5(c, d, e) + this.X[4] + unchecked((int)0xa953fd4e), 9) + a; d = RL(d, 10);
- a = RL(a + F5(b, c, d) + this.X[0] + unchecked((int)0xa953fd4e), 15) + e; c = RL(c, 10);
- e = RL(e + F5(a, b, c) + this.X[5] + unchecked((int)0xa953fd4e), 5) + d; b = RL(b, 10);
- d = RL(d + F5(e, a, b) + this.X[9] + unchecked((int)0xa953fd4e), 11) + c; a = RL(a, 10);
- c = RL(c + F5(d, e, a) + this.X[7] + unchecked((int)0xa953fd4e), 6) + b; e = RL(e, 10);
- b = RL(b + F5(c, d, e) + this.X[12] + unchecked((int)0xa953fd4e), 8) + a; d = RL(d, 10);
- a = RL(a + F5(b, c, d) + this.X[2] + unchecked((int)0xa953fd4e), 13) + e; c = RL(c, 10);
- e = RL(e + F5(a, b, c) + this.X[10] + unchecked((int)0xa953fd4e), 12) + d; b = RL(b, 10);
- d = RL(d + F5(e, a, b) + this.X[14] + unchecked((int)0xa953fd4e), 5) + c; a = RL(a, 10);
- c = RL(c + F5(d, e, a) + this.X[1] + unchecked((int)0xa953fd4e), 12) + b; e = RL(e, 10);
- b = RL(b + F5(c, d, e) + this.X[3] + unchecked((int)0xa953fd4e), 13) + a; d = RL(d, 10);
- a = RL(a + F5(b, c, d) + this.X[8] + unchecked((int)0xa953fd4e), 14) + e; c = RL(c, 10);
- e = RL(e + F5(a, b, c) + this.X[11] + unchecked((int)0xa953fd4e), 11) + d; b = RL(b, 10);
- d = RL(d + F5(e, a, b) + this.X[6] + unchecked((int)0xa953fd4e), 8) + c; a = RL(a, 10);
- c = RL(c + F5(d, e, a) + this.X[15] + unchecked((int)0xa953fd4e), 5) + b; e = RL(e, 10);
- b = RL(b + F5(c, d, e) + this.X[13] + unchecked((int)0xa953fd4e), 6) + a; d = RL(d, 10);
-
- // right
- bb = RL(bb + F1(cc, dd, ee) + this.X[12], 8) + aa; dd = RL(dd, 10);
- aa = RL(aa + F1(bb, cc, dd) + this.X[15], 5) + ee; cc = RL(cc, 10);
- ee = RL(ee + F1(aa, bb, cc) + this.X[10], 12) + dd; bb = RL(bb, 10);
- dd = RL(dd + F1(ee, aa, bb) + this.X[4], 9) + cc; aa = RL(aa, 10);
- cc = RL(cc + F1(dd, ee, aa) + this.X[1], 12) + bb; ee = RL(ee, 10);
- bb = RL(bb + F1(cc, dd, ee) + this.X[5], 5) + aa; dd = RL(dd, 10);
- aa = RL(aa + F1(bb, cc, dd) + this.X[8], 14) + ee; cc = RL(cc, 10);
- ee = RL(ee + F1(aa, bb, cc) + this.X[7], 6) + dd; bb = RL(bb, 10);
- dd = RL(dd + F1(ee, aa, bb) + this.X[6], 8) + cc; aa = RL(aa, 10);
- cc = RL(cc + F1(dd, ee, aa) + this.X[2], 13) + bb; ee = RL(ee, 10);
- bb = RL(bb + F1(cc, dd, ee) + this.X[13], 6) + aa; dd = RL(dd, 10);
- aa = RL(aa + F1(bb, cc, dd) + this.X[14], 5) + ee; cc = RL(cc, 10);
- ee = RL(ee + F1(aa, bb, cc) + this.X[0], 15) + dd; bb = RL(bb, 10);
- dd = RL(dd + F1(ee, aa, bb) + this.X[3], 13) + cc; aa = RL(aa, 10);
- cc = RL(cc + F1(dd, ee, aa) + this.X[9], 11) + bb; ee = RL(ee, 10);
- bb = RL(bb + F1(cc, dd, ee) + this.X[11], 11) + aa; dd = RL(dd, 10);
-
- dd += c + H1;
- H1 = H2 + d + ee;
- H2 = H3 + e + aa;
- H3 = H4 + a + bb;
- H4 = H0 + b + cc;
- H0 = dd;
-
- //
- // reset the offset and clean out the word buffer.
- //
- this._offset = 0;
- for (int i = 0; i < X.Length; i++)
- {
- this.X[i] = 0;
- }
- }
- }
+using System.Security.Cryptography;
+
+namespace Renci.SshNet.Security.Cryptography
+{
+ ///
+ ///
+ ///
+ public sealed class RIPEMD160Hash : HashAlgorithm
+ {
+ private const int DIGEST_SIZE = 20;
+
+ private readonly byte[] _buffer;
+ private int _bufferOffset;
+ private long _byteCount;
+ private int _offset;
+ private int H0, H1, H2, H3, H4; // IV's
+ private readonly int[] X = new int[16];
+
+ ///
+ /// Gets the size, in bits, of the computed hash code.
+ ///
+ /// The size, in bits, of the computed hash code.
+ public override int HashSize
+ {
+ get
+ {
+ return DIGEST_SIZE * 8;
+ }
+ }
+
+ ///
+ /// Gets the input block size.
+ ///
+ /// The input block size.
+ public override int InputBlockSize
+ {
+ get
+ {
+ return 64;
+ }
+ }
+
+ ///
+ /// Gets the output block size.
+ ///
+ /// The output block size.
+ public override int OutputBlockSize
+ {
+ get
+ {
+ return 64;
+ }
+ }
+
+ ///
+ /// Gets a value indicating whether the current transform can be reused.
+ ///
+ /// Always true.
+ public override bool CanReuseTransform
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ ///
+ /// Gets a value indicating whether multiple blocks can be transformed.
+ ///
+ /// true if multiple blocks can be transformed; otherwise, false.
+ public override bool CanTransformMultipleBlocks
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ protected override void HashCore(byte[] array, int ibStart, int cbSize)
+ {
+ //
+ // fill the current word
+ //
+ while ((this._bufferOffset != 0) && (cbSize > 0))
+ {
+ this.Update(array[ibStart]);
+ ibStart++;
+ cbSize--;
+ }
+
+ //
+ // process whole words.
+ //
+ while (cbSize > this._buffer.Length)
+ {
+ this.ProcessWord(array, ibStart);
+
+ ibStart += this._buffer.Length;
+ cbSize -= this._buffer.Length;
+ this._byteCount += this._buffer.Length;
+ }
+
+ //
+ // load in the remainder.
+ //
+ while (cbSize > 0)
+ {
+ this.Update(array[ibStart]);
+
+ ibStart++;
+ cbSize--;
+ }
+ }
+
+ protected override byte[] HashFinal()
+ {
+ var output = new byte[DIGEST_SIZE];
+ long bitLength = (this._byteCount << 3);
+
+ //
+ // add the pad bytes.
+ //
+ this.Update((byte)128);
+
+ while (this._bufferOffset != 0)
+ Update((byte)0);
+ ProcessLength(bitLength);
+ ProcessBlock();
+
+ UnpackWord(H0, output, 0);
+ UnpackWord(H1, output, 4);
+ UnpackWord(H2, output, 8);
+ UnpackWord(H3, output, 12);
+ UnpackWord(H4, output, 16);
+
+ this.InternalInitialize();
+
+ return output;
+ }
+
+ ///
+ /// Initializes an implementation of the class.
+ ///
+ public override void Initialize()
+ {
+ this.InternalInitialize();
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public RIPEMD160Hash()
+ {
+ this._buffer = new byte[4];
+ this.InternalInitialize();
+ }
+
+ private void ProcessWord(byte[] input, int inOff)
+ {
+ this.X[this._offset++] = (input[inOff] & 0xff) | ((input[inOff + 1] & 0xff) << 8)
+ | ((input[inOff + 2] & 0xff) << 16) | ((input[inOff + 3] & 0xff) << 24);
+
+ if (this._offset == 16)
+ {
+ ProcessBlock();
+ }
+ }
+
+ private void ProcessLength(long bitLength)
+ {
+ if (this._offset > 14)
+ {
+ ProcessBlock();
+ }
+
+ this.X[14] = (int)(bitLength & 0xffffffff);
+ this.X[15] = (int)((ulong)bitLength >> 32);
+ }
+
+ private void UnpackWord(int word, byte[] outBytes, int outOff)
+ {
+ outBytes[outOff] = (byte)word;
+ outBytes[outOff + 1] = (byte)((uint)word >> 8);
+ outBytes[outOff + 2] = (byte)((uint)word >> 16);
+ outBytes[outOff + 3] = (byte)((uint)word >> 24);
+ }
+
+ private void Update(byte input)
+ {
+ this._buffer[this._bufferOffset++] = input;
+
+ if (this._bufferOffset == this._buffer.Length)
+ {
+ ProcessWord(this._buffer, 0);
+ this._bufferOffset = 0;
+ }
+
+ this._byteCount++;
+ }
+
+ ///
+ /// Reset the chaining variables to the IV values.
+ ///
+ private void InternalInitialize()
+ {
+ this._byteCount = 0;
+ this._bufferOffset = 0;
+ for (int i = 0; i < _buffer.Length; i++)
+ {
+ this._buffer[i] = 0;
+ }
+
+ H0 = unchecked((int)0x67452301);
+ H1 = unchecked((int)0xefcdab89);
+ H2 = unchecked((int)0x98badcfe);
+ H3 = unchecked((int)0x10325476);
+ H4 = unchecked((int)0xc3d2e1f0);
+
+ this._offset = 0;
+
+ for (int i = 0; i != X.Length; i++)
+ {
+ this.X[i] = 0;
+ }
+ }
+
+ private int RL(int x, int n)
+ {
+ return (x << n) | (int)((uint)x >> (32 - n));
+ }
+
+ ///
+ /// Rounds 0-15
+ ///
+ /// The x.
+ /// The y.
+ /// The z.
+ ///
+ private int F1(int x, int y, int z)
+ {
+ return x ^ y ^ z;
+ }
+
+ ///
+ /// Rounds 16-31
+ ///
+ /// The x.
+ /// The y.
+ /// The z.
+ ///
+ private int F2(int x, int y, int z)
+ {
+ return (x & y) | (~x & z);
+ }
+
+ ///
+ /// ounds 32-47
+ ///
+ /// The x.
+ /// The y.
+ /// The z.
+ ///
+ private int F3(int x, int y, int z)
+ {
+ return (x | ~y) ^ z;
+ }
+
+ ///
+ /// Rounds 48-63
+ ///
+ /// The x.
+ /// The y.
+ /// The z.
+ ///
+ private int F4(int x, int y, int z)
+ {
+ return (x & z) | (y & ~z);
+ }
+
+ ///
+ /// ounds 64-79
+ ///
+ /// The x.
+ /// The y.
+ /// The z.
+ ///
+ private int F5(int x, int y, int z)
+ {
+ return x ^ (y | ~z);
+ }
+
+ private void ProcessBlock()
+ {
+ int a, aa;
+ int b, bb;
+ int c, cc;
+ int d, dd;
+ int e, ee;
+
+ a = aa = H0;
+ b = bb = H1;
+ c = cc = H2;
+ d = dd = H3;
+ e = ee = H4;
+
+ //
+ // Rounds 1 - 16
+ //
+ // left
+ a = RL(a + F1(b, c, d) + this.X[0], 11) + e; c = RL(c, 10);
+ e = RL(e + F1(a, b, c) + this.X[1], 14) + d; b = RL(b, 10);
+ d = RL(d + F1(e, a, b) + this.X[2], 15) + c; a = RL(a, 10);
+ c = RL(c + F1(d, e, a) + this.X[3], 12) + b; e = RL(e, 10);
+ b = RL(b + F1(c, d, e) + this.X[4], 5) + a; d = RL(d, 10);
+ a = RL(a + F1(b, c, d) + this.X[5], 8) + e; c = RL(c, 10);
+ e = RL(e + F1(a, b, c) + this.X[6], 7) + d; b = RL(b, 10);
+ d = RL(d + F1(e, a, b) + this.X[7], 9) + c; a = RL(a, 10);
+ c = RL(c + F1(d, e, a) + this.X[8], 11) + b; e = RL(e, 10);
+ b = RL(b + F1(c, d, e) + this.X[9], 13) + a; d = RL(d, 10);
+ a = RL(a + F1(b, c, d) + this.X[10], 14) + e; c = RL(c, 10);
+ e = RL(e + F1(a, b, c) + this.X[11], 15) + d; b = RL(b, 10);
+ d = RL(d + F1(e, a, b) + this.X[12], 6) + c; a = RL(a, 10);
+ c = RL(c + F1(d, e, a) + this.X[13], 7) + b; e = RL(e, 10);
+ b = RL(b + F1(c, d, e) + this.X[14], 9) + a; d = RL(d, 10);
+ a = RL(a + F1(b, c, d) + this.X[15], 8) + e; c = RL(c, 10);
+
+ // right
+ aa = RL(aa + F5(bb, cc, dd) + this.X[5] + unchecked((int)0x50a28be6), 8) + ee; cc = RL(cc, 10);
+ ee = RL(ee + F5(aa, bb, cc) + this.X[14] + unchecked((int)0x50a28be6), 9) + dd; bb = RL(bb, 10);
+ dd = RL(dd + F5(ee, aa, bb) + this.X[7] + unchecked((int)0x50a28be6), 9) + cc; aa = RL(aa, 10);
+ cc = RL(cc + F5(dd, ee, aa) + this.X[0] + unchecked((int)0x50a28be6), 11) + bb; ee = RL(ee, 10);
+ bb = RL(bb + F5(cc, dd, ee) + this.X[9] + unchecked((int)0x50a28be6), 13) + aa; dd = RL(dd, 10);
+ aa = RL(aa + F5(bb, cc, dd) + this.X[2] + unchecked((int)0x50a28be6), 15) + ee; cc = RL(cc, 10);
+ ee = RL(ee + F5(aa, bb, cc) + this.X[11] + unchecked((int)0x50a28be6), 15) + dd; bb = RL(bb, 10);
+ dd = RL(dd + F5(ee, aa, bb) + this.X[4] + unchecked((int)0x50a28be6), 5) + cc; aa = RL(aa, 10);
+ cc = RL(cc + F5(dd, ee, aa) + this.X[13] + unchecked((int)0x50a28be6), 7) + bb; ee = RL(ee, 10);
+ bb = RL(bb + F5(cc, dd, ee) + this.X[6] + unchecked((int)0x50a28be6), 7) + aa; dd = RL(dd, 10);
+ aa = RL(aa + F5(bb, cc, dd) + this.X[15] + unchecked((int)0x50a28be6), 8) + ee; cc = RL(cc, 10);
+ ee = RL(ee + F5(aa, bb, cc) + this.X[8] + unchecked((int)0x50a28be6), 11) + dd; bb = RL(bb, 10);
+ dd = RL(dd + F5(ee, aa, bb) + this.X[1] + unchecked((int)0x50a28be6), 14) + cc; aa = RL(aa, 10);
+ cc = RL(cc + F5(dd, ee, aa) + this.X[10] + unchecked((int)0x50a28be6), 14) + bb; ee = RL(ee, 10);
+ bb = RL(bb + F5(cc, dd, ee) + this.X[3] + unchecked((int)0x50a28be6), 12) + aa; dd = RL(dd, 10);
+ aa = RL(aa + F5(bb, cc, dd) + this.X[12] + unchecked((int)0x50a28be6), 6) + ee; cc = RL(cc, 10);
+
+ //
+ // Rounds 16-31
+ //
+ // left
+ e = RL(e + F2(a, b, c) + this.X[7] + unchecked((int)0x5a827999), 7) + d; b = RL(b, 10);
+ d = RL(d + F2(e, a, b) + this.X[4] + unchecked((int)0x5a827999), 6) + c; a = RL(a, 10);
+ c = RL(c + F2(d, e, a) + this.X[13] + unchecked((int)0x5a827999), 8) + b; e = RL(e, 10);
+ b = RL(b + F2(c, d, e) + this.X[1] + unchecked((int)0x5a827999), 13) + a; d = RL(d, 10);
+ a = RL(a + F2(b, c, d) + this.X[10] + unchecked((int)0x5a827999), 11) + e; c = RL(c, 10);
+ e = RL(e + F2(a, b, c) + this.X[6] + unchecked((int)0x5a827999), 9) + d; b = RL(b, 10);
+ d = RL(d + F2(e, a, b) + this.X[15] + unchecked((int)0x5a827999), 7) + c; a = RL(a, 10);
+ c = RL(c + F2(d, e, a) + this.X[3] + unchecked((int)0x5a827999), 15) + b; e = RL(e, 10);
+ b = RL(b + F2(c, d, e) + this.X[12] + unchecked((int)0x5a827999), 7) + a; d = RL(d, 10);
+ a = RL(a + F2(b, c, d) + this.X[0] + unchecked((int)0x5a827999), 12) + e; c = RL(c, 10);
+ e = RL(e + F2(a, b, c) + this.X[9] + unchecked((int)0x5a827999), 15) + d; b = RL(b, 10);
+ d = RL(d + F2(e, a, b) + this.X[5] + unchecked((int)0x5a827999), 9) + c; a = RL(a, 10);
+ c = RL(c + F2(d, e, a) + this.X[2] + unchecked((int)0x5a827999), 11) + b; e = RL(e, 10);
+ b = RL(b + F2(c, d, e) + this.X[14] + unchecked((int)0x5a827999), 7) + a; d = RL(d, 10);
+ a = RL(a + F2(b, c, d) + this.X[11] + unchecked((int)0x5a827999), 13) + e; c = RL(c, 10);
+ e = RL(e + F2(a, b, c) + this.X[8] + unchecked((int)0x5a827999), 12) + d; b = RL(b, 10);
+
+ // right
+ ee = RL(ee + F4(aa, bb, cc) + this.X[6] + unchecked((int)0x5c4dd124), 9) + dd; bb = RL(bb, 10);
+ dd = RL(dd + F4(ee, aa, bb) + this.X[11] + unchecked((int)0x5c4dd124), 13) + cc; aa = RL(aa, 10);
+ cc = RL(cc + F4(dd, ee, aa) + this.X[3] + unchecked((int)0x5c4dd124), 15) + bb; ee = RL(ee, 10);
+ bb = RL(bb + F4(cc, dd, ee) + this.X[7] + unchecked((int)0x5c4dd124), 7) + aa; dd = RL(dd, 10);
+ aa = RL(aa + F4(bb, cc, dd) + this.X[0] + unchecked((int)0x5c4dd124), 12) + ee; cc = RL(cc, 10);
+ ee = RL(ee + F4(aa, bb, cc) + this.X[13] + unchecked((int)0x5c4dd124), 8) + dd; bb = RL(bb, 10);
+ dd = RL(dd + F4(ee, aa, bb) + this.X[5] + unchecked((int)0x5c4dd124), 9) + cc; aa = RL(aa, 10);
+ cc = RL(cc + F4(dd, ee, aa) + this.X[10] + unchecked((int)0x5c4dd124), 11) + bb; ee = RL(ee, 10);
+ bb = RL(bb + F4(cc, dd, ee) + this.X[14] + unchecked((int)0x5c4dd124), 7) + aa; dd = RL(dd, 10);
+ aa = RL(aa + F4(bb, cc, dd) + this.X[15] + unchecked((int)0x5c4dd124), 7) + ee; cc = RL(cc, 10);
+ ee = RL(ee + F4(aa, bb, cc) + this.X[8] + unchecked((int)0x5c4dd124), 12) + dd; bb = RL(bb, 10);
+ dd = RL(dd + F4(ee, aa, bb) + this.X[12] + unchecked((int)0x5c4dd124), 7) + cc; aa = RL(aa, 10);
+ cc = RL(cc + F4(dd, ee, aa) + this.X[4] + unchecked((int)0x5c4dd124), 6) + bb; ee = RL(ee, 10);
+ bb = RL(bb + F4(cc, dd, ee) + this.X[9] + unchecked((int)0x5c4dd124), 15) + aa; dd = RL(dd, 10);
+ aa = RL(aa + F4(bb, cc, dd) + this.X[1] + unchecked((int)0x5c4dd124), 13) + ee; cc = RL(cc, 10);
+ ee = RL(ee + F4(aa, bb, cc) + this.X[2] + unchecked((int)0x5c4dd124), 11) + dd; bb = RL(bb, 10);
+
+ //
+ // Rounds 32-47
+ //
+ // left
+ d = RL(d + F3(e, a, b) + this.X[3] + unchecked((int)0x6ed9eba1), 11) + c; a = RL(a, 10);
+ c = RL(c + F3(d, e, a) + this.X[10] + unchecked((int)0x6ed9eba1), 13) + b; e = RL(e, 10);
+ b = RL(b + F3(c, d, e) + this.X[14] + unchecked((int)0x6ed9eba1), 6) + a; d = RL(d, 10);
+ a = RL(a + F3(b, c, d) + this.X[4] + unchecked((int)0x6ed9eba1), 7) + e; c = RL(c, 10);
+ e = RL(e + F3(a, b, c) + this.X[9] + unchecked((int)0x6ed9eba1), 14) + d; b = RL(b, 10);
+ d = RL(d + F3(e, a, b) + this.X[15] + unchecked((int)0x6ed9eba1), 9) + c; a = RL(a, 10);
+ c = RL(c + F3(d, e, a) + this.X[8] + unchecked((int)0x6ed9eba1), 13) + b; e = RL(e, 10);
+ b = RL(b + F3(c, d, e) + this.X[1] + unchecked((int)0x6ed9eba1), 15) + a; d = RL(d, 10);
+ a = RL(a + F3(b, c, d) + this.X[2] + unchecked((int)0x6ed9eba1), 14) + e; c = RL(c, 10);
+ e = RL(e + F3(a, b, c) + this.X[7] + unchecked((int)0x6ed9eba1), 8) + d; b = RL(b, 10);
+ d = RL(d + F3(e, a, b) + this.X[0] + unchecked((int)0x6ed9eba1), 13) + c; a = RL(a, 10);
+ c = RL(c + F3(d, e, a) + this.X[6] + unchecked((int)0x6ed9eba1), 6) + b; e = RL(e, 10);
+ b = RL(b + F3(c, d, e) + this.X[13] + unchecked((int)0x6ed9eba1), 5) + a; d = RL(d, 10);
+ a = RL(a + F3(b, c, d) + this.X[11] + unchecked((int)0x6ed9eba1), 12) + e; c = RL(c, 10);
+ e = RL(e + F3(a, b, c) + this.X[5] + unchecked((int)0x6ed9eba1), 7) + d; b = RL(b, 10);
+ d = RL(d + F3(e, a, b) + this.X[12] + unchecked((int)0x6ed9eba1), 5) + c; a = RL(a, 10);
+
+ // right
+ dd = RL(dd + F3(ee, aa, bb) + this.X[15] + unchecked((int)0x6d703ef3), 9) + cc; aa = RL(aa, 10);
+ cc = RL(cc + F3(dd, ee, aa) + this.X[5] + unchecked((int)0x6d703ef3), 7) + bb; ee = RL(ee, 10);
+ bb = RL(bb + F3(cc, dd, ee) + this.X[1] + unchecked((int)0x6d703ef3), 15) + aa; dd = RL(dd, 10);
+ aa = RL(aa + F3(bb, cc, dd) + this.X[3] + unchecked((int)0x6d703ef3), 11) + ee; cc = RL(cc, 10);
+ ee = RL(ee + F3(aa, bb, cc) + this.X[7] + unchecked((int)0x6d703ef3), 8) + dd; bb = RL(bb, 10);
+ dd = RL(dd + F3(ee, aa, bb) + this.X[14] + unchecked((int)0x6d703ef3), 6) + cc; aa = RL(aa, 10);
+ cc = RL(cc + F3(dd, ee, aa) + this.X[6] + unchecked((int)0x6d703ef3), 6) + bb; ee = RL(ee, 10);
+ bb = RL(bb + F3(cc, dd, ee) + this.X[9] + unchecked((int)0x6d703ef3), 14) + aa; dd = RL(dd, 10);
+ aa = RL(aa + F3(bb, cc, dd) + this.X[11] + unchecked((int)0x6d703ef3), 12) + ee; cc = RL(cc, 10);
+ ee = RL(ee + F3(aa, bb, cc) + this.X[8] + unchecked((int)0x6d703ef3), 13) + dd; bb = RL(bb, 10);
+ dd = RL(dd + F3(ee, aa, bb) + this.X[12] + unchecked((int)0x6d703ef3), 5) + cc; aa = RL(aa, 10);
+ cc = RL(cc + F3(dd, ee, aa) + this.X[2] + unchecked((int)0x6d703ef3), 14) + bb; ee = RL(ee, 10);
+ bb = RL(bb + F3(cc, dd, ee) + this.X[10] + unchecked((int)0x6d703ef3), 13) + aa; dd = RL(dd, 10);
+ aa = RL(aa + F3(bb, cc, dd) + this.X[0] + unchecked((int)0x6d703ef3), 13) + ee; cc = RL(cc, 10);
+ ee = RL(ee + F3(aa, bb, cc) + this.X[4] + unchecked((int)0x6d703ef3), 7) + dd; bb = RL(bb, 10);
+ dd = RL(dd + F3(ee, aa, bb) + this.X[13] + unchecked((int)0x6d703ef3), 5) + cc; aa = RL(aa, 10);
+
+ //
+ // Rounds 48-63
+ //
+ // left
+ c = RL(c + F4(d, e, a) + this.X[1] + unchecked((int)0x8f1bbcdc), 11) + b; e = RL(e, 10);
+ b = RL(b + F4(c, d, e) + this.X[9] + unchecked((int)0x8f1bbcdc), 12) + a; d = RL(d, 10);
+ a = RL(a + F4(b, c, d) + this.X[11] + unchecked((int)0x8f1bbcdc), 14) + e; c = RL(c, 10);
+ e = RL(e + F4(a, b, c) + this.X[10] + unchecked((int)0x8f1bbcdc), 15) + d; b = RL(b, 10);
+ d = RL(d + F4(e, a, b) + this.X[0] + unchecked((int)0x8f1bbcdc), 14) + c; a = RL(a, 10);
+ c = RL(c + F4(d, e, a) + this.X[8] + unchecked((int)0x8f1bbcdc), 15) + b; e = RL(e, 10);
+ b = RL(b + F4(c, d, e) + this.X[12] + unchecked((int)0x8f1bbcdc), 9) + a; d = RL(d, 10);
+ a = RL(a + F4(b, c, d) + this.X[4] + unchecked((int)0x8f1bbcdc), 8) + e; c = RL(c, 10);
+ e = RL(e + F4(a, b, c) + this.X[13] + unchecked((int)0x8f1bbcdc), 9) + d; b = RL(b, 10);
+ d = RL(d + F4(e, a, b) + this.X[3] + unchecked((int)0x8f1bbcdc), 14) + c; a = RL(a, 10);
+ c = RL(c + F4(d, e, a) + this.X[7] + unchecked((int)0x8f1bbcdc), 5) + b; e = RL(e, 10);
+ b = RL(b + F4(c, d, e) + this.X[15] + unchecked((int)0x8f1bbcdc), 6) + a; d = RL(d, 10);
+ a = RL(a + F4(b, c, d) + this.X[14] + unchecked((int)0x8f1bbcdc), 8) + e; c = RL(c, 10);
+ e = RL(e + F4(a, b, c) + this.X[5] + unchecked((int)0x8f1bbcdc), 6) + d; b = RL(b, 10);
+ d = RL(d + F4(e, a, b) + this.X[6] + unchecked((int)0x8f1bbcdc), 5) + c; a = RL(a, 10);
+ c = RL(c + F4(d, e, a) + this.X[2] + unchecked((int)0x8f1bbcdc), 12) + b; e = RL(e, 10);
+
+ // right
+ cc = RL(cc + F2(dd, ee, aa) + this.X[8] + unchecked((int)0x7a6d76e9), 15) + bb; ee = RL(ee, 10);
+ bb = RL(bb + F2(cc, dd, ee) + this.X[6] + unchecked((int)0x7a6d76e9), 5) + aa; dd = RL(dd, 10);
+ aa = RL(aa + F2(bb, cc, dd) + this.X[4] + unchecked((int)0x7a6d76e9), 8) + ee; cc = RL(cc, 10);
+ ee = RL(ee + F2(aa, bb, cc) + this.X[1] + unchecked((int)0x7a6d76e9), 11) + dd; bb = RL(bb, 10);
+ dd = RL(dd + F2(ee, aa, bb) + this.X[3] + unchecked((int)0x7a6d76e9), 14) + cc; aa = RL(aa, 10);
+ cc = RL(cc + F2(dd, ee, aa) + this.X[11] + unchecked((int)0x7a6d76e9), 14) + bb; ee = RL(ee, 10);
+ bb = RL(bb + F2(cc, dd, ee) + this.X[15] + unchecked((int)0x7a6d76e9), 6) + aa; dd = RL(dd, 10);
+ aa = RL(aa + F2(bb, cc, dd) + this.X[0] + unchecked((int)0x7a6d76e9), 14) + ee; cc = RL(cc, 10);
+ ee = RL(ee + F2(aa, bb, cc) + this.X[5] + unchecked((int)0x7a6d76e9), 6) + dd; bb = RL(bb, 10);
+ dd = RL(dd + F2(ee, aa, bb) + this.X[12] + unchecked((int)0x7a6d76e9), 9) + cc; aa = RL(aa, 10);
+ cc = RL(cc + F2(dd, ee, aa) + this.X[2] + unchecked((int)0x7a6d76e9), 12) + bb; ee = RL(ee, 10);
+ bb = RL(bb + F2(cc, dd, ee) + this.X[13] + unchecked((int)0x7a6d76e9), 9) + aa; dd = RL(dd, 10);
+ aa = RL(aa + F2(bb, cc, dd) + this.X[9] + unchecked((int)0x7a6d76e9), 12) + ee; cc = RL(cc, 10);
+ ee = RL(ee + F2(aa, bb, cc) + this.X[7] + unchecked((int)0x7a6d76e9), 5) + dd; bb = RL(bb, 10);
+ dd = RL(dd + F2(ee, aa, bb) + this.X[10] + unchecked((int)0x7a6d76e9), 15) + cc; aa = RL(aa, 10);
+ cc = RL(cc + F2(dd, ee, aa) + this.X[14] + unchecked((int)0x7a6d76e9), 8) + bb; ee = RL(ee, 10);
+
+ //
+ // Rounds 64-79
+ //
+ // left
+ b = RL(b + F5(c, d, e) + this.X[4] + unchecked((int)0xa953fd4e), 9) + a; d = RL(d, 10);
+ a = RL(a + F5(b, c, d) + this.X[0] + unchecked((int)0xa953fd4e), 15) + e; c = RL(c, 10);
+ e = RL(e + F5(a, b, c) + this.X[5] + unchecked((int)0xa953fd4e), 5) + d; b = RL(b, 10);
+ d = RL(d + F5(e, a, b) + this.X[9] + unchecked((int)0xa953fd4e), 11) + c; a = RL(a, 10);
+ c = RL(c + F5(d, e, a) + this.X[7] + unchecked((int)0xa953fd4e), 6) + b; e = RL(e, 10);
+ b = RL(b + F5(c, d, e) + this.X[12] + unchecked((int)0xa953fd4e), 8) + a; d = RL(d, 10);
+ a = RL(a + F5(b, c, d) + this.X[2] + unchecked((int)0xa953fd4e), 13) + e; c = RL(c, 10);
+ e = RL(e + F5(a, b, c) + this.X[10] + unchecked((int)0xa953fd4e), 12) + d; b = RL(b, 10);
+ d = RL(d + F5(e, a, b) + this.X[14] + unchecked((int)0xa953fd4e), 5) + c; a = RL(a, 10);
+ c = RL(c + F5(d, e, a) + this.X[1] + unchecked((int)0xa953fd4e), 12) + b; e = RL(e, 10);
+ b = RL(b + F5(c, d, e) + this.X[3] + unchecked((int)0xa953fd4e), 13) + a; d = RL(d, 10);
+ a = RL(a + F5(b, c, d) + this.X[8] + unchecked((int)0xa953fd4e), 14) + e; c = RL(c, 10);
+ e = RL(e + F5(a, b, c) + this.X[11] + unchecked((int)0xa953fd4e), 11) + d; b = RL(b, 10);
+ d = RL(d + F5(e, a, b) + this.X[6] + unchecked((int)0xa953fd4e), 8) + c; a = RL(a, 10);
+ c = RL(c + F5(d, e, a) + this.X[15] + unchecked((int)0xa953fd4e), 5) + b; e = RL(e, 10);
+ b = RL(b + F5(c, d, e) + this.X[13] + unchecked((int)0xa953fd4e), 6) + a; d = RL(d, 10);
+
+ // right
+ bb = RL(bb + F1(cc, dd, ee) + this.X[12], 8) + aa; dd = RL(dd, 10);
+ aa = RL(aa + F1(bb, cc, dd) + this.X[15], 5) + ee; cc = RL(cc, 10);
+ ee = RL(ee + F1(aa, bb, cc) + this.X[10], 12) + dd; bb = RL(bb, 10);
+ dd = RL(dd + F1(ee, aa, bb) + this.X[4], 9) + cc; aa = RL(aa, 10);
+ cc = RL(cc + F1(dd, ee, aa) + this.X[1], 12) + bb; ee = RL(ee, 10);
+ bb = RL(bb + F1(cc, dd, ee) + this.X[5], 5) + aa; dd = RL(dd, 10);
+ aa = RL(aa + F1(bb, cc, dd) + this.X[8], 14) + ee; cc = RL(cc, 10);
+ ee = RL(ee + F1(aa, bb, cc) + this.X[7], 6) + dd; bb = RL(bb, 10);
+ dd = RL(dd + F1(ee, aa, bb) + this.X[6], 8) + cc; aa = RL(aa, 10);
+ cc = RL(cc + F1(dd, ee, aa) + this.X[2], 13) + bb; ee = RL(ee, 10);
+ bb = RL(bb + F1(cc, dd, ee) + this.X[13], 6) + aa; dd = RL(dd, 10);
+ aa = RL(aa + F1(bb, cc, dd) + this.X[14], 5) + ee; cc = RL(cc, 10);
+ ee = RL(ee + F1(aa, bb, cc) + this.X[0], 15) + dd; bb = RL(bb, 10);
+ dd = RL(dd + F1(ee, aa, bb) + this.X[3], 13) + cc; aa = RL(aa, 10);
+ cc = RL(cc + F1(dd, ee, aa) + this.X[9], 11) + bb; ee = RL(ee, 10);
+ bb = RL(bb + F1(cc, dd, ee) + this.X[11], 11) + aa; dd = RL(dd, 10);
+
+ dd += c + H1;
+ H1 = H2 + d + ee;
+ H2 = H3 + e + aa;
+ H3 = H4 + a + bb;
+ H4 = H0 + b + cc;
+ H0 = dd;
+
+ //
+ // reset the offset and clean out the word buffer.
+ //
+ this._offset = 0;
+ for (int i = 0; i < X.Length; i++)
+ {
+ this.X[i] = 0;
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/Renci.SshNet/Security/Cryptography/Hashes/SHA1Hash.cs b/Renci.SshNet/Security/Cryptography/Hashes/SHA1Hash.cs
index 268ae0f..ad2aa66 100644
--- a/Renci.SshNet/Security/Cryptography/Hashes/SHA1Hash.cs
+++ b/Renci.SshNet/Security/Cryptography/Hashes/SHA1Hash.cs
@@ -1,573 +1,571 @@
-using System.Security.Cryptography;
-using System;
-
-namespace Renci.SshNet.Security.Cryptography
-{
- ///
- /// SHA1 algorithm implementation
- ///
- public sealed class SHA1Hash : HashAlgorithm
- {
- private const int DIGEST_SIZE = 20;
-
- private const uint Y1 = 0x5a827999;
-
- private const uint Y2 = 0x6ed9eba1;
-
- private const uint Y3 = 0x8f1bbcdc;
-
- private const uint Y4 = 0xca62c1d6;
-
- private uint H1, H2, H3, H4, H5;
-
- private uint[] _hashValue = new uint[80];
-
- private int _offset;
-
- private byte[] _buffer;
-
- private int _bufferOffset;
-
- private long _byteCount;
-
- ///
- /// Gets the size, in bits, of the computed hash code.
- ///
- /// The size, in bits, of the computed hash code.
- public override int HashSize
- {
- get
- {
- return DIGEST_SIZE * 8;
- }
- }
-
- ///
- /// Gets the input block size.
- ///
- /// The input block size.
- public override int InputBlockSize
- {
- get
- {
- return 64;
- }
- }
-
- ///
- /// Gets the output block size.
- ///
- /// The output block size.
- public override int OutputBlockSize
- {
- get
- {
- return 64;
- }
- }
-
- ///
- /// Gets a value indicating whether the current transform can be reused.
- ///
- /// Always true.
- public override bool CanReuseTransform
- {
- get
- {
- return true;
- }
- }
-
- ///
- /// Gets a value indicating whether multiple blocks can be transformed.
- ///
- /// true if multiple blocks can be transformed; otherwise, false.
- public override bool CanTransformMultipleBlocks
- {
- get
- {
- return true;
- }
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- public SHA1Hash()
- {
- this._buffer = new byte[4];
- this.InternalInitialize();
- }
-
- ///
- /// Routes data written to the object into the hash algorithm for computing the hash.
- ///
- /// The input to compute the hash code for.
- /// The offset into the byte array from which to begin using data.
- /// The number of bytes in the byte array to use as data.
- protected override void HashCore(byte[] array, int ibStart, int cbSize)
- {
- // Fill the current word
- while ((this._bufferOffset != 0) && (cbSize > 0))
- {
- this.Update(array[ibStart]);
- ibStart++;
- cbSize--;
- }
-
- // Process whole words.
- while (cbSize > this._buffer.Length)
- {
- this.ProcessWord(array, ibStart);
-
- ibStart += this._buffer.Length;
- cbSize -= this._buffer.Length;
- this._byteCount += this._buffer.Length;
- }
-
- // Load in the remainder.
- while (cbSize > 0)
- {
- this.Update(array[ibStart]);
-
- ibStart++;
- cbSize--;
- }
- }
-
- ///
- /// Finalizes the hash computation after the last data is processed by the cryptographic stream object.
- ///
- ///
- /// The computed hash code.
- ///
- protected override byte[] HashFinal()
- {
- var output = new byte[DIGEST_SIZE];
- long bitLength = (this._byteCount << 3);
-
- //
- // add the pad bytes.
- //
- this.Update((byte)128);
-
- while (this._bufferOffset != 0)
- this.Update((byte)0);
-
- if (this._offset > 14)
- {
- this.ProcessBlock();
- }
-
- this._hashValue[14] = (uint)((ulong)bitLength >> 32);
- this._hashValue[15] = (uint)((ulong)bitLength);
-
-
- this.ProcessBlock();
-
- UInt32ToBigEndian(H1, output, 0);
- UInt32ToBigEndian(H2, output, 4);
- UInt32ToBigEndian(H3, output, 8);
- UInt32ToBigEndian(H4, output, 12);
- UInt32ToBigEndian(H5, output, 16);
-
- this.Initialize();
-
- return output;
- }
-
- ///
- /// Initializes an implementation of the class.
- ///
- public override void Initialize()
- {
- this.InternalInitialize();
- }
-
- private void InternalInitialize()
- {
- var i = 0;
- this._byteCount = 0;
- this._bufferOffset = 0;
- for (i = 0; i < 4; i++)
- {
- this._buffer[i] = 0;
- }
-
- H1 = 0x67452301;
- H2 = 0xefcdab89;
- H3 = 0x98badcfe;
- H4 = 0x10325476;
- H5 = 0xc3d2e1f0;
-
- this._offset = 0;
- for (i = 0; i != this._hashValue.Length; i++)
- {
- this._hashValue[i] = 0;
- }
- }
-
- private void Update(byte input)
- {
- this._buffer[this._bufferOffset++] = input;
-
- if (this._bufferOffset == this._buffer.Length)
- {
- this.ProcessWord(this._buffer, 0);
- this._bufferOffset = 0;
- }
-
- this._byteCount++;
- }
-
- private void ProcessWord(byte[] input, int inOff)
- {
- this._hashValue[this._offset] = BigEndianToUInt32(input, inOff);
-
- if (++this._offset == 16)
- {
- this.ProcessBlock();
- }
- }
-
- private static uint F(uint u, uint v, uint w)
- {
- return (u & v) | (~u & w);
- }
-
- private static uint H(uint u, uint v, uint w)
- {
- return u ^ v ^ w;
- }
-
- private static uint G(uint u, uint v, uint w)
- {
- return (u & v) | (u & w) | (v & w);
- }
-
- private void ProcessBlock()
- {
- //
- // expand 16 word block into 80 word block.
- //
- for (int i = 16; i < 80; i++)
- {
- uint t = _hashValue[i - 3] ^ _hashValue[i - 8] ^ _hashValue[i - 14] ^ _hashValue[i - 16];
- _hashValue[i] = t << 1 | t >> 31;
- }
-
- //
- // set up working variables.
- //
- uint A = H1;
- uint B = H2;
- uint C = H3;
- uint D = H4;
- uint E = H5;
-
- //
- // round 1
- //
- int idx = 0;
-
- // E = rotateLeft(A, 5) + F(B, C, D) + E + X[idx++] + Y1
- // B = rotateLeft(B, 30)
- E += (A << 5 | (A >> 27)) + F(B, C, D) + _hashValue[idx++] + Y1;
- B = B << 30 | (B >> 2);
-
- D += (E << 5 | (E >> 27)) + F(A, B, C) + _hashValue[idx++] + Y1;
- A = A << 30 | (A >> 2);
-
- C += (D << 5 | (D >> 27)) + F(E, A, B) + _hashValue[idx++] + Y1;
- E = E << 30 | (E >> 2);
-
- B += (C << 5 | (C >> 27)) + F(D, E, A) + _hashValue[idx++] + Y1;
- D = D << 30 | (D >> 2);
-
- A += (B << 5 | (B >> 27)) + F(C, D, E) + _hashValue[idx++] + Y1;
- C = C << 30 | (C >> 2);
- // E = rotateLeft(A, 5) + F(B, C, D) + E + X[idx++] + Y1
- // B = rotateLeft(B, 30)
- E += (A << 5 | (A >> 27)) + F(B, C, D) + _hashValue[idx++] + Y1;
- B = B << 30 | (B >> 2);
-
- D += (E << 5 | (E >> 27)) + F(A, B, C) + _hashValue[idx++] + Y1;
- A = A << 30 | (A >> 2);
-
- C += (D << 5 | (D >> 27)) + F(E, A, B) + _hashValue[idx++] + Y1;
- E = E << 30 | (E >> 2);
-
- B += (C << 5 | (C >> 27)) + F(D, E, A) + _hashValue[idx++] + Y1;
- D = D << 30 | (D >> 2);
-
- A += (B << 5 | (B >> 27)) + F(C, D, E) + _hashValue[idx++] + Y1;
- C = C << 30 | (C >> 2);
- // E = rotateLeft(A, 5) + F(B, C, D) + E + X[idx++] + Y1
- // B = rotateLeft(B, 30)
- E += (A << 5 | (A >> 27)) + F(B, C, D) + _hashValue[idx++] + Y1;
- B = B << 30 | (B >> 2);
-
- D += (E << 5 | (E >> 27)) + F(A, B, C) + _hashValue[idx++] + Y1;
- A = A << 30 | (A >> 2);
-
- C += (D << 5 | (D >> 27)) + F(E, A, B) + _hashValue[idx++] + Y1;
- E = E << 30 | (E >> 2);
-
- B += (C << 5 | (C >> 27)) + F(D, E, A) + _hashValue[idx++] + Y1;
- D = D << 30 | (D >> 2);
-
- A += (B << 5 | (B >> 27)) + F(C, D, E) + _hashValue[idx++] + Y1;
- C = C << 30 | (C >> 2);
- // E = rotateLeft(A, 5) + F(B, C, D) + E + X[idx++] + Y1
- // B = rotateLeft(B, 30)
- E += (A << 5 | (A >> 27)) + F(B, C, D) + _hashValue[idx++] + Y1;
- B = B << 30 | (B >> 2);
-
- D += (E << 5 | (E >> 27)) + F(A, B, C) + _hashValue[idx++] + Y1;
- A = A << 30 | (A >> 2);
-
- C += (D << 5 | (D >> 27)) + F(E, A, B) + _hashValue[idx++] + Y1;
- E = E << 30 | (E >> 2);
-
- B += (C << 5 | (C >> 27)) + F(D, E, A) + _hashValue[idx++] + Y1;
- D = D << 30 | (D >> 2);
-
- A += (B << 5 | (B >> 27)) + F(C, D, E) + _hashValue[idx++] + Y1;
- C = C << 30 | (C >> 2);
- //
- // round 2
- //
- // E = rotateLeft(A, 5) + H(B, C, D) + E + X[idx++] + Y2
- // B = rotateLeft(B, 30)
- E += (A << 5 | (A >> 27)) + H(B, C, D) + _hashValue[idx++] + Y2;
- B = B << 30 | (B >> 2);
-
- D += (E << 5 | (E >> 27)) + H(A, B, C) + _hashValue[idx++] + Y2;
- A = A << 30 | (A >> 2);
-
- C += (D << 5 | (D >> 27)) + H(E, A, B) + _hashValue[idx++] + Y2;
- E = E << 30 | (E >> 2);
-
- B += (C << 5 | (C >> 27)) + H(D, E, A) + _hashValue[idx++] + Y2;
- D = D << 30 | (D >> 2);
-
- A += (B << 5 | (B >> 27)) + H(C, D, E) + _hashValue[idx++] + Y2;
- C = C << 30 | (C >> 2);
- // E = rotateLeft(A, 5) + H(B, C, D) + E + X[idx++] + Y2
- // B = rotateLeft(B, 30)
- E += (A << 5 | (A >> 27)) + H(B, C, D) + _hashValue[idx++] + Y2;
- B = B << 30 | (B >> 2);
-
- D += (E << 5 | (E >> 27)) + H(A, B, C) + _hashValue[idx++] + Y2;
- A = A << 30 | (A >> 2);
-
- C += (D << 5 | (D >> 27)) + H(E, A, B) + _hashValue[idx++] + Y2;
- E = E << 30 | (E >> 2);
-
- B += (C << 5 | (C >> 27)) + H(D, E, A) + _hashValue[idx++] + Y2;
- D = D << 30 | (D >> 2);
-
- A += (B << 5 | (B >> 27)) + H(C, D, E) + _hashValue[idx++] + Y2;
- C = C << 30 | (C >> 2);
- // E = rotateLeft(A, 5) + H(B, C, D) + E + X[idx++] + Y2
- // B = rotateLeft(B, 30)
- E += (A << 5 | (A >> 27)) + H(B, C, D) + _hashValue[idx++] + Y2;
- B = B << 30 | (B >> 2);
-
- D += (E << 5 | (E >> 27)) + H(A, B, C) + _hashValue[idx++] + Y2;
- A = A << 30 | (A >> 2);
-
- C += (D << 5 | (D >> 27)) + H(E, A, B) + _hashValue[idx++] + Y2;
- E = E << 30 | (E >> 2);
-
- B += (C << 5 | (C >> 27)) + H(D, E, A) + _hashValue[idx++] + Y2;
- D = D << 30 | (D >> 2);
-
- A += (B << 5 | (B >> 27)) + H(C, D, E) + _hashValue[idx++] + Y2;
- C = C << 30 | (C >> 2);
- // E = rotateLeft(A, 5) + H(B, C, D) + E + X[idx++] + Y2
- // B = rotateLeft(B, 30)
- E += (A << 5 | (A >> 27)) + H(B, C, D) + _hashValue[idx++] + Y2;
- B = B << 30 | (B >> 2);
-
- D += (E << 5 | (E >> 27)) + H(A, B, C) + _hashValue[idx++] + Y2;
- A = A << 30 | (A >> 2);
-
- C += (D << 5 | (D >> 27)) + H(E, A, B) + _hashValue[idx++] + Y2;
- E = E << 30 | (E >> 2);
-
- B += (C << 5 | (C >> 27)) + H(D, E, A) + _hashValue[idx++] + Y2;
- D = D << 30 | (D >> 2);
-
- A += (B << 5 | (B >> 27)) + H(C, D, E) + _hashValue[idx++] + Y2;
- C = C << 30 | (C >> 2);
-
- //
- // round 3
- // E = rotateLeft(A, 5) + G(B, C, D) + E + X[idx++] + Y3
- // B = rotateLeft(B, 30)
- E += (A << 5 | (A >> 27)) + G(B, C, D) + _hashValue[idx++] + Y3;
- B = B << 30 | (B >> 2);
-
- D += (E << 5 | (E >> 27)) + G(A, B, C) + _hashValue[idx++] + Y3;
- A = A << 30 | (A >> 2);
-
- C += (D << 5 | (D >> 27)) + G(E, A, B) + _hashValue[idx++] + Y3;
- E = E << 30 | (E >> 2);
-
- B += (C << 5 | (C >> 27)) + G(D, E, A) + _hashValue[idx++] + Y3;
- D = D << 30 | (D >> 2);
-
- A += (B << 5 | (B >> 27)) + G(C, D, E) + _hashValue[idx++] + Y3;
- C = C << 30 | (C >> 2);
- // E = rotateLeft(A, 5) + G(B, C, D) + E + X[idx++] + Y3
- // B = rotateLeft(B, 30)
- E += (A << 5 | (A >> 27)) + G(B, C, D) + _hashValue[idx++] + Y3;
- B = B << 30 | (B >> 2);
-
- D += (E << 5 | (E >> 27)) + G(A, B, C) + _hashValue[idx++] + Y3;
- A = A << 30 | (A >> 2);
-
- C += (D << 5 | (D >> 27)) + G(E, A, B) + _hashValue[idx++] + Y3;
- E = E << 30 | (E >> 2);
-
- B += (C << 5 | (C >> 27)) + G(D, E, A) + _hashValue[idx++] + Y3;
- D = D << 30 | (D >> 2);
-
- A += (B << 5 | (B >> 27)) + G(C, D, E) + _hashValue[idx++] + Y3;
- C = C << 30 | (C >> 2);
- // E = rotateLeft(A, 5) + G(B, C, D) + E + X[idx++] + Y3
- // B = rotateLeft(B, 30)
- E += (A << 5 | (A >> 27)) + G(B, C, D) + _hashValue[idx++] + Y3;
- B = B << 30 | (B >> 2);
-
- D += (E << 5 | (E >> 27)) + G(A, B, C) + _hashValue[idx++] + Y3;
- A = A << 30 | (A >> 2);
-
- C += (D << 5 | (D >> 27)) + G(E, A, B) + _hashValue[idx++] + Y3;
- E = E << 30 | (E >> 2);
-
- B += (C << 5 | (C >> 27)) + G(D, E, A) + _hashValue[idx++] + Y3;
- D = D << 30 | (D >> 2);
-
- A += (B << 5 | (B >> 27)) + G(C, D, E) + _hashValue[idx++] + Y3;
- C = C << 30 | (C >> 2);
- // E = rotateLeft(A, 5) + G(B, C, D) + E + X[idx++] + Y3
- // B = rotateLeft(B, 30)
- E += (A << 5 | (A >> 27)) + G(B, C, D) + _hashValue[idx++] + Y3;
- B = B << 30 | (B >> 2);
-
- D += (E << 5 | (E >> 27)) + G(A, B, C) + _hashValue[idx++] + Y3;
- A = A << 30 | (A >> 2);
-
- C += (D << 5 | (D >> 27)) + G(E, A, B) + _hashValue[idx++] + Y3;
- E = E << 30 | (E >> 2);
-
- B += (C << 5 | (C >> 27)) + G(D, E, A) + _hashValue[idx++] + Y3;
- D = D << 30 | (D >> 2);
-
- A += (B << 5 | (B >> 27)) + G(C, D, E) + _hashValue[idx++] + Y3;
- C = C << 30 | (C >> 2);
-
- //
- // round 4
- //
- // E = rotateLeft(A, 5) + H(B, C, D) + E + X[idx++] + Y4
- // B = rotateLeft(B, 30)
- E += (A << 5 | (A >> 27)) + H(B, C, D) + _hashValue[idx++] + Y4;
- B = B << 30 | (B >> 2);
-
- D += (E << 5 | (E >> 27)) + H(A, B, C) + _hashValue[idx++] + Y4;
- A = A << 30 | (A >> 2);
-
- C += (D << 5 | (D >> 27)) + H(E, A, B) + _hashValue[idx++] + Y4;
- E = E << 30 | (E >> 2);
-
- B += (C << 5 | (C >> 27)) + H(D, E, A) + _hashValue[idx++] + Y4;
- D = D << 30 | (D >> 2);
-
- A += (B << 5 | (B >> 27)) + H(C, D, E) + _hashValue[idx++] + Y4;
- C = C << 30 | (C >> 2);
- // E = rotateLeft(A, 5) + H(B, C, D) + E + X[idx++] + Y4
- // B = rotateLeft(B, 30)
- E += (A << 5 | (A >> 27)) + H(B, C, D) + _hashValue[idx++] + Y4;
- B = B << 30 | (B >> 2);
-
- D += (E << 5 | (E >> 27)) + H(A, B, C) + _hashValue[idx++] + Y4;
- A = A << 30 | (A >> 2);
-
- C += (D << 5 | (D >> 27)) + H(E, A, B) + _hashValue[idx++] + Y4;
- E = E << 30 | (E >> 2);
-
- B += (C << 5 | (C >> 27)) + H(D, E, A) + _hashValue[idx++] + Y4;
- D = D << 30 | (D >> 2);
-
- A += (B << 5 | (B >> 27)) + H(C, D, E) + _hashValue[idx++] + Y4;
- C = C << 30 | (C >> 2);
- // E = rotateLeft(A, 5) + H(B, C, D) + E + X[idx++] + Y4
- // B = rotateLeft(B, 30)
- E += (A << 5 | (A >> 27)) + H(B, C, D) + _hashValue[idx++] + Y4;
- B = B << 30 | (B >> 2);
-
- D += (E << 5 | (E >> 27)) + H(A, B, C) + _hashValue[idx++] + Y4;
- A = A << 30 | (A >> 2);
-
- C += (D << 5 | (D >> 27)) + H(E, A, B) + _hashValue[idx++] + Y4;
- E = E << 30 | (E >> 2);
-
- B += (C << 5 | (C >> 27)) + H(D, E, A) + _hashValue[idx++] + Y4;
- D = D << 30 | (D >> 2);
-
- A += (B << 5 | (B >> 27)) + H(C, D, E) + _hashValue[idx++] + Y4;
- C = C << 30 | (C >> 2);
- // E = rotateLeft(A, 5) + H(B, C, D) + E + X[idx++] + Y4
- // B = rotateLeft(B, 30)
- E += (A << 5 | (A >> 27)) + H(B, C, D) + _hashValue[idx++] + Y4;
- B = B << 30 | (B >> 2);
-
- D += (E << 5 | (E >> 27)) + H(A, B, C) + _hashValue[idx++] + Y4;
- A = A << 30 | (A >> 2);
-
- C += (D << 5 | (D >> 27)) + H(E, A, B) + _hashValue[idx++] + Y4;
- E = E << 30 | (E >> 2);
-
- B += (C << 5 | (C >> 27)) + H(D, E, A) + _hashValue[idx++] + Y4;
- D = D << 30 | (D >> 2);
-
- A += (B << 5 | (B >> 27)) + H(C, D, E) + _hashValue[idx++] + Y4;
- C = C << 30 | (C >> 2);
-
- H1 += A;
- H2 += B;
- H3 += C;
- H4 += D;
- H5 += E;
-
- //
- // reset start of the buffer.
- //
- this._offset = 0;
- for (int i = 0; i < this._hashValue.Length; i++)
- {
- this._hashValue[i] = 0;
- }
- }
-
- private static uint BigEndianToUInt32(byte[] bs, int off)
- {
- uint n = (uint)bs[off] << 24;
- n |= (uint)bs[++off] << 16;
- n |= (uint)bs[++off] << 8;
- n |= (uint)bs[++off];
- return n;
- }
-
- private static void UInt32ToBigEndian(uint n, byte[] bs, int off)
- {
- bs[off] = (byte)(n >> 24);
- bs[++off] = (byte)(n >> 16);
- bs[++off] = (byte)(n >> 8);
- bs[++off] = (byte)(n);
- }
- }
-}
+using System.Security.Cryptography;
+
+namespace Renci.SshNet.Security.Cryptography
+{
+ ///
+ /// SHA1 algorithm implementation
+ ///
+ public sealed class SHA1Hash : HashAlgorithm
+ {
+ private const int DIGEST_SIZE = 20;
+
+ private const uint Y1 = 0x5a827999;
+
+ private const uint Y2 = 0x6ed9eba1;
+
+ private const uint Y3 = 0x8f1bbcdc;
+
+ private const uint Y4 = 0xca62c1d6;
+
+ private uint H1, H2, H3, H4, H5;
+
+ private readonly uint[] _hashValue = new uint[80];
+
+ private int _offset;
+
+ private readonly byte[] _buffer;
+
+ private int _bufferOffset;
+
+ private long _byteCount;
+
+ ///
+ /// Gets the size, in bits, of the computed hash code.
+ ///
+ /// The size, in bits, of the computed hash code.
+ public override int HashSize
+ {
+ get
+ {
+ return DIGEST_SIZE * 8;
+ }
+ }
+
+ ///
+ /// Gets the input block size.
+ ///
+ /// The input block size.
+ public override int InputBlockSize
+ {
+ get
+ {
+ return 64;
+ }
+ }
+
+ ///
+ /// Gets the output block size.
+ ///
+ /// The output block size.
+ public override int OutputBlockSize
+ {
+ get
+ {
+ return 64;
+ }
+ }
+
+ ///
+ /// Gets a value indicating whether the current transform can be reused.
+ ///
+ /// Always true.
+ public override bool CanReuseTransform
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ ///
+ /// Gets a value indicating whether multiple blocks can be transformed.
+ ///
+ /// true if multiple blocks can be transformed; otherwise, false.
+ public override bool CanTransformMultipleBlocks
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public SHA1Hash()
+ {
+ this._buffer = new byte[4];
+ this.InternalInitialize();
+ }
+
+ ///
+ /// Routes data written to the object into the hash algorithm for computing the hash.
+ ///
+ /// The input to compute the hash code for.
+ /// The offset into the byte array from which to begin using data.
+ /// The number of bytes in the byte array to use as data.
+ protected override void HashCore(byte[] array, int ibStart, int cbSize)
+ {
+ // Fill the current word
+ while ((this._bufferOffset != 0) && (cbSize > 0))
+ {
+ this.Update(array[ibStart]);
+ ibStart++;
+ cbSize--;
+ }
+
+ // Process whole words.
+ while (cbSize > this._buffer.Length)
+ {
+ this.ProcessWord(array, ibStart);
+
+ ibStart += this._buffer.Length;
+ cbSize -= this._buffer.Length;
+ this._byteCount += this._buffer.Length;
+ }
+
+ // Load in the remainder.
+ while (cbSize > 0)
+ {
+ this.Update(array[ibStart]);
+
+ ibStart++;
+ cbSize--;
+ }
+ }
+
+ ///
+ /// Finalizes the hash computation after the last data is processed by the cryptographic stream object.
+ ///
+ ///
+ /// The computed hash code.
+ ///
+ protected override byte[] HashFinal()
+ {
+ var output = new byte[DIGEST_SIZE];
+ long bitLength = (this._byteCount << 3);
+
+ //
+ // add the pad bytes.
+ //
+ this.Update((byte)128);
+
+ while (this._bufferOffset != 0)
+ this.Update((byte)0);
+
+ if (this._offset > 14)
+ {
+ this.ProcessBlock();
+ }
+
+ this._hashValue[14] = (uint)((ulong)bitLength >> 32);
+ this._hashValue[15] = (uint)((ulong)bitLength);
+
+
+ this.ProcessBlock();
+
+ UInt32ToBigEndian(H1, output, 0);
+ UInt32ToBigEndian(H2, output, 4);
+ UInt32ToBigEndian(H3, output, 8);
+ UInt32ToBigEndian(H4, output, 12);
+ UInt32ToBigEndian(H5, output, 16);
+
+ this.Initialize();
+
+ return output;
+ }
+
+ ///
+ /// Initializes an implementation of the class.
+ ///
+ public override void Initialize()
+ {
+ this.InternalInitialize();
+ }
+
+ private void InternalInitialize()
+ {
+ this._byteCount = 0;
+ this._bufferOffset = 0;
+ for (var i = 0; i < 4; i++)
+ {
+ this._buffer[i] = 0;
+ }
+
+ H1 = 0x67452301;
+ H2 = 0xefcdab89;
+ H3 = 0x98badcfe;
+ H4 = 0x10325476;
+ H5 = 0xc3d2e1f0;
+
+ this._offset = 0;
+ for (var i = 0; i != this._hashValue.Length; i++)
+ {
+ this._hashValue[i] = 0;
+ }
+ }
+
+ private void Update(byte input)
+ {
+ this._buffer[this._bufferOffset++] = input;
+
+ if (this._bufferOffset == this._buffer.Length)
+ {
+ this.ProcessWord(this._buffer, 0);
+ this._bufferOffset = 0;
+ }
+
+ this._byteCount++;
+ }
+
+ private void ProcessWord(byte[] input, int inOff)
+ {
+ this._hashValue[this._offset] = BigEndianToUInt32(input, inOff);
+
+ if (++this._offset == 16)
+ {
+ this.ProcessBlock();
+ }
+ }
+
+ private static uint F(uint u, uint v, uint w)
+ {
+ return (u & v) | (~u & w);
+ }
+
+ private static uint H(uint u, uint v, uint w)
+ {
+ return u ^ v ^ w;
+ }
+
+ private static uint G(uint u, uint v, uint w)
+ {
+ return (u & v) | (u & w) | (v & w);
+ }
+
+ private void ProcessBlock()
+ {
+ //
+ // expand 16 word block into 80 word block.
+ //
+ for (int i = 16; i < 80; i++)
+ {
+ uint t = _hashValue[i - 3] ^ _hashValue[i - 8] ^ _hashValue[i - 14] ^ _hashValue[i - 16];
+ _hashValue[i] = t << 1 | t >> 31;
+ }
+
+ //
+ // set up working variables.
+ //
+ uint A = H1;
+ uint B = H2;
+ uint C = H3;
+ uint D = H4;
+ uint E = H5;
+
+ //
+ // round 1
+ //
+ int idx = 0;
+
+ // E = rotateLeft(A, 5) + F(B, C, D) + E + X[idx++] + Y1
+ // B = rotateLeft(B, 30)
+ E += (A << 5 | (A >> 27)) + F(B, C, D) + _hashValue[idx++] + Y1;
+ B = B << 30 | (B >> 2);
+
+ D += (E << 5 | (E >> 27)) + F(A, B, C) + _hashValue[idx++] + Y1;
+ A = A << 30 | (A >> 2);
+
+ C += (D << 5 | (D >> 27)) + F(E, A, B) + _hashValue[idx++] + Y1;
+ E = E << 30 | (E >> 2);
+
+ B += (C << 5 | (C >> 27)) + F(D, E, A) + _hashValue[idx++] + Y1;
+ D = D << 30 | (D >> 2);
+
+ A += (B << 5 | (B >> 27)) + F(C, D, E) + _hashValue[idx++] + Y1;
+ C = C << 30 | (C >> 2);
+ // E = rotateLeft(A, 5) + F(B, C, D) + E + X[idx++] + Y1
+ // B = rotateLeft(B, 30)
+ E += (A << 5 | (A >> 27)) + F(B, C, D) + _hashValue[idx++] + Y1;
+ B = B << 30 | (B >> 2);
+
+ D += (E << 5 | (E >> 27)) + F(A, B, C) + _hashValue[idx++] + Y1;
+ A = A << 30 | (A >> 2);
+
+ C += (D << 5 | (D >> 27)) + F(E, A, B) + _hashValue[idx++] + Y1;
+ E = E << 30 | (E >> 2);
+
+ B += (C << 5 | (C >> 27)) + F(D, E, A) + _hashValue[idx++] + Y1;
+ D = D << 30 | (D >> 2);
+
+ A += (B << 5 | (B >> 27)) + F(C, D, E) + _hashValue[idx++] + Y1;
+ C = C << 30 | (C >> 2);
+ // E = rotateLeft(A, 5) + F(B, C, D) + E + X[idx++] + Y1
+ // B = rotateLeft(B, 30)
+ E += (A << 5 | (A >> 27)) + F(B, C, D) + _hashValue[idx++] + Y1;
+ B = B << 30 | (B >> 2);
+
+ D += (E << 5 | (E >> 27)) + F(A, B, C) + _hashValue[idx++] + Y1;
+ A = A << 30 | (A >> 2);
+
+ C += (D << 5 | (D >> 27)) + F(E, A, B) + _hashValue[idx++] + Y1;
+ E = E << 30 | (E >> 2);
+
+ B += (C << 5 | (C >> 27)) + F(D, E, A) + _hashValue[idx++] + Y1;
+ D = D << 30 | (D >> 2);
+
+ A += (B << 5 | (B >> 27)) + F(C, D, E) + _hashValue[idx++] + Y1;
+ C = C << 30 | (C >> 2);
+ // E = rotateLeft(A, 5) + F(B, C, D) + E + X[idx++] + Y1
+ // B = rotateLeft(B, 30)
+ E += (A << 5 | (A >> 27)) + F(B, C, D) + _hashValue[idx++] + Y1;
+ B = B << 30 | (B >> 2);
+
+ D += (E << 5 | (E >> 27)) + F(A, B, C) + _hashValue[idx++] + Y1;
+ A = A << 30 | (A >> 2);
+
+ C += (D << 5 | (D >> 27)) + F(E, A, B) + _hashValue[idx++] + Y1;
+ E = E << 30 | (E >> 2);
+
+ B += (C << 5 | (C >> 27)) + F(D, E, A) + _hashValue[idx++] + Y1;
+ D = D << 30 | (D >> 2);
+
+ A += (B << 5 | (B >> 27)) + F(C, D, E) + _hashValue[idx++] + Y1;
+ C = C << 30 | (C >> 2);
+ //
+ // round 2
+ //
+ // E = rotateLeft(A, 5) + H(B, C, D) + E + X[idx++] + Y2
+ // B = rotateLeft(B, 30)
+ E += (A << 5 | (A >> 27)) + H(B, C, D) + _hashValue[idx++] + Y2;
+ B = B << 30 | (B >> 2);
+
+ D += (E << 5 | (E >> 27)) + H(A, B, C) + _hashValue[idx++] + Y2;
+ A = A << 30 | (A >> 2);
+
+ C += (D << 5 | (D >> 27)) + H(E, A, B) + _hashValue[idx++] + Y2;
+ E = E << 30 | (E >> 2);
+
+ B += (C << 5 | (C >> 27)) + H(D, E, A) + _hashValue[idx++] + Y2;
+ D = D << 30 | (D >> 2);
+
+ A += (B << 5 | (B >> 27)) + H(C, D, E) + _hashValue[idx++] + Y2;
+ C = C << 30 | (C >> 2);
+ // E = rotateLeft(A, 5) + H(B, C, D) + E + X[idx++] + Y2
+ // B = rotateLeft(B, 30)
+ E += (A << 5 | (A >> 27)) + H(B, C, D) + _hashValue[idx++] + Y2;
+ B = B << 30 | (B >> 2);
+
+ D += (E << 5 | (E >> 27)) + H(A, B, C) + _hashValue[idx++] + Y2;
+ A = A << 30 | (A >> 2);
+
+ C += (D << 5 | (D >> 27)) + H(E, A, B) + _hashValue[idx++] + Y2;
+ E = E << 30 | (E >> 2);
+
+ B += (C << 5 | (C >> 27)) + H(D, E, A) + _hashValue[idx++] + Y2;
+ D = D << 30 | (D >> 2);
+
+ A += (B << 5 | (B >> 27)) + H(C, D, E) + _hashValue[idx++] + Y2;
+ C = C << 30 | (C >> 2);
+ // E = rotateLeft(A, 5) + H(B, C, D) + E + X[idx++] + Y2
+ // B = rotateLeft(B, 30)
+ E += (A << 5 | (A >> 27)) + H(B, C, D) + _hashValue[idx++] + Y2;
+ B = B << 30 | (B >> 2);
+
+ D += (E << 5 | (E >> 27)) + H(A, B, C) + _hashValue[idx++] + Y2;
+ A = A << 30 | (A >> 2);
+
+ C += (D << 5 | (D >> 27)) + H(E, A, B) + _hashValue[idx++] + Y2;
+ E = E << 30 | (E >> 2);
+
+ B += (C << 5 | (C >> 27)) + H(D, E, A) + _hashValue[idx++] + Y2;
+ D = D << 30 | (D >> 2);
+
+ A += (B << 5 | (B >> 27)) + H(C, D, E) + _hashValue[idx++] + Y2;
+ C = C << 30 | (C >> 2);
+ // E = rotateLeft(A, 5) + H(B, C, D) + E + X[idx++] + Y2
+ // B = rotateLeft(B, 30)
+ E += (A << 5 | (A >> 27)) + H(B, C, D) + _hashValue[idx++] + Y2;
+ B = B << 30 | (B >> 2);
+
+ D += (E << 5 | (E >> 27)) + H(A, B, C) + _hashValue[idx++] + Y2;
+ A = A << 30 | (A >> 2);
+
+ C += (D << 5 | (D >> 27)) + H(E, A, B) + _hashValue[idx++] + Y2;
+ E = E << 30 | (E >> 2);
+
+ B += (C << 5 | (C >> 27)) + H(D, E, A) + _hashValue[idx++] + Y2;
+ D = D << 30 | (D >> 2);
+
+ A += (B << 5 | (B >> 27)) + H(C, D, E) + _hashValue[idx++] + Y2;
+ C = C << 30 | (C >> 2);
+
+ //
+ // round 3
+ // E = rotateLeft(A, 5) + G(B, C, D) + E + X[idx++] + Y3
+ // B = rotateLeft(B, 30)
+ E += (A << 5 | (A >> 27)) + G(B, C, D) + _hashValue[idx++] + Y3;
+ B = B << 30 | (B >> 2);
+
+ D += (E << 5 | (E >> 27)) + G(A, B, C) + _hashValue[idx++] + Y3;
+ A = A << 30 | (A >> 2);
+
+ C += (D << 5 | (D >> 27)) + G(E, A, B) + _hashValue[idx++] + Y3;
+ E = E << 30 | (E >> 2);
+
+ B += (C << 5 | (C >> 27)) + G(D, E, A) + _hashValue[idx++] + Y3;
+ D = D << 30 | (D >> 2);
+
+ A += (B << 5 | (B >> 27)) + G(C, D, E) + _hashValue[idx++] + Y3;
+ C = C << 30 | (C >> 2);
+ // E = rotateLeft(A, 5) + G(B, C, D) + E + X[idx++] + Y3
+ // B = rotateLeft(B, 30)
+ E += (A << 5 | (A >> 27)) + G(B, C, D) + _hashValue[idx++] + Y3;
+ B = B << 30 | (B >> 2);
+
+ D += (E << 5 | (E >> 27)) + G(A, B, C) + _hashValue[idx++] + Y3;
+ A = A << 30 | (A >> 2);
+
+ C += (D << 5 | (D >> 27)) + G(E, A, B) + _hashValue[idx++] + Y3;
+ E = E << 30 | (E >> 2);
+
+ B += (C << 5 | (C >> 27)) + G(D, E, A) + _hashValue[idx++] + Y3;
+ D = D << 30 | (D >> 2);
+
+ A += (B << 5 | (B >> 27)) + G(C, D, E) + _hashValue[idx++] + Y3;
+ C = C << 30 | (C >> 2);
+ // E = rotateLeft(A, 5) + G(B, C, D) + E + X[idx++] + Y3
+ // B = rotateLeft(B, 30)
+ E += (A << 5 | (A >> 27)) + G(B, C, D) + _hashValue[idx++] + Y3;
+ B = B << 30 | (B >> 2);
+
+ D += (E << 5 | (E >> 27)) + G(A, B, C) + _hashValue[idx++] + Y3;
+ A = A << 30 | (A >> 2);
+
+ C += (D << 5 | (D >> 27)) + G(E, A, B) + _hashValue[idx++] + Y3;
+ E = E << 30 | (E >> 2);
+
+ B += (C << 5 | (C >> 27)) + G(D, E, A) + _hashValue[idx++] + Y3;
+ D = D << 30 | (D >> 2);
+
+ A += (B << 5 | (B >> 27)) + G(C, D, E) + _hashValue[idx++] + Y3;
+ C = C << 30 | (C >> 2);
+ // E = rotateLeft(A, 5) + G(B, C, D) + E + X[idx++] + Y3
+ // B = rotateLeft(B, 30)
+ E += (A << 5 | (A >> 27)) + G(B, C, D) + _hashValue[idx++] + Y3;
+ B = B << 30 | (B >> 2);
+
+ D += (E << 5 | (E >> 27)) + G(A, B, C) + _hashValue[idx++] + Y3;
+ A = A << 30 | (A >> 2);
+
+ C += (D << 5 | (D >> 27)) + G(E, A, B) + _hashValue[idx++] + Y3;
+ E = E << 30 | (E >> 2);
+
+ B += (C << 5 | (C >> 27)) + G(D, E, A) + _hashValue[idx++] + Y3;
+ D = D << 30 | (D >> 2);
+
+ A += (B << 5 | (B >> 27)) + G(C, D, E) + _hashValue[idx++] + Y3;
+ C = C << 30 | (C >> 2);
+
+ //
+ // round 4
+ //
+ // E = rotateLeft(A, 5) + H(B, C, D) + E + X[idx++] + Y4
+ // B = rotateLeft(B, 30)
+ E += (A << 5 | (A >> 27)) + H(B, C, D) + _hashValue[idx++] + Y4;
+ B = B << 30 | (B >> 2);
+
+ D += (E << 5 | (E >> 27)) + H(A, B, C) + _hashValue[idx++] + Y4;
+ A = A << 30 | (A >> 2);
+
+ C += (D << 5 | (D >> 27)) + H(E, A, B) + _hashValue[idx++] + Y4;
+ E = E << 30 | (E >> 2);
+
+ B += (C << 5 | (C >> 27)) + H(D, E, A) + _hashValue[idx++] + Y4;
+ D = D << 30 | (D >> 2);
+
+ A += (B << 5 | (B >> 27)) + H(C, D, E) + _hashValue[idx++] + Y4;
+ C = C << 30 | (C >> 2);
+ // E = rotateLeft(A, 5) + H(B, C, D) + E + X[idx++] + Y4
+ // B = rotateLeft(B, 30)
+ E += (A << 5 | (A >> 27)) + H(B, C, D) + _hashValue[idx++] + Y4;
+ B = B << 30 | (B >> 2);
+
+ D += (E << 5 | (E >> 27)) + H(A, B, C) + _hashValue[idx++] + Y4;
+ A = A << 30 | (A >> 2);
+
+ C += (D << 5 | (D >> 27)) + H(E, A, B) + _hashValue[idx++] + Y4;
+ E = E << 30 | (E >> 2);
+
+ B += (C << 5 | (C >> 27)) + H(D, E, A) + _hashValue[idx++] + Y4;
+ D = D << 30 | (D >> 2);
+
+ A += (B << 5 | (B >> 27)) + H(C, D, E) + _hashValue[idx++] + Y4;
+ C = C << 30 | (C >> 2);
+ // E = rotateLeft(A, 5) + H(B, C, D) + E + X[idx++] + Y4
+ // B = rotateLeft(B, 30)
+ E += (A << 5 | (A >> 27)) + H(B, C, D) + _hashValue[idx++] + Y4;
+ B = B << 30 | (B >> 2);
+
+ D += (E << 5 | (E >> 27)) + H(A, B, C) + _hashValue[idx++] + Y4;
+ A = A << 30 | (A >> 2);
+
+ C += (D << 5 | (D >> 27)) + H(E, A, B) + _hashValue[idx++] + Y4;
+ E = E << 30 | (E >> 2);
+
+ B += (C << 5 | (C >> 27)) + H(D, E, A) + _hashValue[idx++] + Y4;
+ D = D << 30 | (D >> 2);
+
+ A += (B << 5 | (B >> 27)) + H(C, D, E) + _hashValue[idx++] + Y4;
+ C = C << 30 | (C >> 2);
+ // E = rotateLeft(A, 5) + H(B, C, D) + E + X[idx++] + Y4
+ // B = rotateLeft(B, 30)
+ E += (A << 5 | (A >> 27)) + H(B, C, D) + _hashValue[idx++] + Y4;
+ B = B << 30 | (B >> 2);
+
+ D += (E << 5 | (E >> 27)) + H(A, B, C) + _hashValue[idx++] + Y4;
+ A = A << 30 | (A >> 2);
+
+ C += (D << 5 | (D >> 27)) + H(E, A, B) + _hashValue[idx++] + Y4;
+ E = E << 30 | (E >> 2);
+
+ B += (C << 5 | (C >> 27)) + H(D, E, A) + _hashValue[idx++] + Y4;
+ D = D << 30 | (D >> 2);
+
+ A += (B << 5 | (B >> 27)) + H(C, D, E) + _hashValue[idx++] + Y4;
+ C = C << 30 | (C >> 2);
+
+ H1 += A;
+ H2 += B;
+ H3 += C;
+ H4 += D;
+ H5 += E;
+
+ //
+ // reset start of the buffer.
+ //
+ this._offset = 0;
+ for (int i = 0; i < this._hashValue.Length; i++)
+ {
+ this._hashValue[i] = 0;
+ }
+ }
+
+ private static uint BigEndianToUInt32(byte[] bs, int off)
+ {
+ uint n = (uint)bs[off] << 24;
+ n |= (uint)bs[++off] << 16;
+ n |= (uint)bs[++off] << 8;
+ n |= (uint)bs[++off];
+ return n;
+ }
+
+ private static void UInt32ToBigEndian(uint n, byte[] bs, int off)
+ {
+ bs[off] = (byte)(n >> 24);
+ bs[++off] = (byte)(n >> 16);
+ bs[++off] = (byte)(n >> 8);
+ bs[++off] = (byte)(n);
+ }
+ }
+}
diff --git a/Renci.SshNet/Security/Cryptography/Hashes/SHA256Hash.cs b/Renci.SshNet/Security/Cryptography/Hashes/SHA256Hash.cs
index d0fc15c..85cbdda 100644
--- a/Renci.SshNet/Security/Cryptography/Hashes/SHA256Hash.cs
+++ b/Renci.SshNet/Security/Cryptography/Hashes/SHA256Hash.cs
@@ -1,400 +1,396 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Security.Cryptography;
-
-namespace Renci.SshNet.Security.Cryptography
-{
- ///
- /// SHA256 algorithm implementation.
- ///
- public class SHA256Hash : HashAlgorithm
- {
- private const int DIGEST_SIZE = 32;
-
- private uint H1, H2, H3, H4, H5, H6, H7, H8;
-
- private uint[] X = new uint[64];
-
- private int _offset;
-
- private byte[] _buffer;
-
- private int _bufferOffset;
-
- private long _byteCount;
-
- ///
- /// Gets the size, in bits, of the computed hash code.
- ///
- /// The size, in bits, of the computed hash code.
- public override int HashSize
- {
- get
- {
- return DIGEST_SIZE * 8;
- }
- }
-
- ///
- /// Gets the input block size.
- ///
- /// The input block size.
- public override int InputBlockSize
- {
- get
- {
- return 64;
- }
- }
-
- ///
- /// Gets the output block size.
- ///
- /// The output block size.
- public override int OutputBlockSize
- {
- get
- {
- return 64;
- }
- }
-
- ///
- /// Gets a value indicating whether the current transform can be reused.
- ///
- /// Always true.
- public override bool CanReuseTransform
- {
- get
- {
- return true;
- }
- }
-
- ///
- /// Gets a value indicating whether multiple blocks can be transformed.
- ///
- /// true if multiple blocks can be transformed; otherwise, false.
- public override bool CanTransformMultipleBlocks
- {
- get
- {
- return true;
- }
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- public SHA256Hash()
- {
- this._buffer = new byte[4];
- this.InternalInitialize();
- }
-
- ///
- /// Routes data written to the object into the hash algorithm for computing the hash.
- ///
- /// The input to compute the hash code for.
- /// The offset into the byte array from which to begin using data.
- /// The number of bytes in the byte array to use as data.
- protected override void HashCore(byte[] array, int ibStart, int cbSize)
- {
- // Fill the current word
- while ((this._bufferOffset != 0) && (cbSize > 0))
- {
- this.Update(array[ibStart]);
- ibStart++;
- cbSize--;
- }
-
- // Process whole words.
- while (cbSize > this._buffer.Length)
- {
- this.ProcessWord(array, ibStart);
-
- ibStart += this._buffer.Length;
- cbSize -= this._buffer.Length;
- this._byteCount += this._buffer.Length;
- }
-
- // Load in the remainder.
- while (cbSize > 0)
- {
- this.Update(array[ibStart]);
-
- ibStart++;
- cbSize--;
- }
- }
-
- ///
- /// Finalizes the hash computation after the last data is processed by the cryptographic stream object.
- ///
- ///
- /// The computed hash code.
- ///
- protected override byte[] HashFinal()
- {
- var output = new byte[DIGEST_SIZE];
- long bitLength = (this._byteCount << 3);
-
- //
- // add the pad bytes.
- //
- this.Update((byte)128);
-
- while (this._bufferOffset != 0)
- this.Update((byte)0);
-
- if (this._offset > 14)
- {
- this.ProcessBlock();
- }
-
- X[14] = (uint)((ulong)bitLength >> 32);
- X[15] = (uint)((ulong)bitLength);
-
-
- this.ProcessBlock();
-
- UInt32_To_BE((uint)H1, output, 0);
- UInt32_To_BE((uint)H2, output, 0 + 4);
- UInt32_To_BE((uint)H3, output, 0 + 8);
- UInt32_To_BE((uint)H4, output, 0 + 12);
- UInt32_To_BE((uint)H5, output, 0 + 16);
- UInt32_To_BE((uint)H6, output, 0 + 20);
- UInt32_To_BE((uint)H7, output, 0 + 24);
- UInt32_To_BE((uint)H8, output, 0 + 28);
-
- this.Initialize();
-
- return output;
- }
-
- ///
- /// Initializes an implementation of the class.
- ///
- public override void Initialize()
- {
- this.InternalInitialize();
- }
-
- private void InternalInitialize()
- {
- this._byteCount = 0;
- this._bufferOffset = 0;
- for (int i = 0; i < this._buffer.Length; i++)
- {
- this._buffer[i] = 0;
- }
-
- H1 = 0x6a09e667;
- H2 = 0xbb67ae85;
- H3 = 0x3c6ef372;
- H4 = 0xa54ff53a;
- H5 = 0x510e527f;
- H6 = 0x9b05688c;
- H7 = 0x1f83d9ab;
- H8 = 0x5be0cd19;
-
- this._offset = 0;
- for (int i = 0; i < this.X.Length; i++)
- {
- this.X[i] = 0;
- }
- }
-
- private void Update(byte input)
- {
- this._buffer[this._bufferOffset++] = input;
-
- if (this._bufferOffset == this._buffer.Length)
- {
- this.ProcessWord(this._buffer, 0);
- this._bufferOffset = 0;
- }
-
- this._byteCount++;
- }
-
- private static uint BE_To_UInt32(byte[] bs, int off)
- {
- uint n = (uint)bs[off] << 24;
- n |= (uint)bs[++off] << 16;
- n |= (uint)bs[++off] << 8;
- n |= (uint)bs[++off];
- return n;
- }
-
- private static void UInt32_To_BE(uint n, byte[] bs, int off)
- {
- bs[off] = (byte)(n >> 24);
- bs[++off] = (byte)(n >> 16);
- bs[++off] = (byte)(n >> 8);
- bs[++off] = (byte)(n);
- }
-
- private void ProcessWord(byte[] input, int inOff)
- {
- X[this._offset] = BE_To_UInt32(input, inOff);
-
- if (++this._offset == 16)
- {
- ProcessBlock();
- }
- }
-
- private void ProcessLength(long bitLength)
- {
- if (this._offset > 14)
- {
- ProcessBlock();
- }
-
- X[14] = (uint)((ulong)bitLength >> 32);
- X[15] = (uint)((ulong)bitLength);
- }
-
- private void ProcessBlock()
- {
- //
- // expand 16 word block into 64 word blocks.
- //
- for (int ti = 16; ti <= 63; ti++)
- {
- X[ti] = Theta1(X[ti - 2]) + X[ti - 7] + Theta0(X[ti - 15]) + X[ti - 16];
- }
-
- //
- // set up working variables.
- //
- uint a = H1;
- uint b = H2;
- uint c = H3;
- uint d = H4;
- uint e = H5;
- uint f = H6;
- uint g = H7;
- uint h = H8;
-
- int t = 0;
- for (int i = 0; i < 8; ++i)
- {
- // t = 8 * i
- h += Sum1Ch(e, f, g) + K[t] + X[t];
- d += h;
- h += Sum0Maj(a, b, c);
- ++t;
-
- // t = 8 * i + 1
- g += Sum1Ch(d, e, f) + K[t] + X[t];
- c += g;
- g += Sum0Maj(h, a, b);
- ++t;
-
- // t = 8 * i + 2
- f += Sum1Ch(c, d, e) + K[t] + X[t];
- b += f;
- f += Sum0Maj(g, h, a);
- ++t;
-
- // t = 8 * i + 3
- e += Sum1Ch(b, c, d) + K[t] + X[t];
- a += e;
- e += Sum0Maj(f, g, h);
- ++t;
-
- // t = 8 * i + 4
- d += Sum1Ch(a, b, c) + K[t] + X[t];
- h += d;
- d += Sum0Maj(e, f, g);
- ++t;
-
- // t = 8 * i + 5
- c += Sum1Ch(h, a, b) + K[t] + X[t];
- g += c;
- c += Sum0Maj(d, e, f);
- ++t;
-
- // t = 8 * i + 6
- b += Sum1Ch(g, h, a) + K[t] + X[t];
- f += b;
- b += Sum0Maj(c, d, e);
- ++t;
-
- // t = 8 * i + 7
- a += Sum1Ch(f, g, h) + K[t] + X[t];
- e += a;
- a += Sum0Maj(b, c, d);
- ++t;
- }
-
- H1 += a;
- H2 += b;
- H3 += c;
- H4 += d;
- H5 += e;
- H6 += f;
- H7 += g;
- H8 += h;
-
- //
- // reset the offset and clean out the word buffer.
- //
- this._offset = 0;
- for (int i = 0; i < this.X.Length; i++)
- {
- this.X[i] = 0;
- }
- }
-
- private static uint Sum1Ch(uint x, uint y, uint z)
- {
- // return Sum1(x) + Ch(x, y, z);
- return (((x >> 6) | (x << 26)) ^ ((x >> 11) | (x << 21)) ^ ((x >> 25) | (x << 7)))
- + ((x & y) ^ ((~x) & z));
- }
-
- private static uint Sum0Maj(uint x, uint y, uint z)
- {
- // return Sum0(x) + Maj(x, y, z);
- return (((x >> 2) | (x << 30)) ^ ((x >> 13) | (x << 19)) ^ ((x >> 22) | (x << 10)))
- + ((x & y) ^ (x & z) ^ (y & z));
- }
-
- private static uint Theta0(uint x)
- {
- return ((x >> 7) | (x << 25)) ^ ((x >> 18) | (x << 14)) ^ (x >> 3);
- }
-
- private static uint Theta1(uint x)
- {
- return ((x >> 17) | (x << 15)) ^ ((x >> 19) | (x << 13)) ^ (x >> 10);
- }
-
- ///
- /// The SHA-256 Constants (represent the first 32 bits of the fractional parts of the cube roots of the first sixty-four prime numbers)
- ///
- private static readonly uint[] K = {
- 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
- 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
- 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
- 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
- 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
- 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
- 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
- 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
- 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
- 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
- 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
- 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
- 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
- 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
- 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
- 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
- };
- }
-}
+using System.Security.Cryptography;
+
+namespace Renci.SshNet.Security.Cryptography
+{
+ ///
+ /// SHA256 algorithm implementation.
+ ///
+ public class SHA256Hash : HashAlgorithm
+ {
+ private const int DIGEST_SIZE = 32;
+
+ private uint H1, H2, H3, H4, H5, H6, H7, H8;
+
+ private readonly uint[] X = new uint[64];
+
+ private int _offset;
+
+ private readonly byte[] _buffer;
+
+ private int _bufferOffset;
+
+ private long _byteCount;
+
+ ///
+ /// Gets the size, in bits, of the computed hash code.
+ ///
+ /// The size, in bits, of the computed hash code.
+ public override int HashSize
+ {
+ get
+ {
+ return DIGEST_SIZE * 8;
+ }
+ }
+
+ ///
+ /// Gets the input block size.
+ ///
+ /// The input block size.
+ public override int InputBlockSize
+ {
+ get
+ {
+ return 64;
+ }
+ }
+
+ ///
+ /// Gets the output block size.
+ ///
+ /// The output block size.
+ public override int OutputBlockSize
+ {
+ get
+ {
+ return 64;
+ }
+ }
+
+ ///
+ /// Gets a value indicating whether the current transform can be reused.
+ ///
+ /// Always true.
+ public override bool CanReuseTransform
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ ///
+ /// Gets a value indicating whether multiple blocks can be transformed.
+ ///
+ /// true if multiple blocks can be transformed; otherwise, false.
+ public override bool CanTransformMultipleBlocks
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public SHA256Hash()
+ {
+ this._buffer = new byte[4];
+ this.InternalInitialize();
+ }
+
+ ///
+ /// Routes data written to the object into the hash algorithm for computing the hash.
+ ///
+ /// The input to compute the hash code for.
+ /// The offset into the byte array from which to begin using data.
+ /// The number of bytes in the byte array to use as data.
+ protected override void HashCore(byte[] array, int ibStart, int cbSize)
+ {
+ // Fill the current word
+ while ((this._bufferOffset != 0) && (cbSize > 0))
+ {
+ this.Update(array[ibStart]);
+ ibStart++;
+ cbSize--;
+ }
+
+ // Process whole words.
+ while (cbSize > this._buffer.Length)
+ {
+ this.ProcessWord(array, ibStart);
+
+ ibStart += this._buffer.Length;
+ cbSize -= this._buffer.Length;
+ this._byteCount += this._buffer.Length;
+ }
+
+ // Load in the remainder.
+ while (cbSize > 0)
+ {
+ this.Update(array[ibStart]);
+
+ ibStart++;
+ cbSize--;
+ }
+ }
+
+ ///
+ /// Finalizes the hash computation after the last data is processed by the cryptographic stream object.
+ ///
+ ///
+ /// The computed hash code.
+ ///
+ protected override byte[] HashFinal()
+ {
+ var output = new byte[DIGEST_SIZE];
+ long bitLength = (this._byteCount << 3);
+
+ //
+ // add the pad bytes.
+ //
+ this.Update((byte)128);
+
+ while (this._bufferOffset != 0)
+ this.Update((byte)0);
+
+ if (this._offset > 14)
+ {
+ this.ProcessBlock();
+ }
+
+ X[14] = (uint)((ulong)bitLength >> 32);
+ X[15] = (uint)((ulong)bitLength);
+
+
+ this.ProcessBlock();
+
+ UInt32_To_BE((uint)H1, output, 0);
+ UInt32_To_BE((uint)H2, output, 0 + 4);
+ UInt32_To_BE((uint)H3, output, 0 + 8);
+ UInt32_To_BE((uint)H4, output, 0 + 12);
+ UInt32_To_BE((uint)H5, output, 0 + 16);
+ UInt32_To_BE((uint)H6, output, 0 + 20);
+ UInt32_To_BE((uint)H7, output, 0 + 24);
+ UInt32_To_BE((uint)H8, output, 0 + 28);
+
+ this.Initialize();
+
+ return output;
+ }
+
+ ///
+ /// Initializes an implementation of the class.
+ ///
+ public override void Initialize()
+ {
+ this.InternalInitialize();
+ }
+
+ private void InternalInitialize()
+ {
+ this._byteCount = 0;
+ this._bufferOffset = 0;
+ for (int i = 0; i < this._buffer.Length; i++)
+ {
+ this._buffer[i] = 0;
+ }
+
+ H1 = 0x6a09e667;
+ H2 = 0xbb67ae85;
+ H3 = 0x3c6ef372;
+ H4 = 0xa54ff53a;
+ H5 = 0x510e527f;
+ H6 = 0x9b05688c;
+ H7 = 0x1f83d9ab;
+ H8 = 0x5be0cd19;
+
+ this._offset = 0;
+ for (int i = 0; i < this.X.Length; i++)
+ {
+ this.X[i] = 0;
+ }
+ }
+
+ private void Update(byte input)
+ {
+ this._buffer[this._bufferOffset++] = input;
+
+ if (this._bufferOffset == this._buffer.Length)
+ {
+ this.ProcessWord(this._buffer, 0);
+ this._bufferOffset = 0;
+ }
+
+ this._byteCount++;
+ }
+
+ private static uint BE_To_UInt32(byte[] bs, int off)
+ {
+ uint n = (uint)bs[off] << 24;
+ n |= (uint)bs[++off] << 16;
+ n |= (uint)bs[++off] << 8;
+ n |= (uint)bs[++off];
+ return n;
+ }
+
+ private static void UInt32_To_BE(uint n, byte[] bs, int off)
+ {
+ bs[off] = (byte)(n >> 24);
+ bs[++off] = (byte)(n >> 16);
+ bs[++off] = (byte)(n >> 8);
+ bs[++off] = (byte)(n);
+ }
+
+ private void ProcessWord(byte[] input, int inOff)
+ {
+ X[this._offset] = BE_To_UInt32(input, inOff);
+
+ if (++this._offset == 16)
+ {
+ ProcessBlock();
+ }
+ }
+
+ private void ProcessLength(long bitLength)
+ {
+ if (this._offset > 14)
+ {
+ ProcessBlock();
+ }
+
+ X[14] = (uint)((ulong)bitLength >> 32);
+ X[15] = (uint)((ulong)bitLength);
+ }
+
+ private void ProcessBlock()
+ {
+ //
+ // expand 16 word block into 64 word blocks.
+ //
+ for (int ti = 16; ti <= 63; ti++)
+ {
+ X[ti] = Theta1(X[ti - 2]) + X[ti - 7] + Theta0(X[ti - 15]) + X[ti - 16];
+ }
+
+ //
+ // set up working variables.
+ //
+ uint a = H1;
+ uint b = H2;
+ uint c = H3;
+ uint d = H4;
+ uint e = H5;
+ uint f = H6;
+ uint g = H7;
+ uint h = H8;
+
+ int t = 0;
+ for (int i = 0; i < 8; ++i)
+ {
+ // t = 8 * i
+ h += Sum1Ch(e, f, g) + K[t] + X[t];
+ d += h;
+ h += Sum0Maj(a, b, c);
+ ++t;
+
+ // t = 8 * i + 1
+ g += Sum1Ch(d, e, f) + K[t] + X[t];
+ c += g;
+ g += Sum0Maj(h, a, b);
+ ++t;
+
+ // t = 8 * i + 2
+ f += Sum1Ch(c, d, e) + K[t] + X[t];
+ b += f;
+ f += Sum0Maj(g, h, a);
+ ++t;
+
+ // t = 8 * i + 3
+ e += Sum1Ch(b, c, d) + K[t] + X[t];
+ a += e;
+ e += Sum0Maj(f, g, h);
+ ++t;
+
+ // t = 8 * i + 4
+ d += Sum1Ch(a, b, c) + K[t] + X[t];
+ h += d;
+ d += Sum0Maj(e, f, g);
+ ++t;
+
+ // t = 8 * i + 5
+ c += Sum1Ch(h, a, b) + K[t] + X[t];
+ g += c;
+ c += Sum0Maj(d, e, f);
+ ++t;
+
+ // t = 8 * i + 6
+ b += Sum1Ch(g, h, a) + K[t] + X[t];
+ f += b;
+ b += Sum0Maj(c, d, e);
+ ++t;
+
+ // t = 8 * i + 7
+ a += Sum1Ch(f, g, h) + K[t] + X[t];
+ e += a;
+ a += Sum0Maj(b, c, d);
+ ++t;
+ }
+
+ H1 += a;
+ H2 += b;
+ H3 += c;
+ H4 += d;
+ H5 += e;
+ H6 += f;
+ H7 += g;
+ H8 += h;
+
+ //
+ // reset the offset and clean out the word buffer.
+ //
+ this._offset = 0;
+ for (int i = 0; i < this.X.Length; i++)
+ {
+ this.X[i] = 0;
+ }
+ }
+
+ private static uint Sum1Ch(uint x, uint y, uint z)
+ {
+ // return Sum1(x) + Ch(x, y, z);
+ return (((x >> 6) | (x << 26)) ^ ((x >> 11) | (x << 21)) ^ ((x >> 25) | (x << 7)))
+ + ((x & y) ^ ((~x) & z));
+ }
+
+ private static uint Sum0Maj(uint x, uint y, uint z)
+ {
+ // return Sum0(x) + Maj(x, y, z);
+ return (((x >> 2) | (x << 30)) ^ ((x >> 13) | (x << 19)) ^ ((x >> 22) | (x << 10)))
+ + ((x & y) ^ (x & z) ^ (y & z));
+ }
+
+ private static uint Theta0(uint x)
+ {
+ return ((x >> 7) | (x << 25)) ^ ((x >> 18) | (x << 14)) ^ (x >> 3);
+ }
+
+ private static uint Theta1(uint x)
+ {
+ return ((x >> 17) | (x << 15)) ^ ((x >> 19) | (x << 13)) ^ (x >> 10);
+ }
+
+ ///
+ /// The SHA-256 Constants (represent the first 32 bits of the fractional parts of the cube roots of the first sixty-four prime numbers)
+ ///
+ private static readonly uint[] K = {
+ 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
+ 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
+ 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
+ 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+ 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
+ 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
+ 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+ };
+ }
+}
diff --git a/Renci.SshNet/Security/Cryptography/Hashes/SHA2HashBase.cs b/Renci.SshNet/Security/Cryptography/Hashes/SHA2HashBase.cs
index 74293de..e45115a 100644
--- a/Renci.SshNet/Security/Cryptography/Hashes/SHA2HashBase.cs
+++ b/Renci.SshNet/Security/Cryptography/Hashes/SHA2HashBase.cs
@@ -1,366 +1,362 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Security.Cryptography;
-using System.Text;
-
-namespace Renci.SshNet.Security.Cryptography
-{
- ///
- /// SHA256 algorithm implementation.
- ///
- public abstract class SHA2HashBase : HashAlgorithm
- {
- protected ulong H1, H2, H3, H4, H5, H6, H7, H8;
-
- private ulong[] X = new ulong[80];
-
- private int _offset;
-
- private byte[] _buffer;
-
- private int _bufferOffset;
-
- private long _byteCount1;
-
- private long _byteCount2;
-
- ///
- /// Gets a value indicating whether the current transform can be reused.
- ///
- /// Always true.
- public override bool CanReuseTransform
- {
- get
- {
- return true;
- }
- }
-
- ///
- /// Gets a value indicating whether multiple blocks can be transformed.
- ///
- /// true if multiple blocks can be transformed; otherwise, false.
- public override bool CanTransformMultipleBlocks
- {
- get
- {
- return true;
- }
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- public SHA2HashBase()
- {
- this._buffer = new byte[8];
-
- this.Initialize();
- }
-
- protected override void HashCore(byte[] array, int ibStart, int cbSize)
- {
- // Fill the current word
- while ((this._bufferOffset != 0) && (cbSize > 0))
- {
- this.Update(array[ibStart]);
-
- ibStart++;
- cbSize--;
- }
-
- // Process whole words.
- while (cbSize > this._buffer.Length)
- {
- ProcessWord(array, ibStart);
-
- ibStart += this._buffer.Length;
- cbSize -= this._buffer.Length;
- this._byteCount1 += this._buffer.Length;
- }
-
- // Load in the remainder.
- while (cbSize > 0)
- {
- this.Update(array[ibStart]);
-
- ibStart++;
- cbSize--;
- }
- }
-
- public override void Initialize()
- {
- this._byteCount1 = 0;
- this._byteCount2 = 0;
-
- this._bufferOffset = 0;
- for (int i = 0; i < this._buffer.Length; i++)
- {
- this._buffer[i] = 0;
- }
-
- this._offset = 0;
- for (int i = 0; i < this.X.Length; i++)
- {
- this.X[i] = 0;
- }
- }
-
- protected void Finish()
- {
- this.AdjustByteCounts();
-
- long lowBitLength = this._byteCount1 << 3;
- long hiBitLength = this._byteCount2;
-
- //
- // add the pad bytes.
- //
- this.Update((byte)128);
-
- while (this._bufferOffset != 0)
- {
- this.Update((byte)0);
- }
-
- this.ProcessLength(lowBitLength, hiBitLength);
-
- this.ProcessBlock();
- }
-
- private void Update(byte input)
- {
- this._buffer[_bufferOffset++] = input;
-
- if (this._bufferOffset == this._buffer.Length)
- {
- this.ProcessWord(this._buffer, 0);
- this._bufferOffset = 0;
- }
-
- this._byteCount1++;
- }
-
- private void ProcessWord(byte[] input, int inOff)
- {
- this.X[_offset] = SHA512Hash.BE_To_UInt64(input, inOff);
-
- if (++_offset == 16)
- {
- ProcessBlock();
- }
- }
-
- internal void ProcessLength(long lowW, long hiW)
- {
- if (_offset > 14)
- {
- this.ProcessBlock();
- }
-
- this.X[14] = (ulong)hiW;
- this.X[15] = (ulong)lowW;
- }
-
- private void ProcessBlock()
- {
- this.AdjustByteCounts();
-
- //
- // expand 16 word block into 80 word blocks.
- //
- for (int ti = 16; ti <= 79; ++ti)
- {
- X[ti] = Sigma1(X[ti - 2]) + X[ti - 7] + Sigma0(X[ti - 15]) + X[ti - 16];
- }
-
- //
- // set up working variables.
- //
- ulong a = H1;
- ulong b = H2;
- ulong c = H3;
- ulong d = H4;
- ulong e = H5;
- ulong f = H6;
- ulong g = H7;
- ulong h = H8;
-
- int t = 0;
- for (int i = 0; i < 10; i++)
- {
- // t = 8 * i
- h += Sum1(e) + Ch(e, f, g) + K[t] + X[t++];
- d += h;
- h += Sum0(a) + Maj(a, b, c);
-
- // t = 8 * i + 1
- g += Sum1(d) + Ch(d, e, f) + K[t] + X[t++];
- c += g;
- g += Sum0(h) + Maj(h, a, b);
-
- // t = 8 * i + 2
- f += Sum1(c) + Ch(c, d, e) + K[t] + X[t++];
- b += f;
- f += Sum0(g) + Maj(g, h, a);
-
- // t = 8 * i + 3
- e += Sum1(b) + Ch(b, c, d) + K[t] + X[t++];
- a += e;
- e += Sum0(f) + Maj(f, g, h);
-
- // t = 8 * i + 4
- d += Sum1(a) + Ch(a, b, c) + K[t] + X[t++];
- h += d;
- d += Sum0(e) + Maj(e, f, g);
-
- // t = 8 * i + 5
- c += Sum1(h) + Ch(h, a, b) + K[t] + X[t++];
- g += c;
- c += Sum0(d) + Maj(d, e, f);
-
- // t = 8 * i + 6
- b += Sum1(g) + Ch(g, h, a) + K[t] + X[t++];
- f += b;
- b += Sum0(c) + Maj(c, d, e);
-
- // t = 8 * i + 7
- a += Sum1(f) + Ch(f, g, h) + K[t] + X[t++];
- e += a;
- a += Sum0(b) + Maj(b, c, d);
- }
-
- H1 += a;
- H2 += b;
- H3 += c;
- H4 += d;
- H5 += e;
- H6 += f;
- H7 += g;
- H8 += h;
-
- //
- // reset the offset and clean out the word buffer.
- //
- this._offset = 0;
- for (int i = 0; i < this.X.Length; i++)
- {
- this.X[i] = 0;
- }
- }
-
- ///
- /// Adjust the byte counts so that byteCount2 represents the upper long (less 3 bits) word of the byte count.
- ///
- private void AdjustByteCounts()
- {
- if (this._byteCount1 > 0x1fffffffffffffffL)
- {
- this._byteCount2 += (long)((ulong)this._byteCount1 >> 61);
- this._byteCount1 &= 0x1fffffffffffffffL;
- }
- }
-
- /* SHA-384 and SHA-512 functions (as for SHA-256 but for longs) */
- private static ulong Ch(ulong x, ulong y, ulong z)
- {
- return (x & y) ^ (~x & z);
- }
-
- private static ulong Maj(ulong x, ulong y, ulong z)
- {
- return (x & y) ^ (x & z) ^ (y & z);
- }
-
- private static ulong Sum0(ulong x)
- {
- return ((x << 36) | (x >> 28)) ^ ((x << 30) | (x >> 34)) ^ ((x << 25) | (x >> 39));
- }
-
- private static ulong Sum1(ulong x)
- {
- return ((x << 50) | (x >> 14)) ^ ((x << 46) | (x >> 18)) ^ ((x << 23) | (x >> 41));
- }
-
- private static ulong Sigma0(ulong x)
- {
- return ((x << 63) | (x >> 1)) ^ ((x << 56) | (x >> 8)) ^ (x >> 7);
- }
-
- private static ulong Sigma1(ulong x)
- {
- return ((x << 45) | (x >> 19)) ^ ((x << 3) | (x >> 61)) ^ (x >> 6);
- }
-
- /* SHA-384 and SHA-512 Constants
- * (represent the first 64 bits of the fractional parts of the
- * cube roots of the first sixty-four prime numbers)
- */
- private static readonly ulong[] K =
- {
- 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc,
- 0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118,
- 0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
- 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694,
- 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65,
- 0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
- 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4,
- 0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70,
- 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
- 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b,
- 0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30,
- 0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8,
- 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8,
- 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3,
- 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
- 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b,
- 0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178,
- 0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b,
- 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c,
- 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817
- };
-
- protected static void UInt32_To_BE(uint n, byte[] bs, int off)
- {
- bs[off] = (byte)(n >> 24);
- bs[++off] = (byte)(n >> 16);
- bs[++off] = (byte)(n >> 8);
- bs[++off] = (byte)(n);
- }
- protected static void UInt64_To_BE(ulong n, byte[] bs, int off)
- {
- UInt32_To_BE((uint)(n >> 32), bs, off);
- UInt32_To_BE((uint)(n), bs, off + 4);
- }
- protected static ulong BE_To_UInt64(byte[] bs)
- {
- uint hi = BE_To_UInt32(bs);
- uint lo = BE_To_UInt32(bs, 4);
- return ((ulong)hi << 32) | (ulong)lo;
- }
- protected static ulong BE_To_UInt64(byte[] bs, int off)
- {
- uint hi = BE_To_UInt32(bs, off);
- uint lo = BE_To_UInt32(bs, off + 4);
- return ((ulong)hi << 32) | (ulong)lo;
- }
- protected static uint BE_To_UInt32(byte[] bs, int off)
- {
- uint n = (uint)bs[off] << 24;
- n |= (uint)bs[++off] << 16;
- n |= (uint)bs[++off] << 8;
- n |= (uint)bs[++off];
- return n;
- }
- protected static uint BE_To_UInt32(byte[] bs)
- {
- uint n = (uint)bs[0] << 24;
- n |= (uint)bs[1] << 16;
- n |= (uint)bs[2] << 8;
- n |= (uint)bs[3];
- return n;
- }
- }
-}
+using System.Security.Cryptography;
+
+namespace Renci.SshNet.Security.Cryptography
+{
+ ///
+ /// SHA256 algorithm implementation.
+ ///
+ public abstract class SHA2HashBase : HashAlgorithm
+ {
+ protected ulong H1, H2, H3, H4, H5, H6, H7, H8;
+
+ private readonly ulong[] X = new ulong[80];
+
+ private int _offset;
+
+ private readonly byte[] _buffer;
+
+ private int _bufferOffset;
+
+ private long _byteCount1;
+
+ private long _byteCount2;
+
+ ///
+ /// Gets a value indicating whether the current transform can be reused.
+ ///
+ /// Always true.
+ public override bool CanReuseTransform
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ ///
+ /// Gets a value indicating whether multiple blocks can be transformed.
+ ///
+ /// true if multiple blocks can be transformed; otherwise, false.
+ public override bool CanTransformMultipleBlocks
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public SHA2HashBase()
+ {
+ this._buffer = new byte[8];
+
+ this.Initialize();
+ }
+
+ protected override void HashCore(byte[] array, int ibStart, int cbSize)
+ {
+ // Fill the current word
+ while ((this._bufferOffset != 0) && (cbSize > 0))
+ {
+ this.Update(array[ibStart]);
+
+ ibStart++;
+ cbSize--;
+ }
+
+ // Process whole words.
+ while (cbSize > this._buffer.Length)
+ {
+ ProcessWord(array, ibStart);
+
+ ibStart += this._buffer.Length;
+ cbSize -= this._buffer.Length;
+ this._byteCount1 += this._buffer.Length;
+ }
+
+ // Load in the remainder.
+ while (cbSize > 0)
+ {
+ this.Update(array[ibStart]);
+
+ ibStart++;
+ cbSize--;
+ }
+ }
+
+ public override void Initialize()
+ {
+ this._byteCount1 = 0;
+ this._byteCount2 = 0;
+
+ this._bufferOffset = 0;
+ for (int i = 0; i < this._buffer.Length; i++)
+ {
+ this._buffer[i] = 0;
+ }
+
+ this._offset = 0;
+ for (int i = 0; i < this.X.Length; i++)
+ {
+ this.X[i] = 0;
+ }
+ }
+
+ protected void Finish()
+ {
+ this.AdjustByteCounts();
+
+ long lowBitLength = this._byteCount1 << 3;
+ long hiBitLength = this._byteCount2;
+
+ //
+ // add the pad bytes.
+ //
+ this.Update((byte)128);
+
+ while (this._bufferOffset != 0)
+ {
+ this.Update((byte)0);
+ }
+
+ this.ProcessLength(lowBitLength, hiBitLength);
+
+ this.ProcessBlock();
+ }
+
+ private void Update(byte input)
+ {
+ this._buffer[_bufferOffset++] = input;
+
+ if (this._bufferOffset == this._buffer.Length)
+ {
+ this.ProcessWord(this._buffer, 0);
+ this._bufferOffset = 0;
+ }
+
+ this._byteCount1++;
+ }
+
+ private void ProcessWord(byte[] input, int inOff)
+ {
+ this.X[_offset] = SHA512Hash.BE_To_UInt64(input, inOff);
+
+ if (++_offset == 16)
+ {
+ ProcessBlock();
+ }
+ }
+
+ internal void ProcessLength(long lowW, long hiW)
+ {
+ if (_offset > 14)
+ {
+ this.ProcessBlock();
+ }
+
+ this.X[14] = (ulong)hiW;
+ this.X[15] = (ulong)lowW;
+ }
+
+ private void ProcessBlock()
+ {
+ this.AdjustByteCounts();
+
+ //
+ // expand 16 word block into 80 word blocks.
+ //
+ for (int ti = 16; ti <= 79; ++ti)
+ {
+ X[ti] = Sigma1(X[ti - 2]) + X[ti - 7] + Sigma0(X[ti - 15]) + X[ti - 16];
+ }
+
+ //
+ // set up working variables.
+ //
+ ulong a = H1;
+ ulong b = H2;
+ ulong c = H3;
+ ulong d = H4;
+ ulong e = H5;
+ ulong f = H6;
+ ulong g = H7;
+ ulong h = H8;
+
+ int t = 0;
+ for (int i = 0; i < 10; i++)
+ {
+ // t = 8 * i
+ h += Sum1(e) + Ch(e, f, g) + K[t] + X[t++];
+ d += h;
+ h += Sum0(a) + Maj(a, b, c);
+
+ // t = 8 * i + 1
+ g += Sum1(d) + Ch(d, e, f) + K[t] + X[t++];
+ c += g;
+ g += Sum0(h) + Maj(h, a, b);
+
+ // t = 8 * i + 2
+ f += Sum1(c) + Ch(c, d, e) + K[t] + X[t++];
+ b += f;
+ f += Sum0(g) + Maj(g, h, a);
+
+ // t = 8 * i + 3
+ e += Sum1(b) + Ch(b, c, d) + K[t] + X[t++];
+ a += e;
+ e += Sum0(f) + Maj(f, g, h);
+
+ // t = 8 * i + 4
+ d += Sum1(a) + Ch(a, b, c) + K[t] + X[t++];
+ h += d;
+ d += Sum0(e) + Maj(e, f, g);
+
+ // t = 8 * i + 5
+ c += Sum1(h) + Ch(h, a, b) + K[t] + X[t++];
+ g += c;
+ c += Sum0(d) + Maj(d, e, f);
+
+ // t = 8 * i + 6
+ b += Sum1(g) + Ch(g, h, a) + K[t] + X[t++];
+ f += b;
+ b += Sum0(c) + Maj(c, d, e);
+
+ // t = 8 * i + 7
+ a += Sum1(f) + Ch(f, g, h) + K[t] + X[t++];
+ e += a;
+ a += Sum0(b) + Maj(b, c, d);
+ }
+
+ H1 += a;
+ H2 += b;
+ H3 += c;
+ H4 += d;
+ H5 += e;
+ H6 += f;
+ H7 += g;
+ H8 += h;
+
+ //
+ // reset the offset and clean out the word buffer.
+ //
+ this._offset = 0;
+ for (int i = 0; i < this.X.Length; i++)
+ {
+ this.X[i] = 0;
+ }
+ }
+
+ ///
+ /// Adjust the byte counts so that byteCount2 represents the upper long (less 3 bits) word of the byte count.
+ ///
+ private void AdjustByteCounts()
+ {
+ if (this._byteCount1 > 0x1fffffffffffffffL)
+ {
+ this._byteCount2 += (long)((ulong)this._byteCount1 >> 61);
+ this._byteCount1 &= 0x1fffffffffffffffL;
+ }
+ }
+
+ /* SHA-384 and SHA-512 functions (as for SHA-256 but for longs) */
+ private static ulong Ch(ulong x, ulong y, ulong z)
+ {
+ return (x & y) ^ (~x & z);
+ }
+
+ private static ulong Maj(ulong x, ulong y, ulong z)
+ {
+ return (x & y) ^ (x & z) ^ (y & z);
+ }
+
+ private static ulong Sum0(ulong x)
+ {
+ return ((x << 36) | (x >> 28)) ^ ((x << 30) | (x >> 34)) ^ ((x << 25) | (x >> 39));
+ }
+
+ private static ulong Sum1(ulong x)
+ {
+ return ((x << 50) | (x >> 14)) ^ ((x << 46) | (x >> 18)) ^ ((x << 23) | (x >> 41));
+ }
+
+ private static ulong Sigma0(ulong x)
+ {
+ return ((x << 63) | (x >> 1)) ^ ((x << 56) | (x >> 8)) ^ (x >> 7);
+ }
+
+ private static ulong Sigma1(ulong x)
+ {
+ return ((x << 45) | (x >> 19)) ^ ((x << 3) | (x >> 61)) ^ (x >> 6);
+ }
+
+ /* SHA-384 and SHA-512 Constants
+ * (represent the first 64 bits of the fractional parts of the
+ * cube roots of the first sixty-four prime numbers)
+ */
+ private static readonly ulong[] K =
+ {
+ 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc,
+ 0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118,
+ 0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
+ 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694,
+ 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65,
+ 0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
+ 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4,
+ 0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70,
+ 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
+ 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b,
+ 0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30,
+ 0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8,
+ 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8,
+ 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3,
+ 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
+ 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b,
+ 0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178,
+ 0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b,
+ 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c,
+ 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817
+ };
+
+ protected static void UInt32_To_BE(uint n, byte[] bs, int off)
+ {
+ bs[off] = (byte)(n >> 24);
+ bs[++off] = (byte)(n >> 16);
+ bs[++off] = (byte)(n >> 8);
+ bs[++off] = (byte)(n);
+ }
+ protected static void UInt64_To_BE(ulong n, byte[] bs, int off)
+ {
+ UInt32_To_BE((uint)(n >> 32), bs, off);
+ UInt32_To_BE((uint)(n), bs, off + 4);
+ }
+ protected static ulong BE_To_UInt64(byte[] bs)
+ {
+ uint hi = BE_To_UInt32(bs);
+ uint lo = BE_To_UInt32(bs, 4);
+ return ((ulong)hi << 32) | (ulong)lo;
+ }
+ protected static ulong BE_To_UInt64(byte[] bs, int off)
+ {
+ uint hi = BE_To_UInt32(bs, off);
+ uint lo = BE_To_UInt32(bs, off + 4);
+ return ((ulong)hi << 32) | (ulong)lo;
+ }
+ protected static uint BE_To_UInt32(byte[] bs, int off)
+ {
+ uint n = (uint)bs[off] << 24;
+ n |= (uint)bs[++off] << 16;
+ n |= (uint)bs[++off] << 8;
+ n |= (uint)bs[++off];
+ return n;
+ }
+ protected static uint BE_To_UInt32(byte[] bs)
+ {
+ uint n = (uint)bs[0] << 24;
+ n |= (uint)bs[1] << 16;
+ n |= (uint)bs[2] << 8;
+ n |= (uint)bs[3];
+ return n;
+ }
+ }
+}
diff --git a/Renci.SshNet/Security/Cryptography/Hashes/SHA384Hash.cs b/Renci.SshNet/Security/Cryptography/Hashes/SHA384Hash.cs
index 116e300..1c5d2fe 100644
--- a/Renci.SshNet/Security/Cryptography/Hashes/SHA384Hash.cs
+++ b/Renci.SshNet/Security/Cryptography/Hashes/SHA384Hash.cs
@@ -1,85 +1,79 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Security.Cryptography;
-
-namespace Renci.SshNet.Security.Cryptography
-{
- public class SHA384Hash : SHA2HashBase
- {
- private const int DIGEST_SIZE = 48;
-
- ///
- /// Gets the size, in bits, of the computed hash code.
- ///
- /// The size, in bits, of the computed hash code.
- public override int HashSize
- {
- get
- {
- return DIGEST_SIZE * 8;
- }
- }
-
- ///
- /// When overridden in a derived class, gets the input block size.
- ///
- /// The input block size.
- public override int InputBlockSize
- {
- get
- {
- return DIGEST_SIZE * 2;
- }
- }
-
- ///
- /// When overridden in a derived class, gets the output block size.
- ///
- /// The output block size.
- public override int OutputBlockSize
- {
- get
- {
- return DIGEST_SIZE * 2;
- }
- }
-
- protected override byte[] HashFinal()
- {
- var output = new byte[DIGEST_SIZE];
-
- this.Finish();
-
- SHA2HashBase.UInt64_To_BE(H1, output, 0);
- SHA2HashBase.UInt64_To_BE(H2, output, 8);
- SHA2HashBase.UInt64_To_BE(H3, output, 16);
- SHA2HashBase.UInt64_To_BE(H4, output, 24);
- SHA2HashBase.UInt64_To_BE(H5, output, 32);
- SHA2HashBase.UInt64_To_BE(H6, output, 40);
-
- this.Initialize();
-
- return output;
- }
-
- public override void Initialize()
- {
- base.Initialize();
-
- /* SHA-384 initial hash value
- * The first 64 bits of the fractional parts of the square roots
- * of the 9th through 16th prime numbers
- */
- H1 = 0xcbbb9d5dc1059ed8;
- H2 = 0x629a292a367cd507;
- H3 = 0x9159015a3070dd17;
- H4 = 0x152fecd8f70e5939;
- H5 = 0x67332667ffc00b31;
- H6 = 0x8eb44a8768581511;
- H7 = 0xdb0c2e0d64f98fa7;
- H8 = 0x47b5481dbefa4fa4;
- }
- }
-}
+namespace Renci.SshNet.Security.Cryptography
+{
+ public class SHA384Hash : SHA2HashBase
+ {
+ private const int DIGEST_SIZE = 48;
+
+ ///
+ /// Gets the size, in bits, of the computed hash code.
+ ///
+ /// The size, in bits, of the computed hash code.
+ public override int HashSize
+ {
+ get
+ {
+ return DIGEST_SIZE * 8;
+ }
+ }
+
+ ///
+ /// When overridden in a derived class, gets the input block size.
+ ///
+ /// The input block size.
+ public override int InputBlockSize
+ {
+ get
+ {
+ return DIGEST_SIZE * 2;
+ }
+ }
+
+ ///
+ /// When overridden in a derived class, gets the output block size.
+ ///
+ /// The output block size.
+ public override int OutputBlockSize
+ {
+ get
+ {
+ return DIGEST_SIZE * 2;
+ }
+ }
+
+ protected override byte[] HashFinal()
+ {
+ var output = new byte[DIGEST_SIZE];
+
+ this.Finish();
+
+ SHA2HashBase.UInt64_To_BE(H1, output, 0);
+ SHA2HashBase.UInt64_To_BE(H2, output, 8);
+ SHA2HashBase.UInt64_To_BE(H3, output, 16);
+ SHA2HashBase.UInt64_To_BE(H4, output, 24);
+ SHA2HashBase.UInt64_To_BE(H5, output, 32);
+ SHA2HashBase.UInt64_To_BE(H6, output, 40);
+
+ this.Initialize();
+
+ return output;
+ }
+
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ /* SHA-384 initial hash value
+ * The first 64 bits of the fractional parts of the square roots
+ * of the 9th through 16th prime numbers
+ */
+ H1 = 0xcbbb9d5dc1059ed8;
+ H2 = 0x629a292a367cd507;
+ H3 = 0x9159015a3070dd17;
+ H4 = 0x152fecd8f70e5939;
+ H5 = 0x67332667ffc00b31;
+ H6 = 0x8eb44a8768581511;
+ H7 = 0xdb0c2e0d64f98fa7;
+ H8 = 0x47b5481dbefa4fa4;
+ }
+ }
+}
diff --git a/Renci.SshNet/Security/Cryptography/Hashes/SHA512Hash.cs b/Renci.SshNet/Security/Cryptography/Hashes/SHA512Hash.cs
index a21947b..cf5f7df 100644
--- a/Renci.SshNet/Security/Cryptography/Hashes/SHA512Hash.cs
+++ b/Renci.SshNet/Security/Cryptography/Hashes/SHA512Hash.cs
@@ -1,87 +1,81 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Security.Cryptography;
-
-namespace Renci.SshNet.Security.Cryptography
-{
- public class SHA512Hash : SHA2HashBase
- {
- private const int DIGEST_SIZE = 64;
-
- ///
- /// Gets the size, in bits, of the computed hash code.
- ///
- /// The size, in bits, of the computed hash code.
- public override int HashSize
- {
- get
- {
- return DIGEST_SIZE * 8;
- }
- }
-
- ///
- /// When overridden in a derived class, gets the input block size.
- ///
- /// The input block size.
- public override int InputBlockSize
- {
- get
- {
- return DIGEST_SIZE * 2;
- }
- }
-
- ///
- /// When overridden in a derived class, gets the output block size.
- ///
- /// The output block size.
- public override int OutputBlockSize
- {
- get
- {
- return DIGEST_SIZE * 2;
- }
- }
-
- protected override byte[] HashFinal()
- {
- var output = new byte[DIGEST_SIZE];
-
- this.Finish();
-
- SHA2HashBase.UInt64_To_BE(H1, output, 0);
- SHA2HashBase.UInt64_To_BE(H2, output, 8);
- SHA2HashBase.UInt64_To_BE(H3, output, 16);
- SHA2HashBase.UInt64_To_BE(H4, output, 24);
- SHA2HashBase.UInt64_To_BE(H5, output, 32);
- SHA2HashBase.UInt64_To_BE(H6, output, 40);
- SHA2HashBase.UInt64_To_BE(H7, output, 48);
- SHA2HashBase.UInt64_To_BE(H8, output, 56);
-
- this.Initialize();
-
- return output;
- }
-
- public override void Initialize()
- {
- base.Initialize();
-
- /* SHA-512 initial hash value
- * The first 64 bits of the fractional parts of the square roots
- * of the first eight prime numbers
- */
- H1 = 0x6a09e667f3bcc908;
- H2 = 0xbb67ae8584caa73b;
- H3 = 0x3c6ef372fe94f82b;
- H4 = 0xa54ff53a5f1d36f1;
- H5 = 0x510e527fade682d1;
- H6 = 0x9b05688c2b3e6c1f;
- H7 = 0x1f83d9abfb41bd6b;
- H8 = 0x5be0cd19137e2179;
- }
- }
-}
+namespace Renci.SshNet.Security.Cryptography
+{
+ public class SHA512Hash : SHA2HashBase
+ {
+ private const int DIGEST_SIZE = 64;
+
+ ///
+ /// Gets the size, in bits, of the computed hash code.
+ ///
+ /// The size, in bits, of the computed hash code.
+ public override int HashSize
+ {
+ get
+ {
+ return DIGEST_SIZE * 8;
+ }
+ }
+
+ ///
+ /// When overridden in a derived class, gets the input block size.
+ ///
+ /// The input block size.
+ public override int InputBlockSize
+ {
+ get
+ {
+ return DIGEST_SIZE * 2;
+ }
+ }
+
+ ///
+ /// When overridden in a derived class, gets the output block size.
+ ///
+ /// The output block size.
+ public override int OutputBlockSize
+ {
+ get
+ {
+ return DIGEST_SIZE * 2;
+ }
+ }
+
+ protected override byte[] HashFinal()
+ {
+ var output = new byte[DIGEST_SIZE];
+
+ this.Finish();
+
+ SHA2HashBase.UInt64_To_BE(H1, output, 0);
+ SHA2HashBase.UInt64_To_BE(H2, output, 8);
+ SHA2HashBase.UInt64_To_BE(H3, output, 16);
+ SHA2HashBase.UInt64_To_BE(H4, output, 24);
+ SHA2HashBase.UInt64_To_BE(H5, output, 32);
+ SHA2HashBase.UInt64_To_BE(H6, output, 40);
+ SHA2HashBase.UInt64_To_BE(H7, output, 48);
+ SHA2HashBase.UInt64_To_BE(H8, output, 56);
+
+ this.Initialize();
+
+ return output;
+ }
+
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ /* SHA-512 initial hash value
+ * The first 64 bits of the fractional parts of the square roots
+ * of the first eight prime numbers
+ */
+ H1 = 0x6a09e667f3bcc908;
+ H2 = 0xbb67ae8584caa73b;
+ H3 = 0x3c6ef372fe94f82b;
+ H4 = 0xa54ff53a5f1d36f1;
+ H5 = 0x510e527fade682d1;
+ H6 = 0x9b05688c2b3e6c1f;
+ H7 = 0x1f83d9abfb41bd6b;
+ H8 = 0x5be0cd19137e2179;
+ }
+ }
+}
diff --git a/Renci.SshNet/Security/Cryptography/Key.cs b/Renci.SshNet/Security/Cryptography/Key.cs
index 4f0a100..c13ede0 100644
--- a/Renci.SshNet/Security/Cryptography/Key.cs
+++ b/Renci.SshNet/Security/Cryptography/Key.cs
@@ -1,94 +1,90 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Renci.SshNet.Common;
-using Renci.SshNet.Security.Cryptography;
-
-namespace Renci.SshNet.Security
-{
- ///
- /// Base class for asymmetric cipher algorithms
- ///
- public abstract class Key
- {
- ///
- /// Specifies array of big integers that represent private key
- ///
- protected BigInteger[] _privateKey;
-
- ///
- /// Gets the key specific digital signature.
- ///
- protected abstract DigitalSignature DigitalSignature { get; }
-
- ///
- /// Gets or sets the public key.
- ///
- ///
- /// The public.
- ///
- public abstract BigInteger[] Public { get; set; }
-
- ///
- /// Gets the length of the key.
- ///
- ///
- /// The length of the key.
- ///
- public abstract int KeyLength { get; }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// DER encoded private key data.
- public Key(byte[] data)
- {
- if (data == null)
- throw new ArgumentNullException("data");
-
- var der = new DerData(data);
- var version = der.ReadBigInteger();
-
- var keys = new List();
- while (!der.IsEndOfData)
- {
- keys.Add(der.ReadBigInteger());
- }
-
- this._privateKey = keys.ToArray();
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- public Key()
- : base()
- {
-
- }
-
- ///
- /// Signs the specified data with the key.
- ///
- /// The data to sign.
- ///
- /// Signed data.
- ///
- public byte[] Sign(byte[] data)
- {
- return this.DigitalSignature.Sign(data);
- }
-
- ///
- /// Verifies the signature.
- ///
- /// The data to verify.
- /// The signature to verify against.
- /// True is signature was successfully verifies; otherwise false.
- public bool VerifySignature(byte[] data, byte[] signature)
- {
- return this.DigitalSignature.Verify(data, signature);
- }
- }
-}
+using System;
+using System.Collections.Generic;
+using Renci.SshNet.Common;
+using Renci.SshNet.Security.Cryptography;
+
+namespace Renci.SshNet.Security
+{
+ ///
+ /// Base class for asymmetric cipher algorithms
+ ///
+ public abstract class Key
+ {
+ ///
+ /// Specifies array of big integers that represent private key
+ ///
+ protected BigInteger[] _privateKey;
+
+ ///
+ /// Gets the key specific digital signature.
+ ///
+ protected abstract DigitalSignature DigitalSignature { get; }
+
+ ///
+ /// Gets or sets the public key.
+ ///
+ ///
+ /// The public.
+ ///
+ public abstract BigInteger[] Public { get; set; }
+
+ ///
+ /// Gets the length of the key.
+ ///
+ ///
+ /// The length of the key.
+ ///
+ public abstract int KeyLength { get; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// DER encoded private key data.
+ public Key(byte[] data)
+ {
+ if (data == null)
+ throw new ArgumentNullException("data");
+
+ var der = new DerData(data);
+ var version = der.ReadBigInteger();
+
+ var keys = new List();
+ while (!der.IsEndOfData)
+ {
+ keys.Add(der.ReadBigInteger());
+ }
+
+ this._privateKey = keys.ToArray();
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public Key()
+ {
+ }
+
+ ///
+ /// Signs the specified data with the key.
+ ///
+ /// The data to sign.
+ ///
+ /// Signed data.
+ ///
+ public byte[] Sign(byte[] data)
+ {
+ return this.DigitalSignature.Sign(data);
+ }
+
+ ///
+ /// Verifies the signature.
+ ///
+ /// The data to verify.
+ /// The signature to verify against.
+ /// True is signature was successfully verifies; otherwise false.
+ public bool VerifySignature(byte[] data, byte[] signature)
+ {
+ return this.DigitalSignature.Verify(data, signature);
+ }
+ }
+}
diff --git a/Renci.SshNet/Security/Cryptography/RsaDigitalSignature.cs b/Renci.SshNet/Security/Cryptography/RsaDigitalSignature.cs
index 5f9f05f..bf3dedc 100644
--- a/Renci.SshNet/Security/Cryptography/RsaDigitalSignature.cs
+++ b/Renci.SshNet/Security/Cryptography/RsaDigitalSignature.cs
@@ -1,94 +1,91 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Security.Cryptography;
-using Renci.SshNet.Common;
-using Renci.SshNet.Security.Cryptography.Ciphers;
-
-namespace Renci.SshNet.Security.Cryptography
-{
- ///
- /// Implements RSA digital signature algorithm.
- ///
- public class RsaDigitalSignature : CipherDigitalSignature, IDisposable
- {
- private HashAlgorithm _hash;
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The RSA key.
- public RsaDigitalSignature(RsaKey rsaKey)
- : base(new ObjectIdentifier(1, 3, 14, 3, 2, 26), new RsaCipher(rsaKey))
- {
- this._hash = new SHA1Hash();
- }
-
- ///
- /// Hashes the specified input.
- ///
- /// The input.
- ///
- /// Hashed data.
- ///
- protected override byte[] Hash(byte[] input)
- {
- return this._hash.ComputeHash(input);
- }
-
- #region IDisposable Members
-
- private bool _isDisposed = false;
-
- ///
- /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged ResourceMessages.
- ///
- public void Dispose()
- {
- Dispose(true);
-
- GC.SuppressFinalize(this);
- }
-
- ///
- /// Releases unmanaged and - optionally - managed resources
- ///
- /// true to release both managed and unmanaged resources; false to release only unmanaged ResourceMessages.
- 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._hash != null)
- {
- this._hash.Clear();
- this._hash = null;
- }
- }
-
- // Note disposing has been done.
- this._isDisposed = true;
- }
- }
-
- ///
- /// Releases unmanaged resources and performs other cleanup operations before the
- /// is reclaimed by garbage collection.
- ///
- ~RsaDigitalSignature()
- {
- // Do not re-create Dispose clean-up code here.
- // Calling Dispose(false) is optimal in terms of
- // readability and maintainability.
- Dispose(false);
- }
-
- #endregion
- }
-}
+using System;
+using System.Security.Cryptography;
+using Renci.SshNet.Common;
+using Renci.SshNet.Security.Cryptography.Ciphers;
+
+namespace Renci.SshNet.Security.Cryptography
+{
+ ///
+ /// Implements RSA digital signature algorithm.
+ ///
+ public class RsaDigitalSignature : CipherDigitalSignature, IDisposable
+ {
+ private HashAlgorithm _hash;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The RSA key.
+ public RsaDigitalSignature(RsaKey rsaKey)
+ : base(new ObjectIdentifier(1, 3, 14, 3, 2, 26), new RsaCipher(rsaKey))
+ {
+ this._hash = new SHA1Hash();
+ }
+
+ ///
+ /// Hashes the specified input.
+ ///
+ /// The input.
+ ///
+ /// Hashed data.
+ ///
+ protected override byte[] Hash(byte[] input)
+ {
+ return this._hash.ComputeHash(input);
+ }
+
+ #region IDisposable Members
+
+ private bool _isDisposed;
+
+ ///
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged ResourceMessages.
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Releases unmanaged and - optionally - managed resources
+ ///
+ /// true to release both managed and unmanaged resources; false to release only unmanaged ResourceMessages.
+ 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._hash != null)
+ {
+ this._hash.Clear();
+ this._hash = null;
+ }
+ }
+
+ // Note disposing has been done.
+ this._isDisposed = true;
+ }
+ }
+
+ ///
+ /// Releases unmanaged resources and performs other cleanup operations before the
+ /// is reclaimed by garbage collection.
+ ///
+ ~RsaDigitalSignature()
+ {
+ // Do not re-create Dispose clean-up code here.
+ // Calling Dispose(false) is optimal in terms of
+ // readability and maintainability.
+ Dispose(false);
+ }
+
+ #endregion
+ }
+}
diff --git a/Renci.SshNet/Security/Cryptography/RsaKey.cs b/Renci.SshNet/Security/Cryptography/RsaKey.cs
index dae8a44..c293800 100644
--- a/Renci.SshNet/Security/Cryptography/RsaKey.cs
+++ b/Renci.SshNet/Security/Cryptography/RsaKey.cs
@@ -1,273 +1,264 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Renci.SshNet.Common;
-using Renci.SshNet.Security.Cryptography;
-
-namespace Renci.SshNet.Security
-{
- ///
- /// Contains RSA private and public key
- ///
- public class RsaKey : Key, IDisposable
- {
- ///
- /// Gets the modulus.
- ///
- public BigInteger Modulus
- {
- get
- {
- return this._privateKey[0];
- }
- }
-
- ///
- /// Gets the exponent.
- ///
- public BigInteger Exponent
- {
- get
- {
- return this._privateKey[1];
- }
- }
-
- ///
- /// Gets the D.
- ///
- public BigInteger D
- {
- get
- {
- if (this._privateKey.Length > 2)
- return this._privateKey[2];
- else
- return BigInteger.Zero;
- }
- }
-
- ///
- /// Gets the P.
- ///
- public BigInteger P
- {
- get
- {
- if (this._privateKey.Length > 3)
- return this._privateKey[3];
- else
- return BigInteger.Zero;
- }
- }
-
- ///
- /// Gets the Q.
- ///
- public BigInteger Q
- {
- get
- {
- if (this._privateKey.Length > 4)
- return this._privateKey[4];
- else
- return BigInteger.Zero;
- }
- }
-
- ///
- /// Gets the DP.
- ///
- public BigInteger DP
- {
- get
- {
- if (this._privateKey.Length > 5)
- return this._privateKey[5];
- else
- return BigInteger.Zero;
- }
- }
-
- ///
- /// Gets the DQ.
- ///
- public BigInteger DQ
- {
- get
- {
- if (this._privateKey.Length > 6)
- return this._privateKey[6];
- else
- return BigInteger.Zero;
- }
- }
-
- ///
- /// Gets the inverse Q.
- ///
- public BigInteger InverseQ
- {
- get
- {
- if (this._privateKey.Length > 7)
- return this._privateKey[7];
- else
- return BigInteger.Zero;
- }
- }
-
- ///
- /// Gets the length of the key.
- ///
- ///
- /// The length of the key.
- ///
- public override int KeyLength
- {
- get
- {
- return this.Modulus.BitLength;
- }
- }
-
- private RsaDigitalSignature _digitalSignature;
- ///
- /// Gets the digital signature.
- ///
- protected override DigitalSignature DigitalSignature
- {
- get
- {
- if (this._digitalSignature == null)
- {
- this._digitalSignature = new RsaDigitalSignature(this);
- }
- return this._digitalSignature;
- }
- }
-
- ///
- /// Gets or sets the public.
- ///
- ///
- /// The public.
- ///
- public override BigInteger[] Public
- {
- get
- {
- return new BigInteger[] { this.Exponent, this.Modulus };
- }
- set
- {
- if (value.Length != 2)
- throw new InvalidOperationException("Invalid private key.");
-
- this._privateKey = new BigInteger[] { value[1], value[0] };
- }
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- public RsaKey()
- {
-
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// DER encoded private key data.
- public RsaKey(byte[] data)
- : base(data)
- {
- if (this._privateKey.Length != 8)
- throw new InvalidOperationException("Invalid private key.");
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The modulus.
- /// The exponent.
- /// The d.
- /// The p.
- /// The q.
- /// The inverse Q.
- public RsaKey(BigInteger modulus, BigInteger exponent, BigInteger d, BigInteger p, BigInteger q, BigInteger inverseQ)
- {
- this._privateKey = new BigInteger[8];
- this._privateKey[0] = modulus;
- this._privateKey[1] = exponent;
- this._privateKey[2] = d;
- this._privateKey[3] = p;
- this._privateKey[4] = q;
- this._privateKey[5] = PrimeExponent(d, p);
- this._privateKey[6] = PrimeExponent(d, q);
- this._privateKey[7] = inverseQ;
- }
-
- private static BigInteger PrimeExponent(BigInteger privateExponent, BigInteger prime)
- {
- BigInteger pe = prime - new BigInteger(1);
- return privateExponent % pe;
- }
-
- #region IDisposable Members
-
- private bool _isDisposed = false;
-
- ///
- /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged ResourceMessages.
- ///
- public void Dispose()
- {
- Dispose(true);
-
- GC.SuppressFinalize(this);
- }
-
- ///
- /// Releases unmanaged and - optionally - managed resources
- ///
- /// true to release both managed and unmanaged resources; false to release only unmanaged ResourceMessages.
- 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._digitalSignature != null)
- {
- this._digitalSignature.Dispose();
- this._digitalSignature = null;
- }
- }
-
- // Note disposing has been done.
- this._isDisposed = true;
- }
- }
-
- ///
- /// Releases unmanaged resources and performs other cleanup operations before the
- /// is reclaimed by garbage collection.
- ///
- ~RsaKey()
- {
- // Do not re-create Dispose clean-up code here.
- // Calling Dispose(false) is optimal in terms of
- // readability and maintainability.
- Dispose(false);
- }
-
- #endregion
- }
-}
+using System;
+using Renci.SshNet.Common;
+using Renci.SshNet.Security.Cryptography;
+
+namespace Renci.SshNet.Security
+{
+ ///
+ /// Contains RSA private and public key
+ ///
+ public class RsaKey : Key, IDisposable
+ {
+ ///
+ /// Gets the modulus.
+ ///
+ public BigInteger Modulus
+ {
+ get
+ {
+ return this._privateKey[0];
+ }
+ }
+
+ ///
+ /// Gets the exponent.
+ ///
+ public BigInteger Exponent
+ {
+ get
+ {
+ return this._privateKey[1];
+ }
+ }
+
+ ///
+ /// Gets the D.
+ ///
+ public BigInteger D
+ {
+ get
+ {
+ if (this._privateKey.Length > 2)
+ return this._privateKey[2];
+ return BigInteger.Zero;
+ }
+ }
+
+ ///
+ /// Gets the P.
+ ///
+ public BigInteger P
+ {
+ get
+ {
+ if (this._privateKey.Length > 3)
+ return this._privateKey[3];
+ return BigInteger.Zero;
+ }
+ }
+
+ ///
+ /// Gets the Q.
+ ///
+ public BigInteger Q
+ {
+ get
+ {
+ if (this._privateKey.Length > 4)
+ return this._privateKey[4];
+ return BigInteger.Zero;
+ }
+ }
+
+ ///
+ /// Gets the DP.
+ ///
+ public BigInteger DP
+ {
+ get
+ {
+ if (this._privateKey.Length > 5)
+ return this._privateKey[5];
+ return BigInteger.Zero;
+ }
+ }
+
+ ///
+ /// Gets the DQ.
+ ///
+ public BigInteger DQ
+ {
+ get
+ {
+ if (this._privateKey.Length > 6)
+ return this._privateKey[6];
+ return BigInteger.Zero;
+ }
+ }
+
+ ///
+ /// Gets the inverse Q.
+ ///
+ public BigInteger InverseQ
+ {
+ get
+ {
+ if (this._privateKey.Length > 7)
+ return this._privateKey[7];
+ return BigInteger.Zero;
+ }
+ }
+
+ ///
+ /// Gets the length of the key.
+ ///
+ ///
+ /// The length of the key.
+ ///
+ public override int KeyLength
+ {
+ get
+ {
+ return this.Modulus.BitLength;
+ }
+ }
+
+ private RsaDigitalSignature _digitalSignature;
+ ///
+ /// Gets the digital signature.
+ ///
+ protected override DigitalSignature DigitalSignature
+ {
+ get
+ {
+ if (this._digitalSignature == null)
+ {
+ this._digitalSignature = new RsaDigitalSignature(this);
+ }
+ return this._digitalSignature;
+ }
+ }
+
+ ///
+ /// Gets or sets the public.
+ ///
+ ///
+ /// The public.
+ ///
+ public override BigInteger[] Public
+ {
+ get
+ {
+ return new BigInteger[] { this.Exponent, this.Modulus };
+ }
+ set
+ {
+ if (value.Length != 2)
+ throw new InvalidOperationException("Invalid private key.");
+
+ this._privateKey = new BigInteger[] { value[1], value[0] };
+ }
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public RsaKey()
+ {
+
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// DER encoded private key data.
+ public RsaKey(byte[] data)
+ : base(data)
+ {
+ if (this._privateKey.Length != 8)
+ throw new InvalidOperationException("Invalid private key.");
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The modulus.
+ /// The exponent.
+ /// The d.
+ /// The p.
+ /// The q.
+ /// The inverse Q.
+ public RsaKey(BigInteger modulus, BigInteger exponent, BigInteger d, BigInteger p, BigInteger q, BigInteger inverseQ)
+ {
+ this._privateKey = new BigInteger[8];
+ this._privateKey[0] = modulus;
+ this._privateKey[1] = exponent;
+ this._privateKey[2] = d;
+ this._privateKey[3] = p;
+ this._privateKey[4] = q;
+ this._privateKey[5] = PrimeExponent(d, p);
+ this._privateKey[6] = PrimeExponent(d, q);
+ this._privateKey[7] = inverseQ;
+ }
+
+ private static BigInteger PrimeExponent(BigInteger privateExponent, BigInteger prime)
+ {
+ BigInteger pe = prime - new BigInteger(1);
+ return privateExponent % pe;
+ }
+
+ #region IDisposable Members
+
+ private bool _isDisposed;
+
+ ///
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged ResourceMessages.
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Releases unmanaged and - optionally - managed resources
+ ///
+ /// true to release both managed and unmanaged resources; false to release only unmanaged ResourceMessages.
+ 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._digitalSignature != null)
+ {
+ this._digitalSignature.Dispose();
+ this._digitalSignature = null;
+ }
+ }
+
+ // Note disposing has been done.
+ this._isDisposed = true;
+ }
+ }
+
+ ///
+ /// Releases unmanaged resources and performs other cleanup operations before the
+ /// is reclaimed by garbage collection.
+ ///
+ ~RsaKey()
+ {
+ // Do not re-create Dispose clean-up code here.
+ // Calling Dispose(false) is optimal in terms of
+ // readability and maintainability.
+ Dispose(false);
+ }
+
+ #endregion
+ }
+}
diff --git a/Renci.SshNet/Security/Cryptography/StreamCipher.cs b/Renci.SshNet/Security/Cryptography/StreamCipher.cs
index ed5386e..a0f3442 100644
--- a/Renci.SshNet/Security/Cryptography/StreamCipher.cs
+++ b/Renci.SshNet/Security/Cryptography/StreamCipher.cs
@@ -1,23 +1,20 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace Renci.SshNet.Security.Cryptography
-{
- ///
- /// Base class of stream cipher algorithms.
- ///
- public abstract class StreamCipher : SymmetricCipher
- {
- ///
- /// Initializes a new instance of the class.
- ///
- /// The key.
- /// is null.
- protected StreamCipher(byte[] key)
- : base(key)
- {
- }
- }
-}
+using System;
+
+namespace Renci.SshNet.Security.Cryptography
+{
+ ///
+ /// Base class of stream cipher algorithms.
+ ///
+ public abstract class StreamCipher : SymmetricCipher
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The key.
+ /// is null.
+ protected StreamCipher(byte[] key)
+ : base(key)
+ {
+ }
+ }
+}
diff --git a/Renci.SshNet/Security/Cryptography/SymmetricCipher.cs b/Renci.SshNet/Security/Cryptography/SymmetricCipher.cs
index be62410..4eb3396 100644
--- a/Renci.SshNet/Security/Cryptography/SymmetricCipher.cs
+++ b/Renci.SshNet/Security/Cryptography/SymmetricCipher.cs
@@ -1,57 +1,54 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace Renci.SshNet.Security.Cryptography
-{
- ///
- /// Base class for symmetric cipher implementations.
- ///
- public abstract class SymmetricCipher : Cipher
- {
- ///
- /// Gets the key.
- ///
- protected byte[] Key { get; private set; }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The key.
- /// is null.
- protected SymmetricCipher(byte[] key)
- {
- if (key == null)
- throw new ArgumentNullException("key");
-
- this.Key = key;
- }
-
- ///
- /// Encrypts the specified region of the input byte array and copies the encrypted data to the specified region of the output byte array.
- ///
- /// The input data to encrypt.
- /// The offset into the input byte array from which to begin using data.
- /// The number of bytes in the input byte array to use as data.
- /// The output to which to write encrypted data.
- /// The offset into the output byte array from which to begin writing data.
- ///
- /// The number of bytes encrypted.
- ///
- public abstract int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset);
-
- ///
- /// Decrypts the specified region of the input byte array and copies the decrypted data to the specified region of the output byte array.
- ///
- /// The input data to decrypt.
- /// The offset into the input byte array from which to begin using data.
- /// The number of bytes in the input byte array to use as data.
- /// The output to which to write decrypted data.
- /// The offset into the output byte array from which to begin writing data.
- ///
- /// The number of bytes decrypted.
- ///
- public abstract int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset);
- }
-}
+using System;
+
+namespace Renci.SshNet.Security.Cryptography
+{
+ ///
+ /// Base class for symmetric cipher implementations.
+ ///
+ public abstract class SymmetricCipher : Cipher
+ {
+ ///
+ /// Gets the key.
+ ///
+ protected byte[] Key { get; private set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The key.
+ /// is null.
+ protected SymmetricCipher(byte[] key)
+ {
+ if (key == null)
+ throw new ArgumentNullException("key");
+
+ this.Key = key;
+ }
+
+ ///
+ /// Encrypts the specified region of the input byte array and copies the encrypted data to the specified region of the output byte array.
+ ///
+ /// The input data to encrypt.
+ /// The offset into the input byte array from which to begin using data.
+ /// The number of bytes in the input byte array to use as data.
+ /// The output to which to write encrypted data.
+ /// The offset into the output byte array from which to begin writing data.
+ ///
+ /// The number of bytes encrypted.
+ ///
+ public abstract int EncryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset);
+
+ ///
+ /// Decrypts the specified region of the input byte array and copies the decrypted data to the specified region of the output byte array.
+ ///
+ /// The input data to decrypt.
+ /// The offset into the input byte array from which to begin using data.
+ /// The number of bytes in the input byte array to use as data.
+ /// The output to which to write decrypted data.
+ /// The offset into the output byte array from which to begin writing data.
+ ///
+ /// The number of bytes decrypted.
+ ///
+ public abstract int DecryptBlock(byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset);
+ }
+}
diff --git a/Renci.SshNet/Security/HostAlgorithm.cs b/Renci.SshNet/Security/HostAlgorithm.cs
index 9dcfb36..14474d9 100644
--- a/Renci.SshNet/Security/HostAlgorithm.cs
+++ b/Renci.SshNet/Security/HostAlgorithm.cs
@@ -1,49 +1,42 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Renci.SshNet.Common;
-using Renci.SshNet.Security.Cryptography;
-
-namespace Renci.SshNet.Security
-{
- ///
- /// Base class for SSH host algorithms.
- ///
- public abstract class HostAlgorithm
- {
- ///
- /// Gets the host key name.
- ///
- public string Name { get; private set; }
-
- ///
- /// Gets the host key data.
- ///
- public abstract byte[] Data { get; }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The host key name.
- public HostAlgorithm(string name)
- {
- this.Name = name;
- }
-
- ///
- /// Signs the specified data.
- ///
- /// The data.
- /// Signed data.
- public abstract byte[] Sign(byte[] data);
-
- ///
- /// Verifies the signature.
- ///
- /// The data.
- /// The signature.
- /// True is signature was successfully verifies; otherwise false.
- public abstract bool VerifySignature(byte[] data, byte[] signature);
- }
-}
+namespace Renci.SshNet.Security
+{
+ ///
+ /// Base class for SSH host algorithms.
+ ///
+ public abstract class HostAlgorithm
+ {
+ ///
+ /// Gets the host key name.
+ ///
+ public string Name { get; private set; }
+
+ ///
+ /// Gets the host key data.
+ ///
+ public abstract byte[] Data { get; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The host key name.
+ public HostAlgorithm(string name)
+ {
+ this.Name = name;
+ }
+
+ ///
+ /// Signs the specified data.
+ ///
+ /// The data.
+ /// Signed data.
+ public abstract byte[] Sign(byte[] data);
+
+ ///
+ /// Verifies the signature.
+ ///
+ /// The data.
+ /// The signature.
+ /// True is signature was successfully verifies; otherwise false.
+ public abstract bool VerifySignature(byte[] data, byte[] signature);
+ }
+}
diff --git a/Renci.SshNet/Security/KeyExchange.cs b/Renci.SshNet/Security/KeyExchange.cs
index 88759c3..a2bbe70 100644
--- a/Renci.SshNet/Security/KeyExchange.cs
+++ b/Renci.SshNet/Security/KeyExchange.cs
@@ -1,457 +1,456 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Security.Cryptography;
-using Renci.SshNet.Common;
-using Renci.SshNet.Compression;
-using Renci.SshNet.Messages;
-using Renci.SshNet.Messages.Transport;
-using Renci.SshNet.Security.Cryptography.Ciphers;
-using Renci.SshNet.Security.Cryptography;
-
-namespace Renci.SshNet.Security
-{
- ///
- /// Represents base class for different key exchange algorithm implementations
- ///
- public abstract class KeyExchange : Algorithm, IDisposable
- {
- private CipherInfo _clientCipherInfo;
-
- private CipherInfo _serverCipherInfo;
-
- private HashInfo _clientHashInfo;
-
- private HashInfo _serverHashInfo;
-
- private Type _compressionType;
-
- private Type _decompressionType;
-
- ///
- /// Gets or sets the session.
- ///
- ///
- /// The session.
- ///
- protected Session Session { get; private set; }
-
- ///
- /// Gets or sets key exchange shared key.
- ///
- ///
- /// The shared key.
- ///
- public BigInteger SharedKey { get; protected set; }
-
- private byte[] _exchangeHash;
- ///
- /// Gets the exchange hash.
- ///
- /// The exchange hash.
- public byte[] ExchangeHash
- {
- get
- {
- if (this._exchangeHash == null)
- {
- this._exchangeHash = this.CalculateHash();
- }
- return this._exchangeHash;
- }
- }
-
- ///
- /// Occurs when host key received.
- ///
- public event EventHandler HostKeyReceived;
-
- ///
- /// Starts key exchange algorithm
- ///
- /// The session.
- /// Key exchange init message.
- public virtual void Start(Session session, KeyExchangeInitMessage message)
- {
- this.Session = session;
-
- this.SendMessage(session.ClientInitMessage);
-
- // Determine encryption algorithm
- var clientEncryptionAlgorithmName = (from b in session.ConnectionInfo.Encryptions.Keys
- from a in message.EncryptionAlgorithmsClientToServer
- where a == b
- select a).FirstOrDefault();
-
- if (string.IsNullOrEmpty(clientEncryptionAlgorithmName))
- {
- throw new SshConnectionException("Client encryption algorithm not found", DisconnectReason.KeyExchangeFailed);
- }
-
- session.ConnectionInfo.CurrentClientEncryption = clientEncryptionAlgorithmName;
-
- // Determine encryption algorithm
- var serverDecryptionAlgorithmName = (from b in session.ConnectionInfo.Encryptions.Keys
- from a in message.EncryptionAlgorithmsServerToClient
- where a == b
- select a).FirstOrDefault();
- if (string.IsNullOrEmpty(serverDecryptionAlgorithmName))
- {
- throw new SshConnectionException("Server decryption algorithm not found", DisconnectReason.KeyExchangeFailed);
- }
-
- session.ConnectionInfo.CurrentServerEncryption = serverDecryptionAlgorithmName;
-
- // Determine client hmac algorithm
- var clientHmacAlgorithmName = (from b in session.ConnectionInfo.HmacAlgorithms.Keys
- from a in message.MacAlgorithmsClientToServer
- where a == b
- select a).FirstOrDefault();
- if (string.IsNullOrEmpty(clientHmacAlgorithmName))
- {
- throw new SshConnectionException("Server HMAC algorithm not found", DisconnectReason.KeyExchangeFailed);
- }
-
- session.ConnectionInfo.CurrentClientHmacAlgorithm = clientHmacAlgorithmName;
-
- // Determine server hmac algorithm
- var serverHmacAlgorithmName = (from b in session.ConnectionInfo.HmacAlgorithms.Keys
- from a in message.MacAlgorithmsServerToClient
- where a == b
- select a).FirstOrDefault();
- if (string.IsNullOrEmpty(serverHmacAlgorithmName))
- {
- throw new SshConnectionException("Server HMAC algorithm not found", DisconnectReason.KeyExchangeFailed);
- }
-
- session.ConnectionInfo.CurrentServerHmacAlgorithm = serverHmacAlgorithmName;
-
- // Determine compression algorithm
- var compressionAlgorithmName = (from b in session.ConnectionInfo.CompressionAlgorithms.Keys
- from a in message.CompressionAlgorithmsClientToServer
- where a == b
- select a).LastOrDefault();
- if (string.IsNullOrEmpty(compressionAlgorithmName))
- {
- throw new SshConnectionException("Compression algorithm not found", DisconnectReason.KeyExchangeFailed);
- }
-
- session.ConnectionInfo.CurrentClientCompressionAlgorithm = compressionAlgorithmName;
-
- // Determine decompression algorithm
- var decompressionAlgorithmName = (from b in session.ConnectionInfo.CompressionAlgorithms.Keys
- from a in message.CompressionAlgorithmsServerToClient
- where a == b
- select a).LastOrDefault();
- if (string.IsNullOrEmpty(decompressionAlgorithmName))
- {
- throw new SshConnectionException("Decompression algorithm not found", DisconnectReason.KeyExchangeFailed);
- }
-
- session.ConnectionInfo.CurrentServerCompressionAlgorithm = decompressionAlgorithmName;
-
- this._clientCipherInfo = session.ConnectionInfo.Encryptions[clientEncryptionAlgorithmName];
- this._serverCipherInfo = session.ConnectionInfo.Encryptions[clientEncryptionAlgorithmName];
- this._clientHashInfo = session.ConnectionInfo.HmacAlgorithms[clientHmacAlgorithmName];
- this._serverHashInfo = session.ConnectionInfo.HmacAlgorithms[serverHmacAlgorithmName];
- this._compressionType = session.ConnectionInfo.CompressionAlgorithms[compressionAlgorithmName];
- this._decompressionType = session.ConnectionInfo.CompressionAlgorithms[decompressionAlgorithmName];
- }
-
- ///
- /// Finishes key exchange algorithm.
- ///
- public virtual void Finish()
- {
- // Validate hash
- if (this.ValidateExchangeHash())
- {
- this.SendMessage(new NewKeysMessage());
- }
- else
- {
- throw new SshConnectionException("Key exchange negotiation failed.", DisconnectReason.KeyExchangeFailed);
- }
- }
-
- ///
- /// Creates the server side cipher to use.
- ///
- /// Server cipher.
- public Cipher CreateServerCipher()
- {
- // Resolve Session ID
- var sessionId = this.Session.SessionId ?? this.ExchangeHash;
-
- // Calculate server to client initial IV
- var serverVector = this.Hash(this.GenerateSessionKey(this.SharedKey, this.ExchangeHash, 'B', sessionId));
-
- // Calculate server to client encryption
- var serverKey = this.Hash(this.GenerateSessionKey(this.SharedKey, this.ExchangeHash, 'D', sessionId));
-
- serverKey = this.GenerateSessionKey(this.SharedKey, this.ExchangeHash, serverKey, this._serverCipherInfo.KeySize / 8);
-
- // Create server cipher
- return this._serverCipherInfo.Cipher(serverKey, serverVector);
- }
-
- ///
- /// Creates the client side cipher to use.
- ///
- /// Client cipher.
- public Cipher CreateClientCipher()
- {
- // Resolve Session ID
- var sessionId = this.Session.SessionId ?? this.ExchangeHash;
-
- // Calculate client to server initial IV
- var clientVector = this.Hash(this.GenerateSessionKey(this.SharedKey, this.ExchangeHash, 'A', sessionId));
-
- // Calculate client to server encryption
- var clientKey = this.Hash(this.GenerateSessionKey(this.SharedKey, this.ExchangeHash, 'C', sessionId));
-
- clientKey = this.GenerateSessionKey(this.SharedKey, this.ExchangeHash, clientKey, this._clientCipherInfo.KeySize / 8);
-
- // Create client cipher
- return this._clientCipherInfo.Cipher(clientKey, clientVector);
- }
-
- ///
- /// Creates the server side hash algorithm to use.
- ///
- /// Hash algorithm
- public HashAlgorithm CreateServerHash()
- {
- // Resolve Session ID
- var sessionId = this.Session.SessionId ?? this.ExchangeHash;
-
- var serverKey = this.Hash(this.GenerateSessionKey(this.SharedKey, this.ExchangeHash, 'F', sessionId));
-
- serverKey = this.GenerateSessionKey(this.SharedKey, this.ExchangeHash, serverKey, this._serverHashInfo.KeySize / 8);
-
- //return serverHMac;
- return this._serverHashInfo.HashAlgorithm(serverKey);
- }
-
- ///
- /// Creates the client side hash algorithm to use.
- ///
- /// Hash algorithm
- public HashAlgorithm CreateClientHash()
- {
- // Resolve Session ID
- var sessionId = this.Session.SessionId ?? this.ExchangeHash;
-
- var clientKey = this.Hash(this.GenerateSessionKey(this.SharedKey, this.ExchangeHash, 'E', sessionId));
-
- clientKey = this.GenerateSessionKey(this.SharedKey, this.ExchangeHash, clientKey, this._clientHashInfo.KeySize / 8);
-
- //return clientHMac;
- return this._clientHashInfo.HashAlgorithm(clientKey);
- }
-
- ///
- /// Creates the compression algorithm to use to deflate data.
- ///
- /// Compression method.
- public Compressor CreateCompressor()
- {
- if (this._compressionType == null)
- return null;
-
- var compressor = this._compressionType.CreateInstance();
-
- compressor.Init(this.Session);
-
- return compressor;
- }
-
- ///
- /// Creates the compression algorithm to use to inflate data.
- ///
- /// Compression method.
- public Compressor CreateDecompressor()
- {
- if (this._compressionType == null)
- return null;
-
- var decompressor = this._decompressionType.CreateInstance();
-
- decompressor.Init(this.Session);
-
- return decompressor;
- }
-
- ///
- /// Determines whether the specified host key can be trusted.
- ///
- /// The host algorithm.
- ///
- /// true if the specified host can be trusted; otherwise, false.
- ///
- protected bool CanTrustHostKey(KeyHostAlgorithm host)
- {
- var args = new HostKeyEventArgs(host);
-
- if (this.HostKeyReceived != null)
- {
- this.HostKeyReceived(this, args);
- }
-
- return args.CanTrust;
- }
-
- ///
- /// Validates the exchange hash.
- ///
- /// true if exchange hash is valid; otherwise false.
- protected abstract bool ValidateExchangeHash();
-
- ///
- /// Calculates key exchange hash value.
- ///
- /// Key exchange hash.
- protected abstract byte[] CalculateHash();
-
- ///
- /// Hashes the specified data bytes.
- ///
- /// The hash data.
- ///
- /// Hashed bytes
- ///
- protected virtual byte[] Hash(byte[] hashData)
- {
- using (var sha1 = new Renci.SshNet.Security.Cryptography.SHA1Hash())
- {
- return sha1.ComputeHash(hashData, 0, hashData.Length);
- }
- }
-
- ///
- /// Sends SSH message to the server
- ///
- /// The message.
- protected void SendMessage(Message message)
- {
- this.Session.SendMessage(message);
- }
-
- ///
- /// Generates the session key.
- ///
- /// The shared key.
- /// The exchange hash.
- /// The key.
- /// The size.
- ///
- private byte[] GenerateSessionKey(BigInteger sharedKey, byte[] exchangeHash, byte[] key, int size)
- {
- var result = new List(key);
- while (size > result.Count)
- {
- result.AddRange(this.Hash(new _SessionKeyAdjustment
- {
- SharedKey = sharedKey,
- ExcahngeHash = exchangeHash,
- Key = key,
- }.GetBytes()));
- }
-
- return result.ToArray();
- }
-
- ///
- /// Generates the session key.
- ///
- /// The shared key.
- /// The exchange hash.
- /// The p.
- /// The session id.
- ///
- private byte[] GenerateSessionKey(BigInteger sharedKey, byte[] exchangeHash, char p, byte[] sessionId)
- {
- return new _SessionKeyGeneration
- {
- SharedKey = sharedKey,
- ExchangeHash = exchangeHash,
- Char = p,
- SessionId = sessionId,
- }.GetBytes();
- }
-
- private class _SessionKeyGeneration : SshData
- {
- public BigInteger SharedKey { get; set; }
- public byte[] ExchangeHash { get; set; }
- public char Char { get; set; }
- public byte[] SessionId { get; set; }
-
- protected override void LoadData()
- {
- throw new NotImplementedException();
- }
-
- protected override void SaveData()
- {
- this.Write(this.SharedKey);
- this.Write(this.ExchangeHash);
- this.Write((byte)this.Char);
- this.Write(this.SessionId);
- }
- }
-
- private class _SessionKeyAdjustment : SshData
- {
- public BigInteger SharedKey { get; set; }
- public byte[] ExcahngeHash { get; set; }
- public byte[] Key { get; set; }
-
- protected override void LoadData()
- {
- throw new NotImplementedException();
- }
-
- protected override void SaveData()
- {
- this.Write(this.SharedKey);
- this.Write(this.ExcahngeHash);
- this.Write(this.Key);
- }
- }
-
- #region IDisposable Members
-
- ///
- /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged ResourceMessages.
- ///
- public void Dispose()
- {
- Dispose(true);
-
- GC.SuppressFinalize(this);
- }
-
- ///
- /// Releases unmanaged and - optionally - managed resources
- ///
- /// true to release both managed and unmanaged resources; false to release only unmanaged ResourceMessages.
- protected virtual void Dispose(bool disposing)
- {
- }
-
- ///
- /// Releases unmanaged resources and performs other cleanup operations before the
- /// is reclaimed by garbage collection.
- ///
- ~KeyExchange()
- {
- // Do not re-create Dispose clean-up code here.
- // Calling Dispose(false) is optimal in terms of
- // readability and maintainability.
- Dispose(false);
- }
-
- #endregion
- }
-}
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Security.Cryptography;
+using Renci.SshNet.Common;
+using Renci.SshNet.Compression;
+using Renci.SshNet.Messages;
+using Renci.SshNet.Messages.Transport;
+using Renci.SshNet.Security.Cryptography;
+
+namespace Renci.SshNet.Security
+{
+ ///
+ /// Represents base class for different key exchange algorithm implementations
+ ///
+ public abstract class KeyExchange : Algorithm, IDisposable
+ {
+ private CipherInfo _clientCipherInfo;
+
+ private CipherInfo _serverCipherInfo;
+
+ private HashInfo _clientHashInfo;
+
+ private HashInfo _serverHashInfo;
+
+ private Type _compressionType;
+
+ private Type _decompressionType;
+
+ ///
+ /// Gets or sets the session.
+ ///
+ ///
+ /// The session.
+ ///
+ protected Session Session { get; private set; }
+
+ ///
+ /// Gets or sets key exchange shared key.
+ ///
+ ///
+ /// The shared key.
+ ///
+ public BigInteger SharedKey { get; protected set; }
+
+ private byte[] _exchangeHash;
+ ///
+ /// Gets the exchange hash.
+ ///
+ /// The exchange hash.
+ public byte[] ExchangeHash
+ {
+ get
+ {
+ if (this._exchangeHash == null)
+ {
+ this._exchangeHash = this.CalculateHash();
+ }
+ return this._exchangeHash;
+ }
+ }
+
+ ///
+ /// Occurs when host key received.
+ ///
+ public event EventHandler HostKeyReceived;
+
+ ///
+ /// Starts key exchange algorithm
+ ///
+ /// The session.
+ /// Key exchange init message.
+ public virtual void Start(Session session, KeyExchangeInitMessage message)
+ {
+ this.Session = session;
+
+ this.SendMessage(session.ClientInitMessage);
+
+ // Determine encryption algorithm
+ var clientEncryptionAlgorithmName = (from b in session.ConnectionInfo.Encryptions.Keys
+ from a in message.EncryptionAlgorithmsClientToServer
+ where a == b
+ select a).FirstOrDefault();
+
+ if (string.IsNullOrEmpty(clientEncryptionAlgorithmName))
+ {
+ throw new SshConnectionException("Client encryption algorithm not found", DisconnectReason.KeyExchangeFailed);
+ }
+
+ session.ConnectionInfo.CurrentClientEncryption = clientEncryptionAlgorithmName;
+
+ // Determine encryption algorithm
+ var serverDecryptionAlgorithmName = (from b in session.ConnectionInfo.Encryptions.Keys
+ from a in message.EncryptionAlgorithmsServerToClient
+ where a == b
+ select a).FirstOrDefault();
+ if (string.IsNullOrEmpty(serverDecryptionAlgorithmName))
+ {
+ throw new SshConnectionException("Server decryption algorithm not found", DisconnectReason.KeyExchangeFailed);
+ }
+
+ session.ConnectionInfo.CurrentServerEncryption = serverDecryptionAlgorithmName;
+
+ // Determine client hmac algorithm
+ var clientHmacAlgorithmName = (from b in session.ConnectionInfo.HmacAlgorithms.Keys
+ from a in message.MacAlgorithmsClientToServer
+ where a == b
+ select a).FirstOrDefault();
+ if (string.IsNullOrEmpty(clientHmacAlgorithmName))
+ {
+ throw new SshConnectionException("Server HMAC algorithm not found", DisconnectReason.KeyExchangeFailed);
+ }
+
+ session.ConnectionInfo.CurrentClientHmacAlgorithm = clientHmacAlgorithmName;
+
+ // Determine server hmac algorithm
+ var serverHmacAlgorithmName = (from b in session.ConnectionInfo.HmacAlgorithms.Keys
+ from a in message.MacAlgorithmsServerToClient
+ where a == b
+ select a).FirstOrDefault();
+ if (string.IsNullOrEmpty(serverHmacAlgorithmName))
+ {
+ throw new SshConnectionException("Server HMAC algorithm not found", DisconnectReason.KeyExchangeFailed);
+ }
+
+ session.ConnectionInfo.CurrentServerHmacAlgorithm = serverHmacAlgorithmName;
+
+ // Determine compression algorithm
+ var compressionAlgorithmName = (from b in session.ConnectionInfo.CompressionAlgorithms.Keys
+ from a in message.CompressionAlgorithmsClientToServer
+ where a == b
+ select a).LastOrDefault();
+ if (string.IsNullOrEmpty(compressionAlgorithmName))
+ {
+ throw new SshConnectionException("Compression algorithm not found", DisconnectReason.KeyExchangeFailed);
+ }
+
+ session.ConnectionInfo.CurrentClientCompressionAlgorithm = compressionAlgorithmName;
+
+ // Determine decompression algorithm
+ var decompressionAlgorithmName = (from b in session.ConnectionInfo.CompressionAlgorithms.Keys
+ from a in message.CompressionAlgorithmsServerToClient
+ where a == b
+ select a).LastOrDefault();
+ if (string.IsNullOrEmpty(decompressionAlgorithmName))
+ {
+ throw new SshConnectionException("Decompression algorithm not found", DisconnectReason.KeyExchangeFailed);
+ }
+
+ session.ConnectionInfo.CurrentServerCompressionAlgorithm = decompressionAlgorithmName;
+
+ this._clientCipherInfo = session.ConnectionInfo.Encryptions[clientEncryptionAlgorithmName];
+ this._serverCipherInfo = session.ConnectionInfo.Encryptions[serverDecryptionAlgorithmName];
+ this._clientHashInfo = session.ConnectionInfo.HmacAlgorithms[clientHmacAlgorithmName];
+ this._serverHashInfo = session.ConnectionInfo.HmacAlgorithms[serverHmacAlgorithmName];
+ this._compressionType = session.ConnectionInfo.CompressionAlgorithms[compressionAlgorithmName];
+ this._decompressionType = session.ConnectionInfo.CompressionAlgorithms[decompressionAlgorithmName];
+ }
+
+ ///
+ /// Finishes key exchange algorithm.
+ ///
+ public virtual void Finish()
+ {
+ // Validate hash
+ if (this.ValidateExchangeHash())
+ {
+ this.SendMessage(new NewKeysMessage());
+ }
+ else
+ {
+ throw new SshConnectionException("Key exchange negotiation failed.", DisconnectReason.KeyExchangeFailed);
+ }
+ }
+
+ ///
+ /// Creates the server side cipher to use.
+ ///
+ /// Server cipher.
+ public Cipher CreateServerCipher()
+ {
+ // Resolve Session ID
+ var sessionId = this.Session.SessionId ?? this.ExchangeHash;
+
+ // Calculate server to client initial IV
+ var serverVector = this.Hash(this.GenerateSessionKey(this.SharedKey, this.ExchangeHash, 'B', sessionId));
+
+ // Calculate server to client encryption
+ var serverKey = this.Hash(this.GenerateSessionKey(this.SharedKey, this.ExchangeHash, 'D', sessionId));
+
+ serverKey = this.GenerateSessionKey(this.SharedKey, this.ExchangeHash, serverKey, this._serverCipherInfo.KeySize / 8);
+
+ // Create server cipher
+ return this._serverCipherInfo.Cipher(serverKey, serverVector);
+ }
+
+ ///
+ /// Creates the client side cipher to use.
+ ///
+ /// Client cipher.
+ public Cipher CreateClientCipher()
+ {
+ // Resolve Session ID
+ var sessionId = this.Session.SessionId ?? this.ExchangeHash;
+
+ // Calculate client to server initial IV
+ var clientVector = this.Hash(this.GenerateSessionKey(this.SharedKey, this.ExchangeHash, 'A', sessionId));
+
+ // Calculate client to server encryption
+ var clientKey = this.Hash(this.GenerateSessionKey(this.SharedKey, this.ExchangeHash, 'C', sessionId));
+
+ clientKey = this.GenerateSessionKey(this.SharedKey, this.ExchangeHash, clientKey, this._clientCipherInfo.KeySize / 8);
+
+ // Create client cipher
+ return this._clientCipherInfo.Cipher(clientKey, clientVector);
+ }
+
+ ///
+ /// Creates the server side hash algorithm to use.
+ ///
+ /// Hash algorithm
+ public HashAlgorithm CreateServerHash()
+ {
+ // Resolve Session ID
+ var sessionId = this.Session.SessionId ?? this.ExchangeHash;
+
+ var serverKey = this.Hash(this.GenerateSessionKey(this.SharedKey, this.ExchangeHash, 'F', sessionId));
+
+ serverKey = this.GenerateSessionKey(this.SharedKey, this.ExchangeHash, serverKey, this._serverHashInfo.KeySize / 8);
+
+ //return serverHMac;
+ return this._serverHashInfo.HashAlgorithm(serverKey);
+ }
+
+ ///
+ /// Creates the client side hash algorithm to use.
+ ///
+ /// Hash algorithm
+ public HashAlgorithm CreateClientHash()
+ {
+ // Resolve Session ID
+ var sessionId = this.Session.SessionId ?? this.ExchangeHash;
+
+ var clientKey = this.Hash(this.GenerateSessionKey(this.SharedKey, this.ExchangeHash, 'E', sessionId));
+
+ clientKey = this.GenerateSessionKey(this.SharedKey, this.ExchangeHash, clientKey, this._clientHashInfo.KeySize / 8);
+
+ //return clientHMac;
+ return this._clientHashInfo.HashAlgorithm(clientKey);
+ }
+
+ ///
+ /// Creates the compression algorithm to use to deflate data.
+ ///
+ /// Compression method.
+ public Compressor CreateCompressor()
+ {
+ if (this._compressionType == null)
+ return null;
+
+ var compressor = this._compressionType.CreateInstance();
+
+ compressor.Init(this.Session);
+
+ return compressor;
+ }
+
+ ///
+ /// Creates the compression algorithm to use to inflate data.
+ ///
+ /// Compression method.
+ public Compressor CreateDecompressor()
+ {
+ if (this._compressionType == null)
+ return null;
+
+ var decompressor = this._decompressionType.CreateInstance();
+
+ decompressor.Init(this.Session);
+
+ return decompressor;
+ }
+
+ ///
+ /// Determines whether the specified host key can be trusted.
+ ///
+ /// The host algorithm.
+ ///
+ /// true if the specified host can be trusted; otherwise, false.
+ ///
+ protected bool CanTrustHostKey(KeyHostAlgorithm host)
+ {
+ var args = new HostKeyEventArgs(host);
+
+ if (this.HostKeyReceived != null)
+ {
+ this.HostKeyReceived(this, args);
+ }
+
+ return args.CanTrust;
+ }
+
+ ///
+ /// Validates the exchange hash.
+ ///
+ /// true if exchange hash is valid; otherwise false.
+ protected abstract bool ValidateExchangeHash();
+
+ ///
+ /// Calculates key exchange hash value.
+ ///
+ /// Key exchange hash.
+ protected abstract byte[] CalculateHash();
+
+ ///
+ /// Hashes the specified data bytes.
+ ///
+ /// The hash data.
+ ///
+ /// Hashed bytes
+ ///
+ protected virtual byte[] Hash(byte[] hashData)
+ {
+ using (var sha1 = new SHA1Hash())
+ {
+ return sha1.ComputeHash(hashData, 0, hashData.Length);
+ }
+ }
+
+ ///
+ /// Sends SSH message to the server
+ ///
+ /// The message.
+ protected void SendMessage(Message message)
+ {
+ this.Session.SendMessage(message);
+ }
+
+ ///
+ /// Generates the session key.
+ ///
+ /// The shared key.
+ /// The exchange hash.
+ /// The key.
+ /// The size.
+ ///
+ private byte[] GenerateSessionKey(BigInteger sharedKey, byte[] exchangeHash, byte[] key, int size)
+ {
+ var result = new List(key);
+ while (size > result.Count)
+ {
+ result.AddRange(this.Hash(new _SessionKeyAdjustment
+ {
+ SharedKey = sharedKey,
+ ExcahngeHash = exchangeHash,
+ Key = key,
+ }.GetBytes()));
+ }
+
+ return result.ToArray();
+ }
+
+ ///
+ /// Generates the session key.
+ ///
+ /// The shared key.
+ /// The exchange hash.
+ /// The p.
+ /// The session id.
+ ///
+ private byte[] GenerateSessionKey(BigInteger sharedKey, byte[] exchangeHash, char p, byte[] sessionId)
+ {
+ return new _SessionKeyGeneration
+ {
+ SharedKey = sharedKey,
+ ExchangeHash = exchangeHash,
+ Char = p,
+ SessionId = sessionId,
+ }.GetBytes();
+ }
+
+ private class _SessionKeyGeneration : SshData
+ {
+ public BigInteger SharedKey { get; set; }
+ public byte[] ExchangeHash { get; set; }
+ public char Char { get; set; }
+ public byte[] SessionId { get; set; }
+
+ protected override void LoadData()
+ {
+ throw new NotImplementedException();
+ }
+
+ protected override void SaveData()
+ {
+ this.Write(this.SharedKey);
+ this.Write(this.ExchangeHash);
+ this.Write((byte)this.Char);
+ this.Write(this.SessionId);
+ }
+ }
+
+ private class _SessionKeyAdjustment : SshData
+ {
+ public BigInteger SharedKey { get; set; }
+ public byte[] ExcahngeHash { get; set; }
+ public byte[] Key { get; set; }
+
+ protected override void LoadData()
+ {
+ throw new NotImplementedException();
+ }
+
+ protected override void SaveData()
+ {
+ this.Write(this.SharedKey);
+ this.Write(this.ExcahngeHash);
+ this.Write(this.Key);
+ }
+ }
+
+ #region IDisposable Members
+
+ ///
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged ResourceMessages.
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Releases unmanaged and - optionally - managed resources
+ ///
+ /// true to release both managed and unmanaged resources; false to release only unmanaged ResourceMessages.
+ protected virtual void Dispose(bool disposing)
+ {
+ }
+
+ ///
+ /// Releases unmanaged resources and performs other cleanup operations before the
+ /// is reclaimed by garbage collection.
+ ///
+ ~KeyExchange()
+ {
+ // Do not re-create Dispose clean-up code here.
+ // Calling Dispose(false) is optimal in terms of
+ // readability and maintainability.
+ Dispose(false);
+ }
+
+ #endregion
+ }
+}
diff --git a/Renci.SshNet/Security/KeyExchangeDiffieHellman.cs b/Renci.SshNet/Security/KeyExchangeDiffieHellman.cs
index 65db8cc..20b2f1c 100644
--- a/Renci.SshNet/Security/KeyExchangeDiffieHellman.cs
+++ b/Renci.SshNet/Security/KeyExchangeDiffieHellman.cs
@@ -1,142 +1,134 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Security.Cryptography;
-using Renci.SshNet.Messages.Transport;
-using System.Diagnostics;
-using Renci.SshNet.Messages;
-using Renci.SshNet.Common;
-using Renci.SshNet.Security.Cryptography;
-
-namespace Renci.SshNet.Security
-{
- ///
- /// Represents base class for Diffie Hellman key exchange algorithm
- ///
- public abstract class KeyExchangeDiffieHellman : KeyExchange
- {
- ///
- /// Specifies key exchange group number.
- ///
- protected BigInteger _group;
-
- ///
- /// Specifies key exchange prime number.
- ///
- protected BigInteger _prime;
-
- ///
- /// Specifies client payload
- ///
- protected byte[] _clientPayload;
-
- ///
- /// Specifies server payload
- ///
- protected byte[] _serverPayload;
-
- ///
- /// Specifies client exchange number.
- ///
- protected BigInteger _clientExchangeValue;
-
- ///
- /// Specifies server exchange number.
- ///
- protected BigInteger _serverExchangeValue;
-
- ///
- /// Specifies random generated number.
- ///
- protected BigInteger _randomValue;
-
- ///
- /// Specifies host key data.
- ///
- protected byte[] _hostKey;
-
- ///
- /// Specifies signature data.
- ///
- protected byte[] _signature;
-
- ///
- /// Validates the exchange hash.
- ///
- ///
- /// true if exchange hash is valid; otherwise false.
- ///
- protected override bool ValidateExchangeHash()
- {
- var exchangeHash = this.CalculateHash();
-
- var length = (uint)(this._hostKey[0] << 24 | this._hostKey[1] << 16 | this._hostKey[2] << 8 | this._hostKey[3]);
-
- var algorithmName = Encoding.UTF8.GetString(this._hostKey, 4, (int)length);
-
- var key = this.Session.ConnectionInfo.HostKeyAlgorithms[algorithmName](this._hostKey);
-
- this.Session.ConnectionInfo.CurrentHostKeyAlgorithm = algorithmName;
-
- if (this.CanTrustHostKey(key))
- {
-
- return key.VerifySignature(exchangeHash, this._signature);
- }
- else
- {
- return false;
- }
- }
-
- ///
- /// Starts key exchange algorithm
- ///
- /// The session.
- /// Key exchange init message.
- public override void Start(Session session, KeyExchangeInitMessage message)
- {
- base.Start(session, message);
-
- this._serverPayload = message.GetBytes().ToArray();
- this._clientPayload = this.Session.ClientInitMessage.GetBytes().ToArray();
- }
-
- ///
- /// Populates the client exchange value.
- ///
- protected void PopulateClientExchangeValue()
- {
- if (this._group.IsZero)
- throw new ArgumentNullException("_group");
-
- if (this._prime.IsZero)
- throw new ArgumentNullException("_prime");
-
- var bitLength = this._prime.BitLength;
-
- do
- {
- this._randomValue = BigInteger.Random(bitLength);
-
- this._clientExchangeValue = BigInteger.ModPow(this._group, this._randomValue, this._prime);
-
- } while (this._clientExchangeValue < 1 || this._clientExchangeValue > ((this._prime - 1)));
- }
-
- ///
- /// Handles the server DH reply message.
- ///
- /// The host key.
- /// The server exchange value.
- /// The signature.
- protected virtual void HandleServerDhReply(byte[] hostKey, BigInteger serverExchangeValue, byte[] signature)
- {
- this._serverExchangeValue = serverExchangeValue;
- this._hostKey = hostKey;
- this.SharedKey = BigInteger.ModPow(serverExchangeValue, this._randomValue, this._prime);
- this._signature = signature;
- }
- }
-}
+using System;
+using System.Linq;
+using System.Text;
+using Renci.SshNet.Messages.Transport;
+using Renci.SshNet.Common;
+
+namespace Renci.SshNet.Security
+{
+ ///
+ /// Represents base class for Diffie Hellman key exchange algorithm
+ ///
+ public abstract class KeyExchangeDiffieHellman : KeyExchange
+ {
+ ///
+ /// Specifies key exchange group number.
+ ///
+ protected BigInteger _group;
+
+ ///
+ /// Specifies key exchange prime number.
+ ///
+ protected BigInteger _prime;
+
+ ///
+ /// Specifies client payload
+ ///
+ protected byte[] _clientPayload;
+
+ ///
+ /// Specifies server payload
+ ///
+ protected byte[] _serverPayload;
+
+ ///
+ /// Specifies client exchange number.
+ ///
+ protected BigInteger _clientExchangeValue;
+
+ ///
+ /// Specifies server exchange number.
+ ///
+ protected BigInteger _serverExchangeValue;
+
+ ///
+ /// Specifies random generated number.
+ ///
+ protected BigInteger _randomValue;
+
+ ///
+ /// Specifies host key data.
+ ///
+ protected byte[] _hostKey;
+
+ ///
+ /// Specifies signature data.
+ ///
+ protected byte[] _signature;
+
+ ///
+ /// Validates the exchange hash.
+ ///
+ ///
+ /// true if exchange hash is valid; otherwise false.
+ ///
+ protected override bool ValidateExchangeHash()
+ {
+ var exchangeHash = this.CalculateHash();
+
+ var length = (uint)(this._hostKey[0] << 24 | this._hostKey[1] << 16 | this._hostKey[2] << 8 | this._hostKey[3]);
+
+ var algorithmName = Encoding.UTF8.GetString(this._hostKey, 4, (int)length);
+
+ var key = this.Session.ConnectionInfo.HostKeyAlgorithms[algorithmName](this._hostKey);
+
+ this.Session.ConnectionInfo.CurrentHostKeyAlgorithm = algorithmName;
+
+ if (this.CanTrustHostKey(key))
+ {
+
+ return key.VerifySignature(exchangeHash, this._signature);
+ }
+ return false;
+ }
+
+ ///
+ /// Starts key exchange algorithm
+ ///
+ /// The session.
+ /// Key exchange init message.
+ public override void Start(Session session, KeyExchangeInitMessage message)
+ {
+ base.Start(session, message);
+
+ this._serverPayload = message.GetBytes().ToArray();
+ this._clientPayload = this.Session.ClientInitMessage.GetBytes().ToArray();
+ }
+
+ ///
+ /// Populates the client exchange value.
+ ///
+ protected void PopulateClientExchangeValue()
+ {
+ if (this._group.IsZero)
+ throw new ArgumentNullException("_group");
+
+ if (this._prime.IsZero)
+ throw new ArgumentNullException("_prime");
+
+ var bitLength = this._prime.BitLength;
+
+ do
+ {
+ this._randomValue = BigInteger.Random(bitLength);
+
+ this._clientExchangeValue = BigInteger.ModPow(this._group, this._randomValue, this._prime);
+
+ } while (this._clientExchangeValue < 1 || this._clientExchangeValue > ((this._prime - 1)));
+ }
+
+ ///
+ /// Handles the server DH reply message.
+ ///
+ /// The host key.
+ /// The server exchange value.
+ /// The signature.
+ protected virtual void HandleServerDhReply(byte[] hostKey, BigInteger serverExchangeValue, byte[] signature)
+ {
+ this._serverExchangeValue = serverExchangeValue;
+ this._hostKey = hostKey;
+ this.SharedKey = BigInteger.ModPow(serverExchangeValue, this._randomValue, this._prime);
+ this._signature = signature;
+ }
+ }
+}
diff --git a/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroup14Sha1.cs b/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroup14Sha1.cs
index b99671f..a64efbf 100644
--- a/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroup14Sha1.cs
+++ b/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroup14Sha1.cs
@@ -1,42 +1,37 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Security.Cryptography;
-using Renci.SshNet.Common;
-using Renci.SshNet.Messages;
-using Renci.SshNet.Messages.Transport;
-using System.Globalization;
-
-namespace Renci.SshNet.Security
-{
- ///
- /// Represents "diffie-hellman-group14-sha1" algorithm implementation.
- ///
- internal class KeyExchangeDiffieHellmanGroup14Sha1 : KeyExchangeDiffieHellmanGroupSha1
- {
- ///
- /// Gets algorithm name.
- ///
- public override string Name
- {
- get { return "diffie-hellman-group14-sha1"; }
- }
-
- ///
- /// Gets the group prime.
- ///
- ///
- /// The group prime.
- ///
- public override BigInteger GroupPrime
- {
- get
- {
- BigInteger prime;
- var secondOkleyGroup = "00FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF";
- BigInteger.TryParse(secondOkleyGroup, System.Globalization.NumberStyles.AllowHexSpecifier, CultureInfo.CurrentCulture, out prime);
- return prime;
- }
- }
- }
-}
+using Renci.SshNet.Common;
+using System.Globalization;
+
+namespace Renci.SshNet.Security
+{
+ ///
+ /// Represents "diffie-hellman-group14-sha1" algorithm implementation.
+ ///
+ internal class KeyExchangeDiffieHellmanGroup14Sha1 : KeyExchangeDiffieHellmanGroupSha1
+ {
+ private const string SecondOkleyGroup = "00FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF";
+
+ ///
+ /// Gets algorithm name.
+ ///
+ public override string Name
+ {
+ get { return "diffie-hellman-group14-sha1"; }
+ }
+
+ ///
+ /// Gets the group prime.
+ ///
+ ///
+ /// The group prime.
+ ///
+ public override BigInteger GroupPrime
+ {
+ get
+ {
+ BigInteger prime;
+ BigInteger.TryParse(SecondOkleyGroup, NumberStyles.AllowHexSpecifier, CultureInfo.CurrentCulture, out prime);
+ return prime;
+ }
+ }
+ }
+}
diff --git a/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroup1Sha1.cs b/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroup1Sha1.cs
index ae908d6..25613a4 100644
--- a/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroup1Sha1.cs
+++ b/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroup1Sha1.cs
@@ -1,42 +1,37 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Security.Cryptography;
-using Renci.SshNet.Common;
-using Renci.SshNet.Messages;
-using Renci.SshNet.Messages.Transport;
-using System.Globalization;
-
-namespace Renci.SshNet.Security
-{
- ///
- /// Represents "diffie-hellman-group1-sha1" algorithm implementation.
- ///
- public class KeyExchangeDiffieHellmanGroup1Sha1 : KeyExchangeDiffieHellmanGroupSha1
- {
- ///
- /// Gets algorithm name.
- ///
- public override string Name
- {
- get { return "diffie-hellman-group1-sha1"; }
- }
-
- ///
- /// Gets the group prime.
- ///
- ///
- /// The group prime.
- ///
- public override BigInteger GroupPrime
- {
- get
- {
- BigInteger prime;
- var secondOkleyGroup = @"00FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF";
- BigInteger.TryParse(secondOkleyGroup, System.Globalization.NumberStyles.AllowHexSpecifier, CultureInfo.CurrentCulture, out prime);
- return prime;
- }
- }
- }
-}
+using Renci.SshNet.Common;
+using System.Globalization;
+
+namespace Renci.SshNet.Security
+{
+ ///
+ /// Represents "diffie-hellman-group1-sha1" algorithm implementation.
+ ///
+ public class KeyExchangeDiffieHellmanGroup1Sha1 : KeyExchangeDiffieHellmanGroupSha1
+ {
+ private const string SecondOkleyGroup = @"00FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF";
+
+ ///
+ /// Gets algorithm name.
+ ///
+ public override string Name
+ {
+ get { return "diffie-hellman-group1-sha1"; }
+ }
+
+ ///
+ /// Gets the group prime.
+ ///
+ ///
+ /// The group prime.
+ ///
+ public override BigInteger GroupPrime
+ {
+ get
+ {
+ BigInteger prime;
+ BigInteger.TryParse(SecondOkleyGroup, NumberStyles.AllowHexSpecifier, CultureInfo.CurrentCulture, out prime);
+ return prime;
+ }
+ }
+ }
+}
diff --git a/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupExchangeSha1.cs b/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupExchangeSha1.cs
index ddd2a84..2e91396 100644
--- a/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupExchangeSha1.cs
+++ b/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupExchangeSha1.cs
@@ -1,166 +1,161 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Renci.SshNet.Messages.Transport;
-using System.Security.Cryptography;
-using Renci.SshNet.Messages;
-using Renci.SshNet.Common;
-using System.Diagnostics;
-
-namespace Renci.SshNet.Security
-{
- ///
- /// Represents "diffie-hellman-group-exchange-sha1" algorithm implementation.
- ///
- internal class KeyExchangeDiffieHellmanGroupExchangeSha1 : KeyExchangeDiffieHellman
- {
- ///
- /// Gets algorithm name.
- ///
- public override string Name
- {
- get { return "diffie-hellman-group-exchange-sha1"; }
- }
-
- ///
- /// Calculates key exchange hash value.
- ///
- ///
- /// Key exchange hash.
- ///
- protected override byte[] CalculateHash()
- {
- var hashData = new _ExchangeHashData
- {
- ClientVersion = this.Session.ClientVersion,
- ServerVersion = this.Session.ServerVersion,
- ClientPayload = this._clientPayload,
- ServerPayload = this._serverPayload,
- HostKey = this._hostKey,
- MinimumGroupSize = 1024,
- PreferredGroupSize = 1024,
- MaximumGroupSize = 1024,
- Prime = this._prime,
- SubGroup = this._group,
- ClientExchangeValue = this._clientExchangeValue,
- ServerExchangeValue = this._serverExchangeValue,
- SharedKey = this.SharedKey,
- }.GetBytes();
-
- return this.Hash(hashData);
- }
-
- ///
- /// Starts key exchange algorithm
- ///
- /// The session.
- /// Key exchange init message.
- public override void Start(Session session, KeyExchangeInitMessage message)
- {
- base.Start(session, message);
-
- this.Session.RegisterMessage("SSH_MSG_KEX_DH_GEX_GROUP");
- this.Session.RegisterMessage("SSH_MSG_KEX_DH_GEX_REPLY");
-
- this.Session.MessageReceived += Session_MessageReceived;
-
- // 1. send SSH_MSG_KEY_DH_GEX_REQUEST
- this.SendMessage(new KeyExchangeDhGroupExchangeRequest(1024, 1024, 1024));
- }
-
- ///
- /// Finishes key exchange algorithm.
- ///
- public override void Finish()
- {
- base.Finish();
-
- this.Session.MessageReceived -= Session_MessageReceived;
- }
-
- private void Session_MessageReceived(object sender, MessageEventArgs e)
- {
- var groupMessage = e.Message as KeyExchangeDhGroupExchangeGroup;
-
- if (groupMessage != null)
- {
- // Unregister message once received
- this.Session.UnRegisterMessage("SSH_MSG_KEX_DH_GEX_GROUP");
-
- // 2. Receive SSH_MSG_KEX_DH_GEX_GROUP
- this._prime = groupMessage.SafePrime;
- this._group = groupMessage.SubGroup;
-
- this.PopulateClientExchangeValue();
-
- // 3. Send SSH_MSG_KEX_DH_GEX_INIT
- this.SendMessage(new KeyExchangeDhGroupExchangeInit(this._clientExchangeValue));
-
- }
- var replyMessage = e.Message as KeyExchangeDhGroupExchangeReply;
-
- if (replyMessage != null)
- {
- // Unregister message once received
- this.Session.UnRegisterMessage("SSH_MSG_KEX_DH_GEX_REPLY");
-
- this.HandleServerDhReply(replyMessage.HostKey, replyMessage.F, replyMessage.Signature);
-
- // When SSH_MSG_KEX_DH_GEX_REPLY received key exchange is completed
- this.Finish();
- }
- }
-
- private class _ExchangeHashData : SshData
- {
- public string ServerVersion { get; set; }
-
- public string ClientVersion { get; set; }
-
- public byte[] ClientPayload { get; set; }
-
- public byte[] ServerPayload { get; set; }
-
- public byte[] HostKey { get; set; }
-
- public UInt32 MinimumGroupSize { get; set; }
-
- public UInt32 PreferredGroupSize { get; set; }
-
- public UInt32 MaximumGroupSize { get; set; }
-
- public BigInteger Prime { get; set; }
-
- public BigInteger SubGroup { get; set; }
-
- public BigInteger ClientExchangeValue { get; set; }
-
- public BigInteger ServerExchangeValue { get; set; }
-
- public BigInteger SharedKey { get; set; }
-
- protected override void LoadData()
- {
- throw new System.NotImplementedException();
- }
-
- protected override void SaveData()
- {
- this.Write(this.ClientVersion);
- this.Write(this.ServerVersion);
- this.WriteBinaryString(this.ClientPayload);
- this.WriteBinaryString(this.ServerPayload);
- this.WriteBinaryString(this.HostKey);
- this.Write(this.MinimumGroupSize);
- this.Write(this.PreferredGroupSize);
- this.Write(this.MaximumGroupSize);
- this.Write(this.Prime);
- this.Write(this.SubGroup);
- this.Write(this.ClientExchangeValue);
- this.Write(this.ServerExchangeValue);
- this.Write(this.SharedKey);
- }
- }
- }
-}
+using System;
+using Renci.SshNet.Messages.Transport;
+using Renci.SshNet.Messages;
+using Renci.SshNet.Common;
+
+namespace Renci.SshNet.Security
+{
+ ///
+ /// Represents "diffie-hellman-group-exchange-sha1" algorithm implementation.
+ ///
+ internal class KeyExchangeDiffieHellmanGroupExchangeSha1 : KeyExchangeDiffieHellman
+ {
+ ///
+ /// Gets algorithm name.
+ ///
+ public override string Name
+ {
+ get { return "diffie-hellman-group-exchange-sha1"; }
+ }
+
+ ///
+ /// Calculates key exchange hash value.
+ ///
+ ///
+ /// Key exchange hash.
+ ///
+ protected override byte[] CalculateHash()
+ {
+ var hashData = new _ExchangeHashData
+ {
+ ClientVersion = this.Session.ClientVersion,
+ ServerVersion = this.Session.ServerVersion,
+ ClientPayload = this._clientPayload,
+ ServerPayload = this._serverPayload,
+ HostKey = this._hostKey,
+ MinimumGroupSize = 1024,
+ PreferredGroupSize = 1024,
+ MaximumGroupSize = 1024,
+ Prime = this._prime,
+ SubGroup = this._group,
+ ClientExchangeValue = this._clientExchangeValue,
+ ServerExchangeValue = this._serverExchangeValue,
+ SharedKey = this.SharedKey,
+ }.GetBytes();
+
+ return this.Hash(hashData);
+ }
+
+ ///
+ /// Starts key exchange algorithm
+ ///
+ /// The session.
+ /// Key exchange init message.
+ public override void Start(Session session, KeyExchangeInitMessage message)
+ {
+ base.Start(session, message);
+
+ this.Session.RegisterMessage("SSH_MSG_KEX_DH_GEX_GROUP");
+ this.Session.RegisterMessage("SSH_MSG_KEX_DH_GEX_REPLY");
+
+ this.Session.MessageReceived += Session_MessageReceived;
+
+ // 1. send SSH_MSG_KEY_DH_GEX_REQUEST
+ this.SendMessage(new KeyExchangeDhGroupExchangeRequest(1024, 1024, 1024));
+ }
+
+ ///
+ /// Finishes key exchange algorithm.
+ ///
+ public override void Finish()
+ {
+ base.Finish();
+
+ this.Session.MessageReceived -= Session_MessageReceived;
+ }
+
+ private void Session_MessageReceived(object sender, MessageEventArgs e)
+ {
+ var groupMessage = e.Message as KeyExchangeDhGroupExchangeGroup;
+
+ if (groupMessage != null)
+ {
+ // Unregister message once received
+ this.Session.UnRegisterMessage("SSH_MSG_KEX_DH_GEX_GROUP");
+
+ // 2. Receive SSH_MSG_KEX_DH_GEX_GROUP
+ this._prime = groupMessage.SafePrime;
+ this._group = groupMessage.SubGroup;
+
+ this.PopulateClientExchangeValue();
+
+ // 3. Send SSH_MSG_KEX_DH_GEX_INIT
+ this.SendMessage(new KeyExchangeDhGroupExchangeInit(this._clientExchangeValue));
+
+ }
+ var replyMessage = e.Message as KeyExchangeDhGroupExchangeReply;
+
+ if (replyMessage != null)
+ {
+ // Unregister message once received
+ this.Session.UnRegisterMessage("SSH_MSG_KEX_DH_GEX_REPLY");
+
+ this.HandleServerDhReply(replyMessage.HostKey, replyMessage.F, replyMessage.Signature);
+
+ // When SSH_MSG_KEX_DH_GEX_REPLY received key exchange is completed
+ this.Finish();
+ }
+ }
+
+ private class _ExchangeHashData : SshData
+ {
+ public string ServerVersion { get; set; }
+
+ public string ClientVersion { get; set; }
+
+ public byte[] ClientPayload { get; set; }
+
+ public byte[] ServerPayload { get; set; }
+
+ public byte[] HostKey { get; set; }
+
+ public UInt32 MinimumGroupSize { get; set; }
+
+ public UInt32 PreferredGroupSize { get; set; }
+
+ public UInt32 MaximumGroupSize { get; set; }
+
+ public BigInteger Prime { get; set; }
+
+ public BigInteger SubGroup { get; set; }
+
+ public BigInteger ClientExchangeValue { get; set; }
+
+ public BigInteger ServerExchangeValue { get; set; }
+
+ public BigInteger SharedKey { get; set; }
+
+ protected override void LoadData()
+ {
+ throw new NotImplementedException();
+ }
+
+ protected override void SaveData()
+ {
+ this.Write(this.ClientVersion);
+ this.Write(this.ServerVersion);
+ this.WriteBinaryString(this.ClientPayload);
+ this.WriteBinaryString(this.ServerPayload);
+ this.WriteBinaryString(this.HostKey);
+ this.Write(this.MinimumGroupSize);
+ this.Write(this.PreferredGroupSize);
+ this.Write(this.MaximumGroupSize);
+ this.Write(this.Prime);
+ this.Write(this.SubGroup);
+ this.Write(this.ClientExchangeValue);
+ this.Write(this.ServerExchangeValue);
+ this.Write(this.SharedKey);
+ }
+ }
+ }
+}
diff --git a/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupExchangeSha256.cs b/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupExchangeSha256.cs
index b936e5e..5cc9c23 100644
--- a/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupExchangeSha256.cs
+++ b/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupExchangeSha256.cs
@@ -1,182 +1,177 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Renci.SshNet.Messages.Transport;
-using System.Security.Cryptography;
-using Renci.SshNet.Messages;
-using Renci.SshNet.Common;
-using System.Diagnostics;
-using Renci.SshNet.Security.Cryptography;
-
-namespace Renci.SshNet.Security
-{
- ///
- /// Represents "diffie-hellman-group-exchange-sha256" algorithm implementation.
- ///
- public class KeyExchangeDiffieHellmanGroupExchangeSha256 : KeyExchangeDiffieHellman
- {
- ///
- /// Gets algorithm name.
- ///
- public override string Name
- {
- get { return "diffie-hellman-group-exchange-sha256"; }
- }
-
- ///
- /// Starts key exchange algorithm
- ///
- /// The session.
- /// Key exchange init message.
- public override void Start(Session session, KeyExchangeInitMessage message)
- {
- base.Start(session, message);
-
- this.Session.RegisterMessage("SSH_MSG_KEX_DH_GEX_GROUP");
- this.Session.RegisterMessage("SSH_MSG_KEX_DH_GEX_REPLY");
-
- this.Session.MessageReceived += Session_MessageReceived;
-
- // 1. send SSH_MSG_KEY_DH_GEX_REQUEST
- this.SendMessage(new KeyExchangeDhGroupExchangeRequest(1024,1024,1024));
-
- }
-
- ///
- /// Finishes key exchange algorithm.
- ///
- public override void Finish()
- {
- base.Finish();
-
- this.Session.MessageReceived -= Session_MessageReceived;
- }
-
- ///
- /// Calculates key exchange hash value.
- ///
- ///
- /// Key exchange hash.
- ///
- protected override byte[] CalculateHash()
- {
- var hashData = new _ExchangeHashData
- {
- ClientVersion = this.Session.ClientVersion,
- ServerVersion = this.Session.ServerVersion,
- ClientPayload = this._clientPayload,
- ServerPayload = this._serverPayload,
- HostKey = this._hostKey,
- MinimumGroupSize = 1024,
- PreferredGroupSize = 1024,
- MaximumGroupSize = 1024,
- Prime = this._prime,
- SubGroup = this._group,
- ClientExchangeValue = this._clientExchangeValue,
- ServerExchangeValue = this._serverExchangeValue,
- SharedKey = this.SharedKey,
- }.GetBytes();
-
- return this.Hash(hashData);
- }
-
- ///
- /// Hashes the specified data bytes.
- ///
- /// Data to hash.
- ///
- /// Hashed bytes
- ///
- protected override byte[] Hash(byte[] hashBytes)
- {
- using (var md = new SHA256Hash())
- {
- return md.ComputeHash(hashBytes);
- }
- }
-
- private void Session_MessageReceived(object sender, MessageEventArgs e)
- {
- var groupMessage = e.Message as KeyExchangeDhGroupExchangeGroup;
-
- if (groupMessage != null)
- {
- // Unregister message once received
- this.Session.UnRegisterMessage("SSH_MSG_KEX_DH_GEX_GROUP");
-
- // 2. Receive SSH_MSG_KEX_DH_GEX_GROUP
- this._prime = groupMessage.SafePrime;
- this._group = groupMessage.SubGroup;
-
- this.PopulateClientExchangeValue();
-
- // 3. Send SSH_MSG_KEX_DH_GEX_INIT
- this.SendMessage(new KeyExchangeDhGroupExchangeInit(this._clientExchangeValue));
- }
- var replyMessage = e.Message as KeyExchangeDhGroupExchangeReply;
-
- if (replyMessage != null)
- {
- // Unregister message once received
- this.Session.UnRegisterMessage("SSH_MSG_KEX_DH_GEX_REPLY");
-
- this.HandleServerDhReply(replyMessage.HostKey, replyMessage.F, replyMessage.Signature);
-
- // When SSH_MSG_KEX_DH_GEX_REPLY received key exchange is completed
- this.Finish();
- }
- }
-
- private class _ExchangeHashData : SshData
- {
- public string ServerVersion { get; set; }
-
- public string ClientVersion { get; set; }
-
- public byte[] ClientPayload { get; set; }
-
- public byte[] ServerPayload { get; set; }
-
- public byte[] HostKey { get; set; }
-
- public UInt32 MinimumGroupSize { get; set; }
-
- public UInt32 PreferredGroupSize { get; set; }
-
- public UInt32 MaximumGroupSize { get; set; }
-
- public BigInteger Prime { get; set; }
-
- public BigInteger SubGroup { get; set; }
-
- public BigInteger ClientExchangeValue { get; set; }
-
- public BigInteger ServerExchangeValue { get; set; }
-
- public BigInteger SharedKey { get; set; }
-
- protected override void LoadData()
- {
- throw new System.NotImplementedException();
- }
-
- protected override void SaveData()
- {
- this.Write(this.ClientVersion);
- this.Write(this.ServerVersion);
- this.WriteBinaryString(this.ClientPayload);
- this.WriteBinaryString(this.ServerPayload);
- this.WriteBinaryString(this.HostKey);
- this.Write(this.MinimumGroupSize);
- this.Write(this.PreferredGroupSize);
- this.Write(this.MaximumGroupSize);
- this.Write(this.Prime);
- this.Write(this.SubGroup);
- this.Write(this.ClientExchangeValue);
- this.Write(this.ServerExchangeValue);
- this.Write(this.SharedKey);
- }
- }
- }
-}
+using System;
+using Renci.SshNet.Messages.Transport;
+using Renci.SshNet.Messages;
+using Renci.SshNet.Common;
+using Renci.SshNet.Security.Cryptography;
+
+namespace Renci.SshNet.Security
+{
+ ///
+ /// Represents "diffie-hellman-group-exchange-sha256" algorithm implementation.
+ ///
+ public class KeyExchangeDiffieHellmanGroupExchangeSha256 : KeyExchangeDiffieHellman
+ {
+ ///
+ /// Gets algorithm name.
+ ///
+ public override string Name
+ {
+ get { return "diffie-hellman-group-exchange-sha256"; }
+ }
+
+ ///
+ /// Starts key exchange algorithm
+ ///
+ /// The session.
+ /// Key exchange init message.
+ public override void Start(Session session, KeyExchangeInitMessage message)
+ {
+ base.Start(session, message);
+
+ this.Session.RegisterMessage("SSH_MSG_KEX_DH_GEX_GROUP");
+ this.Session.RegisterMessage("SSH_MSG_KEX_DH_GEX_REPLY");
+
+ this.Session.MessageReceived += Session_MessageReceived;
+
+ // 1. send SSH_MSG_KEY_DH_GEX_REQUEST
+ this.SendMessage(new KeyExchangeDhGroupExchangeRequest(1024,1024,1024));
+
+ }
+
+ ///
+ /// Finishes key exchange algorithm.
+ ///
+ public override void Finish()
+ {
+ base.Finish();
+
+ this.Session.MessageReceived -= Session_MessageReceived;
+ }
+
+ ///
+ /// Calculates key exchange hash value.
+ ///
+ ///
+ /// Key exchange hash.
+ ///
+ protected override byte[] CalculateHash()
+ {
+ var hashData = new _ExchangeHashData
+ {
+ ClientVersion = this.Session.ClientVersion,
+ ServerVersion = this.Session.ServerVersion,
+ ClientPayload = this._clientPayload,
+ ServerPayload = this._serverPayload,
+ HostKey = this._hostKey,
+ MinimumGroupSize = 1024,
+ PreferredGroupSize = 1024,
+ MaximumGroupSize = 1024,
+ Prime = this._prime,
+ SubGroup = this._group,
+ ClientExchangeValue = this._clientExchangeValue,
+ ServerExchangeValue = this._serverExchangeValue,
+ SharedKey = this.SharedKey,
+ }.GetBytes();
+
+ return this.Hash(hashData);
+ }
+
+ ///
+ /// Hashes the specified data bytes.
+ ///
+ /// Data to hash.
+ ///
+ /// Hashed bytes
+ ///
+ protected override byte[] Hash(byte[] hashBytes)
+ {
+ using (var md = new SHA256Hash())
+ {
+ return md.ComputeHash(hashBytes);
+ }
+ }
+
+ private void Session_MessageReceived(object sender, MessageEventArgs e)
+ {
+ var groupMessage = e.Message as KeyExchangeDhGroupExchangeGroup;
+
+ if (groupMessage != null)
+ {
+ // Unregister message once received
+ this.Session.UnRegisterMessage("SSH_MSG_KEX_DH_GEX_GROUP");
+
+ // 2. Receive SSH_MSG_KEX_DH_GEX_GROUP
+ this._prime = groupMessage.SafePrime;
+ this._group = groupMessage.SubGroup;
+
+ this.PopulateClientExchangeValue();
+
+ // 3. Send SSH_MSG_KEX_DH_GEX_INIT
+ this.SendMessage(new KeyExchangeDhGroupExchangeInit(this._clientExchangeValue));
+ }
+ var replyMessage = e.Message as KeyExchangeDhGroupExchangeReply;
+
+ if (replyMessage != null)
+ {
+ // Unregister message once received
+ this.Session.UnRegisterMessage("SSH_MSG_KEX_DH_GEX_REPLY");
+
+ this.HandleServerDhReply(replyMessage.HostKey, replyMessage.F, replyMessage.Signature);
+
+ // When SSH_MSG_KEX_DH_GEX_REPLY received key exchange is completed
+ this.Finish();
+ }
+ }
+
+ private class _ExchangeHashData : SshData
+ {
+ public string ServerVersion { get; set; }
+
+ public string ClientVersion { get; set; }
+
+ public byte[] ClientPayload { get; set; }
+
+ public byte[] ServerPayload { get; set; }
+
+ public byte[] HostKey { get; set; }
+
+ public UInt32 MinimumGroupSize { get; set; }
+
+ public UInt32 PreferredGroupSize { get; set; }
+
+ public UInt32 MaximumGroupSize { get; set; }
+
+ public BigInteger Prime { get; set; }
+
+ public BigInteger SubGroup { get; set; }
+
+ public BigInteger ClientExchangeValue { get; set; }
+
+ public BigInteger ServerExchangeValue { get; set; }
+
+ public BigInteger SharedKey { get; set; }
+
+ protected override void LoadData()
+ {
+ throw new NotImplementedException();
+ }
+
+ protected override void SaveData()
+ {
+ this.Write(this.ClientVersion);
+ this.Write(this.ServerVersion);
+ this.WriteBinaryString(this.ClientPayload);
+ this.WriteBinaryString(this.ServerPayload);
+ this.WriteBinaryString(this.HostKey);
+ this.Write(this.MinimumGroupSize);
+ this.Write(this.PreferredGroupSize);
+ this.Write(this.MaximumGroupSize);
+ this.Write(this.Prime);
+ this.Write(this.SubGroup);
+ this.Write(this.ClientExchangeValue);
+ this.Write(this.ServerExchangeValue);
+ this.Write(this.SharedKey);
+ }
+ }
+ }
+}
diff --git a/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupSha1.cs b/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupSha1.cs
index e72fab1..d66bff5 100644
--- a/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupSha1.cs
+++ b/Renci.SshNet/Security/KeyExchangeDiffieHellmanGroupSha1.cs
@@ -1,132 +1,127 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Security.Cryptography;
-using Renci.SshNet.Common;
-using Renci.SshNet.Messages;
-using Renci.SshNet.Messages.Transport;
-using System.Globalization;
-
-namespace Renci.SshNet.Security
-{
- ///
- /// Represents "diffie-hellman-group1-sha1" algorithm implementation.
- ///
- public abstract class KeyExchangeDiffieHellmanGroupSha1 : KeyExchangeDiffieHellman
- {
- ///
- /// Gets the group prime.
- ///
- ///
- /// The group prime.
- ///
- public abstract BigInteger GroupPrime { get; }
-
- ///
- /// Calculates key exchange hash value.
- ///
- ///
- /// Key exchange hash.
- ///
- protected override byte[] CalculateHash()
- {
- var hashData = new _ExchangeHashData
- {
- ClientVersion = this.Session.ClientVersion,
- ServerVersion = this.Session.ServerVersion,
- ClientPayload = this._clientPayload,
- ServerPayload = this._serverPayload,
- HostKey = this._hostKey,
- ClientExchangeValue = this._clientExchangeValue,
- ServerExchangeValue = this._serverExchangeValue,
- SharedKey = this.SharedKey,
- }.GetBytes();
-
- return this.Hash(hashData);
- }
-
- ///
- /// Starts key exchange algorithm
- ///
- /// The session.
- /// Key exchange init message.
- public override void Start(Session session, KeyExchangeInitMessage message)
- {
- base.Start(session, message);
-
- this.Session.RegisterMessage("SSH_MSG_KEXDH_REPLY");
-
- this.Session.MessageReceived += Session_MessageReceived;
-
- this._prime = this.GroupPrime;
-
- this._group = new BigInteger(new byte[] { 2 });
-
- this.PopulateClientExchangeValue();
-
- this.SendMessage(new KeyExchangeDhInitMessage(this._clientExchangeValue));
-
- }
-
- ///
- /// Finishes key exchange algorithm.
- ///
- public override void Finish()
- {
- base.Finish();
-
- this.Session.MessageReceived -= Session_MessageReceived;
- }
-
- private void Session_MessageReceived(object sender, MessageEventArgs e)
- {
- var message = e.Message as KeyExchangeDhReplyMessage;
- if (message != null)
- {
- // Unregister message once received
- this.Session.UnRegisterMessage("SSH_MSG_KEXDH_REPLY");
-
- this.HandleServerDhReply(message.HostKey, message.F, message.Signature);
-
- // When SSH_MSG_KEXDH_REPLY received key exchange is completed
- this.Finish();
- }
- }
-
- private class _ExchangeHashData : SshData
- {
- public string ServerVersion { get; set; }
-
- public string ClientVersion { get; set; }
-
- public byte[] ClientPayload { get; set; }
-
- public byte[] ServerPayload { get; set; }
-
- public byte[] HostKey { get; set; }
-
- public BigInteger ClientExchangeValue { get; set; }
-
- public BigInteger ServerExchangeValue { get; set; }
-
- public BigInteger SharedKey { get; set; }
-
- protected override void LoadData()
- {
- throw new System.NotImplementedException();
- }
-
- protected override void SaveData()
- {
- this.Write(this.ClientVersion);
- this.Write(this.ServerVersion);
- this.WriteBinaryString(this.ClientPayload);
- this.WriteBinaryString(this.ServerPayload);
- this.WriteBinaryString(this.HostKey);
- this.Write(this.ClientExchangeValue);
- this.Write(this.ServerExchangeValue);
- this.Write(this.SharedKey);
- }
- }
- }
-}
+using Renci.SshNet.Common;
+using Renci.SshNet.Messages;
+using Renci.SshNet.Messages.Transport;
+
+namespace Renci.SshNet.Security
+{
+ ///
+ /// Represents "diffie-hellman-group1-sha1" algorithm implementation.
+ ///
+ public abstract class KeyExchangeDiffieHellmanGroupSha1 : KeyExchangeDiffieHellman
+ {
+ ///
+ /// Gets the group prime.
+ ///
+ ///
+ /// The group prime.
+ ///
+ public abstract BigInteger GroupPrime { get; }
+
+ ///
+ /// Calculates key exchange hash value.
+ ///
+ ///
+ /// Key exchange hash.
+ ///
+ protected override byte[] CalculateHash()
+ {
+ var hashData = new _ExchangeHashData
+ {
+ ClientVersion = this.Session.ClientVersion,
+ ServerVersion = this.Session.ServerVersion,
+ ClientPayload = this._clientPayload,
+ ServerPayload = this._serverPayload,
+ HostKey = this._hostKey,
+ ClientExchangeValue = this._clientExchangeValue,
+ ServerExchangeValue = this._serverExchangeValue,
+ SharedKey = this.SharedKey,
+ }.GetBytes();
+
+ return this.Hash(hashData);
+ }
+
+ ///
+ /// Starts key exchange algorithm
+ ///
+ /// The session.
+ /// Key exchange init message.
+ public override void Start(Session session, KeyExchangeInitMessage message)
+ {
+ base.Start(session, message);
+
+ this.Session.RegisterMessage("SSH_MSG_KEXDH_REPLY");
+
+ this.Session.MessageReceived += Session_MessageReceived;
+
+ this._prime = this.GroupPrime;
+
+ this._group = new BigInteger(new byte[] { 2 });
+
+ this.PopulateClientExchangeValue();
+
+ this.SendMessage(new KeyExchangeDhInitMessage(this._clientExchangeValue));
+
+ }
+
+ ///
+ /// Finishes key exchange algorithm.
+ ///
+ public override void Finish()
+ {
+ base.Finish();
+
+ this.Session.MessageReceived -= Session_MessageReceived;
+ }
+
+ private void Session_MessageReceived(object sender, MessageEventArgs e)
+ {
+ var message = e.Message as KeyExchangeDhReplyMessage;
+ if (message != null)
+ {
+ // Unregister message once received
+ this.Session.UnRegisterMessage("SSH_MSG_KEXDH_REPLY");
+
+ this.HandleServerDhReply(message.HostKey, message.F, message.Signature);
+
+ // When SSH_MSG_KEXDH_REPLY received key exchange is completed
+ this.Finish();
+ }
+ }
+
+ private class _ExchangeHashData : SshData
+ {
+ public string ServerVersion { get; set; }
+
+ public string ClientVersion { get; set; }
+
+ public byte[] ClientPayload { get; set; }
+
+ public byte[] ServerPayload { get; set; }
+
+ public byte[] HostKey { get; set; }
+
+ public BigInteger ClientExchangeValue { get; set; }
+
+ public BigInteger ServerExchangeValue { get; set; }
+
+ public BigInteger SharedKey { get; set; }
+
+ protected override void LoadData()
+ {
+ throw new System.NotImplementedException();
+ }
+
+ protected override void SaveData()
+ {
+ this.Write(this.ClientVersion);
+ this.Write(this.ServerVersion);
+ this.WriteBinaryString(this.ClientPayload);
+ this.WriteBinaryString(this.ServerPayload);
+ this.WriteBinaryString(this.HostKey);
+ this.Write(this.ClientExchangeValue);
+ this.Write(this.ServerExchangeValue);
+ this.Write(this.SharedKey);
+ }
+ }
+ }
+}
diff --git a/Renci.SshNet/Security/KeyExchangeEllipticCurveDiffieHellman.cs b/Renci.SshNet/Security/KeyExchangeEllipticCurveDiffieHellman.cs
index 1f6d85c..50a2cb5 100644
--- a/Renci.SshNet/Security/KeyExchangeEllipticCurveDiffieHellman.cs
+++ b/Renci.SshNet/Security/KeyExchangeEllipticCurveDiffieHellman.cs
@@ -1,284 +1,279 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Security.Cryptography;
-using Renci.SshNet.Messages.Transport;
-using System.Diagnostics;
-using Renci.SshNet.Messages;
-using Renci.SshNet.Common;
-using Renci.SshNet.Security.Cryptography;
-using System.Globalization;
-
-namespace Renci.SshNet.Security
-{
- ///
- /// Represents base class for Diffie Hellman key exchange algorithm
- ///
- public class KeyExchangeEllipticCurveDiffieHellman : KeyExchange
- {
- ///
- /// Specifies client payload
- ///
- protected byte[] _clientPayload;
-
- ///
- /// Specifies server payload
- ///
- protected byte[] _serverPayload;
-
- ///
- /// Specifies client exchange number.
- ///
- protected BigInteger _clientExchangeValue;
-
- ///
- /// Specifies server exchange number.
- ///
- protected BigInteger _serverExchangeValue;
-
- ///
- /// Specifies random generated number.
- ///
- protected BigInteger _randomValue;
-
- ///
- /// Specifies host key data.
- ///
- protected byte[] _hostKey;
-
- ///
- /// Specifies signature data.
- ///
- protected byte[] _signature;
-
- //// 256
- //p = FFFFFFFF 00000001 00000000 00000000 00000000 FFFFFFFF FFFFFFFF FFFFFFFF
- //a = FFFFFFFF 00000001 00000000 00000000 00000000 FFFFFFFF FFFFFFFF FFFFFFFC
- //b = 5AC635D8 AA3A93E7 B3EBBD55 769886BC 651D06B0 CC53B0F6 3BCE3C3E 27D2604B
- //S = C49D3608 86E70493 6A6678E1 139D26B7 819F7E90
- //The base point G in compressed form is:
- //G = 03 6B17D1F2 E12C4247 F8BCE6E5 63A440F2 77037D81 2DEB33A0 F4A13945 D898C296
- //and in uncompressed form is:
- //G = 04 6B17D1F2 E12C4247 F8BCE6E5 63A440F2 77037D81 2DEB33A0 F4A13945 D898C296 4FE342E2 FE1A7F9B 8EE7EB4A 7C0F9E16 2BCE3357 6B315ECE CBB64068 37BF51F5
- //n = FFFFFFFF 00000000 FFFFFFFF FFFFFFFF BCE6FAAD A7179E84 F3B9CAC2 FC632551
- //h = 01
-
- //// 384
- //p = FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFFFF 00000000 00000000 FFFFFFFF
- //a = FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFFFF 00000000 00000000 FFFFFFFC
- //b = B3312FA7 E23EE7E4 988E056B E3F82D19 181D9C6E FE814112 0314088F 5013875A C656398D 8A2ED19D 2A85C8ED D3EC2AEF
- //S = A335926A A319A27A 1D00896A 6773A482 7ACDAC73
- //The base point G in compressed form is:
- //G = 03 AA87CA22 BE8B0537 8EB1C71E F320AD74 6E1D3B62 8BA79B98 59F741E0 82542A38 5502F25D BF55296C 3A545E38 72760AB7
- //and in uncompressed form is:
- //G = 04 AA87CA22 BE8B0537 8EB1C71E F320AD74 6E1D3B62 8BA79B98 59F741E0 82542A38 5502F25D BF55296C 3A545E38 72760AB7 3617DE4A 96262C6F 5D9E98BF 9292DC29 F8F41DBD 289A147C E9DA3113 B5F0B8C0 0A60B1CE 1D7E819D 7A431D7C 90EA0E5F
- //n = FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF C7634D81 F4372DDF 581A0DB2 48B0A77A ECEC196A CCC52973
- //h = 01
-
- public override string Name
- {
- get { return "ecdh-sha2-nistp256"; }
- }
-
- ///
- /// Starts key exchange algorithm
- ///
- /// The session.
- /// Key exchange init message.
- public override void Start(Session session, KeyExchangeInitMessage message)
- {
- base.Start(session, message);
-
- this._serverPayload = message.GetBytes().ToArray();
- this._clientPayload = this.Session.ClientInitMessage.GetBytes().ToArray();
-
- this.Session.RegisterMessage("SSH_MSG_KEXECDH_REPLY");
-
- this.Session.MessageReceived += Session_MessageReceived;
-
- //3.2.1 Elliptic Curve Key Pair Generation Primitive
- //Elliptic curve key pairs should be generated as follows:
- //Input: Valid elliptic curve domain parameters T = (p, a, b, G, n, h) or (m, f(x), a, b,G, n, h).
- //Output: An elliptic curve key pair (d,Q) associated with T.
- //Actions: Generate an elliptic curve key pair as follows:
- //1. Randomly or pseudorandomly select an integer d in the interval [1, n − 1].
- //2. Compute Q = dG.
- //3. Output (d,Q).
-
- BigInteger p;
- BigInteger.TryParse("00FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", System.Globalization.NumberStyles.AllowHexSpecifier, CultureInfo.CurrentCulture, out p);
-
-
-
- BigInteger n;
- BigInteger.TryParse("00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", System.Globalization.NumberStyles.AllowHexSpecifier, CultureInfo.CurrentCulture, out n);
- BigInteger G;
- BigInteger.TryParse("00036B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", System.Globalization.NumberStyles.AllowHexSpecifier, CultureInfo.CurrentCulture, out G);
-
- BigInteger d;
-
- do
- {
- d = BigInteger.Random(n.BitLength);
- } while (d < 1 || d > n);
-
- var Q = d * G;
-
-
- this.SendMessage(new KeyExchangeEcdhInitMessage(d, Q));
-
- }
-
- private void Session_MessageReceived(object sender, MessageEventArgs e)
- {
- var message = e.Message as KeyExchangeEcdhReplyMessage;
- if (message != null)
- {
- // Unregister message once received
- this.Session.UnRegisterMessage("SSH_MSG_KEXECDH_REPLY");
-
- this.HandleServerEcdhReply();
-
- // When SSH_MSG_KEXDH_REPLY received key exchange is completed
- this.Finish();
- }
- }
-
- ///
- /// Validates the exchange hash.
- ///
- ///
- /// true if exchange hash is valid; otherwise false.
- ///
- protected override bool ValidateExchangeHash()
- {
- //var exchangeHash = this.CalculateHash();
-
- //var length = (uint)(this._hostKey[0] << 24 | this._hostKey[1] << 16 | this._hostKey[2] << 8 | this._hostKey[3]);
-
- //var algorithmName = Encoding.UTF8.GetString(this._hostKey, 4, (int)length);
-
- //var key = this.Session.ConnectionInfo.HostKeyAlgorithms[algorithmName](this._hostKey);
-
- //this.Session.ConnectionInfo.CurrentHostKeyAlgorithm = algorithmName;
-
- //if (this.CanTrustHostKey(key))
- //{
-
- // return key.VerifySignature(exchangeHash, this._signature);
- //}
- //else
- //{
- // return false;
- //}
-
- return false;
- }
-
- ///
- /// Populates the client exchange value.
- ///
- //protected void PopulateClientExchangeValue()
- //{
- // if (this._group.IsZero)
- // throw new ArgumentNullException("_group");
-
- // if (this._prime.IsZero)
- // throw new ArgumentNullException("_prime");
-
- // var bitLength = this._prime.BitLength;
-
- // do
- // {
- // this._randomValue = BigInteger.Random(bitLength);
-
- // this._clientExchangeValue = BigInteger.ModPow(this._group, this._randomValue, this._prime);
-
- // } while (this._clientExchangeValue < 1 || this._clientExchangeValue > ((this._prime - 1)));
- //}
-
- protected virtual void HandleServerEcdhReply()
- {
- //this._serverExchangeValue = serverExchangeValue;
- //this._hostKey = hostKey;
- //this.SharedKey = BigInteger.ModPow(serverExchangeValue, this._randomValue, this._prime);
- //this._signature = signature;
- }
-
- protected override byte[] CalculateHash()
- {
- var hashData = new _ExchangeHashData
- {
- ClientVersion = this.Session.ClientVersion,
- ServerVersion = this.Session.ServerVersion,
- ClientPayload = this._clientPayload,
- ServerPayload = this._serverPayload,
- HostKey = this._hostKey,
- SharedKey = this.SharedKey,
- }.GetBytes();
-
- //string V_C, client's identification string (CR and LF excluded)
- //string V_S, server's identification string (CR and LF excluded)
- //string I_C, payload of the client's SSH_MSG_KEXINIT
- //string I_S, payload of the server's SSH_MSG_KEXINIT
- //string K_S, server's public host key
- //string Q_C, client's ephemeral public key octet string
- //string Q_S, server's ephemeral public key octet string
- //mpint K, shared secret
- return this.Hash(hashData);
- }
-
- private class _ExchangeHashData : SshData
- {
- public string ServerVersion { get; set; }
-
- public string ClientVersion { get; set; }
-
- public byte[] ClientPayload { get; set; }
-
- public byte[] ServerPayload { get; set; }
-
- public byte[] HostKey { get; set; }
-
- public UInt32 MinimumGroupSize { get; set; }
-
- public UInt32 PreferredGroupSize { get; set; }
-
- public UInt32 MaximumGroupSize { get; set; }
-
- public BigInteger Prime { get; set; }
-
- public BigInteger SubGroup { get; set; }
-
- public BigInteger ClientExchangeValue { get; set; }
-
- public BigInteger ServerExchangeValue { get; set; }
-
- public BigInteger SharedKey { get; set; }
-
- protected override void LoadData()
- {
- throw new System.NotImplementedException();
- }
-
- protected override void SaveData()
- {
- this.Write(this.ClientVersion);
- this.Write(this.ServerVersion);
- this.WriteBinaryString(this.ClientPayload);
- this.WriteBinaryString(this.ServerPayload);
- this.WriteBinaryString(this.HostKey);
- this.Write(this.MinimumGroupSize);
- this.Write(this.PreferredGroupSize);
- this.Write(this.MaximumGroupSize);
- this.Write(this.Prime);
- this.Write(this.SubGroup);
- this.Write(this.ClientExchangeValue);
- this.Write(this.ServerExchangeValue);
- this.Write(this.SharedKey);
- }
- }
-
- }
-}
+using System;
+using System.Linq;
+using Renci.SshNet.Messages.Transport;
+using Renci.SshNet.Messages;
+using Renci.SshNet.Common;
+using System.Globalization;
+
+namespace Renci.SshNet.Security
+{
+ ///
+ /// Represents base class for Diffie Hellman key exchange algorithm
+ ///
+ public class KeyExchangeEllipticCurveDiffieHellman : KeyExchange
+ {
+ ///
+ /// Specifies client payload
+ ///
+ protected byte[] _clientPayload;
+
+ ///
+ /// Specifies server payload
+ ///
+ protected byte[] _serverPayload;
+
+ ///
+ /// Specifies client exchange number.
+ ///
+ protected BigInteger _clientExchangeValue;
+
+ ///
+ /// Specifies server exchange number.
+ ///
+ protected BigInteger _serverExchangeValue;
+
+ ///
+ /// Specifies random generated number.
+ ///
+ protected BigInteger _randomValue;
+
+ ///
+ /// Specifies host key data.
+ ///
+ protected byte[] _hostKey;
+
+ ///
+ /// Specifies signature data.
+ ///
+ protected byte[] _signature;
+
+ //// 256
+ //p = FFFFFFFF 00000001 00000000 00000000 00000000 FFFFFFFF FFFFFFFF FFFFFFFF
+ //a = FFFFFFFF 00000001 00000000 00000000 00000000 FFFFFFFF FFFFFFFF FFFFFFFC
+ //b = 5AC635D8 AA3A93E7 B3EBBD55 769886BC 651D06B0 CC53B0F6 3BCE3C3E 27D2604B
+ //S = C49D3608 86E70493 6A6678E1 139D26B7 819F7E90
+ //The base point G in compressed form is:
+ //G = 03 6B17D1F2 E12C4247 F8BCE6E5 63A440F2 77037D81 2DEB33A0 F4A13945 D898C296
+ //and in uncompressed form is:
+ //G = 04 6B17D1F2 E12C4247 F8BCE6E5 63A440F2 77037D81 2DEB33A0 F4A13945 D898C296 4FE342E2 FE1A7F9B 8EE7EB4A 7C0F9E16 2BCE3357 6B315ECE CBB64068 37BF51F5
+ //n = FFFFFFFF 00000000 FFFFFFFF FFFFFFFF BCE6FAAD A7179E84 F3B9CAC2 FC632551
+ //h = 01
+
+ //// 384
+ //p = FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFFFF 00000000 00000000 FFFFFFFF
+ //a = FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFFFF 00000000 00000000 FFFFFFFC
+ //b = B3312FA7 E23EE7E4 988E056B E3F82D19 181D9C6E FE814112 0314088F 5013875A C656398D 8A2ED19D 2A85C8ED D3EC2AEF
+ //S = A335926A A319A27A 1D00896A 6773A482 7ACDAC73
+ //The base point G in compressed form is:
+ //G = 03 AA87CA22 BE8B0537 8EB1C71E F320AD74 6E1D3B62 8BA79B98 59F741E0 82542A38 5502F25D BF55296C 3A545E38 72760AB7
+ //and in uncompressed form is:
+ //G = 04 AA87CA22 BE8B0537 8EB1C71E F320AD74 6E1D3B62 8BA79B98 59F741E0 82542A38 5502F25D BF55296C 3A545E38 72760AB7 3617DE4A 96262C6F 5D9E98BF 9292DC29 F8F41DBD 289A147C E9DA3113 B5F0B8C0 0A60B1CE 1D7E819D 7A431D7C 90EA0E5F
+ //n = FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF C7634D81 F4372DDF 581A0DB2 48B0A77A ECEC196A CCC52973
+ //h = 01
+
+ public override string Name
+ {
+ get { return "ecdh-sha2-nistp256"; }
+ }
+
+ ///
+ /// Starts key exchange algorithm
+ ///
+ /// The session.
+ /// Key exchange init message.
+ public override void Start(Session session, KeyExchangeInitMessage message)
+ {
+ base.Start(session, message);
+
+ this._serverPayload = message.GetBytes().ToArray();
+ this._clientPayload = this.Session.ClientInitMessage.GetBytes().ToArray();
+
+ this.Session.RegisterMessage("SSH_MSG_KEXECDH_REPLY");
+
+ this.Session.MessageReceived += Session_MessageReceived;
+
+ //3.2.1 Elliptic Curve Key Pair Generation Primitive
+ //Elliptic curve key pairs should be generated as follows:
+ //Input: Valid elliptic curve domain parameters T = (p, a, b, G, n, h) or (m, f(x), a, b,G, n, h).
+ //Output: An elliptic curve key pair (d,Q) associated with T.
+ //Actions: Generate an elliptic curve key pair as follows:
+ //1. Randomly or pseudorandomly select an integer d in the interval [1, n − 1].
+ //2. Compute Q = dG.
+ //3. Output (d,Q).
+
+ BigInteger p;
+ BigInteger.TryParse("00FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", NumberStyles.AllowHexSpecifier, CultureInfo.CurrentCulture, out p);
+
+
+
+ BigInteger n;
+ BigInteger.TryParse("00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", NumberStyles.AllowHexSpecifier, CultureInfo.CurrentCulture, out n);
+ BigInteger G;
+ BigInteger.TryParse("00036B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", NumberStyles.AllowHexSpecifier, CultureInfo.CurrentCulture, out G);
+
+ BigInteger d;
+
+ do
+ {
+ d = BigInteger.Random(n.BitLength);
+ } while (d < 1 || d > n);
+
+ var Q = d * G;
+
+
+ this.SendMessage(new KeyExchangeEcdhInitMessage(d, Q));
+
+ }
+
+ private void Session_MessageReceived(object sender, MessageEventArgs e)
+ {
+ var message = e.Message as KeyExchangeEcdhReplyMessage;
+ if (message != null)
+ {
+ // Unregister message once received
+ this.Session.UnRegisterMessage("SSH_MSG_KEXECDH_REPLY");
+
+ this.HandleServerEcdhReply();
+
+ // When SSH_MSG_KEXDH_REPLY received key exchange is completed
+ this.Finish();
+ }
+ }
+
+ ///
+ /// Validates the exchange hash.
+ ///
+ ///
+ /// true if exchange hash is valid; otherwise false.
+ ///
+ protected override bool ValidateExchangeHash()
+ {
+ //var exchangeHash = this.CalculateHash();
+
+ //var length = (uint)(this._hostKey[0] << 24 | this._hostKey[1] << 16 | this._hostKey[2] << 8 | this._hostKey[3]);
+
+ //var algorithmName = Encoding.UTF8.GetString(this._hostKey, 4, (int)length);
+
+ //var key = this.Session.ConnectionInfo.HostKeyAlgorithms[algorithmName](this._hostKey);
+
+ //this.Session.ConnectionInfo.CurrentHostKeyAlgorithm = algorithmName;
+
+ //if (this.CanTrustHostKey(key))
+ //{
+
+ // return key.VerifySignature(exchangeHash, this._signature);
+ //}
+ //else
+ //{
+ // return false;
+ //}
+
+ return false;
+ }
+
+ ///
+ /// Populates the client exchange value.
+ ///
+ //protected void PopulateClientExchangeValue()
+ //{
+ // if (this._group.IsZero)
+ // throw new ArgumentNullException("_group");
+
+ // if (this._prime.IsZero)
+ // throw new ArgumentNullException("_prime");
+
+ // var bitLength = this._prime.BitLength;
+
+ // do
+ // {
+ // this._randomValue = BigInteger.Random(bitLength);
+
+ // this._clientExchangeValue = BigInteger.ModPow(this._group, this._randomValue, this._prime);
+
+ // } while (this._clientExchangeValue < 1 || this._clientExchangeValue > ((this._prime - 1)));
+ //}
+
+ protected virtual void HandleServerEcdhReply()
+ {
+ //this._serverExchangeValue = serverExchangeValue;
+ //this._hostKey = hostKey;
+ //this.SharedKey = BigInteger.ModPow(serverExchangeValue, this._randomValue, this._prime);
+ //this._signature = signature;
+ }
+
+ protected override byte[] CalculateHash()
+ {
+ var hashData = new _ExchangeHashData
+ {
+ ClientVersion = this.Session.ClientVersion,
+ ServerVersion = this.Session.ServerVersion,
+ ClientPayload = this._clientPayload,
+ ServerPayload = this._serverPayload,
+ HostKey = this._hostKey,
+ SharedKey = this.SharedKey,
+ }.GetBytes();
+
+ //string V_C, client's identification string (CR and LF excluded)
+ //string V_S, server's identification string (CR and LF excluded)
+ //string I_C, payload of the client's SSH_MSG_KEXINIT
+ //string I_S, payload of the server's SSH_MSG_KEXINIT
+ //string K_S, server's public host key
+ //string Q_C, client's ephemeral public key octet string
+ //string Q_S, server's ephemeral public key octet string
+ //mpint K, shared secret
+ return this.Hash(hashData);
+ }
+
+ private class _ExchangeHashData : SshData
+ {
+ public string ServerVersion { get; set; }
+
+ public string ClientVersion { get; set; }
+
+ public byte[] ClientPayload { get; set; }
+
+ public byte[] ServerPayload { get; set; }
+
+ public byte[] HostKey { get; set; }
+
+ public UInt32 MinimumGroupSize { get; set; }
+
+ public UInt32 PreferredGroupSize { get; set; }
+
+ public UInt32 MaximumGroupSize { get; set; }
+
+ public BigInteger Prime { get; set; }
+
+ public BigInteger SubGroup { get; set; }
+
+ public BigInteger ClientExchangeValue { get; set; }
+
+ public BigInteger ServerExchangeValue { get; set; }
+
+ public BigInteger SharedKey { get; set; }
+
+ protected override void LoadData()
+ {
+ throw new NotImplementedException();
+ }
+
+ protected override void SaveData()
+ {
+ this.Write(this.ClientVersion);
+ this.Write(this.ServerVersion);
+ this.WriteBinaryString(this.ClientPayload);
+ this.WriteBinaryString(this.ServerPayload);
+ this.WriteBinaryString(this.HostKey);
+ this.Write(this.MinimumGroupSize);
+ this.Write(this.PreferredGroupSize);
+ this.Write(this.MaximumGroupSize);
+ this.Write(this.Prime);
+ this.Write(this.SubGroup);
+ this.Write(this.ClientExchangeValue);
+ this.Write(this.ServerExchangeValue);
+ this.Write(this.SharedKey);
+ }
+ }
+
+ }
+}
diff --git a/Renci.SshNet/Security/KeyHostAlgorithm.cs b/Renci.SshNet/Security/KeyHostAlgorithm.cs
index 74f90c6..261b882 100644
--- a/Renci.SshNet/Security/KeyHostAlgorithm.cs
+++ b/Renci.SshNet/Security/KeyHostAlgorithm.cs
@@ -1,173 +1,170 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Renci.SshNet.Common;
-using Renci.SshNet.Security.Cryptography;
-
-namespace Renci.SshNet.Security
-{
- ///
- /// Implements key support for host algorithm.
- ///
- public class KeyHostAlgorithm : HostAlgorithm
- {
-
- ///
- /// Gets the key.
- ///
- public Key Key { get; private set; }
-
- ///
- /// Gets the public key data.
- ///
- public override byte[] Data
- {
- get
- {
- return new SshKeyData(this.Name, this.Key.Public).GetBytes();
- }
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// Host key name.
- /// Host key.
- public KeyHostAlgorithm(string name, Key key)
- : base(name)
- {
- this.Key = key;
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// Host key name.
- /// Host key.
- /// Host key encoded data.
- public KeyHostAlgorithm(string name, Key key, byte[] data)
- : base(name)
- {
- this.Key = key;
-
- var sshKey = new SshKeyData();
- sshKey.Load(data);
- this.Key.Public = sshKey.Keys;
- }
-
- ///
- /// Signs the specified data.
- ///
- /// The data.
- ///
- /// Signed data.
- ///
- public override byte[] Sign(byte[] data)
- {
- return new SignatureKeyData(this.Name, this.Key.Sign(data)).GetBytes().ToArray();
- }
-
- ///
- /// Verifies the signature.
- ///
- /// The data.
- /// The signature.
- ///
- /// True is signature was successfully verifies; otherwise false.
- ///
- public override bool VerifySignature(byte[] data, byte[] signature)
- {
- var signatureData = new SignatureKeyData();
- signatureData.Load(signature);
-
- return this.Key.VerifySignature(data, signatureData.Signature);
- }
-
- private class SshKeyData : SshData
- {
- public BigInteger[] Keys { get; private set; }
-
- public string Name { get; private set; }
-
- public SshKeyData()
- {
-
- }
-
- public SshKeyData(string name, params BigInteger[] keys)
- {
- this.Name = name;
- this.Keys = keys;
- }
-
- protected override void LoadData()
- {
- this.Name = this.ReadString();
- var keys = new List();
- while (!this.IsEndOfData)
- {
- keys.Add(this.ReadBigInt());
- }
- this.Keys = keys.ToArray();
- }
-
- protected override void SaveData()
- {
- this.Write(this.Name);
- foreach (var key in this.Keys)
- {
- this.Write(key);
- }
- }
- }
-
- private class SignatureKeyData : SshData
- {
- ///
- /// Gets or sets the name of the algorithm.
- ///
- ///
- /// The name of the algorithm.
- ///
- public string AlgorithmName { get; private set; }
-
- ///
- /// Gets or sets the signature.
- ///
- ///
- /// The signature.
- ///
- public byte[] Signature { get; private set; }
-
- public SignatureKeyData()
- {
-
- }
-
- public SignatureKeyData(string name, byte[] signature)
- {
- this.AlgorithmName = name;
- this.Signature = signature;
- }
-
- ///
- /// Called when type specific data need to be loaded.
- ///
- protected override void LoadData()
- {
- this.AlgorithmName = this.ReadString();
- this.Signature = this.ReadBinaryString();
- }
-
- ///
- /// Called when type specific data need to be saved.
- ///
- protected override void SaveData()
- {
- this.Write(this.AlgorithmName);
- this.WriteBinaryString(this.Signature);
- }
- }
- }
-}
+using System.Collections.Generic;
+using System.Linq;
+using Renci.SshNet.Common;
+
+namespace Renci.SshNet.Security
+{
+ ///
+ /// Implements key support for host algorithm.
+ ///
+ public class KeyHostAlgorithm : HostAlgorithm
+ {
+
+ ///
+ /// Gets the key.
+ ///
+ public Key Key { get; private set; }
+
+ ///
+ /// Gets the public key data.
+ ///
+ public override byte[] Data
+ {
+ get
+ {
+ return new SshKeyData(this.Name, this.Key.Public).GetBytes();
+ }
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Host key name.
+ /// Host key.
+ public KeyHostAlgorithm(string name, Key key)
+ : base(name)
+ {
+ this.Key = key;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// Host key name.
+ /// Host key.
+ /// Host key encoded data.
+ public KeyHostAlgorithm(string name, Key key, byte[] data)
+ : base(name)
+ {
+ this.Key = key;
+
+ var sshKey = new SshKeyData();
+ sshKey.Load(data);
+ this.Key.Public = sshKey.Keys;
+ }
+
+ ///
+ /// Signs the specified data.
+ ///
+ /// The data.
+ ///
+ /// Signed data.
+ ///
+ public override byte[] Sign(byte[] data)
+ {
+ return new SignatureKeyData(this.Name, this.Key.Sign(data)).GetBytes();
+ }
+
+ ///
+ /// Verifies the signature.
+ ///
+ /// The data.
+ /// The signature.
+ ///
+ /// True is signature was successfully verifies; otherwise false.
+ ///
+ public override bool VerifySignature(byte[] data, byte[] signature)
+ {
+ var signatureData = new SignatureKeyData();
+ signatureData.Load(signature);
+
+ return this.Key.VerifySignature(data, signatureData.Signature);
+ }
+
+ private class SshKeyData : SshData
+ {
+ public BigInteger[] Keys { get; private set; }
+
+ public string Name { get; private set; }
+
+ public SshKeyData()
+ {
+
+ }
+
+ public SshKeyData(string name, params BigInteger[] keys)
+ {
+ this.Name = name;
+ this.Keys = keys;
+ }
+
+ protected override void LoadData()
+ {
+ this.Name = this.ReadString();
+ var keys = new List();
+ while (!this.IsEndOfData)
+ {
+ keys.Add(this.ReadBigInt());
+ }
+ this.Keys = keys.ToArray();
+ }
+
+ protected override void SaveData()
+ {
+ this.Write(this.Name);
+ foreach (var key in this.Keys)
+ {
+ this.Write(key);
+ }
+ }
+ }
+
+ private class SignatureKeyData : SshData
+ {
+ ///
+ /// Gets or sets the name of the algorithm.
+ ///
+ ///
+ /// The name of the algorithm.
+ ///
+ public string AlgorithmName { get; private set; }
+
+ ///
+ /// Gets or sets the signature.
+ ///
+ ///
+ /// The signature.
+ ///
+ public byte[] Signature { get; private set; }
+
+ public SignatureKeyData()
+ {
+
+ }
+
+ public SignatureKeyData(string name, byte[] signature)
+ {
+ this.AlgorithmName = name;
+ this.Signature = signature;
+ }
+
+ ///
+ /// Called when type specific data need to be loaded.
+ ///
+ protected override void LoadData()
+ {
+ this.AlgorithmName = this.ReadString();
+ this.Signature = this.ReadBinaryString();
+ }
+
+ ///
+ /// Called when type specific data need to be saved.
+ ///
+ protected override void SaveData()
+ {
+ this.Write(this.AlgorithmName);
+ this.WriteBinaryString(this.Signature);
+ }
+ }
+ }
+}
diff --git a/Renci.SshNet/Session.NET.cs b/Renci.SshNet/Session.NET.cs
index 5493332..6432a5d 100644
--- a/Renci.SshNet/Session.NET.cs
+++ b/Renci.SshNet/Session.NET.cs
@@ -1,188 +1,196 @@
-using System.Linq;
-using System;
-using System.Net.Sockets;
-using System.Net;
-using Renci.SshNet.Messages;
-using Renci.SshNet.Common;
-using System.Threading;
-using Renci.SshNet.Messages.Transport;
-using System.IO;
-using System.Diagnostics;
-using System.Text;
-using System.Collections.Generic;
-
-namespace Renci.SshNet
-{
- public partial class Session
- {
- private TraceSource _log =
-#if DEBUG
- new TraceSource("SshNet.Logging", SourceLevels.All);
-#else
- new TraceSource("SshNet.Logging");
-#endif
-
- partial void IsSocketConnected(ref bool isConnected)
- {
- isConnected = (!this._isDisconnecting && this._socket != null && this._socket.Connected && this._isAuthenticated && this._messageListenerCompleted != null)
- && this._socket.Poll(-1, SelectMode.SelectWrite);
- }
-
- partial void SocketConnect(string host, int port)
- {
- IPAddress addr = host.GetIPAddress();
-
- var ep = new IPEndPoint(addr, port);
- this._socket = new Socket(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
-
- var socketBufferSize = 2 * MAXIMUM_PACKET_SIZE;
-
- this._socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
- this._socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendBuffer, socketBufferSize);
- this._socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, socketBufferSize);
-
- this.Log(string.Format("Initiating connect to '{0}:{1}'.", this.ConnectionInfo.Host, this.ConnectionInfo.Port));
-
- // Connect socket with specified timeout
- var connectResult = this._socket.BeginConnect(ep, null, null);
-
- if (!connectResult.AsyncWaitHandle.WaitOne(this.ConnectionInfo.Timeout, false))
- {
- throw new SshOperationTimeoutException("Connection Could Not Be Established");
- }
-
- this._socket.EndConnect(connectResult);
- }
-
- partial void SocketDisconnect()
- {
- this._socket.Disconnect(true);
- }
-
- partial void SocketReadLine(ref string response)
- {
- var encoding = new Renci.SshNet.Common.ASCIIEncoding();
-
- var line = new StringBuilder();
- // Read data one byte at a time to find end of line and leave any unhandled information in the buffer to be processed later
- var buffer = new List();
-
- var data = new byte[1];
- do
- {
- var asyncResult = this._socket.BeginReceive(data, 0, data.Length, SocketFlags.None, null, null);
-
- if (!asyncResult.AsyncWaitHandle.WaitOne(this.ConnectionInfo.Timeout))
- throw new SshOperationTimeoutException("Socket read operation has timed out");
-
- var received = this._socket.EndReceive(asyncResult);
-
- // If zero bytes received then exit
- if (received == 0)
- break;
-
- buffer.Add(data[0]);
- }
- while (!(buffer.Count > 0 && (buffer[buffer.Count - 1] == 0x0A || buffer[buffer.Count - 1] == 0x00)));
-
- // Return an empty version string if the buffer consists of a 0x00 character.
- if (buffer.Count > 0 && buffer[buffer.Count - 1] == 0x00)
- {
- response = string.Empty;
- }
- else if (buffer.Count > 1 && buffer[buffer.Count - 2] == 0x0D)
- response = encoding.GetString(buffer.Take(buffer.Count - 2).ToArray());
- else
- response = encoding.GetString(buffer.Take(buffer.Count - 1).ToArray());
- }
-
- ///
- /// Function to read amount of data before returning, or throwing an exception.
- ///
- /// The amount wanted.
- /// The buffer to read to.
- /// Happens when the socket is closed.
- /// Unhandled exception.
- partial void SocketRead(int length, ref byte[] buffer)
- {
- var offset = 0;
- int receivedTotal = 0; // how many bytes is already received
-
- do
- {
- try
- {
- var receivedBytes = this._socket.Receive(buffer, offset + receivedTotal, length - receivedTotal, SocketFlags.None);
- if (receivedBytes > 0)
- {
- receivedTotal += receivedBytes;
- continue;
- }
- else
- {
- // 2012-09-11: Kenneth_aa
- // When Disconnect or Dispose is called, this throws SshConnectionException(), which...
- // 1 - goes up to ReceiveMessage()
- // 2 - up again to MessageListener()
- // which is where there is a catch-all exception block so it can notify event listeners.
- // 3 - MessageListener then again calls RaiseError().
- // There the exception is checked for the exception thrown here (ConnectionLost), and if it matches it will not call Session.SendDisconnect().
- //
- // Adding a check for this._isDisconnecting causes ReceiveMessage() to throw SshConnectionException: "Bad packet length {0}".
- //
- throw new SshConnectionException("An established connection was aborted by the software in your host machine.", DisconnectReason.ConnectionLost);
- }
- }
- catch (SocketException exp)
- {
- if (exp.SocketErrorCode == SocketError.ConnectionAborted)
- {
- buffer = new byte[length];
- this.Disconnect();
- return;
- }
- else if (exp.SocketErrorCode == SocketError.WouldBlock ||
- exp.SocketErrorCode == SocketError.IOPending ||
- exp.SocketErrorCode == SocketError.NoBufferSpaceAvailable)
- {
- // socket buffer is probably empty, wait and try again
- Thread.Sleep(30);
- }
- else
- throw; // any serious error occurred
- }
- } while (receivedTotal < length);
- }
-
- partial void SocketWrite(byte[] data)
- {
- int sent = 0; // how many bytes is already sent
- int length = data.Length;
-
- do
- {
- try
- {
- sent += this._socket.Send(data, sent, length - sent, SocketFlags.None);
- }
- catch (SocketException ex)
- {
- if (ex.SocketErrorCode == SocketError.WouldBlock ||
- ex.SocketErrorCode == SocketError.IOPending ||
- ex.SocketErrorCode == SocketError.NoBufferSpaceAvailable)
- {
- // socket buffer is probably full, wait and try again
- Thread.Sleep(30);
- }
- else
- throw; // any serious error occurr
- }
- } while (sent < length);
- }
-
- partial void Log(string text)
- {
- this._log.TraceEvent(System.Diagnostics.TraceEventType.Verbose, 1, text);
- }
- }
-}
+using System.Linq;
+using System;
+using System.Net.Sockets;
+using System.Net;
+using Renci.SshNet.Common;
+using System.Threading;
+using Renci.SshNet.Messages.Transport;
+using System.Diagnostics;
+using System.Collections.Generic;
+
+namespace Renci.SshNet
+{
+ public partial class Session
+ {
+ private readonly TraceSource _log =
+#if DEBUG
+ new TraceSource("SshNet.Logging", SourceLevels.All);
+#else
+ new TraceSource("SshNet.Logging");
+#endif
+
+ ///
+ /// Gets a value indicating whether the socket is connected.
+ ///
+ ///
+ /// true if the socket is connected; otherwise, false.
+ ///
+ partial void IsSocketConnected(ref bool isConnected)
+ {
+ isConnected = (_socket != null && _socket.Connected);
+ if (isConnected)
+ {
+ var connectionClosedOrDataAvailable = _socket.Poll(1000, SelectMode.SelectRead);
+ isConnected = !(connectionClosedOrDataAvailable && _socket.Available == 0);
+ }
+ }
+
+ partial void SocketConnect(string host, int port)
+ {
+ const int socketBufferSize = 2 * MaximumSshPacketSize;
+
+ var addr = host.GetIPAddress();
+
+ var ep = new IPEndPoint(addr, port);
+ this._socket = new Socket(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
+
+ this._socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);
+ this._socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendBuffer, socketBufferSize);
+ this._socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveBuffer, socketBufferSize);
+
+ this.Log(string.Format("Initiating connect to '{0}:{1}'.", this.ConnectionInfo.Host, this.ConnectionInfo.Port));
+
+ // Connect socket with specified timeout
+ var connectResult = this._socket.BeginConnect(ep, null, null);
+
+ if (!connectResult.AsyncWaitHandle.WaitOne(this.ConnectionInfo.Timeout, false))
+ {
+ throw new SshOperationTimeoutException("Connection Could Not Be Established");
+ }
+
+ this._socket.EndConnect(connectResult);
+ }
+
+ partial void SocketDisconnect()
+ {
+ _socket.Disconnect(true);
+ }
+
+ partial void SocketReadLine(ref string response)
+ {
+ var encoding = new ASCIIEncoding();
+
+ // Read data one byte at a time to find end of line and leave any unhandled information in the buffer to be processed later
+ var buffer = new List();
+
+ var data = new byte[1];
+ do
+ {
+ var asyncResult = this._socket.BeginReceive(data, 0, data.Length, SocketFlags.None, null, null);
+
+ if (!asyncResult.AsyncWaitHandle.WaitOne(this.ConnectionInfo.Timeout))
+ throw new SshOperationTimeoutException("Socket read operation has timed out");
+
+ var received = this._socket.EndReceive(asyncResult);
+
+ // If zero bytes received then exit
+ if (received == 0)
+ break;
+
+ buffer.Add(data[0]);
+ }
+ while (!(buffer.Count > 0 && (buffer[buffer.Count - 1] == 0x0A || buffer[buffer.Count - 1] == 0x00)));
+
+ // Return an empty version string if the buffer consists of a 0x00 character.
+ if (buffer.Count > 0 && buffer[buffer.Count - 1] == 0x00)
+ {
+ response = string.Empty;
+ }
+ else if (buffer.Count > 1 && buffer[buffer.Count - 2] == 0x0D)
+ response = encoding.GetString(buffer.Take(buffer.Count - 2).ToArray());
+ else
+ response = encoding.GetString(buffer.Take(buffer.Count - 1).ToArray());
+ }
+
+ ///
+ /// Function to read amount of data before returning, or throwing an exception.
+ ///
+ /// The amount wanted.
+ /// The buffer to read to.
+ /// Happens when the socket is closed.
+ /// Unhandled exception.
+ partial void SocketRead(int length, ref byte[] buffer)
+ {
+ var receivedTotal = 0; // how many bytes is already received
+
+ do
+ {
+ try
+ {
+ var receivedBytes = this._socket.Receive(buffer, receivedTotal, length - receivedTotal, SocketFlags.None);
+ if (receivedBytes > 0)
+ {
+ receivedTotal += receivedBytes;
+ continue;
+ }
+
+ // 2012-09-11: Kenneth_aa
+ // When Disconnect or Dispose is called, this throws SshConnectionException(), which...
+ // 1 - goes up to ReceiveMessage()
+ // 2 - up again to MessageListener()
+ // which is where there is a catch-all exception block so it can notify event listeners.
+ // 3 - MessageListener then again calls RaiseError().
+ // There the exception is checked for the exception thrown here (ConnectionLost), and if it matches it will not call Session.SendDisconnect().
+ //
+ // Adding a check for this._isDisconnecting causes ReceiveMessage() to throw SshConnectionException: "Bad packet length {0}".
+ //
+
+ if (_isDisconnecting)
+ throw new SshConnectionException("An established connection was aborted by the software in your host machine.", DisconnectReason.ConnectionLost);
+ throw new SshConnectionException("An established connection was aborted by the server.", DisconnectReason.ConnectionLost);
+ }
+ catch (SocketException exp)
+ {
+ if (exp.SocketErrorCode == SocketError.ConnectionAborted)
+ {
+ buffer = new byte[length];
+ this.Disconnect();
+ return;
+ }
+
+ if (exp.SocketErrorCode == SocketError.WouldBlock ||
+ exp.SocketErrorCode == SocketError.IOPending ||
+ exp.SocketErrorCode == SocketError.NoBufferSpaceAvailable)
+ {
+ // socket buffer is probably empty, wait and try again
+ Thread.Sleep(30);
+ }
+ else
+ throw; // any serious error occurred
+ }
+ } while (receivedTotal < length);
+ }
+
+ partial void SocketWrite(byte[] data)
+ {
+ var sent = 0; // how many bytes is already sent
+ var length = data.Length;
+
+ do
+ {
+ try
+ {
+ sent += this._socket.Send(data, sent, length - sent, SocketFlags.None);
+ }
+ catch (SocketException ex)
+ {
+ if (ex.SocketErrorCode == SocketError.WouldBlock ||
+ ex.SocketErrorCode == SocketError.IOPending ||
+ ex.SocketErrorCode == SocketError.NoBufferSpaceAvailable)
+ {
+ // socket buffer is probably full, wait and try again
+ Thread.Sleep(30);
+ }
+ else
+ throw; // any serious error occurr
+ }
+ } while (sent < length);
+ }
+
+ [Conditional("DEBUG")]
+ partial void Log(string text)
+ {
+ this._log.TraceEvent(TraceEventType.Verbose, 1, text);
+ }
+ }
+}
diff --git a/Renci.SshNet/Session.NET40.cs b/Renci.SshNet/Session.NET40.cs
index cdc721b..7d286a2 100644
--- a/Renci.SshNet/Session.NET40.cs
+++ b/Renci.SshNet/Session.NET40.cs
@@ -1,48 +1,44 @@
-using System.Threading.Tasks;
-using System.Linq;
-using System;
-using System.Net.Sockets;
-using System.Net;
-using Renci.SshNet.Messages;
-using Renci.SshNet.Common;
-using System.Threading;
-using Renci.SshNet.Messages.Transport;
-
-namespace Renci.SshNet
-{
- ///
- /// Provides functionality to connect and interact with SSH server.
- ///
- public partial class Session
- {
- partial void HandleMessageCore(Message message)
- {
- this.HandleMessage((dynamic)message);
- }
-
- partial void ExecuteThread(Action action)
- {
- ThreadPool.QueueUserWorkItem((o) => { action(); });
- }
-
- partial void InternalRegisterMessage(string messageName)
- {
- lock (this._messagesMetadata)
- {
- Parallel.ForEach(
- from m in this._messagesMetadata where m.Name == messageName select m,
- (item) => { item.Enabled = true; item.Activated = true; });
- }
- }
-
- partial void InternalUnRegisterMessage(string messageName)
- {
- lock (this._messagesMetadata)
- {
- Parallel.ForEach(
- from m in this._messagesMetadata where m.Name == messageName select m,
- (item) => { item.Enabled = false; item.Activated = false; });
- }
- }
- }
-}
+using System.Threading.Tasks;
+using System.Linq;
+using System;
+using Renci.SshNet.Messages;
+using System.Threading;
+
+namespace Renci.SshNet
+{
+ ///
+ /// Provides functionality to connect and interact with SSH server.
+ ///
+ public partial class Session
+ {
+ partial void HandleMessageCore(Message message)
+ {
+ this.HandleMessage((dynamic)message);
+ }
+
+ partial void ExecuteThread(Action action)
+ {
+ ThreadPool.QueueUserWorkItem(o => action());
+ }
+
+ partial void InternalRegisterMessage(string messageName)
+ {
+ lock (this._messagesMetadata)
+ {
+ Parallel.ForEach(
+ from m in this._messagesMetadata where m.Name == messageName select m,
+ item => { item.Enabled = true; item.Activated = true; });
+ }
+ }
+
+ partial void InternalUnRegisterMessage(string messageName)
+ {
+ lock (this._messagesMetadata)
+ {
+ Parallel.ForEach(
+ from m in this._messagesMetadata where m.Name == messageName select m,
+ item => { item.Enabled = false; item.Activated = false; });
+ }
+ }
+ }
+}
diff --git a/Renci.SshNet/Session.cs b/Renci.SshNet/Session.cs
index 18229b8..b5dbd7f 100644
--- a/Renci.SshNet/Session.cs
+++ b/Renci.SshNet/Session.cs
@@ -1,2030 +1,2121 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Net;
-using System.Net.Sockets;
-using System.Security.Cryptography;
-using System.Text;
-using System.Text.RegularExpressions;
-using System.Threading;
-using Renci.SshNet.Channels;
-using Renci.SshNet.Common;
-using Renci.SshNet.Compression;
-using Renci.SshNet.Messages;
-using Renci.SshNet.Messages.Authentication;
-using Renci.SshNet.Messages.Connection;
-using Renci.SshNet.Messages.Transport;
-using Renci.SshNet.Security;
-using System.Globalization;
-using Renci.SshNet.Security.Cryptography.Ciphers;
-using Renci.SshNet.Security.Cryptography;
-
-namespace Renci.SshNet
-{
- ///
- /// Provides functionality to connect and interact with SSH server.
- ///
- public partial class Session : IDisposable
- {
- ///
- /// Specifies maximum packet size defined by the protocol.
- ///
- protected const int MAXIMUM_PACKET_SIZE = 35000;
-
- ///
- /// Specifies maximum payload size defined by the protocol.
- ///
- protected const int MAXIMUM_PAYLOAD_SIZE = 1024 * 32;
-
- private static RNGCryptoServiceProvider _randomizer = new System.Security.Cryptography.RNGCryptoServiceProvider();
-
-#if SILVERLIGHT
- private static Regex _serverVersionRe = new Regex("^SSH-(?[^-]+)-(?.+)( SP.+)?$");
-#else
- private static Regex _serverVersionRe = new Regex("^SSH-(?[^-]+)-(?.+)( SP.+)?$", RegexOptions.Compiled);
-#endif
-
- ///
- /// Controls how many authentication attempts can take place at the same time.
- ///
- ///
- /// Some server may restrict number to prevent authentication attacks
- ///
- private static SemaphoreLight _authenticationConnection = new SemaphoreLight(3);
-
- ///
- /// Holds metada about session messages
- ///
- private IEnumerable _messagesMetadata;
-
- ///
- /// Holds connection socket.
- ///
- private Socket _socket;
-
- ///
- /// Holds locker object for the socket
- ///
- private object _socketLock = new object();
-
- ///
- /// Holds reference to task that listens for incoming messages
- ///
- private EventWaitHandle _messageListenerCompleted;
-
- ///
- /// Specifies outbound packet number
- ///
- private volatile UInt32 _outboundPacketSequence = 0;
-
- ///
- /// Specifies incoming packet number
- ///
- private UInt32 _inboundPacketSequence = 0;
-
- ///
- /// WaitHandle to signal that last service request was accepted
- ///
- private EventWaitHandle _serviceAccepted = new AutoResetEvent(false);
-
- ///
- /// WaitHandle to signal that exception was thrown by another thread.
- ///
- private EventWaitHandle _exceptionWaitHandle = new ManualResetEvent(false);
-
- ///
- /// WaitHandle to signal that key exchange was completed.
- ///
- private EventWaitHandle _keyExchangeCompletedWaitHandle = new ManualResetEvent(false);
-
- ///
- /// WaitHandle to signal that key exchange is in progress.
- ///
- private bool _keyExchangeInProgress = false;
-
- ///
- /// Exception that need to be thrown by waiting thread
- ///
- private Exception _exception;
-
- ///
- /// Specifies whether connection is authenticated
- ///
- private bool _isAuthenticated;
-
- ///
- /// Specifies whether user issued Disconnect command or not
- ///
- private bool _isDisconnecting;
-
- private KeyExchange _keyExchange;
-
- private HashAlgorithm _serverMac;
-
- private HashAlgorithm _clientMac;
-
- private Cipher _clientCipher;
-
- private Cipher _serverCipher;
-
- private Compressor _serverDecompression;
-
- private Compressor _clientCompression;
-
- private SemaphoreLight _sessionSemaphore;
- ///
- /// Gets the session semaphore that controls session channels.
- ///
- /// The session semaphore.
- public SemaphoreLight SessionSemaphore
- {
- get
- {
- if (this._sessionSemaphore == null)
- {
- lock (this)
- {
- if (this._sessionSemaphore == null)
- {
- this._sessionSemaphore = new SemaphoreLight(this.ConnectionInfo.MaxSessions);
- }
- }
- }
-
- return this._sessionSemaphore;
- }
- }
-
- private bool _isDisconnectMessageSent;
-
- private uint _nextChannelNumber;
- ///
- /// Gets the next channel number.
- ///
- /// The next channel number.
- internal uint NextChannelNumber
- {
- get
- {
- uint result;
-
- lock (this)
- {
- result = this._nextChannelNumber++;
- }
-
- return result;
- }
- }
-
- ///
- /// Gets a value indicating whether socket connected.
- ///
- ///
- /// true if socket connected; otherwise, false.
- ///
- public bool IsConnected
- {
- get
- {
- var isSocketConnected = false;
- IsSocketConnected(ref isSocketConnected);
- return isSocketConnected;
- }
- }
-
- ///
- /// Gets or sets the session id.
- ///
- /// The session id.
- public byte[] SessionId { get; private set; }
-
- private Message _clientInitMessage;
- ///
- /// Gets the client init message.
- ///
- /// The client init message.
- public Message ClientInitMessage
- {
- get
- {
- if (this._clientInitMessage == null)
- {
- this._clientInitMessage = new KeyExchangeInitMessage()
- {
- KeyExchangeAlgorithms = this.ConnectionInfo.KeyExchangeAlgorithms.Keys.ToArray(),
- ServerHostKeyAlgorithms = this.ConnectionInfo.HostKeyAlgorithms.Keys.ToArray(),
- EncryptionAlgorithmsClientToServer = this.ConnectionInfo.Encryptions.Keys.ToArray(),
- EncryptionAlgorithmsServerToClient = this.ConnectionInfo.Encryptions.Keys.ToArray(),
- MacAlgorithmsClientToServer = this.ConnectionInfo.HmacAlgorithms.Keys.ToArray(),
- MacAlgorithmsServerToClient = this.ConnectionInfo.HmacAlgorithms.Keys.ToArray(),
- CompressionAlgorithmsClientToServer = this.ConnectionInfo.CompressionAlgorithms.Keys.ToArray(),
- CompressionAlgorithmsServerToClient = this.ConnectionInfo.CompressionAlgorithms.Keys.ToArray(),
- LanguagesClientToServer = new string[] { string.Empty },
- LanguagesServerToClient = new string[] { string.Empty },
- FirstKexPacketFollows = false,
- Reserved = 0,
- };
- }
- return this._clientInitMessage;
- }
- }
-
- ///
- /// Gets or sets the server version string.
- ///
- /// The server version.
- public string ServerVersion { get; private set; }
-
- ///
- /// Gets or sets the client version string.
- ///
- /// The client version.
- public string ClientVersion { get; private set; }
-
- ///
- /// Gets or sets the connection info.
- ///
- /// The connection info.
- public ConnectionInfo ConnectionInfo { get; private set; }
-
- ///
- /// Occurs when an error occurred.
- ///
- public event EventHandler ErrorOccured;
-
- ///
- /// Occurs when session has been disconnected form the server.
- ///
- public event EventHandler Disconnected;
-
- ///
- /// Occurs when host key received.
- ///
- public event EventHandler HostKeyReceived;
-
- #region Message events
-
- ///
- /// Occurs when message received
- ///
- internal event EventHandler> DisconnectReceived;
-
- ///
- /// Occurs when message received
- ///
- internal event EventHandler> IgnoreReceived;
-
- ///
- /// Occurs when message received
- ///
- internal event EventHandler> UnimplementedReceived;
-
- ///
- /// Occurs when message received
- ///
- internal event EventHandler> DebugReceived;
-
- ///
- /// Occurs when message received
- ///
- internal event EventHandler> ServiceRequestReceived;
-
- ///
- /// Occurs when message received
- ///
- internal event EventHandler> ServiceAcceptReceived;
-
- ///
- /// Occurs when message received
- ///
- internal event EventHandler> KeyExchangeInitReceived;
-
- ///
- /// Occurs when message received
- ///
- internal event EventHandler> NewKeysReceived;
-
- ///
- /// Occurs when message received
- ///
- internal event EventHandler> UserAuthenticationRequestReceived;
-
- ///
- /// Occurs when message received
- ///
- internal event EventHandler> UserAuthenticationFailureReceived;
-
- ///
- /// Occurs when message received
- ///
- internal event EventHandler> UserAuthenticationSuccessReceived;
-
- ///
- /// Occurs when message received
- ///
- internal event EventHandler> UserAuthenticationBannerReceived;
-
- ///
- /// Occurs when message received
- ///
- internal event EventHandler> GlobalRequestReceived;
-
- ///
- /// Occurs when message received
- ///
- internal event EventHandler> RequestSuccessReceived;
-
- ///
- /// Occurs when message received
- ///
- internal event EventHandler> RequestFailureReceived;
-
- ///
- /// Occurs when message received
- ///
- internal event EventHandler> ChannelOpenReceived;
-
- ///
- /// Occurs when message received
- ///
- internal event EventHandler> ChannelOpenConfirmationReceived;
-
- ///
- /// Occurs when message received
- ///
- internal event EventHandler> ChannelOpenFailureReceived;
-
- ///
- /// Occurs when message received
- ///
- internal event EventHandler> ChannelWindowAdjustReceived;
-
- ///
- /// Occurs when message received
- ///
- internal event EventHandler> ChannelDataReceived;
-
- ///
- /// Occurs when message received
- ///
- internal event EventHandler> ChannelExtendedDataReceived;
-
- ///
- /// Occurs when message received
- ///
- internal event EventHandler> ChannelEofReceived;
-
- ///
- /// Occurs when message received
- ///
- internal event EventHandler> ChannelCloseReceived;
-
- ///
- /// Occurs when message received
- ///
- internal event EventHandler> ChannelRequestReceived;
-
- ///
- /// Occurs when message received
- ///
- internal event EventHandler> ChannelSuccessReceived;
-
- ///
- /// Occurs when message received
- ///
- internal event EventHandler> ChannelFailureReceived;
-
- ///
- /// Occurs when message received and is not handled by any of the event handlers
- ///
- internal event EventHandler> MessageReceived;
-
- #endregion
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The connection info.
- internal Session(ConnectionInfo connectionInfo)
- {
- this.ConnectionInfo = connectionInfo;
- //this.ClientVersion = string.Format(CultureInfo.CurrentCulture, "SSH-2.0-Renci.SshNet.SshClient.{0}", this.GetType().Assembly.GetName().Version);
- this.ClientVersion = string.Format(CultureInfo.CurrentCulture, "SSH-2.0-Renci.SshNet.SshClient.0.0.1");
- }
-
- ///
- /// Connects to the server.
- ///
- public void Connect()
- {
- // TODO: Add exception documentation for Proxy.
- if (this.ConnectionInfo == null)
- {
- throw new ArgumentNullException("connectionInfo");
- }
-
- if (this.IsConnected)
- return;
-
- try
- {
- _authenticationConnection.Wait();
-
- if (this.IsConnected)
- return;
-
- lock (this)
- {
- // If connected don't connect again
- if (this.IsConnected)
- return;
-
- // Build list of available messages while connecting
- this._messagesMetadata = GetMessagesMetadata();
-
- switch (this.ConnectionInfo.ProxyType)
- {
- case ProxyTypes.None:
- this.SocketConnect(this.ConnectionInfo.Host, this.ConnectionInfo.Port);
- break;
- case ProxyTypes.Socks4:
- this.SocketConnect(this.ConnectionInfo.ProxyHost, this.ConnectionInfo.ProxyPort);
- this.ConnectSocks4();
- break;
- case ProxyTypes.Socks5:
- this.SocketConnect(this.ConnectionInfo.ProxyHost, this.ConnectionInfo.ProxyPort);
- this.ConnectSocks5();
- break;
- case ProxyTypes.Http:
- this.SocketConnect(this.ConnectionInfo.ProxyHost, this.ConnectionInfo.ProxyPort);
- this.ConnectHttp();
- break;
- default:
- break;
- }
-
-
- Match versionMatch = null;
-
- // Get server version from the server,
- // ignore text lines which are sent before if any
- while (true)
- {
- string serverVersion = string.Empty;
- this.SocketReadLine(ref serverVersion);
-
- this.ServerVersion = serverVersion;
- if (string.IsNullOrEmpty(this.ServerVersion))
- {
- throw new InvalidOperationException("Server string is null or empty.");
- }
-
- versionMatch = _serverVersionRe.Match(this.ServerVersion);
-
- if (versionMatch.Success)
- {
- break;
- }
- }
-
- // Set connection versions
- this.ConnectionInfo.ServerVersion = this.ServerVersion;
- this.ConnectionInfo.ClientVersion = this.ClientVersion;
-
- // Get server SSH version
- var version = versionMatch.Result("${protoversion}");
-
- var softwareName = versionMatch.Result("${softwareversion}");
-
- this.Log(string.Format("Server version '{0}' on '{1}'.", version, softwareName));
-
- if (!(version.Equals("2.0") || version.Equals("1.99")))
- {
- throw new SshConnectionException(string.Format(CultureInfo.CurrentCulture, "Server version '{0}' is not supported.", version), DisconnectReason.ProtocolVersionNotSupported);
- }
-
- this.SocketWrite(Encoding.UTF8.GetBytes(string.Format(CultureInfo.InvariantCulture, "{0}\x0D\x0A", this.ClientVersion)));
-
- // Register Transport response messages
- this.RegisterMessage("SSH_MSG_DISCONNECT");
- this.RegisterMessage("SSH_MSG_IGNORE");
- this.RegisterMessage("SSH_MSG_UNIMPLEMENTED");
- this.RegisterMessage("SSH_MSG_DEBUG");
- this.RegisterMessage("SSH_MSG_SERVICE_ACCEPT");
- this.RegisterMessage("SSH_MSG_KEXINIT");
- this.RegisterMessage("SSH_MSG_NEWKEYS");
-
- // Some server implementations might sent this message first, prior establishing encryption algorithm
- this.RegisterMessage("SSH_MSG_USERAUTH_BANNER");
-
- // Start incoming request listener
- this._messageListenerCompleted = new ManualResetEvent(false);
-
- this.ExecuteThread(() =>
- {
- try
- {
- this.MessageListener();
- }
- finally
- {
- this._messageListenerCompleted.Set();
- }
- });
-
- // Wait for key exchange to be completed
- this.WaitHandle(this._keyExchangeCompletedWaitHandle);
-
- // If sessionId is not set then its not connected
- if (this.SessionId == null)
- {
- this.Disconnect();
- return;
- }
-
- // Request user authorization service
- this.SendMessage(new ServiceRequestMessage(ServiceName.UserAuthentication));
-
- // Wait for service to be accepted
- this.WaitHandle(this._serviceAccepted);
-
- if (string.IsNullOrEmpty(this.ConnectionInfo.Username))
- {
- throw new SshException("Username is not specified.");
- }
-
- this._isAuthenticated = this.ConnectionInfo.Authenticate(this);
-
- if (!this._isAuthenticated)
- {
- throw new SshAuthenticationException("User cannot be authenticated.");
- }
-
- // Register Connection messages
- this.RegisterMessage("SSH_MSG_GLOBAL_REQUEST");
- this.RegisterMessage("SSH_MSG_REQUEST_SUCCESS");
- this.RegisterMessage("SSH_MSG_REQUEST_FAILURE");
- this.RegisterMessage("SSH_MSG_CHANNEL_OPEN_CONFIRMATION");
- this.RegisterMessage("SSH_MSG_CHANNEL_OPEN_FAILURE");
- this.RegisterMessage("SSH_MSG_CHANNEL_WINDOW_ADJUST");
- this.RegisterMessage("SSH_MSG_CHANNEL_EXTENDED_DATA");
- this.RegisterMessage("SSH_MSG_CHANNEL_REQUEST");
- this.RegisterMessage("SSH_MSG_CHANNEL_SUCCESS");
- this.RegisterMessage("SSH_MSG_CHANNEL_FAILURE");
- this.RegisterMessage("SSH_MSG_CHANNEL_DATA");
- this.RegisterMessage("SSH_MSG_CHANNEL_EOF");
- this.RegisterMessage("SSH_MSG_CHANNEL_CLOSE");
-
- Monitor.Pulse(this);
- }
- }
- finally
- {
- _authenticationConnection.Release();
- }
- }
-
- ///
- /// Disconnects from the server
- ///
- public void Disconnect()
- {
- this._isDisconnecting = true;
-
- // If socket still open try to send disconnect message to the server
- this.SendDisconnect(DisconnectReason.ByApplication, "Connection terminated by the client.");
-
- //this.Dispose();
- }
-
- internal T CreateChannel() where T : Channel, new()
- {
- return CreateChannel(0, 0x100000, 0x8000);
- }
-
- internal T CreateChannel(uint serverChannelNumber, uint windowSize, uint packetSize) where T : Channel, new()
- {
- T channel = new T();
- lock (this)
- {
- channel.Initialize(this, serverChannelNumber, windowSize, packetSize);
- }
- return channel;
- }
-
- ///
- /// Sends "keep alive" message to keep connection alive.
- ///
- internal void SendKeepAlive()
- {
- this.SendMessage(new IgnoreMessage());
- }
-
- ///
- /// Waits for handle to signal while checking other handles as well including timeout check to prevent waiting for ever
- ///
- /// The wait handle.
- internal void WaitHandle(WaitHandle waitHandle)
- {
- var waitHandles = new WaitHandle[]
- {
- this._exceptionWaitHandle,
- waitHandle,
- };
-
- switch (EventWaitHandle.WaitAny(waitHandles, this.ConnectionInfo.Timeout))
- {
- case 0:
- throw this._exception;
- case System.Threading.WaitHandle.WaitTimeout:
- this.SendDisconnect(DisconnectReason.ByApplication, "Operation timeout");
- throw new SshOperationTimeoutException("Session operation has timed out");
- default:
- break;
- }
- }
-
- ///
- /// Sends packet message to the server.
- ///
- /// The message.
- internal void SendMessage(Message message)
- {
- if (this._socket == null || !this._socket.CanWrite())
- throw new SshConnectionException("Client not connected.");
-
- if (this._keyExchangeInProgress && !(message is IKeyExchangedAllowed))
- {
- // Wait for key exchange to be completed
- this.WaitHandle(this._keyExchangeCompletedWaitHandle);
- }
-
- this.Log(string.Format("SendMessage to server '{0}': '{1}'.", message.GetType().Name, message.ToString()));
-
- // Messages can be sent by different thread so we need to synchronize it
- var paddingMultiplier = this._clientCipher == null ? (byte)8 : Math.Max((byte)8, this._serverCipher.MinimumSize); // Should be recalculate base on cipher min length if cipher specified
-
- var messageData = message.GetBytes();
-
- if (messageData.Length > Session.MAXIMUM_PAYLOAD_SIZE)
- {
- throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, "Payload cannot be more then {0} bytes.", Session.MAXIMUM_PAYLOAD_SIZE));
- }
-
- if (this._clientCompression != null)
- {
- messageData = this._clientCompression.Compress(messageData);
- }
-
- var packetLength = messageData.Length + 4 + 1; // add length bytes and padding byte
- byte paddingLength = (byte)((-packetLength) & (paddingMultiplier - 1));
- if (paddingLength < paddingMultiplier)
- {
- paddingLength += paddingMultiplier;
- }
-
- // Build Packet data
- var packetData = new byte[4 + 1 + messageData.Length + paddingLength];
-
- // Add packet length
- ((uint)packetData.Length - 4).GetBytes().CopyTo(packetData, 0);
-
- // Add packet padding length
- packetData[4] = paddingLength;
-
- // Add packet payload
- messageData.CopyTo(packetData, 4 + 1);
-
- // Add random padding
- var paddingBytes = new byte[paddingLength];
- _randomizer.GetBytes(paddingBytes);
- paddingBytes.CopyTo(packetData, 4 + 1 + messageData.Length);
-
- // Lock handling of _outboundPacketSequence since it must be sent sequently to server
- lock (this._socketLock)
- {
- if (this._socket == null || !this._socket.Connected)
- throw new SshConnectionException("Client not connected.");
-
- // Calculate packet hash
- var hashData = new byte[4 + packetData.Length];
- this._outboundPacketSequence.GetBytes().CopyTo(hashData, 0);
- packetData.CopyTo(hashData, 4);
-
- // Encrypt packet data
- if (this._clientCipher != null)
- {
- packetData = this._clientCipher.Encrypt(packetData);
- }
-
- if (packetData.Length > Session.MAXIMUM_PACKET_SIZE)
- {
- throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, "Packet is too big. Maximum packet size is {0} bytes.", Session.MAXIMUM_PACKET_SIZE));
- }
-
- if (this._clientMac == null)
- {
- this.SocketWrite(packetData);
- }
- else
- {
- var hash = this._clientMac.ComputeHash(hashData.ToArray());
-
- var data = new byte[packetData.Length + this._clientMac.HashSize / 8];
- packetData.CopyTo(data, 0);
- hash.CopyTo(data, packetData.Length);
-
- this.SocketWrite(data);
- }
-
- this._outboundPacketSequence++;
-
- Monitor.Pulse(this._socketLock);
- }
- }
-
- private static IEnumerable GetMessagesMetadata()
- {
- return new MessageMetadata[]
- {
- new MessageMetadata { Name = "SSH_MSG_NEWKEYS", Number = 21, Enabled = false, Activated = false, Type = typeof(NewKeysMessage), },
- new MessageMetadata { Name = "SSH_MSG_REQUEST_FAILURE", Number = 82, Enabled = false, Activated = false, Type = typeof(RequestFailureMessage), },
- new MessageMetadata { Name = "SSH_MSG_KEXINIT", Number = 20, Enabled = false, Activated = false, Type = typeof(KeyExchangeInitMessage), },
- new MessageMetadata { Name = "SSH_MSG_CHANNEL_OPEN_FAILURE", Number = 92, Enabled = false, Activated = false, Type = typeof(ChannelOpenFailureMessage), },
- new MessageMetadata { Name = "SSH_MSG_CHANNEL_FAILURE", Number = 100, Enabled = false, Activated = false, Type = typeof(ChannelFailureMessage), },
- new MessageMetadata { Name = "SSH_MSG_CHANNEL_EXTENDED_DATA", Number = 95, Enabled = false, Activated = false, Type = typeof(ChannelExtendedDataMessage), },
- new MessageMetadata { Name = "SSH_MSG_CHANNEL_DATA", Number = 94, Enabled = false, Activated = false, Type = typeof(ChannelDataMessage), },
- new MessageMetadata { Name = "SSH_MSG_USERAUTH_REQUEST", Number = 50, Enabled = false, Activated = false, Type = typeof(RequestMessage), },
- new MessageMetadata { Name = "SSH_MSG_CHANNEL_REQUEST", Number = 98, Enabled = false, Activated = false, Type = typeof(ChannelRequestMessage), },
- new MessageMetadata { Name = "SSH_MSG_USERAUTH_BANNER", Number = 53, Enabled = false, Activated = false, Type = typeof(BannerMessage), },
- new MessageMetadata { Name = "SSH_MSG_USERAUTH_INFO_RESPONSE", Number = 61, Enabled = false, Activated = false, Type = typeof(InformationResponseMessage), },
- new MessageMetadata { Name = "SSH_MSG_USERAUTH_FAILURE", Number = 51, Enabled = false, Activated = false, Type = typeof(FailureMessage), },
- new MessageMetadata { Name = "SSH_MSG_DEBUG", Number = 4, Enabled = false, Activated = false, Type = typeof(DebugMessage), },
- new MessageMetadata { Name = "SSH_MSG_KEXDH_INIT", Number = 30, Enabled = false, Activated = false, Type = typeof(KeyExchangeDhInitMessage), },
- new MessageMetadata { Name = "SSH_MSG_GLOBAL_REQUEST", Number = 80, Enabled = false, Activated = false, Type = typeof(GlobalRequestMessage), },
- new MessageMetadata { Name = "SSH_MSG_CHANNEL_OPEN", Number = 90, Enabled = false, Activated = false, Type = typeof(ChannelOpenMessage), },
- new MessageMetadata { Name = "SSH_MSG_CHANNEL_OPEN_CONFIRMATION", Number = 91, Enabled = false, Activated = false, Type = typeof(ChannelOpenConfirmationMessage), },
- new MessageMetadata { Name = "SSH_MSG_USERAUTH_INFO_REQUEST", Number = 60, Enabled = false, Activated = false, Type = typeof(InformationRequestMessage), },
- new MessageMetadata { Name = "SSH_MSG_UNIMPLEMENTED", Number = 3, Enabled = false, Activated = false, Type = typeof(UnimplementedMessage), },
- new MessageMetadata { Name = "SSH_MSG_REQUEST_SUCCESS", Number = 81, Enabled = false, Activated = false, Type = typeof(RequestSuccessMessage), },
- new MessageMetadata { Name = "SSH_MSG_CHANNEL_SUCCESS", Number = 99, Enabled = false, Activated = false, Type = typeof(ChannelSuccessMessage), },
- new MessageMetadata { Name = "SSH_MSG_USERAUTH_PASSWD_CHANGEREQ", Number = 60, Enabled = false, Activated = false, Type = typeof(PasswordChangeRequiredMessage), },
- new MessageMetadata { Name = "SSH_MSG_DISCONNECT", Number = 1, Enabled = false, Activated = false, Type = typeof(DisconnectMessage), },
- new MessageMetadata { Name = "SSH_MSG_SERVICE_REQUEST", Number = 5, Enabled = false, Activated = false, Type = typeof(ServiceRequestMessage), },
- new MessageMetadata { Name = "SSH_MSG_KEX_DH_GEX_REQUEST", Number = 34, Enabled = false, Activated = false, Type = typeof(KeyExchangeDhGroupExchangeRequest), },
- new MessageMetadata { Name = "SSH_MSG_KEX_DH_GEX_GROUP", Number = 31, Enabled = false, Activated = false, Type = typeof(KeyExchangeDhGroupExchangeGroup), },
- new MessageMetadata { Name = "SSH_MSG_USERAUTH_SUCCESS", Number = 52, Enabled = false, Activated = false, Type = typeof(SuccessMessage), },
- new MessageMetadata { Name = "SSH_MSG_USERAUTH_PK_OK", Number = 60, Enabled = false, Activated = false, Type = typeof(PublicKeyMessage), },
- new MessageMetadata { Name = "SSH_MSG_IGNORE", Number = 2, Enabled = false, Activated = false, Type = typeof(IgnoreMessage), },
- new MessageMetadata { Name = "SSH_MSG_CHANNEL_WINDOW_ADJUST", Number = 93, Enabled = false, Activated = false, Type = typeof(ChannelWindowAdjustMessage), },
- new MessageMetadata { Name = "SSH_MSG_CHANNEL_EOF", Number = 96, Enabled = false, Activated = false, Type = typeof(ChannelEofMessage), },
- new MessageMetadata { Name = "SSH_MSG_CHANNEL_CLOSE", Number = 97, Enabled = false, Activated = false, Type = typeof(ChannelCloseMessage), },
- new MessageMetadata { Name = "SSH_MSG_SERVICE_ACCEPT", Number = 6, Enabled = false, Activated = false, Type = typeof(ServiceAcceptMessage), },
- new MessageMetadata { Name = "SSH_MSG_KEXDH_REPLY", Number = 31, Enabled = false, Activated = false, Type = typeof(KeyExchangeDhReplyMessage), },
- new MessageMetadata { Name = "SSH_MSG_KEX_DH_GEX_INIT", Number = 32, Enabled = false, Activated = false, Type = typeof(KeyExchangeDhGroupExchangeInit), },
- new MessageMetadata { Name = "SSH_MSG_KEX_DH_GEX_REPLY", Number = 33, Enabled = false, Activated = false, Type = typeof(KeyExchangeDhGroupExchangeReply), },
- };
- }
-
- ///
- /// Receives the message from the server.
- ///
- /// Incoming SSH message.
- ///
- private Message ReceiveMessage()
- {
- if (!this._socket.Connected)
- return null;
-
- // No lock needed since all messages read by only one thread
- var blockSize = this._serverCipher == null ? (byte)8 : Math.Max((byte)8, this._serverCipher.MinimumSize);
-
- // Read packet length first
- var firstBlock = this.Read(blockSize);
-
- if (this._serverCipher != null)
- {
- firstBlock = this._serverCipher.Decrypt(firstBlock);
- }
-
- var packetLength = (uint)(firstBlock[0] << 24 | firstBlock[1] << 16 | firstBlock[2] << 8 | firstBlock[3]);
-
- // Test packet minimum and maximum boundaries
- if (packetLength < Math.Max((byte)16, blockSize) - 4 || packetLength > Session.MAXIMUM_PACKET_SIZE - 4)
- throw new SshConnectionException(string.Format(CultureInfo.CurrentCulture, "Bad packet length {0}", packetLength), DisconnectReason.ProtocolError);
-
- // Read rest of the packet data
- int bytesToRead = (int)(packetLength - (blockSize - 4));
-
- var data = new byte[bytesToRead + blockSize];
-
- firstBlock.CopyTo(data, 0);
-
- byte[] serverHash = null;
- if (this._serverMac != null)
- {
- serverHash = new byte[this._serverMac.HashSize / 8];
- bytesToRead += serverHash.Length;
- }
-
- if (bytesToRead > 0)
- {
- var nextBlocks = this.Read(bytesToRead);
-
- if (serverHash != null)
- {
- Buffer.BlockCopy(nextBlocks, nextBlocks.Length - serverHash.Length, serverHash, 0, serverHash.Length);
- nextBlocks = nextBlocks.Take(nextBlocks.Length - serverHash.Length).ToArray();
- }
-
- if (nextBlocks.Length > 0)
- {
- if (this._serverCipher != null)
- {
- nextBlocks = this._serverCipher.Decrypt(nextBlocks);
- }
- nextBlocks.CopyTo(data, blockSize);
- }
- }
-
- var paddingLength = data[4];
-
- var messagePayload = new byte[packetLength - paddingLength - 1];
- Buffer.BlockCopy(data, 5, messagePayload, 0, messagePayload.Length);
-
- if (this._serverDecompression != null)
- {
- messagePayload = this._serverDecompression.Decompress(messagePayload);
- }
-
- // Validate message against MAC
- if (this._serverMac != null)
- {
- var clientHashData = new byte[4 + data.Length];
- var lengthBytes = this._inboundPacketSequence.GetBytes();
-
- lengthBytes.CopyTo(clientHashData, 0);
- data.CopyTo(clientHashData, 4);
-
- // Calculate packet hash
- var clientHash = this._serverMac.ComputeHash(clientHashData);
-
- if (!serverHash.SequenceEqual(clientHash))
- {
- throw new SshConnectionException("MAC error", DisconnectReason.MacError);
- }
- }
-
- this._inboundPacketSequence++;
-
- return this.LoadMessage(messagePayload);
- }
-
- private void SendDisconnect(DisconnectReason reasonCode, string message)
- {
- // If disconnect message was sent already dont send it again
- if (this._isDisconnectMessageSent)
- return;
-
- var disconnectMessage = new DisconnectMessage(reasonCode, message);
-
- this.SendMessage(disconnectMessage);
-
- this._isDisconnectMessageSent = true;
- }
-
- partial void HandleMessageCore(Message message);
-
- ///
- /// Handles the message.
- ///
- ///
- /// The message.
- private void HandleMessage(T message) where T : Message
- {
- this.OnMessageReceived(message);
- }
-
- #region Handle transport messages
-
- private void HandleMessage(DisconnectMessage message)
- {
- this.OnDisconnectReceived(message);
-
- // Shutdown and disconnect from the socket
- if (this._socket != null)
- {
- lock (this._socketLock)
- {
- if (this._socket != null)
- {
- this.SocketDisconnect();
- this._socket.Dispose();
- this._socket = null;
- }
- }
- }
- }
-
- private void HandleMessage(IgnoreMessage message)
- {
- this.OnIgnoreReceived(message);
- }
-
- private void HandleMessage(UnimplementedMessage message)
- {
- this.OnUnimplementedReceived(message);
- }
-
- private void HandleMessage(DebugMessage message)
- {
- this.OnDebugReceived(message);
- }
-
- private void HandleMessage(ServiceRequestMessage message)
- {
- this.OnServiceRequestReceived(message);
- }
-
- private void HandleMessage(ServiceAcceptMessage message)
- {
- // TODO: Refactor to avoid this method here
- this.OnServiceAcceptReceived(message);
-
- this._serviceAccepted.Set();
- }
-
- private void HandleMessage(KeyExchangeInitMessage message)
- {
- this.OnKeyExchangeInitReceived(message);
- }
-
- private void HandleMessage(NewKeysMessage message)
- {
- this.OnNewKeysReceived(message);
- }
-
- #endregion
-
- #region Handle User Authentication messages
-
- private void HandleMessage(RequestMessage message)
- {
- this.OnUserAuthenticationRequestReceived(message);
- }
-
- private void HandleMessage(FailureMessage message)
- {
- this.OnUserAuthenticationFailureReceived(message);
- }
-
- private void HandleMessage(SuccessMessage message)
- {
- this.OnUserAuthenticationSuccessReceived(message);
- }
-
- private void HandleMessage(BannerMessage message)
- {
- this.OnUserAuthenticationBannerReceived(message);
- }
-
- #endregion
-
- #region Handle connection messages
-
- private void HandleMessage(GlobalRequestMessage message)
- {
- this.OnGlobalRequestReceived(message);
- }
-
- private void HandleMessage(RequestSuccessMessage message)
- {
- this.OnRequestSuccessReceived(message);
- }
-
- private void HandleMessage(RequestFailureMessage message)
- {
- this.OnRequestFailureReceived(message);
- }
-
- private void HandleMessage(ChannelOpenMessage message)
- {
- this.OnChannelOpenReceived(message);
- }
-
- private void HandleMessage(ChannelOpenConfirmationMessage message)
- {
- this.OnChannelOpenConfirmationReceived(message);
- }
-
- private void HandleMessage(ChannelOpenFailureMessage message)
- {
- this.OnChannelOpenFailureReceived(message);
- }
-
- private void HandleMessage(ChannelWindowAdjustMessage message)
- {
- this.OnChannelWindowAdjustReceived(message);
- }
-
- private void HandleMessage(ChannelDataMessage message)
- {
- this.OnChannelDataReceived(message);
- }
-
- private void HandleMessage(ChannelExtendedDataMessage message)
- {
- this.OnChannelExtendedDataReceived(message);
- }
-
- private void HandleMessage(ChannelEofMessage message)
- {
- this.OnChannelEofReceived(message);
- }
-
- private void HandleMessage(ChannelCloseMessage message)
- {
- this.OnChannelCloseReceived(message);
- }
-
- private void HandleMessage(ChannelRequestMessage message)
- {
- this.OnChannelRequestReceived(message);
- }
-
- private void HandleMessage(ChannelSuccessMessage message)
- {
- this.OnChannelSuccessReceived(message);
- }
-
- private void HandleMessage(ChannelFailureMessage message)
- {
- this.OnChannelFailureReceived(message);
- }
-
- #endregion
-
- #region Handle received message events
-
- ///
- /// Called when received.
- ///
- /// message.
- protected virtual void OnDisconnectReceived(DisconnectMessage message)
- {
- this.Log(string.Format("Disconnect received: {0} {1}", message.ReasonCode, message.Description));
-
- if (this.DisconnectReceived != null)
- {
- this.DisconnectReceived(this, new MessageEventArgs(message));
- }
-
- if (this.Disconnected != null)
- {
- this.Disconnected(this, new EventArgs());
- }
- }
-
- ///
- /// Called when received.
- ///
- /// message.
- protected virtual void OnIgnoreReceived(IgnoreMessage message)
- {
- if (this.IgnoreReceived != null)
- {
- this.IgnoreReceived(this, new MessageEventArgs(message));
- }
- }
-
- ///
- /// Called when message received.
- ///
- /// message.
- protected virtual void OnUnimplementedReceived(UnimplementedMessage message)
- {
- if (this.UnimplementedReceived != null)
- {
- this.UnimplementedReceived(this, new MessageEventArgs(message));
- }
- }
-
- ///
- /// Called when message received.
- ///
- /// message.
- protected virtual void OnDebugReceived(DebugMessage message)
- {
- if (this.DebugReceived != null)
- {
- this.DebugReceived(this, new MessageEventArgs(message));
- }
- }
-
- ///
- /// Called when message received.
- ///
- /// message.
- protected virtual void OnServiceRequestReceived(ServiceRequestMessage message)
- {
- if (this.ServiceRequestReceived != null)
- {
- this.ServiceRequestReceived(this, new MessageEventArgs(message));
- }
- }
-
- ///
- /// Called when message received.
- ///
- /// message.
- protected virtual void OnServiceAcceptReceived(ServiceAcceptMessage message)
- {
- if (this.ServiceAcceptReceived != null)
- {
- this.ServiceAcceptReceived(this, new MessageEventArgs(message));
- }
- }
-
- ///
- /// Called when message received.
- ///
- /// message.
- protected virtual void OnKeyExchangeInitReceived(KeyExchangeInitMessage message)
- {
- this._keyExchangeInProgress = true;
-
- this._keyExchangeCompletedWaitHandle.Reset();
-
- // Disable all registered messages except key exchange related
- foreach (var messageMetadata in this._messagesMetadata)
- {
- if (messageMetadata.Activated == true && messageMetadata.Number > 2 && (messageMetadata.Number < 20 || messageMetadata.Number > 30))
- messageMetadata.Enabled = false;
- }
-
- var keyExchangeAlgorithmName = (from c in this.ConnectionInfo.KeyExchangeAlgorithms.Keys
- from s in message.KeyExchangeAlgorithms
- where s == c
- select c).FirstOrDefault();
-
- if (keyExchangeAlgorithmName == null)
- {
- throw new SshConnectionException("Failed to negotiate key exchange algorithm.", DisconnectReason.KeyExchangeFailed);
- }
-
- // Create instance of key exchange algorithm that will be used
- this._keyExchange = this.ConnectionInfo.KeyExchangeAlgorithms[keyExchangeAlgorithmName].CreateInstance();
-
- this.ConnectionInfo.CurrentKeyExchangeAlgorithm = keyExchangeAlgorithmName;
-
- this._keyExchange.HostKeyReceived += KeyExchange_HostKeyReceived;
-
- // Start the algorithm implementation
- this._keyExchange.Start(this, message);
-
- if (this.KeyExchangeInitReceived != null)
- {
- this.KeyExchangeInitReceived(this, new MessageEventArgs(message));
- }
- }
-
- ///
- /// Called when message received.
- ///
- /// message.
- protected virtual void OnNewKeysReceived(NewKeysMessage message)
- {
- // Update sessionId
- if (this.SessionId == null)
- {
- this.SessionId = this._keyExchange.ExchangeHash;
- }
-
- // Dispose of old ciphers and hash algorithms
- if (this._serverMac != null)
- {
- this._serverMac.Clear();
- this._serverMac = null;
- }
-
- if (this._clientMac != null)
- {
- this._clientMac.Clear();
- this._clientMac = null;
- }
-
- // Update negotiated algorithms
- this._serverCipher = this._keyExchange.CreateServerCipher();
- this._clientCipher = this._keyExchange.CreateClientCipher();
- this._serverMac = this._keyExchange.CreateServerHash();
- this._clientMac = this._keyExchange.CreateClientHash();
- this._clientCompression = this._keyExchange.CreateCompressor();
- this._serverDecompression = this._keyExchange.CreateDecompressor();
-
- // Dispose of old KeyExchange object as it is no longer needed.
- if (this._keyExchange != null)
- {
- this._keyExchange.HostKeyReceived -= KeyExchange_HostKeyReceived;
- this._keyExchange.Dispose();
- this._keyExchange = null;
- }
-
- // Enable all active registered messages
- foreach (var messageMetadata in this._messagesMetadata)
- {
- if (messageMetadata.Activated == true)
- messageMetadata.Enabled = true;
- }
-
- if (this.NewKeysReceived != null)
- {
- this.NewKeysReceived(this, new MessageEventArgs(message));
- }
-
- // Signal that key exchange completed
- this._keyExchangeCompletedWaitHandle.Set();
-
- this._keyExchangeInProgress = false;
- }
-
- ///
- /// Called when message received.
- ///
- /// message.
- protected virtual void OnUserAuthenticationRequestReceived(RequestMessage message)
- {
- if (this.UserAuthenticationRequestReceived != null)
- {
- this.UserAuthenticationRequestReceived(this, new MessageEventArgs(message));
- }
- }
-
- ///
- /// Called when message received.
- ///
- /// message.
- protected virtual void OnUserAuthenticationFailureReceived(FailureMessage message)
- {
- if (this.UserAuthenticationFailureReceived != null)
- {
- this.UserAuthenticationFailureReceived(this, new MessageEventArgs(message));
- }
- }
-
- ///
- /// Called when message received.
- ///
- /// message.
- protected virtual void OnUserAuthenticationSuccessReceived(SuccessMessage message)
- {
- if (this.UserAuthenticationSuccessReceived != null)
- {
- this.UserAuthenticationSuccessReceived(this, new MessageEventArgs(message));
- }
- }
-
- ///
- /// Called when message received.
- ///
- /// message.
- protected virtual void OnUserAuthenticationBannerReceived(BannerMessage message)
- {
- if (this.UserAuthenticationBannerReceived != null)
- {
- this.UserAuthenticationBannerReceived(this, new MessageEventArgs(message));
- }
- }
-
- ///
- /// Called when message received.
- ///
- /// message.
- protected virtual void OnGlobalRequestReceived(GlobalRequestMessage message)
- {
- if (this.GlobalRequestReceived != null)
- {
- this.GlobalRequestReceived(this, new MessageEventArgs(message));
- }
- }
-
- ///
- /// Called when message received.
- ///
- /// message.
- protected virtual void OnRequestSuccessReceived(RequestSuccessMessage message)
- {
- if (this.RequestSuccessReceived != null)
- {
- this.RequestSuccessReceived(this, new MessageEventArgs(message));
- }
- }
-
- ///
- /// Called when message received.
- ///
- /// message.
- protected virtual void OnRequestFailureReceived(RequestFailureMessage message)
- {
- if (this.RequestFailureReceived != null)
- {
- this.RequestFailureReceived(this, new MessageEventArgs(message));
- }
- }
-
- ///
- /// Called when message received.
- ///
- /// message.
- protected virtual void OnChannelOpenReceived(ChannelOpenMessage message)
- {
- if (this.ChannelOpenReceived != null)
- {
- this.ChannelOpenReceived(this, new MessageEventArgs(message));
- }
- }
-
- ///
- /// Called when message received.
- ///
- /// message.
- protected virtual void OnChannelOpenConfirmationReceived(ChannelOpenConfirmationMessage message)
- {
- if (this.ChannelOpenConfirmationReceived != null)
- {
- this.ChannelOpenConfirmationReceived(this, new MessageEventArgs(message));
- }
- }
-
- ///
- /// Called when message received.
- ///
- /// message.
- protected virtual void OnChannelOpenFailureReceived(ChannelOpenFailureMessage message)
- {
- if (this.ChannelOpenFailureReceived != null)
- {
- this.ChannelOpenFailureReceived(this, new MessageEventArgs(message));
- }
- }
-
- ///
- /// Called when message received.
- ///
- /// message.
- protected virtual void OnChannelWindowAdjustReceived(ChannelWindowAdjustMessage message)
- {
- if (this.ChannelWindowAdjustReceived != null)
- {
- this.ChannelWindowAdjustReceived(this, new MessageEventArgs(message));
- }
- }
-
- ///
- /// Called when message received.
- ///
- /// message.
- protected virtual void OnChannelDataReceived(ChannelDataMessage message)
- {
- if (this.ChannelDataReceived != null)
- {
- this.ChannelDataReceived(this, new MessageEventArgs(message));
- }
- }
-
- ///
- /// Called when message received.
- ///
- /// message.
- protected virtual void OnChannelExtendedDataReceived(ChannelExtendedDataMessage message)
- {
- if (this.ChannelExtendedDataReceived != null)
- {
- this.ChannelExtendedDataReceived(this, new MessageEventArgs(message));
- }
- }
-
- ///
- /// Called when message received.
- ///
- /// message.
- protected virtual void OnChannelEofReceived(ChannelEofMessage message)
- {
- if (this.ChannelEofReceived != null)
- {
- this.ChannelEofReceived(this, new MessageEventArgs(message));
- }
- }
-
- ///
- /// Called when message received.
- ///
- /// message.
- protected virtual void OnChannelCloseReceived(ChannelCloseMessage message)
- {
- if (this.ChannelCloseReceived != null)
- {
- this.ChannelCloseReceived(this, new MessageEventArgs(message));
- }
- }
-
- ///
- /// Called when message received.
- ///
- /// message.
- protected virtual void OnChannelRequestReceived(ChannelRequestMessage message)
- {
- if (this.ChannelRequestReceived != null)
- {
- this.ChannelRequestReceived(this, new MessageEventArgs(message));
- }
- }
-
- ///
- /// Called when message received.
- ///
- /// message.
- protected virtual void OnChannelSuccessReceived(ChannelSuccessMessage message)
- {
- if (this.ChannelSuccessReceived != null)
- {
- this.ChannelSuccessReceived(this, new MessageEventArgs(message));
- }
- }
-
- ///
- /// Called when message received.
- ///
- /// message.
- protected virtual void OnChannelFailureReceived(ChannelFailureMessage message)
- {
- if (this.ChannelFailureReceived != null)
- {
- this.ChannelFailureReceived(this, new MessageEventArgs(message));
- }
- }
-
- ///
- /// Called when message received.
- ///
- /// message.
- protected virtual void OnMessageReceived(Message message)
- {
- if (this.MessageReceived != null)
- {
- this.MessageReceived(this, new MessageEventArgs(message));
- }
- }
-
- #endregion
-
- private void KeyExchange_HostKeyReceived(object sender, HostKeyEventArgs e)
- {
- var handler = this.HostKeyReceived;
- if (handler != null)
- {
- handler(this, e);
- }
- }
-
- ///
- /// Reads the specified length of bytes from the server
- ///
- /// The length.
- ///
- private byte[] Read(int length)
- {
- byte[] buffer = new byte[length];
-
- this.SocketRead(length, ref buffer);
-
- return buffer;
- }
-
- #region Message loading functions
-
- ///
- /// Registers SSH Message with the session.
- ///
- /// Name of the message.
- public void RegisterMessage(string messageName)
- {
- this.InternalRegisterMessage(messageName);
- }
-
- ///
- /// Removes SSH message from the session
- ///
- /// Name of the message.
- public void UnRegisterMessage(string messageName)
- {
- this.InternalUnRegisterMessage(messageName);
- }
-
- ///
- /// Loads the message.
- ///
- /// Message data.
- /// New message
- private Message LoadMessage(byte[] data)
- {
- var messageType = data[0];
- var messageMetadata = (from m in this._messagesMetadata where m.Number == messageType && m.Enabled && m.Activated select m).SingleOrDefault();
-
- if (messageMetadata == null)
- throw new SshException(string.Format(CultureInfo.CurrentCulture, "Message type {0} is not valid.", messageType));
-
- var message = messageMetadata.Type.CreateInstance();
-
- message.Load(data);
-
- this.Log(string.Format("ReceiveMessage from server: '{0}': '{1}'.", message.GetType().Name, message.ToString()));
-
- return message;
- }
-
- partial void InternalRegisterMessage(string messageName);
-
- partial void InternalUnRegisterMessage(string messageName);
-
- #endregion
-
- partial void ExecuteThread(Action action);
-
- partial void IsSocketConnected(ref bool isConnected);
-
- partial void SocketConnect(string host, int port);
-
- partial void SocketDisconnect();
-
- partial void SocketRead(int length, ref byte[] buffer);
-
- partial void SocketReadLine(ref string response);
-
- partial void Log(string text);
-
- ///
- /// Writes the specified data to the server.
- ///
- /// The data.
- partial void SocketWrite(byte[] data);
-
- ///
- /// Listens for incoming message from the server and handles them. This method run as a task on separate thread.
- ///
- private void MessageListener()
- {
- try
- {
- while (this._socket != null && this._socket.Connected)
- {
- var message = this.ReceiveMessage();
-
- if (message == null)
- {
- throw new NullReferenceException("The 'message' variable cannot be null");
- }
-
- this.HandleMessageCore(message);
- }
- }
- catch (Exception exp)
- {
- this.RaiseError(exp);
- }
- }
-
- private byte SocketReadByte()
- {
- byte[] buffer = new byte[1];
-
- this.SocketRead(1, ref buffer);
-
- return buffer[0];
- }
-
- private void SocketWriteByte(byte data)
- {
- this.SocketWrite(new byte[] { data });
- }
-
- private void ConnectSocks4()
- {
- // Send socks version number
- this.SocketWriteByte(0x04);
-
- // Send command code
- this.SocketWriteByte(0x01);
-
- // Send port
- this.SocketWriteByte((byte)(this.ConnectionInfo.Port / 0xFF));
- this.SocketWriteByte((byte)(this.ConnectionInfo.Port % 0xFF));
-
- // Send IP
- IPAddress ipAddress = this.ConnectionInfo.Host.GetIPAddress();
- this.SocketWrite(ipAddress.GetAddressBytes());
-
- // Send username
- var username = new Renci.SshNet.Common.ASCIIEncoding().GetBytes(this.ConnectionInfo.ProxyUsername);
- this.SocketWrite(username);
- this.SocketWriteByte(0x00);
-
- // Read 0
- if (this.SocketReadByte() != 0)
- {
- throw new ProxyException("SOCKS4: Null is expected.");
- }
-
- // Read response code
- var code = this.SocketReadByte();
-
- switch (code)
- {
- case 0x5a:
- break;
- case 0x5b:
- throw new ProxyException("SOCKS4: Connection rejected.");
- case 0x5c:
- throw new ProxyException("SOCKS4: Client is not running identd or not reachable from the server.");
- case 0x5d:
- throw new ProxyException("SOCKS4: Client's identd could not confirm the user ID string in the request.");
- default:
- throw new ProxyException("SOCKS4: Not valid response.");
- }
-
- byte[] dummyBuffer = new byte[4];
-
- // Read 2 bytes to be ignored
- this.SocketRead(2, ref dummyBuffer);
-
- // Read 4 bytes to be ignored
- this.SocketRead(4, ref dummyBuffer);
- }
-
- private void ConnectSocks5()
- {
- // Send socks version number
- this.SocketWriteByte(0x05);
-
- // Send number of supported authentication methods
- this.SocketWriteByte(0x02);
-
- // Send supported authentication methods
- this.SocketWriteByte(0x00); // No authentication
- this.SocketWriteByte(0x02); // Username/Password
-
- var socksVersion = this.SocketReadByte();
- if (socksVersion != 0x05)
- throw new ProxyException(string.Format("SOCKS Version '{0}' is not supported.", socksVersion));
-
- var authenticationMethod = this.SocketReadByte();
- switch (authenticationMethod)
- {
- case 0x00:
- break;
- case 0x02:
-
- // Send version
- this.SocketWriteByte(0x01);
-
- var encoding = new Renci.SshNet.Common.ASCIIEncoding();
-
- var username = encoding.GetBytes(this.ConnectionInfo.ProxyUsername);
-
- if (username.Length > byte.MaxValue)
- throw new ProxyException("Proxy username is too long.");
-
- // Send username length
- this.SocketWriteByte((byte)username.Length);
-
- // Send username
- this.SocketWrite(username);
-
- var password = encoding.GetBytes(this.ConnectionInfo.ProxyPassword);
-
- if (password.Length > byte.MaxValue)
- throw new ProxyException("Proxy password is too long.");
-
- // Send username length
- this.SocketWriteByte((byte)password.Length);
-
- // Send username
- this.SocketWrite(password);
-
- var serverVersion = this.SocketReadByte();
-
- if (serverVersion != 1)
- throw new ProxyException("SOCKS5: Server authentication version is not valid.");
-
- var statusCode = this.SocketReadByte();
- if (statusCode != 0)
- throw new ProxyException("SOCKS5: Username/Password authentication failed.");
-
- break;
- case 0xFF:
- throw new ProxyException("SOCKS5: No acceptable authentication methods were offered.");
- default:
- break;
- }
-
- // Send socks version number
- this.SocketWriteByte(0x05);
-
- // Send command code
- this.SocketWriteByte(0x01); // establish a TCP/IP stream connection
-
- // Send reserved, must be 0x00
- this.SocketWriteByte(0x00);
-
- IPAddress ip = this.ConnectionInfo.Host.GetIPAddress();
-
- // Send address type and address
- if (ip.AddressFamily == AddressFamily.InterNetwork)
- {
- this.SocketWriteByte(0x01);
- var address = ip.GetAddressBytes();
- this.SocketWrite(address);
- }
- else if (ip.AddressFamily == AddressFamily.InterNetworkV6)
- {
- this.SocketWriteByte(0x04);
- var address = ip.GetAddressBytes();
- this.SocketWrite(address);
- }
- else
- {
- throw new ProxyException(string.Format("SOCKS5: IP address '{0}' is not supported.", ip));
- }
-
- // Send port
- this.SocketWriteByte((byte)(this.ConnectionInfo.Port / 0xFF));
- this.SocketWriteByte((byte)(this.ConnectionInfo.Port % 0xFF));
-
- // Read Server SOCKS5 version
- if (this.SocketReadByte() != 5)
- {
- throw new ProxyException("SOCKS5: Version 5 is expected.");
- }
-
- // Read response code
- var status = this.SocketReadByte();
-
- switch (status)
- {
- case 0x00:
- break;
- case 0x01:
- throw new ProxyException("SOCKS5: General failure.");
- case 0x02:
- throw new ProxyException("SOCKS5: Connection not allowed by ruleset.");
- case 0x03:
- throw new ProxyException("SOCKS5: Network unreachable.");
- case 0x04:
- throw new ProxyException("SOCKS5: Host unreachable.");
- case 0x05:
- throw new ProxyException("SOCKS5: Connection refused by destination host.");
- case 0x06:
- throw new ProxyException("SOCKS5: TTL expired.");
- case 0x07:
- throw new ProxyException("SOCKS5: Command not supported or protocol error.");
- case 0x08:
- throw new ProxyException("SOCKS5: Address type not supported.");
- default:
- throw new ProxyException("SOCKS4: Not valid response.");
- }
-
- // Read 0
- if (this.SocketReadByte() != 0)
- {
- throw new ProxyException("SOCKS5: 0 byte is expected.");
- }
-
- var addressType = this.SocketReadByte();
- byte[] responseIp = new byte[16];
-
- switch (addressType)
- {
- case 0x01:
- this.SocketRead(4, ref responseIp);
- break;
- case 0x04:
- this.SocketRead(16, ref responseIp);
- break;
- default:
- throw new ProxyException(string.Format("Address type '{0}' is not supported.", addressType));
- }
-
- byte[] port = new byte[2];
-
- // Read 2 bytes to be ignored
- this.SocketRead(2, ref port);
-
- }
-
- private void ConnectHttp()
- {
- var httpResponseRe = new Regex(@"HTTP/(?\d[.]\d) (?\d{3}) (?.+)$");
- var httpHeaderRe = new Regex(@"(?[^\[\]()<>@,;:\""/?={} \t]+):(?.+)?");
-
- var encoding = new Renci.SshNet.Common.ASCIIEncoding();
-
- this.SocketWrite(encoding.GetBytes(string.Format("CONNECT {0}:{1} HTTP/1.0\r\n", this.ConnectionInfo.Host, this.ConnectionInfo.Port)));
-
- // Sent proxy authorization is specified
- if (!string.IsNullOrEmpty(this.ConnectionInfo.ProxyUsername))
- {
- var authorization = string.Format("Proxy-Authorization: Basic {0}\r\n",
- Convert.ToBase64String(encoding.GetBytes(string.Format("{0}:{1}", this.ConnectionInfo.ProxyUsername, this.ConnectionInfo.ProxyPassword)))
- );
- this.SocketWrite(encoding.GetBytes(authorization));
- }
-
- this.SocketWrite(encoding.GetBytes("\r\n"));
-
- HttpStatusCode statusCode = HttpStatusCode.OK;
- var response = string.Empty;
- var contentLength = 0;
-
- while (true)
- {
- this.SocketReadLine(ref response);
-
- var match = httpResponseRe.Match(response);
-
- if (match.Success)
- {
- statusCode = (HttpStatusCode)int.Parse(match.Result("${statusCode}"));
- continue;
- }
-
- // continue on parsing message headers coming from the server
- match = httpHeaderRe.Match(response);
- if (match.Success)
- {
- var fieldName = match.Result("${fieldName}");
- if (fieldName.Equals("Content-Length", StringComparison.InvariantCultureIgnoreCase))
- {
- contentLength = int.Parse(match.Result("${fieldValue}"));
- }
- continue;
- }
-
- // Read response body if specified
- if (string.IsNullOrEmpty(response) && contentLength > 0)
- {
- var contentBody = new byte[contentLength];
- this.SocketRead(contentLength, ref contentBody);
- }
-
- switch (statusCode)
- {
- case HttpStatusCode.OK:
- break;
- default:
- throw new ProxyException(string.Format("HTTP: Status code {0}, \"{1}\"", statusCode, statusCode));
- }
- }
- }
-
- ///
- /// Raises the event.
- ///
- /// The exp.
- private void RaiseError(Exception exp)
- {
- var connectionException = exp as SshConnectionException;
-
- // If connection exception was raised while isDisconnecting is true then this is expected
- // case and should be ignore
- if (connectionException != null && this._isDisconnecting)
- return;
-
- this._exception = exp;
-
- this._exceptionWaitHandle.Set();
-
- if (this.ErrorOccured != null)
- {
- this.ErrorOccured(this, new ExceptionEventArgs(exp));
- }
-
- if (connectionException != null && connectionException.DisconnectReason != DisconnectReason.ConnectionLost)
- {
- this.SendDisconnect(connectionException.DisconnectReason, exp.ToString());
- }
- }
-
- #region IDisposable Members
-
- private bool _disposed = false;
-
- ///
- /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged ResourceMessages.
- ///
- public void Dispose()
- {
- Dispose(true);
-
- GC.SuppressFinalize(this);
- }
-
- ///
- /// Releases unmanaged and - optionally - managed resources
- ///
- /// true to release both managed and unmanaged resources; false to release only unmanaged ResourceMessages.
- protected virtual void Dispose(bool disposing)
- {
- // Check to see if Dispose has already been called.
- if (!this._disposed)
- {
- // If disposing equals true, dispose all managed
- // and unmanaged ResourceMessages.
- if (disposing)
- {
-
- if (this._socket != null)
- {
- this._socket.Dispose();
- this._socket = null;
- }
-
- if (this._messageListenerCompleted != null)
- {
- // Wait for socket to be closed and for task to complete before disposing a task
- this._messageListenerCompleted.WaitOne();
- this._messageListenerCompleted.Dispose();
- this._messageListenerCompleted = null;
- }
-
- if (this._serviceAccepted != null)
- {
- this._serviceAccepted.Dispose();
- this._serviceAccepted = null;
- }
-
- if (this._exceptionWaitHandle != null)
- {
- this._exceptionWaitHandle.Dispose();
- this._exceptionWaitHandle = null;
- }
-
- if (this._keyExchangeCompletedWaitHandle != null)
- {
- this._keyExchangeCompletedWaitHandle.Dispose();
- this._keyExchangeCompletedWaitHandle = null;
- }
-
- if (this._serverMac != null)
- {
- this._serverMac.Clear();
- this._serverMac = null;
- }
-
- if (this._clientMac != null)
- {
- this._clientMac.Clear();
- this._clientMac = null;
- }
-
- if (this._keyExchange != null)
- {
- this._keyExchange.HostKeyReceived -= KeyExchange_HostKeyReceived;
- this._keyExchange.Dispose();
- this._keyExchange = null;
- }
- }
-
- // Note disposing has been done.
- this._disposed = true;
- }
- }
-
- ///
- /// Releases unmanaged resources and performs other cleanup operations before the
- /// is reclaimed by garbage collection.
- ///
- ~Session()
- {
- // Do not re-create Dispose clean-up code here.
- // Calling Dispose(false) is optimal in terms of
- // readability and maintainability.
- Dispose(false);
- }
-
- #endregion
-
- private class MessageMetadata
- {
- public string Name { get; set; }
-
- public byte Number { get; set; }
-
- public bool Enabled { get; set; }
-
- public bool Activated { get; set; }
-
- public Type Type { get; set; }
- }
- }
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Net.Sockets;
+using System.Security.Cryptography;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading;
+using Renci.SshNet.Channels;
+using Renci.SshNet.Common;
+using Renci.SshNet.Compression;
+using Renci.SshNet.Messages;
+using Renci.SshNet.Messages.Authentication;
+using Renci.SshNet.Messages.Connection;
+using Renci.SshNet.Messages.Transport;
+using Renci.SshNet.Security;
+using System.Globalization;
+using Renci.SshNet.Security.Cryptography;
+
+namespace Renci.SshNet
+{
+ ///
+ /// Provides functionality to connect and interact with SSH server.
+ ///
+ public partial class Session : IDisposable
+ {
+ ///
+ /// Specifies maximum packet size defined by the protocol.
+ ///
+ private const int MaximumSshPacketSize = LocalChannelDataPacketSize + 3000;
+
+ ///
+ /// Holds the initial local window size for the channels.
+ ///
+ ///
+ /// 2 MB.
+ ///
+ private const int InitialLocalWindowSize = LocalChannelDataPacketSize * 32;
+
+ ///
+ /// Holds the maximum size of channel data packets that we receive.
+ ///
+ ///
+ /// 64 KB.
+ ///
+ private const int LocalChannelDataPacketSize = 1024*64;
+
+ private static readonly RNGCryptoServiceProvider Randomizer = new RNGCryptoServiceProvider();
+
+#if SILVERLIGHT
+ private static readonly Regex ServerVersionRe = new Regex("^SSH-(?[^-]+)-(?.+)( SP.+)?$");
+#else
+ private static readonly Regex ServerVersionRe = new Regex("^SSH-(?[^-]+)-(?.+)( SP.+)?$", RegexOptions.Compiled);
+#endif
+
+ ///
+ /// Controls how many authentication attempts can take place at the same time.
+ ///
+ ///
+ /// Some server may restrict number to prevent authentication attacks
+ ///
+ private static readonly SemaphoreLight AuthenticationConnection = new SemaphoreLight(3);
+
+ ///
+ /// Holds metada about session messages
+ ///
+ private IEnumerable _messagesMetadata;
+
+ ///
+ /// Holds connection socket.
+ ///
+ private Socket _socket;
+
+ ///
+ /// Holds locker object for the socket
+ ///
+ private readonly object _socketLock = new object();
+
+ ///
+ /// Holds reference to task that listens for incoming messages
+ ///
+ private EventWaitHandle _messageListenerCompleted;
+
+ ///
+ /// Specifies outbound packet number
+ ///
+ private volatile UInt32 _outboundPacketSequence;
+
+ ///
+ /// Specifies incoming packet number
+ ///
+ private UInt32 _inboundPacketSequence;
+
+ ///
+ /// WaitHandle to signal that last service request was accepted
+ ///
+ private EventWaitHandle _serviceAccepted = new AutoResetEvent(false);
+
+ ///
+ /// WaitHandle to signal that exception was thrown by another thread.
+ ///
+ private EventWaitHandle _exceptionWaitHandle = new ManualResetEvent(false);
+
+ ///
+ /// WaitHandle to signal that key exchange was completed.
+ ///
+ private EventWaitHandle _keyExchangeCompletedWaitHandle = new ManualResetEvent(false);
+
+ ///
+ /// WaitHandle to signal that key exchange is in progress.
+ ///
+ private bool _keyExchangeInProgress;
+
+ ///
+ /// Exception that need to be thrown by waiting thread
+ ///
+ private Exception _exception;
+
+ ///
+ /// Specifies whether connection is authenticated
+ ///
+ private bool _isAuthenticated;
+
+ ///
+ /// Specifies whether user issued Disconnect command or not
+ ///
+ private bool _isDisconnecting;
+
+ private KeyExchange _keyExchange;
+
+ private HashAlgorithm _serverMac;
+
+ private HashAlgorithm _clientMac;
+
+ private Cipher _clientCipher;
+
+ private Cipher _serverCipher;
+
+ private Compressor _serverDecompression;
+
+ private Compressor _clientCompression;
+
+ private SemaphoreLight _sessionSemaphore;
+
+ ///
+ /// Gets the session semaphore that controls session channels.
+ ///
+ /// The session semaphore.
+ public SemaphoreLight SessionSemaphore
+ {
+ get
+ {
+ if (this._sessionSemaphore == null)
+ {
+ lock (this)
+ {
+ if (this._sessionSemaphore == null)
+ {
+ this._sessionSemaphore = new SemaphoreLight(this.ConnectionInfo.MaxSessions);
+ }
+ }
+ }
+
+ return this._sessionSemaphore;
+ }
+ }
+
+ private bool _isDisconnectMessageSent;
+
+ private uint _nextChannelNumber;
+ ///
+ /// Gets the next channel number.
+ ///
+ /// The next channel number.
+ internal uint NextChannelNumber
+ {
+ get
+ {
+ uint result;
+
+ lock (this)
+ {
+ result = this._nextChannelNumber++;
+ }
+
+ return result;
+ }
+ }
+
+ ///
+ /// Gets a value indicating whether the session is connected.
+ ///
+ ///
+ /// true if the session is connected; otherwise, false.
+ ///
+ ///
+ /// This methods returns true in all but the following cases:
+ ///
+ /// -
+ /// The SSH_MSG_DISCONNECT message - which is used to disconnect from the server - has been sent.
+ ///
+ /// -
+ /// The client has not been authenticated successfully.
+ ///
+ /// -
+ /// The listener thread - which is used to receive messages from the server - has stopped.
+ ///
+ /// -
+ /// The socket used to communicate with the server is no longer connected.
+ ///
+ ///
+ ///
+ public bool IsConnected
+ {
+ get
+ {
+ if (_isDisconnectMessageSent || !this._isAuthenticated)
+ return false;
+ if (_messageListenerCompleted == null || _messageListenerCompleted.WaitOne(0))
+ return false;
+
+ var isSocketConnected = false;
+ IsSocketConnected(ref isSocketConnected);
+ return isSocketConnected;
+ }
+ }
+
+ ///
+ /// Gets the session id.
+ ///
+ ///
+ /// The session id, or null if the client has not been authenticated.
+ ///
+ public byte[] SessionId { get; private set; }
+
+ private Message _clientInitMessage;
+ ///
+ /// Gets the client init message.
+ ///
+ /// The client init message.
+ public Message ClientInitMessage
+ {
+ get
+ {
+ if (this._clientInitMessage == null)
+ {
+ this._clientInitMessage = new KeyExchangeInitMessage
+ {
+ KeyExchangeAlgorithms = this.ConnectionInfo.KeyExchangeAlgorithms.Keys.ToArray(),
+ ServerHostKeyAlgorithms = this.ConnectionInfo.HostKeyAlgorithms.Keys.ToArray(),
+ EncryptionAlgorithmsClientToServer = this.ConnectionInfo.Encryptions.Keys.ToArray(),
+ EncryptionAlgorithmsServerToClient = this.ConnectionInfo.Encryptions.Keys.ToArray(),
+ MacAlgorithmsClientToServer = this.ConnectionInfo.HmacAlgorithms.Keys.ToArray(),
+ MacAlgorithmsServerToClient = this.ConnectionInfo.HmacAlgorithms.Keys.ToArray(),
+ CompressionAlgorithmsClientToServer = this.ConnectionInfo.CompressionAlgorithms.Keys.ToArray(),
+ CompressionAlgorithmsServerToClient = this.ConnectionInfo.CompressionAlgorithms.Keys.ToArray(),
+ LanguagesClientToServer = new[] {string.Empty},
+ LanguagesServerToClient = new[] {string.Empty},
+ FirstKexPacketFollows = false,
+ Reserved = 0
+ };
+ }
+ return this._clientInitMessage;
+ }
+ }
+
+ ///
+ /// Gets or sets the server version string.
+ ///
+ /// The server version.
+ public string ServerVersion { get; private set; }
+
+ ///
+ /// Gets or sets the client version string.
+ ///
+ /// The client version.
+ public string ClientVersion { get; private set; }
+
+ ///
+ /// Gets or sets the connection info.
+ ///
+ /// The connection info.
+ public ConnectionInfo ConnectionInfo { get; private set; }
+
+ ///
+ /// Occurs when an error occurred.
+ ///
+ public event EventHandler ErrorOccured;
+
+ ///
+ /// Occurs when session has been disconnected form the server.
+ ///
+ public event EventHandler Disconnected;
+
+ ///
+ /// Occurs when host key received.
+ ///
+ public event EventHandler HostKeyReceived;
+
+ #region Message events
+
+ ///
+ /// Occurs when message received
+ ///
+ internal event EventHandler> DisconnectReceived;
+
+ ///
+ /// Occurs when message received
+ ///
+ internal event EventHandler> IgnoreReceived;
+
+ ///
+ /// Occurs when message received
+ ///
+ internal event EventHandler> UnimplementedReceived;
+
+ ///
+ /// Occurs when message received
+ ///
+ internal event EventHandler> DebugReceived;
+
+ ///
+ /// Occurs when message received
+ ///
+ internal event EventHandler> ServiceRequestReceived;
+
+ ///
+ /// Occurs when message received
+ ///
+ internal event EventHandler> ServiceAcceptReceived;
+
+ ///
+ /// Occurs when message received
+ ///
+ internal event EventHandler> KeyExchangeInitReceived;
+
+ ///
+ /// Occurs when message received
+ ///
+ internal event EventHandler> NewKeysReceived;
+
+ ///
+ /// Occurs when message received
+ ///
+ internal event EventHandler> UserAuthenticationRequestReceived;
+
+ ///
+ /// Occurs when message received
+ ///
+ internal event EventHandler> UserAuthenticationFailureReceived;
+
+ ///
+ /// Occurs when message received
+ ///
+ internal event EventHandler> UserAuthenticationSuccessReceived;
+
+ ///
+ /// Occurs when message received
+ ///
+ internal event EventHandler> UserAuthenticationBannerReceived;
+
+ ///
+ /// Occurs when message received
+ ///
+ internal event EventHandler> GlobalRequestReceived;
+
+ ///
+ /// Occurs when message received
+ ///
+ internal event EventHandler> RequestSuccessReceived;
+
+ ///
+ /// Occurs when message received
+ ///
+ internal event EventHandler> RequestFailureReceived;
+
+ ///
+ /// Occurs when message received
+ ///
+ internal event EventHandler> ChannelOpenReceived;
+
+ ///
+ /// Occurs when message received
+ ///
+ internal event EventHandler> ChannelOpenConfirmationReceived;
+
+ ///
+ /// Occurs when message received
+ ///
+ internal event EventHandler> ChannelOpenFailureReceived;
+
+ ///
+ /// Occurs when message received
+ ///
+ internal event EventHandler> ChannelWindowAdjustReceived;
+
+ ///
+ /// Occurs when message received
+ ///
+ internal event EventHandler> ChannelDataReceived;
+
+ ///
+ /// Occurs when message received
+ ///
+ internal event EventHandler> ChannelExtendedDataReceived;
+
+ ///
+ /// Occurs when message received
+ ///
+ internal event EventHandler> ChannelEofReceived;
+
+ ///
+ /// Occurs when message received
+ ///
+ internal event EventHandler> ChannelCloseReceived;
+
+ ///
+ /// Occurs when message received
+ ///
+ internal event EventHandler> ChannelRequestReceived;
+
+ ///
+ /// Occurs when message received
+ ///
+ internal event EventHandler> ChannelSuccessReceived;
+
+ ///
+ /// Occurs when message received
+ ///
+ internal event EventHandler> ChannelFailureReceived;
+
+ ///
+ /// Occurs when message received and is not handled by any of the event handlers
+ ///
+ internal event EventHandler> MessageReceived;
+
+ #endregion
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The connection info.
+ /// is null.
+ internal Session(ConnectionInfo connectionInfo)
+ {
+ if (connectionInfo == null)
+ throw new ArgumentNullException("connectionInfo");
+
+ this.ConnectionInfo = connectionInfo;
+ //this.ClientVersion = string.Format(CultureInfo.CurrentCulture, "SSH-2.0-Renci.SshNet.SshClient.{0}", this.GetType().Assembly.GetName().Version);
+ this.ClientVersion = string.Format(CultureInfo.CurrentCulture, "SSH-2.0-Renci.SshNet.SshClient.0.0.1");
+ }
+
+ ///
+ /// Connects to the server.
+ ///
+ public void Connect()
+ {
+ if (this.IsConnected)
+ return;
+
+ try
+ {
+ AuthenticationConnection.Wait();
+
+ if (this.IsConnected)
+ return;
+
+ lock (this)
+ {
+ // If connected don't connect again
+ if (this.IsConnected)
+ return;
+
+ // reset connection specific information
+ Reset();
+
+ // Build list of available messages while connecting
+ this._messagesMetadata = GetMessagesMetadata();
+
+ switch (this.ConnectionInfo.ProxyType)
+ {
+ case ProxyTypes.None:
+ this.SocketConnect(this.ConnectionInfo.Host, this.ConnectionInfo.Port);
+ break;
+ case ProxyTypes.Socks4:
+ this.SocketConnect(this.ConnectionInfo.ProxyHost, this.ConnectionInfo.ProxyPort);
+ this.ConnectSocks4();
+ break;
+ case ProxyTypes.Socks5:
+ this.SocketConnect(this.ConnectionInfo.ProxyHost, this.ConnectionInfo.ProxyPort);
+ this.ConnectSocks5();
+ break;
+ case ProxyTypes.Http:
+ this.SocketConnect(this.ConnectionInfo.ProxyHost, this.ConnectionInfo.ProxyPort);
+ this.ConnectHttp();
+ break;
+ }
+
+ Match versionMatch;
+
+ // Get server version from the server,
+ // ignore text lines which are sent before if any
+ while (true)
+ {
+ string serverVersion = string.Empty;
+ this.SocketReadLine(ref serverVersion);
+
+ this.ServerVersion = serverVersion;
+ if (string.IsNullOrEmpty(this.ServerVersion))
+ {
+ throw new InvalidOperationException("Server string is null or empty.");
+ }
+
+ versionMatch = ServerVersionRe.Match(this.ServerVersion);
+
+ if (versionMatch.Success)
+ {
+ break;
+ }
+ }
+
+ // Set connection versions
+ this.ConnectionInfo.ServerVersion = this.ServerVersion;
+ this.ConnectionInfo.ClientVersion = this.ClientVersion;
+
+ // Get server SSH version
+ var version = versionMatch.Result("${protoversion}");
+
+ var softwareName = versionMatch.Result("${softwareversion}");
+
+ this.Log(string.Format("Server version '{0}' on '{1}'.", version, softwareName));
+
+ if (!(version.Equals("2.0") || version.Equals("1.99")))
+ {
+ throw new SshConnectionException(string.Format(CultureInfo.CurrentCulture, "Server version '{0}' is not supported.", version), DisconnectReason.ProtocolVersionNotSupported);
+ }
+
+ this.SocketWrite(Encoding.UTF8.GetBytes(string.Format(CultureInfo.InvariantCulture, "{0}\x0D\x0A", this.ClientVersion)));
+
+ // Register Transport response messages
+ this.RegisterMessage("SSH_MSG_DISCONNECT");
+ this.RegisterMessage("SSH_MSG_IGNORE");
+ this.RegisterMessage("SSH_MSG_UNIMPLEMENTED");
+ this.RegisterMessage("SSH_MSG_DEBUG");
+ this.RegisterMessage("SSH_MSG_SERVICE_ACCEPT");
+ this.RegisterMessage("SSH_MSG_KEXINIT");
+ this.RegisterMessage("SSH_MSG_NEWKEYS");
+
+ // Some server implementations might sent this message first, prior establishing encryption algorithm
+ this.RegisterMessage("SSH_MSG_USERAUTH_BANNER");
+
+ // Start incoming request listener
+ this._messageListenerCompleted = new ManualResetEvent(false);
+
+ this.ExecuteThread(() =>
+ {
+ try
+ {
+ this.MessageListener();
+ }
+ finally
+ {
+ this._messageListenerCompleted.Set();
+ }
+ });
+
+ // Wait for key exchange to be completed
+ this.WaitOnHandle(this._keyExchangeCompletedWaitHandle);
+
+ // If sessionId is not set then its not connected
+ if (this.SessionId == null)
+ {
+ this.Disconnect();
+ return;
+ }
+
+ // Request user authorization service
+ this.SendMessage(new ServiceRequestMessage(ServiceName.UserAuthentication));
+
+ // Wait for service to be accepted
+ this.WaitOnHandle(this._serviceAccepted);
+
+ if (string.IsNullOrEmpty(this.ConnectionInfo.Username))
+ {
+ throw new SshException("Username is not specified.");
+ }
+
+ this.ConnectionInfo.Authenticate(this);
+ this._isAuthenticated = true;
+
+ // Register Connection messages
+ this.RegisterMessage("SSH_MSG_GLOBAL_REQUEST");
+ this.RegisterMessage("SSH_MSG_REQUEST_SUCCESS");
+ this.RegisterMessage("SSH_MSG_REQUEST_FAILURE");
+ this.RegisterMessage("SSH_MSG_CHANNEL_OPEN_CONFIRMATION");
+ this.RegisterMessage("SSH_MSG_CHANNEL_OPEN_FAILURE");
+ this.RegisterMessage("SSH_MSG_CHANNEL_WINDOW_ADJUST");
+ this.RegisterMessage("SSH_MSG_CHANNEL_EXTENDED_DATA");
+ this.RegisterMessage("SSH_MSG_CHANNEL_REQUEST");
+ this.RegisterMessage("SSH_MSG_CHANNEL_SUCCESS");
+ this.RegisterMessage("SSH_MSG_CHANNEL_FAILURE");
+ this.RegisterMessage("SSH_MSG_CHANNEL_DATA");
+ this.RegisterMessage("SSH_MSG_CHANNEL_EOF");
+ this.RegisterMessage("SSH_MSG_CHANNEL_CLOSE");
+
+ Monitor.Pulse(this);
+ }
+ }
+ finally
+ {
+ AuthenticationConnection.Release();
+ }
+ }
+
+ ///
+ /// Disconnects from the server.
+ ///
+ ///
+ /// This sends a SSH_MSG_DISCONNECT message to the server, waits for the
+ /// server to close the socket on its end and subsequently closes the client socket.
+ ///
+ public void Disconnect()
+ {
+ Disconnect(DisconnectReason.ByApplication, "Connection terminated by the client.");
+ }
+
+ private void Disconnect(DisconnectReason reason, string message)
+ {
+ this._isDisconnecting = true;
+
+ // send disconnect message to the server if the connection is still open
+ // and the disconnect message has not yet been sent
+ //
+ // note that this should also cause the listener thread to be stopped as
+ // the server should respond by closing the socket
+ SendDisconnect(reason, message);
+
+ // disconnect socket, and dispose it
+ SocketDisconnectAndDispose();
+
+ if (_messageListenerCompleted != null)
+ {
+ // at this point, we are sure that the listener thread will stop
+ // as we've disconnected the socket
+ _messageListenerCompleted.WaitOne();
+ _messageListenerCompleted.Dispose();
+ _messageListenerCompleted = null;
+ }
+ }
+
+ internal T CreateClientChannel() where T : ClientChannel, new()
+ {
+ var channel = new T();
+ lock (this)
+ {
+ channel.Initialize(this, InitialLocalWindowSize, LocalChannelDataPacketSize);
+ }
+ return channel;
+ }
+
+ internal T CreateServerChannel(uint remoteChannelNumber, uint remoteWindowSize, uint remoteChannelDataPacketSize) where T : ServerChannel, new()
+ {
+ var channel = new T();
+ lock (this)
+ {
+ channel.Initialize(this, InitialLocalWindowSize, LocalChannelDataPacketSize, remoteChannelNumber, remoteWindowSize,
+ remoteChannelDataPacketSize);
+ }
+ return channel;
+ }
+
+ ///
+ /// Sends "keep alive" message to keep connection alive.
+ ///
+ internal void SendKeepAlive()
+ {
+ this.SendMessage(new IgnoreMessage());
+ }
+
+ ///
+ /// Waits for the specified handle or the exception handle for the receive thread
+ /// to signal within the connection timeout.
+ ///
+ /// The wait handle.
+ /// A received package was invalid or failed the message integrity check.
+ /// None of the handles are signaled in time and the session is not disconnecting.
+ /// A socket error was signaled while receiving messages from the server.
+ ///
+ /// When neither handles are signaled in time and the session is not closing, then the
+ /// session is disconnected.
+ ///
+ ///
+ internal void WaitOnHandle(WaitHandle waitHandle)
+ {
+ var waitHandles = new[]
+ {
+ this._exceptionWaitHandle,
+ this._messageListenerCompleted,
+ waitHandle
+ };
+
+ switch (WaitHandle.WaitAny(waitHandles, ConnectionInfo.Timeout))
+ {
+ case 0:
+ throw this._exception;
+ case 1:
+ // when the session is NOT disconnecting, the listener should actually
+ // never complete without setting the exception wait handle and should
+ // end up in case 0...
+ //
+ // when the session is disconnecting, the completion of the listener
+ // should not be considered an error (quite the oppposite actually)
+ if (!_isDisconnecting)
+ {
+ throw new SshConnectionException("Client not connected.");
+ }
+ break;
+ case WaitHandle.WaitTimeout:
+ // when the session is NOT disconnecting, then we want to disconnect
+ // the session altogether in case of a timeout, and throw a
+ // SshOperationTimeoutException
+ //
+ // when the session is disconnecting, a timeout is likely when no
+ // network connectivity is available; depending on the configured
+ // timeout either the WaitAny times out first or a SocketException
+ // detailing a timeout thrown hereby completing the listener thread
+ // (which makes us end up in case 1). Either way, we do not want to
+ // disconnect while we're already disconnecting and we do not want
+ // to report an exception to the client when we're disconnecting
+ // anyway
+ if (!_isDisconnecting)
+ {
+ this.Disconnect(DisconnectReason.ByApplication, "Operation timeout");
+ throw new SshOperationTimeoutException("Session operation has timed out");
+ }
+ break;
+ }
+ }
+
+ ///
+ /// Sends packet message to the server.
+ ///
+ /// The message.
+ internal void SendMessage(Message message)
+ {
+ if (this._socket == null || !this._socket.CanWrite())
+ throw new SshConnectionException("Client not connected.");
+
+ if (this._keyExchangeInProgress && !(message is IKeyExchangedAllowed))
+ {
+ // Wait for key exchange to be completed
+ this.WaitOnHandle(this._keyExchangeCompletedWaitHandle);
+ }
+
+ this.Log(string.Format("SendMessage to server '{0}': '{1}'.", message.GetType().Name, message));
+
+ // Messages can be sent by different thread so we need to synchronize it
+ var paddingMultiplier = this._clientCipher == null ? (byte)8 : Math.Max((byte)8, this._serverCipher.MinimumSize); // Should be recalculate base on cipher min length if cipher specified
+
+ var messageData = message.GetBytes();
+
+ if (this._clientCompression != null)
+ {
+ messageData = this._clientCompression.Compress(messageData);
+ }
+
+ var packetLength = messageData.Length + 4 + 1; // add length bytes and padding byte
+ var paddingLength = (byte)((-packetLength) & (paddingMultiplier - 1));
+ if (paddingLength < paddingMultiplier)
+ {
+ paddingLength += paddingMultiplier;
+ }
+
+ // Build Packet data
+ var packetData = new byte[4 + 1 + messageData.Length + paddingLength];
+
+ // Add packet length
+ ((uint)packetData.Length - 4).GetBytes().CopyTo(packetData, 0);
+
+ // Add packet padding length
+ packetData[4] = paddingLength;
+
+ // Add packet payload
+ messageData.CopyTo(packetData, 4 + 1);
+
+ // Add random padding
+ var paddingBytes = new byte[paddingLength];
+ Randomizer.GetBytes(paddingBytes);
+ paddingBytes.CopyTo(packetData, 4 + 1 + messageData.Length);
+
+ // Lock handling of _outboundPacketSequence since it must be sent sequently to server
+ lock (this._socketLock)
+ {
+ if (this._socket == null || !this._socket.Connected)
+ throw new SshConnectionException("Client not connected.");
+
+ // Calculate packet hash
+ var hashData = new byte[4 + packetData.Length];
+ this._outboundPacketSequence.GetBytes().CopyTo(hashData, 0);
+ packetData.CopyTo(hashData, 4);
+
+ // Encrypt packet data
+ if (this._clientCipher != null)
+ {
+ packetData = this._clientCipher.Encrypt(packetData);
+ }
+
+ if (packetData.Length > MaximumSshPacketSize)
+ {
+ throw new InvalidOperationException(string.Format(CultureInfo.CurrentCulture, "Packet is too big. Maximum packet size is {0} bytes.", MaximumSshPacketSize));
+ }
+
+ if (this._clientMac == null)
+ {
+ this.SocketWrite(packetData);
+ }
+ else
+ {
+ var hash = this._clientMac.ComputeHash(hashData.ToArray());
+
+ var data = new byte[packetData.Length + this._clientMac.HashSize / 8];
+ packetData.CopyTo(data, 0);
+ hash.CopyTo(data, packetData.Length);
+
+ this.SocketWrite(data);
+ }
+
+ this._outboundPacketSequence++;
+
+ Monitor.Pulse(this._socketLock);
+ }
+ }
+
+ private static IEnumerable GetMessagesMetadata()
+ {
+ return new []
+ {
+ new MessageMetadata { Name = "SSH_MSG_NEWKEYS", Number = 21, Type = typeof(NewKeysMessage) },
+ new MessageMetadata { Name = "SSH_MSG_REQUEST_FAILURE", Number = 82, Type = typeof(RequestFailureMessage) },
+ new MessageMetadata { Name = "SSH_MSG_KEXINIT", Number = 20, Type = typeof(KeyExchangeInitMessage) },
+ new MessageMetadata { Name = "SSH_MSG_CHANNEL_OPEN_FAILURE", Number = 92, Type = typeof(ChannelOpenFailureMessage) },
+ new MessageMetadata { Name = "SSH_MSG_CHANNEL_FAILURE", Number = 100, Type = typeof(ChannelFailureMessage) },
+ new MessageMetadata { Name = "SSH_MSG_CHANNEL_EXTENDED_DATA", Number = 95, Type = typeof(ChannelExtendedDataMessage) },
+ new MessageMetadata { Name = "SSH_MSG_CHANNEL_DATA", Number = 94, Type = typeof(ChannelDataMessage) },
+ new MessageMetadata { Name = "SSH_MSG_USERAUTH_REQUEST", Number = 50, Type = typeof(RequestMessage) },
+ new MessageMetadata { Name = "SSH_MSG_CHANNEL_REQUEST", Number = 98, Type = typeof(ChannelRequestMessage) },
+ new MessageMetadata { Name = "SSH_MSG_USERAUTH_BANNER", Number = 53, Type = typeof(BannerMessage) },
+ new MessageMetadata { Name = "SSH_MSG_USERAUTH_INFO_RESPONSE", Number = 61, Type = typeof(InformationResponseMessage) },
+ new MessageMetadata { Name = "SSH_MSG_USERAUTH_FAILURE", Number = 51, Type = typeof(FailureMessage) },
+ new MessageMetadata { Name = "SSH_MSG_DEBUG", Number = 4, Type = typeof(DebugMessage), },
+ new MessageMetadata { Name = "SSH_MSG_KEXDH_INIT", Number = 30, Type = typeof(KeyExchangeDhInitMessage) },
+ new MessageMetadata { Name = "SSH_MSG_GLOBAL_REQUEST", Number = 80, Type = typeof(GlobalRequestMessage) },
+ new MessageMetadata { Name = "SSH_MSG_CHANNEL_OPEN", Number = 90, Type = typeof(ChannelOpenMessage) },
+ new MessageMetadata { Name = "SSH_MSG_CHANNEL_OPEN_CONFIRMATION", Number = 91, Type = typeof(ChannelOpenConfirmationMessage) },
+ new MessageMetadata { Name = "SSH_MSG_USERAUTH_INFO_REQUEST", Number = 60, Type = typeof(InformationRequestMessage) },
+ new MessageMetadata { Name = "SSH_MSG_UNIMPLEMENTED", Number = 3, Type = typeof(UnimplementedMessage) },
+ new MessageMetadata { Name = "SSH_MSG_REQUEST_SUCCESS", Number = 81, Type = typeof(RequestSuccessMessage) },
+ new MessageMetadata { Name = "SSH_MSG_CHANNEL_SUCCESS", Number = 99, Type = typeof(ChannelSuccessMessage) },
+ new MessageMetadata { Name = "SSH_MSG_USERAUTH_PASSWD_CHANGEREQ", Number = 60, Type = typeof(PasswordChangeRequiredMessage) },
+ new MessageMetadata { Name = "SSH_MSG_DISCONNECT", Number = 1, Type = typeof(DisconnectMessage) },
+ new MessageMetadata { Name = "SSH_MSG_SERVICE_REQUEST", Number = 5, Type = typeof(ServiceRequestMessage) },
+ new MessageMetadata { Name = "SSH_MSG_KEX_DH_GEX_REQUEST", Number = 34, Type = typeof(KeyExchangeDhGroupExchangeRequest) },
+ new MessageMetadata { Name = "SSH_MSG_KEX_DH_GEX_GROUP", Number = 31, Type = typeof(KeyExchangeDhGroupExchangeGroup) },
+ new MessageMetadata { Name = "SSH_MSG_USERAUTH_SUCCESS", Number = 52, Type = typeof(SuccessMessage) },
+ new MessageMetadata { Name = "SSH_MSG_USERAUTH_PK_OK", Number = 60, Type = typeof(PublicKeyMessage) },
+ new MessageMetadata { Name = "SSH_MSG_IGNORE", Number = 2, Type = typeof(IgnoreMessage) },
+ new MessageMetadata { Name = "SSH_MSG_CHANNEL_WINDOW_ADJUST", Number = 93, Type = typeof(ChannelWindowAdjustMessage) },
+ new MessageMetadata { Name = "SSH_MSG_CHANNEL_EOF", Number = 96, Type = typeof(ChannelEofMessage) },
+ new MessageMetadata { Name = "SSH_MSG_CHANNEL_CLOSE", Number = 97, Type = typeof(ChannelCloseMessage) },
+ new MessageMetadata { Name = "SSH_MSG_SERVICE_ACCEPT", Number = 6, Type = typeof(ServiceAcceptMessage) },
+ new MessageMetadata { Name = "SSH_MSG_KEXDH_REPLY", Number = 31, Type = typeof(KeyExchangeDhReplyMessage) },
+ new MessageMetadata { Name = "SSH_MSG_KEX_DH_GEX_INIT", Number = 32, Type = typeof(KeyExchangeDhGroupExchangeInit) },
+ new MessageMetadata { Name = "SSH_MSG_KEX_DH_GEX_REPLY", Number = 33, Type = typeof(KeyExchangeDhGroupExchangeReply) }
+ };
+ }
+
+ ///
+ /// Receives the message from the server.
+ ///
+ /// Incoming SSH message.
+ ///
+ private Message ReceiveMessage()
+ {
+ // No lock needed since all messages read by only one thread
+ var blockSize = this._serverCipher == null ? (byte)8 : Math.Max((byte)8, this._serverCipher.MinimumSize);
+
+ // Read packet length first
+ var firstBlock = this.Read(blockSize);
+
+ if (this._serverCipher != null)
+ {
+ firstBlock = this._serverCipher.Decrypt(firstBlock);
+ }
+
+ var packetLength = (uint)(firstBlock[0] << 24 | firstBlock[1] << 16 | firstBlock[2] << 8 | firstBlock[3]);
+
+ // Test packet minimum and maximum boundaries
+ if (packetLength < Math.Max((byte)16, blockSize) - 4 || packetLength > MaximumSshPacketSize - 4)
+ throw new SshConnectionException(string.Format(CultureInfo.CurrentCulture, "Bad packet length {0}", packetLength), DisconnectReason.ProtocolError);
+
+ // Read rest of the packet data
+ var bytesToRead = (int)(packetLength - (blockSize - 4));
+
+ var data = new byte[bytesToRead + blockSize];
+
+ firstBlock.CopyTo(data, 0);
+
+ byte[] serverHash = null;
+ if (this._serverMac != null)
+ {
+ serverHash = new byte[this._serverMac.HashSize / 8];
+ bytesToRead += serverHash.Length;
+ }
+
+ if (bytesToRead > 0)
+ {
+ var nextBlocks = this.Read(bytesToRead);
+
+ if (serverHash != null)
+ {
+ Buffer.BlockCopy(nextBlocks, nextBlocks.Length - serverHash.Length, serverHash, 0, serverHash.Length);
+ nextBlocks = nextBlocks.Take(nextBlocks.Length - serverHash.Length).ToArray();
+ }
+
+ if (nextBlocks.Length > 0)
+ {
+ if (this._serverCipher != null)
+ {
+ nextBlocks = this._serverCipher.Decrypt(nextBlocks);
+ }
+ nextBlocks.CopyTo(data, blockSize);
+ }
+ }
+
+ var paddingLength = data[4];
+
+ var messagePayload = new byte[packetLength - paddingLength - 1];
+ Buffer.BlockCopy(data, 5, messagePayload, 0, messagePayload.Length);
+
+ if (this._serverDecompression != null)
+ {
+ messagePayload = this._serverDecompression.Decompress(messagePayload);
+ }
+
+ // Validate message against MAC
+ if (this._serverMac != null)
+ {
+ var clientHashData = new byte[4 + data.Length];
+ var lengthBytes = this._inboundPacketSequence.GetBytes();
+
+ lengthBytes.CopyTo(clientHashData, 0);
+ data.CopyTo(clientHashData, 4);
+
+ // Calculate packet hash
+ var clientHash = this._serverMac.ComputeHash(clientHashData);
+
+ if (!serverHash.SequenceEqual(clientHash))
+ {
+ throw new SshConnectionException("MAC error", DisconnectReason.MacError);
+ }
+ }
+
+ this._inboundPacketSequence++;
+
+ return this.LoadMessage(messagePayload);
+ }
+
+ private void SendDisconnect(DisconnectReason reasonCode, string message)
+ {
+ // only send a disconnect message if it wasn't already sent, and we're
+ // still connected
+ if (this._isDisconnectMessageSent || !IsConnected)
+ return;
+
+ var disconnectMessage = new DisconnectMessage(reasonCode, message);
+
+ this.SendMessage(disconnectMessage);
+
+ this._isDisconnectMessageSent = true;
+ }
+
+ partial void HandleMessageCore(Message message);
+
+ ///
+ /// Handles the message.
+ ///
+ ///
+ /// The message.
+ private void HandleMessage(T message) where T : Message
+ {
+ this.OnMessageReceived(message);
+ }
+
+ #region Handle transport messages
+
+ private void HandleMessage(DisconnectMessage message)
+ {
+ this.OnDisconnectReceived(message);
+
+ // disconnect from the socket, and dispose it
+ SocketDisconnectAndDispose();
+ }
+
+ private void HandleMessage(IgnoreMessage message)
+ {
+ this.OnIgnoreReceived(message);
+ }
+
+ private void HandleMessage(UnimplementedMessage message)
+ {
+ this.OnUnimplementedReceived(message);
+ }
+
+ private void HandleMessage(DebugMessage message)
+ {
+ this.OnDebugReceived(message);
+ }
+
+ private void HandleMessage(ServiceRequestMessage message)
+ {
+ this.OnServiceRequestReceived(message);
+ }
+
+ private void HandleMessage(ServiceAcceptMessage message)
+ {
+ // TODO: Refactor to avoid this method here
+ this.OnServiceAcceptReceived(message);
+
+ this._serviceAccepted.Set();
+ }
+
+ private void HandleMessage(KeyExchangeInitMessage message)
+ {
+ this.OnKeyExchangeInitReceived(message);
+ }
+
+ private void HandleMessage(NewKeysMessage message)
+ {
+ this.OnNewKeysReceived(message);
+ }
+
+ #endregion
+
+ #region Handle User Authentication messages
+
+ private void HandleMessage(RequestMessage message)
+ {
+ this.OnUserAuthenticationRequestReceived(message);
+ }
+
+ private void HandleMessage(FailureMessage message)
+ {
+ this.OnUserAuthenticationFailureReceived(message);
+ }
+
+ private void HandleMessage(SuccessMessage message)
+ {
+ this.OnUserAuthenticationSuccessReceived(message);
+ }
+
+ private void HandleMessage(BannerMessage message)
+ {
+ this.OnUserAuthenticationBannerReceived(message);
+ }
+
+ #endregion
+
+ #region Handle connection messages
+
+ private void HandleMessage(GlobalRequestMessage message)
+ {
+ this.OnGlobalRequestReceived(message);
+ }
+
+ private void HandleMessage(RequestSuccessMessage message)
+ {
+ this.OnRequestSuccessReceived(message);
+ }
+
+ private void HandleMessage(RequestFailureMessage message)
+ {
+ this.OnRequestFailureReceived(message);
+ }
+
+ private void HandleMessage(ChannelOpenMessage message)
+ {
+ this.OnChannelOpenReceived(message);
+ }
+
+ private void HandleMessage(ChannelOpenConfirmationMessage message)
+ {
+ this.OnChannelOpenConfirmationReceived(message);
+ }
+
+ private void HandleMessage(ChannelOpenFailureMessage message)
+ {
+ this.OnChannelOpenFailureReceived(message);
+ }
+
+ private void HandleMessage(ChannelWindowAdjustMessage message)
+ {
+ this.OnChannelWindowAdjustReceived(message);
+ }
+
+ private void HandleMessage(ChannelDataMessage message)
+ {
+ this.OnChannelDataReceived(message);
+ }
+
+ private void HandleMessage(ChannelExtendedDataMessage message)
+ {
+ this.OnChannelExtendedDataReceived(message);
+ }
+
+ private void HandleMessage(ChannelEofMessage message)
+ {
+ this.OnChannelEofReceived(message);
+ }
+
+ private void HandleMessage(ChannelCloseMessage message)
+ {
+ this.OnChannelCloseReceived(message);
+ }
+
+ private void HandleMessage(ChannelRequestMessage message)
+ {
+ this.OnChannelRequestReceived(message);
+ }
+
+ private void HandleMessage(ChannelSuccessMessage message)
+ {
+ this.OnChannelSuccessReceived(message);
+ }
+
+ private void HandleMessage(ChannelFailureMessage message)
+ {
+ this.OnChannelFailureReceived(message);
+ }
+
+ #endregion
+
+ #region Handle received message events
+
+ ///
+ /// Called when received.
+ ///
+ /// message.
+ protected virtual void OnDisconnectReceived(DisconnectMessage message)
+ {
+ this.Log(string.Format("Disconnect received: {0} {1}", message.ReasonCode, message.Description));
+
+ var disconnectReceived = DisconnectReceived;
+ if (disconnectReceived != null)
+ disconnectReceived(this, new MessageEventArgs(message));
+
+ var disconnected = Disconnected;
+ if (disconnected != null)
+ disconnected(this, new EventArgs());
+ }
+
+ ///
+ /// Called when received.
+ ///
+ /// message.
+ protected virtual void OnIgnoreReceived(IgnoreMessage message)
+ {
+ var handlers = IgnoreReceived;
+ if (handlers != null)
+ handlers(this, new MessageEventArgs(message));
+ }
+
+ ///
+ /// Called when message received.
+ ///
+ /// message.
+ protected virtual void OnUnimplementedReceived(UnimplementedMessage message)
+ {
+ var handlers = UnimplementedReceived;
+ if (handlers != null)
+ handlers(this, new MessageEventArgs(message));
+ }
+
+ ///
+ /// Called when message received.
+ ///
+ /// message.
+ protected virtual void OnDebugReceived(DebugMessage message)
+ {
+ var handlers = DebugReceived;
+ if (handlers != null)
+ handlers(this, new MessageEventArgs(message));
+ }
+
+ ///
+ /// Called when message received.
+ ///
+ /// message.
+ protected virtual void OnServiceRequestReceived(ServiceRequestMessage message)
+ {
+ var handlers = ServiceRequestReceived;
+ if (handlers != null)
+ handlers(this, new MessageEventArgs(message));
+ }
+
+ ///
+ /// Called when message received.
+ ///
+ /// message.
+ protected virtual void OnServiceAcceptReceived(ServiceAcceptMessage message)
+ {
+ var handlers = ServiceAcceptReceived;
+ if (handlers != null)
+ handlers(this, new MessageEventArgs(message));
+ }
+
+ ///
+ /// Called when message received.
+ ///
+ /// message.
+ protected virtual void OnKeyExchangeInitReceived(KeyExchangeInitMessage message)
+ {
+ this._keyExchangeInProgress = true;
+
+ this._keyExchangeCompletedWaitHandle.Reset();
+
+ // Disable all registered messages except key exchange related
+ foreach (var messageMetadata in this._messagesMetadata)
+ {
+ if (messageMetadata.Activated && messageMetadata.Number > 2 && (messageMetadata.Number < 20 || messageMetadata.Number > 30))
+ messageMetadata.Enabled = false;
+ }
+
+ var keyExchangeAlgorithmName = (from c in this.ConnectionInfo.KeyExchangeAlgorithms.Keys
+ from s in message.KeyExchangeAlgorithms
+ where s == c
+ select c).FirstOrDefault();
+
+ if (keyExchangeAlgorithmName == null)
+ {
+ throw new SshConnectionException("Failed to negotiate key exchange algorithm.", DisconnectReason.KeyExchangeFailed);
+ }
+
+ // Create instance of key exchange algorithm that will be used
+ this._keyExchange = this.ConnectionInfo.KeyExchangeAlgorithms[keyExchangeAlgorithmName].CreateInstance();
+
+ this.ConnectionInfo.CurrentKeyExchangeAlgorithm = keyExchangeAlgorithmName;
+
+ this._keyExchange.HostKeyReceived += KeyExchange_HostKeyReceived;
+
+ // Start the algorithm implementation
+ this._keyExchange.Start(this, message);
+
+ var keyExchangeInitReceived = KeyExchangeInitReceived;
+ if (keyExchangeInitReceived != null)
+ keyExchangeInitReceived(this, new MessageEventArgs(message));
+ }
+
+ ///
+ /// Called when message received.
+ ///
+ /// message.
+ protected virtual void OnNewKeysReceived(NewKeysMessage message)
+ {
+ // Update sessionId
+ if (this.SessionId == null)
+ {
+ this.SessionId = this._keyExchange.ExchangeHash;
+ }
+
+ // Dispose of old ciphers and hash algorithms
+ if (this._serverMac != null)
+ {
+ this._serverMac.Clear();
+ this._serverMac = null;
+ }
+
+ if (this._clientMac != null)
+ {
+ this._clientMac.Clear();
+ this._clientMac = null;
+ }
+
+ // Update negotiated algorithms
+ this._serverCipher = this._keyExchange.CreateServerCipher();
+ this._clientCipher = this._keyExchange.CreateClientCipher();
+ this._serverMac = this._keyExchange.CreateServerHash();
+ this._clientMac = this._keyExchange.CreateClientHash();
+ this._clientCompression = this._keyExchange.CreateCompressor();
+ this._serverDecompression = this._keyExchange.CreateDecompressor();
+
+ // Dispose of old KeyExchange object as it is no longer needed.
+ if (this._keyExchange != null)
+ {
+ this._keyExchange.HostKeyReceived -= KeyExchange_HostKeyReceived;
+ this._keyExchange.Dispose();
+ this._keyExchange = null;
+ }
+
+ // Enable all active registered messages
+ foreach (var messageMetadata in this._messagesMetadata)
+ {
+ if (messageMetadata.Activated)
+ messageMetadata.Enabled = true;
+ }
+
+ var newKeysReceived = NewKeysReceived;
+ if (newKeysReceived != null)
+ newKeysReceived(this, new MessageEventArgs(message));
+
+ // Signal that key exchange completed
+ this._keyExchangeCompletedWaitHandle.Set();
+
+ this._keyExchangeInProgress = false;
+ }
+
+ ///
+ /// Called when client is disconnecting from the server.
+ ///
+ internal void OnDisconnecting()
+ {
+ _isDisconnecting = true;
+ }
+
+ ///
+ /// Called when message received.
+ ///
+ /// message.
+ protected virtual void OnUserAuthenticationRequestReceived(RequestMessage message)
+ {
+ var handlers = UserAuthenticationRequestReceived;
+ if (handlers != null)
+ handlers(this, new MessageEventArgs(message));
+ }
+
+ ///
+ /// Called when message received.
+ ///
+ /// message.
+ protected virtual void OnUserAuthenticationFailureReceived(FailureMessage message)
+ {
+ var handlers = UserAuthenticationFailureReceived;
+ if (handlers != null)
+ handlers(this, new MessageEventArgs(message));
+ }
+
+ ///
+ /// Called when message received.
+ ///
+ /// message.
+ protected virtual void OnUserAuthenticationSuccessReceived(SuccessMessage message)
+ {
+ var handlers = UserAuthenticationSuccessReceived;
+ if (handlers != null)
+ handlers(this, new MessageEventArgs(message));
+ }
+
+ ///
+ /// Called when message received.
+ ///
+ /// message.
+ protected virtual void OnUserAuthenticationBannerReceived(BannerMessage message)
+ {
+ var handlers = UserAuthenticationBannerReceived;
+ if (handlers != null)
+ handlers(this, new MessageEventArgs(message));
+ }
+
+ ///
+ /// Called when message received.
+ ///
+ /// message.
+ protected virtual void OnGlobalRequestReceived(GlobalRequestMessage message)
+ {
+ var handlers = GlobalRequestReceived;
+ if (handlers != null)
+ handlers(this, new MessageEventArgs(message));
+ }
+
+ ///
+ /// Called when message received.
+ ///
+ /// message.
+ protected virtual void OnRequestSuccessReceived(RequestSuccessMessage message)
+ {
+ var handlers = RequestSuccessReceived;
+ if (handlers != null)
+ handlers(this, new MessageEventArgs(message));
+ }
+
+ ///
+ /// Called when message received.
+ ///
+ /// message.
+ protected virtual void OnRequestFailureReceived(RequestFailureMessage message)
+ {
+ var handlers = RequestFailureReceived;
+ if (handlers != null)
+ handlers(this, new MessageEventArgs(message));
+ }
+
+ ///
+ /// Called when message received.
+ ///
+ /// message.
+ protected virtual void OnChannelOpenReceived(ChannelOpenMessage message)
+ {
+ var handlers = ChannelOpenReceived;
+ if (handlers != null)
+ handlers(this, new MessageEventArgs(message));
+ }
+
+ ///
+ /// Called when message received.
+ ///
+ /// message.
+ protected virtual void OnChannelOpenConfirmationReceived(ChannelOpenConfirmationMessage message)
+ {
+ var handlers = ChannelOpenConfirmationReceived;
+ if (handlers != null)
+ handlers(this, new MessageEventArgs(message));
+ }
+
+ ///
+ /// Called when message received.
+ ///
+ /// message.
+ protected virtual void OnChannelOpenFailureReceived(ChannelOpenFailureMessage message)
+ {
+ var handlers = ChannelOpenFailureReceived;
+ if (handlers != null)
+ handlers(this, new MessageEventArgs(message));
+ }
+
+ ///
+ /// Called when message received.
+ ///
+ /// message.
+ protected virtual void OnChannelWindowAdjustReceived(ChannelWindowAdjustMessage message)
+ {
+ var handlers = ChannelWindowAdjustReceived;
+ if (handlers != null)
+ handlers(this, new MessageEventArgs(message));
+ }
+
+ ///
+ /// Called when message received.
+ ///
+ /// message.
+ protected virtual void OnChannelDataReceived(ChannelDataMessage message)
+ {
+ var handlers = ChannelDataReceived;
+ if (handlers != null)
+ handlers(this, new MessageEventArgs(message));
+ }
+
+ ///
+ /// Called when message received.
+ ///
+ /// message.
+ protected virtual void OnChannelExtendedDataReceived(ChannelExtendedDataMessage message)
+ {
+ var handlers = ChannelExtendedDataReceived;
+ if (handlers != null)
+ handlers(this, new MessageEventArgs(message));
+ }
+
+ ///
+ /// Called when message received.
+ ///
+ /// message.
+ protected virtual void OnChannelEofReceived(ChannelEofMessage message)
+ {
+ var handlers = ChannelEofReceived;
+ if (handlers != null)
+ handlers(this, new MessageEventArgs(message));
+ }
+
+ ///
+ /// Called when message received.
+ ///
+ /// message.
+ protected virtual void OnChannelCloseReceived(ChannelCloseMessage message)
+ {
+ var handlers = ChannelCloseReceived;
+ if (handlers != null)
+ handlers(this, new MessageEventArgs(message));
+ }
+
+ ///
+ /// Called when message received.
+ ///
+ /// message.
+ protected virtual void OnChannelRequestReceived(ChannelRequestMessage message)
+ {
+ var handlers = ChannelRequestReceived;
+ if (handlers != null)
+ handlers(this, new MessageEventArgs(message));
+ }
+
+ ///
+ /// Called when message received.
+ ///
+ /// message.
+ protected virtual void OnChannelSuccessReceived(ChannelSuccessMessage message)
+ {
+ var handlers = ChannelSuccessReceived;
+ if (handlers != null)
+ handlers(this, new MessageEventArgs(message));
+ }
+
+ ///
+ /// Called when message received.
+ ///
+ /// message.
+ protected virtual void OnChannelFailureReceived(ChannelFailureMessage message)
+ {
+ var handlers = ChannelFailureReceived;
+ if (handlers != null)
+ handlers(this, new MessageEventArgs(message));
+ }
+
+ ///
+ /// Called when message received.
+ ///
+ /// message.
+ protected virtual void OnMessageReceived(Message message)
+ {
+ var handlers = MessageReceived;
+ if (handlers != null)
+ handlers(this, new MessageEventArgs(message));
+ }
+
+ #endregion
+
+ private void KeyExchange_HostKeyReceived(object sender, HostKeyEventArgs e)
+ {
+ var handlers = HostKeyReceived;
+ if (handlers != null)
+ handlers(this, e);
+ }
+
+ ///
+ /// Reads the specified length of bytes from the server.
+ ///
+ /// The length.
+ ///
+ /// The bytes read from the server.
+ ///
+ private byte[] Read(int length)
+ {
+ var buffer = new byte[length];
+
+ this.SocketRead(length, ref buffer);
+
+ return buffer;
+ }
+
+ #region Message loading functions
+
+ ///
+ /// Registers SSH Message with the session.
+ ///
+ /// Name of the message.
+ public void RegisterMessage(string messageName)
+ {
+ this.InternalRegisterMessage(messageName);
+ }
+
+ ///
+ /// Removes SSH message from the session
+ ///
+ /// Name of the message.
+ public void UnRegisterMessage(string messageName)
+ {
+ this.InternalUnRegisterMessage(messageName);
+ }
+
+ ///
+ /// Loads the message.
+ ///
+ /// Message data.
+ /// New message
+ private Message LoadMessage(byte[] data)
+ {
+ var messageType = data[0];
+ var messageMetadata = (from m in this._messagesMetadata where m.Number == messageType && m.Enabled && m.Activated select m).SingleOrDefault();
+ if (messageMetadata == null)
+ throw new SshException(string.Format(CultureInfo.CurrentCulture, "Message type {0} is not valid.", messageType));
+
+ var message = messageMetadata.Type.CreateInstance();
+
+ message.Load(data);
+
+ this.Log(string.Format("ReceiveMessage from server: '{0}': '{1}'.", message.GetType().Name, message));
+
+ return message;
+ }
+
+ partial void InternalRegisterMessage(string messageName);
+
+ partial void InternalUnRegisterMessage(string messageName);
+
+ #endregion
+
+ partial void ExecuteThread(Action action);
+
+ ///
+ /// Gets a value indicating whether the socket is connected.
+ ///
+ ///
+ /// true if the socket is connected; otherwise, false.
+ ///
+ partial void IsSocketConnected(ref bool isConnected);
+
+ partial void SocketConnect(string host, int port);
+
+ partial void SocketDisconnect();
+
+ partial void SocketRead(int length, ref byte[] buffer);
+
+ partial void SocketReadLine(ref string response);
+
+ partial void Log(string text);
+
+ ///
+ /// Writes the specified data to the server.
+ ///
+ /// The data.
+ partial void SocketWrite(byte[] data);
+
+ ///
+ /// Disconnects and disposes the socket.
+ ///
+ private void SocketDisconnectAndDispose()
+ {
+ if (_socket != null)
+ {
+ lock (_socketLock)
+ {
+ if (_socket != null)
+ {
+ SocketDisconnect();
+ _socket.Dispose();
+ _socket = null;
+ }
+ }
+ }
+ }
+
+ ///
+ /// Listens for incoming message from the server and handles them. This method run as a task on separate thread.
+ ///
+ private void MessageListener()
+ {
+ try
+ {
+ while (this._socket != null && this._socket.Connected)
+ {
+ var message = this.ReceiveMessage();
+ this.HandleMessageCore(message);
+ }
+ }
+ catch (Exception exp)
+ {
+ this.RaiseError(exp);
+ }
+ }
+
+ private byte SocketReadByte()
+ {
+ var buffer = new byte[1];
+
+ this.SocketRead(1, ref buffer);
+
+ return buffer[0];
+ }
+
+ private void SocketWriteByte(byte data)
+ {
+ this.SocketWrite(new[] {data});
+ }
+
+ private void ConnectSocks4()
+ {
+ // Send socks version number
+ this.SocketWriteByte(0x04);
+
+ // Send command code
+ this.SocketWriteByte(0x01);
+
+ // Send port
+ this.SocketWriteByte((byte)(this.ConnectionInfo.Port / 0xFF));
+ this.SocketWriteByte((byte)(this.ConnectionInfo.Port % 0xFF));
+
+ // Send IP
+ IPAddress ipAddress = this.ConnectionInfo.Host.GetIPAddress();
+ this.SocketWrite(ipAddress.GetAddressBytes());
+
+ // Send username
+ var username = new Common.ASCIIEncoding().GetBytes(this.ConnectionInfo.ProxyUsername);
+ this.SocketWrite(username);
+ this.SocketWriteByte(0x00);
+
+ // Read 0
+ if (this.SocketReadByte() != 0)
+ {
+ throw new ProxyException("SOCKS4: Null is expected.");
+ }
+
+ // Read response code
+ var code = this.SocketReadByte();
+
+ switch (code)
+ {
+ case 0x5a:
+ break;
+ case 0x5b:
+ throw new ProxyException("SOCKS4: Connection rejected.");
+ case 0x5c:
+ throw new ProxyException("SOCKS4: Client is not running identd or not reachable from the server.");
+ case 0x5d:
+ throw new ProxyException("SOCKS4: Client's identd could not confirm the user ID string in the request.");
+ default:
+ throw new ProxyException("SOCKS4: Not valid response.");
+ }
+
+ var dummyBuffer = new byte[4];
+
+ // Read 2 bytes to be ignored
+ this.SocketRead(2, ref dummyBuffer);
+
+ // Read 4 bytes to be ignored
+ this.SocketRead(4, ref dummyBuffer);
+ }
+
+ private void ConnectSocks5()
+ {
+ // Send socks version number
+ this.SocketWriteByte(0x05);
+
+ // Send number of supported authentication methods
+ this.SocketWriteByte(0x02);
+
+ // Send supported authentication methods
+ this.SocketWriteByte(0x00); // No authentication
+ this.SocketWriteByte(0x02); // Username/Password
+
+ var socksVersion = this.SocketReadByte();
+ if (socksVersion != 0x05)
+ throw new ProxyException(string.Format("SOCKS Version '{0}' is not supported.", socksVersion));
+
+ var authenticationMethod = this.SocketReadByte();
+ switch (authenticationMethod)
+ {
+ case 0x00:
+ break;
+ case 0x02:
+
+ // Send version
+ this.SocketWriteByte(0x01);
+
+ var encoding = new Common.ASCIIEncoding();
+
+ var username = encoding.GetBytes(this.ConnectionInfo.ProxyUsername);
+
+ if (username.Length > byte.MaxValue)
+ throw new ProxyException("Proxy username is too long.");
+
+ // Send username length
+ this.SocketWriteByte((byte)username.Length);
+
+ // Send username
+ this.SocketWrite(username);
+
+ var password = encoding.GetBytes(this.ConnectionInfo.ProxyPassword);
+
+ if (password.Length > byte.MaxValue)
+ throw new ProxyException("Proxy password is too long.");
+
+ // Send username length
+ this.SocketWriteByte((byte)password.Length);
+
+ // Send username
+ this.SocketWrite(password);
+
+ var serverVersion = this.SocketReadByte();
+
+ if (serverVersion != 1)
+ throw new ProxyException("SOCKS5: Server authentication version is not valid.");
+
+ var statusCode = this.SocketReadByte();
+ if (statusCode != 0)
+ throw new ProxyException("SOCKS5: Username/Password authentication failed.");
+
+ break;
+ case 0xFF:
+ throw new ProxyException("SOCKS5: No acceptable authentication methods were offered.");
+ }
+
+ // Send socks version number
+ this.SocketWriteByte(0x05);
+
+ // Send command code
+ this.SocketWriteByte(0x01); // establish a TCP/IP stream connection
+
+ // Send reserved, must be 0x00
+ this.SocketWriteByte(0x00);
+
+ IPAddress ip = this.ConnectionInfo.Host.GetIPAddress();
+
+ // Send address type and address
+ if (ip.AddressFamily == AddressFamily.InterNetwork)
+ {
+ this.SocketWriteByte(0x01);
+ var address = ip.GetAddressBytes();
+ this.SocketWrite(address);
+ }
+ else if (ip.AddressFamily == AddressFamily.InterNetworkV6)
+ {
+ this.SocketWriteByte(0x04);
+ var address = ip.GetAddressBytes();
+ this.SocketWrite(address);
+ }
+ else
+ {
+ throw new ProxyException(string.Format("SOCKS5: IP address '{0}' is not supported.", ip));
+ }
+
+ // Send port
+ this.SocketWriteByte((byte)(this.ConnectionInfo.Port / 0xFF));
+ this.SocketWriteByte((byte)(this.ConnectionInfo.Port % 0xFF));
+
+ // Read Server SOCKS5 version
+ if (this.SocketReadByte() != 5)
+ {
+ throw new ProxyException("SOCKS5: Version 5 is expected.");
+ }
+
+ // Read response code
+ var status = this.SocketReadByte();
+
+ switch (status)
+ {
+ case 0x00:
+ break;
+ case 0x01:
+ throw new ProxyException("SOCKS5: General failure.");
+ case 0x02:
+ throw new ProxyException("SOCKS5: Connection not allowed by ruleset.");
+ case 0x03:
+ throw new ProxyException("SOCKS5: Network unreachable.");
+ case 0x04:
+ throw new ProxyException("SOCKS5: Host unreachable.");
+ case 0x05:
+ throw new ProxyException("SOCKS5: Connection refused by destination host.");
+ case 0x06:
+ throw new ProxyException("SOCKS5: TTL expired.");
+ case 0x07:
+ throw new ProxyException("SOCKS5: Command not supported or protocol error.");
+ case 0x08:
+ throw new ProxyException("SOCKS5: Address type not supported.");
+ default:
+ throw new ProxyException("SOCKS4: Not valid response.");
+ }
+
+ // Read 0
+ if (this.SocketReadByte() != 0)
+ {
+ throw new ProxyException("SOCKS5: 0 byte is expected.");
+ }
+
+ var addressType = this.SocketReadByte();
+ var responseIp = new byte[16];
+
+ switch (addressType)
+ {
+ case 0x01:
+ this.SocketRead(4, ref responseIp);
+ break;
+ case 0x04:
+ this.SocketRead(16, ref responseIp);
+ break;
+ default:
+ throw new ProxyException(string.Format("Address type '{0}' is not supported.", addressType));
+ }
+
+ var port = new byte[2];
+
+ // Read 2 bytes to be ignored
+ this.SocketRead(2, ref port);
+ }
+
+ private void ConnectHttp()
+ {
+ var httpResponseRe = new Regex(@"HTTP/(?\d[.]\d) (?\d{3}) (?.+)$");
+ var httpHeaderRe = new Regex(@"(?[^\[\]()<>@,;:\""/?={} \t]+):(?.+)?");
+
+ var encoding = new Common.ASCIIEncoding();
+
+ this.SocketWrite(encoding.GetBytes(string.Format("CONNECT {0}:{1} HTTP/1.0\r\n", this.ConnectionInfo.Host, this.ConnectionInfo.Port)));
+
+ // Sent proxy authorization is specified
+ if (!string.IsNullOrEmpty(this.ConnectionInfo.ProxyUsername))
+ {
+ var authorization = string.Format("Proxy-Authorization: Basic {0}\r\n",
+ Convert.ToBase64String(encoding.GetBytes(string.Format("{0}:{1}", this.ConnectionInfo.ProxyUsername, this.ConnectionInfo.ProxyPassword)))
+ );
+ this.SocketWrite(encoding.GetBytes(authorization));
+ }
+
+ this.SocketWrite(encoding.GetBytes("\r\n"));
+
+ HttpStatusCode? statusCode = null;
+ var response = string.Empty;
+ var contentLength = 0;
+
+ while (true)
+ {
+ this.SocketReadLine(ref response);
+
+ if (statusCode == null)
+ {
+ var statusMatch = httpResponseRe.Match(response);
+ if (statusMatch.Success)
+ {
+ var httpStatusCode = statusMatch.Result("${statusCode}");
+ statusCode = (HttpStatusCode) int.Parse(httpStatusCode);
+ if (statusCode != HttpStatusCode.OK)
+ {
+ var reasonPhrase = statusMatch.Result("${reasonPhrase}");
+ throw new ProxyException(string.Format("HTTP: Status code {0}, \"{1}\"", httpStatusCode,
+ reasonPhrase));
+ }
+ continue;
+ }
+ }
+
+ // continue on parsing message headers coming from the server
+ var headerMatch = httpHeaderRe.Match(response);
+ if (headerMatch.Success)
+ {
+ var fieldName = headerMatch.Result("${fieldName}");
+ if (fieldName.Equals("Content-Length", StringComparison.InvariantCultureIgnoreCase))
+ {
+ contentLength = int.Parse(headerMatch.Result("${fieldValue}"));
+ }
+ continue;
+ }
+
+ // check if we've reached the CRLF which separates request line and headers from the message body
+ if (response.Length == 0)
+ {
+ // read response body if specified
+ if (contentLength > 0)
+ {
+ var contentBody = new byte[contentLength];
+ SocketRead(contentLength, ref contentBody);
+ }
+ break;
+ }
+ }
+ }
+
+ ///
+ /// Raises the event.
+ ///
+ /// The exp.
+ private void RaiseError(Exception exp)
+ {
+ var connectionException = exp as SshConnectionException;
+
+ if (_isDisconnecting)
+ {
+ // a connection exception which is raised while isDisconnecting is normal and
+ // should be ignored
+ if (connectionException != null)
+ return;
+
+ // any timeout while disconnecting can be caused by loss of connectivity
+ // altogether and should be ignored
+ var socketException = exp as SocketException;
+ if (socketException != null && socketException.SocketErrorCode == SocketError.TimedOut)
+ return;
+ }
+
+ this._exception = exp;
+
+ this._exceptionWaitHandle.Set();
+
+ var errorOccured = ErrorOccured;
+ if (errorOccured != null)
+ errorOccured(this, new ExceptionEventArgs(exp));
+
+ if (connectionException != null && connectionException.DisconnectReason != DisconnectReason.ConnectionLost)
+ {
+ this.Disconnect(connectionException.DisconnectReason, exp.ToString());
+ }
+ }
+
+ ///
+ /// Resets connection-specific information to ensure state of a previous connection
+ /// does not affect new connections.
+ ///
+ private void Reset()
+ {
+ if (_exceptionWaitHandle != null)
+ _exceptionWaitHandle.Reset();
+ if (_keyExchangeCompletedWaitHandle != null)
+ _keyExchangeCompletedWaitHandle.Reset();
+ if (_messageListenerCompleted != null)
+ _messageListenerCompleted.Reset();
+
+ SessionId = null;
+ _isDisconnectMessageSent = false;
+ _isDisconnecting = false;
+ _isAuthenticated = false;
+ _exception = null;
+ _keyExchangeInProgress = false;
+ }
+
+ #region IDisposable Members
+
+ private bool _disposed;
+
+ ///
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged ResourceMessages.
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ ///
+ /// Releases unmanaged and - optionally - managed resources
+ ///
+ /// true to release both managed and unmanaged resources; false to release only unmanaged ResourceMessages.
+ protected virtual void Dispose(bool disposing)
+ {
+ // Check to see if Dispose has already been called.
+ if (!this._disposed)
+ {
+ // If disposing equals true, dispose all managed
+ // and unmanaged ResourceMessages.
+ if (disposing)
+ {
+ Disconnect();
+
+ if (this._serviceAccepted != null)
+ {
+ this._serviceAccepted.Dispose();
+ this._serviceAccepted = null;
+ }
+
+ if (this._exceptionWaitHandle != null)
+ {
+ this._exceptionWaitHandle.Dispose();
+ this._exceptionWaitHandle = null;
+ }
+
+ if (this._keyExchangeCompletedWaitHandle != null)
+ {
+ this._keyExchangeCompletedWaitHandle.Dispose();
+ this._keyExchangeCompletedWaitHandle = null;
+ }
+
+ if (this._serverMac != null)
+ {
+ this._serverMac.Clear();
+ this._serverMac = null;
+ }
+
+ if (this._clientMac != null)
+ {
+ this._clientMac.Clear();
+ this._clientMac = null;
+ }
+
+ if (this._keyExchange != null)
+ {
+ this._keyExchange.HostKeyReceived -= KeyExchange_HostKeyReceived;
+ this._keyExchange.Dispose();
+ this._keyExchange = null;
+ }
+ }
+
+ // Note disposing has been done.
+ this._disposed = true;
+ }
+ }
+
+ ///
+ /// Releases unmanaged resources and performs other cleanup operations before the
+ /// is reclaimed by garbage collection.
+ ///
+ ~Session()
+ {
+ // Do not re-create Dispose clean-up code here.
+ // Calling Dispose(false) is optimal in terms of
+ // readability and maintainability.
+ Dispose(false);
+ }
+
+ #endregion
+
+ private class MessageMetadata
+ {
+ public string Name { get; set; }
+
+ public byte Number { get; set; }
+
+ public bool Enabled { get; set; }
+
+ public bool Activated { get; set; }
+
+ public Type Type { get; set; }
+ }
+ }
}
\ No newline at end of file
diff --git a/Renci.SshNet/Sftp/Flags.cs b/Renci.SshNet/Sftp/Flags.cs
index 837d824..d8cbe17 100644
--- a/Renci.SshNet/Sftp/Flags.cs
+++ b/Renci.SshNet/Sftp/Flags.cs
@@ -1,31 +1,31 @@
-namespace Renci.SshNet.Sftp
-{
- public enum Flags
- {
- None = 0x00000000,
- ///
- /// SSH_FXF_READ
- ///
- Read = 0x00000001,
- ///
- /// SSH_FXF_WRITE
- ///
- Write = 0x00000002,
- ///
- /// SSH_FXF_APPEND
- ///
- Append = 0x00000004,
- ///
- /// SSH_FXF_CREAT
- ///
- CreateNewOrOpen = 0x00000008,
- ///
- /// SSH_FXF_TRUNC
- ///
- Truncate = 0x00000010,
- ///
- /// SSH_FXF_EXCL
- ///
- CreateNew = 0x00000028
- }
-}
+namespace Renci.SshNet.Sftp
+{
+ internal enum Flags
+ {
+ None = 0x00000000,
+ ///
+ /// SSH_FXF_READ
+ ///
+ Read = 0x00000001,
+ ///
+ /// SSH_FXF_WRITE
+ ///
+ Write = 0x00000002,
+ ///
+ /// SSH_FXF_APPEND
+ ///
+ Append = 0x00000004,
+ ///
+ /// SSH_FXF_CREAT
+ ///
+ CreateNewOrOpen = 0x00000008,
+ ///
+ /// SSH_FXF_TRUNC
+ ///
+ Truncate = 0x00000010,
+ ///
+ /// SSH_FXF_EXCL
+ ///
+ CreateNew = 0x00000028
+ }
+}
diff --git a/Renci.SshNet/Sftp/Requests/ExtendedRequests/FStatVfsRequest.cs b/Renci.SshNet/Sftp/Requests/ExtendedRequests/FStatVfsRequest.cs
index 068b26e..c9ebd0e 100644
--- a/Renci.SshNet/Sftp/Requests/ExtendedRequests/FStatVfsRequest.cs
+++ b/Renci.SshNet/Sftp/Requests/ExtendedRequests/FStatVfsRequest.cs
@@ -1,33 +1,33 @@
-using System;
-using Renci.SshNet.Sftp.Responses;
-
-namespace Renci.SshNet.Sftp.Requests
-{
- internal class FStatVfsRequest : SftpExtendedRequest
- {
- public override SftpMessageTypes SftpMessageType
- {
- get { return SftpMessageTypes.Extended; }
- }
-
- public override string Name
- {
- get { return "fstatvfs@openssh.com"; }
- }
-
- public byte[] Handle { get; private set; }
-
- public FStatVfsRequest(uint protocolVersion, uint requestId, byte[] handle, Action extendedAction, Action statusAction)
- : base(protocolVersion, requestId, statusAction)
- {
- this.Handle = handle;
- this.SetAction(extendedAction);
- }
-
- protected override void SaveData()
- {
- base.SaveData();
- this.WriteBinaryString(this.Handle);
- }
- }
-}
+using System;
+using Renci.SshNet.Sftp.Responses;
+
+namespace Renci.SshNet.Sftp.Requests
+{
+ internal class FStatVfsRequest : SftpExtendedRequest
+ {
+ public override SftpMessageTypes SftpMessageType
+ {
+ get { return SftpMessageTypes.Extended; }
+ }
+
+ public override string Name
+ {
+ get { return "fstatvfs@openssh.com"; }
+ }
+
+ public byte[] Handle { get; private set; }
+
+ public FStatVfsRequest(uint protocolVersion, uint requestId, byte[] handle, Action extendedAction, Action statusAction)
+ : base(protocolVersion, requestId, statusAction)
+ {
+ this.Handle = handle;
+ this.SetAction(extendedAction);
+ }
+
+ protected override void SaveData()
+ {
+ base.SaveData();
+ this.WriteBinaryString(this.Handle);
+ }
+ }
+}
diff --git a/Renci.SshNet/Sftp/Requests/ExtendedRequests/HardLinkRequest.cs b/Renci.SshNet/Sftp/Requests/ExtendedRequests/HardLinkRequest.cs
index 422826a..188bc1b 100644
--- a/Renci.SshNet/Sftp/Requests/ExtendedRequests/HardLinkRequest.cs
+++ b/Renci.SshNet/Sftp/Requests/ExtendedRequests/HardLinkRequest.cs
@@ -1,36 +1,36 @@
-using System;
-using Renci.SshNet.Sftp.Responses;
-
-namespace Renci.SshNet.Sftp.Requests
-{
- internal class HardLinkRequest : SftpExtendedRequest
- {
- public override SftpMessageTypes SftpMessageType
- {
- get { return SftpMessageTypes.Extended; }
- }
-
- public override string Name
- {
- get { return "hardlink@openssh.com"; }
- }
-
- public string OldPath { get; private set; }
-
- public string NewPath { get; private set; }
-
- public HardLinkRequest(uint protocolVersion, uint requestId, string oldPath, string newPath, Action statusAction)
- : base(protocolVersion, requestId, statusAction)
- {
- this.OldPath = oldPath;
- this.NewPath = newPath;
- }
-
- protected override void SaveData()
- {
- base.SaveData();
- this.Write(this.OldPath);
- this.Write(this.NewPath);
- }
- }
+using System;
+using Renci.SshNet.Sftp.Responses;
+
+namespace Renci.SshNet.Sftp.Requests
+{
+ internal class HardLinkRequest : SftpExtendedRequest
+ {
+ public override SftpMessageTypes SftpMessageType
+ {
+ get { return SftpMessageTypes.Extended; }
+ }
+
+ public override string Name
+ {
+ get { return "hardlink@openssh.com"; }
+ }
+
+ public string OldPath { get; private set; }
+
+ public string NewPath { get; private set; }
+
+ public HardLinkRequest(uint protocolVersion, uint requestId, string oldPath, string newPath, Action statusAction)
+ : base(protocolVersion, requestId, statusAction)
+ {
+ this.OldPath = oldPath;
+ this.NewPath = newPath;
+ }
+
+ protected override void SaveData()
+ {
+ base.SaveData();
+ this.Write(this.OldPath);
+ this.Write(this.NewPath);
+ }
+ }
}
\ No newline at end of file
diff --git a/Renci.SshNet/Sftp/Requests/ExtendedRequests/PosixRenameRequest.cs b/Renci.SshNet/Sftp/Requests/ExtendedRequests/PosixRenameRequest.cs
index 11e4dda..3a3681f 100644
--- a/Renci.SshNet/Sftp/Requests/ExtendedRequests/PosixRenameRequest.cs
+++ b/Renci.SshNet/Sftp/Requests/ExtendedRequests/PosixRenameRequest.cs
@@ -1,40 +1,40 @@
-using System;
-using Renci.SshNet.Sftp.Responses;
-using System.Text;
-
-namespace Renci.SshNet.Sftp.Requests
-{
- internal class PosixRenameRequest : SftpExtendedRequest
- {
- public override SftpMessageTypes SftpMessageType
- {
- get { return SftpMessageTypes.Extended; }
- }
-
- public override string Name
- {
- get { return "posix-rename@openssh.com"; }
- }
-
- public string OldPath { get; private set; }
-
- public string NewPath { get; private set; }
-
- public Encoding Encoding { get; private set; }
-
- public PosixRenameRequest(uint protocolVersion, uint requestId, string oldPath, string newPath, Encoding encoding, Action statusAction)
- : base(protocolVersion, requestId, statusAction)
- {
- this.OldPath = oldPath;
- this.NewPath = newPath;
- this.Encoding = encoding;
- }
-
- protected override void SaveData()
- {
- base.SaveData();
- this.Write(this.OldPath, this.Encoding);
- this.Write(this.NewPath, this.Encoding);
- }
- }
+using System;
+using Renci.SshNet.Sftp.Responses;
+using System.Text;
+
+namespace Renci.SshNet.Sftp.Requests
+{
+ internal class PosixRenameRequest : SftpExtendedRequest
+ {
+ public override SftpMessageTypes SftpMessageType
+ {
+ get { return SftpMessageTypes.Extended; }
+ }
+
+ public override string Name
+ {
+ get { return "posix-rename@openssh.com"; }
+ }
+
+ public string OldPath { get; private set; }
+
+ public string NewPath { get; private set; }
+
+ public Encoding Encoding { get; private set; }
+
+ public PosixRenameRequest(uint protocolVersion, uint requestId, string oldPath, string newPath, Encoding encoding, Action statusAction)
+ : base(protocolVersion, requestId, statusAction)
+ {
+ this.OldPath = oldPath;
+ this.NewPath = newPath;
+ this.Encoding = encoding;
+ }
+
+ protected override void SaveData()
+ {
+ base.SaveData();
+ this.Write(this.OldPath, this.Encoding);
+ this.Write(this.NewPath, this.Encoding);
+ }
+ }
}
\ No newline at end of file
diff --git a/Renci.SshNet/Sftp/Requests/ExtendedRequests/StatVfsRequest.cs b/Renci.SshNet/Sftp/Requests/ExtendedRequests/StatVfsRequest.cs
index b21e7aa..cdeadb2 100644
--- a/Renci.SshNet/Sftp/Requests/ExtendedRequests/StatVfsRequest.cs
+++ b/Renci.SshNet/Sftp/Requests/ExtendedRequests/StatVfsRequest.cs
@@ -1,37 +1,37 @@
-using System;
-using Renci.SshNet.Sftp.Responses;
-using System.Text;
-
-namespace Renci.SshNet.Sftp.Requests
-{
- internal class StatVfsRequest : SftpExtendedRequest
- {
- public override SftpMessageTypes SftpMessageType
- {
- get { return SftpMessageTypes.Extended; }
- }
-
- public override string Name
- {
- get { return "statvfs@openssh.com"; }
- }
-
- public string Path { get; private set; }
-
- public Encoding Encoding { get; private set; }
-
- public StatVfsRequest(uint protocolVersion, uint requestId, string path, Encoding encoding, Action extendedAction, Action statusAction)
- : base(protocolVersion, requestId, statusAction)
- {
- this.Path = path;
- this.Encoding = encoding;
- this.SetAction(extendedAction);
- }
-
- protected override void SaveData()
- {
- base.SaveData();
- this.Write(this.Path, this.Encoding);
- }
- }
-}
+using System;
+using Renci.SshNet.Sftp.Responses;
+using System.Text;
+
+namespace Renci.SshNet.Sftp.Requests
+{
+ internal class StatVfsRequest : SftpExtendedRequest
+ {
+ public override SftpMessageTypes SftpMessageType
+ {
+ get { return SftpMessageTypes.Extended; }
+ }
+
+ public override string Name
+ {
+ get { return "statvfs@openssh.com"; }
+ }
+
+ public string Path { get; private set; }
+
+ public Encoding Encoding { get; private set; }
+
+ public StatVfsRequest(uint protocolVersion, uint requestId, string path, Encoding encoding, Action extendedAction, Action statusAction)
+ : base(protocolVersion, requestId, statusAction)
+ {
+ this.Path = path;
+ this.Encoding = encoding;
+ this.SetAction(extendedAction);
+ }
+
+ protected override void SaveData()
+ {
+ base.SaveData();
+ this.Write(this.Path, this.Encoding);
+ }
+ }
+}
diff --git a/Renci.SshNet/Sftp/Requests/PosixRenameRequest.cs b/Renci.SshNet/Sftp/Requests/PosixRenameRequest.cs
index a593e44..b272aa1 100644
--- a/Renci.SshNet/Sftp/Requests/PosixRenameRequest.cs
+++ b/Renci.SshNet/Sftp/Requests/PosixRenameRequest.cs
@@ -1,34 +1,34 @@
-using System;
-using Renci.SshNet.Sftp.Responses;
-
-namespace Renci.SshNet.Sftp.Requests
-{
- internal class PosixRenameRequest : SftpRequest
- {
- public const string NAME = "posix-rename@openssh.com";
-
- public override SftpMessageTypes SftpMessageType
- {
- get { return SftpMessageTypes.Extended; }
- }
-
- public string OldPath { get; private set; }
-
- public string NewPath { get; private set; }
-
- public PosixRenameRequest(uint protocolVersion, uint requestId, string oldPath, string newPath, Action statusAction)
- : base(protocolVersion, requestId, statusAction)
- {
- this.OldPath = oldPath;
- this.NewPath = newPath;
- }
-
- protected override void SaveData()
- {
- base.SaveData();
- this.Write(PosixRenameRequest.NAME);
- this.Write(this.OldPath);
- this.Write(this.NewPath);
- }
- }
+using System;
+using Renci.SshNet.Sftp.Responses;
+
+namespace Renci.SshNet.Sftp.Requests
+{
+ internal class PosixRenameRequest : SftpRequest
+ {
+ public const string NAME = "posix-rename@openssh.com";
+
+ public override SftpMessageTypes SftpMessageType
+ {
+ get { return SftpMessageTypes.Extended; }
+ }
+
+ public string OldPath { get; private set; }
+
+ public string NewPath { get; private set; }
+
+ public PosixRenameRequest(uint protocolVersion, uint requestId, string oldPath, string newPath, Action statusAction)
+ : base(protocolVersion, requestId, statusAction)
+ {
+ this.OldPath = oldPath;
+ this.NewPath = newPath;
+ }
+
+ protected override void SaveData()
+ {
+ base.SaveData();
+ this.Write(PosixRenameRequest.NAME);
+ this.Write(this.OldPath);
+ this.Write(this.NewPath);
+ }
+ }
}
\ No newline at end of file
diff --git a/Renci.SshNet/Sftp/Requests/SftpBlockRequest.cs b/Renci.SshNet/Sftp/Requests/SftpBlockRequest.cs
index 45424db..d17e6f1 100644
--- a/Renci.SshNet/Sftp/Requests/SftpBlockRequest.cs
+++ b/Renci.SshNet/Sftp/Requests/SftpBlockRequest.cs
@@ -1,51 +1,48 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Renci.SshNet.Sftp.Responses;
-
-namespace Renci.SshNet.Sftp.Requests
-{
- internal class SftpBlockRequest : SftpRequest
- {
- public override SftpMessageTypes SftpMessageType
- {
- get { return SftpMessageTypes.Block; }
- }
-
- public byte[] Handle { get; private set; }
-
- public UInt64 Offset { get; private set; }
-
- public UInt64 Length { get; private set; }
-
- public UInt32 LockMask { get; private set; }
-
- public SftpBlockRequest(uint protocolVersion, uint requestId, byte[] handle, UInt64 offset, UInt64 length, UInt32 lockMask, Action statusAction)
- : base(protocolVersion, requestId, statusAction)
- {
- this.Handle = handle;
- this.Offset = offset;
- this.Length = length;
- this.LockMask = lockMask;
- }
-
- protected override void LoadData()
- {
- base.LoadData();
- this.Handle = this.ReadBinaryString();
- this.Offset = this.ReadUInt64();
- this.Length = this.ReadUInt64();
- this.LockMask = this.ReadUInt32();
- }
-
- protected override void SaveData()
- {
- base.SaveData();
- this.WriteBinaryString(this.Handle);
- this.Write(this.Offset);
- this.Write(this.Length);
- this.Write(this.LockMask);
- }
- }
-}
+using System;
+using Renci.SshNet.Sftp.Responses;
+
+namespace Renci.SshNet.Sftp.Requests
+{
+ internal class SftpBlockRequest : SftpRequest
+ {
+ public override SftpMessageTypes SftpMessageType
+ {
+ get { return SftpMessageTypes.Block; }
+ }
+
+ public byte[] Handle { get; private set; }
+
+ public UInt64 Offset { get; private set; }
+
+ public UInt64 Length { get; private set; }
+
+ public UInt32 LockMask { get; private set; }
+
+ public SftpBlockRequest(uint protocolVersion, uint requestId, byte[] handle, UInt64 offset, UInt64 length, UInt32 lockMask, Action statusAction)
+ : base(protocolVersion, requestId, statusAction)
+ {
+ this.Handle = handle;
+ this.Offset = offset;
+ this.Length = length;
+ this.LockMask = lockMask;
+ }
+
+ protected override void LoadData()
+ {
+ base.LoadData();
+ this.Handle = this.ReadBinaryString();
+ this.Offset = this.ReadUInt64();
+ this.Length = this.ReadUInt64();
+ this.LockMask = this.ReadUInt32();
+ }
+
+ protected override void SaveData()
+ {
+ base.SaveData();
+ this.WriteBinaryString(this.Handle);
+ this.Write(this.Offset);
+ this.Write(this.Length);
+ this.Write(this.LockMask);
+ }
+ }
+}
diff --git a/Renci.SshNet/Sftp/Requests/SftpCloseRequest.cs b/Renci.SshNet/Sftp/Requests/SftpCloseRequest.cs
index f034607..3ceb1fd 100644
--- a/Renci.SshNet/Sftp/Requests/SftpCloseRequest.cs
+++ b/Renci.SshNet/Sftp/Requests/SftpCloseRequest.cs
@@ -1,36 +1,33 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Renci.SshNet.Sftp.Responses;
-
-namespace Renci.SshNet.Sftp.Requests
-{
- internal class SftpCloseRequest : SftpRequest
- {
- public override SftpMessageTypes SftpMessageType
- {
- get { return SftpMessageTypes.Close; }
- }
-
- public byte[] Handle { get; private set; }
-
- public SftpCloseRequest(uint protocolVersion, uint requestId, byte[] handle, Action statusAction)
- : base(protocolVersion, requestId, statusAction)
- {
- this.Handle = handle;
- }
-
- protected override void LoadData()
- {
- base.LoadData();
- this.Handle = this.ReadBinaryString();
- }
-
- protected override void SaveData()
- {
- base.SaveData();
- this.WriteBinaryString(this.Handle);
- }
- }
-}
+using System;
+using Renci.SshNet.Sftp.Responses;
+
+namespace Renci.SshNet.Sftp.Requests
+{
+ internal class SftpCloseRequest : SftpRequest
+ {
+ public override SftpMessageTypes SftpMessageType
+ {
+ get { return SftpMessageTypes.Close; }
+ }
+
+ public byte[] Handle { get; private set; }
+
+ public SftpCloseRequest(uint protocolVersion, uint requestId, byte[] handle, Action statusAction)
+ : base(protocolVersion, requestId, statusAction)
+ {
+ this.Handle = handle;
+ }
+
+ protected override void LoadData()
+ {
+ base.LoadData();
+ this.Handle = this.ReadBinaryString();
+ }
+
+ protected override void SaveData()
+ {
+ base.SaveData();
+ this.WriteBinaryString(this.Handle);
+ }
+ }
+}
diff --git a/Renci.SshNet/Sftp/Requests/SftpExtendedRequest.cs b/Renci.SshNet/Sftp/Requests/SftpExtendedRequest.cs
index f716691..e500e51 100644
--- a/Renci.SshNet/Sftp/Requests/SftpExtendedRequest.cs
+++ b/Renci.SshNet/Sftp/Requests/SftpExtendedRequest.cs
@@ -1,28 +1,28 @@
-using System;
-using Renci.SshNet.Sftp.Responses;
-
-namespace Renci.SshNet.Sftp.Requests
-{
- internal abstract class SftpExtendedRequest : SftpRequest
- {
- public const string NAME = "posix-rename@openssh.com";
-
- public override SftpMessageTypes SftpMessageType
- {
- get { return SftpMessageTypes.Extended; }
- }
-
- public abstract string Name { get; }
-
- public SftpExtendedRequest(uint protocolVersion, uint requestId, Action statusAction)
- : base(protocolVersion, requestId, statusAction)
- {
- }
-
- protected override void SaveData()
- {
- base.SaveData();
- this.Write(this.Name);
- }
- }
+using System;
+using Renci.SshNet.Sftp.Responses;
+
+namespace Renci.SshNet.Sftp.Requests
+{
+ internal abstract class SftpExtendedRequest : SftpRequest
+ {
+ public const string NAME = "posix-rename@openssh.com";
+
+ public override SftpMessageTypes SftpMessageType
+ {
+ get { return SftpMessageTypes.Extended; }
+ }
+
+ public abstract string Name { get; }
+
+ public SftpExtendedRequest(uint protocolVersion, uint requestId, Action statusAction)
+ : base(protocolVersion, requestId, statusAction)
+ {
+ }
+
+ protected override void SaveData()
+ {
+ base.SaveData();
+ this.Write(this.Name);
+ }
+ }
}
\ No newline at end of file
diff --git a/Renci.SshNet/Sftp/Requests/SftpFSetStatRequest.cs b/Renci.SshNet/Sftp/Requests/SftpFSetStatRequest.cs
index cf1b501..64795d0 100644
--- a/Renci.SshNet/Sftp/Requests/SftpFSetStatRequest.cs
+++ b/Renci.SshNet/Sftp/Requests/SftpFSetStatRequest.cs
@@ -1,41 +1,38 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Renci.SshNet.Sftp.Responses;
-
-namespace Renci.SshNet.Sftp.Requests
-{
- internal class SftpFSetStatRequest : SftpRequest
- {
- public override SftpMessageTypes SftpMessageType
- {
- get { return SftpMessageTypes.FSetStat; }
- }
-
- public byte[] Handle { get; private set; }
-
- public SftpFileAttributes Attributes { get; private set; }
-
- public SftpFSetStatRequest(uint protocolVersion, uint requestId, byte[] handle, SftpFileAttributes attributes, Action statusAction)
- : base(protocolVersion, requestId, statusAction)
- {
- this.Handle = handle;
- this.Attributes = attributes;
- }
-
- protected override void LoadData()
- {
- base.LoadData();
- this.Handle = this.ReadBinaryString();
- this.Attributes = this.ReadAttributes();
- }
-
- protected override void SaveData()
- {
- base.SaveData();
- this.WriteBinaryString(this.Handle);
- this.Write(this.Attributes);
- }
- }
-}
+using System;
+using Renci.SshNet.Sftp.Responses;
+
+namespace Renci.SshNet.Sftp.Requests
+{
+ internal class SftpFSetStatRequest : SftpRequest
+ {
+ public override SftpMessageTypes SftpMessageType
+ {
+ get { return SftpMessageTypes.FSetStat; }
+ }
+
+ public byte[] Handle { get; private set; }
+
+ public SftpFileAttributes Attributes { get; private set; }
+
+ public SftpFSetStatRequest(uint protocolVersion, uint requestId, byte[] handle, SftpFileAttributes attributes, Action statusAction)
+ : base(protocolVersion, requestId, statusAction)
+ {
+ this.Handle = handle;
+ this.Attributes = attributes;
+ }
+
+ protected override void LoadData()
+ {
+ base.LoadData();
+ this.Handle = this.ReadBinaryString();
+ this.Attributes = this.ReadAttributes();
+ }
+
+ protected override void SaveData()
+ {
+ base.SaveData();
+ this.WriteBinaryString(this.Handle);
+ this.Write(this.Attributes);
+ }
+ }
+}
diff --git a/Renci.SshNet/Sftp/Requests/SftpFStatRequest.cs b/Renci.SshNet/Sftp/Requests/SftpFStatRequest.cs
index 075c819..9265891 100644
--- a/Renci.SshNet/Sftp/Requests/SftpFStatRequest.cs
+++ b/Renci.SshNet/Sftp/Requests/SftpFStatRequest.cs
@@ -1,37 +1,34 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Renci.SshNet.Sftp.Responses;
-
-namespace Renci.SshNet.Sftp.Requests
-{
- internal class SftpFStatRequest : SftpRequest
- {
- public override SftpMessageTypes SftpMessageType
- {
- get { return SftpMessageTypes.FStat; }
- }
-
- public byte[] Handle { get; private set; }
-
- public SftpFStatRequest(uint protocolVersion, uint requestId, byte[] handle, Action attrsAction, Action statusAction)
- : base(protocolVersion, requestId, statusAction)
- {
- this.Handle = handle;
- this.SetAction(attrsAction);
- }
-
- protected override void LoadData()
- {
- base.LoadData();
- this.Handle = this.ReadBinaryString();
- }
-
- protected override void SaveData()
- {
- base.SaveData();
- this.WriteBinaryString(this.Handle);
- }
- }
-}
+using System;
+using Renci.SshNet.Sftp.Responses;
+
+namespace Renci.SshNet.Sftp.Requests
+{
+ internal class SftpFStatRequest : SftpRequest
+ {
+ public override SftpMessageTypes SftpMessageType
+ {
+ get { return SftpMessageTypes.FStat; }
+ }
+
+ public byte[] Handle { get; private set; }
+
+ public SftpFStatRequest(uint protocolVersion, uint requestId, byte[] handle, Action attrsAction, Action statusAction)
+ : base(protocolVersion, requestId, statusAction)
+ {
+ this.Handle = handle;
+ this.SetAction(attrsAction);
+ }
+
+ protected override void LoadData()
+ {
+ base.LoadData();
+ this.Handle = this.ReadBinaryString();
+ }
+
+ protected override void SaveData()
+ {
+ base.SaveData();
+ this.WriteBinaryString(this.Handle);
+ }
+ }
+}
diff --git a/Renci.SshNet/Sftp/Requests/SftpInitRequest.cs b/Renci.SshNet/Sftp/Requests/SftpInitRequest.cs
index f329597..7d05694 100644
--- a/Renci.SshNet/Sftp/Requests/SftpInitRequest.cs
+++ b/Renci.SshNet/Sftp/Requests/SftpInitRequest.cs
@@ -1,34 +1,29 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace Renci.SshNet.Sftp.Requests
-{
- internal class SftpInitRequest : SftpMessage
- {
- public override SftpMessageTypes SftpMessageType
- {
- get { return SftpMessageTypes.Init; }
- }
-
- public uint Version { get; private set; }
-
- public SftpInitRequest(uint version)
- {
- this.Version = version;
- }
-
- protected override void LoadData()
- {
- base.LoadData();
- this.Version = this.ReadUInt32();
- }
-
- protected override void SaveData()
- {
- base.SaveData();
- this.Write(this.Version);
- }
- }
-}
+namespace Renci.SshNet.Sftp.Requests
+{
+ internal class SftpInitRequest : SftpMessage
+ {
+ public override SftpMessageTypes SftpMessageType
+ {
+ get { return SftpMessageTypes.Init; }
+ }
+
+ public uint Version { get; private set; }
+
+ public SftpInitRequest(uint version)
+ {
+ this.Version = version;
+ }
+
+ protected override void LoadData()
+ {
+ base.LoadData();
+ this.Version = this.ReadUInt32();
+ }
+
+ protected override void SaveData()
+ {
+ base.SaveData();
+ this.Write(this.Version);
+ }
+ }
+}
diff --git a/Renci.SshNet/Sftp/Requests/SftpLStatRequest.cs b/Renci.SshNet/Sftp/Requests/SftpLStatRequest.cs
index a57d3d2..b03545c 100644
--- a/Renci.SshNet/Sftp/Requests/SftpLStatRequest.cs
+++ b/Renci.SshNet/Sftp/Requests/SftpLStatRequest.cs
@@ -1,40 +1,38 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Renci.SshNet.Sftp.Responses;
-
-namespace Renci.SshNet.Sftp.Requests
-{
- internal class SftpLStatRequest : SftpRequest
- {
- public override SftpMessageTypes SftpMessageType
- {
- get { return SftpMessageTypes.LStat; }
- }
-
- public string Path { get; private set; }
-
- public Encoding Encoding { get; private set; }
-
- public SftpLStatRequest(uint protocolVersion, uint requestId, string path, Encoding encoding, Action attrsAction, Action statusAction)
- : base(protocolVersion, requestId, statusAction)
- {
- this.Path = path;
- this.Encoding = encoding;
- this.SetAction(attrsAction);
- }
-
- protected override void LoadData()
- {
- base.LoadData();
- this.Path = this.ReadString(this.Encoding);
- }
-
- protected override void SaveData()
- {
- base.SaveData();
- this.Write(this.Path, this.Encoding);
- }
- }
-}
+using System;
+using System.Text;
+using Renci.SshNet.Sftp.Responses;
+
+namespace Renci.SshNet.Sftp.Requests
+{
+ internal class SftpLStatRequest : SftpRequest
+ {
+ public override SftpMessageTypes SftpMessageType
+ {
+ get { return SftpMessageTypes.LStat; }
+ }
+
+ public string Path { get; private set; }
+
+ public Encoding Encoding { get; private set; }
+
+ public SftpLStatRequest(uint protocolVersion, uint requestId, string path, Encoding encoding, Action attrsAction, Action statusAction)
+ : base(protocolVersion, requestId, statusAction)
+ {
+ this.Path = path;
+ this.Encoding = encoding;
+ this.SetAction(attrsAction);
+ }
+
+ protected override void LoadData()
+ {
+ base.LoadData();
+ this.Path = this.ReadString(this.Encoding);
+ }
+
+ protected override void SaveData()
+ {
+ base.SaveData();
+ this.Write(this.Path, this.Encoding);
+ }
+ }
+}
diff --git a/Renci.SshNet/Sftp/Requests/SftpLinkRequest.cs b/Renci.SshNet/Sftp/Requests/SftpLinkRequest.cs
index b95cd7e..d62d0be 100644
--- a/Renci.SshNet/Sftp/Requests/SftpLinkRequest.cs
+++ b/Renci.SshNet/Sftp/Requests/SftpLinkRequest.cs
@@ -1,55 +1,52 @@
-using Renci.SshNet.Sftp.Responses;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-namespace Renci.SshNet.Sftp.Requests
-{
- internal class SftpLinkRequest : SftpRequest
- {
- public override SftpMessageTypes SftpMessageType
- {
- get { return SftpMessageTypes.Link; }
- }
-
- public string NewLinkPath { get; private set; }
-
- public string ExistingPath { get; private set; }
-
- public bool IsSymLink { get; private set; }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The protocol version.
- /// The request id.
- /// Specifies the path name of the new link to create.
- /// Specifies the path of a target object to which the newly created link will refer. In the case of a symbolic link, this path may not exist.
- /// if set to false the link should be a hard link, or a second directory entry referring to the same file or directory object.
- /// The status action.
- public SftpLinkRequest(uint protocolVersion, uint requestId, string newLinkPath, string existingPath, bool isSymLink, Action statusAction)
- : base(protocolVersion, requestId, statusAction)
- {
- this.NewLinkPath = newLinkPath;
- this.ExistingPath = existingPath;
- this.IsSymLink = isSymLink;
- }
-
- protected override void LoadData()
- {
- base.LoadData();
- this.NewLinkPath = this.ReadString();
- this.ExistingPath = this.ReadString();
- this.IsSymLink = this.ReadBoolean();
- }
-
- protected override void SaveData()
- {
- base.SaveData();
- this.Write(this.NewLinkPath);
- this.Write(this.ExistingPath);
- this.Write(this.IsSymLink);
- }
- }
-}
+using Renci.SshNet.Sftp.Responses;
+using System;
+
+namespace Renci.SshNet.Sftp.Requests
+{
+ internal class SftpLinkRequest : SftpRequest
+ {
+ public override SftpMessageTypes SftpMessageType
+ {
+ get { return SftpMessageTypes.Link; }
+ }
+
+ public string NewLinkPath { get; private set; }
+
+ public string ExistingPath { get; private set; }
+
+ public bool IsSymLink { get; private set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The protocol version.
+ /// The request id.
+ /// Specifies the path name of the new link to create.
+ /// Specifies the path of a target object to which the newly created link will refer. In the case of a symbolic link, this path may not exist.
+ /// if set to false the link should be a hard link, or a second directory entry referring to the same file or directory object.
+ /// The status action.
+ public SftpLinkRequest(uint protocolVersion, uint requestId, string newLinkPath, string existingPath, bool isSymLink, Action statusAction)
+ : base(protocolVersion, requestId, statusAction)
+ {
+ this.NewLinkPath = newLinkPath;
+ this.ExistingPath = existingPath;
+ this.IsSymLink = isSymLink;
+ }
+
+ protected override void LoadData()
+ {
+ base.LoadData();
+ this.NewLinkPath = this.ReadString();
+ this.ExistingPath = this.ReadString();
+ this.IsSymLink = this.ReadBoolean();
+ }
+
+ protected override void SaveData()
+ {
+ base.SaveData();
+ this.Write(this.NewLinkPath);
+ this.Write(this.ExistingPath);
+ this.Write(this.IsSymLink);
+ }
+ }
+}
diff --git a/Renci.SshNet/Sftp/Requests/SftpMkDirRequest.cs b/Renci.SshNet/Sftp/Requests/SftpMkDirRequest.cs
index cef26f6..ef7a690 100644
--- a/Renci.SshNet/Sftp/Requests/SftpMkDirRequest.cs
+++ b/Renci.SshNet/Sftp/Requests/SftpMkDirRequest.cs
@@ -1,49 +1,47 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Renci.SshNet.Sftp.Responses;
-
-namespace Renci.SshNet.Sftp.Requests
-{
- internal class SftpMkDirRequest : SftpRequest
- {
- public override SftpMessageTypes SftpMessageType
- {
- get { return SftpMessageTypes.MkDir; }
- }
-
- public string Path { get; private set; }
-
- public Encoding Encoding { get; private set; }
-
- public SftpFileAttributes Attributes { get; private set; }
-
- public SftpMkDirRequest(uint protocolVersion, uint requestId, string path, Encoding encoding, Action statusAction)
- : this(protocolVersion, requestId, path, encoding, null, statusAction)
- {
- }
-
- public SftpMkDirRequest(uint protocolVersion, uint requestId, string path, Encoding encoding, SftpFileAttributes attributes, Action statusAction)
- : base(protocolVersion, requestId, statusAction)
- {
- this.Path = path;
- this.Encoding = encoding;
- this.Attributes = attributes;
- }
-
- protected override void LoadData()
- {
- base.LoadData();
- this.Path = this.ReadString(this.Encoding);
- this.Attributes = this.ReadAttributes();
- }
-
- protected override void SaveData()
- {
- base.SaveData();
- this.Write(this.Path, this.Encoding);
- this.Write(this.Attributes);
- }
- }
-}
+using System;
+using System.Text;
+using Renci.SshNet.Sftp.Responses;
+
+namespace Renci.SshNet.Sftp.Requests
+{
+ internal class SftpMkDirRequest : SftpRequest
+ {
+ public override SftpMessageTypes SftpMessageType
+ {
+ get { return SftpMessageTypes.MkDir; }
+ }
+
+ public string Path { get; private set; }
+
+ public Encoding Encoding { get; private set; }
+
+ public SftpFileAttributes Attributes { get; private set; }
+
+ public SftpMkDirRequest(uint protocolVersion, uint requestId, string path, Encoding encoding, Action statusAction)
+ : this(protocolVersion, requestId, path, encoding, null, statusAction)
+ {
+ }
+
+ public SftpMkDirRequest(uint protocolVersion, uint requestId, string path, Encoding encoding, SftpFileAttributes attributes, Action statusAction)
+ : base(protocolVersion, requestId, statusAction)
+ {
+ this.Path = path;
+ this.Encoding = encoding;
+ this.Attributes = attributes;
+ }
+
+ protected override void LoadData()
+ {
+ base.LoadData();
+ this.Path = this.ReadString(this.Encoding);
+ this.Attributes = this.ReadAttributes();
+ }
+
+ protected override void SaveData()
+ {
+ base.SaveData();
+ this.Write(this.Path, this.Encoding);
+ this.Write(this.Attributes);
+ }
+ }
+}
diff --git a/Renci.SshNet/Sftp/Requests/SftpOpenDirRequest.cs b/Renci.SshNet/Sftp/Requests/SftpOpenDirRequest.cs
index 89b0a24..6792031 100644
--- a/Renci.SshNet/Sftp/Requests/SftpOpenDirRequest.cs
+++ b/Renci.SshNet/Sftp/Requests/SftpOpenDirRequest.cs
@@ -1,40 +1,38 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Renci.SshNet.Sftp.Responses;
-
-namespace Renci.SshNet.Sftp.Requests
-{
- internal class SftpOpenDirRequest : SftpRequest
- {
- public override SftpMessageTypes SftpMessageType
- {
- get { return SftpMessageTypes.OpenDir; }
- }
-
- public string Path { get; private set; }
-
- public Encoding Encoding { get; private set; }
-
- public SftpOpenDirRequest(uint protocolVersion, uint requestId, string path, Encoding encoding, Action handleAction, Action statusAction)
- : base(protocolVersion, requestId, statusAction)
- {
- this.Path = path;
- this.Encoding = encoding;
- this.SetAction(handleAction);
- }
-
- protected override void LoadData()
- {
- base.LoadData();
- this.Path = this.ReadString(this.Encoding);
- }
-
- protected override void SaveData()
- {
- base.SaveData();
- this.Write(this.Path, this.Encoding);
- }
- }
-}
+using System;
+using System.Text;
+using Renci.SshNet.Sftp.Responses;
+
+namespace Renci.SshNet.Sftp.Requests
+{
+ internal class SftpOpenDirRequest : SftpRequest
+ {
+ public override SftpMessageTypes SftpMessageType
+ {
+ get { return SftpMessageTypes.OpenDir; }
+ }
+
+ public string Path { get; private set; }
+
+ public Encoding Encoding { get; private set; }
+
+ public SftpOpenDirRequest(uint protocolVersion, uint requestId, string path, Encoding encoding, Action handleAction, Action statusAction)
+ : base(protocolVersion, requestId, statusAction)
+ {
+ this.Path = path;
+ this.Encoding = encoding;
+ this.SetAction(handleAction);
+ }
+
+ protected override void LoadData()
+ {
+ base.LoadData();
+ this.Path = this.ReadString(this.Encoding);
+ }
+
+ protected override void SaveData()
+ {
+ base.SaveData();
+ this.Write(this.Path, this.Encoding);
+ }
+ }
+}
diff --git a/Renci.SshNet/Sftp/Requests/SftpOpenRequest.cs b/Renci.SshNet/Sftp/Requests/SftpOpenRequest.cs
index 853cc76..9fa3333 100644
--- a/Renci.SshNet/Sftp/Requests/SftpOpenRequest.cs
+++ b/Renci.SshNet/Sftp/Requests/SftpOpenRequest.cs
@@ -1,55 +1,53 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Renci.SshNet.Sftp.Responses;
-
-namespace Renci.SshNet.Sftp.Requests
-{
- internal class SftpOpenRequest : SftpRequest
- {
- public override SftpMessageTypes SftpMessageType
- {
- get { return SftpMessageTypes.Open; }
- }
-
- public string Filename { get; private set; }
-
- public Flags Flags { get; private set; }
-
- public SftpFileAttributes Attributes { get; private set; }
-
- public Encoding Encoding { get; private set; }
-
- public SftpOpenRequest(uint protocolVersion, uint requestId, string fileName, Encoding encoding, Flags flags, Action handleAction, Action statusAction)
- : this(protocolVersion, requestId, fileName, encoding, flags, new SftpFileAttributes(), handleAction, statusAction)
- {
- }
-
- public SftpOpenRequest(uint protocolVersion, uint requestId, string fileName, Encoding encoding, Flags flags, SftpFileAttributes attributes, Action handleAction, Action statusAction)
- : base(protocolVersion, requestId, statusAction)
- {
- this.Filename = fileName;
- this.Flags = flags;
- this.Attributes = attributes;
- this.Encoding = encoding;
-
- this.SetAction(handleAction);
- }
-
- protected override void LoadData()
- {
- base.LoadData();
- throw new NotSupportedException();
- }
-
- protected override void SaveData()
- {
- base.SaveData();
-
- this.Write(this.Filename, this.Encoding);
- this.Write((uint)this.Flags);
- this.Write(this.Attributes);
- }
- }
-}
+using System;
+using System.Text;
+using Renci.SshNet.Sftp.Responses;
+
+namespace Renci.SshNet.Sftp.Requests
+{
+ internal class SftpOpenRequest : SftpRequest
+ {
+ public override SftpMessageTypes SftpMessageType
+ {
+ get { return SftpMessageTypes.Open; }
+ }
+
+ public string Filename { get; private set; }
+
+ public Flags Flags { get; private set; }
+
+ public SftpFileAttributes Attributes { get; private set; }
+
+ public Encoding Encoding { get; private set; }
+
+ public SftpOpenRequest(uint protocolVersion, uint requestId, string fileName, Encoding encoding, Flags flags, Action handleAction, Action statusAction)
+ : this(protocolVersion, requestId, fileName, encoding, flags, new SftpFileAttributes(), handleAction, statusAction)
+ {
+ }
+
+ public SftpOpenRequest(uint protocolVersion, uint requestId, string fileName, Encoding encoding, Flags flags, SftpFileAttributes attributes, Action handleAction, Action statusAction)
+ : base(protocolVersion, requestId, statusAction)
+ {
+ this.Filename = fileName;
+ this.Flags = flags;
+ this.Attributes = attributes;
+ this.Encoding = encoding;
+
+ this.SetAction(handleAction);
+ }
+
+ protected override void LoadData()
+ {
+ base.LoadData();
+ throw new NotSupportedException();
+ }
+
+ protected override void SaveData()
+ {
+ base.SaveData();
+
+ this.Write(this.Filename, this.Encoding);
+ this.Write((uint)this.Flags);
+ this.Write(this.Attributes);
+ }
+ }
+}
diff --git a/Renci.SshNet/Sftp/Requests/SftpReadDirRequest.cs b/Renci.SshNet/Sftp/Requests/SftpReadDirRequest.cs
index c666d71..90806b8 100644
--- a/Renci.SshNet/Sftp/Requests/SftpReadDirRequest.cs
+++ b/Renci.SshNet/Sftp/Requests/SftpReadDirRequest.cs
@@ -1,37 +1,34 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Renci.SshNet.Sftp.Responses;
-
-namespace Renci.SshNet.Sftp.Requests
-{
- internal class SftpReadDirRequest : SftpRequest
- {
- public override SftpMessageTypes SftpMessageType
- {
- get { return SftpMessageTypes.ReadDir; }
- }
-
- public byte[] Handle { get; private set; }
-
- public SftpReadDirRequest(uint protocolVersion, uint requestId, byte[] handle, Action nameAction, Action statusAction)
- : base(protocolVersion, requestId, statusAction)
- {
- this.Handle = handle;
- this.SetAction(nameAction);
- }
-
- protected override void LoadData()
- {
- base.LoadData();
- this.Handle = this.ReadBinaryString();
- }
-
- protected override void SaveData()
- {
- base.SaveData();
- this.WriteBinaryString(this.Handle);
- }
- }
-}
+using System;
+using Renci.SshNet.Sftp.Responses;
+
+namespace Renci.SshNet.Sftp.Requests
+{
+ internal class SftpReadDirRequest : SftpRequest
+ {
+ public override SftpMessageTypes SftpMessageType
+ {
+ get { return SftpMessageTypes.ReadDir; }
+ }
+
+ public byte[] Handle { get; private set; }
+
+ public SftpReadDirRequest(uint protocolVersion, uint requestId, byte[] handle, Action nameAction, Action statusAction)
+ : base(protocolVersion, requestId, statusAction)
+ {
+ this.Handle = handle;
+ this.SetAction(nameAction);
+ }
+
+ protected override void LoadData()
+ {
+ base.LoadData();
+ this.Handle = this.ReadBinaryString();
+ }
+
+ protected override void SaveData()
+ {
+ base.SaveData();
+ this.WriteBinaryString(this.Handle);
+ }
+ }
+}
diff --git a/Renci.SshNet/Sftp/Requests/SftpReadLinkRequest.cs b/Renci.SshNet/Sftp/Requests/SftpReadLinkRequest.cs
index e3f279e..e567a11 100644
--- a/Renci.SshNet/Sftp/Requests/SftpReadLinkRequest.cs
+++ b/Renci.SshNet/Sftp/Requests/SftpReadLinkRequest.cs
@@ -1,40 +1,38 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Renci.SshNet.Sftp.Responses;
-
-namespace Renci.SshNet.Sftp.Requests
-{
- internal class SftpReadLinkRequest : SftpRequest
- {
- public override SftpMessageTypes SftpMessageType
- {
- get { return SftpMessageTypes.ReadLink; }
- }
-
- public string Path { get; private set; }
-
- public Encoding Encoding { get; private set; }
-
- public SftpReadLinkRequest(uint protocolVersion, uint requestId, string path, Encoding encoding, Action nameAction, Action statusAction)
- : base(protocolVersion, requestId, statusAction)
- {
- this.Path = path;
- this.Encoding = encoding;
- this.SetAction(nameAction);
- }
-
- protected override void LoadData()
- {
- base.LoadData();
- this.Path = this.ReadString(this.Encoding);
- }
-
- protected override void SaveData()
- {
- base.SaveData();
- this.Write(this.Path, this.Encoding);
- }
- }
-}
+using System;
+using System.Text;
+using Renci.SshNet.Sftp.Responses;
+
+namespace Renci.SshNet.Sftp.Requests
+{
+ internal class SftpReadLinkRequest : SftpRequest
+ {
+ public override SftpMessageTypes SftpMessageType
+ {
+ get { return SftpMessageTypes.ReadLink; }
+ }
+
+ public string Path { get; private set; }
+
+ public Encoding Encoding { get; private set; }
+
+ public SftpReadLinkRequest(uint protocolVersion, uint requestId, string path, Encoding encoding, Action nameAction, Action statusAction)
+ : base(protocolVersion, requestId, statusAction)
+ {
+ this.Path = path;
+ this.Encoding = encoding;
+ this.SetAction(nameAction);
+ }
+
+ protected override void LoadData()
+ {
+ base.LoadData();
+ this.Path = this.ReadString(this.Encoding);
+ }
+
+ protected override void SaveData()
+ {
+ base.SaveData();
+ this.Write(this.Path, this.Encoding);
+ }
+ }
+}
diff --git a/Renci.SshNet/Sftp/Requests/SftpReadRequest.cs b/Renci.SshNet/Sftp/Requests/SftpReadRequest.cs
index 2db39b4..745035d 100644
--- a/Renci.SshNet/Sftp/Requests/SftpReadRequest.cs
+++ b/Renci.SshNet/Sftp/Requests/SftpReadRequest.cs
@@ -1,47 +1,44 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Renci.SshNet.Sftp.Responses;
-
-namespace Renci.SshNet.Sftp.Requests
-{
- internal class SftpReadRequest : SftpRequest
- {
- public override SftpMessageTypes SftpMessageType
- {
- get { return SftpMessageTypes.Read; }
- }
-
- public byte[] Handle { get; private set; }
-
- public UInt64 Offset { get; private set; }
-
- public UInt32 Length { get; private set; }
-
- public SftpReadRequest(uint protocolVersion, uint requestId, byte[] handle, UInt64 offset, UInt32 length, Action dataAction, Action statusAction)
- : base(protocolVersion, requestId, statusAction)
- {
- this.Handle = handle;
- this.Offset = offset;
- this.Length = length;
- this.SetAction(dataAction);
- }
-
- protected override void LoadData()
- {
- base.LoadData();
- this.Handle = this.ReadBinaryString();
- this.Offset = this.ReadUInt64();
- this.Length = this.ReadUInt32();
- }
-
- protected override void SaveData()
- {
- base.SaveData();
- this.WriteBinaryString(this.Handle);
- this.Write(this.Offset);
- this.Write(this.Length);
- }
- }
-}
+using System;
+using Renci.SshNet.Sftp.Responses;
+
+namespace Renci.SshNet.Sftp.Requests
+{
+ internal class SftpReadRequest : SftpRequest
+ {
+ public override SftpMessageTypes SftpMessageType
+ {
+ get { return SftpMessageTypes.Read; }
+ }
+
+ public byte[] Handle { get; private set; }
+
+ public UInt64 Offset { get; private set; }
+
+ public UInt32 Length { get; private set; }
+
+ public SftpReadRequest(uint protocolVersion, uint requestId, byte[] handle, UInt64 offset, UInt32 length, Action dataAction, Action statusAction)
+ : base(protocolVersion, requestId, statusAction)
+ {
+ this.Handle = handle;
+ this.Offset = offset;
+ this.Length = length;
+ this.SetAction(dataAction);
+ }
+
+ protected override void LoadData()
+ {
+ base.LoadData();
+ this.Handle = this.ReadBinaryString();
+ this.Offset = this.ReadUInt64();
+ this.Length = this.ReadUInt32();
+ }
+
+ protected override void SaveData()
+ {
+ base.SaveData();
+ this.WriteBinaryString(this.Handle);
+ this.Write(this.Offset);
+ this.Write(this.Length);
+ }
+ }
+}
diff --git a/Renci.SshNet/Sftp/Requests/SftpRealPathRequest.cs b/Renci.SshNet/Sftp/Requests/SftpRealPathRequest.cs
index d23e3e3..e0e193c 100644
--- a/Renci.SshNet/Sftp/Requests/SftpRealPathRequest.cs
+++ b/Renci.SshNet/Sftp/Requests/SftpRealPathRequest.cs
@@ -1,41 +1,38 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Renci.SshNet.Sftp.Responses;
-
-namespace Renci.SshNet.Sftp.Requests
-{
- internal class SftpRealPathRequest : SftpRequest
- {
- public override SftpMessageTypes SftpMessageType
- {
- get { return SftpMessageTypes.RealPath; }
- }
-
- public string Path { get; private set; }
-
- public Encoding Encoding { get; private set; }
-
- public SftpRealPathRequest(uint protocolVersion, uint requestId, string path, Encoding encoding, Action nameAction, Action statusAction)
- : base(protocolVersion, requestId, statusAction)
- {
- if (nameAction == null)
- throw new ArgumentNullException("name");
-
- if (statusAction == null)
- throw new ArgumentNullException("status");
-
- this.Path = path;
- this.Encoding = encoding;
- this.SetAction(nameAction);
-
- }
-
- protected override void SaveData()
- {
- base.SaveData();
- this.Write(this.Path, this.Encoding);
- }
- }
-}
+using System;
+using System.Text;
+using Renci.SshNet.Sftp.Responses;
+
+namespace Renci.SshNet.Sftp.Requests
+{
+ internal class SftpRealPathRequest : SftpRequest
+ {
+ public override SftpMessageTypes SftpMessageType
+ {
+ get { return SftpMessageTypes.RealPath; }
+ }
+
+ public string Path { get; private set; }
+
+ public Encoding Encoding { get; private set; }
+
+ public SftpRealPathRequest(uint protocolVersion, uint requestId, string path, Encoding encoding, Action nameAction, Action statusAction)
+ : base(protocolVersion, requestId, statusAction)
+ {
+ if (nameAction == null)
+ throw new ArgumentNullException("nameAction");
+ if (statusAction == null)
+ throw new ArgumentNullException("statusAction");
+
+ this.Path = path;
+ this.Encoding = encoding;
+ this.SetAction(nameAction);
+
+ }
+
+ protected override void SaveData()
+ {
+ base.SaveData();
+ this.Write(this.Path, this.Encoding);
+ }
+ }
+}
diff --git a/Renci.SshNet/Sftp/Requests/SftpRemoveRequest.cs b/Renci.SshNet/Sftp/Requests/SftpRemoveRequest.cs
index c71b481..8eefa27 100644
--- a/Renci.SshNet/Sftp/Requests/SftpRemoveRequest.cs
+++ b/Renci.SshNet/Sftp/Requests/SftpRemoveRequest.cs
@@ -1,39 +1,37 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Renci.SshNet.Sftp.Responses;
-
-namespace Renci.SshNet.Sftp.Requests
-{
- internal class SftpRemoveRequest : SftpRequest
- {
- public override SftpMessageTypes SftpMessageType
- {
- get { return SftpMessageTypes.Remove; }
- }
-
- public string Filename { get; private set; }
-
- public Encoding Encoding { get; private set; }
-
- public SftpRemoveRequest(uint protocolVersion, uint requestId, string filename, Encoding encoding, Action statusAction)
- : base(protocolVersion, requestId, statusAction)
- {
- this.Filename = filename;
- this.Encoding = encoding;
- }
-
- protected override void LoadData()
- {
- base.LoadData();
- this.Filename = this.ReadString(this.Encoding);
- }
-
- protected override void SaveData()
- {
- base.SaveData();
- this.Write(this.Filename, this.Encoding);
- }
- }
-}
+using System;
+using System.Text;
+using Renci.SshNet.Sftp.Responses;
+
+namespace Renci.SshNet.Sftp.Requests
+{
+ internal class SftpRemoveRequest : SftpRequest
+ {
+ public override SftpMessageTypes SftpMessageType
+ {
+ get { return SftpMessageTypes.Remove; }
+ }
+
+ public string Filename { get; private set; }
+
+ public Encoding Encoding { get; private set; }
+
+ public SftpRemoveRequest(uint protocolVersion, uint requestId, string filename, Encoding encoding, Action statusAction)
+ : base(protocolVersion, requestId, statusAction)
+ {
+ this.Filename = filename;
+ this.Encoding = encoding;
+ }
+
+ protected override void LoadData()
+ {
+ base.LoadData();
+ this.Filename = this.ReadString(this.Encoding);
+ }
+
+ protected override void SaveData()
+ {
+ base.SaveData();
+ this.Write(this.Filename, this.Encoding);
+ }
+ }
+}
diff --git a/Renci.SshNet/Sftp/Requests/SftpRenameRequest.cs b/Renci.SshNet/Sftp/Requests/SftpRenameRequest.cs
index 3267fb7..07aa990 100644
--- a/Renci.SshNet/Sftp/Requests/SftpRenameRequest.cs
+++ b/Renci.SshNet/Sftp/Requests/SftpRenameRequest.cs
@@ -1,44 +1,42 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Renci.SshNet.Sftp.Responses;
-
-namespace Renci.SshNet.Sftp.Requests
-{
- internal class SftpRenameRequest : SftpRequest
- {
- public override SftpMessageTypes SftpMessageType
- {
- get { return SftpMessageTypes.Rename; }
- }
-
- public string OldPath { get; private set; }
-
- public string NewPath { get; private set; }
-
- public Encoding Encoding { get; private set; }
-
- public SftpRenameRequest(uint protocolVersion, uint requestId, string oldPath, string newPath, Encoding encoding, Action statusAction)
- : base(protocolVersion, requestId, statusAction)
- {
- this.OldPath = oldPath;
- this.NewPath = newPath;
- this.Encoding = encoding;
- }
-
- protected override void LoadData()
- {
- base.LoadData();
- this.OldPath = this.ReadString(this.Encoding);
- this.NewPath = this.ReadString(this.Encoding);
- }
-
- protected override void SaveData()
- {
- base.SaveData();
- this.Write(this.OldPath, this.Encoding);
- this.Write(this.NewPath, this.Encoding);
- }
- }
-}
+using System;
+using System.Text;
+using Renci.SshNet.Sftp.Responses;
+
+namespace Renci.SshNet.Sftp.Requests
+{
+ internal class SftpRenameRequest : SftpRequest
+ {
+ public override SftpMessageTypes SftpMessageType
+ {
+ get { return SftpMessageTypes.Rename; }
+ }
+
+ public string OldPath { get; private set; }
+
+ public string NewPath { get; private set; }
+
+ public Encoding Encoding { get; private set; }
+
+ public SftpRenameRequest(uint protocolVersion, uint requestId, string oldPath, string newPath, Encoding encoding, Action statusAction)
+ : base(protocolVersion, requestId, statusAction)
+ {
+ this.OldPath = oldPath;
+ this.NewPath = newPath;
+ this.Encoding = encoding;
+ }
+
+ protected override void LoadData()
+ {
+ base.LoadData();
+ this.OldPath = this.ReadString(this.Encoding);
+ this.NewPath = this.ReadString(this.Encoding);
+ }
+
+ protected override void SaveData()
+ {
+ base.SaveData();
+ this.Write(this.OldPath, this.Encoding);
+ this.Write(this.NewPath, this.Encoding);
+ }
+ }
+}
diff --git a/Renci.SshNet/Sftp/Requests/SftpRequest.cs b/Renci.SshNet/Sftp/Requests/SftpRequest.cs
index c864034..f1964b5 100644
--- a/Renci.SshNet/Sftp/Requests/SftpRequest.cs
+++ b/Renci.SshNet/Sftp/Requests/SftpRequest.cs
@@ -1,98 +1,94 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Renci.SshNet.Sftp.Responses;
-using System.Threading;
-
-namespace Renci.SshNet.Sftp.Requests
-{
- internal abstract class SftpRequest : SftpMessage
- {
- private Action _statusAction;
- private Action _attrsAction;
- private Action _dataAction;
- private Action _extendedReplyAction;
- private Action _handleAction;
- private Action _nameAction;
-
- public uint RequestId { get; private set; }
-
- public uint ProtocolVersion { get; private set; }
-
- public SftpRequest(uint protocolVersion, uint requestId, Action statusAction)
- {
- this.RequestId = requestId;
- this.ProtocolVersion = protocolVersion;
- this._statusAction = statusAction;
- }
-
- public void Complete(SftpResponse response)
- {
- if (response is SftpStatusResponse)
- {
- this._statusAction(response as SftpStatusResponse);
- }
- else if (response is SftpAttrsResponse)
- {
- this._attrsAction(response as SftpAttrsResponse);
- }
- else if (response is SftpDataResponse)
- {
- this._dataAction(response as SftpDataResponse);
- }
- else if (response is SftpExtendedReplyResponse)
- {
- this._extendedReplyAction(response as SftpExtendedReplyResponse);
- }
- else if (response is SftpHandleResponse)
- {
- this._handleAction(response as SftpHandleResponse);
- }
- else if (response is SftpNameResponse)
- {
- this._nameAction(response as SftpNameResponse);
- }
- else
- {
- throw new InvalidOperationException(string.Format("Response of type '{0}' is not expected.", response.GetType().Name));
- }
- }
-
- protected void SetAction(Action action)
- {
- this._attrsAction = action;
- }
-
- protected void SetAction(Action action)
- {
- this._dataAction = action;
- }
-
- protected void SetAction(Action action)
- {
- this._extendedReplyAction = action;
- }
-
- protected void SetAction(Action action)
- {
- this._handleAction = action;
- }
-
- protected void SetAction(Action action)
- {
- this._nameAction = action;
- }
-
- protected override void LoadData()
- {
- throw new InvalidOperationException("Request cannot be saved.");
- }
-
- protected override void SaveData()
- {
- base.SaveData();
- this.Write(this.RequestId);
- }
- }
-}
+using System;
+using Renci.SshNet.Sftp.Responses;
+
+namespace Renci.SshNet.Sftp.Requests
+{
+ internal abstract class SftpRequest : SftpMessage
+ {
+ private readonly Action _statusAction;
+ private Action _attrsAction;
+ private Action