mirror of
https://github.com/sshnet/SSH.NET.git
synced 2026-09-10 09:15:47 +00:00
Renamed Quote transformation and corresponding class to ShellQuote.
Added DoubleQuote transformation. Modified default remote path transformation for ScpClient to DoubleQuote.
This commit is contained in:
@@ -581,14 +581,14 @@
|
||||
<Compile Include="..\Renci.SshNet\ProxyTypes.cs">
|
||||
<Link>ProxyTypes.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Renci.SshNet\RemotePathEscapeTransformation.cs">
|
||||
<Link>RemotePathEscapeTransformation.cs</Link>
|
||||
<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\RemotePathQuoteTransformation.cs">
|
||||
<Link>RemotePathQuoteTransformation.cs</Link>
|
||||
<Compile Include="..\Renci.SshNet\RemotePathShellQuoteTransformation.cs">
|
||||
<Link>RemotePathShellQuoteTransformation.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\Renci.SshNet\RemotePathTransformation.cs">
|
||||
<Link>RemotePathTransformation.cs</Link>
|
||||
|
||||
@@ -768,6 +768,9 @@
|
||||
<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>
|
||||
@@ -1584,7 +1587,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.
|
||||
|
||||
@@ -15,6 +15,206 @@ namespace Renci.SshNet.Tests.Classes
|
||||
[TestClass]
|
||||
public partial class ScpClientTest : TestBase
|
||||
{
|
||||
private Random _random;
|
||||
|
||||
[TestInitialize]
|
||||
public void SetUp()
|
||||
{
|
||||
_random = new Random();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Ctor_ConnectionInfo_Null()
|
||||
{
|
||||
const ConnectionInfo connectionInfo = null;
|
||||
|
||||
try
|
||||
{
|
||||
new ScpClient(connectionInfo);
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ArgumentNullException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual("connectionInfo", ex.ParamName);
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Ctor_ConnectionInfo_NotNull()
|
||||
{
|
||||
var connectionInfo = new ConnectionInfo("HOST", "USER", new PasswordAuthenticationMethod("USER", "PWD"));
|
||||
|
||||
var client = new ScpClient(connectionInfo);
|
||||
Assert.AreEqual(16 * 1024U, client.BufferSize);
|
||||
Assert.AreSame(connectionInfo, client.ConnectionInfo);
|
||||
Assert.IsFalse(client.IsConnected);
|
||||
Assert.AreEqual(new TimeSpan(0, 0, 0, 0, -1), client.KeepAliveInterval);
|
||||
Assert.AreEqual(new TimeSpan(0, 0, 0, 0, -1), client.OperationTimeout);
|
||||
Assert.AreSame(RemotePathTransformation.DoubleQuote, client.RemotePathTransformation);
|
||||
Assert.IsNull(client.Session);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Ctor_HostAndPortAndUsernameAndPassword()
|
||||
{
|
||||
var host = _random.Next().ToString();
|
||||
var port = _random.Next(1, 100);
|
||||
var userName = _random.Next().ToString();
|
||||
var password = _random.Next().ToString();
|
||||
|
||||
var client = new ScpClient(host, port, userName, password);
|
||||
Assert.AreEqual(16 * 1024U, client.BufferSize);
|
||||
Assert.IsNotNull(client.ConnectionInfo);
|
||||
Assert.IsFalse(client.IsConnected);
|
||||
Assert.AreEqual(new TimeSpan(0, 0, 0, 0, -1), client.KeepAliveInterval);
|
||||
Assert.AreEqual(new TimeSpan(0, 0, 0, 0, -1), client.OperationTimeout);
|
||||
Assert.AreSame(RemotePathTransformation.DoubleQuote, client.RemotePathTransformation);
|
||||
Assert.IsNull(client.Session);
|
||||
|
||||
var passwordConnectionInfo = client.ConnectionInfo as PasswordConnectionInfo;
|
||||
Assert.IsNotNull(passwordConnectionInfo);
|
||||
Assert.AreEqual(host, passwordConnectionInfo.Host);
|
||||
Assert.AreEqual(port, passwordConnectionInfo.Port);
|
||||
Assert.AreSame(userName, passwordConnectionInfo.Username);
|
||||
Assert.IsNotNull(passwordConnectionInfo.AuthenticationMethods);
|
||||
Assert.AreEqual(1, passwordConnectionInfo.AuthenticationMethods.Count);
|
||||
|
||||
var passwordAuthentication = passwordConnectionInfo.AuthenticationMethods[0] as PasswordAuthenticationMethod;
|
||||
Assert.IsNotNull(passwordAuthentication);
|
||||
Assert.AreEqual(userName, passwordAuthentication.Username);
|
||||
Assert.IsTrue(Encoding.UTF8.GetBytes(password).IsEqualTo(passwordAuthentication.Password));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Ctor_HostAndUsernameAndPassword()
|
||||
{
|
||||
var host = _random.Next().ToString();
|
||||
var userName = _random.Next().ToString();
|
||||
var password = _random.Next().ToString();
|
||||
|
||||
var client = new ScpClient(host, userName, password);
|
||||
Assert.AreEqual(16 * 1024U, client.BufferSize);
|
||||
Assert.IsNotNull(client.ConnectionInfo);
|
||||
Assert.IsFalse(client.IsConnected);
|
||||
Assert.AreEqual(new TimeSpan(0, 0, 0, 0, -1), client.KeepAliveInterval);
|
||||
Assert.AreEqual(new TimeSpan(0, 0, 0, 0, -1), client.OperationTimeout);
|
||||
Assert.AreSame(RemotePathTransformation.DoubleQuote, client.RemotePathTransformation);
|
||||
Assert.IsNull(client.Session);
|
||||
|
||||
var passwordConnectionInfo = client.ConnectionInfo as PasswordConnectionInfo;
|
||||
Assert.IsNotNull(passwordConnectionInfo);
|
||||
Assert.AreEqual(host, passwordConnectionInfo.Host);
|
||||
Assert.AreEqual(22, passwordConnectionInfo.Port);
|
||||
Assert.AreSame(userName, passwordConnectionInfo.Username);
|
||||
Assert.IsNotNull(passwordConnectionInfo.AuthenticationMethods);
|
||||
Assert.AreEqual(1, passwordConnectionInfo.AuthenticationMethods.Count);
|
||||
|
||||
var passwordAuthentication = passwordConnectionInfo.AuthenticationMethods[0] as PasswordAuthenticationMethod;
|
||||
Assert.IsNotNull(passwordAuthentication);
|
||||
Assert.AreEqual(userName, passwordAuthentication.Username);
|
||||
Assert.IsTrue(Encoding.UTF8.GetBytes(password).IsEqualTo(passwordAuthentication.Password));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Ctor_HostAndPortAndUsernameAndPrivateKeys()
|
||||
{
|
||||
var host = _random.Next().ToString();
|
||||
var port = _random.Next(1, 100);
|
||||
var userName = _random.Next().ToString();
|
||||
var privateKeys = new[] {GetRsaKey(), GetDsaKey()};
|
||||
|
||||
var client = new ScpClient(host, port, userName, privateKeys);
|
||||
Assert.AreEqual(16 * 1024U, client.BufferSize);
|
||||
Assert.IsNotNull(client.ConnectionInfo);
|
||||
Assert.IsFalse(client.IsConnected);
|
||||
Assert.AreEqual(new TimeSpan(0, 0, 0, 0, -1), client.KeepAliveInterval);
|
||||
Assert.AreEqual(new TimeSpan(0, 0, 0, 0, -1), client.OperationTimeout);
|
||||
Assert.AreSame(RemotePathTransformation.DoubleQuote, client.RemotePathTransformation);
|
||||
Assert.IsNull(client.Session);
|
||||
|
||||
var privateKeyConnectionInfo = client.ConnectionInfo as PrivateKeyConnectionInfo;
|
||||
Assert.IsNotNull(privateKeyConnectionInfo);
|
||||
Assert.AreEqual(host, privateKeyConnectionInfo.Host);
|
||||
Assert.AreEqual(port, privateKeyConnectionInfo.Port);
|
||||
Assert.AreSame(userName, privateKeyConnectionInfo.Username);
|
||||
Assert.IsNotNull(privateKeyConnectionInfo.AuthenticationMethods);
|
||||
Assert.AreEqual(1, privateKeyConnectionInfo.AuthenticationMethods.Count);
|
||||
|
||||
var privateKeyAuthentication = privateKeyConnectionInfo.AuthenticationMethods[0] as PrivateKeyAuthenticationMethod;
|
||||
Assert.IsNotNull(privateKeyAuthentication);
|
||||
Assert.AreEqual(userName, privateKeyAuthentication.Username);
|
||||
Assert.IsNotNull(privateKeyAuthentication.KeyFiles);
|
||||
Assert.AreEqual(privateKeys.Length, privateKeyAuthentication.KeyFiles.Count);
|
||||
Assert.IsTrue(privateKeyAuthentication.KeyFiles.Contains(privateKeys[0]));
|
||||
Assert.IsTrue(privateKeyAuthentication.KeyFiles.Contains(privateKeys[1]));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void Ctor_HostAndUsernameAndPrivateKeys()
|
||||
{
|
||||
var host = _random.Next().ToString();
|
||||
var userName = _random.Next().ToString();
|
||||
var privateKeys = new[] { GetRsaKey(), GetDsaKey() };
|
||||
|
||||
var client = new ScpClient(host, userName, privateKeys);
|
||||
Assert.AreEqual(16 * 1024U, client.BufferSize);
|
||||
Assert.IsNotNull(client.ConnectionInfo);
|
||||
Assert.IsFalse(client.IsConnected);
|
||||
Assert.AreEqual(new TimeSpan(0, 0, 0, 0, -1), client.KeepAliveInterval);
|
||||
Assert.AreEqual(new TimeSpan(0, 0, 0, 0, -1), client.OperationTimeout);
|
||||
Assert.AreSame(RemotePathTransformation.DoubleQuote, client.RemotePathTransformation);
|
||||
Assert.IsNull(client.Session);
|
||||
|
||||
var privateKeyConnectionInfo = client.ConnectionInfo as PrivateKeyConnectionInfo;
|
||||
Assert.IsNotNull(privateKeyConnectionInfo);
|
||||
Assert.AreEqual(host, privateKeyConnectionInfo.Host);
|
||||
Assert.AreEqual(22, privateKeyConnectionInfo.Port);
|
||||
Assert.AreSame(userName, privateKeyConnectionInfo.Username);
|
||||
Assert.IsNotNull(privateKeyConnectionInfo.AuthenticationMethods);
|
||||
Assert.AreEqual(1, privateKeyConnectionInfo.AuthenticationMethods.Count);
|
||||
|
||||
var privateKeyAuthentication = privateKeyConnectionInfo.AuthenticationMethods[0] as PrivateKeyAuthenticationMethod;
|
||||
Assert.IsNotNull(privateKeyAuthentication);
|
||||
Assert.AreEqual(userName, privateKeyAuthentication.Username);
|
||||
Assert.IsNotNull(privateKeyAuthentication.KeyFiles);
|
||||
Assert.AreEqual(privateKeys.Length, privateKeyAuthentication.KeyFiles.Count);
|
||||
Assert.IsTrue(privateKeyAuthentication.KeyFiles.Contains(privateKeys[0]));
|
||||
Assert.IsTrue(privateKeyAuthentication.KeyFiles.Contains(privateKeys[1]));
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void RemotePathTransformation_Value_NotNull()
|
||||
{
|
||||
var client = new ScpClient("HOST", 22, "USER", "PWD");
|
||||
|
||||
Assert.AreSame(RemotePathTransformation.DoubleQuote, client.RemotePathTransformation);
|
||||
client.RemotePathTransformation = RemotePathTransformation.ShellQuote;
|
||||
Assert.AreSame(RemotePathTransformation.ShellQuote, client.RemotePathTransformation);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void RemotePathTransformation_Value_Null()
|
||||
{
|
||||
var client = new ScpClient("HOST", 22, "USER", "PWD")
|
||||
{
|
||||
RemotePathTransformation = RemotePathTransformation.ShellQuote
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
client.RemotePathTransformation = null;
|
||||
Assert.Fail();
|
||||
}
|
||||
catch (ArgumentNullException ex)
|
||||
{
|
||||
Assert.IsNull(ex.InnerException);
|
||||
Assert.AreEqual("value", ex.ParamName);
|
||||
}
|
||||
|
||||
Assert.AreSame(RemotePathTransformation.ShellQuote, client.RemotePathTransformation);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
[TestCategory("Scp")]
|
||||
[TestCategory("integration")]
|
||||
@@ -172,10 +372,12 @@ namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
scp.Connect();
|
||||
|
||||
var uploadDirectory = Directory.CreateDirectory(string.Format("{0}\\{1}", Path.GetTempPath(), Path.GetRandomFileName()));
|
||||
var uploadDirectory =
|
||||
Directory.CreateDirectory(string.Format("{0}\\{1}", Path.GetTempPath(), Path.GetRandomFileName()));
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
var subfolder = Directory.CreateDirectory(string.Format(@"{0}\folder_{1}", uploadDirectory.FullName, i));
|
||||
var subfolder =
|
||||
Directory.CreateDirectory(string.Format(@"{0}\folder_{1}", uploadDirectory.FullName, i));
|
||||
for (int j = 0; j < 5; j++)
|
||||
{
|
||||
this.CreateTestFile(string.Format(@"{0}\file_{1}", subfolder.FullName, j), 1);
|
||||
@@ -185,7 +387,8 @@ namespace Renci.SshNet.Tests.Classes
|
||||
|
||||
scp.Upload(uploadDirectory, "uploaded_dir");
|
||||
|
||||
var downloadDirectory = Directory.CreateDirectory(string.Format("{0}\\{1}", Path.GetTempPath(), Path.GetRandomFileName()));
|
||||
var downloadDirectory =
|
||||
Directory.CreateDirectory(string.Format("{0}\\{1}", Path.GetTempPath(), Path.GetRandomFileName()));
|
||||
|
||||
scp.Download("uploaded_dir", downloadDirectory);
|
||||
|
||||
@@ -193,11 +396,12 @@ namespace Renci.SshNet.Tests.Classes
|
||||
var downloadFiles = downloadDirectory.GetFiles("*.*", System.IO.SearchOption.AllDirectories);
|
||||
|
||||
var result = from f1 in uploadedFiles
|
||||
from f2 in downloadFiles
|
||||
where
|
||||
f1.FullName.Substring(uploadDirectory.FullName.Length) == f2.FullName.Substring(downloadDirectory.FullName.Length)
|
||||
&& CalculateMD5(f1.FullName) == CalculateMD5(f2.FullName)
|
||||
select f1;
|
||||
from f2 in downloadFiles
|
||||
where
|
||||
f1.FullName.Substring(uploadDirectory.FullName.Length) ==
|
||||
f2.FullName.Substring(downloadDirectory.FullName.Length)
|
||||
&& CalculateMD5(f1.FullName) == CalculateMD5(f2.FullName)
|
||||
select f1;
|
||||
|
||||
var counter = result.Count();
|
||||
|
||||
@@ -331,76 +535,6 @@ namespace Renci.SshNet.Tests.Classes
|
||||
Assert.Inconclusive("A method that does not return a value cannot be verified.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///A test for ScpClient Constructor
|
||||
///</summary>
|
||||
[TestMethod]
|
||||
[Ignore] // placeholder for actual test
|
||||
public void ScpClientConstructorTest()
|
||||
{
|
||||
string host = string.Empty; // TODO: Initialize to an appropriate value
|
||||
string username = string.Empty; // TODO: Initialize to an appropriate value
|
||||
PrivateKeyFile[] keyFiles = null; // TODO: Initialize to an appropriate value
|
||||
ScpClient target = new ScpClient(host, username, keyFiles);
|
||||
Assert.Inconclusive("TODO: Implement code to verify target");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///A test for ScpClient Constructor
|
||||
///</summary>
|
||||
[TestMethod]
|
||||
[Ignore] // placeholder for actual test
|
||||
public void ScpClientConstructorTest1()
|
||||
{
|
||||
string host = string.Empty; // TODO: Initialize to an appropriate value
|
||||
int port = 0; // TODO: Initialize to an appropriate value
|
||||
string username = string.Empty; // TODO: Initialize to an appropriate value
|
||||
PrivateKeyFile[] keyFiles = null; // TODO: Initialize to an appropriate value
|
||||
ScpClient target = new ScpClient(host, port, username, keyFiles);
|
||||
Assert.Inconclusive("TODO: Implement code to verify target");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///A test for ScpClient Constructor
|
||||
///</summary>
|
||||
[TestMethod]
|
||||
[Ignore] // placeholder for actual test
|
||||
public void ScpClientConstructorTest2()
|
||||
{
|
||||
string host = string.Empty; // TODO: Initialize to an appropriate value
|
||||
string username = string.Empty; // TODO: Initialize to an appropriate value
|
||||
string password = string.Empty; // TODO: Initialize to an appropriate value
|
||||
ScpClient target = new ScpClient(host, username, password);
|
||||
Assert.Inconclusive("TODO: Implement code to verify target");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///A test for ScpClient Constructor
|
||||
///</summary>
|
||||
[TestMethod]
|
||||
[Ignore] // placeholder for actual test
|
||||
public void ScpClientConstructorTest3()
|
||||
{
|
||||
string host = string.Empty; // TODO: Initialize to an appropriate value
|
||||
int port = 0; // TODO: Initialize to an appropriate value
|
||||
string username = string.Empty; // TODO: Initialize to an appropriate value
|
||||
string password = string.Empty; // TODO: Initialize to an appropriate value
|
||||
ScpClient target = new ScpClient(host, port, username, password);
|
||||
Assert.Inconclusive("TODO: Implement code to verify target");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///A test for ScpClient Constructor
|
||||
///</summary>
|
||||
[TestMethod]
|
||||
[Ignore] // placeholder for actual test
|
||||
public void ScpClientConstructorTest4()
|
||||
{
|
||||
ConnectionInfo connectionInfo = null; // TODO: Initialize to an appropriate value
|
||||
ScpClient target = new ScpClient(connectionInfo);
|
||||
Assert.Inconclusive("TODO: Implement code to verify target");
|
||||
}
|
||||
|
||||
protected static string CalculateMD5(string fileName)
|
||||
{
|
||||
using (var file = new FileStream(fileName, FileMode.Open))
|
||||
@@ -427,5 +561,21 @@ namespace Renci.SshNet.Tests.Classes
|
||||
client.Disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
private PrivateKeyFile GetRsaKey()
|
||||
{
|
||||
using (var stream = GetData("Key.RSA.txt"))
|
||||
{
|
||||
return new PrivateKeyFile(stream);
|
||||
}
|
||||
}
|
||||
|
||||
private PrivateKeyFile GetDsaKey()
|
||||
{
|
||||
using (var stream = GetData("Key.SSH2.DSA.txt"))
|
||||
{
|
||||
return new PrivateKeyFile(stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Channels;
|
||||
using Renci.SshNet.Common;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
public abstract class ScpClientTestBase
|
||||
{
|
||||
internal Mock<IServiceFactory> _serviceFactoryMock;
|
||||
internal Mock<IRemotePathTransformation> _remotePathTransformationMock;
|
||||
internal Mock<ISession> _sessionMock;
|
||||
internal Mock<IChannelSession> _channelSessionMock;
|
||||
internal Mock<PipeStream> _pipeStreamMock;
|
||||
|
||||
protected abstract void SetupData();
|
||||
|
||||
protected void CreateMocks()
|
||||
{
|
||||
_serviceFactoryMock = new Mock<IServiceFactory>(MockBehavior.Strict);
|
||||
_remotePathTransformationMock = new Mock<IRemotePathTransformation>(MockBehavior.Strict);
|
||||
_sessionMock = new Mock<ISession>(MockBehavior.Strict);
|
||||
_channelSessionMock = new Mock<IChannelSession>(MockBehavior.Strict);
|
||||
_pipeStreamMock = new Mock<PipeStream>(MockBehavior.Strict);
|
||||
}
|
||||
|
||||
protected abstract void SetupMocks();
|
||||
|
||||
protected virtual void Arrange()
|
||||
{
|
||||
SetupData();
|
||||
CreateMocks();
|
||||
SetupMocks();
|
||||
}
|
||||
|
||||
[TestInitialize]
|
||||
public void Initialize()
|
||||
{
|
||||
Arrange();
|
||||
Act();
|
||||
}
|
||||
|
||||
protected abstract void Act();
|
||||
}
|
||||
}
|
||||
+26
-26
@@ -4,66 +4,66 @@ using System.Globalization;
|
||||
using System.IO;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Channels;
|
||||
using Renci.SshNet.Common;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
[TestClass]
|
||||
public class ScpClientTest_Download_PathAndDirectoryInfo_SendExecRequestReturnsFalse
|
||||
public class ScpClientTest_Download_PathAndDirectoryInfo_SendExecRequestReturnsFalse : ScpClientTestBase
|
||||
{
|
||||
private Mock<IServiceFactory> _serviceFactoryMock;
|
||||
private Mock<ISession> _sessionMock;
|
||||
private Mock<IChannelSession> _channelSessionMock;
|
||||
private Mock<PipeStream> _pipeStreamMock;
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private ScpClient _scpClient;
|
||||
private DirectoryInfo _directoryInfo;
|
||||
private string _path;
|
||||
private string _quotedPath;
|
||||
private string _transformedPath;
|
||||
private IList<ScpUploadEventArgs> _uploadingRegister;
|
||||
private SshException _actualException;
|
||||
|
||||
[TestInitialize]
|
||||
public void Setup()
|
||||
{
|
||||
Arrange();
|
||||
Act();
|
||||
}
|
||||
|
||||
protected void Arrange()
|
||||
protected override void SetupData()
|
||||
{
|
||||
var random = new Random();
|
||||
|
||||
_connectionInfo = new ConnectionInfo("host", 22, "user", new PasswordAuthenticationMethod("user", "pwd"));
|
||||
_directoryInfo = new DirectoryInfo("destination");
|
||||
_path = "/home/sshnet/" + random.Next().ToString(CultureInfo.InvariantCulture);
|
||||
_quotedPath = _path.ShellQuote();
|
||||
_transformedPath = random.Next().ToString();
|
||||
_uploadingRegister = new List<ScpUploadEventArgs>();
|
||||
}
|
||||
|
||||
_serviceFactoryMock = new Mock<IServiceFactory>(MockBehavior.Strict);
|
||||
_sessionMock = new Mock<ISession>(MockBehavior.Strict);
|
||||
_channelSessionMock = new Mock<IChannelSession>(MockBehavior.Strict);
|
||||
_pipeStreamMock = new Mock<PipeStream>(MockBehavior.Strict);
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
var sequence = new MockSequence();
|
||||
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo))
|
||||
.Returns(_sessionMock.Object);
|
||||
.Setup(p => p.CreateRemotePathDoubleQuoteTransformation())
|
||||
.Returns(_remotePathTransformationMock.Object);
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.Connect());
|
||||
_serviceFactoryMock.InSequence(sequence).Setup(p => p.CreatePipeStream()).Returns(_pipeStreamMock.Object);
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.CreateChannelSession()).Returns(_channelSessionMock.Object);
|
||||
_channelSessionMock.InSequence(sequence).Setup(p => p.Open());
|
||||
_remotePathTransformationMock.InSequence(sequence)
|
||||
.Setup(p => p.Transform(_path))
|
||||
.Returns(_transformedPath);
|
||||
_channelSessionMock.InSequence(sequence)
|
||||
.Setup(p => p.SendExecRequest(string.Format("scp -prf {0}", _quotedPath))).Returns(false);
|
||||
.Setup(p => p.SendExecRequest(string.Format("scp -prf {0}", _transformedPath)))
|
||||
.Returns(false);
|
||||
_channelSessionMock.InSequence(sequence).Setup(p => p.Dispose());
|
||||
_pipeStreamMock.As<IDisposable>().InSequence(sequence).Setup(p => p.Dispose());
|
||||
}
|
||||
|
||||
protected override void Arrange()
|
||||
{
|
||||
base.Arrange();
|
||||
|
||||
_scpClient = new ScpClient(_connectionInfo, false, _serviceFactoryMock.Object);
|
||||
_scpClient.Uploading += (sender, args) => _uploadingRegister.Add(args);
|
||||
_scpClient.Connect();
|
||||
}
|
||||
|
||||
protected virtual void Act()
|
||||
protected override void Act()
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -87,7 +87,7 @@ namespace Renci.SshNet.Tests.Classes
|
||||
[TestMethod]
|
||||
public void SendExecRequestOnChannelSessionShouldBeInvokedOnce()
|
||||
{
|
||||
_channelSessionMock.Verify(p => p.SendExecRequest(string.Format("scp -prf {0}", _quotedPath)), Times.Once);
|
||||
_channelSessionMock.Verify(p => p.SendExecRequest(string.Format("scp -prf {0}", _transformedPath)), Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
||||
+25
-26
@@ -4,66 +4,65 @@ using System.Globalization;
|
||||
using System.IO;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Channels;
|
||||
using Renci.SshNet.Common;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
[TestClass]
|
||||
public class ScpClientTest_Download_PathAndFileInfo_SendExecRequestReturnsFalse
|
||||
public class ScpClientTest_Download_PathAndFileInfo_SendExecRequestReturnsFalse : ScpClientTestBase
|
||||
{
|
||||
private Mock<IServiceFactory> _serviceFactoryMock;
|
||||
private Mock<ISession> _sessionMock;
|
||||
private Mock<IChannelSession> _channelSessionMock;
|
||||
private Mock<PipeStream> _pipeStreamMock;
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private ScpClient _scpClient;
|
||||
private FileInfo _fileInfo;
|
||||
private string _path;
|
||||
private string _quotedPath;
|
||||
private string _transformedPath;
|
||||
private IList<ScpUploadEventArgs> _uploadingRegister;
|
||||
private SshException _actualException;
|
||||
|
||||
[TestInitialize]
|
||||
public void Setup()
|
||||
{
|
||||
Arrange();
|
||||
Act();
|
||||
}
|
||||
|
||||
protected void Arrange()
|
||||
protected override void SetupData()
|
||||
{
|
||||
var random = new Random();
|
||||
|
||||
_connectionInfo = new ConnectionInfo("host", 22, "user", new PasswordAuthenticationMethod("user", "pwd"));
|
||||
_fileInfo = new FileInfo("destination");
|
||||
_path = "/home/sshnet/" + random.Next().ToString(CultureInfo.InvariantCulture);
|
||||
_quotedPath = _path.ShellQuote();
|
||||
_transformedPath = random.Next().ToString();
|
||||
_uploadingRegister = new List<ScpUploadEventArgs>();
|
||||
}
|
||||
|
||||
_serviceFactoryMock = new Mock<IServiceFactory>(MockBehavior.Strict);
|
||||
_sessionMock = new Mock<ISession>(MockBehavior.Strict);
|
||||
_channelSessionMock = new Mock<IChannelSession>(MockBehavior.Strict);
|
||||
_pipeStreamMock = new Mock<PipeStream>(MockBehavior.Strict);
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
var sequence = new MockSequence();
|
||||
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo))
|
||||
.Returns(_sessionMock.Object);
|
||||
.Setup(p => p.CreateRemotePathDoubleQuoteTransformation())
|
||||
.Returns(_remotePathTransformationMock.Object);
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.Connect());
|
||||
_serviceFactoryMock.InSequence(sequence).Setup(p => p.CreatePipeStream()).Returns(_pipeStreamMock.Object);
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.CreateChannelSession()).Returns(_channelSessionMock.Object);
|
||||
_channelSessionMock.InSequence(sequence).Setup(p => p.Open());
|
||||
_remotePathTransformationMock.InSequence(sequence)
|
||||
.Setup(p => p.Transform(_path))
|
||||
.Returns(_transformedPath);
|
||||
_channelSessionMock.InSequence(sequence)
|
||||
.Setup(p => p.SendExecRequest(string.Format("scp -pf {0}", _quotedPath))).Returns(false);
|
||||
.Setup(p => p.SendExecRequest(string.Format("scp -pf {0}", _transformedPath))).Returns(false);
|
||||
_channelSessionMock.InSequence(sequence).Setup(p => p.Dispose());
|
||||
_pipeStreamMock.As<IDisposable>().InSequence(sequence).Setup(p => p.Dispose());
|
||||
}
|
||||
|
||||
protected override void Arrange()
|
||||
{
|
||||
base.Arrange();
|
||||
|
||||
_scpClient = new ScpClient(_connectionInfo, false, _serviceFactoryMock.Object);
|
||||
_scpClient.Uploading += (sender, args) => _uploadingRegister.Add(args);
|
||||
_scpClient.Connect();
|
||||
}
|
||||
|
||||
protected virtual void Act()
|
||||
protected override void Act()
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -87,7 +86,7 @@ namespace Renci.SshNet.Tests.Classes
|
||||
[TestMethod]
|
||||
public void SendExecRequestOnChannelSessionShouldBeInvokedOnce()
|
||||
{
|
||||
_channelSessionMock.Verify(p => p.SendExecRequest(string.Format("scp -pf {0}", _quotedPath)), Times.Once);
|
||||
_channelSessionMock.Verify(p => p.SendExecRequest(string.Format("scp -pf {0}", _transformedPath)), Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
||||
+26
-26
@@ -4,33 +4,21 @@ using System.Globalization;
|
||||
using System.IO;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Channels;
|
||||
using Renci.SshNet.Common;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
[TestClass]
|
||||
public class ScpClientTest_Download_PathAndStream_SendExecRequestReturnsFalse
|
||||
public class ScpClientTest_Download_PathAndStream_SendExecRequestReturnsFalse : ScpClientTestBase
|
||||
{
|
||||
private Mock<IServiceFactory> _serviceFactoryMock;
|
||||
private Mock<ISession> _sessionMock;
|
||||
private Mock<IChannelSession> _channelSessionMock;
|
||||
private Mock<PipeStream> _pipeStreamMock;
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private ScpClient _scpClient;
|
||||
private Stream _destination;
|
||||
private string _path;
|
||||
private string _quotedPath;
|
||||
private string _transformedPath;
|
||||
private IList<ScpUploadEventArgs> _uploadingRegister;
|
||||
private SshException _actualException;
|
||||
|
||||
[TestInitialize]
|
||||
public void Setup()
|
||||
{
|
||||
Arrange();
|
||||
Act();
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public void Cleanup()
|
||||
{
|
||||
@@ -40,39 +28,51 @@ namespace Renci.SshNet.Tests.Classes
|
||||
}
|
||||
}
|
||||
|
||||
protected void Arrange()
|
||||
protected override void SetupData()
|
||||
{
|
||||
var random = new Random();
|
||||
|
||||
_connectionInfo = new ConnectionInfo("host", 22, "user", new PasswordAuthenticationMethod("user", "pwd"));
|
||||
_destination = new MemoryStream();
|
||||
_path = "/home/sshnet/" + random.Next().ToString(CultureInfo.InvariantCulture);
|
||||
_quotedPath = _path.ShellQuote();
|
||||
_transformedPath = random.Next().ToString();
|
||||
_uploadingRegister = new List<ScpUploadEventArgs>();
|
||||
}
|
||||
|
||||
_serviceFactoryMock = new Mock<IServiceFactory>(MockBehavior.Strict);
|
||||
_sessionMock = new Mock<ISession>(MockBehavior.Strict);
|
||||
_channelSessionMock = new Mock<IChannelSession>(MockBehavior.Strict);
|
||||
_pipeStreamMock = new Mock<PipeStream>(MockBehavior.Strict);
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
var sequence = new MockSequence();
|
||||
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo))
|
||||
.Returns(_sessionMock.Object);
|
||||
.Setup(p => p.CreateRemotePathDoubleQuoteTransformation())
|
||||
.Returns(_remotePathTransformationMock.Object);
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.Connect());
|
||||
_serviceFactoryMock.InSequence(sequence).Setup(p => p.CreatePipeStream()).Returns(_pipeStreamMock.Object);
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.CreateChannelSession()).Returns(_channelSessionMock.Object);
|
||||
_channelSessionMock.InSequence(sequence).Setup(p => p.Open());
|
||||
_remotePathTransformationMock.InSequence(sequence)
|
||||
.Setup(p => p.Transform(_path))
|
||||
.Returns(_transformedPath);
|
||||
_channelSessionMock.InSequence(sequence)
|
||||
.Setup(p => p.SendExecRequest(string.Format("scp -f {0}", _quotedPath))).Returns(false);
|
||||
.Setup(p => p.SendExecRequest(string.Format("scp -f {0}", _transformedPath)))
|
||||
.Returns(false);
|
||||
_channelSessionMock.InSequence(sequence).Setup(p => p.Dispose());
|
||||
_pipeStreamMock.As<IDisposable>().InSequence(sequence).Setup(p => p.Dispose());
|
||||
}
|
||||
|
||||
protected override void Arrange()
|
||||
{
|
||||
base.Arrange();
|
||||
|
||||
_scpClient = new ScpClient(_connectionInfo, false, _serviceFactoryMock.Object);
|
||||
_scpClient.Uploading += (sender, args) => _uploadingRegister.Add(args);
|
||||
_scpClient.Connect();
|
||||
}
|
||||
|
||||
protected virtual void Act()
|
||||
protected override void Act()
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -96,7 +96,7 @@ namespace Renci.SshNet.Tests.Classes
|
||||
[TestMethod]
|
||||
public void SendExecRequestOnChannelSessionShouldBeInvokedOnce()
|
||||
{
|
||||
_channelSessionMock.Verify(p => p.SendExecRequest(string.Format("scp -f {0}", _quotedPath)), Times.Once);
|
||||
_channelSessionMock.Verify(p => p.SendExecRequest(string.Format("scp -f {0}", _transformedPath)), Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
||||
+26
-26
@@ -4,66 +4,66 @@ using System.Globalization;
|
||||
using System.IO;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Channels;
|
||||
using Renci.SshNet.Common;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
[TestClass]
|
||||
public class ScpClientTest_Upload_DirectoryInfoAndPath_SendExecRequestReturnsFalse
|
||||
public class ScpClientTest_Upload_DirectoryInfoAndPath_SendExecRequestReturnsFalse : ScpClientTestBase
|
||||
{
|
||||
private Mock<IServiceFactory> _serviceFactoryMock;
|
||||
private Mock<ISession> _sessionMock;
|
||||
private Mock<IChannelSession> _channelSessionMock;
|
||||
private Mock<PipeStream> _pipeStreamMock;
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private ScpClient _scpClient;
|
||||
private DirectoryInfo _directoryInfo;
|
||||
private string _path;
|
||||
private string _quotedPath;
|
||||
private string _transformedPath;
|
||||
private IList<ScpUploadEventArgs> _uploadingRegister;
|
||||
private SshException _actualException;
|
||||
|
||||
[TestInitialize]
|
||||
public void Setup()
|
||||
{
|
||||
Arrange();
|
||||
Act();
|
||||
}
|
||||
|
||||
protected void Arrange()
|
||||
protected override void SetupData()
|
||||
{
|
||||
var random = new Random();
|
||||
|
||||
_connectionInfo = new ConnectionInfo("host", 22, "user", new PasswordAuthenticationMethod("user", "pwd"));
|
||||
_directoryInfo = new DirectoryInfo("source");
|
||||
_path = "/home/sshnet/" + random.Next().ToString(CultureInfo.InvariantCulture);
|
||||
_quotedPath = _path.ShellQuote();
|
||||
_transformedPath = random.Next().ToString();
|
||||
_uploadingRegister = new List<ScpUploadEventArgs>();
|
||||
}
|
||||
|
||||
_serviceFactoryMock = new Mock<IServiceFactory>(MockBehavior.Strict);
|
||||
_sessionMock = new Mock<ISession>(MockBehavior.Strict);
|
||||
_channelSessionMock = new Mock<IChannelSession>(MockBehavior.Strict);
|
||||
_pipeStreamMock = new Mock<PipeStream>(MockBehavior.Strict);
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
var sequence = new MockSequence();
|
||||
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo))
|
||||
.Returns(_sessionMock.Object);
|
||||
.Setup(p => p.CreateRemotePathDoubleQuoteTransformation())
|
||||
.Returns(_remotePathTransformationMock.Object);
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.Connect());
|
||||
_serviceFactoryMock.InSequence(sequence).Setup(p => p.CreatePipeStream()).Returns(_pipeStreamMock.Object);
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.CreateChannelSession()).Returns(_channelSessionMock.Object);
|
||||
_channelSessionMock.InSequence(sequence).Setup(p => p.Open());
|
||||
_remotePathTransformationMock.InSequence(sequence)
|
||||
.Setup(p => p.Transform(_path))
|
||||
.Returns(_transformedPath);
|
||||
_channelSessionMock.InSequence(sequence)
|
||||
.Setup(p => p.SendExecRequest(string.Format("scp -rt {0}", _quotedPath))).Returns(false);
|
||||
.Setup(p => p.SendExecRequest(string.Format("scp -rt {0}", _transformedPath)))
|
||||
.Returns(false);
|
||||
_channelSessionMock.InSequence(sequence).Setup(p => p.Dispose());
|
||||
_pipeStreamMock.As<IDisposable>().InSequence(sequence).Setup(p => p.Dispose());
|
||||
}
|
||||
|
||||
protected override void Arrange()
|
||||
{
|
||||
base.Arrange();
|
||||
|
||||
_scpClient = new ScpClient(_connectionInfo, false, _serviceFactoryMock.Object);
|
||||
_scpClient.Uploading += (sender, args) => _uploadingRegister.Add(args);
|
||||
_scpClient.Connect();
|
||||
}
|
||||
|
||||
protected virtual void Act()
|
||||
protected override void Act()
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -87,7 +87,7 @@ namespace Renci.SshNet.Tests.Classes
|
||||
[TestMethod]
|
||||
public void SendExecREquestOnChannelSessionShouldBeInvokedOnce()
|
||||
{
|
||||
_channelSessionMock.Verify(p => p.SendExecRequest(string.Format("scp -rt {0}", _quotedPath)), Times.Once);
|
||||
_channelSessionMock.Verify(p => p.SendExecRequest(string.Format("scp -rt {0}", _transformedPath)), Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
||||
+27
-27
@@ -4,34 +4,22 @@ using System.Globalization;
|
||||
using System.IO;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Channels;
|
||||
using Renci.SshNet.Common;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
[TestClass]
|
||||
public class ScpClientTest_Upload_FileInfoAndPath_SendExecRequestReturnsFalse
|
||||
public class ScpClientTest_Upload_FileInfoAndPath_SendExecRequestReturnsFalse : ScpClientTestBase
|
||||
{
|
||||
private Mock<IServiceFactory> _serviceFactoryMock;
|
||||
private Mock<ISession> _sessionMock;
|
||||
private Mock<IChannelSession> _channelSessionMock;
|
||||
private Mock<PipeStream> _pipeStreamMock;
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private ScpClient _scpClient;
|
||||
private FileInfo _fileInfo;
|
||||
private string _path;
|
||||
private string _quotedPath;
|
||||
private string _transformedPath;
|
||||
private string _fileName;
|
||||
private IList<ScpUploadEventArgs> _uploadingRegister;
|
||||
private SshException _actualException;
|
||||
|
||||
[TestInitialize]
|
||||
public void Setup()
|
||||
{
|
||||
Arrange();
|
||||
Act();
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public void Cleanup()
|
||||
{
|
||||
@@ -42,40 +30,52 @@ namespace Renci.SshNet.Tests.Classes
|
||||
}
|
||||
}
|
||||
|
||||
protected void Arrange()
|
||||
protected override void SetupData()
|
||||
{
|
||||
var random = new Random();
|
||||
_fileName = CreateTemporaryFile(new byte[] {1});
|
||||
|
||||
_fileName = CreateTemporaryFile(new byte[] { 1 });
|
||||
_connectionInfo = new ConnectionInfo("host", 22, "user", new PasswordAuthenticationMethod("user", "pwd"));
|
||||
_fileInfo = new FileInfo(_fileName);
|
||||
_path = "/home/sshnet/" + random.Next().ToString(CultureInfo.InvariantCulture);
|
||||
_quotedPath = _path.ShellQuote();
|
||||
_transformedPath = _path.ShellQuote();
|
||||
_uploadingRegister = new List<ScpUploadEventArgs>();
|
||||
}
|
||||
|
||||
_serviceFactoryMock = new Mock<IServiceFactory>(MockBehavior.Strict);
|
||||
_sessionMock = new Mock<ISession>(MockBehavior.Strict);
|
||||
_channelSessionMock = new Mock<IChannelSession>(MockBehavior.Strict);
|
||||
_pipeStreamMock = new Mock<PipeStream>(MockBehavior.Strict);
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
var sequence = new MockSequence();
|
||||
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo))
|
||||
.Returns(_sessionMock.Object);
|
||||
.Setup(p => p.CreateRemotePathDoubleQuoteTransformation())
|
||||
.Returns(_remotePathTransformationMock.Object);
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.Connect());
|
||||
_serviceFactoryMock.InSequence(sequence).Setup(p => p.CreatePipeStream()).Returns(_pipeStreamMock.Object);
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.CreateChannelSession()).Returns(_channelSessionMock.Object);
|
||||
_channelSessionMock.InSequence(sequence).Setup(p => p.Open());
|
||||
_remotePathTransformationMock.InSequence(sequence)
|
||||
.Setup(p => p.Transform(_path))
|
||||
.Returns(_transformedPath);
|
||||
_channelSessionMock.InSequence(sequence)
|
||||
.Setup(p => p.SendExecRequest(string.Format("scp -t {0}", _quotedPath))).Returns(false);
|
||||
.Setup(p => p.SendExecRequest(string.Format("scp -t {0}", _transformedPath)))
|
||||
.Returns(false);
|
||||
_channelSessionMock.InSequence(sequence).Setup(p => p.Dispose());
|
||||
_pipeStreamMock.As<IDisposable>().InSequence(sequence).Setup(p => p.Dispose());
|
||||
}
|
||||
|
||||
protected override void Arrange()
|
||||
{
|
||||
base.Arrange();
|
||||
|
||||
_scpClient = new ScpClient(_connectionInfo, false, _serviceFactoryMock.Object);
|
||||
_scpClient.Uploading += (sender, args) => _uploadingRegister.Add(args);
|
||||
_scpClient.Connect();
|
||||
}
|
||||
|
||||
protected virtual void Act()
|
||||
protected override void Act()
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -99,7 +99,7 @@ namespace Renci.SshNet.Tests.Classes
|
||||
[TestMethod]
|
||||
public void SendExecRequestOnChannelSessionShouldBeInvokedOnce()
|
||||
{
|
||||
_channelSessionMock.Verify(p => p.SendExecRequest(string.Format("scp -t {0}", _quotedPath)), Times.Once);
|
||||
_channelSessionMock.Verify(p => p.SendExecRequest(string.Format("scp -t {0}", _transformedPath)), Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
||||
@@ -6,36 +6,24 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Channels;
|
||||
using Renci.SshNet.Common;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
[TestClass]
|
||||
public class ScpClientTest_Upload_FileInfoAndPath_Success
|
||||
public class ScpClientTest_Upload_FileInfoAndPath_Success : ScpClientTestBase
|
||||
{
|
||||
private Mock<IServiceFactory> _serviceFactoryMock;
|
||||
private Mock<ISession> _sessionMock;
|
||||
private Mock<IChannelSession> _channelSessionMock;
|
||||
private Mock<PipeStream> _pipeStreamMock;
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private ScpClient _scpClient;
|
||||
private FileInfo _fileInfo;
|
||||
private string _path;
|
||||
private string _quotedPath;
|
||||
private string _transformedPath;
|
||||
private int _bufferSize;
|
||||
private byte[] _fileContent;
|
||||
private string _fileName;
|
||||
private int _fileSize;
|
||||
private IList<ScpUploadEventArgs> _uploadingRegister;
|
||||
|
||||
[TestInitialize]
|
||||
public void Setup()
|
||||
{
|
||||
Arrange();
|
||||
Act();
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public void Cleanup()
|
||||
{
|
||||
@@ -46,7 +34,7 @@ namespace Renci.SshNet.Tests.Classes
|
||||
}
|
||||
}
|
||||
|
||||
private void SetupData()
|
||||
protected override void SetupData()
|
||||
{
|
||||
var random = new Random();
|
||||
|
||||
@@ -57,30 +45,30 @@ namespace Renci.SshNet.Tests.Classes
|
||||
_connectionInfo = new ConnectionInfo("host", 22, "user", new PasswordAuthenticationMethod("user", "pwd"));
|
||||
_fileInfo = new FileInfo(_fileName);
|
||||
_path = "/home/sshnet/" + random.Next().ToString(CultureInfo.InvariantCulture);
|
||||
_quotedPath = _path.ShellQuote();
|
||||
_transformedPath = random.Next().ToString();
|
||||
_uploadingRegister = new List<ScpUploadEventArgs>();
|
||||
}
|
||||
|
||||
private void CreateMocks()
|
||||
{
|
||||
_serviceFactoryMock = new Mock<IServiceFactory>(MockBehavior.Strict);
|
||||
_sessionMock = new Mock<ISession>(MockBehavior.Strict);
|
||||
_channelSessionMock = new Mock<IChannelSession>(MockBehavior.Strict);
|
||||
_pipeStreamMock = new Mock<PipeStream>(MockBehavior.Strict);
|
||||
}
|
||||
|
||||
private void SetupMocks()
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
var sequence = new MockSequence();
|
||||
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo))
|
||||
.Returns(_sessionMock.Object);
|
||||
.Setup(p => p.CreateRemotePathDoubleQuoteTransformation())
|
||||
.Returns(_remotePathTransformationMock.Object);
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.Connect());
|
||||
_serviceFactoryMock.InSequence(sequence).Setup(p => p.CreatePipeStream()).Returns(_pipeStreamMock.Object);
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.CreateChannelSession()).Returns(_channelSessionMock.Object);
|
||||
_channelSessionMock.InSequence(sequence).Setup(p => p.Open());
|
||||
_remotePathTransformationMock.InSequence(sequence)
|
||||
.Setup(p => p.Transform(_path))
|
||||
.Returns(_transformedPath);
|
||||
_channelSessionMock.InSequence(sequence)
|
||||
.Setup(p => p.SendExecRequest(string.Format("scp -t {0}", _quotedPath))).Returns(true);
|
||||
.Setup(p => p.SendExecRequest(string.Format("scp -t {0}", _transformedPath)))
|
||||
.Returns(true);
|
||||
_pipeStreamMock.InSequence(sequence).Setup(p => p.ReadByte()).Returns(0);
|
||||
_channelSessionMock.InSequence(sequence).Setup(p => p.SendData(It.IsAny<byte[]>()));
|
||||
_pipeStreamMock.InSequence(sequence).Setup(p => p.ReadByte()).Returns(0);
|
||||
@@ -102,11 +90,9 @@ namespace Renci.SshNet.Tests.Classes
|
||||
_pipeStreamMock.As<IDisposable>().InSequence(sequence).Setup(p => p.Dispose());
|
||||
}
|
||||
|
||||
protected void Arrange()
|
||||
protected override void Arrange()
|
||||
{
|
||||
SetupData();
|
||||
CreateMocks();
|
||||
SetupMocks();
|
||||
base.Arrange();
|
||||
|
||||
_scpClient = new ScpClient(_connectionInfo, false, _serviceFactoryMock.Object)
|
||||
{
|
||||
@@ -116,7 +102,7 @@ namespace Renci.SshNet.Tests.Classes
|
||||
_scpClient.Connect();
|
||||
}
|
||||
|
||||
protected virtual void Act()
|
||||
protected override void Act()
|
||||
{
|
||||
_scpClient.Upload(_fileInfo, _path);
|
||||
}
|
||||
@@ -124,7 +110,7 @@ namespace Renci.SshNet.Tests.Classes
|
||||
[TestMethod]
|
||||
public void SendExecRequestOnChannelSessionShouldBeInvokedOnce()
|
||||
{
|
||||
_channelSessionMock.Verify(p => p.SendExecRequest(string.Format("scp -t {0}", _quotedPath)), Times.Once);
|
||||
_channelSessionMock.Verify(p => p.SendExecRequest(string.Format("scp -t {0}", _transformedPath)), Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
||||
+26
-26
@@ -4,33 +4,21 @@ using System.Globalization;
|
||||
using System.IO;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using Renci.SshNet.Channels;
|
||||
using Renci.SshNet.Common;
|
||||
|
||||
namespace Renci.SshNet.Tests.Classes
|
||||
{
|
||||
[TestClass]
|
||||
public class ScpClientTest_Upload_StreamAndPath_SendExecRequestReturnsFalse
|
||||
public class ScpClientTest_Upload_StreamAndPath_SendExecRequestReturnsFalse : ScpClientTestBase
|
||||
{
|
||||
private Mock<IServiceFactory> _serviceFactoryMock;
|
||||
private Mock<ISession> _sessionMock;
|
||||
private Mock<IChannelSession> _channelSessionMock;
|
||||
private Mock<PipeStream> _pipeStreamMock;
|
||||
private ConnectionInfo _connectionInfo;
|
||||
private ScpClient _scpClient;
|
||||
private Stream _source;
|
||||
private string _path;
|
||||
private string _quotedPath;
|
||||
private string _transformedPath;
|
||||
private IList<ScpUploadEventArgs> _uploadingRegister;
|
||||
private SshException _actualException;
|
||||
|
||||
[TestInitialize]
|
||||
public void Setup()
|
||||
{
|
||||
Arrange();
|
||||
Act();
|
||||
}
|
||||
|
||||
[TestCleanup]
|
||||
public void Cleanup()
|
||||
{
|
||||
@@ -40,39 +28,51 @@ namespace Renci.SshNet.Tests.Classes
|
||||
}
|
||||
}
|
||||
|
||||
protected void Arrange()
|
||||
protected override void SetupData()
|
||||
{
|
||||
var random = new Random();
|
||||
|
||||
_connectionInfo = new ConnectionInfo("host", 22, "user", new PasswordAuthenticationMethod("user", "pwd"));
|
||||
_source = new MemoryStream();
|
||||
_path = "/home/sshnet/" + random.Next().ToString(CultureInfo.InvariantCulture);
|
||||
_quotedPath = _path.ShellQuote();
|
||||
_transformedPath = random.Next().ToString();
|
||||
_uploadingRegister = new List<ScpUploadEventArgs>();
|
||||
}
|
||||
|
||||
_serviceFactoryMock = new Mock<IServiceFactory>(MockBehavior.Strict);
|
||||
_sessionMock = new Mock<ISession>(MockBehavior.Strict);
|
||||
_channelSessionMock = new Mock<IChannelSession>(MockBehavior.Strict);
|
||||
_pipeStreamMock = new Mock<PipeStream>(MockBehavior.Strict);
|
||||
|
||||
protected override void SetupMocks()
|
||||
{
|
||||
var sequence = new MockSequence();
|
||||
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo))
|
||||
.Returns(_sessionMock.Object);
|
||||
.Setup(p => p.CreateRemotePathDoubleQuoteTransformation())
|
||||
.Returns(_remotePathTransformationMock.Object);
|
||||
_serviceFactoryMock.InSequence(sequence)
|
||||
.Setup(p => p.CreateSession(_connectionInfo))
|
||||
.Returns(_sessionMock.Object);
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.Connect());
|
||||
_serviceFactoryMock.InSequence(sequence).Setup(p => p.CreatePipeStream()).Returns(_pipeStreamMock.Object);
|
||||
_sessionMock.InSequence(sequence).Setup(p => p.CreateChannelSession()).Returns(_channelSessionMock.Object);
|
||||
_channelSessionMock.InSequence(sequence).Setup(p => p.Open());
|
||||
_remotePathTransformationMock.InSequence(sequence)
|
||||
.Setup(p => p.Transform(_path))
|
||||
.Returns(_transformedPath);
|
||||
_channelSessionMock.InSequence(sequence)
|
||||
.Setup(p => p.SendExecRequest(string.Format("scp -t {0}", _quotedPath))).Returns(false);
|
||||
.Setup(p => p.SendExecRequest(string.Format("scp -t {0}", _transformedPath)))
|
||||
.Returns(false);
|
||||
_channelSessionMock.InSequence(sequence).Setup(p => p.Dispose());
|
||||
_pipeStreamMock.As<IDisposable>().InSequence(sequence).Setup(p => p.Dispose());
|
||||
}
|
||||
|
||||
protected override void Arrange()
|
||||
{
|
||||
base.Arrange();
|
||||
|
||||
_scpClient = new ScpClient(_connectionInfo, false, _serviceFactoryMock.Object);
|
||||
_scpClient.Uploading += (sender, args) => _uploadingRegister.Add(args);
|
||||
_scpClient.Connect();
|
||||
}
|
||||
|
||||
protected virtual void Act()
|
||||
protected override void Act()
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -96,7 +96,7 @@ namespace Renci.SshNet.Tests.Classes
|
||||
[TestMethod]
|
||||
public void SendExecRequestOnChannelSessionShouldBeInvokedOnce()
|
||||
{
|
||||
_channelSessionMock.Verify(p => p.SendExecRequest(string.Format("scp -t {0}", _quotedPath)), Times.Once);
|
||||
_channelSessionMock.Verify(p => p.SendExecRequest(string.Format("scp -t {0}", _transformedPath)), Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
||||
@@ -211,6 +211,7 @@
|
||||
<Compile Include="Classes\NetConfClientTest_Dispose_Disposed.cs" />
|
||||
<Compile Include="Classes\NetConfClientTest_Finalize_Connected.cs" />
|
||||
<Compile Include="Classes\PipeStreamTest_Dispose.cs" />
|
||||
<Compile Include="Classes\ScpClientTestBase.cs" />
|
||||
<Compile Include="Classes\ScpClientTest_Download_PathAndDirectoryInfo_SendExecRequestReturnsFalse.cs" />
|
||||
<Compile Include="Classes\ScpClientTest_Download_PathAndFileInfo_SendExecRequestReturnsFalse.cs" />
|
||||
<Compile Include="Classes\ScpClientTest_Download_PathAndStream_SendExecRequestReturnsFalse.cs" />
|
||||
|
||||
@@ -64,13 +64,14 @@ namespace Renci.SshNet
|
||||
ISftpResponseFactory CreateSftpResponseFactory();
|
||||
|
||||
/// <summary>
|
||||
/// Creates an <see cref="IRemotePathTransformation"/> that quotes a path in a way to be suitable
|
||||
/// to be used with a shell.
|
||||
/// Creates an <see cref="IRemotePathTransformation"/> that encloses a path in double quotes, and escapes
|
||||
/// any embedded double quote with a backslash.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// An <see cref="IRemotePathTransformation"/> that quotes a path in a way to be suitable to be used
|
||||
/// An <see cref="IRemotePathTransformation"/> that encloses a path in double quotes, and escapes any
|
||||
/// embedded double quote with a backslash.
|
||||
/// with a shell.
|
||||
/// </returns>
|
||||
IRemotePathTransformation CreateRemotePathQuoteTransformation();
|
||||
IRemotePathTransformation CreateRemotePathDoubleQuoteTransformation();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,17 @@ namespace Renci.SshNet
|
||||
get { return _requestMessage.MethodName; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the password as a sequence of bytes.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The password as a sequence of bytes.
|
||||
/// </value>
|
||||
internal byte[] Password
|
||||
{
|
||||
get { return _password; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when user's password has expired and needs to be changed.
|
||||
/// </summary>
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace Renci.SshNet
|
||||
{
|
||||
/// <summary>
|
||||
/// Encloses a path in double quotes, and escapes any embedded double quote with a backslash.
|
||||
/// </summary>
|
||||
internal class RemotePathDoubleQuoteTransformation : IRemotePathTransformation
|
||||
{
|
||||
/// <summary>
|
||||
/// Encloses a path in double quotes, and escapes any embedded double quote with a backslash.
|
||||
/// </summary>
|
||||
/// <param name="path">The path to transform.</param>
|
||||
/// <returns>
|
||||
/// The transformed path.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="path"/> is <c>null</c>.</exception>
|
||||
/// <example>
|
||||
/// <list type="table">
|
||||
/// <listheader>
|
||||
/// <term>Original</term>
|
||||
/// <term>Transformed</term>
|
||||
/// </listheader>
|
||||
/// <item>
|
||||
/// <term>/var/log/auth.log</term>
|
||||
/// <term>"/var/log/auth.log"</term>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>/var/mp3/Guns N' Roses</term>
|
||||
/// <term>"/var/mp3/Guns N' Roses"</term>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>/var/garbage!/temp</term>
|
||||
/// <term>"/var/garbage!/temp"</term>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>/var/would be 'kewl'!/not?</term>
|
||||
/// <term>"/var/would be 'kewl'!, not?"</term>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>!ignore!</term>
|
||||
/// <term>"!ignore!"</term>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term></term>
|
||||
/// <term>""</term>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>Hello "World"</term>
|
||||
/// <term>"Hello \"World"</term>
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// </example>
|
||||
public string Transform(string path)
|
||||
{
|
||||
if (path == null)
|
||||
{
|
||||
throw new ArgumentNullException("path");
|
||||
}
|
||||
|
||||
var transformed = new StringBuilder(path.Length);
|
||||
|
||||
transformed.Append('"');
|
||||
foreach (var c in path)
|
||||
{
|
||||
if (c == '"')
|
||||
transformed.Append('\\');
|
||||
transformed.Append(c);
|
||||
}
|
||||
transformed.Append('"');
|
||||
|
||||
return transformed.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,10 @@
|
||||
/// <returns>
|
||||
/// The specified path as is.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// This transformation is recommended for servers that do not require any quoting to preserve the
|
||||
/// literal value of metacharacters, or when paths are guaranteed to never contain any such characters.
|
||||
/// </remarks>
|
||||
public string Transform(string path)
|
||||
{
|
||||
return path;
|
||||
|
||||
+46
-10
@@ -4,12 +4,12 @@ using System.Text;
|
||||
namespace Renci.SshNet
|
||||
{
|
||||
/// <summary>
|
||||
/// Quotes a path in a way to be suitable to be used with a shell.
|
||||
/// Quotes a path in a way to be suitable to be used with a shell-based server.
|
||||
/// </summary>
|
||||
internal class RemotePathQuoteTransformation : IRemotePathTransformation
|
||||
internal class RemotePathShellQuoteTransformation : IRemotePathTransformation
|
||||
{
|
||||
/// <summary>
|
||||
/// Quotes a path in a way to be suitable to be used with a shell.
|
||||
/// Quotes a path in a way to be suitable to be used with a shell-based server.
|
||||
/// </summary>
|
||||
/// <param name="path">The path to transform.</param>
|
||||
/// <returns>
|
||||
@@ -23,9 +23,13 @@ namespace Renci.SshNet
|
||||
/// pair of quotation marks.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// If a shell command contains an exclamation mark (!), the C-Shell interprets it as a
|
||||
/// meta-character for history substitution. This even works inside single-quotes or
|
||||
/// quotation marks, unless escaped with a backslash (\).
|
||||
/// An exclamation mark in <paramref name="path"/> is escaped with a backslash. This is
|
||||
/// necessary because C Shell interprets it as a meta-character for history substitution
|
||||
/// even when enclosed in single quotes or quotation marks.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// All other characters are enclosed in single quotes. Sequences of such characters are grouped
|
||||
/// in a single pair of single quotes.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// References:
|
||||
@@ -42,10 +46,42 @@ namespace Renci.SshNet
|
||||
/// </list>
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <returns>
|
||||
/// The transformed path.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="path"/> is <c>null</c>.</exception>
|
||||
/// <example>
|
||||
/// <list type="table">
|
||||
/// <listheader>
|
||||
/// <term>Original</term>
|
||||
/// <term>Transformed</term>
|
||||
/// </listheader>
|
||||
/// <item>
|
||||
/// <term>/var/log/auth.log</term>
|
||||
/// <term>'/var/log/auth.log'</term>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>/var/mp3/Guns N' Roses</term>
|
||||
/// <term>'/var/mp3/Guns N'"'"' Roses'</term>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>/var/garbage!/temp</term>
|
||||
/// <term>'/var/garbage'\!'/temp'</term>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>/var/would be 'kewl'!, not?</term>
|
||||
/// <term>'/var/would be '"'"'kewl'"'"\!', not?'</term>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>!ignore!</term>
|
||||
/// <term>\!'ignore'\!</term>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term></term>
|
||||
/// <term>''</term>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>Hello "World"</term>
|
||||
/// <term>'Hello "World"'</term>
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// </example>
|
||||
public string Transform(string path)
|
||||
{
|
||||
if (path == null)
|
||||
@@ -5,32 +5,36 @@
|
||||
/// </summary>
|
||||
public static class RemotePathTransformation
|
||||
{
|
||||
private static readonly IRemotePathTransformation QuoteTransformation = new RemotePathQuoteTransformation();
|
||||
private static readonly IRemotePathTransformation ShellQuoteTransformation = new RemotePathShellQuoteTransformation();
|
||||
private static readonly IRemotePathTransformation NoneTransformation = new RemotePathNoneTransformation();
|
||||
private static readonly IRemotePathTransformation DoubleQuoteTransformation = new RemotePathDoubleQuoteTransformation();
|
||||
|
||||
/// <summary>
|
||||
/// Quotes a path in a way to be suitable to be used with a shell.
|
||||
/// Quotes a path in a way to be suitable to be used with a shell-based server.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// A quoted path.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// If the path contains a single-quote, that character is embedded in quotation marks.
|
||||
/// If a path contains a single-quote, that character is embedded in quotation marks (eg. "'").
|
||||
/// Sequences of single-quotes are grouped in a single pair of quotation marks.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// An exclamation mark (!) is escaped with a backslash, because the C shell would otherwise
|
||||
/// interprete it as a meta-character for history substitution. It does this even if it's
|
||||
/// enclosed in single-quotes or quotation marks, unless escaped with a backslash (\).
|
||||
/// An exclamation mark in a path is escaped with a backslash. This is necessary because C Shell
|
||||
/// interprets it as a meta-character for history substitution even when enclosed in single quotes
|
||||
/// or quotation marks.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// All other character are enclosed in single-quotes, and grouped in a single pair of
|
||||
/// single quotes where contiguous.
|
||||
/// All other characters are enclosed in single quotes. Sequences of such characters are grouped
|
||||
/// in a single pair of single quotes.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <example>
|
||||
/// <list type="table">
|
||||
/// <listheader>
|
||||
/// <term>Original</term>
|
||||
/// <term>Quoted</term>
|
||||
/// <term>Transformed</term>
|
||||
/// </listheader>
|
||||
/// <item>
|
||||
/// <term>/var/log/auth.log</term>
|
||||
@@ -42,15 +46,11 @@
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>/var/garbage!/temp</term>
|
||||
/// <term>'/var/garbage\!/temp'</term>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>/var/garbage!/temp</term>
|
||||
/// <term>'/var/garbage'\!'/temp'</term>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>/var/would be 'kewl'!/not?</term>
|
||||
/// <term>'/var/would be '"'"'kewl'"'"\!'/not?'</term>
|
||||
/// <term>/var/would be 'kewl'!, not?</term>
|
||||
/// <term>'/var/would be '"'"'kewl'"'"\!', not?'</term>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>!ignore!</term>
|
||||
@@ -60,24 +60,76 @@
|
||||
/// <term></term>
|
||||
/// <term>''</term>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>Hello "World"</term>
|
||||
/// <term>'Hello "World"'</term>
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// </example>
|
||||
public static IRemotePathTransformation Quote
|
||||
public static IRemotePathTransformation ShellQuote
|
||||
{
|
||||
get { return QuoteTransformation; }
|
||||
get { return ShellQuoteTransformation; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs no transformation.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This transformation should be used for servers that do not support escape sequences in paths
|
||||
/// or paths enclosed in quotes, or would preserve the escape characters or quotes in the path that
|
||||
/// is handed off to the IO layer. This is recommended for servers that are not shell-based.
|
||||
/// Recommended for servers that do not require any character to be escaped or enclosed in quotes,
|
||||
/// or when paths are guaranteed to never contain any special characters (such as #, ", ', $, ...).
|
||||
/// </remarks>
|
||||
public static IRemotePathTransformation None
|
||||
{
|
||||
get { return NoneTransformation; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Encloses a path in double quotes, and escapes any embedded double quote with a backslash.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// A transformation that encloses a path in double quotes, and escapes any embedded double quote with
|
||||
/// a backslash.
|
||||
/// </value>
|
||||
/// <example>
|
||||
/// <list type="table">
|
||||
/// <listheader>
|
||||
/// <term>Original</term>
|
||||
/// <term>Transformed</term>
|
||||
/// </listheader>
|
||||
/// <item>
|
||||
/// <term>/var/log/auth.log</term>
|
||||
/// <term>"/var/log/auth.log"</term>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>/var/mp3/Guns N' Roses</term>
|
||||
/// <term>"/var/mp3/Guns N' Roses"</term>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>/var/garbage!/temp</term>
|
||||
/// <term>"/var/garbage!/temp"</term>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>/var/would be 'kewl'!/not?</term>
|
||||
/// <term>"/var/would be 'kewl'!, not?"</term>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>!ignore!</term>
|
||||
/// <term>"!ignore!"</term>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term></term>
|
||||
/// <term>""</term>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>Hello "World"</term>
|
||||
/// <term>"Hello \"World"</term>
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// </example>
|
||||
public static IRemotePathTransformation DoubleQuote
|
||||
{
|
||||
get { return DoubleQuoteTransformation; }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,8 +163,9 @@
|
||||
<Compile Include="Messages\Transport\KeyExchangeEcdhInitMessage.cs" />
|
||||
<Compile Include="Messages\Transport\KeyExchangeEcdhReplyMessage.cs" />
|
||||
<Compile Include="Netconf\INetConfSession.cs" />
|
||||
<Compile Include="RemotePathDoubleQuoteTransformation.cs" />
|
||||
<Compile Include="RemotePathNoneTransformation.cs" />
|
||||
<Compile Include="RemotePathQuoteTransformation.cs" />
|
||||
<Compile Include="RemotePathShellQuoteTransformation.cs" />
|
||||
<Compile Include="RemotePathTransformation.cs" />
|
||||
<Compile Include="Security\Cryptography\HMACMD5.cs" />
|
||||
<Compile Include="Security\Cryptography\HMACSHA1.cs" />
|
||||
|
||||
@@ -56,12 +56,18 @@ namespace Renci.SshNet
|
||||
/// Gets or sets the transformation to apply to remote paths.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The transformation to apply to remote paths. The default is <see cref="SshNet.RemotePathTransformation.Quote"/>.
|
||||
/// The transformation to apply to remote paths. The default is <see cref="SshNet.RemotePathTransformation.DoubleQuote"/>.
|
||||
/// </value>
|
||||
/// <exception cref="RemotePathTransformation"><paramref name="value"/> is <c>null</c>.</exception>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="value"/> is <c>null</c>.</exception>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This transformation is applied to the remote file or directory path that is passed to the
|
||||
/// <c>scp</c> command.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// See <see cref="SshNet.RemotePathTransformation"/> for the transformations that are supplied
|
||||
/// out-of-the-box with SSH.NET.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public IRemotePathTransformation RemotePathTransformation
|
||||
{
|
||||
@@ -186,7 +192,7 @@ namespace Renci.SshNet
|
||||
{
|
||||
OperationTimeout = SshNet.Session.InfiniteTimeSpan;
|
||||
BufferSize = 1024 * 16;
|
||||
_remotePathTransformation = SshNet.RemotePathTransformation.Quote;
|
||||
_remotePathTransformation = serviceFactory.CreateRemotePathDoubleQuoteTransformation();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -138,16 +138,17 @@ namespace Renci.SshNet
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an <see cref="IRemotePathTransformation"/> that quotes a path in a way to be suitable
|
||||
/// to be used with a shell.
|
||||
/// Creates an <see cref="IRemotePathTransformation"/> that encloses a path in double quotes, and escapes
|
||||
/// any embedded double quote with a backslash.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// An <see cref="IRemotePathTransformation"/> that quotes a path in a way to be suitable to be used
|
||||
/// An <see cref="IRemotePathTransformation"/> that encloses a path in double quotes, and escapes any
|
||||
/// embedded double quote with a backslash.
|
||||
/// with a shell.
|
||||
/// </returns>
|
||||
public IRemotePathTransformation CreateRemotePathQuoteTransformation()
|
||||
public IRemotePathTransformation CreateRemotePathDoubleQuoteTransformation()
|
||||
{
|
||||
return new RemotePathQuoteTransformation();
|
||||
return RemotePathTransformation.DoubleQuote;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user