resolved several parsing bugs in the rdcman deserializer

This commit is contained in:
David Sparer
2019-03-04 11:17:45 -06:00
parent ec42fe7d7d
commit 4847ce054b
7 changed files with 273 additions and 257 deletions

View File

@@ -1,20 +1,21 @@
using System.IO;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using mRemoteNG.Config.Serializers;
using mRemoteNG.Connection;
using mRemoteNG.Connection.Protocol;
using mRemoteNG.Connection.Protocol.RDP;
using mRemoteNG.Container;
using mRemoteNG.Tree;
using mRemoteNGTests.Properties;
using NUnit.Framework;
namespace mRemoteNGTests.Config.Serializers.MiscSerializers
{
public class RemoteDesktopConnectionManager27DeserializerTests
public class RemoteDesktopConnectionManager27DeserializerTests
{
private string _connectionFileContents;
private RemoteDesktopConnectionManagerDeserializer _deserializer;
private ConnectionTreeModel _connectionTreeModel;
private const string ExpectedName = "server1_displayname";
private const string ExpectedHostname = "server1";
private const string ExpectedDescription = "Comment text here";
@@ -44,262 +45,62 @@ namespace mRemoteNGTests.Config.Serializers.MiscSerializers
{
_connectionFileContents = Resources.test_rdcman_v2_7_schema3;
_deserializer = new RemoteDesktopConnectionManagerDeserializer();
_connectionTreeModel = _deserializer.Deserialize(_connectionFileContents);
}
[Test]
public void ConnectionTreeModelHasARootNode()
{
var numberOfRootNodes = _connectionTreeModel.RootNodes.Count;
var connectionTreeModel = _deserializer.Deserialize(_connectionFileContents);
var numberOfRootNodes = connectionTreeModel.RootNodes.Count;
Assert.That(numberOfRootNodes, Is.GreaterThan(0));
}
[Test]
public void RootNodeHasContents()
{
var rootNodeContents = _connectionTreeModel.RootNodes.First().Children;
var connectionTreeModel = _deserializer.Deserialize(_connectionFileContents);
var rootNodeContents = connectionTreeModel.RootNodes.First().Children;
Assert.That(rootNodeContents, Is.Not.Empty);
}
[Test]
public void AllSubRootFoldersImported()
{
var rootNode = _connectionTreeModel.RootNodes.First();
var connectionTreeModel = _deserializer.Deserialize(_connectionFileContents);
var rootNode = connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var rootNodeContents = importedRdcmanRootNode.Children.Count(node => node.Name == "Group1" || node.Name == "Group2");
Assert.That(rootNodeContents, Is.EqualTo(2));
}
[Test]
public void ConnectionDisplayNameImported()
[TestCaseSource(nameof(ExpectedPropertyValues))]
public void PropertiesWithValuesAreCorrectlyImported(Func<ConnectionInfo, object> propSelector, object expectedValue)
{
var rootNode = _connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
var connection = group1.Children.First();
Assert.That(connection.Name, Is.EqualTo(ExpectedName));
var connectionTreeModel = _deserializer.Deserialize(_connectionFileContents);
var connection = connectionTreeModel
.GetRecursiveChildList()
.OfType<ContainerInfo>()
.First(node => node.Name == "Group1")
.Children
.First();
Assert.That(propSelector(connection), Is.EqualTo(expectedValue));
}
[Test]
public void ConnectionHostnameImported()
[TestCaseSource(nameof(NullPropertyValues))]
public void PropertiesWithoutValuesAreIgnored(Func<ConnectionInfo, object> propSelector)
{
var rootNode = _connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
var connection = group1.Children.First();
Assert.That(connection.Hostname, Is.EqualTo(ExpectedHostname));
}
var connectionTreeModel = _deserializer.Deserialize(Resources.test_rdcman_v2_7_schema3_null_values);
[Test]
public void ConnectionDescriptionImported()
{
var rootNode = _connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
var connection = group1.Children.First();
Assert.That(connection.Description, Is.EqualTo(ExpectedDescription));
}
var importedConnection = connectionTreeModel
.GetRecursiveChildList()
.OfType<ContainerInfo>()
.First(node => node.Name == "Group1")
.Children
.First();
[Test]
public void ConnectionUsernameImported()
{
var rootNode = _connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
var connection = group1.Children.First();
Assert.That(connection.Username, Is.EqualTo(ExpectedUsername));
}
[Test]
public void ConnectionDomainImported()
{
var rootNode = _connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
var connection = group1.Children.First();
Assert.That(connection.Domain, Is.EqualTo(ExpectedDomain));
}
// Since password is encrypted with a machine key, cant test decryption on another machine
//[Test]
//public void ConnectionPasswordImported()
//{
// var rootNode = _connectionTreeModel.RootNodes.First();
// var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
// var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
// var connection = group1.Children.First();
// Assert.That(connection.Password, Is.EqualTo(ExpectedPassword));
//}
[Test]
public void ConnectionProtocolSetToRdp()
{
var rootNode = _connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
var connection = group1.Children.First();
Assert.That(connection.Protocol, Is.EqualTo(ProtocolType.RDP));
}
[Test]
public void ConnectionUseConsoleSessionImported()
{
var rootNode = _connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
var connection = group1.Children.First();
Assert.That(connection.UseConsoleSession, Is.EqualTo(ExpectedUseConsoleSession));
}
[Test]
public void ConnectionPortImported()
{
var rootNode = _connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
var connection = group1.Children.First();
Assert.That(connection.Port, Is.EqualTo(ExpectedPort));
}
[Test]
public void ConnectionGatewayUsageMethodImported()
{
var rootNode = _connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
var connection = group1.Children.First();
Assert.That(connection.RDGatewayUsageMethod, Is.EqualTo(ExpectedGatewayUsageMethod));
}
[Test]
public void ConnectionGatewayHostnameImported()
{
var rootNode = _connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
var connection = group1.Children.First();
Assert.That(connection.RDGatewayHostname, Is.EqualTo(ExpectedGatewayHostname));
}
[Test]
public void ConnectionGatewayUsernameImported()
{
var rootNode = _connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
var connection = group1.Children.First();
Assert.That(connection.RDGatewayUsername, Is.EqualTo(ExpectedGatewayUsername));
}
// Since password is encrypted with a machine key, cant test decryption on another machine
//[Test]
//public void ConnectionGatewayPasswordImported()
//{
// var rootNode = _connectionTreeModel.RootNodes.First();
// var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
// var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
// var connection = group1.Children.First();
// Assert.That(connection.RDGatewayPassword, Is.EqualTo(ExpectedGatewayPassword));
//}
[Test]
public void ConnectionGatewayDomainImported()
{
var rootNode = _connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
var connection = group1.Children.First();
Assert.That(connection.RDGatewayDomain, Is.EqualTo(ExpectedGatewayDomain));
}
[Test]
public void ConnectionResolutionImported()
{
var rootNode = _connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
var connection = group1.Children.First();
Assert.That(connection.Resolution, Is.EqualTo(ExpectedRdpResolution));
}
[Test]
public void ConnectionColorDepthImported()
{
var rootNode = _connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
var connection = group1.Children.First();
Assert.That(connection.Colors, Is.EqualTo(ExpectedRdpColorDepth));
}
[Test]
public void ConnectionAudioRedirectionImported()
{
var rootNode = _connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
var connection = group1.Children.First();
Assert.That(connection.RedirectSound, Is.EqualTo(ExpectedAudioRedirection));
}
[Test]
public void ConnectionKeyRedirectionImported()
{
var rootNode = _connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
var connection = group1.Children.First();
Assert.That(connection.RedirectKeys, Is.EqualTo(ExpectedKeyRedirection));
}
[Test]
public void ConnectionDriveRedirectionImported()
{
var rootNode = _connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
var connection = group1.Children.First();
Assert.That(connection.RedirectDiskDrives, Is.EqualTo(ExpectedDriveRedirection));
}
[Test]
public void ConnectionPortRedirectionImported()
{
var rootNode = _connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
var connection = group1.Children.First();
Assert.That(connection.RedirectPorts, Is.EqualTo(ExpectedPortRedirection));
}
[Test]
public void ConnectionPrinterRedirectionImported()
{
var rootNode = _connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
var connection = group1.Children.First();
Assert.That(connection.RedirectPrinters, Is.EqualTo(ExpectedPrinterRedirection));
}
[Test]
public void ConnectionSmartcardRedirectionImported()
{
var rootNode = _connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
var connection = group1.Children.First();
Assert.That(connection.RedirectSmartCards, Is.EqualTo(ExpectedSmartcardRedirection));
}
[Test]
public void ConnectionauthenticationLevelImported()
{
var rootNode = _connectionTreeModel.RootNodes.First();
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
var connection = group1.Children.First();
Assert.That(connection.RDPAuthenticationLevel, Is.EqualTo(ExpectedAuthLevel));
Assert.That(propSelector(importedConnection), Is.EqualTo(propSelector(new ConnectionInfo())));
}
[Test]
@@ -322,5 +123,61 @@ namespace mRemoteNGTests.Config.Serializers.MiscSerializers
var badFileContents = Resources.test_rdcman_noversion;
Assert.That(() => _deserializer.Deserialize(badFileContents), Throws.TypeOf<FileFormatException>());
}
private static IEnumerable<TestCaseData> ExpectedPropertyValues()
{
return new[]
{
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Name), ExpectedName).SetName(nameof(ConnectionInfo.Name)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Hostname), ExpectedHostname).SetName(nameof(ConnectionInfo.Hostname)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Description), ExpectedDescription).SetName(nameof(ConnectionInfo.Description)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Username), ExpectedUsername).SetName(nameof(ConnectionInfo.Username)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Domain), ExpectedDomain).SetName(nameof(ConnectionInfo.Domain)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Protocol), ProtocolType.RDP).SetName(nameof(ConnectionInfo.Protocol)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.UseConsoleSession), ExpectedUseConsoleSession).SetName(nameof(ConnectionInfo.UseConsoleSession)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Port), ExpectedPort).SetName(nameof(ConnectionInfo.Port)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RDGatewayUsageMethod), ExpectedGatewayUsageMethod).SetName(nameof(ConnectionInfo.RDGatewayUsageMethod)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RDGatewayHostname), ExpectedGatewayHostname).SetName(nameof(ConnectionInfo.RDGatewayHostname)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RDGatewayUsername), ExpectedGatewayUsername).SetName(nameof(ConnectionInfo.RDGatewayUsername)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RDGatewayDomain), ExpectedGatewayDomain).SetName(nameof(ConnectionInfo.RDGatewayDomain)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Resolution), ExpectedRdpResolution).SetName(nameof(ConnectionInfo.Resolution)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Colors), ExpectedRdpColorDepth).SetName(nameof(ConnectionInfo.Colors)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RedirectSound), ExpectedAudioRedirection).SetName(nameof(ConnectionInfo.RedirectSound)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RedirectKeys), ExpectedKeyRedirection).SetName(nameof(ConnectionInfo.RedirectKeys)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RDPAuthenticationLevel), ExpectedAuthLevel).SetName(nameof(ConnectionInfo.RDPAuthenticationLevel)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RedirectSmartCards), ExpectedSmartcardRedirection).SetName(nameof(ConnectionInfo.RedirectSmartCards)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RedirectPrinters), ExpectedPrinterRedirection).SetName(nameof(ConnectionInfo.RedirectPrinters)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RedirectPorts), ExpectedPortRedirection).SetName(nameof(ConnectionInfo.RedirectPorts)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RedirectDiskDrives), ExpectedDriveRedirection).SetName(nameof(ConnectionInfo.RedirectDiskDrives)),
};
}
private static IEnumerable<TestCaseData> NullPropertyValues()
{
return new[]
{
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Name)).SetName(nameof(ConnectionInfo.Name)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Hostname)).SetName(nameof(ConnectionInfo.Hostname)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Description)).SetName(nameof(ConnectionInfo.Description)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Username)).SetName(nameof(ConnectionInfo.Username)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Domain)).SetName(nameof(ConnectionInfo.Domain)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Protocol)).SetName(nameof(ConnectionInfo.Protocol)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.UseConsoleSession)).SetName(nameof(ConnectionInfo.UseConsoleSession)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Port)).SetName(nameof(ConnectionInfo.Port)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RDGatewayUsageMethod)).SetName(nameof(ConnectionInfo.RDGatewayUsageMethod)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RDGatewayHostname)).SetName(nameof(ConnectionInfo.RDGatewayHostname)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RDGatewayUsername)).SetName(nameof(ConnectionInfo.RDGatewayUsername)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RDGatewayDomain)).SetName(nameof(ConnectionInfo.RDGatewayDomain)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Resolution)).SetName(nameof(ConnectionInfo.Resolution)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Colors)).SetName(nameof(ConnectionInfo.Colors)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RedirectSound)).SetName(nameof(ConnectionInfo.RedirectSound)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RedirectKeys)).SetName(nameof(ConnectionInfo.RedirectKeys)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RDPAuthenticationLevel)).SetName(nameof(ConnectionInfo.RDPAuthenticationLevel)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RedirectSmartCards)).SetName(nameof(ConnectionInfo.RedirectSmartCards)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RedirectPrinters)).SetName(nameof(ConnectionInfo.RedirectPrinters)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RedirectPorts)).SetName(nameof(ConnectionInfo.RedirectPorts)),
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RedirectDiskDrives)).SetName(nameof(ConnectionInfo.RedirectDiskDrives)),
};
}
}
}

