Merge branch 'develop' into improve_credential_manager

This commit is contained in:
David Sparer
2017-03-01 17:37:06 -07:00
17 changed files with 259 additions and 179 deletions

View File

@@ -6,15 +6,17 @@ Added more logging/notifications options
1.75 RC1 (2017-01-27):
1.75 (2017-03-01):
Known Issue:
------------
Portable build MD5 check will fail when updating from 1.75 Beta 1 to newer versions.
File hash check will fail when updating from 1.75 Beta 1 to newer versions.
Exception will be: "MD5 Hashes didn't match!" for 1.75 Beta 1 - 1.75 RC1
Features/Enhancements:
----------------------
#344 - Use SHA512 File Hashes to validate downloads (in the update mechanism & posted to the Downloads page)
Added Release Channels to the update check functionality allowing users to select one of 3 release channels for updates: Stable, Beta, Dev
#360: Help -> About, Version # is now selectable/copyable
#221: RDP: Optional disconnect after X number of minutes of inactivity

View File

@@ -18,7 +18,7 @@ Write-Host Version: $version
Write-Host dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/$tag/$filename
Write-Host clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/$tag/CHANGELOG.TXT
$hash = Get-FileHash -Algorithm MD5 $file | % { $_.Hash }
$hash = Get-FileHash -Algorithm SHA512 $file | % { $_.Hash }
Write-Host Checksum: $hash
@@ -38,5 +38,5 @@ Write-Host dURL: https://github.com/mRemoteNG/mRemoteNG/releases/download/$tag/$
Write-Host clURL: https://raw.githubusercontent.com/mRemoteNG/mRemoteNG/$tag/CHANGELOG.TXT
Write-Host CertificateThumbprint: 0CEA828E5C787EA8AA89268D83816C1EA03375BA
$hash = Get-FileHash -Algorithm MD5 $file | % { $_.Hash }
$hash = Get-FileHash -Algorithm SHA512 $file | % { $_.Hash }
Write-Host Checksum: $hash

View File

@@ -37,14 +37,14 @@ namespace mRemoteNGTests.Config.Serializers
[Test]
public void XDocumentHasXmlDeclaration()
{
var xdoc = _documentCompiler.CompileDocument(_connectionTreeModel, false, false);
var xdoc = _documentCompiler.CompileDocument(_connectionTreeModel, false);
Assert.That(xdoc.Declaration, Is.Not.Null);
}
[Test]
public void DocumentHasRootConnectionElement()
{
var xdoc =_documentCompiler.CompileDocument(_connectionTreeModel, false, false);
var xdoc =_documentCompiler.CompileDocument(_connectionTreeModel, false);
var rootElementName = xdoc.Root?.Name.LocalName;
Assert.That(rootElementName, Is.EqualTo("Connections"));
}
@@ -52,7 +52,7 @@ namespace mRemoteNGTests.Config.Serializers
[Test]
public void ConnectionNodesSerializedRecursively()
{
var xdoc = _documentCompiler.CompileDocument(_connectionTreeModel, false, false);
var xdoc = _documentCompiler.CompileDocument(_connectionTreeModel, false);
var con4 = xdoc.Root?.XPathSelectElement("Node[@Name='folder2']/Node[@Name='folder3']/Node[@Name='con4']");
Assert.That(con4, Is.Not.Null);
}
@@ -60,7 +60,7 @@ namespace mRemoteNGTests.Config.Serializers
[Test]
public void XmlContentEncryptedWhenFullFileEncryptionTurnedOn()
{
var xdoc = _documentCompiler.CompileDocument(_connectionTreeModel, true, false);
var xdoc = _documentCompiler.CompileDocument(_connectionTreeModel, true);
var rootElementValue = xdoc.Root?.Value;
Assert.That(rootElementValue, Is.Not.EqualTo(string.Empty));
}

View File

@@ -22,7 +22,7 @@ namespace mRemoteNGTests.Config.Serializers
var connectionTreeModel = SetupConnectionTreeModel();
var cryptoProvider = new CryptographyProviderFactory().CreateAeadCryptographyProvider(BlockCipherEngines.AES, BlockCipherModes.GCM);
var connectionNodeSerializer = new XmlConnectionNodeSerializer27(cryptoProvider, connectionTreeModel.RootNodes.OfType<RootNodeInfo>().First().PasswordString.ConvertToSecureString());
_originalDocument = new XmlConnectionsDocumentCompiler(cryptoProvider, connectionNodeSerializer).CompileDocument(connectionTreeModel, false, false);
_originalDocument = new XmlConnectionsDocumentCompiler(cryptoProvider, connectionNodeSerializer).CompileDocument(connectionTreeModel, false);
_documentEncryptor = new XmlConnectionsDocumentEncryptor(cryptoProvider);
}

View File

