Skip to content

Commit

Permalink
Introduce extensible remote path quoting mechanism
Browse files Browse the repository at this point in the history
Introduce extensible remote path quoting mechanism.
Fixes issues #256 and #108.
  • Loading branch information
drieseng authored Sep 9, 2017
2 parents 5852a96 + 82634b4 commit cde3331
Show file tree
Hide file tree
Showing 40 changed files with 3,971 additions and 327 deletions.
15 changes: 15 additions & 0 deletions src/Renci.SshNet.NET35/Renci.SshNet.NET35.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,9 @@
<Compile Include="..\Renci.SshNet\IForwardedPort.cs">
<Link>IForwardedPort.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\IRemotePathTransformation.cs">
<Link>IRemotePathTransformation.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\IServiceFactory.cs">
<Link>IServiceFactory.cs</Link>
</Compile>
Expand Down Expand Up @@ -578,6 +581,18 @@
<Compile Include="..\Renci.SshNet\ProxyTypes.cs">
<Link>ProxyTypes.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\RemotePathDoubleQuoteTransformation.cs">
<Link>RemotePathDoubleQuoteTransformation.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\RemotePathNoneTransformation.cs">
<Link>RemotePathNoneTransformation.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\RemotePathShellQuoteTransformation.cs">
<Link>RemotePathShellQuoteTransformation.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\RemotePathTransformation.cs">
<Link>RemotePathTransformation.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\ScpClient.cs">
<Link>ScpClient.cs</Link>
</Compile>
Expand Down
17 changes: 16 additions & 1 deletion src/Renci.SshNet.Silverlight/Renci.SshNet.Silverlight.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,9 @@
<Compile Include="..\Renci.SshNet\IForwardedPort.cs">
<Link>IForwardedPort.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\IRemotePathTransformation.cs">
<Link>IRemotePathTransformation.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\IServiceFactory.cs">
<Link>IServiceFactory.cs</Link>
</Compile>
Expand Down Expand Up @@ -572,6 +575,18 @@
<Compile Include="..\Renci.SshNet\ProxyTypes.cs">
<Link>ProxyTypes.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\RemotePathDoubleQuoteTransformation.cs">
<Link>RemotePathDoubleQuoteTransformation.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\RemotePathNoneTransformation.cs">
<Link>RemotePathNoneTransformation.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\RemotePathShellQuoteTransformation.cs">
<Link>RemotePathShellQuoteTransformation.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\RemotePathTransformation.cs">
<Link>RemotePathTransformation.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\ScpClient.cs">
<Link>ScpClient.cs</Link>
</Compile>
Expand Down Expand Up @@ -949,7 +964,7 @@
<FlavorProperties GUID="{A1591282-1198-4647-A2B1-27E5FF5F6F3B}">
<SilverlightProjectProperties />
</FlavorProperties>
<UserProperties ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" ProjectLinkReference="2f5f8c90-0bd1-424f-997c-7bc6280919d1" />
<UserProperties ProjectLinkReference="2f5f8c90-0bd1-424f-997c-7bc6280919d1" ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" />
</VisualStudio>
</ProjectExtensions>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Expand Down
17 changes: 16 additions & 1 deletion src/Renci.SshNet.Silverlight5/Renci.SshNet.Silverlight5.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,9 @@
<Compile Include="..\Renci.SshNet\IForwardedPort.cs">
<Link>IForwardedPort.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\IRemotePathTransformation.cs">
<Link>IRemotePathTransformation.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\IServiceFactory.cs">
<Link>IServiceFactory.cs</Link>
</Compile>
Expand Down Expand Up @@ -581,6 +584,18 @@
<Compile Include="..\Renci.SshNet\ProxyTypes.cs">
<Link>ProxyTypes.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\RemotePathDoubleQuoteTransformation.cs">
<Link>RemotePathDoubleQuoteTransformation.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\RemotePathNoneTransformation.cs">
<Link>RemotePathNoneTransformation.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\RemotePathShellQuoteTransformation.cs">
<Link>RemotePathShellQuoteTransformation.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\RemotePathTransformation.cs">
<Link>RemotePathTransformation.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet\ScpClient.cs">
<Link>ScpClient.cs</Link>
</Compile>
Expand Down Expand Up @@ -955,7 +970,7 @@
<FlavorProperties GUID="{A1591282-1198-4647-A2B1-27E5FF5F6F3B}">
<SilverlightProjectProperties />
</FlavorProperties>
<UserProperties ProjectLinkReference="2f5f8c90-0bd1-424f-997c-7bc6280919d1" ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" />
<UserProperties ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" ProjectLinkReference="2f5f8c90-0bd1-424f-997c-7bc6280919d1" />
</VisualStudio>
</ProjectExtensions>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Expand Down
20 changes: 19 additions & 1 deletion src/Renci.SshNet.Tests.NET35/Renci.SshNet.Tests.NET35.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,12 @@
<Compile Include="..\Renci.SshNet.Tests\Classes\Common\CountdownEventTest.cs">
<Link>Classes\Common\CountdownEventTest.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet.Tests\Classes\Common\CountdownEventTest_Dispose_NotSet.cs">
<Link>Classes\Common\CountdownEventTest_Dispose_NotSet.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet.Tests\Classes\Common\CountdownEventTest_Dispose_Set.cs">
<Link>Classes\Common\CountdownEventTest_Dispose_Set.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet.Tests\Classes\Common\DerDataTest.cs">
<Link>Classes\Common\DerDataTest.cs</Link>
</Compile>
Expand Down Expand Up @@ -327,6 +333,9 @@
<Compile Include="..\Renci.SshNet.Tests\Classes\Common\PortForwardEventArgsTest.cs">
<Link>Classes\Common\PortForwardEventArgsTest.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet.Tests\Classes\Common\PosixPathTest_GetFileName.cs">
<Link>Classes\Common\PosixPathTest_GetFileName.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet.Tests\Classes\Common\ProxyExceptionTest.cs">
<Link>Classes\Common\ProxyExceptionTest.cs</Link>
</Compile>
Expand Down Expand Up @@ -765,9 +774,18 @@
<Compile Include="..\Renci.SshNet.Tests\Classes\PrivateKeyFileTest.cs">
<Link>Classes\PrivateKeyFileTest.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet.Tests\Classes\RemotePathDoubleQuoteTransformationTest.cs">
<Link>Classes\RemotePathDoubleQuoteTransformationTest.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet.Tests\Classes\RemotePathShellQuoteTransformationTest.cs">
<Link>Classes\RemotePathShellQuoteTransformationTest.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet.Tests\Classes\ScpClientTest.cs">
<Link>Classes\ScpClientTest.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet.Tests\Classes\ScpClientTestBase.cs">
<Link>Classes\ScpClientTestBase.cs</Link>
</Compile>
<Compile Include="..\Renci.SshNet.Tests\Classes\ScpClientTest_Download_PathAndDirectoryInfo_SendExecRequestReturnsFalse.cs">
<Link>Classes\ScpClientTest_Download_PathAndDirectoryInfo_SendExecRequestReturnsFalse.cs</Link>
</Compile>
Expand Down Expand Up @@ -1584,7 +1602,7 @@
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ProjectExtensions>
<VisualStudio>
<UserProperties ProjectLinkReference="c45379b9-17b1-4e89-bc2e-6d41726413e8" ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" />
<UserProperties ProjectLinkerExcludeFilter="\\?desktop(\\.*)?$;\\?silverlight(\\.*)?$;\.desktop;\.silverlight;\.xaml;^service references(\\.*)?$;\.clientconfig;^web references(\\.*)?$" ProjectLinkReference="c45379b9-17b1-4e89-bc2e-6d41726413e8" />
</VisualStudio>
</ProjectExtensions>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
Expand All @@ -21,9 +20,59 @@ public class ChannelTest_Dispose_SessionIsConnectedAndChannelIsOpen_EofReceived
private uint _remotePacketSize;
private ChannelStub _channel;
private List<ChannelEventArgs> _channelClosedRegister;
private List<ChannelEventArgs> _channelEndOfDataRegister;
private IList<ExceptionEventArgs> _channelExceptionRegister;
private ManualResetEvent _channelClosedReceived;