View File

@@ -298,6 +298,32 @@ namespace mRemoteNGTests.Properties {
}
}
/// <summary>
/// Looks up a localized string similar to &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
///&lt;RDCMan programVersion=&quot;2.7&quot; schemaVersion=&quot;3&quot;&gt;
/// &lt;file&gt;
/// &lt;credentialsProfiles /&gt;
/// &lt;properties&gt;
/// &lt;expanded&gt;True&lt;/expanded&gt;
/// &lt;name&gt;test_RDCMan_connections&lt;/name&gt;
/// &lt;/properties&gt;
/// &lt;smartGroup&gt;
/// &lt;properties&gt;
/// &lt;expanded&gt;False&lt;/expanded&gt;
/// &lt;name&gt;AllServers&lt;/name&gt;
/// &lt;/properties&gt;
/// &lt;ruleGroup operator=&quot;All&quot;&gt;
/// &lt;rule&gt;
/// &lt;property&gt;DisplayName&lt;/property&gt;
/// &lt;operator&gt;Matches&lt;/operator&gt;
/// [rest of string was truncated]&quot;;.
/// </summary>
internal static string test_rdcman_v2_7_schema3_null_values {
get {
return ResourceManager.GetString("test_rdcman_v2_7_schema3_null_values", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to screen mode id:i:1
///use multimon:i:0

View File

@@ -172,6 +172,9 @@
<data name="test_rdcman_v2_7_schema3" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\test_RDCMan_v2_7_schema3.rdg;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
</data>
<data name="test_rdcman_v2_7_schema3_null_values" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\test_rdcman_v2_7_schema3_null_values.rdg;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
</data>
<data name="test_remotedesktopconnection_rdp" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\test_remotedesktopconnection.rdp;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16</value>
</data>

View File

@@ -0,0 +1,95 @@
<?xml version="1.0" encoding="utf-8"?>
<RDCMan programVersion="2.7" schemaVersion="3">
<file>
<credentialsProfiles />
<properties>
<expanded>True</expanded>
<name>test_RDCMan_connections</name>
</properties>
<smartGroup>
<properties>
<expanded>False</expanded>
<name>AllServers</name>
</properties>
<ruleGroup operator="All">
<rule>
<property>DisplayName</property>
<operator>Matches</operator>
<value>server</value>
</rule>
</ruleGroup>
</smartGroup>
<group>
<properties>
<expanded>True</expanded>
<name>Group1</name>
</properties>
<server>
<properties>
<displayName></displayName>
<name></name>
<comment></comment>
</properties>
<logonCredentials inherit="None">
<profileName scope="Local"></profileName>
<userName></userName>
<password></password>
<domain></domain>
</logonCredentials>
<connectionSettings inherit="None">
<connectToConsole></connectToConsole>
<startProgram />
<workingDir />
<port></port>
<loadBalanceInfo />
</connectionSettings>
<gatewaySettings inherit="None">
<enabled></enabled>
<hostName></hostName>
<logonMethod></logonMethod>
<localBypass></localBypass>
<credSharing></credSharing>
<profileName scope="Local"></profileName>
<userName></userName>
<password />
<domain></domain>
</gatewaySettings>
<remoteDesktop inherit="None">
<sameSizeAsClientArea></sameSizeAsClientArea>
<fullScreen></fullScreen>
<colorDepth></colorDepth>
</remoteDesktop>
<localResources inherit="None">
<audioRedirection></audioRedirection>
<audioRedirectionQuality></audioRedirectionQuality>
<audioCaptureRedirection></audioCaptureRedirection>
<keyboardHook></keyboardHook>
<redirectClipboard></redirectClipboard>
<redirectDrives></redirectDrives>
<redirectDrivesList>
<item></item>
<item></item>
<item></item>
<item></item>
<item></item>
</redirectDrivesList>
<redirectPrinters></redirectPrinters>
<redirectPorts></redirectPorts>
<redirectSmartCards></redirectSmartCards>
<redirectPnpDevices></redirectPnpDevices>
</localResources>
<displaySettings inherit="None">
<thumbnailScale></thumbnailScale>
<smartSizeDockedWindows></smartSizeDockedWindows>
<smartSizeUndockedWindows></smartSizeUndockedWindows>
</displaySettings>
<securitySettings inherit="None">
<authentication></authentication>
</securitySettings>
</server>
</group>
</file>
<connected />
<favorites />
<recentlyUsed />
</RDCMan>

View File

@@ -1,4 +1,5 @@
using System.IO;
using mRemoteNG.Tools;
namespace mRemoteNGTests.TestHelpers
{
@@ -18,9 +19,17 @@ namespace mRemoteNGTests.TestHelpers
File.Delete(file);
}
public static string NewTempFilePath()
public static void DeleteDirectory(string directory)
{
if (Directory.Exists(directory))
Directory.Delete(directory, true);
}
public static string NewTempFilePath(string extension = "")
{
var newPath = Path.Combine(GetTestSpecificTempDirectory(), Path.GetRandomFileName());
if (!string.IsNullOrWhiteSpace(extension))
newPath = newPath + extension;
var folderPath = Path.GetDirectoryName(newPath);
if (!Directory.Exists(folderPath))
Directory.CreateDirectory(folderPath);
@@ -35,5 +44,15 @@ namespace mRemoteNGTests.TestHelpers
{
return Path.Combine(Path.GetTempPath(), "mRemoteNGTests", Path.GetRandomFileName());
}
public static DisposableAction DisposableTempFile(out string filePath, string extension = "")
{
var file = NewTempFilePath(extension);
filePath = file;
File.AppendAllText(file, "");
return new DisposableAction(
() => {},
() => DeleteDirectory(Path.GetDirectoryName(file)));
}
}
}

View File

@@ -266,6 +266,7 @@
<None Include="Resources\test_rdcman_v2_2_badschemaversion.rdg" />
<None Include="Resources\test_rdcman_v2_2_schema1.rdg" />
<None Include="Resources\test_RDCMan_v2_7_schema3.rdg" />
<None Include="Resources\test_rdcman_v2_7_schema3_null_values.rdg" />
<None Include="Resources\test_remotedesktopconnection.rdp" />
</ItemGroup>
<ItemGroup>

View File

@@ -13,7 +13,7 @@ using mRemoteNG.Tree.Root;
namespace mRemoteNG.Config.Serializers
{
public class RemoteDesktopConnectionManagerDeserializer : IDeserializer<string, ConnectionTreeModel>
public class RemoteDesktopConnectionManagerDeserializer : IDeserializer<string, ConnectionTreeModel>
{
private static int _schemaVersion; /* 1 = RDCMan v2.2
3 = RDCMan v2.7 */
@@ -129,11 +129,19 @@ namespace mRemoteNG.Config.Serializers
{
var connectionInfo = new ConnectionInfo {Protocol = ProtocolType.RDP};
var propertiesNode = xmlNode.SelectSingleNode("./properties");
if (_schemaVersion == 1) propertiesNode = xmlNode; // Version 2.2 defines the container name at the root instead
if (_schemaVersion == 1)
propertiesNode = xmlNode; // Version 2.2 defines the container name at the root instead
connectionInfo.Hostname = propertiesNode?.SelectSingleNode("./name")?.InnerText ?? "";
connectionInfo.Name = propertiesNode?.SelectSingleNode("./displayName")?.InnerText ?? connectionInfo.Hostname;
var connectionDisplayName = propertiesNode?.SelectSingleNode("./displayName")?.InnerText;
connectionInfo.Name = !string.IsNullOrWhiteSpace(connectionDisplayName)
? connectionDisplayName
: string.IsNullOrWhiteSpace(connectionInfo.Hostname)
? connectionInfo.Name
: connectionInfo.Hostname;
connectionInfo.Description = propertiesNode?.SelectSingleNode("./comment")?.InnerText ?? string.Empty;
var logonCredentialsNode = xmlNode.SelectSingleNode("./logonCredentials");
@@ -165,10 +173,12 @@ namespace mRemoteNG.Config.Serializers
var connectionSettingsNode = xmlNode.SelectSingleNode("./connectionSettings");
if (connectionSettingsNode?.Attributes?["inherit"]?.Value == "None")
{
connectionInfo.UseConsoleSession = bool.Parse(connectionSettingsNode.SelectSingleNode("./connectToConsole")?.InnerText ?? "false");
if (bool.TryParse(connectionSettingsNode.SelectSingleNode("./connectToConsole")?.InnerText, out var useConsole))
connectionInfo.UseConsoleSession = useConsole;
// ./startProgram
// ./workingDir
connectionInfo.Port = Convert.ToInt32(connectionSettingsNode.SelectSingleNode("./port")?.InnerText);
if (int.TryParse(connectionSettingsNode.SelectSingleNode("./port")?.InnerText, out var port))
connectionInfo.Port = port;
}
else
{
@@ -179,12 +189,16 @@ namespace mRemoteNG.Config.Serializers
var gatewaySettingsNode = xmlNode.SelectSingleNode("./gatewaySettings");
if (gatewaySettingsNode?.Attributes?["inherit"]?.Value == "None")
{
connectionInfo.RDGatewayUsageMethod = gatewaySettingsNode.SelectSingleNode("./enabled")?.InnerText == "True" ? RdpProtocol.RDGatewayUsageMethod.Always : RdpProtocol.RDGatewayUsageMethod.Never;
connectionInfo.RDGatewayUsageMethod = gatewaySettingsNode.SelectSingleNode("./enabled")?.InnerText == "True"
? RdpProtocol.RDGatewayUsageMethod.Always
: RdpProtocol.RDGatewayUsageMethod.Never;
connectionInfo.RDGatewayHostname = gatewaySettingsNode.SelectSingleNode("./hostName")?.InnerText;
connectionInfo.RDGatewayUsername = gatewaySettingsNode.SelectSingleNode("./userName")?.InnerText;
var passwordNode = gatewaySettingsNode.SelectSingleNode("./password");
connectionInfo.RDGatewayPassword = passwordNode?.Attributes?["storeAsClearText"]?.Value == "True" ? passwordNode.InnerText : DecryptRdcManPassword(passwordNode?.InnerText);
connectionInfo.RDGatewayPassword = passwordNode?.Attributes?["storeAsClearText"]?.Value == "True"
? passwordNode.InnerText
: DecryptRdcManPassword(passwordNode?.InnerText);
connectionInfo.RDGatewayDomain = gatewaySettingsNode.SelectSingleNode("./domain")?.InnerText;
// ./logonMethod
@@ -203,15 +217,10 @@ namespace mRemoteNG.Config.Serializers
var remoteDesktopNode = xmlNode.SelectSingleNode("./remoteDesktop");
if (remoteDesktopNode?.Attributes?["inherit"]?.Value == "None")
{
var resolutionString = remoteDesktopNode.SelectSingleNode("./size")?.InnerText.Replace(" ", "");
try
{
connectionInfo.Resolution = (RdpProtocol.RDPResolutions)Enum.Parse(typeof(RdpProtocol.RDPResolutions), "Res" + resolutionString);
}
catch (ArgumentException)
{
connectionInfo.Resolution = RdpProtocol.RDPResolutions.FitToWindow;
}
connectionInfo.Resolution =
Enum.TryParse<RdpProtocol.RDPResolutions>(remoteDesktopNode.SelectSingleNode("./size")?.InnerText.Replace(" ", ""), true, out var rdpResolution)
? rdpResolution
: RdpProtocol.RDPResolutions.FitToWindow;
if (remoteDesktopNode.SelectSingleNode("./sameSizeAsClientArea")?.InnerText == "True")
{
@@ -223,9 +232,8 @@ namespace mRemoteNG.Config.Serializers
connectionInfo.Resolution = RdpProtocol.RDPResolutions.Fullscreen;
}
var colorDepth = remoteDesktopNode.SelectSingleNode("./colorDepth")?.InnerText;
if (colorDepth != null)
connectionInfo.Colors = (RdpProtocol.RDPColors)Enum.Parse(typeof(RdpProtocol.RDPColors), colorDepth);
if (Enum.TryParse<RdpProtocol.RDPColors>(remoteDesktopNode.SelectSingleNode("./colorDepth")?.InnerText, true, out var rdpColors))
connectionInfo.Colors = rdpColors;
}
else
{
@@ -274,10 +282,17 @@ namespace mRemoteNG.Config.Serializers
}
// ./redirectClipboard
connectionInfo.RedirectDiskDrives = bool.Parse(localResourcesNode?.SelectSingleNode("./redirectDrives")?.InnerText ?? "false");
connectionInfo.RedirectPorts = bool.Parse(localResourcesNode?.SelectSingleNode("./redirectPorts")?.InnerText ?? "false");
connectionInfo.RedirectPrinters = bool.Parse(localResourcesNode?.SelectSingleNode("./redirectPrinters")?.InnerText ?? "false");
connectionInfo.RedirectSmartCards = bool.Parse(localResourcesNode?.SelectSingleNode("./redirectSmartCards")?.InnerText ?? "false");
if (bool.TryParse(localResourcesNode?.SelectSingleNode("./redirectDrives")?.InnerText, out var redirectDisks))
connectionInfo.RedirectDiskDrives = redirectDisks;
if (bool.TryParse(localResourcesNode?.SelectSingleNode("./redirectPorts")?.InnerText, out var redirectPorts))
connectionInfo.RedirectPorts = redirectPorts;
if (bool.TryParse(localResourcesNode?.SelectSingleNode("./redirectPrinters")?.InnerText, out var redirectPrinters))
connectionInfo.RedirectPrinters = redirectPrinters;
if (bool.TryParse(localResourcesNode?.SelectSingleNode("./redirectSmartCards")?.InnerText, out var redirectSmartCards))
connectionInfo.RedirectSmartCards = redirectSmartCards;
}
else
{