@@ -39,15 +39,6 @@ namespace mRemoteNGTests.Config.Serializers
Assert.That(attributeValue, Is.EqualTo("Connections"));
}
[TestCase(true)]
[TestCase(false)]
public void ExportValueSerialized(bool export)
{
var element = _rootNodeSerializer.SerializeRootNodeInfo(_rootNodeInfo, _cryptographyProvider, export:export);
var attributeValue = element.Attribute(XName.Get("Export"))?.Value;
Assert.That(attributeValue, Is.EqualTo(export.ToString()));
}
[TestCaseSource(typeof(TestCaseSources), nameof(TestCaseSources.AllEngineAndModeCombos))]
public void EncryptionEngineSerialized(BlockCipherEngines engine, BlockCipherModes mode)
{
@@ -100,23 +91,13 @@ namespace mRemoteNGTests.Config.Serializers
Assert.That(attributeValuePlainText, Is.EqualTo(expectedPlainText));
}
[TestCase("", "ThisIsNotProtected")]
[TestCase("customPassword1", "ThisIsNotProtected")]
public void EncryptWithDefaultPasswordWhenExporting(string customPassword, string expectedPlainText)
{
_rootNodeInfo.PasswordString = customPassword;
var element = _rootNodeSerializer.SerializeRootNodeInfo(_rootNodeInfo, _cryptographyProvider, export:true);
var attributeValue = element.Attribute(XName.Get("Protected"))?.Value;
var attributeValuePlainText = _cryptographyProvider.Decrypt(attributeValue, _rootNodeInfo.DefaultPassword.ConvertToSecureString());
Assert.That(attributeValuePlainText, Is.EqualTo(expectedPlainText));
}
[Test]
public void ConfVersionSerialized()
{
var element = _rootNodeSerializer.SerializeRootNodeInfo(_rootNodeInfo, _cryptographyProvider);
var attributeValue = element.Attribute(XName.Get("ConfVersion"))?.Value;
Assert.That(attributeValue, Is.EqualTo("2.7"));
var attributeValue = element.Attribute(XName.Get("ConfVersion"))?.Value ?? "";
var versionAsNumber = double.Parse(attributeValue);
Assert.That(versionAsNumber, Is.GreaterThan(0));
}
private class TestCaseSources

View File

@@ -1,6 +1,5 @@
using System;
using System.Linq;
using System.Security;
using System.Windows.Forms;
using mRemoteNG.Config.Connections;
using mRemoteNG.Config.DataProviders;
@@ -79,12 +78,16 @@ namespace mRemoteNG.App
cryptographyProvider.KeyDerivationIterations = Settings.Default.EncryptionKeyDerivationIterations;
var rootNode = exportTarget.GetRootParent() as RootNodeInfo;
var connectionNodeSerializer = new XmlConnectionNodeSerializer27(cryptographyProvider, rootNode?.PasswordString.ConvertToSecureString() ?? new RootNodeInfo(RootNodeType.Connection).PasswordString.ConvertToSecureString());
serializer = new XmlConnectionsSerializer(cryptographyProvider, connectionNodeSerializer);
((XmlConnectionsSerializer) serializer).SaveFilter = saveFilter;
serializer = new XmlConnectionsSerializer(cryptographyProvider, connectionNodeSerializer)
{
SaveFilter = saveFilter
};
break;
case ConnectionsSaver.Format.mRCSV:
serializer = new CsvConnectionsSerializerMremotengFormat();
((CsvConnectionsSerializerMremotengFormat)serializer).SaveFilter = saveFilter;
serializer = new CsvConnectionsSerializerMremotengFormat
{
SaveFilter = saveFilter
};
break;
default:
throw new ArgumentOutOfRangeException(nameof(saveFormat), saveFormat, null);

View File

@@ -453,7 +453,6 @@ namespace mRemoteNG.App
if (!Settings.Default.UseSQLServer)
connectionsSaver.ConnectionFileName = GetStartupConnectionFileName();
connectionsSaver.Export = false;
connectionsSaver.SaveFilter = new SaveFilter();
connectionsSaver.ConnectionTreeModel = ConnectionTreeModel;
@@ -507,7 +506,6 @@ namespace mRemoteNG.App
connectionsSave.SaveFormat = ConnectionsSaver.Format.mRXML;
connectionsSave.ConnectionFileName = saveFileDialog.FileName;
connectionsSave.Export = false;
connectionsSave.SaveFilter = new SaveFilter();
connectionsSave.ConnectionTreeModel = ConnectionTreeModel;

View File

@@ -276,14 +276,14 @@ namespace mRemoteNG.App.Update
}
#endif
using (var md5 = MD5.Create())
using (var cksum = SHA512.Create())
{
using (var stream = File.OpenRead(CurrentUpdateInfo.UpdateFilePath))
{
var hash = md5.ComputeHash(stream);
var hash = cksum.ComputeHash(stream);
var hashString = BitConverter.ToString(hash).Replace("-", "").ToUpperInvariant();
if (!hashString.Equals(CurrentUpdateInfo.Checksum))
throw new Exception("MD5 Hashes didn't match!");
throw new Exception("SHA512 Hashes didn't match!");
}
}
}

View File