private void SetupData()
{
var random = new Random();

_localChannelNumber = (uint) random.Next(0, int.MaxValue);
_localWindowSize = (uint) random.Next(0, int.MaxValue);
_localPacketSize = (uint) random.Next(0, int.MaxValue);
_remoteChannelNumber = (uint) random.Next(0, int.MaxValue);
_remoteWindowSize = (uint) random.Next(0, int.MaxValue);
_remotePacketSize = (uint) random.Next(0, int.MaxValue);
_channelClosedRegister = new List<ChannelEventArgs>();
_channelEndOfDataRegister = new List<ChannelEventArgs>();
_channelExceptionRegister = new List<ExceptionEventArgs>();
_channelClosedReceived = new ManualResetEvent(false);
}

private void CreateMocks()
{
_sessionMock = new Mock<ISession>(MockBehavior.Strict);
}

private void SetupMocks()
{
var sequence = new MockSequence();

_sessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
_sessionMock.InSequence(sequence).Setup(p => p.TrySendMessage(It.Is<ChannelCloseMessage>(c => c.LocalChannelNumber == _remoteChannelNumber))).Returns(true);
_sessionMock.InSequence(sequence).Setup(p => p.WaitOnHandle(It.IsAny<EventWaitHandle>()))
.Callback<WaitHandle>(w =>
{
new Thread(() =>
{
Thread.Sleep(100);
// raise ChannelCloseReceived event to set waithandle for receiving
// SSH_MSG_CHANNEL_CLOSE message from server which is waited on after
// sending the SSH_MSG_CHANNEL_CLOSE message to the server
//
// we're mocking the wait on the ChannelCloseMessage, but we still want
// to get the channel in the state that it would have after actually receiving
// the ChannelCloseMessage
_sessionMock.Raise(s => s.ChannelCloseReceived += null, new MessageEventArgs<ChannelCloseMessage>(new ChannelCloseMessage(_localChannelNumber)));
// signal that the ChannelCloseMessage was received; we use this to verify whether we've actually
// waited on the EventWaitHandle to be set
_channelClosedReceived.Set();
}).Start();
w.WaitOne();
});
}