@@ -50,7 +50,6 @@ namespace mRemoteNG.Config.Connections
public string ConnectionFileName {get; set;}
public TreeNode RootTreeNode {get; set;}
public bool Export {get; set;}
public Format SaveFormat {get; set;}
public SaveFilter SaveFilter {get; set;}
public ConnectionTreeModel ConnectionTreeModel { get; set; }
@@ -72,8 +71,7 @@ namespace mRemoteNG.Config.Connections
break;
default:
SaveToXml();
if (!Export)
FrmMain.Default.ConnectionsFileName = ConnectionFileName;
FrmMain.Default.ConnectionsFileName = ConnectionFileName;
break;
}
FrmMain.Default.AreWeUsingSqlServerForSavingConnections = SaveFormat == Format.SQL;
@@ -248,7 +246,6 @@ namespace mRemoteNG.Config.Connections
var connectionNodeSerializer = new XmlConnectionNodeSerializer27(cryptographyProvider, ConnectionTreeModel.RootNodes.OfType<RootNodeInfo>().First().PasswordString.ConvertToSecureString());
var xmlConnectionsSerializer = new XmlConnectionsSerializer(cryptographyProvider, connectionNodeSerializer)
{
Export = Export,
SaveFilter = SaveFilter,
UseFullEncryption = mRemoteNG.Settings.Default.EncryptCompleteConnectionsFile
};

View File

@@ -31,7 +31,7 @@ namespace mRemoteNG.Config.Serializers
private XmlConnectionsDecryptor _decryptor;
//TODO find way to inject data source info
private string ConnectionFileName = "";
private const double MaxSupportedConfVersion = 2.7;
private const double MaxSupportedConfVersion = 2.8;
private readonly RootNodeInfo _rootNodeInfo = new RootNodeInfo(RootNodeType.Connection);
private readonly IEnumerable<ICredentialRecord> _credentialRecords;
@@ -123,12 +123,6 @@ namespace mRemoteNG.Config.Serializers
}
}
if (import && !IsExportFile(rootXmlElement))
{
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, Language.strCannotImportNormalSessionFile);
return null;
}
AddNodesFromXmlRecursive(_xmlDocument.DocumentElement, _rootNodeInfo);
if (!import)
@@ -529,14 +523,5 @@ namespace mRemoteNG.Config.Serializers
}
return connectionInfo;
}
private bool IsExportFile(XmlElement rootConnectionsNode)
{
var isExportFile = false;
if (_confVersion < 1.0) return false;
if (Convert.ToBoolean(rootConnectionsNode.Attributes["Export"].Value))
isExportFile = true;
return isExportFile;
}
}
}

View File

@@ -22,17 +22,17 @@ namespace mRemoteNG.Config.Serializers
_connectionNodeSerializer = connectionNodeSerializer;
}
public XDocument CompileDocument(ConnectionTreeModel connectionTreeModel, bool fullFileEncryption, bool export)
public XDocument CompileDocument(ConnectionTreeModel connectionTreeModel, bool fullFileEncryption)
{
var rootNodeInfo = GetRootNodeFromConnectionTreeModel(connectionTreeModel);
return CompileDocument(rootNodeInfo, fullFileEncryption, export);
return CompileDocument(rootNodeInfo, fullFileEncryption);
}
public XDocument CompileDocument(ConnectionInfo serializationTarget, bool fullFileEncryption, bool export)
public XDocument CompileDocument(ConnectionInfo serializationTarget, bool fullFileEncryption)
{
var rootNodeInfo = GetRootNodeFromConnectionInfo(serializationTarget);
_encryptionKey = rootNodeInfo.PasswordString.ConvertToSecureString();
var rootElement = CompileRootNode(rootNodeInfo, fullFileEncryption, export);
var rootElement = CompileRootNode(rootNodeInfo, fullFileEncryption);
CompileRecursive(serializationTarget, rootElement);
var xmlDeclaration = new XDeclaration("1.0", "utf-8", null);
@@ -71,10 +71,10 @@ namespace mRemoteNG.Config.Serializers
}
}
private XElement CompileRootNode(RootNodeInfo rootNodeInfo, bool fullFileEncryption, bool export)
private XElement CompileRootNode(RootNodeInfo rootNodeInfo, bool fullFileEncryption)
{
var rootNodeSerializer = new XmlRootNodeSerializer();
return rootNodeSerializer.SerializeRootNodeInfo(rootNodeInfo, _cryptographyProvider, fullFileEncryption, export);
return rootNodeSerializer.SerializeRootNodeInfo(rootNodeInfo, _cryptographyProvider, fullFileEncryption);
}
private XElement CompileConnectionInfoNode(ConnectionInfo connectionInfo)

View File

@@ -17,7 +17,6 @@ namespace mRemoteNG.Config.Serializers
private readonly ICryptographyProvider _cryptographyProvider;
private readonly ISerializer<ConnectionInfo, XElement> _connectionNodeSerializer;
public bool Export { get; set; }
public SaveFilter SaveFilter { get; set; } = new SaveFilter();
public bool UseFullEncryption { get; set; }
@@ -44,7 +43,7 @@ namespace mRemoteNG.Config.Serializers
try
{
var documentCompiler = new XmlConnectionsDocumentCompiler(_cryptographyProvider, _connectionNodeSerializer);
var xmlDocument = documentCompiler.CompileDocument(serializationTarget, UseFullEncryption, Export);
var xmlDocument = documentCompiler.CompileDocument(serializationTarget, UseFullEncryption);
xml = WriteXmlToString(xmlDocument);
}
catch (Exception ex)