[TestInitialize]
public void Initialize()
{
Expand All @@ -43,45 +92,13 @@ public void TearDown()

private void Arrange()
{
var random = new Random();
_localChannelNumber = (uint)random.Next(0, int.MaxValue);
_localWindowSize = (uint)random.Next(0, int.MaxValue);
_localPacketSize = (uint)random.Next(0, int.MaxValue);
_remoteChannelNumber = (uint)random.Next(0, int.MaxValue);
_remoteWindowSize = (uint)random.Next(0, int.MaxValue);
_remotePacketSize = (uint)random.Next(0, int.MaxValue);
_channelClosedRegister = new List<ChannelEventArgs>();
_channelExceptionRegister = new List<ExceptionEventArgs>();
_channelClosedReceived = new ManualResetEvent(false);

_sessionMock = new Mock<ISession>(MockBehavior.Strict);

var sequence = new MockSequence();
_sessionMock.InSequence(sequence).Setup(p => p.IsConnected).Returns(true);
_sessionMock.InSequence(sequence).Setup(p => p.TrySendMessage(It.Is<ChannelCloseMessage>(c => c.LocalChannelNumber == _remoteChannelNumber))).Returns(true);
_sessionMock.InSequence(sequence).Setup(p => p.WaitOnHandle(It.IsAny<EventWaitHandle>()))
.Callback<WaitHandle>(w =>
{
new Thread(() =>
{
Thread.Sleep(100);
// signal that the ChannelCloseMessage was received; we use this to verify whether we've actually
// waited on the EventWaitHandle to be set
_channelClosedReceived.Set();
// raise ChannelCloseReceived event to set waithandle for receiving
// SSH_MSG_CHANNEL_CLOSE message from server which is waited on after
// sending the SSH_MSG_CHANNEL_CLOSE message to the server
//
// we're mocking the wait on the ChannelCloseMessage, but we still want
// to get the channel in the state that it would have after actually receiving
// the ChannelCloseMessage
_sessionMock.Raise(s => s.ChannelCloseReceived += null, new MessageEventArgs<ChannelCloseMessage>(new ChannelCloseMessage(_localChannelNumber)));
}).Start();
w.WaitOne();
});
SetupData();
CreateMocks();
SetupMocks();

_channel = new ChannelStub(_sessionMock.Object, _localChannelNumber, _localWindowSize, _localPacketSize);
_channel.Closed += (sender, args) => _channelClosedRegister.Add(args);
_channel.EndOfData += (sender, args) => _channelEndOfDataRegister.Add(args);
_channel.Exception += (sender, args) => _channelExceptionRegister.Add(args);
_channel.InitializeRemoteChannelInfo(_remoteChannelNumber, _remoteWindowSize, _remotePacketSize);
_channel.SetIsOpen(true);
Expand Down Expand Up @@ -137,6 +154,13 @@ public void ClosedEventShouldHaveFiredOnce()
Assert.AreEqual(_localChannelNumber, _channelClosedRegister[0].ChannelNumber);
}

[TestMethod]
public void EndOfDataEventShouldHaveFiredOnce()
{
Assert.AreEqual(1, _channelEndOfDataRegister.Count);
Assert.AreEqual(_localChannelNumber, _channelEndOfDataRegister[0].ChannelNumber);
}

[TestMethod]
public void ExceptionShouldNeverHaveFired()
{
Expand Down
Loading

0 comments on commit cde3331

Please sign in to comment.