View File

@@ -7,27 +7,24 @@ namespace mRemoteNG.Config.Serializers
{
public class XmlRootNodeSerializer
{
public XElement SerializeRootNodeInfo(RootNodeInfo rootNodeInfo, ICryptographyProvider cryptographyProvider, bool fullFileEncryption = false, bool export = false)
public XElement SerializeRootNodeInfo(RootNodeInfo rootNodeInfo, ICryptographyProvider cryptographyProvider, bool fullFileEncryption = false)
{
var element = new XElement("Connections");
element.Add(new XAttribute(XName.Get("Name"), rootNodeInfo.Name));
element.Add(new XAttribute(XName.Get("Export"), export.ToString()));
element.Add(new XAttribute(XName.Get("EncryptionEngine"), cryptographyProvider.CipherEngine));
element.Add(new XAttribute(XName.Get("BlockCipherMode"), cryptographyProvider.CipherMode));
element.Add(new XAttribute(XName.Get("KdfIterations"), cryptographyProvider.KeyDerivationIterations));
element.Add(new XAttribute(XName.Get("FullFileEncryption"), fullFileEncryption.ToString()));
element.Add(CreateProtectedAttribute(rootNodeInfo, cryptographyProvider, export));
element.Add(new XAttribute(XName.Get("ConfVersion"), "2.7"));
element.Add(CreateProtectedAttribute(rootNodeInfo, cryptographyProvider));
element.Add(new XAttribute(XName.Get("ConfVersion"), "2.8"));
return element;
}
private XAttribute CreateProtectedAttribute(RootNodeInfo rootNodeInfo, ICryptographyProvider cryptographyProvider, bool export)
private XAttribute CreateProtectedAttribute(RootNodeInfo rootNodeInfo, ICryptographyProvider cryptographyProvider)
{
var attribute = new XAttribute(XName.Get("Protected"), "");
var plainText = rootNodeInfo.Password && !export ? "ThisIsProtected" : "ThisIsNotProtected";
var encryptionPassword = export
? rootNodeInfo.DefaultPassword.ConvertToSecureString()
: rootNodeInfo.PasswordString.ConvertToSecureString();
var plainText = rootNodeInfo.Password ? "ThisIsProtected" : "ThisIsNotProtected";
var encryptionPassword = rootNodeInfo.PasswordString.ConvertToSecureString();
attribute.Value = cryptographyProvider.Encrypt(plainText, encryptionPassword);
return attribute;
}

View File

@@ -0,0 +1,141 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="mremoteng_confcons_v2_8"
targetNamespace="http://mremoteng.org"
elementFormDefault="qualified"
xmlns="http://mremoteng.org"
xmlns:mrng="http://mremoteng.org"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
<xs:element name="Connections">
<xs:complexType>
<xs:sequence>
<xs:element name="Node" type="mrng:connectioninfo" />
</xs:sequence>
<xs:attribute name="Name" type="xs:string" use="required" />
<xs:attribute name="EncryptionEngine" type="xs:string" use="required" />
<xs:attribute name="BlockCipherMode" type="xs:string" use="required" />
<xs:attribute name="KdfIterations" type="xs:int" use="optional" />
<xs:attribute name="FullFileEncryption" type="xs:boolean" use="required" />
<xs:attribute name="Protected" type="xs:string" use="required" />
<xs:attribute name="ConfVersion" type="xs:float" use="required" />
</xs:complexType>
</xs:element>
<xs:complexType name="connectioninfo">
<xs:sequence minOccurs="0" maxOccurs="unbounded">
<xs:element name="Node" type="mrng:connectioninfo" />
</xs:sequence>
<xs:attribute name="Name" type="xs:string" use="required" />
<xs:attribute name="Type" type="xs:string" use="required" />
<xs:attribute name="Descr" type="xs:string" use="required" />
<xs:attribute name="Icon" type="xs:string" use="required" />
<xs:attribute name="Panel" type="xs:string" use="required" />
<xs:attribute name="CredentialId" type="xs:string" use="required" />
<xs:attribute name="Hostname" type="xs:string" use="required" />
<xs:attribute name="Protocol" type="xs:string" use="required" />
<xs:attribute name="PuttySession" type="xs:string" use="required" />
<xs:attribute name="Port" type="xs:int" use="required" />
<xs:attribute name="ConnectToConsole" type="xs:boolean" use="required" />
<xs:attribute name="UseCredSsp" type="xs:boolean" use="required" />
<xs:attribute name="RenderingEngine" type="xs:string" use="required" />
<xs:attribute name="ICAEncryptionStrength" type="xs:string" use="required" />
<xs:attribute name="RDPAuthenticationLevel" type="xs:string" use="required" />
<xs:attribute name="RDPMinutesToIdleTimeout" type="xs:int" use="required" />
<xs:attribute name="LoadBalanceInfo" type="xs:string" use="required" />
<xs:attribute name="Colors" type="xs:string" use="required" />
<xs:attribute name="Resolution" type="xs:string" use="required" />
<xs:attribute name="AutomaticResize" type="xs:boolean" use="required" />
<xs:attribute name="DisplayWallpaper" type="xs:boolean" use="required" />
<xs:attribute name="DisplayThemes" type="xs:boolean" use="required" />
<xs:attribute name="EnableFontSmoothing" type="xs:boolean" use="required" />
<xs:attribute name="EnableDesktopComposition" type="xs:boolean" use="required" />
<xs:attribute name="CacheBitmaps" type="xs:boolean" use="required" />
<xs:attribute name="RedirectDiskDrives" type="xs:boolean" use="required" />
<xs:attribute name="RedirectPorts" type="xs:boolean" use="required" />
<xs:attribute name="RedirectPrinters" type="xs:boolean" use="required" />
<xs:attribute name="RedirectSmartCards" type="xs:boolean" use="required" />
<xs:attribute name="RedirectSound" type="xs:string" use="required" />
<xs:attribute name="SoundQuality" type="xs:string" use="required" />
<xs:attribute name="RedirectKeys" type="xs:boolean" use="required" />
<xs:attribute name="Connected" type="xs:boolean" use="required" />
<xs:attribute name="PreExtApp" type="xs:string" use="required" />
<xs:attribute name="PostExtApp" type="xs:string" use="required" />
<xs:attribute name="MacAddress" type="xs:string" use="required" />
<xs:attribute name="UserField" type="xs:string" use="required" />
<xs:attribute name="ExtApp" type="xs:string" use="required" />
<xs:attribute name="VNCCompression" type="xs:string" use="required" />
<xs:attribute name="VNCEncoding" type="xs:string" use="required" />
<xs:attribute name="VNCAuthMode" type="xs:string" use="required" />
<xs:attribute name="VNCProxyType" type="xs:string" use="required" />
<xs:attribute name="VNCProxyIP" type="xs:string" use="required" />
<xs:attribute name="VNCProxyPort" type="xs:int" use="required" />
<xs:attribute name="VNCProxyUsername" type="xs:string" use="required" />
<xs:attribute name="VNCProxyPassword" type="xs:string" use="required" />
<xs:attribute name="VNCColors" type="xs:string" use="required" />
<xs:attribute name="VNCSmartSizeMode" type="xs:string" use="required" />
<xs:attribute name="VNCViewOnly" type="xs:boolean" use="required" />
<xs:attribute name="RDGatewayUsageMethod" type="xs:string" use="required" />
<xs:attribute name="RDGatewayHostname" type="xs:string" use="required" />
<xs:attribute name="RDGatewayUseConnectionCredentials" type="xs:string" use="required" />
<xs:attribute name="RDGatewayUsername" type="xs:string" use="required" />
<xs:attribute name="RDGatewayPassword" type="xs:string" use="required" />
<xs:attribute name="RDGatewayDomain" type="xs:string" use="required" />
<xs:attribute name="InheritCredentialRecord" type="xs:boolean" use="optional" />
<xs:attribute name="InheritCacheBitmaps" type="xs:boolean" use="optional" />
<xs:attribute name="InheritColors" type="xs:boolean" use="optional" />
<xs:attribute name="InheritDescription" type="xs:boolean" use="optional" />
<xs:attribute name="InheritDisplayThemes" type="xs:boolean" use="optional" />
<xs:attribute name="InheritDisplayWallpaper" type="xs:boolean" use="optional" />
<xs:attribute name="InheritEnableFontSmoothing" type="xs:boolean" use="optional" />
<xs:attribute name="InheritEnableDesktopComposition" type="xs:boolean" use="optional" />
<xs:attribute name="InheritDomain" type="xs:boolean" use="optional" />
<xs:attribute name="InheritIcon" type="xs:boolean" use="optional" />
<xs:attribute name="InheritPanel" type="xs:boolean" use="optional" />
<xs:attribute name="InheritPassword" type="xs:boolean" use="optional" />
<xs:attribute name="InheritPort" type="xs:boolean" use="optional" />
<xs:attribute name="InheritProtocol" type="xs:boolean" use="optional" />
<xs:attribute name="InheritPuttySession" type="xs:boolean" use="optional" />
<xs:attribute name="InheritRedirectDiskDrives" type="xs:boolean" use="optional" />
<xs:attribute name="InheritRedirectKeys" type="xs:boolean" use="optional" />
<xs:attribute name="InheritRedirectPorts" type="xs:boolean" use="optional" />
<xs:attribute name="InheritRedirectPrinters" type="xs:boolean" use="optional" />
<xs:attribute name="InheritRedirectSmartCards" type="xs:boolean" use="optional" />
<xs:attribute name="InheritRedirectSound" type="xs:boolean" use="optional" />
<xs:attribute name="InheritSoundQuality" type="xs:boolean" use="optional" />
<xs:attribute name="InheritResolution" type="xs:boolean" use="optional" />
<xs:attribute name="InheritAutomaticResize" type="xs:boolean" use="optional" />
<xs:attribute name="InheritUseConsoleSession" type="xs:boolean" use="optional" />
<xs:attribute name="InheritUseCredSsp" type="xs:boolean" use="optional" />
<xs:attribute name="InheritRenderingEngine" type="xs:boolean" use="optional" />
<xs:attribute name="InheritUsername" type="xs:boolean" use="optional" />
<xs:attribute name="InheritICAEncryptionStrength" type="xs:boolean" use="optional" />
<xs:attribute name="InheritRDPAuthenticationLevel" type="xs:boolean" use="optional" />
<xs:attribute name="InheritRDPMinutesToIdleTimeout" type="xs:boolean" use="optional" />
<xs:attribute name="InheritLoadBalanceInfo" type="xs:boolean" use="optional" />
<xs:attribute name="InheritPreExtApp" type="xs:boolean" use="optional" />
<xs:attribute name="InheritPostExtApp" type="xs:boolean" use="optional" />
<xs:attribute name="InheritMacAddress" type="xs:boolean" use="optional" />
<xs:attribute name="InheritUserField" type="xs:boolean" use="optional" />
<xs:attribute name="InheritExtApp" type="xs:boolean" use="optional" />
<xs:attribute name="InheritVNCCompression" type="xs:boolean" use="optional" />
<xs:attribute name="InheritVNCEncoding" type="xs:boolean" use="optional" />
<xs:attribute name="InheritVNCAuthMode" type="xs:boolean" use="optional" />
<xs:attribute name="InheritVNCProxyType" type="xs:boolean" use="optional" />
<xs:attribute name="InheritVNCProxyIP" type="xs:boolean" use="optional" />
<xs:attribute name="InheritVNCProxyPort" type="xs:boolean" use="optional" />
<xs:attribute name="InheritVNCProxyUsername" type="xs:boolean" use="optional" />
<xs:attribute name="InheritVNCProxyPassword" type="xs:boolean" use="optional" />
<xs:attribute name="InheritVNCColors" type="xs:boolean" use="optional" />
<xs:attribute name="InheritVNCSmartSizeMode" type="xs:boolean" use="optional" />
<xs:attribute name="InheritVNCViewOnly" type="xs:boolean" use="optional" />
<xs:attribute name="InheritRDGatewayUsageMethod" type="xs:boolean" use="optional" />
<xs:attribute name="InheritRDGatewayHostname" type="xs:boolean" use="optional" />
<xs:attribute name="InheritRDGatewayUseConnectionCredentials" type="xs:boolean" use="optional" />
<xs:attribute name="InheritRDGatewayUsername" type="xs:boolean" use="optional" />
<xs:attribute name="InheritRDGatewayPassword" type="xs:boolean" use="optional" />
<xs:attribute name="InheritRDGatewayDomain" type="xs:boolean" use="optional" />
</xs:complexType>
</xs:schema>

View File

@@ -99,8 +99,8 @@ namespace mRemoteNG.UI.Controls
container.IsExpanded = true;
};
SelectionChanged += tvConnections_AfterSelect;
CellClick += tvConnections_NodeMouseSingleClick;
CellClick += tvConnections_NodeMouseDoubleClick;
MouseDoubleClick += OnMouse_DoubleClick;
MouseClick += OnMouse_SingleClick;
CellToolTipShowing += tvConnections_CellToolTipShowing;
ModelCanDrop += _dragAndDropHandler.HandleEvent_ModelCanDrop;
ModelDropped += _dragAndDropHandler.HandleEvent_ModelDropped;
@@ -249,22 +249,26 @@ namespace mRemoteNG.UI.Controls
}
}
private void tvConnections_NodeMouseSingleClick(object sender, CellClickEventArgs e)
private void OnMouse_DoubleClick(object sender, MouseEventArgs mouseEventArgs)
{
if (e.ClickCount > 1) return;
var clickedNode = e.Model as ConnectionInfo;
if (clickedNode == null) return;
SingleClickHandler.Execute(clickedNode);
}
private void tvConnections_NodeMouseDoubleClick(object sender, CellClickEventArgs e)
{
if (e.ClickCount < 2) return;
var clickedNode = e.Model as ConnectionInfo;
if (mouseEventArgs.Clicks < 2) return;
OLVColumn column;
var listItem = GetItemAt(mouseEventArgs.X, mouseEventArgs.Y, out column);
var clickedNode = listItem.RowObject as ConnectionInfo;
if (clickedNode == null) return;
DoubleClickHandler.Execute(clickedNode);
}
private void OnMouse_SingleClick(object sender, MouseEventArgs mouseEventArgs)
{
if (mouseEventArgs.Clicks > 1) return;
OLVColumn column;
var listItem = GetItemAt(mouseEventArgs.X, mouseEventArgs.Y, out column);
var clickedNode = listItem?.RowObject as ConnectionInfo;
if (clickedNode == null) return;
SingleClickHandler.Execute(clickedNode);
}
private void tvConnections_CellToolTipShowing(object sender, ToolTipShowingEventArgs e)
{
try

View File

@@ -213,12 +213,10 @@ namespace mRemoteNG.UI.Window
set
{
_btnShowProperties.Checked = value;
if (value)
{
_btnShowInheritance.Checked = false;
_btnShowDefaultInheritance.Checked = false;
_btnShowDefaultProperties.Checked = false;
}
if (!value) return;
_btnShowInheritance.Checked = false;
_btnShowDefaultInheritance.Checked = false;
_btnShowDefaultProperties.Checked = false;
}
}
@@ -231,12 +229,10 @@ namespace mRemoteNG.UI.Window
set
{
_btnShowInheritance.Checked = value;
if (value)
{
_btnShowProperties.Checked = false;
_btnShowDefaultInheritance.Checked = false;
_btnShowDefaultProperties.Checked = false;
}
if (!value) return;
_btnShowProperties.Checked = false;
_btnShowDefaultInheritance.Checked = false;
_btnShowDefaultProperties.Checked = false;
}
}
@@ -249,12 +245,10 @@ namespace mRemoteNG.UI.Window
set
{
_btnShowDefaultProperties.Checked = value;
if (value)
{
_btnShowProperties.Checked = false;
_btnShowDefaultInheritance.Checked = false;
_btnShowInheritance.Checked = false;
}
if (!value) return;
_btnShowProperties.Checked = false;
_btnShowDefaultInheritance.Checked = false;
_btnShowInheritance.Checked = false;
}
}
@@ -264,12 +258,10 @@ namespace mRemoteNG.UI.Window
set
{
_btnShowDefaultInheritance.Checked = value;
if (value)
{
_btnShowProperties.Checked = false;
_btnShowDefaultProperties.Checked = false;
_btnShowInheritance.Checked = false;
}
if (!value) return;
_btnShowProperties.Checked = false;
_btnShowDefaultProperties.Checked = false;
_btnShowInheritance.Checked = false;
}
}
#endregion
@@ -292,7 +284,7 @@ namespace mRemoteNG.UI.Window
protected override bool ProcessCmdKey(ref System.Windows.Forms.Message msg, Keys keyData)
{
// Main form handle command key events
// Main form handle command key events
// Adapted from http://kiwigis.blogspot.com/2009/05/adding-tab-key-support-to-propertygrid.html
if ((keyData & Keys.KeyCode) == Keys.Tab)
{
@@ -311,19 +303,23 @@ namespace mRemoteNG.UI.Window
var newItem = selectedItem;
if (keyData == (Keys.Tab | Keys.Shift))
newItem = FindPreviousGridItemProperty(gridItems, selectedItem);
else if (keyData == Keys.Tab)
newItem = FindNextGridItemProperty(gridItems, selectedItem);
// ReSharper disable once SwitchStatementMissingSomeCases
switch (keyData)
{
case (Keys.Tab | Keys.Shift):
newItem = FindPreviousGridItemProperty(gridItems, selectedItem);
break;
case Keys.Tab:
newItem = FindNextGridItemProperty(gridItems, selectedItem);
break;
}
_pGrid.SelectedGridItem = newItem;
return true; // Handled
}
else
{
return base.ProcessCmdKey(ref msg, keyData);
}
return base.ProcessCmdKey(ref msg, keyData);
}
private void FindChildGridItems(GridItem item, ref List<GridItem> gridItems)
@@ -378,9 +374,7 @@ namespace mRemoteNG.UI.Window
break;
}
if (!previousIndexValid)
return null;
return gridItems[previousIndex];
return !previousIndexValid ? null : gridItems[previousIndex];
}
private GridItem FindNextGridItemProperty(IList<GridItem> gridItems, GridItem startItem)
@@ -402,12 +396,10 @@ namespace mRemoteNG.UI.Window
var nextIndexValid = false;
for (var index = startIndex; index <= gridItems.Count - 1; index++)
{
if (gridItems[index].GridItemType == GridItemType.Property)
{
nextIndex = index;
nextIndexValid = true;
break;
}
if (gridItems[index].GridItemType != GridItemType.Property) continue;
nextIndex = index;
nextIndexValid = true;
break;
}
if (nextIndexValid)
@@ -415,17 +407,13 @@ namespace mRemoteNG.UI.Window
for (var index = 0; index <= startIndex - 1; index++)
{
if (gridItems[index].GridItemType == GridItemType.Property)
{
nextIndex = index;
nextIndexValid = true;
break;
}
if (gridItems[index].GridItemType != GridItemType.Property) continue;
nextIndex = index;
nextIndexValid = true;
break;
}
if (!nextIndexValid)
return null;
return gridItems[nextIndex];
return !nextIndexValid ? null : gridItems[nextIndex];
}
public void SetPropertyGridObject(object propertyGridObject)
@@ -450,6 +438,7 @@ namespace mRemoteNG.UI.Window
var gridObjectAsRootNodeInfo = propertyGridObject as RootNodeInfo;
if (gridObjectAsRootNodeInfo != null) // ROOT
{
// ReSharper disable once SwitchStatementMissingSomeCases
switch (gridObjectAsRootNodeInfo.Type)
{
case RootNodeType.Connection:
@@ -649,11 +638,9 @@ namespace mRemoteNG.UI.Window
foreach (Control control in _pGrid.Controls)
{
toolStrip = control as ToolStrip;
if (toolStrip != null)
{
propertyGridToolStrip = toolStrip;
break;
}
if (toolStrip == null) continue;
propertyGridToolStrip = toolStrip;
break;
}
if (toolStrip == null)
@@ -673,11 +660,9 @@ namespace mRemoteNG.UI.Window
propertyGridToolStrip.Items[_originalPropertyGridToolStripItemCount - 1].Visible = false;
var expectedToolStripItemCount = _originalPropertyGridToolStripItemCount + customToolStrip.Items.Count;
if (propertyGridToolStrip.Items.Count != expectedToolStripItemCount)
{
propertyGridToolStrip.AllowMerge = true;
ToolStripManager.Merge(customToolStrip, propertyGridToolStrip);
}
if (propertyGridToolStrip.Items.Count == expectedToolStripItemCount) return;
propertyGridToolStrip.AllowMerge = true;
ToolStripManager.Merge(customToolStrip, propertyGridToolStrip);
}
catch (Exception ex)
{
@@ -745,7 +730,7 @@ namespace mRemoteNG.UI.Window
}
if (selectedGridObject is DefaultConnectionInfo)
DefaultConnectionInfo.Instance.SaveTo(Settings.Default, (a)=>"ConDefault"+a);
DefaultConnectionInfo.Instance.SaveTo(Settings.Default, a=>"ConDefault"+a);
}
private void UpdateRootInfoNode(PropertyValueChangedEventArgs e)
@@ -753,6 +738,7 @@ namespace mRemoteNG.UI.Window
var rootInfo = _pGrid.SelectedObject as RootNodeInfo;
if (rootInfo == null) return;
if (e.ChangedItem.PropertyDescriptor == null) return;
// ReSharper disable once SwitchStatementMissingSomeCases
switch (e.ChangedItem.PropertyDescriptor.Name)
{
case "Password":
@@ -779,7 +765,7 @@ namespace mRemoteNG.UI.Window
private void UpdateInheritanceNode()
{
if (!(_pGrid.SelectedObject is DefaultConnectionInheritance)) return;
DefaultConnectionInheritance.Instance.SaveTo(Settings.Default, (a)=>"InhDefault"+a);
DefaultConnectionInheritance.Instance.SaveTo(Settings.Default, a=>"InhDefault"+a);
}
private void pGrid_PropertySortChanged(object sender, EventArgs e)
@@ -860,6 +846,7 @@ namespace mRemoteNG.UI.Window
else if (_pGrid.SelectedObject is ConnectionInfo)
{
var conI = (ConnectionInfo)_pGrid.SelectedObject;
// ReSharper disable once SwitchStatementMissingSomeCases
switch (conI.Protocol)
{
case ProtocolType.RDP:
@@ -1585,24 +1572,15 @@ namespace mRemoteNG.UI.Window
try
{
var connectionInfo = (ConnectionInfo)_pGrid.SelectedObject;
if (connectionInfo == null)
{
return;
}
if (connectionInfo == null) return;
var selectedMenuItem = (ToolStripMenuItem)sender;
var iconName = selectedMenuItem?.Text;
if (string.IsNullOrEmpty(iconName))
{
return;
}
if (string.IsNullOrEmpty(iconName)) return;
var connectionIcon = ConnectionIcon.FromString(iconName);
if (connectionIcon == null)
{
return;
}
if (connectionIcon == null) return;
_btnIcon.Image = connectionIcon.ToBitmap();
@@ -1675,17 +1653,9 @@ namespace mRemoteNG.UI.Window
_btnHostStatus.Image = Resources.HostStatus_Check;
// To check status, ConnectionInfo must be an mRemoteNG.Connection.Info that is not a container
var info = connectionInfo as ConnectionInfo;
if (info != null)
{
if (info.IsContainer)
{
return;
}
}
else
{
return;
}
if (info == null) return;
if (info.IsContainer) return;
_btnHostStatus.Tag = "checking";
_hostName = ((ConnectionInfo)connectionInfo).Hostname;
@@ -1712,7 +1682,7 @@ namespace mRemoteNG.UI.Window
}
catch (Exception ex)
{
Runtime.MessageCollector.AddExceptionMessage("UI.Window.Config.propertyGridContextMenu_Opening() failed.", ex, MessageClass.ErrorMsg, true);
Runtime.MessageCollector.AddExceptionMessage("UI.Window.Config.propertyGridContextMenu_Opening() failed.", ex);
}
}
@@ -1728,7 +1698,7 @@ namespace mRemoteNG.UI.Window
}
catch (Exception ex)
{
Runtime.MessageCollector.AddExceptionMessage("UI.Window.Config.propertyGridContextMenuReset_Click() failed.", ex, MessageClass.ErrorMsg, true);
Runtime.MessageCollector.AddExceptionMessage("UI.Window.Config.propertyGridContextMenuReset_Click() failed.", ex);
}
}

View File

@@ -897,6 +897,9 @@
<None Include="Schemas\mremoteng_confcons_v2_5.xsd">
<SubType>Designer</SubType>
</None>
<None Include="Schemas\mremoteng_confcons_v2_8.xsd">
<SubType>Designer</SubType>
</None>
<None Include="Schemas\mremoteng_confcons_v2_7.xsd">
<SubType>Designer</SubType>
</None>