Compare commits

..

109 Commits

Author SHA1 Message Date
David Sparer
7445e917d6 fixed an incomplete merge 2018-10-25 10:26:28 -05:00
David Sparer
7a54b98ea2 Merge branch 'develop' into remove_statics
# Conflicts:
#	mRemoteV1/UI/Controls/MultiSshToolStrip.cs
#	mRemoteV1/UI/Forms/frmMain.cs
#	mRemoteV1/UI/Panels/PanelAdder.cs
#	mRemoteV1/UI/Window/ConnectionTreeWindow.cs
2018-10-25 10:02:32 -05:00
David Sparer
f56b8f8e42 Merge branch 'master' into develop
# Conflicts:
#	CHANGELOG.TXT
#	CREDITS.TXT
#	mRemoteV1/Properties/AssemblyInfo.cs
2018-10-20 09:48:50 -05:00
David Sparer
8ab221e5a8 Merge branch 'release/v1.76' 2018-10-18 17:29:11 -05:00
David Sparer
6b280b5aa4 Merge pull request #1145 from st-schuler/reconnect-patch
Fixing "Reconnect to previously opened sessions on startup"
2018-10-17 16:46:39 -05:00
st-schuler
e6713520c7 Fixing "Reconnect to previously opened sessions on startup" 2018-10-17 20:01:51 +02:00
David Sparer
4f75b0343e Merge pull request #1120 from Fyers/develop
Improved German translations
2018-10-10 08:22:34 -05:00
David Sparer
097ebccdcd Merge pull request #1129 from pablomh/patch-1
Update Language.es.resx
2018-10-10 06:48:49 -05:00
pablomh
954e1de4da Update Language.es.resx
Misc fixes.
2018-10-10 09:22:31 +02:00
Fyers
63dc79699d Merge pull request #2 from Fyers/merge
Merge
2018-10-08 23:31:54 +02:00
Fyers
63f342bbdb resolved conflicts 2018-10-08 23:31:01 +02:00
Fyers
7c9b90ed7d Merge remote-tracking branch 'upstream/develop' into merge 2018-10-08 23:21:31 +02:00
David Sparer
00e45b60ad Merge branch 'master' into develop
# Conflicts:
#	CHANGELOG.TXT
#	mRemoteV1/Properties/AssemblyInfo.cs
#	mRemoteV1/Resources/Language/Language.resx
2018-10-08 15:23:25 -05:00
David Sparer
d1a7a37909 Merge branch 'release/v1.76' 2018-10-07 18:42:03 -05:00
David Sparer
fbd0407863 added redirect clipboard to xml schema for v2.7 confcons 2018-10-03 21:05:12 -05:00
David Sparer
7bab1b4297 created a confcons v2.7 serializer 2018-10-03 21:00:23 -05:00
David Sparer
cfce9e9887 Merge pull request #951 from CrAbelleira/develop
Clipboard sharing setting implementation for RDP protocol
2018-10-03 20:51:19 -05:00
Fyers
9df2a96027 improved german translations 2018-10-01 19:26:26 +02:00
Cristian Abelleira Olañeta
d967c719f5 Added "RedirectClipboard" to ConnectionSerializers/Xml and MiscSerializers 2018-10-01 00:52:31 +02:00
Cristian Abelleira Olañeta
726491feee Completed BuildExpectedConnectionInfoPropertyList 2018-09-24 18:19:33 +02:00
Cristian Abelleira
36a94e1399 Merge branch 'develop' into develop 2018-09-24 11:39:32 +02:00
David Sparer
d9e65719d3 Merge branch 'release/v1.76' into develop
# Conflicts:
#	CHANGELOG.TXT
2018-09-22 17:40:42 -05:00
David Sparer
ee63292e55 Merge branch 'update-asset-labels' into develop 2018-08-26 12:49:18 -05:00
David Sparer
9fbcde3ca0 simplify labels 2018-08-26 12:46:17 -05:00
David Sparer
9e48c8e359 changed labels to be more enduser appropriate 2018-08-26 12:21:59 -05:00
David Sparer
da07f50e49 Merge branch 'label-github-assets' into develop 2018-08-25 18:27:39 -05:00
David Sparer
cc872cd2b4 fixed powershell script 2018-08-25 17:03:28 -05:00
David Sparer
a3fa1e541c modified build to label assets 2018-08-25 17:02:54 -05:00
David Sparer
b579e823bd updated credits 2018-08-25 11:42:11 -05:00
David Sparer
fc5b1ec85e adjusted a few english strings that were added in #928 2018-08-25 11:39:25 -05:00
David Sparer
e0c2037831 set assembly version to 1.77.0 2018-08-25 11:38:40 -05:00
David Sparer
9f44d6b75b added changelog items for v1.77 updates 2018-08-25 10:56:30 -05:00
David Sparer
b6f2fff42b Merge branch 'release/v1.76' into develop 2018-08-25 10:46:10 -05:00
David Sparer
067ac8fb56 Merge branch 'areytsman-Advanced_closing_tabs' into develop 2018-08-25 09:51:09 -05:00
David Sparer
4428089146 Merge branch 'Advanced_closing_tabs' of https://github.com/areytsman/mRemoteNG into areytsman-Advanced_closing_tabs
# Conflicts:
#	mRemoteV1/Resources/Language/Language.resx
#	mRemoteV1/Resources/Language/Language.ru.resx
2018-08-25 09:24:58 -05:00
David Sparer
4dea0d03ed Merge branch 'develop' into remove_statics
# Conflicts:
#	mRemoteNGTests/IntegrationTests/XmlSerializationLifeCycleTests.cs
#	mRemoteV1/App/Windows.cs
#	mRemoteV1/Config/Settings/SettingsLoader.cs
#	mRemoteV1/Messages/WriterDecorators/MessageFocusDecorator.cs
#	mRemoteV1/UI/Controls/ConnectionTree/ConnectionTree.cs
#	mRemoteV1/UI/Forms/OptionsPages/ConnectionsPage.cs
#	mRemoteV1/UI/Forms/OptionsPages/CredentialsPage.cs
#	mRemoteV1/UI/Forms/OptionsPages/TabsPanelsPage.cs
#	mRemoteV1/UI/Forms/OptionsPages/UpdatesPage.cs
#	mRemoteV1/UI/Forms/frmChoosePanel.cs
#	mRemoteV1/UI/Forms/frmMain.cs
#	mRemoteV1/UI/Window/ConfigWindow.cs
#	mRemoteV1/UI/Window/ConnectionTreeWindow.cs
#	mRemoteV1/UI/Window/ErrorAndInfoWindow.cs
2018-08-24 18:14:54 -05:00
David Sparer
44ce674166 Merge branch 'release/v1.76' into develop 2018-08-24 17:20:56 -05:00
David Sparer
3fad827b9f Merge branch 'release/v1.76' into develop
# Conflicts:
#	Tools/zip_portable_files.ps1
#	mRemoteV1/Config/Putty/PuttySessionsRegistryProvider.cs
2018-08-22 10:39:09 -05:00
David Sparer
8bd571c78d added a wrapper around the windows registry api so we can better unit test classes that use the registry 2018-08-22 09:41:32 -05:00
David Sparer
38ff8340e4 Merge pull request #1016 from wwj402/develop
Chinese simplified language update for latest commit 05c96da
2018-08-19 12:01:31 -05:00
David Sparer
f759ea4bc2 Merge pull request #1072 from sli-pro/develop
Update the Russian language
2018-08-19 11:54:19 -05:00
sli-pro
011d0cad8c Update the Russian language
- Update the Russian language (Language.ru.resx)

- Update Language.resx
2018-08-11 18:34:11 +03:00
David Sparer
7526bb430f Merge pull request #1057 from Toomix/patch-1
Fixing NullReferenceException when renaming node
2018-08-01 06:45:42 -05:00
Toomix
7dbef77687 Fixing NullReferenceExcepction in renaming Node
When I have no selected node and I press F2 key, NullReferenceException appears in method RenameSelectedNode(). I added not null condition, it is working now. Debugged in VS2017.
2018-08-01 08:50:55 +02:00
Sean Kaim
a259ab9541 fix typo 2018-07-27 14:16:14 -04:00
Sean Kaim
08569276eb Revert "fixing changelog item"
This reverts commit edc4be2d44.
2018-07-27 14:11:43 -04:00
David Sparer
edc4be2d44 fixing changelog item 2018-07-27 07:49:00 -05:00
Sean Kaim
64422c60bb update changelog 2018-07-25 14:08:05 -04:00
Sean Kaim
a8b082ed4b fix test failures 2018-07-25 13:46:54 -04:00
Sean Kaim
5a5ade0d60 fix build failure 2018-07-25 13:10:39 -04:00
Sean Kaim
7e24e2dcfb fixes #971
Remove the "machineNode" XML node so that settings are portable to all systems
2018-07-25 13:02:30 -04:00
Sean Kaim
930579d983 PortableSettingsProvider code clean up 2018-07-25 12:35:53 -04:00
David Sparer
e05eb0807e fixed a few missed merge items 2018-07-23 15:19:29 -05:00
David Sparer
1aca1b7ae8 Merge branch 'develop' into remove_statics
# Conflicts:
#	mRemoteNGTests/Config/Serializers/ConnectionSerializers/Xml/XmlConnectionsDeserializerTests.cs
#	mRemoteNGTests/mRemoteNGTests.csproj
#	mRemoteV1/App/Runtime.cs
#	mRemoteV1/Config/Connections/XmlConnectionsLoader.cs
#	mRemoteV1/Config/Serializers/ConnectionSerializers/Xml/XmlConnectionsDeserializer.cs
#	mRemoteV1/Connection/ConnectionsService.cs
#	mRemoteV1/UI/Forms/frmMain.cs
#	mRemoteV1/UI/Menu/MainFileMenu.cs
#	mRemoteV1/UI/Window/ConfigWindow.cs
#	mRemoteV1/UI/Window/ConnectionTreeWindow.cs
#	mRemoteV1/UI/Window/PortScanWindow.cs
2018-07-23 15:06:15 -05:00
David Sparer
82847f07b2 Merge branch 'release/v1.76' into develop 2018-07-23 13:22:39 -05:00
Sean Kaim
a7280da30c Solution config was building wrong projects 2018-07-07 14:10:18 -04:00
Sean Kaim
ac2920820d the post publish job in the appveyor.yaml in ps1 form 2018-07-03 17:04:11 -04:00
Sean Kaim
fcecc4b31e post build zip artifact test 2018-07-03 14:24:12 -04:00
Sean Kaim
4abef50ca0 appveyor post build tests 2018-07-03 13:38:22 -04:00
Sean Kaim
5e16445b08 testing post build appveyor script 2018-07-03 13:11:10 -04:00
Sean Kaim
be593b8185 don't run post build zip in appveyor 2018-07-03 13:10:52 -04:00
Sean Kaim
ca27cb9981 Trim ConfigurationName 2018-07-03 12:34:20 -04:00
Sean Kaim
5b64e629c9 zip portable directly via powershell
Trying to fix appveyor artifact build
2018-07-03 11:59:02 -04:00
Sean Kaim
18640826b6 latest 7-zip 2018-07-03 11:48:26 -04:00
Sean Kaim
e4d3239831 appveyor build installer 2018-07-02 17:34:08 -04:00
Sean Kaim
e834eadbe1 appveyor artifacts test 2018-07-02 17:03:23 -04:00
Sean Kaim
0ec8f66972 Revert "test appveyor artifacts"
This reverts commit 458c462f49.
2018-07-02 15:31:17 -04:00
Sean Kaim
28b49aab70 fix quotes 2018-07-02 15:29:27 -04:00
Sean Kaim
458c462f49 test appveyor artifacts 2018-07-02 15:29:05 -04:00
Sean Kaim
6f6e2a1254 code clean up (convert to expression body) 2018-07-02 15:12:01 -04:00
Sean Kaim
f46a3d69e1 minor code clean up 2018-07-02 14:57:10 -04:00
Sean Kaim
fa787ed082 minor code clean up 2018-07-02 14:34:22 -04:00
wwj402
b5b748f993 Chinese simplified language update for latest commit 05c96da 2018-07-02 11:02:48 +08:00
David Sparer
75c866f7c1 remove unnecessary frmmain singleton property 2018-05-24 17:49:03 -05:00
David Sparer
c3ae438e9c fix failing test 2018-05-24 17:48:44 -05:00
David Sparer
314c989dae created IConnectionService interface and replaced usage with concrete type 2018-05-24 17:25:04 -05:00
David Sparer
8c350429b7 massive refactor of the rest of the frmmain statics 2018-05-22 21:31:22 -05:00
David Sparer
b21f2ffe65 removed some more default frmmain uses 2018-05-20 20:18:58 -05:00
David Sparer
66b307bff9 rdp protocol now no longer uses static frmmain ref 2018-05-20 20:06:22 -05:00
David Sparer
c43ef052c6 removed some frmmain static instance refs 2018-05-20 19:57:25 -05:00
David Sparer
d0a011d8ff Merge branch 'develop' into remove_statics 2018-05-20 11:08:29 -05:00
David Sparer
05c96da98f Merge branch 'release/v1.76' into develop 2018-05-20 11:08:14 -05:00
David Sparer
de9b78c5fb fix test 2018-05-20 09:51:35 -05:00
David Sparer
991505b043 fixed bug where connection properties weren't being passed to external tools 2018-05-20 09:42:31 -05:00
David Sparer
729166fc30 Merge branch 'develop' into remove_statics
# Conflicts:
#	mRemoteV1/UI/Forms/frmMain.Designer.cs
#	mRemoteV1/UI/Forms/frmMain.cs
#	mRemoteV1/UI/Menu/ViewMenu.cs
2018-05-20 09:29:55 -05:00
David Sparer
ea53fc190b Merge branch 'release/v1.76' into develop 2018-05-20 09:08:41 -05:00
Sean Kaim
662b5bde31 code clean up 2018-05-16 22:58:12 -04:00
Sean Kaim
388a4ed75b minor code clean up
* No need to kick off the registry provider here (it's done already in PuttySessionsManager#StartWatcher())

* if (Directory.Exists(sessionsFolderPath)) thows an exception even though it should have just fallen through... but if (!Directory.Exists(sessionsFolderPath)) doesn't throw and logs a message with a graceful return????

IDK... I had a Uri.IsWellFormedUriString test in there to avoid the exception, but it seems unnecessary...
2018-05-16 21:55:24 -04:00
Cristian Abelleira Olañeta
5311b522b7 Added InheritRedirectClipboard to CsvSerializer 2018-04-18 18:07:52 +02:00
Cristian Abelleira Olañeta
ea682e218d Fixed multiple errors in implementation 2018-04-15 20:13:28 +02:00
Cristian Abelleira Olañeta
aa5f7ef2a8 Implemented clipboard sharing setting for RDP protocol 2018-04-15 10:41:39 +02:00
Aleksei Reytsman
2c62218fd6 Add context menu items to close other and other to the right tabs 2018-03-28 18:21:47 +03:00
David Sparer
3fbad29017 removed a reference to static FrmMain 2018-03-12 21:43:01 -05:00
David Sparer
7a4b232695 updated a few more classes to not rely on Runtime 2018-03-04 12:23:19 -06:00
David Sparer
ba94e10cfa modified a few more classes to reduce reliance on Runtime 2018-03-04 12:04:32 -06:00
David Sparer
5093035f68 changed more classes to not rely on Runtime for the connections service 2018-03-04 11:52:58 -06:00
David Sparer
8159165968 modified some classes to request ConnectionsService as a ctor arg 2018-03-04 11:34:48 -06:00
David Sparer
5903481c87 made the Import class non static 2018-03-03 17:53:00 -06:00
David Sparer
e7afe5ea93 made some references to the connection service non static 2018-03-03 17:34:45 -06:00
David Sparer
f00dad3c96 moved several methods from Runtime to the connections service 2018-03-03 17:20:04 -06:00
David Sparer
db99a32c1d moved encryption key variable to the connections service where it makes more sense 2018-03-03 17:14:02 -06:00
David Sparer
c04bb44da3 fixed a composition bug and created a few tests 2018-03-03 13:25:42 -06:00
David Sparer
ba11746e6f removed ExternalToolsService var from Runtime 2018-03-03 12:47:37 -06:00
David Sparer
ced33027b8 made Shutdown and SettingsSaver non-static 2018-03-03 12:05:38 -06:00
David Sparer
0febc13ec7 removed use of the credential catalog Runtime var 2018-03-03 11:02:36 -06:00
David Sparer
05e62ff76f made Export class non static 2018-03-03 10:48:02 -06:00
David Sparer
107067cead removed unnecessary var in Runtime 2018-03-03 10:47:47 -06:00
David Sparer
13f51629af completed first round of fixes 2018-03-02 13:40:24 -06:00
David Sparer
8dc3303e0f first wave of changes 2018-03-02 06:38:55 -06:00
156 changed files with 4968 additions and 3065 deletions

View File

@@ -1,42 +1,10 @@
1.76.15 (2019-03-09):
Fixes:
------
#1303: Exception on first connection with new SQL server database
#1304: Resolved several issues with importing multiple RDP Manager v2.7 files
1.77.0 (2018-xx-xx):
Features/Enhancements:
----------------------
Importing multiple files now only causes 1 save event, rather than 1 per file imported.
1.76.14 (2019-02-08):
Features/Enhancements:
----------------------
#222: Allow FIPS to be enabled
1.76.13 (2018-12-22):
Changes:
--------
#222: Pre-Release Test build for running on systems with FIPS Enabled
1.76.12 (2018-11-08):
Features/Enhancements:
----------------------
#1180: Allow saving certain connection properties locally when using database
Fixes:
------
#1181: Connections sometimes dont immediately load when switching to sql feature
#1173: Fixed memory leak when loading connections multiple times
#1168: Autohide Connection and Config tab won't open when ssh connection active
#1134: Fixed issue where opening a connection opens same connection on other clients when using database feature
#449: Encrypt passwords saved to database
#1072: Russian translation improvements
#1016: Chinese (simplified) translation improvements
#928: Add context menu items to 'Close all but this' and 'Close all tabs to the right'
1.76.11 (2018-10-18):

View File

@@ -25,6 +25,7 @@ github.com/sirLoaf
github.com/Fyers
Vladimir Semenov (github.com/sli-pro)
Stephan (github.com/st-schuler)
Aleksey Reytsman (github.com/areytsman)
Past Contributors
@@ -63,6 +64,7 @@ Stefan (github.com/polluks)
github.com/emazv72
Vladimir Semenov (github.com/sli-pro)
Marco Sousa (github.com/marcomsousa)
github.com/wwj402
Included Source Code

View File

@@ -1,47 +0,0 @@
using System.IO;
using mRemoteNG.App;
using mRemoteNG.Config.Putty;
using mRemoteNG.Connection;
using mRemoteNG.Container;
using mRemoteNGTests.Properties;
using mRemoteNGTests.TestHelpers;
using NUnit.Framework;
namespace mRemoteNGTests.App
{
public class ImportTests
{
[Test]
public void ErrorHandlerCalledWhenUnsupportedFileExtensionFound()
{
using (FileTestHelpers.DisposableTempFile(out var file, ".blah"))
{
var conService = new ConnectionsService(PuttySessionsManager.Instance);
var container = new ContainerInfo();
var exceptionOccurred = false;
Import.HeadlessFileImport(new []{file}, container, conService, s => exceptionOccurred = true);
Assert.That(exceptionOccurred);
}
}
[Test]
public void AnErrorInOneFileDoNotPreventOtherFilesFromProcessing()
{
using (FileTestHelpers.DisposableTempFile(out var badFile, ".blah"))
using (FileTestHelpers.DisposableTempFile(out var rdpFile, ".rdp"))
{
File.AppendAllText(rdpFile, Resources.test_remotedesktopconnection_rdp);
var conService = new ConnectionsService(PuttySessionsManager.Instance);
var container = new ContainerInfo();
var exceptionCount = 0;
Import.HeadlessFileImport(new[] { badFile, rdpFile }, container, conService, s => exceptionCount++);
Assert.That(exceptionCount, Is.EqualTo(1));
Assert.That(container.Children, Has.One.Items);
}
}
}
}

View File

@@ -0,0 +1,17 @@
using System.Windows.Forms;
using NUnit.Framework;
// Dont put this in a namespace. Leaving it by itself tells NUnit
// to run it on assembly load
[SetUpFixture]
public class AssemblyTestSetup
{
[OneTimeSetUp]
public void AssemblySetup()
{
// ensure window options set before any test window created
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
}
}

View File

@@ -1,12 +1,16 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using mRemoteNG.App;
using mRemoteNG.Config.Putty;
using mRemoteNG.Config.Serializers.Xml;
using mRemoteNG.Connection;
using mRemoteNG.Container;
using mRemoteNG.Security;
using mRemoteNG.Tree;
using mRemoteNGTests.Properties;
using NSubstitute;
using NUnit.Framework;
namespace mRemoteNGTests.Config.Serializers.ConnectionSerializers.Xml
@@ -18,7 +22,10 @@ namespace mRemoteNGTests.Config.Serializers.ConnectionSerializers.Xml
public void Setup(string confCons, string password)
{
_xmlConnectionsDeserializer = new XmlConnectionsDeserializer(() => password.ConvertToSecureString());
var connectionsService = new ConnectionsService(PuttySessionsManager.Instance,
new Import(Substitute.For<IWin32Window>()),
Substitute.For<IWin32Window>());
_xmlConnectionsDeserializer = new XmlConnectionsDeserializer(connectionsService, Substitute.For<IWin32Window>(), () => password.ConvertToSecureString());
_connectionTreeModel = _xmlConnectionsDeserializer.Deserialize(confCons);
}

View File

@@ -1,9 +1,8 @@
using System.Data;
using System.Security;
using mRemoteNG.Config.Serializers.MsSql;
using System.Linq;
using mRemoteNG.Config.Serializers;
using mRemoteNG.Connection;
using mRemoteNG.Security;
using mRemoteNG.Security.SymmetricEncryption;
using mRemoteNG.Tree;
using mRemoteNGTests.TestHelpers;
using NSubstitute;
@@ -14,37 +13,30 @@ namespace mRemoteNGTests.Config.Serializers
public class DataTableDeserializerTests
{
private DataTableDeserializer _deserializer;
private ICryptographyProvider _cryptographyProvider;
[SetUp]
public void Setup()
{
_cryptographyProvider = new LegacyRijndaelCryptographyProvider();
}
[Test]
public void WeCanDeserializeATree()
{
var model = CreateConnectionTreeModel();
var dataTable = CreateDataTable(model.RootNodes[0]);
_deserializer = new DataTableDeserializer(_cryptographyProvider, new SecureString());
_deserializer = new DataTableDeserializer(Substitute.For<IConnectionsService>());
var output = _deserializer.Deserialize(dataTable);
Assert.That(output.GetRecursiveChildList().Count, Is.EqualTo(model.GetRecursiveChildList().Count));
Assert.That(output.GetRecursiveChildList().Count(), Is.EqualTo(model.GetRecursiveChildList().Count()));
}
[Test]
public void WeCanDeserializeASingleEntry()
{
var dataTable = CreateDataTable(new ConnectionInfo());
_deserializer = new DataTableDeserializer(_cryptographyProvider, new SecureString());
_deserializer = new DataTableDeserializer(Substitute.For<IConnectionsService>());
var output = _deserializer.Deserialize(dataTable);
Assert.That(output.GetRecursiveChildList().Count, Is.EqualTo(1));
Assert.That(output.GetRecursiveChildList().Count(), Is.EqualTo(1));
}
private DataTable CreateDataTable(ConnectionInfo tableContent)
{
var serializer = new DataTableSerializer(new SaveFilter(), _cryptographyProvider, new SecureString());
var serializer = new DataTableSerializer(new SaveFilter());
return serializer.Serialize(tableContent);
}

View File

@@ -1,15 +1,11 @@
using System.Linq;
using System.Security;
using mRemoteNG.Config.Serializers;
using mRemoteNG.Config.Serializers.MsSql;
using mRemoteNG.Connection;
using mRemoteNG.Container;
using mRemoteNG.Security;
using mRemoteNG.Security.SymmetricEncryption;
using mRemoteNG.Tree;
using mRemoteNG.Tree.Root;
using mRemoteNGTests.TestHelpers;
using NSubstitute;
using NUnit.Framework;
namespace mRemoteNGTests.Config.Serializers
@@ -23,10 +19,7 @@ namespace mRemoteNGTests.Config.Serializers
public void Setup()
{
_saveFilter = new SaveFilter();
_dataTableSerializer = new DataTableSerializer(
_saveFilter,
new LegacyRijndaelCryptographyProvider(),
new SecureString());
_dataTableSerializer = new DataTableSerializer(_saveFilter);
}
[Test]

View File

@@ -1,21 +1,20 @@
using System;
using System.Collections.Generic;
using System.IO;
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";
@@ -45,62 +44,262 @@ namespace mRemoteNGTests.Config.Serializers.MiscSerializers
{
_connectionFileContents = Resources.test_rdcman_v2_7_schema3;
_deserializer = new RemoteDesktopConnectionManagerDeserializer();
_connectionTreeModel = _deserializer.Deserialize(_connectionFileContents);
}
[Test]
public void ConnectionTreeModelHasARootNode()
{
var connectionTreeModel = _deserializer.Deserialize(_connectionFileContents);
var numberOfRootNodes = connectionTreeModel.RootNodes.Count;
var numberOfRootNodes = _connectionTreeModel.RootNodes.Count;
Assert.That(numberOfRootNodes, Is.GreaterThan(0));
}
[Test]
public void RootNodeHasContents()
{
var connectionTreeModel = _deserializer.Deserialize(_connectionFileContents);
var rootNodeContents = connectionTreeModel.RootNodes.First().Children;
var rootNodeContents = _connectionTreeModel.RootNodes.First().Children;
Assert.That(rootNodeContents, Is.Not.Empty);
}
[Test]
public void AllSubRootFoldersImported()
{
var connectionTreeModel = _deserializer.Deserialize(_connectionFileContents);
var rootNode = connectionTreeModel.RootNodes.First();
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));
}
[TestCaseSource(nameof(ExpectedPropertyValues))]
public void PropertiesWithValuesAreCorrectlyImported(Func<ConnectionInfo, object> propSelector, object expectedValue)
[Test]
public void ConnectionDisplayNameImported()
{
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));
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));
}
[TestCaseSource(nameof(NullPropertyValues))]
public void PropertiesWithoutValuesAreIgnored(Func<ConnectionInfo, object> propSelector)
[Test]
public void ConnectionHostnameImported()
{
var connectionTreeModel = _deserializer.Deserialize(Resources.test_rdcman_v2_7_schema3_null_values);
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 importedConnection = connectionTreeModel
.GetRecursiveChildList()
.OfType<ContainerInfo>()
.First(node => node.Name == "Group1")
.Children
.First();
[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));
}
Assert.That(propSelector(importedConnection), Is.EqualTo(propSelector(new ConnectionInfo())));
[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));
}
[Test]
@@ -123,61 +322,5 @@ 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

@@ -5,6 +5,7 @@ using mRemoteNG.Connection.Protocol;
using mRemoteNG.Connection.Protocol.SSH;
using mRemoteNG.Container;
using mRemoteNG.Tree.Root;
using NSubstitute;
using NUnit.Framework;
@@ -13,11 +14,13 @@ namespace mRemoteNGTests.Connection
public class ConnectionInfoTests
{
private ConnectionInfo _connectionInfo;
private IConnectionsService _connectionsService;
private const string TestDomain = "somedomain";
[SetUp]
public void Setup()
{
_connectionsService = Substitute.For<IConnectionsService>();
_connectionInfo = new ConnectionInfo();
}
@@ -79,7 +82,7 @@ namespace mRemoteNGTests.Connection
{
var eventWasCalled = false;
_connectionInfo.PropertyChanged += (sender, args) => eventWasCalled = true;
_connectionInfo.OpenConnections.Add(new ProtocolSSH2());
_connectionInfo.OpenConnections.Add(new ProtocolSSH2(_connectionsService));
Assert.That(eventWasCalled);
}
@@ -88,7 +91,7 @@ namespace mRemoteNGTests.Connection
{
var nameOfModifiedProperty = "";
_connectionInfo.PropertyChanged += (sender, args) => nameOfModifiedProperty = args.PropertyName;
_connectionInfo.OpenConnections.Add(new ProtocolSSH2());
_connectionInfo.OpenConnections.Add(new ProtocolSSH2(_connectionsService));
Assert.That(nameOfModifiedProperty, Is.EqualTo("OpenConnections"));
}

View File

@@ -1,31 +1,50 @@
using System.Collections.ObjectModel;
using System;
using System.Security;
using System.Threading;
using System.Windows.Forms;
using mRemoteNG.App;
using mRemoteNG.App.Update;
using mRemoteNG.Config.DatabaseConnectors;
using mRemoteNG.Config.Putty;
using mRemoteNG.Config.Settings;
using mRemoteNG.Connection;
using mRemoteNG.Connection.Protocol;
using mRemoteNG.Credential.Repositories;
using mRemoteNG.Tools;
using mRemoteNG.Tools.CustomCollections;
using mRemoteNG.UI.Controls;
using mRemoteNG.UI.Forms;
using mRemoteNG.UI.Window;
using NSubstitute;
using NUnit.Framework;
using WeifenLuo.WinFormsUI.Docking;
namespace mRemoteNGTests.Connection.Protocol
{
public class IntegratedProgramTests
{
private readonly ExternalTool _extTool = new ExternalTool
{
DisplayName = "notepad",
FileName = @"%windir%\system32\notepad.exe",
Arguments = "",
TryIntegrate = true
};
public class IntegratedProgramTests
{
private ExternalToolsService _externalToolsService;
private IConnectionInitiator _connectionInitiator;
[Test]
[OneTimeSetUp]
public void OneTimeSetUp()
{
_connectionInitiator = Substitute.For<IConnectionInitiator>();
var extTool = new ExternalTool(_connectionInitiator, Substitute.For<IConnectionsService>())
{
DisplayName = "notepad",
FileName = @"%windir%\system32\notepad.exe",
Arguments = "",
TryIntegrate = true
};
_externalToolsService = new ExternalToolsService();
_externalToolsService.ExternalTools.Add(extTool);
}
[Test]
[Apartment(ApartmentState.STA)]
public void CanStartExternalApp()
{
SetExternalToolList(_extTool);
var sut = new IntegratedProgram();
var sut = new IntegratedProgram(_externalToolsService, Substitute.For<IConnectionsService>());
sut.InterfaceControl = BuildInterfaceControl("notepad", sut);
sut.Initialize();
var appStarted = sut.Connect();
@@ -34,23 +53,42 @@ namespace mRemoteNGTests.Connection.Protocol
}
[Test]
[Apartment(ApartmentState.STA)]
public void ConnectingToExternalAppThatDoesntExistDoesNothing()
{
SetExternalToolList(_extTool);
var sut = new IntegratedProgram();
var sut = new IntegratedProgram(_externalToolsService, Substitute.For<IConnectionsService>());
sut.InterfaceControl = BuildInterfaceControl("doesntExist", sut);
var appInitialized = sut.Initialize();
Assert.That(appInitialized, Is.False);
}
private void SetExternalToolList(ExternalTool externalTool)
{
Runtime.ExternalToolsService.ExternalTools = new FullyObservableCollection<ExternalTool> {externalTool};
}
private InterfaceControl BuildInterfaceControl(string extAppName, ProtocolBase sut)
{
var connectionWindow = new ConnectionWindow(new DockContent());
var frmMain = new FrmMain();
var import = new Import(Substitute.For<IWin32Window>());
var connectionsService = new ConnectionsService(PuttySessionsManager.Instance, import, frmMain);
var configWindow = new ConfigWindow(new DockContent(), connectionsService);
var sshTransferWindow = new SSHTransferWindow();
var connectionTreeWindow = new ConnectionTreeWindow(new DockContent(), _connectionInitiator, connectionsService);
Func<SecureString> encryptionKeySelectionFunc = () => connectionsService.EncryptionKey;
var connectionTree = connectionTreeWindow.ConnectionTree;
var export = new Export(new CredentialRepositoryList(), connectionsService, frmMain);
var connectionTreeContextMenu = new ConnectionContextMenu(connectionTree, _connectionInitiator, sshTransferWindow, export, _externalToolsService, import, connectionsService);
connectionTreeWindow.ConnectionTreeContextMenu = connectionTreeContextMenu;
var errorAndInfoWindow = new ErrorAndInfoWindow(new DockContent(), new DockPanel(), connectionTreeWindow);
var screenshotManagerWindow = new ScreenshotManagerWindow(new DockContent(), new DockPanel());
var shutdown = new Shutdown(new SettingsSaver(new ExternalToolsService()), new ConnectionsService(PuttySessionsManager.Instance, import, frmMain), frmMain);
var appUpdater = new AppUpdater(encryptionKeySelectionFunc);
Func<UpdateWindow> updateWindowBuilder = () => new UpdateWindow(new DockContent(), shutdown, appUpdater);
Func<NotificationAreaIcon> notificationAreaIconBuilder = () => new NotificationAreaIcon(frmMain, _connectionInitiator, shutdown, connectionsService);
Func<ExternalToolsWindow> externalToolsWindowBuilder = () => new ExternalToolsWindow(_connectionInitiator, _externalToolsService, () => connectionTree.SelectedNode, frmMain, connectionsService);
Func<PortScanWindow> portScanWindowBuilder = () => new PortScanWindow(connectionTreeWindow, import);
Func<ActiveDirectoryImportWindow> activeDirectoryImportWindowBuilder = () => new ActiveDirectoryImportWindow(() => connectionTreeWindow.SelectedNode, import, connectionsService);
var databaseConnectorFactory = new DatabaseConnectorFactory(encryptionKeySelectionFunc);
var windows = new Windows(_connectionInitiator, connectionTreeWindow, configWindow, errorAndInfoWindow, screenshotManagerWindow,
sshTransferWindow, updateWindowBuilder, notificationAreaIconBuilder, externalToolsWindowBuilder,
connectionsService, portScanWindowBuilder, activeDirectoryImportWindowBuilder, appUpdater, databaseConnectorFactory, frmMain);
var connectionWindow = new ConnectionWindow(new DockContent(), _connectionInitiator, windows, _externalToolsService, frmMain);
var connectionInfo = new ConnectionInfo {ExtApp = extAppName};
return new InterfaceControl(connectionWindow, sut, connectionInfo);
}

View File

@@ -1,9 +1,12 @@
using System.Collections;
using System.Collections.Specialized;
using mRemoteNG.Config.Putty;
using mRemoteNG.Connection;
using mRemoteNG.Connection.Protocol;
using mRemoteNG.Connection.Protocol.SSH;
using mRemoteNG.Connection.Protocol.Telnet;
using mRemoteNG.Connection.Protocol.VNC;
using NSubstitute;
using NUnit.Framework;
@@ -20,9 +23,10 @@ namespace mRemoteNGTests.Connection.Protocol
[SetUp]
public void Setup()
{
var connectionService = Substitute.For<IConnectionsService>();
_protocolList = new ProtocolList();
_protocol1 = new ProtocolTelnet();
_protocol2 = new ProtocolSSH2();
_protocol1 = new ProtocolTelnet(connectionService);
_protocol2 = new ProtocolSSH2(connectionService);
_protocol3 = new ProtocolVNC();
}

View File

@@ -1,7 +1,8 @@
using System;
using System.Linq;
using System.Xml.Linq;
using mRemoteNG.Config.Serializers;
using System.Windows.Forms;
using mRemoteNG.App;
using mRemoteNG.Config.Putty;
using mRemoteNG.Config.Serializers.Xml;
using mRemoteNG.Connection;
using mRemoteNG.Container;
@@ -9,6 +10,7 @@ using mRemoteNG.Security;
using mRemoteNG.Security.Factories;
using mRemoteNG.Tree;
using mRemoteNG.Tree.Root;
using NSubstitute;
using NUnit.Framework;
@@ -31,7 +33,8 @@ namespace mRemoteNGTests.IntegrationTests
_originalModel.RootNodes.OfType<RootNodeInfo>().First().PasswordString.ConvertToSecureString(),
new SaveFilter());
_serializer = new XmlConnectionsSerializer(cryptoProvider, nodeSerializer);
_deserializer = new XmlConnectionsDeserializer();
var mockWindow = Substitute.For<IWin32Window>();
_deserializer = new XmlConnectionsDeserializer(new ConnectionsService(PuttySessionsManager.Instance, new Import(mockWindow), mockWindow), mockWindow);
}
[TearDown]
@@ -139,4 +142,4 @@ namespace mRemoteNGTests.IntegrationTests
return connectionTreeModel;
}
}
}
}

View File

@@ -298,32 +298,6 @@ 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,9 +172,6 @@
<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

@@ -1,95 +0,0 @@
<?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,5 +1,4 @@
using System.IO;
using mRemoteNG.Tools;
namespace mRemoteNGTests.TestHelpers
{
@@ -19,17 +18,9 @@ namespace mRemoteNGTests.TestHelpers
File.Delete(file);
}
public static void DeleteDirectory(string directory)
{
if (Directory.Exists(directory))
Directory.Delete(directory, true);
}
public static string NewTempFilePath(string extension = "")
public static string NewTempFilePath()
{
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);
@@ -44,15 +35,5 @@ 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

@@ -40,7 +40,8 @@
public TType RedirectKeys { get; set; }
public TType RedirectDiskDrives { get; set; }
public TType RedirectPrinters { get; set; }
public TType RedirectPorts { get; set; }
public TType RedirectClipboard { get; set; }
public TType RedirectPorts { get; set; }
public TType RedirectSmartCards { get; set; }
public TType RedirectSound { get; set; }
public TType SoundQuality { get; set; }

View File

@@ -1,42 +0,0 @@
using mRemoteNG.Tools;
using NUnit.Framework;
namespace mRemoteNGTests.Tools
{
public class DisposableActionTests
{
[Test]
public void InitializerActionRunsWhenObjectIsCreated()
{
var initializerRan = false;
new DisposableAction(() => initializerRan = true, () => { });
Assert.That(initializerRan);
}
[Test]
public void DisposalActionRunsWhenDisposeIsCalled()
{
var disposeActionRan = false;
var action = new DisposableAction(() => {}, () => disposeActionRan = true);
Assert.That(disposeActionRan, Is.False);
action.Dispose();
Assert.That(disposeActionRan, Is.True);
}
[Test]
public void DisposeActionOnlyExecutedOnceWhenCallingDisposeMultipleTimes()
{
var invokeCount = 0;
var action = new DisposableAction(() => { }, () => invokeCount++);
action.Dispose();
action.Dispose();
action.Dispose();
action.Dispose();
action.Dispose();
Assert.That(invokeCount, Is.EqualTo(1));
}
}
}

View File

@@ -2,6 +2,7 @@
using System.Collections;
using mRemoteNG.Connection;
using mRemoteNG.Tools;
using NSubstitute;
using NUnit.Framework;
@@ -34,7 +35,7 @@ namespace mRemoteNGTests.Tools
MacAddress = TestString,
UserField = TestString
};
_argumentParser = new ExternalToolArgumentParser(connectionInfo);
_argumentParser = new ExternalToolArgumentParser(connectionInfo, Substitute.For<IConnectionsService>());
}
[OneTimeTearDown]
@@ -52,7 +53,7 @@ namespace mRemoteNGTests.Tools
[Test]
public void NullConnectionInfoResultsInEmptyVariables()
{
var parser = new ExternalToolArgumentParser(null);
var parser = new ExternalToolArgumentParser(null, Substitute.For<IConnectionsService>());
var parsedText = parser.ParseArguments("test %USERNAME% test");
Assert.That(parsedText, Is.EqualTo("test test"));
}

View File

@@ -0,0 +1,50 @@
using System;
using System.Linq;
using mRemoteNG.Tools.WindowsRegistry;
using NUnit.Framework;
namespace mRemoteNGTests.Tools.Registry
{
public class WindowsRegistryTests
{
private WindowsRegistry _registry;
[SetUp]
public void Setup()
{
_registry = new WindowsRegistry();
}
[Test]
public void CanGetSubkeyNames()
{
var subKeyNames = _registry.GetSubKeyNames(RegistryHive.CurrentUser, "Software");
Assert.That(subKeyNames, Does.Contain("Microsoft"));
}
[Test]
public void GetSubkeyNamesThrowsIfGivenNullKeyPath()
{
Assert.Throws<ArgumentNullException>(() => _registry.GetSubKeyNames(RegistryHive.CurrentUser, null));
}
[Test]
public void CanGetKeyValue()
{
var keyValue = _registry.GetKeyValue(RegistryHive.ClassesRoot, @".dll\PersistentHandler", "");
Assert.That(keyValue.FirstOrDefault(), Is.EqualTo("{098f2470-bae0-11cd-b579-08002b30bfeb}"));
}
[Test]
public void GetKeyValueThrowsIfGivenNullKeyPath()
{
Assert.Throws<ArgumentNullException>(() => _registry.GetKeyValue(RegistryHive.CurrentUser, null, ""));
}
[Test]
public void GetKeyValueThrowsIfGivenNullPropertyName()
{
Assert.Throws<ArgumentNullException>(() => _registry.GetKeyValue(RegistryHive.CurrentUser, "", null));
}
}
}

View File

@@ -0,0 +1,49 @@
using System;
using mRemoteNG.Connection;
using mRemoteNG.Tools;
using mRemoteNG.UI.Controls;
using NSubstitute;
using NUnit.Framework;
namespace mRemoteNGTests.UI.Controls
{
public class ExternalToolsToolStripTests
{
private ExternalToolsToolStrip _externalToolsToolStrip;
[SetUp]
public void Setup()
{
_externalToolsToolStrip = new ExternalToolsToolStrip();
}
[TearDown]
public void Teardown()
{
_externalToolsToolStrip.Dispose();
}
[Test]
public void SettingExternalToolsServiceToNullThrowsException()
{
Assert.Throws<ArgumentNullException>(() => _externalToolsToolStrip.ExternalToolsService = null);
}
[Test]
public void AddExternalToolsToToolBarCreatesControlsForAllExternalTools()
{
var externaltoolsService = new ExternalToolsService();
externaltoolsService.ExternalTools.Add(BuildExternalTool());
externaltoolsService.ExternalTools.Add(BuildExternalTool());
_externalToolsToolStrip.ExternalToolsService = externaltoolsService;
_externalToolsToolStrip.AddExternalToolsToToolBar();
Assert.That(_externalToolsToolStrip.Items.Count, Is.EqualTo(2));
}
private ExternalTool BuildExternalTool()
{
return new ExternalTool(Substitute.For<IConnectionInitiator>(), Substitute.For<IConnectionsService>());
}
}
}

View File

@@ -6,7 +6,6 @@ namespace mRemoteNGTests.UI.Controls
{
public TextBoxExtensionsTestForm()
{
Application.EnableVisualStyles();
InitializeComponent();
}
}

View File

@@ -30,7 +30,8 @@ namespace mRemoteNGTests.UI.Controls
{
const string text = "Type Here";
var textBox = new TextBoxTester(_textBoxExtensionsTestForm.textBox1.Name);
Assert.That(textBox.Properties.SetCueBannerText(text), Is.True);
var textWasSet = textBox.Properties.SetCueBannerText(text);
Assert.That(textWasSet, Is.True);
}
[Test]

View File

@@ -0,0 +1,16 @@
using System.Threading;
using mRemoteNG.UI.Forms;
using NUnit.Framework;
namespace mRemoteNGTests.UI.Forms
{
public class FrmMainTests
{
[Test]
[Apartment(ApartmentState.STA)]
public void CanCreateFrmMain()
{
var frmMain = new FrmMain();
}
}
}

View File

@@ -1,9 +1,24 @@
using NUnit.Framework;
using System;
using System.Security;
using System.Windows.Forms;
using System.Xml.Linq;
using mRemoteNG.App;
using mRemoteNG.App.Update;
using mRemoteNG.Config.DatabaseConnectors;
using mRemoteNG.Config.Putty;
using mRemoteNG.Config.Serializers;
using mRemoteNG.Config.Serializers.Xml;
using mRemoteNG.Config.Settings;
using mRemoteNG.Connection;
using mRemoteNG.Security;
using mRemoteNG.Tools;
using mRemoteNG.UI.Forms;
using NSubstitute;
using NUnit.Framework;
namespace mRemoteNGTests.UI.Forms
{
public class OptionsFormSetupAndTeardown
public class OptionsFormSetupAndTeardown
{
protected frmOptions _optionsForm;
@@ -15,7 +30,16 @@ namespace mRemoteNGTests.UI.Forms
[SetUp]
public void Setup()
{
_optionsForm = new frmOptions();
var frmMain = new FrmMain();
var connectionInitiator = Substitute.For<IConnectionInitiator>();
var import = new Import(Substitute.For<IWin32Window>());
var shutdown = new Shutdown(new SettingsSaver(new ExternalToolsService()), new ConnectionsService(PuttySessionsManager.Instance, import, frmMain), frmMain);
var connectionsService = new ConnectionsService(PuttySessionsManager.Instance, import, frmMain);
Func<NotificationAreaIcon> notificationIconBuilder = () => new NotificationAreaIcon(frmMain, connectionInitiator, shutdown, connectionsService);
Func<SecureString> encryptionKeySelectionFunc = () => connectionsService.EncryptionKey;
var databaseConnectorFactory = new DatabaseConnectorFactory(encryptionKeySelectionFunc);
var appUpdater = new AppUpdater(encryptionKeySelectionFunc);
_optionsForm = new frmOptions(connectionInitiator, type => {}, notificationIconBuilder, connectionsService, appUpdater, databaseConnectorFactory, frmMain);
_optionsForm.Show();
}

View File

@@ -8,7 +8,9 @@ using mRemoteNG.Connection.Protocol.VNC;
using mRemoteNG.Container;
using mRemoteNG.Tree.Root;
using mRemoteNG.UI.Window;
using NSubstitute;
using NUnit.Framework;
using WeifenLuo.WinFormsUI.Docking;
namespace mRemoteNGTests.UI.Window.ConfigWindowTests
{
@@ -19,7 +21,7 @@ namespace mRemoteNGTests.UI.Window.ConfigWindowTests
[SetUp]
public void Setup()
{
_configWindow = new ConfigWindow
_configWindow = new ConfigWindow(new DockContent(), Substitute.For<IConnectionsService>())
{
PropertiesVisible = true
};
@@ -149,6 +151,7 @@ namespace mRemoteNGTests.UI.Window.ConfigWindowTests
nameof(ConnectionInfo.RedirectKeys),
nameof(ConnectionInfo.RedirectDiskDrives),
nameof(ConnectionInfo.RedirectPrinters),
nameof(ConnectionInfo.RedirectClipboard),
nameof(ConnectionInfo.RedirectPorts),
nameof(ConnectionInfo.RedirectSmartCards),
nameof(ConnectionInfo.RedirectSound),

View File

@@ -2,7 +2,9 @@
using mRemoteNG.Connection;
using mRemoteNG.Connection.Protocol;
using mRemoteNG.UI.Window;
using NSubstitute;
using NUnit.Framework;
using WeifenLuo.WinFormsUI.Docking;
namespace mRemoteNGTests.UI.Window.ConfigWindowTests
{
@@ -20,7 +22,7 @@ namespace mRemoteNGTests.UI.Window.ConfigWindowTests
ConnectionInfo = ConfigWindowGeneralTests.ConstructConnectionInfo(Protocol, TestAgainstContainerInfo);
ExpectedPropertyList = ConfigWindowGeneralTests.BuildExpectedConnectionInfoPropertyList(Protocol, TestAgainstContainerInfo);
ConfigWindow = new ConfigWindow
ConfigWindow = new ConfigWindow(new DockContent(), Substitute.For<IConnectionsService>())
{
PropertiesVisible = true,
};

View File

@@ -1,19 +1,38 @@
using System.Threading;
using System.Security;
using System.Threading;
using System.Windows.Forms;
using mRemoteNG.App;
using mRemoteNG.Config.Putty;
using mRemoteNG.Config.Serializers.Xml;
using mRemoteNG.Connection;
using mRemoteNG.Credential.Repositories;
using mRemoteNG.Security;
using mRemoteNG.Security.SymmetricEncryption;
using mRemoteNG.Tools;
using mRemoteNG.UI.Controls;
using mRemoteNG.UI.Window;
using NSubstitute;
using NUnit.Framework;
using WeifenLuo.WinFormsUI.Docking;
namespace mRemoteNGTests.UI.Window
{
public class ConnectionTreeWindowTests
public class ConnectionTreeWindowTests
{
private ConnectionTreeWindow _connectionTreeWindow;
[SetUp]
public void Setup()
{
_connectionTreeWindow = new ConnectionTreeWindow(new DockContent());
var connectionInitiator = Substitute.For<IConnectionInitiator>();
var connectionTree = new ConnectionTree();
var sshTransferWindow = new SSHTransferWindow();
var externalToolsService = new ExternalToolsService();
var import = new Import(Substitute.For<IWin32Window>());
var connectionsService = new ConnectionsService(PuttySessionsManager.Instance, import, connectionTree);
var export = new Export(new CredentialRepositoryList(), connectionsService, connectionTree);
var connectionContextMenu = new ConnectionContextMenu(connectionTree, connectionInitiator, sshTransferWindow, export, externalToolsService, import, connectionsService);
_connectionTreeWindow = new ConnectionTreeWindow(new DockContent(), connectionInitiator, connectionsService) {ConnectionTreeContextMenu = connectionContextMenu};
}
[TearDown]

View File

@@ -108,8 +108,8 @@
</Otherwise>
</Choose>
<ItemGroup>
<Compile Include="App\ImportTests.cs" />
<Compile Include="App\UpdaterTests.cs" />
<Compile Include="AssemblyTestSetup.cs" />
<Compile Include="BinaryFileTests.cs" />
<Compile Include="Config\Connections\Multiuser\ConnectionsUpdateAvailableEventArgsTests.cs" />
<Compile Include="Config\DataProviders\FileBackupCreatorTests.cs" />
@@ -176,10 +176,10 @@
<Compile Include="Security\XmlCryptoProviderBuilderTests.cs" />
<Compile Include="TestHelpers\FileTestHelpers.cs" />
<Compile Include="TestHelpers\SerializableConnectionInfoAllPropertiesOfType.cs" />
<Compile Include="Tools\DisposableActionTests.cs" />
<Compile Include="Tools\ExternalToolsArgumentParserTests.cs" />
<Compile Include="Tools\FullyObservableCollectionTests.cs" />
<Compile Include="Tools\OptionalTests.cs" />
<Compile Include="Tools\Registry\WindowsRegistryTests.cs" />
<Compile Include="Tree\ClickHandlers\TreeNodeCompositeClickHandlerTests.cs" />
<Compile Include="Tree\ConnectionTreeDragAndDropHandlerTests.cs" />
<Compile Include="Tree\ConnectionTreeModelTests.cs" />
@@ -209,6 +209,7 @@
<Compile Include="Tree\RootNodeInfoTests.cs" />
<Compile Include="Tree\ClickHandlers\SwitchToConnectionClickHandlerTests.cs" />
<Compile Include="Tree\SelectedConnectionDeletionConfirmerTests.cs" />
<Compile Include="UI\Controls\ExternalToolsToolStripTests.cs" />
<Compile Include="UI\Controls\ConnectionTreeTests.cs" />
<Compile Include="UI\Controls\PageSequenceTests.cs" />
<Compile Include="UI\Controls\SecureTextBoxTestForm.cs">
@@ -231,6 +232,7 @@
<DependentUpon>TextBoxExtensionsTestForm.cs</DependentUpon>
</Compile>
<Compile Include="UI\Controls\TextBoxExtensionsTests.cs" />
<Compile Include="UI\Forms\FrmMainTests.cs" />
<Compile Include="UI\Forms\OptionsFormSetupAndTeardown.cs" />
<Compile Include="UI\Forms\PasswordFormTests.cs" />
<Compile Include="UI\WindowListTests.cs" />
@@ -267,7 +269,6 @@
<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

@@ -6,42 +6,36 @@ using System;
using System.Diagnostics;
using System.Windows.Forms;
using mRemoteNG.Messages;
using mRemoteNG.Tools;
namespace mRemoteNG.App
{
public static class CompatibilityChecker
public class CompatibilityChecker
{
public static void CheckCompatibility(MessageCollector messageCollector)
private readonly MessageCollector _messageCollector;
private readonly IWin32Window _dialogWindowParent;
public CompatibilityChecker(MessageCollector messageCollector, IWin32Window dialogWindowParent)
{
CheckFipsPolicy(messageCollector);
CheckLenovoAutoScrollUtility(messageCollector);
_messageCollector = messageCollector.ThrowIfNull(nameof(messageCollector));
_dialogWindowParent = dialogWindowParent.ThrowIfNull(nameof(dialogWindowParent));
}
private static void CheckFipsPolicy(MessageCollector messageCollector)
public void CheckCompatibility()
{
if (Settings.Default.OverrideFIPSCheck)
{
messageCollector.AddMessage(MessageClass.InformationMsg, "OverrideFIPSCheck is set. Will skip check...", true);
return;
}
CheckFipsPolicy();
CheckLenovoAutoScrollUtility();
}
messageCollector.AddMessage(MessageClass.InformationMsg, "Checking FIPS Policy...", true);
private void CheckFipsPolicy()
{
_messageCollector.AddMessage(MessageClass.InformationMsg, "Checking FIPS Policy...", true);
if (!FipsPolicyEnabledForServer2003() && !FipsPolicyEnabledForServer2008AndNewer()) return;
var errorText = string.Format(Language.strErrorFipsPolicyIncompatible, GeneralAppInfo.ProductName);
messageCollector.AddMessage(MessageClass.ErrorMsg, errorText, true);
var ShouldIStayOrShouldIGo = CTaskDialog.MessageBox(Application.ProductName, Language.strCompatibilityProblemDetected, errorText, "", "", Language.strCheckboxDoNotShowThisMessageAgain, ETaskDialogButtons.OkCancel, ESysIcons.Warning, ESysIcons.Warning);
if (CTaskDialog.VerificationChecked && ShouldIStayOrShouldIGo == DialogResult.OK)
{
messageCollector.AddMessage(MessageClass.ErrorMsg, "User requests that FIPS check be overridden", true);
Settings.Default.OverrideFIPSCheck = true;
Settings.Default.Save();
return;
}
if (ShouldIStayOrShouldIGo == DialogResult.Cancel)
Environment.Exit(1);
var errorText = string.Format(Language.strErrorFipsPolicyIncompatible, GeneralAppInfo.ProductName,
GeneralAppInfo.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
_messageCollector.AddMessage(MessageClass.ErrorMsg, errorText, true);
MessageBox.Show(_dialogWindowParent, errorText);
Environment.Exit(1);
}
private static bool FipsPolicyEnabledForServer2003()
@@ -62,9 +56,9 @@ namespace mRemoteNG.App
return (int)fipsPolicy != 0;
}
private static void CheckLenovoAutoScrollUtility(MessageCollector messageCollector)
private void CheckLenovoAutoScrollUtility()
{
messageCollector.AddMessage(MessageClass.InformationMsg, "Checking Lenovo AutoScroll Utility...", true);
_messageCollector.AddMessage(MessageClass.InformationMsg, "Checking Lenovo AutoScroll Utility...", true);
if (!Settings.Default.CompatibilityWarnLenovoAutoScrollUtility)
return;
@@ -76,7 +70,7 @@ namespace mRemoteNG.App
}
catch (InvalidOperationException ex)
{
messageCollector.AddExceptionMessage("Error in CheckLenovoAutoScrollUtility", ex);
_messageCollector.AddExceptionMessage("Error in CheckLenovoAutoScrollUtility", ex);
}
if (proccesses.Length <= 0) return;

View File

@@ -8,8 +8,10 @@ using mRemoteNG.Config.Serializers.Csv;
using mRemoteNG.Config.Serializers.Xml;
using mRemoteNG.Connection;
using mRemoteNG.Container;
using mRemoteNG.Credential;
using mRemoteNG.Security;
using mRemoteNG.Security.Factories;
using mRemoteNG.Tools;
using mRemoteNG.Tree;
using mRemoteNG.Tree.Root;
using mRemoteNG.UI.Forms;
@@ -17,9 +19,20 @@ using mRemoteNG.UI.Forms;
namespace mRemoteNG.App
{
public static class Export
public class Export
{
public static void ExportToFile(ConnectionInfo selectedNode, ConnectionTreeModel connectionTreeModel)
private readonly IConnectionsService _connectionsService;
private readonly ICredentialRepositoryList _credentialRepositoryList;
private readonly IWin32Window _dialogWindowParent;
public Export(ICredentialRepositoryList credentialRepositoryList, IConnectionsService connectionsService, IWin32Window dialogWindowParent)
{
_credentialRepositoryList = credentialRepositoryList.ThrowIfNull(nameof(credentialRepositoryList));
_connectionsService = connectionsService.ThrowIfNull(nameof(connectionsService));
_dialogWindowParent = dialogWindowParent.ThrowIfNull(nameof(dialogWindowParent));
}
public void ExportToFile(ConnectionInfo selectedNode, ConnectionTreeModel connectionTreeModel)
{
try
{
@@ -36,7 +49,7 @@ namespace mRemoteNG.App
exportForm.SelectedConnection = selectedNode;
}
if (exportForm.ShowDialog(FrmMain.Default) != DialogResult.OK)
if (exportForm.ShowDialog(_dialogWindowParent) != DialogResult.OK)
return;
ConnectionInfo exportTarget;
@@ -69,7 +82,7 @@ namespace mRemoteNG.App
}
}
private static void SaveExportFile(string fileName, SaveFormat saveFormat, SaveFilter saveFilter, ConnectionInfo exportTarget)
private void SaveExportFile(string fileName, SaveFormat saveFormat, SaveFilter saveFilter, ConnectionInfo exportTarget)
{
try
{
@@ -79,14 +92,14 @@ namespace mRemoteNG.App
case SaveFormat.mRXML:
var cryptographyProvider = new CryptoProviderFactoryFromSettings().Build();
var rootNode = exportTarget.GetRootParent() as RootNodeInfo;
var connectionNodeSerializer = new XmlConnectionNodeSerializer26(
var connectionNodeSerializer = new XmlConnectionNodeSerializer27(
cryptographyProvider,
rootNode?.PasswordString.ConvertToSecureString() ?? new RootNodeInfo(RootNodeType.Connection).PasswordString.ConvertToSecureString(),
saveFilter);
serializer = new XmlConnectionsSerializer(cryptographyProvider, connectionNodeSerializer);
break;
case SaveFormat.mRCSV:
serializer = new CsvConnectionsSerializerMremotengFormat(saveFilter, Runtime.CredentialProviderCatalog);
serializer = new CsvConnectionsSerializerMremotengFormat(saveFilter, _credentialRepositoryList);
break;
default:
throw new ArgumentOutOfRangeException(nameof(saveFormat), saveFormat, null);
@@ -101,7 +114,7 @@ namespace mRemoteNG.App
}
finally
{
Runtime.ConnectionsService.RemoteConnectionsSyncronizer?.Enable();
_connectionsService.RemoteConnectionsSyncronizer?.Enable();
}
}
}

View File

@@ -10,9 +10,19 @@ using mRemoteNG.Tools;
namespace mRemoteNG.App
{
public static class Import
public class Import
{
public static void ImportFromFile(ContainerInfo importDestinationContainer)
private readonly IWin32Window _dialogWindowParent;
public Import(IWin32Window dialogWindowParent)
{
_dialogWindowParent = dialogWindowParent.ThrowIfNull(nameof(dialogWindowParent));
}
// TODO - this is only a property to break up a circular dependency. move this to ctor when able
public IConnectionsService ConnectionsService { get; set; }
public void ImportFromFile(ContainerInfo importDestinationContainer)
{
try
{
@@ -36,12 +46,22 @@ namespace mRemoteNG.App
if (openFileDialog.ShowDialog() != DialogResult.OK)
return;
HeadlessFileImport(
openFileDialog.FileNames,
importDestinationContainer,
Runtime.ConnectionsService,
fileName => MessageBox.Show(string.Format(Language.strImportFileFailedContent, fileName), Language.strImportFileFailedMainInstruction,
MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1));
foreach (var fileName in openFileDialog.FileNames)
{
try
{
var importer = BuildConnectionImporterFromFileExtension(fileName);
importer.Import(fileName, importDestinationContainer);
}
catch (Exception ex)
{
MessageBox.Show(string.Format(Language.strImportFileFailedContent, fileName), Language.strImportFileFailedMainInstruction,
MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);
Runtime.MessageCollector.AddExceptionMessage("Unable to import file.", ex);
}
}
ConnectionsService.SaveConnectionsAsync();
}
}
catch (Exception ex)
@@ -50,38 +70,12 @@ namespace mRemoteNG.App
}
}
public static void HeadlessFileImport(
IEnumerable<string> filePaths,
ContainerInfo importDestinationContainer,
ConnectionsService connectionsService,
Action<string> exceptionAction = null)
{
using (connectionsService.BatchedSavingContext())
{
foreach (var fileName in filePaths)
{
try
{
var importer = BuildConnectionImporterFromFileExtension(fileName);
importer.Import(fileName, importDestinationContainer);
}
catch (Exception ex)
{
exceptionAction?.Invoke(fileName);
Runtime.MessageCollector.AddExceptionMessage($"Error occurred while importing file '{fileName}'.", ex);
}
}
}
}
public static void ImportFromActiveDirectory(string ldapPath, ContainerInfo importDestinationContainer, bool importSubOu)
public void ImportFromActiveDirectory(string ldapPath, ContainerInfo importDestinationContainer, bool importSubOu)
{
try
{
using (Runtime.ConnectionsService.BatchedSavingContext())
{
ActiveDirectoryImporter.Import(ldapPath, importDestinationContainer, importSubOu);
}
ActiveDirectoryImporter.Import(ldapPath, importDestinationContainer, importSubOu);
ConnectionsService.SaveConnectionsAsync();
}
catch (Exception ex)
{
@@ -89,15 +83,13 @@ namespace mRemoteNG.App
}
}
public static void ImportFromPortScan(IEnumerable<ScanHost> hosts, ProtocolType protocol, ContainerInfo importDestinationContainer)
public void ImportFromPortScan(IEnumerable<ScanHost> hosts, ProtocolType protocol, ContainerInfo importDestinationContainer)
{
try
{
using (Runtime.ConnectionsService.BatchedSavingContext())
{
var importer = new PortScanImporter(protocol);
importer.Import(hosts, importDestinationContainer);
}
var importer = new PortScanImporter(protocol);
importer.Import(hosts, importDestinationContainer);
ConnectionsService.SaveConnectionsAsync();
}
catch (Exception ex)
{
@@ -105,14 +97,14 @@ namespace mRemoteNG.App
}
}
private static IConnectionImporter<string> BuildConnectionImporterFromFileExtension(string fileName)
private IConnectionImporter<string> BuildConnectionImporterFromFileExtension(string fileName)
{
// TODO: Use the file contents to determine the file type instead of trusting the extension
var extension = Path.GetExtension(fileName) ?? "";
switch (extension.ToLowerInvariant())
{
case ".xml":
return new MRemoteNGXmlImporter();
return new MRemoteNGXmlImporter(ConnectionsService, _dialogWindowParent);
case ".csv":
return new MRemoteNGCsvImporter();
case ".rdp":

View File

@@ -2,15 +2,14 @@
using System.IO;
using System.Reflection;
using System.Windows.Forms;
using mRemoteNG.Connection;
namespace mRemoteNG.App.Info
{
public static class SettingsFileInfo
{
private static readonly string ExePath = Path.GetDirectoryName(Assembly.GetAssembly(typeof(ConnectionInfo))?.Location);
private static readonly string ExePath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
public static string SettingsPath => Runtime.IsPortableEdition ? ExePath : Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\" + Application.ProductName;
public static string SettingsPath { get; } = Runtime.IsPortableEdition ? ExePath : Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\" + Application.ProductName;
public static string LayoutFileName { get; } = "pnlLayout.xml";
public static string ExtAppsFilesName { get; } = "extApps.xml";
public static string ThemesFileName { get; } = "Themes.xml";

View File

@@ -1,18 +1,24 @@
using System.IO;
using mRemoteNG.Config.Connections;
using mRemoteNG.Connection;
using mRemoteNG.Tools;
using System.IO;
namespace mRemoteNG.App.Initialization
{
public class CredsAndConsSetup
{
public void LoadCredsAndCons()
public class CredsAndConsSetup
{
private readonly IConnectionsService _connectionsService;
public CredsAndConsSetup(IConnectionsService connectionsService)
{
_connectionsService = connectionsService.ThrowIfNull(nameof(connectionsService));
}
public void LoadCredsAndCons()
{
new SaveConnectionsOnEdit(Runtime.ConnectionsService);
if (Settings.Default.FirstStart && !Settings.Default.LoadConsFromCustomLocation && !File.Exists(_connectionsService.GetStartupConnectionFileName()))
_connectionsService.NewConnectionsFile(_connectionsService.GetStartupConnectionFileName());
if (Settings.Default.FirstStart && !Settings.Default.LoadConsFromCustomLocation && !File.Exists(Runtime.ConnectionsService.GetStartupConnectionFileName()))
Runtime.ConnectionsService.NewConnectionsFile(Runtime.ConnectionsService.GetStartupConnectionFileName());
Runtime.LoadConnections();
_connectionsService.LoadConnections();
}
}
}

View File

@@ -3,10 +3,13 @@ using System.Linq;
using mRemoteNG.Messages;
using mRemoteNG.Messages.MessageWriters;
using mRemoteNG.Messages.WriterDecorators;
using mRemoteNG.Tools;
using mRemoteNG.UI.Forms;
using mRemoteNG.UI.Window;
namespace mRemoteNG.App.Initialization
{
public class MessageCollectorSetup
public class MessageCollectorSetup
{
public static void SetupMessageCollector(MessageCollector messageCollector, IList<IMessageWriter> messageWriterList)
{
@@ -19,13 +22,13 @@ namespace mRemoteNG.App.Initialization
};
}
public static void BuildMessageWritersFromSettings(IList<IMessageWriter> messageWriterList)
public static void BuildMessageWritersFromSettings(IList<IMessageWriter> messageWriterList, FrmMain frmMain, ErrorAndInfoWindow errorAndInfoWindow)
{
#if DEBUG
messageWriterList.Add(BuildDebugConsoleWriter());
#endif
messageWriterList.Add(BuildTextLogMessageWriter());
messageWriterList.Add(BuildNotificationPanelMessageWriter());
messageWriterList.Add(BuildNotificationPanelMessageWriter(frmMain, errorAndInfoWindow));
messageWriterList.Add(BuildPopupMessageWriter());
}
@@ -42,16 +45,17 @@ namespace mRemoteNG.App.Initialization
);
}
private static IMessageWriter BuildNotificationPanelMessageWriter()
private static IMessageWriter BuildNotificationPanelMessageWriter(FrmMain frmMain, ErrorAndInfoWindow errorAndInfoWindow)
{
return new OnlyLogMessageFilter(
errorAndInfoWindow.ThrowIfNull(nameof(errorAndInfoWindow));
return new OnlyLogMessageFilter(
new MessageTypeFilterDecorator(
new NotificationPanelMessageFilteringOptions(),
new MessageFocusDecorator(
Windows.ErrorsForm,
frmMain,
errorAndInfoWindow,
new NotificationPanelSwitchOnMessageFilteringOptions(),
new NotificationPanelMessageWriter(Windows.ErrorsForm)
new NotificationPanelMessageWriter(errorAndInfoWindow)
)
)
);

View File

@@ -26,7 +26,8 @@ namespace mRemoteNG.App
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(FrmMain.Default);
var frmMain = new FrmMain();
Application.Run(frmMain);
}
public static void CloseSingletonInstanceMutex()

View File

@@ -1,24 +1,11 @@
using mRemoteNG.App.Info;
using mRemoteNG.Config.Putty;
using mRemoteNG.Connection;
using mRemoteNG.Credential;
using mRemoteNG.Credential.Repositories;
using mRemoteNG.Messages;
using mRemoteNG.Security;
using mRemoteNG.Tools;
using mRemoteNG.Tree.Root;
using mRemoteNG.UI;
using mRemoteNG.UI.Forms;
using mRemoteNG.UI.TaskDialog;
using System;
using System.IO;
using System.Security;
using System.Threading;
using System.Windows.Forms;
namespace mRemoteNG.App
{
public static class Runtime
public class Runtime
{
public static bool IsPortableEdition
{
@@ -32,158 +19,7 @@ namespace mRemoteNG.App
}
}
public static WindowList WindowList { get; set; }
public static MessageCollector MessageCollector { get; } = new MessageCollector();
public static NotificationAreaIcon NotificationAreaIcon { get; set; }
public static ExternalToolsService ExternalToolsService { get; } = new ExternalToolsService();
public static SecureString EncryptionKey { get; set; } = new RootNodeInfo(RootNodeType.Connection).PasswordString.ConvertToSecureString();
public static ICredentialRepositoryList CredentialProviderCatalog { get; } = new CredentialRepositoryList();
public static ConnectionsService ConnectionsService { get; } = new ConnectionsService(PuttySessionsManager.Instance);
#region Connections Loading/Saving
public static void LoadConnectionsAsync()
{
var t = new Thread(LoadConnectionsBGd);
t.SetApartmentState(ApartmentState.STA);
t.Start();
}
private static void LoadConnectionsBGd()
{
LoadConnections();
}
/// <summary>
///
/// </summary>
/// <param name="withDialog">
/// Should we show the file selection dialog to allow the user to select
/// a connection file
/// </param>
public static void LoadConnections(bool withDialog = false)
{
var connectionFileName = "";
try
{
// disable sql update checking while we are loading updates
ConnectionsService.RemoteConnectionsSyncronizer?.Disable();
if (withDialog)
{
var loadDialog = DialogFactory.BuildLoadConnectionsDialog();
if (loadDialog.ShowDialog() != DialogResult.OK)
return;
connectionFileName = loadDialog.FileName;
Settings.Default.UseSQLServer = false;
Settings.Default.Save();
}
else if (!Settings.Default.UseSQLServer)
{
connectionFileName = ConnectionsService.GetStartupConnectionFileName();
}
ConnectionsService.LoadConnections(Settings.Default.UseSQLServer, false, connectionFileName);
if (Settings.Default.UseSQLServer)
{
ConnectionsService.LastSqlUpdate = DateTime.Now;
}
// re-enable sql update checking after updates are loaded
ConnectionsService.RemoteConnectionsSyncronizer?.Enable();
}
catch (Exception ex)
{
if (Settings.Default.UseSQLServer)
{
MessageCollector.AddExceptionMessage(Language.strLoadFromSqlFailed, ex);
var commandButtons = string.Join("|", Language.strCommandTryAgain, Language.strCommandOpenConnectionFile, string.Format(Language.strCommandExitProgram, Application.ProductName));
CTaskDialog.ShowCommandBox(Application.ProductName, Language.strLoadFromSqlFailed, Language.strLoadFromSqlFailedContent, MiscTools.GetExceptionMessageRecursive(ex), "", "", commandButtons, false, ESysIcons.Error, ESysIcons.Error);
switch (CTaskDialog.CommandButtonResult)
{
case 0:
LoadConnections(withDialog);
return;
case 1:
Settings.Default.UseSQLServer = false;
LoadConnections(true);
return;
default:
Application.Exit();
return;
}
}
if (ex is FileNotFoundException && !withDialog)
{
MessageCollector.AddExceptionMessage(string.Format(Language.strConnectionsFileCouldNotBeLoadedNew, connectionFileName), ex, MessageClass.InformationMsg);
string[] commandButtons =
{
Language.ConfigurationCreateNew,
Language.ConfigurationCustomPath,
Language.ConfigurationImportFile,
Language.strMenuExit
};
var answered = false;
while (!answered)
{
try
{
CTaskDialog.ShowTaskDialogBox(
GeneralAppInfo.ProductName,
Language.ConnectionFileNotFound,
"", "", "", "", "",
string.Join(" | ", commandButtons),
ETaskDialogButtons.None,
ESysIcons.Question,
ESysIcons.Question);
switch (CTaskDialog.CommandButtonResult)
{
case 0:
ConnectionsService.NewConnectionsFile(connectionFileName);
answered = true;
break;
case 1:
LoadConnections(true);
answered = true;
break;
case 2:
ConnectionsService.NewConnectionsFile(connectionFileName);
Import.ImportFromFile(ConnectionsService.ConnectionTreeModel.RootNodes[0]);
answered = true;
break;
case 3:
Application.Exit();
answered = true;
break;
}
}
catch (Exception exc)
{
MessageCollector.AddExceptionMessage(string.Format(Language.strConnectionsFileCouldNotBeLoadedNew, connectionFileName), exc, MessageClass.InformationMsg);
}
}
return;
}
MessageCollector.AddExceptionStackTrace(string.Format(Language.strConnectionsFileCouldNotBeLoaded, connectionFileName), ex);
if (connectionFileName != ConnectionsService.GetStartupConnectionFileName())
{
LoadConnections(withDialog);
}
else
{
MessageBox.Show(FrmMain.Default,
string.Format(Language.strErrorStartupConnectionFileLoad, Environment.NewLine, Application.ProductName, ConnectionsService.GetStartupConnectionFileName(), MiscTools.GetExceptionMessageRecursive(ex)),
@"Could not load startup file.", MessageBoxButtons.OK, MessageBoxIcon.Error);
Application.Exit();
}
}
}
#endregion
}
}

View File

@@ -1,31 +1,38 @@
using System.Windows.Forms;
using mRemoteNG.Tools;
using mRemoteNG.UI.Forms;
using WeifenLuo.WinFormsUI.Docking;
namespace mRemoteNG.App
{
public static class Screens
public class Screens
{
public static void SendFormToScreen(Screen screen)
private readonly FrmMain _frmMain;
public Screens(FrmMain frmMain)
{
_frmMain = frmMain.ThrowIfNull(nameof(frmMain));
}
public void SendFormToScreen(Screen screen)
{
var frmMain = FrmMain.Default;
var wasMax = false;
if (frmMain.WindowState == FormWindowState.Maximized)
if (_frmMain.WindowState == FormWindowState.Maximized)
{
wasMax = true;
frmMain.WindowState = FormWindowState.Normal;
_frmMain.WindowState = FormWindowState.Normal;
}
frmMain.Location = screen.Bounds.Location;
_frmMain.Location = screen.Bounds.Location;
if (wasMax)
{
frmMain.WindowState = FormWindowState.Maximized;
_frmMain.WindowState = FormWindowState.Maximized;
}
}
public static void SendPanelToScreen(DockContent panel, Screen screen)
public void SendPanelToScreen(DockContent panel, Screen screen)
{
panel.DockState = DockState.Float;
if (panel.ParentForm == null) return;

View File

@@ -3,29 +3,41 @@ using System;
using System.Diagnostics;
using System.Windows.Forms;
using mRemoteNG.Config.Putty;
using mRemoteNG.Config.Settings;
using mRemoteNG.Connection;
using mRemoteNG.UI.Controls;
using mRemoteNG.UI.Forms;
// ReSharper disable ArrangeAccessorOwnerBody
namespace mRemoteNG.App
{
public static class Shutdown
public class Shutdown
{
private readonly SettingsSaver _settingsSaver;
private readonly IConnectionsService _connectionsService;
private readonly FrmMain _frmMain;
private static string _updateFilePath;
public Shutdown(SettingsSaver settingsSaver, IConnectionsService connectionsService, FrmMain frmMain)
{
_settingsSaver = settingsSaver.ThrowIfNull(nameof(settingsSaver));
_connectionsService = connectionsService.ThrowIfNull(nameof(connectionsService));
_frmMain = frmMain.ThrowIfNull(nameof(frmMain));
}
private static bool UpdatePending
{
get { return !string.IsNullOrEmpty(_updateFilePath); }
}
public static void Quit(string updateFilePath = null)
public void Quit(string updateFilePath = null)
{
_updateFilePath = updateFilePath;
FrmMain.Default.Close();
_frmMain.Close();
ProgramRoot.CloseSingletonInstanceMutex();
}
public static void Cleanup(Control quickConnectToolStrip, ExternalToolsToolStrip externalToolsToolStrip, MultiSshToolStrip multiSshToolStrip, FrmMain frmMain)
public void Cleanup(Control quickConnectToolStrip, ExternalToolsToolStrip externalToolsToolStrip, MultiSshToolStrip multiSshToolStrip, FrmMain frmMain)
{
try
{
@@ -41,34 +53,34 @@ namespace mRemoteNG.App
}
}
private static void StopPuttySessionWatcher()
private void StopPuttySessionWatcher()
{
PuttySessionsManager.Instance.StopWatcher();
}
private static void DisposeNotificationAreaIcon()
private void DisposeNotificationAreaIcon()
{
if (Runtime.NotificationAreaIcon != null && Runtime.NotificationAreaIcon.Disposed == false)
Runtime.NotificationAreaIcon.Dispose();
}
private static void SaveConnections()
private void SaveConnections()
{
if (Settings.Default.SaveConsOnExit)
Runtime.ConnectionsService.SaveConnections();
_connectionsService.SaveConnections();
}
private static void SaveSettings(Control quickConnectToolStrip, ExternalToolsToolStrip externalToolsToolStrip, MultiSshToolStrip multiSshToolStrip, FrmMain frmMain)
private void SaveSettings(Control quickConnectToolStrip, ExternalToolsToolStrip externalToolsToolStrip, MultiSshToolStrip multiSshToolStrip, FrmMain frmMain)
{
Config.Settings.SettingsSaver.SaveSettings(quickConnectToolStrip, externalToolsToolStrip, multiSshToolStrip, frmMain);
_settingsSaver.SaveSettings(quickConnectToolStrip, externalToolsToolStrip, multiSshToolStrip, frmMain);
}
private static void UnregisterBrowsers()
private void UnregisterBrowsers()
{
IeBrowserEmulation.Unregister();
}
public static void StartUpdate()
public void StartUpdate()
{
try
{
@@ -80,7 +92,7 @@ namespace mRemoteNG.App
}
}
private static void RunUpdateFile()
private void RunUpdateFile()
{
if (UpdatePending)
Process.Start(_updateFilePath);

View File

@@ -7,6 +7,7 @@ using mRemoteNG.App.Initialization;
using mRemoteNG.App.Update;
using mRemoteNG.Config.Connections;
using mRemoteNG.Config.Connections.Multiuser;
using mRemoteNG.Config.DatabaseConnectors;
using mRemoteNG.Connection;
using mRemoteNG.Messages;
using mRemoteNG.Tools;
@@ -17,30 +18,34 @@ using mRemoteNG.UI.Forms;
namespace mRemoteNG.App
{
public class Startup
public class Startup
{
private AppUpdater _appUpdate;
private readonly AppUpdater _appUpdate;
private readonly ConnectionIconLoader _connectionIconLoader;
private readonly FrmMain _frmMain = FrmMain.Default;
private readonly FrmMain _frmMain;
private readonly Windows _windows;
private readonly IConnectionsService _connectionsService;
private readonly DatabaseConnectorFactory _databaseConnectorFactory;
private readonly CompatibilityChecker _compatibilityChecker;
public static Startup Instance { get; } = new Startup();
private Startup()
public Startup(FrmMain frmMain, Windows windows, IConnectionsService connectionsService,
AppUpdater appUpdate, DatabaseConnectorFactory databaseConnectorFactory, CompatibilityChecker compatibilityChecker)
{
_appUpdate = new AppUpdater();
_frmMain = frmMain.ThrowIfNull(nameof(frmMain));
_windows = windows.ThrowIfNull(nameof(windows));
_connectionsService = connectionsService.ThrowIfNull(nameof(connectionsService));
_appUpdate = appUpdate.ThrowIfNull(nameof(appUpdate));
_databaseConnectorFactory = databaseConnectorFactory.ThrowIfNull(nameof(databaseConnectorFactory));
_compatibilityChecker = compatibilityChecker.ThrowIfNull(nameof(compatibilityChecker));
_connectionIconLoader = new ConnectionIconLoader(GeneralAppInfo.HomePath + "\\Icons\\");
}
static Startup()
{
}
public void InitializeProgram(MessageCollector messageCollector)
{
Debug.Print("---------------------------" + Environment.NewLine + "[START] - " + Convert.ToString(DateTime.Now, CultureInfo.InvariantCulture));
var startupLogger = new StartupDataLogger(messageCollector);
startupLogger.LogStartupData();
CompatibilityChecker.CheckCompatibility(messageCollector);
_compatibilityChecker.CheckCompatibility();
ParseCommandLineArgs(messageCollector);
IeBrowserEmulation.Register();
_connectionIconLoader.GetConnectionIcons();
@@ -59,17 +64,14 @@ namespace mRemoteNG.App
messageCollector.AddMessage(MessageClass.DebugMsg, "Determining if we need a database syncronizer");
if (!Settings.Default.UseSQLServer) return;
messageCollector.AddMessage(MessageClass.DebugMsg, "Creating database syncronizer");
Runtime.ConnectionsService.RemoteConnectionsSyncronizer = new RemoteConnectionsSyncronizer(new SqlConnectionsUpdateChecker());
Runtime.ConnectionsService.RemoteConnectionsSyncronizer.Enable();
var sqlConnectionsUpdateChecker = new SqlConnectionsUpdateChecker(_connectionsService, _databaseConnectorFactory);
_connectionsService.RemoteConnectionsSyncronizer = new RemoteConnectionsSyncronizer(sqlConnectionsUpdateChecker, _connectionsService);
_connectionsService.RemoteConnectionsSyncronizer.Enable();
}
public void CheckForUpdate()
{
if (_appUpdate == null)
{
_appUpdate = new AppUpdater();
}
else if (_appUpdate.IsGetUpdateInfoRunning)
if (_appUpdate.IsGetUpdateInfoRunning)
{
return;
}
@@ -107,7 +109,7 @@ namespace mRemoteNG.App
if (_appUpdate.IsUpdateAvailable())
{
Windows.Show(WindowType.Update);
_windows.Show(WindowType.Update);
}
}
catch (Exception ex)

View File

@@ -4,6 +4,7 @@ using System.Net;
using System.ComponentModel;
using System.Threading;
using System.Reflection;
using System.Security;
using mRemoteNG.App.Info;
using mRemoteNG.Security.SymmetricEncryption;
using System.Security.Cryptography;
@@ -22,6 +23,7 @@ namespace mRemoteNG.App.Update
private WebProxy _webProxy;
private Thread _getUpdateInfoThread;
private Thread _getChangeLogThread;
private readonly Func<SecureString> _encryptionKeyRetrievalFunc;
#region Public Properties
@@ -48,8 +50,9 @@ namespace mRemoteNG.App.Update
#region Public Methods
public AppUpdater()
public AppUpdater(Func<SecureString> encryptionKeyRetrievalFunc)
{
_encryptionKeyRetrievalFunc = encryptionKeyRetrievalFunc;
SetProxySettings();
}
@@ -61,7 +64,7 @@ namespace mRemoteNG.App.Update
var useAuthentication = Settings.Default.UpdateProxyUseAuthentication;
var username = Settings.Default.UpdateProxyAuthUser;
var cryptographyProvider = new LegacyRijndaelCryptographyProvider();
var password = cryptographyProvider.Decrypt(Settings.Default.UpdateProxyAuthPass, Runtime.EncryptionKey);
var password = cryptographyProvider.Decrypt(Settings.Default.UpdateProxyAuthPass, _encryptionKeyRetrievalFunc());
SetProxySettings(shouldWeUseProxy, proxyAddress, port, useAuthentication, username, password);
}

View File

@@ -1,94 +1,134 @@
using System;
using mRemoteNG.App.Update;
using mRemoteNG.Config.DatabaseConnectors;
using mRemoteNG.Connection;
using mRemoteNG.Messages;
using mRemoteNG.Tools;
using mRemoteNG.UI;
using mRemoteNG.UI.Forms;
using mRemoteNG.UI.Window;
using WeifenLuo.WinFormsUI.Docking;
namespace mRemoteNG.App
{
public static class Windows
public class Windows
{
private static AboutWindow _aboutForm;
private static ActiveDirectoryImportWindow _adimportForm;
private static HelpWindow _helpForm;
private static ExternalToolsWindow _externalappsForm;
private static PortScanWindow _portscanForm;
private static UltraVNCWindow _ultravncscForm;
private static ComponentsCheckWindow _componentscheckForm;
private static ConnectionTreeWindow _treeForm;
private readonly IConnectionInitiator _connectionInitiator;
private AboutWindow _aboutForm;
private ActiveDirectoryImportWindow _adimportForm;
private HelpWindow _helpForm;
private ExternalToolsWindow _externalappsForm;
private PortScanWindow _portscanForm;
private UltraVNCWindow _ultravncscForm;
private ComponentsCheckWindow _componentscheckForm;
private UpdateWindow _updateForm;
private readonly Func<UpdateWindow> _updateWindowBuilder;
private readonly Func<NotificationAreaIcon> _notificationAreaIconBuilder;
private readonly Func<ExternalToolsWindow> _externalToolsWindowBuilder;
private readonly Func<PortScanWindow> _portScanWindowBuilder;
private readonly Func<ActiveDirectoryImportWindow> _activeDirectoryImportWindowBuilder;
private readonly IConnectionsService _connectionsService;
private readonly AppUpdater _appUpdater;
private readonly DatabaseConnectorFactory _databaseConnectorFactory;
private readonly FrmMain _frmMain;
internal static ConnectionTreeWindow TreeForm
internal ConnectionTreeWindow TreeForm { get; }
internal ConfigWindow ConfigForm { get; }
internal ErrorAndInfoWindow ErrorsForm { get; }
internal ScreenshotManagerWindow ScreenshotForm { get; }
internal SSHTransferWindow SshtransferForm { get; private set; }
public Windows(
IConnectionInitiator connectionInitiator,
ConnectionTreeWindow treeForm,
ConfigWindow configForm,
ErrorAndInfoWindow errorAndInfoWindow,
ScreenshotManagerWindow screenshotForm,
SSHTransferWindow sshtransferForm,
Func<UpdateWindow> updateWindowBuilder,
Func<NotificationAreaIcon> notificationAreaIconBuilder,
Func<ExternalToolsWindow> externalToolsWindowBuilder,
IConnectionsService connectionsService,
Func<PortScanWindow> portScanWindowBuilder,
Func<ActiveDirectoryImportWindow> activeDirectoryImportWindowBuilder,
AppUpdater appUpdater,
DatabaseConnectorFactory databaseConnectorFactory,
FrmMain frmMain)
{
get => _treeForm ?? (_treeForm = new ConnectionTreeWindow());
set => _treeForm = value;
_connectionInitiator = connectionInitiator.ThrowIfNull(nameof(connectionInitiator));
TreeForm = treeForm.ThrowIfNull(nameof(treeForm));
ConfigForm = configForm.ThrowIfNull(nameof(configForm));
ErrorsForm = errorAndInfoWindow.ThrowIfNull(nameof(errorAndInfoWindow));
ScreenshotForm = screenshotForm.ThrowIfNull(nameof(screenshotForm));
SshtransferForm = sshtransferForm.ThrowIfNull(nameof(sshtransferForm));
_updateWindowBuilder = updateWindowBuilder;
_notificationAreaIconBuilder = notificationAreaIconBuilder;
_externalToolsWindowBuilder = externalToolsWindowBuilder;
_portScanWindowBuilder = portScanWindowBuilder;
_activeDirectoryImportWindowBuilder = activeDirectoryImportWindowBuilder;
_frmMain = frmMain;
_databaseConnectorFactory = databaseConnectorFactory.ThrowIfNull(nameof(databaseConnectorFactory));
_appUpdater = appUpdater.ThrowIfNull(nameof(appUpdater));
_connectionsService = connectionsService.ThrowIfNull(nameof(connectionsService));
}
internal static ConfigWindow ConfigForm { get; set; } = new ConfigWindow();
internal static ErrorAndInfoWindow ErrorsForm { get; set; } = new ErrorAndInfoWindow();
internal static ScreenshotManagerWindow ScreenshotForm { get; set; } = new ScreenshotManagerWindow();
private static UpdateWindow UpdateForm { get; set; } = new UpdateWindow();
internal static SSHTransferWindow SshtransferForm { get; private set; } = new SSHTransferWindow();
public static void Show(WindowType windowType)
public void Show(WindowType windowType)
{
try
{
var dockPanel = FrmMain.Default.pnlDock;
// ReSharper disable once SwitchStatementMissingSomeCases
switch (windowType)
{
case WindowType.About:
if (_aboutForm == null || _aboutForm.IsDisposed)
_aboutForm = new AboutWindow();
_aboutForm.Show(dockPanel);
_aboutForm.Show(_frmMain.pnlDock);
break;
case WindowType.ActiveDirectoryImport:
if (_adimportForm == null || _adimportForm.IsDisposed)
_adimportForm = new ActiveDirectoryImportWindow();
_adimportForm.Show(dockPanel);
_adimportForm = _activeDirectoryImportWindowBuilder();
_adimportForm.Show(_frmMain.pnlDock);
break;
case WindowType.Options:
using (var optionsForm = new frmOptions())
using (var optionsForm = new frmOptions(_connectionInitiator, Show, _notificationAreaIconBuilder, _connectionsService, _appUpdater, _databaseConnectorFactory, _frmMain))
{
optionsForm.ShowDialog(dockPanel);
optionsForm.ShowDialog(_frmMain);
}
break;
case WindowType.SSHTransfer:
if (SshtransferForm == null || SshtransferForm.IsDisposed)
SshtransferForm = new SSHTransferWindow();
SshtransferForm.Show(dockPanel);
SshtransferForm = new SSHTransferWindow(_frmMain);
SshtransferForm.Show(_frmMain.pnlDock);
break;
case WindowType.Update:
if (UpdateForm == null || UpdateForm.IsDisposed)
UpdateForm = new UpdateWindow();
UpdateForm.Show(dockPanel);
if (_updateForm == null || _updateForm.IsDisposed)
_updateForm = _updateWindowBuilder();
_updateForm.Show(_frmMain.pnlDock);
break;
case WindowType.Help:
if (_helpForm == null || _helpForm.IsDisposed)
_helpForm = new HelpWindow();
_helpForm.Show(dockPanel);
_helpForm.Show(_frmMain.pnlDock);
break;
case WindowType.ExternalApps:
if (_externalappsForm == null || _externalappsForm.IsDisposed)
_externalappsForm = new ExternalToolsWindow();
_externalappsForm.Show(dockPanel);
_externalappsForm = _externalToolsWindowBuilder();
_externalappsForm.Show(_frmMain.pnlDock);
break;
case WindowType.PortScan:
_portscanForm = new PortScanWindow();
_portscanForm.Show(dockPanel);
_portscanForm = _portScanWindowBuilder();
_portscanForm.Show(_frmMain.pnlDock);
break;
case WindowType.UltraVNCSC:
if (_ultravncscForm == null || _ultravncscForm.IsDisposed)
_ultravncscForm = new UltraVNCWindow();
_ultravncscForm.Show(dockPanel);
_ultravncscForm = new UltraVNCWindow(Show);
_ultravncscForm.Show(_frmMain.pnlDock);
break;
case WindowType.ComponentsCheck:
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, "Showing ComponentsCheck window", true);
if (_componentscheckForm == null || _componentscheckForm.IsDisposed)
_componentscheckForm = new ComponentsCheckWindow();
_componentscheckForm.Show(dockPanel);
_componentscheckForm.Show(_frmMain.pnlDock);
break;
}
}
@@ -98,4 +138,4 @@ namespace mRemoteNG.App
}
}
}
}
}

View File

@@ -1,9 +1,8 @@
using System;
using mRemoteNG.App;
using mRemoteNG.Config.DataProviders;
using mRemoteNG.Config.Serializers;
using mRemoteNG.Config.DataProviders;
using mRemoteNG.Config.Serializers.Csv;
using mRemoteNG.Credential;
using mRemoteNG.Security;
using mRemoteNG.Tools;
using mRemoteNG.Tree;
namespace mRemoteNG.Config.Connections
@@ -12,21 +11,18 @@ namespace mRemoteNG.Config.Connections
{
private readonly string _connectionFileName;
private readonly SaveFilter _saveFilter;
private readonly ICredentialRepositoryList _credentialRepositoryList;
public CsvConnectionsSaver(string connectionFileName, SaveFilter saveFilter)
public CsvConnectionsSaver(string connectionFileName, SaveFilter saveFilter, ICredentialRepositoryList credentialRepositoryList)
{
if (string.IsNullOrEmpty(connectionFileName))
throw new ArgumentException($"Argument '{nameof(connectionFileName)}' cannot be null or empty");
if (saveFilter == null)
throw new ArgumentNullException(nameof(saveFilter));
_connectionFileName = connectionFileName;
_saveFilter = saveFilter;
_connectionFileName = connectionFileName.ThrowIfNullOrEmpty(nameof(connectionFileName));
_saveFilter = saveFilter.ThrowIfNull(nameof(saveFilter));
_credentialRepositoryList = credentialRepositoryList.ThrowIfNull(nameof(credentialRepositoryList));
}
public void Save(ConnectionTreeModel connectionTreeModel, string propertyNameTrigger = "")
public void Save(ConnectionTreeModel connectionTreeModel)
{
var csvConnectionsSerializer = new CsvConnectionsSerializerMremotengFormat(_saveFilter, Runtime.CredentialProviderCatalog);
var csvConnectionsSerializer = new CsvConnectionsSerializerMremotengFormat(_saveFilter, _credentialRepositoryList);
var dataProvider = new FileDataProvider(_connectionFileName);
var csvContent = csvConnectionsSerializer.Serialize(connectionTreeModel);
dataProvider.Save(csvContent);

View File

@@ -1,9 +0,0 @@
using mRemoteNG.Tree;
namespace mRemoteNG.Config.Connections
{
public interface IConnectionsLoader
{
ConnectionTreeModel Load();
}
}

View File

@@ -1,6 +1,7 @@
using mRemoteNG.App;
using System;
using System;
using System.Timers;
using mRemoteNG.Connection;
using mRemoteNG.Tools;
// ReSharper disable ArrangeAccessorOwnerBody
@@ -10,15 +11,17 @@ namespace mRemoteNG.Config.Connections.Multiuser
{
private readonly Timer _updateTimer;
private readonly IConnectionsUpdateChecker _updateChecker;
private readonly IConnectionsService _connectionsService;
public double TimerIntervalInMilliseconds
{
get { return _updateTimer.Interval; }
}
public RemoteConnectionsSyncronizer(IConnectionsUpdateChecker updateChecker)
public RemoteConnectionsSyncronizer(IConnectionsUpdateChecker updateChecker, IConnectionsService connectionsService)
{
_updateChecker = updateChecker;
_updateChecker = updateChecker.ThrowIfNull(nameof(updateChecker));
_connectionsService = connectionsService.ThrowIfNull(nameof(connectionsService));
_updateTimer = new Timer(3000);
SetEventListeners();
}
@@ -34,7 +37,7 @@ namespace mRemoteNG.Config.Connections.Multiuser
private void Load(object sender, ConnectionsUpdateAvailableEventArgs args)
{
Runtime.ConnectionsService.LoadConnections(true, false, "");
_connectionsService.LoadConnections(true, false, "");
args.Handled = true;
}

View File

@@ -1,11 +1,13 @@
using mRemoteNG.App;
using mRemoteNG.Config.Connections.Multiuser;
using mRemoteNG.Config.DatabaseConnectors;
using mRemoteNG.Messages;
using System;
using System.Data;
using System.Data.SqlClient;
using System.Threading;
using mRemoteNG.Config.Connections.Multiuser;
using mRemoteNG.Config.DatabaseConnectors;
using mRemoteNG.Connection;
using mRemoteNG.Tools;
namespace mRemoteNG.Config.Connections
{
@@ -13,14 +15,17 @@ namespace mRemoteNG.Config.Connections
{
private readonly SqlDatabaseConnector _sqlConnector;
private readonly SqlCommand _sqlQuery;
private DateTime LastUpdateTime => Runtime.ConnectionsService.LastSqlUpdate;
private readonly IConnectionsService _connectionsService;
private DateTime _lastUpdateTime;
private DateTime _lastDatabaseUpdateTime;
public SqlConnectionsUpdateChecker()
public SqlConnectionsUpdateChecker(IConnectionsService connectionsService, DatabaseConnectorFactory databaseConnectorFactory)
{
_sqlConnector = DatabaseConnectorFactory.SqlDatabaseConnectorFromSettings();
_connectionsService = connectionsService.ThrowIfNull(nameof(connectionsService));
databaseConnectorFactory.ThrowIfNull(nameof(databaseConnectorFactory));
_sqlConnector = databaseConnectorFactory.SqlDatabaseConnectorFromSettings();
_sqlQuery = new SqlCommand("SELECT * FROM tblUpdate", _sqlConnector.SqlConnection);
_lastUpdateTime = default(DateTime);
_lastDatabaseUpdateTime = default(DateTime);
}
@@ -57,14 +62,14 @@ namespace mRemoteNG.Config.Connections
private bool DatabaseIsMoreUpToDateThanUs()
{
var lastUpdateInDb = GetLastUpdateTimeFromDbResponse();
var amTheLastoneUpdated = CheckIfIAmTheLastOneUpdated(lastUpdateInDb);
return (lastUpdateInDb > LastUpdateTime && !amTheLastoneUpdated);
var IAmTheLastoneUpdated = CheckIfIAmTheLastOneUpdated(lastUpdateInDb);
return (lastUpdateInDb > _lastUpdateTime && !IAmTheLastoneUpdated);
}
private bool CheckIfIAmTheLastOneUpdated(DateTime lastUpdateInDb)
{
DateTime lastSqlUpdateWithoutMilliseconds = new DateTime(LastUpdateTime.Ticks - (LastUpdateTime.Ticks % TimeSpan.TicksPerSecond), LastUpdateTime.Kind);
return lastUpdateInDb == lastSqlUpdateWithoutMilliseconds;
DateTime LastSqlUpdateWithoutMilliseconds = new DateTime(_connectionsService.LastSqlUpdate.Ticks - (_connectionsService.LastSqlUpdate.Ticks % TimeSpan.TicksPerSecond), _connectionsService.LastSqlUpdate.Kind);
return lastUpdateInDb == LastSqlUpdateWithoutMilliseconds;
}
private DateTime GetLastUpdateTimeFromDbResponse()
@@ -103,9 +108,10 @@ namespace mRemoteNG.Config.Connections
public event ConnectionsUpdateAvailableEventHandler ConnectionsUpdateAvailable;
private void RaiseConnectionsUpdateAvailableEvent()
{
Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, "Remote connection update is available");
var args = new ConnectionsUpdateAvailableEventArgs(_sqlConnector, _lastDatabaseUpdateTime);
ConnectionsUpdateAvailable?.Invoke(this, args);
if(args.Handled)
_lastUpdateTime = _lastDatabaseUpdateTime;
}
public void Dispose()

View File

@@ -1,16 +1,17 @@
using System;
using mRemoteNG.Connection;
using System;
using System.Collections.Specialized;
using System.ComponentModel;
using mRemoteNG.Connection;
using mRemoteNG.UI.Forms;
namespace mRemoteNG.Config.Connections
{
public class SaveConnectionsOnEdit
{
private readonly ConnectionsService _connectionsService;
private readonly IConnectionsService _connectionsService;
public SaveConnectionsOnEdit(ConnectionsService connectionsService)
public bool Enabled { get; set; } = true;
public SaveConnectionsOnEdit(IConnectionsService connectionsService)
{
if (connectionsService == null)
throw new ArgumentNullException(nameof(connectionsService));
@@ -33,7 +34,7 @@ namespace mRemoteNG.Config.Connections
private void ConnectionTreeModelOnPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs)
{
SaveConnectionOnEdit(propertyChangedEventArgs.PropertyName);
SaveConnectionOnEdit();
}
private void ConnectionTreeModelOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs)
@@ -41,14 +42,15 @@ namespace mRemoteNG.Config.Connections
SaveConnectionOnEdit();
}
private void SaveConnectionOnEdit(string propertyName = "")
private void SaveConnectionOnEdit()
{
if (!mRemoteNG.Settings.Default.SaveConnectionsAfterEveryEdit)
return;
if (FrmMain.Default.IsClosing)
if (!Enabled)
return;
_connectionsService.SaveConnectionsAsync(propertyName);
_connectionsService.SaveConnectionsAsync();
}
}
}

View File

@@ -1,96 +1,33 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security;
using mRemoteNG.Config.DatabaseConnectors;
using mRemoteNG.Config.DatabaseConnectors;
using mRemoteNG.Config.DataProviders;
using mRemoteNG.Config.Serializers;
using mRemoteNG.Config.Serializers.MsSql;
using mRemoteNG.Config.Serializers.Versioning;
using mRemoteNG.Container;
using mRemoteNG.Security;
using mRemoteNG.Security.Authentication;
using mRemoteNG.Security.SymmetricEncryption;
using mRemoteNG.Connection;
using mRemoteNG.Tools;
using mRemoteNG.Tree;
using mRemoteNG.Tree.Root;
namespace mRemoteNG.Config.Connections
{
public class SqlConnectionsLoader : IConnectionsLoader
public class SqlConnectionsLoader
{
private readonly IDeserializer<string, IEnumerable<LocalConnectionPropertiesModel>> _localConnectionPropertiesDeserializer;
private readonly IDataProvider<string> _dataProvider;
private readonly DatabaseConnectorFactory _databaseConnectorFactory;
private readonly IConnectionsService _connectionsService;
public Func<Optional<SecureString>> AuthenticationRequestor { get; set; } =
() => MiscTools.PasswordDialog("", false);
public SqlConnectionsLoader(
IDeserializer<string, IEnumerable<LocalConnectionPropertiesModel>> localConnectionPropertiesDeserializer,
IDataProvider<string> dataProvider)
public SqlConnectionsLoader(DatabaseConnectorFactory databaseConnectorFactory, IConnectionsService connectionsService)
{
_localConnectionPropertiesDeserializer = localConnectionPropertiesDeserializer.ThrowIfNull(nameof(localConnectionPropertiesDeserializer));
_dataProvider = dataProvider.ThrowIfNull(nameof(dataProvider));
_databaseConnectorFactory = databaseConnectorFactory.ThrowIfNull(nameof(databaseConnectorFactory));
_connectionsService = connectionsService.ThrowIfNull(nameof(connectionsService));
}
public ConnectionTreeModel Load()
{
var connector = DatabaseConnectorFactory.SqlDatabaseConnectorFromSettings();
var connector = _databaseConnectorFactory.SqlDatabaseConnectorFromSettings();
var dataProvider = new SqlDataProvider(connector);
var metaDataRetriever = new SqlDatabaseMetaDataRetriever();
var databaseVersionVerifier = new SqlDatabaseVersionVerifier(connector);
var cryptoProvider = new LegacyRijndaelCryptographyProvider();
var metaData = metaDataRetriever.GetDatabaseMetaData(connector) ??
HandleFirstRun(metaDataRetriever, connector);
var decryptionKey = GetDecryptionKey(metaData);
if (!decryptionKey.Any())
throw new Exception("Could not load SQL connections");
databaseVersionVerifier.VerifyDatabaseVersion(metaData.ConfVersion);
databaseVersionVerifier.VerifyDatabaseVersion();
var dataTable = dataProvider.Load();
var deserializer = new DataTableDeserializer(cryptoProvider, decryptionKey.First());
var connectionTree = deserializer.Deserialize(dataTable);
ApplyLocalConnectionProperties(connectionTree.RootNodes.First(i => i is RootNodeInfo));
return connectionTree;
var deserializer = new DataTableDeserializer(_connectionsService);
return deserializer.Deserialize(dataTable);
}
private Optional<SecureString> GetDecryptionKey(SqlConnectionListMetaData metaData)
{
var cryptographyProvider = new LegacyRijndaelCryptographyProvider();
var cipherText = metaData.Protected;
var authenticator = new PasswordAuthenticator(cryptographyProvider, cipherText, AuthenticationRequestor);
var authenticated = authenticator.Authenticate(new RootNodeInfo(RootNodeType.Connection).DefaultPassword.ConvertToSecureString());
if (authenticated)
return authenticator.LastAuthenticatedPassword;
return Optional<SecureString>.Empty;
}
private void ApplyLocalConnectionProperties(ContainerInfo rootNode)
{
var localPropertiesXml = _dataProvider.Load();
var localConnectionProperties = _localConnectionPropertiesDeserializer.Deserialize(localPropertiesXml);
rootNode
.GetRecursiveChildList()
.Join(localConnectionProperties,
con => con.ConstantID,
locals => locals.ConnectionId,
(con, locals) => new {Connection = con, LocalProperties = locals})
.ForEach(x =>
{
x.Connection.PleaseConnect = x.LocalProperties.Connected;
if (x.Connection is ContainerInfo container)
container.IsExpanded = x.LocalProperties.Expanded;
});
}
private SqlConnectionListMetaData HandleFirstRun(SqlDatabaseMetaDataRetriever metaDataRetriever, SqlDatabaseConnector connector)
{
metaDataRetriever.WriteDatabaseMetaData(new RootNodeInfo(RootNodeType.Connection), connector);
return metaDataRetriever.GetDatabaseMetaData(connector);
}
}
}

View File

@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Globalization;
using System.Linq;
@@ -8,7 +7,6 @@ using mRemoteNG.App.Info;
using mRemoteNG.Config.DatabaseConnectors;
using mRemoteNG.Config.DataProviders;
using mRemoteNG.Config.Serializers;
using mRemoteNG.Config.Serializers.MsSql;
using mRemoteNG.Config.Serializers.Versioning;
using mRemoteNG.Connection;
using mRemoteNG.Container;
@@ -21,90 +19,45 @@ using mRemoteNG.Tree.Root;
namespace mRemoteNG.Config.Connections
{
public class SqlConnectionsSaver : ISaver<ConnectionTreeModel>
public class SqlConnectionsSaver : ISaver<ConnectionTreeModel>
{
private readonly IConnectionsService _connectionsService;
private readonly SaveFilter _saveFilter;
private readonly ISerializer<IEnumerable<LocalConnectionPropertiesModel>, string> _localPropertiesSerializer;
private readonly IDataProvider<string> _dataProvider;
private readonly DatabaseConnectorFactory _databaseConnectorFactory;
public SqlConnectionsSaver(
SaveFilter saveFilter,
ISerializer<IEnumerable<LocalConnectionPropertiesModel>, string> localPropertieSerializer,
IDataProvider<string> localPropertiesDataProvider)
public SqlConnectionsSaver(SaveFilter saveFilter, IConnectionsService connectionsService, DatabaseConnectorFactory databaseConnectorFactory)
{
if (saveFilter == null)
throw new ArgumentNullException(nameof(saveFilter));
_saveFilter = saveFilter;
_localPropertiesSerializer = localPropertieSerializer.ThrowIfNull(nameof(localPropertieSerializer));
_dataProvider = localPropertiesDataProvider.ThrowIfNull(nameof(localPropertiesDataProvider));
_saveFilter = saveFilter.ThrowIfNull(nameof(saveFilter));
_databaseConnectorFactory = databaseConnectorFactory.ThrowIfNull(nameof(databaseConnectorFactory));
_connectionsService = connectionsService.ThrowIfNull(nameof(connectionsService));
}
public void Save(ConnectionTreeModel connectionTreeModel, string propertyNameTrigger = "")
public void Save(ConnectionTreeModel connectionTreeModel)
{
var rootTreeNode = connectionTreeModel.RootNodes.OfType<RootNodeInfo>().First();
UpdateLocalConnectionProperties(rootTreeNode);
if (PropertyIsLocalOnly(propertyNameTrigger))
{
Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg,
$"Property {propertyNameTrigger} is local only. Not saving to database.");
return;
}
if (SqlUserIsReadOnly())
{
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, "Trying to save connection tree but the SQL read only checkbox is checked, aborting!");
return;
}
using (var sqlConnector = DatabaseConnectorFactory.SqlDatabaseConnectorFromSettings())
using (var sqlConnector = _databaseConnectorFactory.SqlDatabaseConnectorFromSettings())
{
sqlConnector.Connect();
var databaseVersionVerifier = new SqlDatabaseVersionVerifier(sqlConnector);
var metaDataRetriever = new SqlDatabaseMetaDataRetriever();
var metaData = metaDataRetriever.GetDatabaseMetaData(sqlConnector);
if (!databaseVersionVerifier.VerifyDatabaseVersion(metaData.ConfVersion))
if (!databaseVersionVerifier.VerifyDatabaseVersion())
{
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, Language.strErrorConnectionListSaveFailed);
return;
}
metaDataRetriever.WriteDatabaseMetaData(rootTreeNode, sqlConnector);
var rootTreeNode = connectionTreeModel.RootNodes.OfType<RootNodeInfo>().First();
UpdateRootNodeTable(rootTreeNode, sqlConnector);
UpdateConnectionsTable(rootTreeNode, sqlConnector);
UpdateUpdatesTable(sqlConnector);
}
Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, "Saved connections to database");
}
/// <summary>
/// Determines if a given property name should be only saved
/// locally.
/// </summary>
/// <param name="property">
/// The name of the property that triggered the save event
/// </param>
/// <returns></returns>
private bool PropertyIsLocalOnly(string property)
{
return property == nameof(ConnectionInfo.OpenConnections) ||
property == nameof(ContainerInfo.IsExpanded);
}
private void UpdateLocalConnectionProperties(ContainerInfo rootNode)
{
var a = rootNode.GetRecursiveChildList().Select(info => new LocalConnectionPropertiesModel
{
ConnectionId = info.ConstantID,
Connected = info.OpenConnections.Count > 0,
Expanded = info is ContainerInfo c && c.IsExpanded
});
var serializedProperties = _localPropertiesSerializer.Serialize(a);
_dataProvider.Save(serializedProperties);
Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, "Saved local connection properties");
}
private void UpdateRootNodeTable(RootNodeInfo rootTreeNode, SqlDatabaseConnector sqlDatabaseConnector)
@@ -115,17 +68,17 @@ namespace mRemoteNG.Config.Connections
{
if (rootTreeNode.Password)
{
var password = rootTreeNode.PasswordString.ConvertToSecureString();
strProtected = cryptographyProvider.Encrypt("ThisIsProtected", password);
_connectionsService.EncryptionKey = rootTreeNode.PasswordString.ConvertToSecureString();
strProtected = cryptographyProvider.Encrypt("ThisIsProtected", _connectionsService.EncryptionKey);
}
else
{
strProtected = cryptographyProvider.Encrypt("ThisIsNotProtected", Runtime.EncryptionKey);
strProtected = cryptographyProvider.Encrypt("ThisIsNotProtected", _connectionsService.EncryptionKey);
}
}
else
{
strProtected = cryptographyProvider.Encrypt("ThisIsNotProtected", Runtime.EncryptionKey);
strProtected = cryptographyProvider.Encrypt("ThisIsNotProtected", _connectionsService.EncryptionKey);
}
var sqlQuery = new SqlCommand("DELETE FROM tblRoot", sqlDatabaseConnector.SqlConnection);
@@ -147,15 +100,13 @@ namespace mRemoteNG.Config.Connections
}
}
private void UpdateConnectionsTable(RootNodeInfo rootTreeNode, SqlDatabaseConnector sqlDatabaseConnector)
private void UpdateConnectionsTable(ContainerInfo rootTreeNode, SqlDatabaseConnector sqlDatabaseConnector)
{
var cryptoProvider = new LegacyRijndaelCryptographyProvider();
var serializer = new DataTableSerializer(_saveFilter, cryptoProvider, rootTreeNode.PasswordString.ConvertToSecureString());
var dataTable = serializer.Serialize(rootTreeNode);
var dataProvider = new SqlDataProvider(sqlDatabaseConnector);
var sqlQuery = new SqlCommand("DELETE FROM tblCons", sqlDatabaseConnector.SqlConnection);
sqlQuery.ExecuteNonQuery();
var serializer = new DataTableSerializer(_saveFilter);
var dataTable = serializer.Serialize(rootTreeNode);
var dataProvider = new SqlDataProvider(sqlDatabaseConnector);
dataProvider.Save(dataTable);
}

View File

@@ -1,40 +1,37 @@
using mRemoteNG.Config.DataProviders;
using System.Security;
using System.Windows.Forms;
using mRemoteNG.Config.DataProviders;
using mRemoteNG.Config.Serializers.Xml;
using mRemoteNG.Connection;
using mRemoteNG.Tools;
using mRemoteNG.Tree;
using System;
using System.IO;
using System.Security;
namespace mRemoteNG.Config.Connections
{
public class XmlConnectionsLoader : IConnectionsLoader
{
public class XmlConnectionsLoader
{
private readonly IConnectionsService _connectionsService;
private readonly string _connectionFilePath;
private readonly IWin32Window _dialogWindowParent;
public XmlConnectionsLoader(string connectionFilePath)
public XmlConnectionsLoader(string connectionFilePath, IConnectionsService connectionsService, IWin32Window dialogWindowParent)
{
if (string.IsNullOrEmpty(connectionFilePath))
throw new ArgumentException($"{nameof(connectionFilePath)} cannot be null or empty");
if (!File.Exists(connectionFilePath))
throw new FileNotFoundException($"{connectionFilePath} does not exist");
_connectionFilePath = connectionFilePath;
_dialogWindowParent = dialogWindowParent;
_connectionFilePath = connectionFilePath.ThrowIfNullOrEmpty(nameof(connectionFilePath));
_connectionsService = connectionsService.ThrowIfNull(nameof(connectionsService));
}
public ConnectionTreeModel Load()
{
var dataProvider = new FileDataProvider(_connectionFilePath);
var xmlString = dataProvider.Load();
var deserializer = new XmlConnectionsDeserializer(PromptForPassword);
var deserializer = new XmlConnectionsDeserializer(_connectionsService, _dialogWindowParent, PromptForPassword);
return deserializer.Deserialize(xmlString);
}
private Optional<SecureString> PromptForPassword()
{
var password = MiscTools.PasswordDialog("", false);
return password;
return MiscTools.PasswordDialog("", false);
}
}
}

View File

@@ -27,12 +27,12 @@ namespace mRemoteNG.Config.Connections
_saveFilter = saveFilter;
}
public void Save(ConnectionTreeModel connectionTreeModel, string propertyNameTrigger = "")
public void Save(ConnectionTreeModel connectionTreeModel)
{
try
{
var cryptographyProvider = new CryptoProviderFactoryFromSettings().Build();
var connectionNodeSerializer = new XmlConnectionNodeSerializer26(
var connectionNodeSerializer = new XmlConnectionNodeSerializer27(
cryptographyProvider,
connectionTreeModel.RootNodes.OfType<RootNodeInfo>().First().PasswordString.ConvertToSecureString(),
_saveFilter);

View File

@@ -18,7 +18,7 @@ namespace mRemoteNG.Config
_dataProvider = dataProvider;
}
public void Save(IEnumerable<ICredentialRepository> repositories, string propertyNameTrigger = "")
public void Save(IEnumerable<ICredentialRepository> repositories)
{
var serializer = new CredentialRepositoryListSerializer();
var data = serializer.Serialize(repositories);

View File

@@ -1,17 +1,26 @@
using mRemoteNG.App;
using System;
using System.Security;
using mRemoteNG.App;
using mRemoteNG.Security.SymmetricEncryption;
namespace mRemoteNG.Config.DatabaseConnectors
{
public class DatabaseConnectorFactory
{
public static SqlDatabaseConnector SqlDatabaseConnectorFromSettings()
private readonly Func<SecureString> _decryptionKeyRetrievalFun;
public DatabaseConnectorFactory(Func<SecureString> decryptionKeyRetrievalFun)
{
_decryptionKeyRetrievalFun = decryptionKeyRetrievalFun;
}
public SqlDatabaseConnector SqlDatabaseConnectorFromSettings()
{
var sqlHost = mRemoteNG.Settings.Default.SQLHost;
var sqlCatalog = mRemoteNG.Settings.Default.SQLDatabaseName;
var sqlUsername = mRemoteNG.Settings.Default.SQLUser;
var cryptographyProvider = new LegacyRijndaelCryptographyProvider();
var sqlPassword = cryptographyProvider.Decrypt(mRemoteNG.Settings.Default.SQLPass, Runtime.EncryptionKey);
var sqlPassword = cryptographyProvider.Decrypt(mRemoteNG.Settings.Default.SQLPass, _decryptionKeyRetrievalFun());
return new SqlDatabaseConnector(sqlHost, sqlCatalog, sqlUsername, sqlPassword);
}
}

View File

@@ -2,6 +2,6 @@
{
public interface ISaver<in T>
{
void Save(T model, string propertyNameTrigger = "");
void Save(T model);
}
}

View File

@@ -1,11 +1,13 @@
using System.IO;
using System.Linq;
using System.Windows.Forms;
using mRemoteNG.App;
using mRemoteNG.Config.DataProviders;
using mRemoteNG.Config.Serializers;
using mRemoteNG.Config.Serializers.Xml;
using mRemoteNG.Connection;
using mRemoteNG.Container;
using mRemoteNG.Messages;
using mRemoteNG.Tools;
namespace mRemoteNG.Config.Import
@@ -13,6 +15,15 @@ namespace mRemoteNG.Config.Import
// ReSharper disable once InconsistentNaming
public class MRemoteNGXmlImporter : IConnectionImporter<string>
{
private readonly IConnectionsService _connectionsService;
private readonly IWin32Window _dialogWindowParent;
public MRemoteNGXmlImporter(IConnectionsService connectionsService, IWin32Window dialogWindowParent)
{
_connectionsService = connectionsService.ThrowIfNull(nameof(connectionsService));
_dialogWindowParent = dialogWindowParent.ThrowIfNull(nameof(dialogWindowParent));
}
public void Import(string fileName, ContainerInfo destinationContainer)
{
if (fileName == null)
@@ -26,7 +37,7 @@ namespace mRemoteNG.Config.Import
var dataProvider = new FileDataProvider(fileName);
var xmlString = dataProvider.Load();
var xmlConnectionsDeserializer = new XmlConnectionsDeserializer();
var xmlConnectionsDeserializer = new XmlConnectionsDeserializer(_connectionsService, _dialogWindowParent);
var connectionTreeModel = xmlConnectionsDeserializer.Deserialize(xmlString, true);
var rootImportContainer = new ContainerInfo { Name = Path.GetFileNameWithoutExtension(fileName) };

View File

@@ -234,6 +234,12 @@ namespace mRemoteNG.Config.Serializers.Csv
if (bool.TryParse(connectionCsv[headers.IndexOf("RedirectPrinters")], out value))
connectionRecord.RedirectPrinters = value;
}
if (headers.Contains("RedirectClipboard"))
{
bool value;
if (bool.TryParse(connectionCsv[headers.IndexOf("RedirectClipboard")], out value))
connectionRecord.RedirectClipboard = value;
}
if (headers.Contains("RedirectSmartCards"))
{
@@ -453,6 +459,13 @@ namespace mRemoteNG.Config.Serializers.Csv
connectionRecord.Inheritance.RedirectPrinters = value;
}
if (headers.Contains("InheritRedirectClipboard"))
{
bool value;
if (bool.TryParse(connectionCsv[headers.IndexOf("InheritRedirectClipboard")], out value))
connectionRecord.Inheritance.RedirectClipboard = value;
}
if (headers.Contains("InheritRedirectSmartCards"))
{
bool value;

View File

@@ -52,9 +52,9 @@ namespace mRemoteNG.Config.Serializers.Csv
sb.Append("Password;");
if (_saveFilter.SaveDomain)
sb.Append("Domain;");
sb.Append("Hostname;Protocol;PuttySession;Port;ConnectToConsole;UseCredSsp;RenderingEngine;ICAEncryptionStrength;RDPAuthenticationLevel;LoadBalanceInfo;Colors;Resolution;AutomaticResize;DisplayWallpaper;DisplayThemes;EnableFontSmoothing;EnableDesktopComposition;CacheBitmaps;RedirectDiskDrives;RedirectPorts;RedirectPrinters;RedirectSmartCards;RedirectSound;RedirectKeys;PreExtApp;PostExtApp;MacAddress;UserField;ExtApp;VNCCompression;VNCEncoding;VNCAuthMode;VNCProxyType;VNCProxyIP;VNCProxyPort;VNCProxyUsername;VNCProxyPassword;VNCColors;VNCSmartSizeMode;VNCViewOnly;RDGatewayUsageMethod;RDGatewayHostname;RDGatewayUseConnectionCredentials;RDGatewayUsername;RDGatewayPassword;RDGatewayDomain;");
sb.Append("Hostname;Protocol;PuttySession;Port;ConnectToConsole;UseCredSsp;RenderingEngine;ICAEncryptionStrength;RDPAuthenticationLevel;LoadBalanceInfo;Colors;Resolution;AutomaticResize;DisplayWallpaper;DisplayThemes;EnableFontSmoothing;EnableDesktopComposition;CacheBitmaps;RedirectDiskDrives;RedirectPorts;RedirectPrinters;RedirectClipboard;RedirectSmartCards;RedirectSound;RedirectKeys;PreExtApp;PostExtApp;MacAddress;UserField;ExtApp;VNCCompression;VNCEncoding;VNCAuthMode;VNCProxyType;VNCProxyIP;VNCProxyPort;VNCProxyUsername;VNCProxyPassword;VNCColors;VNCSmartSizeMode;VNCViewOnly;RDGatewayUsageMethod;RDGatewayHostname;RDGatewayUseConnectionCredentials;RDGatewayUsername;RDGatewayPassword;RDGatewayDomain;");
if (_saveFilter.SaveInheritance)
sb.Append("InheritCacheBitmaps;InheritColors;InheritDescription;InheritDisplayThemes;InheritDisplayWallpaper;InheritEnableFontSmoothing;InheritEnableDesktopComposition;InheritDomain;InheritIcon;InheritPanel;InheritPassword;InheritPort;InheritProtocol;InheritPuttySession;InheritRedirectDiskDrives;InheritRedirectKeys;InheritRedirectPorts;InheritRedirectPrinters;InheritRedirectSmartCards;InheritRedirectSound;InheritResolution;InheritAutomaticResize;InheritUseConsoleSession;InheritUseCredSsp;InheritRenderingEngine;InheritUsername;InheritICAEncryptionStrength;InheritRDPAuthenticationLevel;InheritLoadBalanceInfo;InheritPreExtApp;InheritPostExtApp;InheritMacAddress;InheritUserField;InheritExtApp;InheritVNCCompression;InheritVNCEncoding;InheritVNCAuthMode;InheritVNCProxyType;InheritVNCProxyIP;InheritVNCProxyPort;InheritVNCProxyUsername;InheritVNCProxyPassword;InheritVNCColors;InheritVNCSmartSizeMode;InheritVNCViewOnly;InheritRDGatewayUsageMethod;InheritRDGatewayHostname;InheritRDGatewayUseConnectionCredentials;InheritRDGatewayUsername;InheritRDGatewayPassword;InheritRDGatewayDomain;InheritRDPAlertIdleTimeout;InheritRDPMinutesToIdleTimeout;InheritSoundQuality");
sb.Append("InheritCacheBitmaps;InheritColors;InheritDescription;InheritDisplayThemes;InheritDisplayWallpaper;InheritEnableFontSmoothing;InheritEnableDesktopComposition;InheritDomain;InheritIcon;InheritPanel;InheritPassword;InheritPort;InheritProtocol;InheritPuttySession;InheritRedirectDiskDrives;InheritRedirectKeys;InheritRedirectPorts;InheritRedirectPrinters;InheritRedirectClipboard;InheritRedirectSmartCards;InheritRedirectSound;InheritResolution;InheritAutomaticResize;InheritUseConsoleSession;InheritUseCredSsp;InheritRenderingEngine;InheritUsername;InheritICAEncryptionStrength;InheritRDPAuthenticationLevel;InheritLoadBalanceInfo;InheritPreExtApp;InheritPostExtApp;InheritMacAddress;InheritUserField;InheritExtApp;InheritVNCCompression;InheritVNCEncoding;InheritVNCAuthMode;InheritVNCProxyType;InheritVNCProxyIP;InheritVNCProxyPort;InheritVNCProxyUsername;InheritVNCProxyPassword;InheritVNCColors;InheritVNCSmartSizeMode;InheritVNCViewOnly;InheritRDGatewayUsageMethod;InheritRDGatewayHostname;InheritRDGatewayUseConnectionCredentials;InheritRDGatewayUsername;InheritRDGatewayPassword;InheritRDGatewayDomain;InheritRDPAlertIdleTimeout;InheritRDPMinutesToIdleTimeout;InheritSoundQuality");
}
private void SerializeNodesRecursive(ConnectionInfo node, StringBuilder sb)
@@ -116,6 +116,7 @@ namespace mRemoteNG.Config.Serializers.Csv
.Append(FormatForCsv(con.RedirectDiskDrives))
.Append(FormatForCsv(con.RedirectPorts))
.Append(FormatForCsv(con.RedirectPrinters))
.Append(FormatForCsv(con.RedirectClipboard))
.Append(FormatForCsv(con.RedirectSmartCards))
.Append(FormatForCsv(con.RedirectSound))
.Append(FormatForCsv(con.RedirectKeys))
@@ -164,6 +165,7 @@ namespace mRemoteNG.Config.Serializers.Csv
.Append(FormatForCsv(con.Inheritance.RedirectKeys))
.Append(FormatForCsv(con.Inheritance.RedirectPorts))
.Append(FormatForCsv(con.Inheritance.RedirectPrinters))
.Append(FormatForCsv(con.Inheritance.RedirectClipboard))
.Append(FormatForCsv(con.Inheritance.RedirectSmartCards))
.Append(FormatForCsv(con.Inheritance.RedirectSound))
.Append(FormatForCsv(con.Inheritance.Resolution))

View File

@@ -1,20 +0,0 @@
namespace mRemoteNG.Config.Serializers.MsSql
{
public class LocalConnectionPropertiesModel
{
/// <summary>
/// The unique Id of this tree node
/// </summary>
public string ConnectionId { get; set; }
/// <summary>
/// Indicates whether this connection is connected
/// </summary>
public bool Connected { get; set; }
/// <summary>
/// Indicates whether this container is expanded in the tree
/// </summary>
public bool Expanded { get; set; }
}
}

View File

@@ -1,60 +0,0 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace mRemoteNG.Config.Serializers.MsSql
{
public class LocalConnectionPropertiesXmlSerializer :
ISerializer<IEnumerable<LocalConnectionPropertiesModel>, string>,
IDeserializer<string, IEnumerable<LocalConnectionPropertiesModel>>
{
public string Serialize(IEnumerable<LocalConnectionPropertiesModel> models)
{
var localConnections = models
.Select(m => new XElement("Node",
new XAttribute("ConnectionId", m.ConnectionId),
new XAttribute("Connected", m.Connected),
new XAttribute("Expanded", m.Expanded)));
var root = new XElement("LocalConnections", localConnections);
var xdoc = new XDocument(new XDeclaration("1.0", "utf-8", null), root);
return WriteXmlToString(xdoc);
}
public IEnumerable<LocalConnectionPropertiesModel> Deserialize(string serializedData)
{
if (string.IsNullOrWhiteSpace(serializedData))
return Enumerable.Empty<LocalConnectionPropertiesModel>();
var xdoc = XDocument.Parse(serializedData);
return xdoc
.Descendants("Node")
.Where(e => e.Attribute("ConnectionId") != null)
.Select(e => new LocalConnectionPropertiesModel
{
ConnectionId = e.Attribute("ConnectionId")?.Value,
Connected = bool.Parse(e.Attribute("Connected")?.Value ?? "False"),
Expanded = bool.Parse(e.Attribute("Expanded")?.Value ?? "False")
});
}
private static string WriteXmlToString(XNode xmlDocument)
{
string xmlString;
var xmlWriterSettings = new XmlWriterSettings { Indent = true, IndentChars = " ", Encoding = Encoding.UTF8 };
var memoryStream = new MemoryStream();
using (var xmlTextWriter = XmlWriter.Create(memoryStream, xmlWriterSettings))
{
xmlDocument.WriteTo(xmlTextWriter);
xmlTextWriter.Flush();
var streamReader = new StreamReader(memoryStream, Encoding.UTF8, true);
memoryStream.Seek(0, SeekOrigin.Begin);
xmlString = streamReader.ReadToEnd();
}
return xmlString;
}
}
}

View File

@@ -1,13 +0,0 @@
using System;
using System.Security;
namespace mRemoteNG.Config.Serializers.MsSql
{
public class SqlConnectionListMetaData
{
public string Name { get; set; }
public string Protected { get; set; }
public bool Export { get; set; }
public Version ConfVersion { get; set; }
}
}

View File

@@ -1,93 +0,0 @@
using System;
using System.Data.SqlClient;
using System.Globalization;
using mRemoteNG.App;
using mRemoteNG.App.Info;
using mRemoteNG.Config.DatabaseConnectors;
using mRemoteNG.Messages;
using mRemoteNG.Security;
using mRemoteNG.Security.SymmetricEncryption;
using mRemoteNG.Tools;
using mRemoteNG.Tree.Root;
namespace mRemoteNG.Config.Serializers.MsSql
{
public class SqlDatabaseMetaDataRetriever
{
public SqlConnectionListMetaData GetDatabaseMetaData(SqlDatabaseConnector sqlDatabaseConnector)
{
SqlConnectionListMetaData metaData;
SqlDataReader sqlDataReader = null;
try
{
var sqlCommand = new SqlCommand("SELECT * FROM tblRoot", sqlDatabaseConnector.SqlConnection);
if (!sqlDatabaseConnector.IsConnected)
sqlDatabaseConnector.Connect();
sqlDataReader = sqlCommand.ExecuteReader();
if (!sqlDataReader.HasRows)
return null; // assume new empty database
else
sqlDataReader.Read();
metaData = new SqlConnectionListMetaData
{
Name = sqlDataReader["Name"] as string ?? "",
Protected = sqlDataReader["Protected"] as string ?? "",
Export = (bool)sqlDataReader["Export"],
ConfVersion = new Version(Convert.ToString(sqlDataReader["confVersion"], CultureInfo.InvariantCulture))
};
}
catch (Exception ex)
{
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, $"Retrieving database version failed. {ex}");
throw;
}
finally
{
if (sqlDataReader != null && !sqlDataReader.IsClosed)
sqlDataReader.Close();
}
return metaData;
}
public void WriteDatabaseMetaData(RootNodeInfo rootTreeNode, SqlDatabaseConnector sqlDatabaseConnector)
{
var cryptographyProvider = new LegacyRijndaelCryptographyProvider();
string strProtected;
if (rootTreeNode != null)
{
if (rootTreeNode.Password)
{
var password = rootTreeNode.PasswordString.ConvertToSecureString();
strProtected = cryptographyProvider.Encrypt("ThisIsProtected", password);
}
else
{
strProtected = cryptographyProvider.Encrypt("ThisIsNotProtected", Runtime.EncryptionKey);
}
}
else
{
strProtected = cryptographyProvider.Encrypt("ThisIsNotProtected", Runtime.EncryptionKey);
}
var sqlQuery = new SqlCommand("DELETE FROM tblRoot", sqlDatabaseConnector.SqlConnection);
sqlQuery.ExecuteNonQuery();
if (rootTreeNode != null)
{
sqlQuery =
new SqlCommand(
"INSERT INTO tblRoot (Name, Export, Protected, ConfVersion) VALUES(\'" +
MiscTools.PrepareValueForDB(rootTreeNode.Name) + "\', 0, \'" + strProtected + "\'," +
ConnectionsFileInfo.ConnectionFileVersion.ToString(CultureInfo.InvariantCulture) + ")",
sqlDatabaseConnector.SqlConnection);
sqlQuery.ExecuteNonQuery();
}
else
{
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, $"UpdateRootNodeTable: rootTreeNode was null. Could not insert!");
}
}
}
}

View File

@@ -210,7 +210,7 @@ namespace mRemoteNG.Config.Serializers.Xml
element.Add(new XAttribute("InheritRedirectDiskDrives", falseString));
element.Add(new XAttribute("InheritRedirectKeys", falseString));
element.Add(new XAttribute("InheritRedirectPorts", falseString));
element.Add(new XAttribute("InheritRedirectPrinters", falseString));
element.Add(new XAttribute("InheritRedirectPrinters", falseString));
element.Add(new XAttribute("InheritRedirectSmartCards", falseString));
element.Add(new XAttribute("InheritRedirectSound", falseString));
element.Add(new XAttribute("InheritSoundQuality", falseString));

View File

@@ -0,0 +1,256 @@
using System;
using System.Security;
using System.Xml.Linq;
using mRemoteNG.Connection;
using mRemoteNG.Container;
using mRemoteNG.Security;
namespace mRemoteNG.Config.Serializers.Xml
{
// ReSharper disable once InconsistentNaming
public class XmlConnectionNodeSerializer27 : ISerializer<ConnectionInfo,XElement>
{
private readonly ICryptographyProvider _cryptographyProvider;
private readonly SecureString _encryptionKey;
private readonly SaveFilter _saveFilter;
public XmlConnectionNodeSerializer27(ICryptographyProvider cryptographyProvider, SecureString encryptionKey, SaveFilter saveFilter)
{
if (cryptographyProvider == null)
throw new ArgumentNullException(nameof(cryptographyProvider));
if (encryptionKey == null)
throw new ArgumentNullException(nameof(encryptionKey));
if (saveFilter == null)
throw new ArgumentNullException(nameof(saveFilter));
_cryptographyProvider = cryptographyProvider;
_encryptionKey = encryptionKey;
_saveFilter = saveFilter;
}
public XElement Serialize(ConnectionInfo connectionInfo)
{
var element = new XElement(XName.Get("Node", ""));
SetElementAttributes(element, connectionInfo);
SetInheritanceAttributes(element, connectionInfo);
return element;
}
private void SetElementAttributes(XContainer element, ConnectionInfo connectionInfo)
{
var nodeAsContainer = connectionInfo as ContainerInfo;
element.Add(new XAttribute("Name", connectionInfo.Name));
element.Add(new XAttribute("Type", connectionInfo.GetTreeNodeType().ToString()));
if (nodeAsContainer != null)
element.Add(new XAttribute("Expanded", nodeAsContainer.IsExpanded.ToString().ToLowerInvariant()));
element.Add(new XAttribute("Descr", connectionInfo.Description));
element.Add(new XAttribute("Icon", connectionInfo.Icon));
element.Add(new XAttribute("Panel", connectionInfo.Panel));
element.Add(new XAttribute("Id", connectionInfo.ConstantID));
element.Add(_saveFilter.SaveUsername
? new XAttribute("Username", connectionInfo.Username)
: new XAttribute("Username", ""));
element.Add(_saveFilter.SaveDomain
? new XAttribute("Domain", connectionInfo.Domain)
: new XAttribute("Domain", ""));
if (_saveFilter.SavePassword && !connectionInfo.Inheritance.Password)
element.Add(new XAttribute("Password", _cryptographyProvider.Encrypt(connectionInfo.Password, _encryptionKey)));
else
element.Add(new XAttribute("Password", ""));
element.Add(new XAttribute("Hostname", connectionInfo.Hostname));
element.Add(new XAttribute("Protocol", connectionInfo.Protocol));
element.Add(new XAttribute("PuttySession", connectionInfo.PuttySession));
element.Add(new XAttribute("Port", connectionInfo.Port));
element.Add(new XAttribute("ConnectToConsole", connectionInfo.UseConsoleSession.ToString().ToLowerInvariant()));
element.Add(new XAttribute("UseCredSsp", connectionInfo.UseCredSsp.ToString().ToLowerInvariant()));
element.Add(new XAttribute("RenderingEngine", connectionInfo.RenderingEngine));
element.Add(new XAttribute("ICAEncryptionStrength", connectionInfo.ICAEncryptionStrength));
element.Add(new XAttribute("RDPAuthenticationLevel", connectionInfo.RDPAuthenticationLevel));
element.Add(new XAttribute("RDPMinutesToIdleTimeout", connectionInfo.RDPMinutesToIdleTimeout));
element.Add(new XAttribute("RDPAlertIdleTimeout", connectionInfo.RDPAlertIdleTimeout.ToString().ToLowerInvariant()));
element.Add(new XAttribute("LoadBalanceInfo", connectionInfo.LoadBalanceInfo));
element.Add(new XAttribute("Colors", connectionInfo.Colors));
element.Add(new XAttribute("Resolution", connectionInfo.Resolution));
element.Add(new XAttribute("AutomaticResize", connectionInfo.AutomaticResize.ToString().ToLowerInvariant()));
element.Add(new XAttribute("DisplayWallpaper", connectionInfo.DisplayWallpaper.ToString().ToLowerInvariant()));
element.Add(new XAttribute("DisplayThemes", connectionInfo.DisplayThemes.ToString().ToLowerInvariant()));
element.Add(new XAttribute("EnableFontSmoothing", connectionInfo.EnableFontSmoothing.ToString().ToLowerInvariant()));
element.Add(new XAttribute("EnableDesktopComposition", connectionInfo.EnableDesktopComposition.ToString().ToLowerInvariant()));
element.Add(new XAttribute("CacheBitmaps", connectionInfo.CacheBitmaps.ToString().ToLowerInvariant()));
element.Add(new XAttribute("RedirectDiskDrives", connectionInfo.RedirectDiskDrives.ToString().ToLowerInvariant()));
element.Add(new XAttribute("RedirectPorts", connectionInfo.RedirectPorts.ToString().ToLowerInvariant()));
element.Add(new XAttribute("RedirectPrinters", connectionInfo.RedirectPrinters.ToString().ToLowerInvariant()));
element.Add(new XAttribute("RedirectClipboard", connectionInfo.RedirectClipboard.ToString().ToLowerInvariant()));
element.Add(new XAttribute("RedirectSmartCards", connectionInfo.RedirectSmartCards.ToString().ToLowerInvariant()));
element.Add(new XAttribute("RedirectSound", connectionInfo.RedirectSound.ToString()));
element.Add(new XAttribute("SoundQuality", connectionInfo.SoundQuality.ToString()));
element.Add(new XAttribute("RedirectKeys", connectionInfo.RedirectKeys.ToString().ToLowerInvariant()));
element.Add(new XAttribute("Connected", (connectionInfo.OpenConnections.Count > 0).ToString().ToLowerInvariant()));
element.Add(new XAttribute("PreExtApp", connectionInfo.PreExtApp));
element.Add(new XAttribute("PostExtApp", connectionInfo.PostExtApp));
element.Add(new XAttribute("MacAddress", connectionInfo.MacAddress));
element.Add(new XAttribute("UserField", connectionInfo.UserField));
element.Add(new XAttribute("ExtApp", connectionInfo.ExtApp));
element.Add(new XAttribute("VNCCompression", connectionInfo.VNCCompression));
element.Add(new XAttribute("VNCEncoding", connectionInfo.VNCEncoding));
element.Add(new XAttribute("VNCAuthMode", connectionInfo.VNCAuthMode));
element.Add(new XAttribute("VNCProxyType", connectionInfo.VNCProxyType));
element.Add(new XAttribute("VNCProxyIP", connectionInfo.VNCProxyIP));
element.Add(new XAttribute("VNCProxyPort", connectionInfo.VNCProxyPort));
element.Add(_saveFilter.SaveUsername
? new XAttribute("VNCProxyUsername", connectionInfo.VNCProxyUsername)
: new XAttribute("VNCProxyUsername", ""));
element.Add(_saveFilter.SavePassword
? new XAttribute("VNCProxyPassword",
_cryptographyProvider.Encrypt(connectionInfo.VNCProxyPassword, _encryptionKey))
: new XAttribute("VNCProxyPassword", ""));
element.Add(new XAttribute("VNCColors", connectionInfo.VNCColors));
element.Add(new XAttribute("VNCSmartSizeMode", connectionInfo.VNCSmartSizeMode));
element.Add(new XAttribute("VNCViewOnly", connectionInfo.VNCViewOnly.ToString().ToLowerInvariant()));
element.Add(new XAttribute("RDGatewayUsageMethod", connectionInfo.RDGatewayUsageMethod));
element.Add(new XAttribute("RDGatewayHostname", connectionInfo.RDGatewayHostname));
element.Add(new XAttribute("RDGatewayUseConnectionCredentials", connectionInfo.RDGatewayUseConnectionCredentials));
element.Add(_saveFilter.SaveUsername
? new XAttribute("RDGatewayUsername", connectionInfo.RDGatewayUsername)
: new XAttribute("RDGatewayUsername", ""));
element.Add(_saveFilter.SavePassword
? new XAttribute("RDGatewayPassword",
_cryptographyProvider.Encrypt(connectionInfo.RDGatewayPassword, _encryptionKey))
: new XAttribute("RDGatewayPassword", ""));
element.Add(_saveFilter.SaveDomain
? new XAttribute("RDGatewayDomain", connectionInfo.RDGatewayDomain)
: new XAttribute("RDGatewayDomain", ""));
}
private void SetInheritanceAttributes(XContainer element, IInheritable connectionInfo)
{
if (_saveFilter.SaveInheritance)
{
element.Add(new XAttribute("InheritCacheBitmaps", connectionInfo.Inheritance.CacheBitmaps.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritColors", connectionInfo.Inheritance.Colors.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritDescription", connectionInfo.Inheritance.Description.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritDisplayThemes", connectionInfo.Inheritance.DisplayThemes.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritDisplayWallpaper", connectionInfo.Inheritance.DisplayWallpaper.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritEnableFontSmoothing", connectionInfo.Inheritance.EnableFontSmoothing.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritEnableDesktopComposition", connectionInfo.Inheritance.EnableDesktopComposition.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritDomain", connectionInfo.Inheritance.Domain.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritIcon", connectionInfo.Inheritance.Icon.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritPanel", connectionInfo.Inheritance.Panel.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritPassword", connectionInfo.Inheritance.Password.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritPort", connectionInfo.Inheritance.Port.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritProtocol", connectionInfo.Inheritance.Protocol.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritPuttySession", connectionInfo.Inheritance.PuttySession.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritRedirectDiskDrives", connectionInfo.Inheritance.RedirectDiskDrives.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritRedirectKeys", connectionInfo.Inheritance.RedirectKeys.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritRedirectPorts", connectionInfo.Inheritance.RedirectPorts.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritRedirectPrinters", connectionInfo.Inheritance.RedirectPrinters.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritRedirectClipboard", connectionInfo.Inheritance.RedirectClipboard.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritRedirectSmartCards", connectionInfo.Inheritance.RedirectSmartCards.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritRedirectSound", connectionInfo.Inheritance.RedirectSound.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritSoundQuality", connectionInfo.Inheritance.SoundQuality.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritResolution", connectionInfo.Inheritance.Resolution.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritAutomaticResize", connectionInfo.Inheritance.AutomaticResize.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritUseConsoleSession", connectionInfo.Inheritance.UseConsoleSession.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritUseCredSsp", connectionInfo.Inheritance.UseCredSsp.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritRenderingEngine", connectionInfo.Inheritance.RenderingEngine.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritUsername", connectionInfo.Inheritance.Username.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritICAEncryptionStrength", connectionInfo.Inheritance.ICAEncryptionStrength.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritRDPAuthenticationLevel", connectionInfo.Inheritance.RDPAuthenticationLevel.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritRDPMinutesToIdleTimeout", connectionInfo.Inheritance.RDPMinutesToIdleTimeout.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritRDPAlertIdleTimeout", connectionInfo.Inheritance.RDPAlertIdleTimeout.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritLoadBalanceInfo", connectionInfo.Inheritance.LoadBalanceInfo.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritPreExtApp", connectionInfo.Inheritance.PreExtApp.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritPostExtApp", connectionInfo.Inheritance.PostExtApp.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritMacAddress", connectionInfo.Inheritance.MacAddress.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritUserField", connectionInfo.Inheritance.UserField.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritExtApp", connectionInfo.Inheritance.ExtApp.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritVNCCompression", connectionInfo.Inheritance.VNCCompression.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritVNCEncoding", connectionInfo.Inheritance.VNCEncoding.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritVNCAuthMode", connectionInfo.Inheritance.VNCAuthMode.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritVNCProxyType", connectionInfo.Inheritance.VNCProxyType.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritVNCProxyIP", connectionInfo.Inheritance.VNCProxyIP.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritVNCProxyPort", connectionInfo.Inheritance.VNCProxyPort.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritVNCProxyUsername", connectionInfo.Inheritance.VNCProxyUsername.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritVNCProxyPassword", connectionInfo.Inheritance.VNCProxyPassword.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritVNCColors", connectionInfo.Inheritance.VNCColors.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritVNCSmartSizeMode", connectionInfo.Inheritance.VNCSmartSizeMode.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritVNCViewOnly", connectionInfo.Inheritance.VNCViewOnly.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritRDGatewayUsageMethod", connectionInfo.Inheritance.RDGatewayUsageMethod.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritRDGatewayHostname", connectionInfo.Inheritance.RDGatewayHostname.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritRDGatewayUseConnectionCredentials", connectionInfo.Inheritance.RDGatewayUseConnectionCredentials.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritRDGatewayUsername", connectionInfo.Inheritance.RDGatewayUsername.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritRDGatewayPassword", connectionInfo.Inheritance.RDGatewayPassword.ToString().ToLowerInvariant()));
element.Add(new XAttribute("InheritRDGatewayDomain", connectionInfo.Inheritance.RDGatewayDomain.ToString().ToLowerInvariant()));
}
else
{
var falseString = false.ToString().ToLowerInvariant();
element.Add(new XAttribute("InheritCacheBitmaps", falseString));
element.Add(new XAttribute("InheritColors", falseString));
element.Add(new XAttribute("InheritDescription", falseString));
element.Add(new XAttribute("InheritDisplayThemes", falseString));
element.Add(new XAttribute("InheritDisplayWallpaper", falseString));
element.Add(new XAttribute("InheritEnableFontSmoothing", falseString));
element.Add(new XAttribute("InheritEnableDesktopComposition", falseString));
element.Add(new XAttribute("InheritDomain", falseString));
element.Add(new XAttribute("InheritIcon", falseString));
element.Add(new XAttribute("InheritPanel", falseString));
element.Add(new XAttribute("InheritPassword", falseString));
element.Add(new XAttribute("InheritPort", falseString));
element.Add(new XAttribute("InheritProtocol", falseString));
element.Add(new XAttribute("InheritPuttySession", falseString));
element.Add(new XAttribute("InheritRedirectDiskDrives", falseString));
element.Add(new XAttribute("InheritRedirectKeys", falseString));
element.Add(new XAttribute("InheritRedirectPorts", falseString));
element.Add(new XAttribute("InheritRedirectPrinters", falseString));
element.Add(new XAttribute("InheritRedirectClipboard", falseString));
element.Add(new XAttribute("InheritRedirectSmartCards", falseString));
element.Add(new XAttribute("InheritRedirectSound", falseString));
element.Add(new XAttribute("InheritSoundQuality", falseString));
element.Add(new XAttribute("InheritResolution", falseString));
element.Add(new XAttribute("InheritAutomaticResize", falseString));
element.Add(new XAttribute("InheritUseConsoleSession", falseString));
element.Add(new XAttribute("InheritUseCredSsp", falseString));
element.Add(new XAttribute("InheritRenderingEngine", falseString));
element.Add(new XAttribute("InheritUsername", falseString));
element.Add(new XAttribute("InheritICAEncryptionStrength", falseString));
element.Add(new XAttribute("InheritRDPAuthenticationLevel", falseString));
element.Add(new XAttribute("InheritRDPMinutesToIdleTimeout", falseString));
element.Add(new XAttribute("InheritRDPAlertIdleTimeout", falseString));
element.Add(new XAttribute("InheritLoadBalanceInfo", falseString));
element.Add(new XAttribute("InheritPreExtApp", falseString));
element.Add(new XAttribute("InheritPostExtApp", falseString));
element.Add(new XAttribute("InheritMacAddress", falseString));
element.Add(new XAttribute("InheritUserField", falseString));
element.Add(new XAttribute("InheritExtApp", falseString));
element.Add(new XAttribute("InheritVNCCompression", falseString));
element.Add(new XAttribute("InheritVNCEncoding", falseString));
element.Add(new XAttribute("InheritVNCAuthMode", falseString));
element.Add(new XAttribute("InheritVNCProxyType", falseString));
element.Add(new XAttribute("InheritVNCProxyIP", falseString));
element.Add(new XAttribute("InheritVNCProxyPort", falseString));
element.Add(new XAttribute("InheritVNCProxyUsername", falseString));
element.Add(new XAttribute("InheritVNCProxyPassword", falseString));
element.Add(new XAttribute("InheritVNCColors", falseString));
element.Add(new XAttribute("InheritVNCSmartSizeMode", falseString));
element.Add(new XAttribute("InheritVNCViewOnly", falseString));
element.Add(new XAttribute("InheritRDGatewayUsageMethod", falseString));
element.Add(new XAttribute("InheritRDGatewayHostname", falseString));
element.Add(new XAttribute("InheritRDGatewayUseConnectionCredentials", falseString));
element.Add(new XAttribute("InheritRDGatewayUsername", falseString));
element.Add(new XAttribute("InheritRDGatewayPassword", falseString));
element.Add(new XAttribute("InheritRDGatewayDomain", falseString));
}
}
}
}

View File

@@ -22,18 +22,22 @@ using mRemoteNG.UI.TaskDialog;
namespace mRemoteNG.Config.Serializers.Xml
{
public class XmlConnectionsDeserializer : IDeserializer<string, ConnectionTreeModel>
{
{
private readonly IConnectionsService _connectionsService;
private XmlDocument _xmlDocument;
private double _confVersion;
private XmlConnectionsDecryptor _decryptor;
private string ConnectionFileName = "";
private const double MaxSupportedConfVersion = 2.8;
private readonly RootNodeInfo _rootNodeInfo = new RootNodeInfo(RootNodeType.Connection);
private readonly IWin32Window _dialogWindowParent;
public Func<Optional<SecureString>> AuthenticationRequestor { get; set; }
public XmlConnectionsDeserializer(Func<Optional<SecureString>> authenticationRequestor = null)
public XmlConnectionsDeserializer(IConnectionsService connectionsService, IWin32Window dialogWindowParent, Func<Optional<SecureString>> authenticationRequestor = null)
{
_connectionsService = connectionsService.ThrowIfNull(nameof(connectionsService));
_dialogWindowParent = dialogWindowParent.ThrowIfNull(nameof(dialogWindowParent));
AuthenticationRequestor = authenticationRequestor;
}
@@ -78,13 +82,13 @@ namespace mRemoteNG.Config.Serializers.Xml
AddNodesFromXmlRecursive(_xmlDocument.DocumentElement, _rootNodeInfo);
if (!import)
Runtime.ConnectionsService.IsConnectionsFileLoaded = true;
_connectionsService.IsConnectionsFileLoaded = true;
return connectionTreeModel;
}
catch (Exception ex)
{
Runtime.ConnectionsService.IsConnectionsFileLoaded = false;
_connectionsService.IsConnectionsFileLoaded = false;
Runtime.MessageCollector.AddExceptionStackTrace(Language.strLoadFromXmlFailed, ex);
throw;
}
@@ -114,7 +118,7 @@ namespace mRemoteNG.Config.Serializers.Xml
private void ShowIncompatibleVersionDialogBox()
{
CTaskDialog.ShowTaskDialogBox(
FrmMain.Default,
_dialogWindowParent,
Application.ProductName,
"Incompatible connection file format",
$"The format of this connection file is not supported. Please upgrade to a newer version of {Application.ProductName}.",
@@ -285,14 +289,14 @@ namespace mRemoteNG.Config.Serializers.Xml
if (_confVersion >= 0.5)
{
connectionInfo.RedirectDiskDrives = bool.Parse(xmlnode.Attributes["RedirectDiskDrives"].Value);
connectionInfo.RedirectPrinters = bool.Parse(xmlnode.Attributes["RedirectPrinters"].Value);
connectionInfo.RedirectPrinters = bool.Parse(xmlnode.Attributes["RedirectPrinters"].Value);
connectionInfo.RedirectPorts = bool.Parse(xmlnode.Attributes["RedirectPorts"].Value);
connectionInfo.RedirectSmartCards = bool.Parse(xmlnode.Attributes["RedirectSmartCards"].Value);
}
else
{
connectionInfo.RedirectDiskDrives = false;
connectionInfo.RedirectPrinters = false;
connectionInfo.RedirectPrinters = false;
connectionInfo.RedirectPorts = false;
connectionInfo.RedirectSmartCards = false;
}
@@ -508,6 +512,11 @@ namespace mRemoteNG.Config.Serializers.Xml
connectionInfo.RDPAlertIdleTimeout = bool.Parse(xmlnode.Attributes["RDPAlertIdleTimeout"]?.Value ?? "False");
connectionInfo.Inheritance.RDPAlertIdleTimeout = bool.Parse(xmlnode.Attributes["InheritRDPAlertIdleTimeout"]?.Value ?? "False");
}
if(_confVersion >= 2.7)
{
connectionInfo.RedirectClipboard = bool.Parse(xmlnode.Attributes["RedirectClipboard"].Value);
connectionInfo.Inheritance.RedirectClipboard = bool.Parse(xmlnode.Attributes["InheritRedirectClipboard"].Value);
}
}
catch (Exception ex)
{

View File

@@ -1,4 +1,8 @@
using mRemoteNG.App;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using mRemoteNG.App;
using mRemoteNG.Connection;
using mRemoteNG.Connection.Protocol;
using mRemoteNG.Connection.Protocol.Http;
@@ -6,35 +10,26 @@ using mRemoteNG.Connection.Protocol.ICA;
using mRemoteNG.Connection.Protocol.RDP;
using mRemoteNG.Connection.Protocol.VNC;
using mRemoteNG.Container;
using mRemoteNG.Tools;
using mRemoteNG.Tree;
using mRemoteNG.Tree.Root;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Security;
using mRemoteNG.Security;
using mRemoteNG.Security.SymmetricEncryption;
using mRemoteNG.Tools;
namespace mRemoteNG.Config.Serializers.MsSql
namespace mRemoteNG.Config.Serializers
{
public class DataTableDeserializer : IDeserializer<DataTable, ConnectionTreeModel>
{
private readonly ICryptographyProvider _cryptographyProvider;
private readonly SecureString _decryptionKey;
public class DataTableDeserializer : IDeserializer<DataTable, ConnectionTreeModel>
{
private readonly IConnectionsService _connectionsService;
public DataTableDeserializer(ICryptographyProvider cryptographyProvider, SecureString decryptionKey)
{
_cryptographyProvider = cryptographyProvider.ThrowIfNull(nameof(cryptographyProvider));
_decryptionKey = decryptionKey.ThrowIfNull(nameof(decryptionKey));
}
public DataTableDeserializer(IConnectionsService connectionsService)
{
_connectionsService = connectionsService.ThrowIfNull(nameof(connectionsService));
}
public ConnectionTreeModel Deserialize(DataTable table)
public ConnectionTreeModel Deserialize(DataTable table)
{
var connectionList = CreateNodesFromTable(table);
var connectionTreeModel = CreateNodeHierarchy(connectionList, table);
Runtime.ConnectionsService.IsConnectionsFileLoaded = true;
_connectionsService.IsConnectionsFileLoaded = true;
return connectionTreeModel;
}
@@ -47,10 +42,10 @@ namespace mRemoteNG.Config.Serializers.MsSql
switch ((string)row["Type"])
{
case "Connection":
nodeList.Add(DeserializeConnectionInfo(row));
nodeList.Add(DeserializeConnectionInfo(row));
break;
case "Container":
nodeList.Add(DeserializeContainerInfo(row));
nodeList.Add(DeserializeContainerInfo(row));
break;
}
}
@@ -81,12 +76,16 @@ namespace mRemoteNG.Config.Serializers.MsSql
// The Parent object is linked properly later in CreateNodeHierarchy()
//connectionInfo.Parent.ConstantID = (string)dataRow["ParentID"];
var info = connectionInfo as ContainerInfo;
if(info != null)
info.IsExpanded = (bool)dataRow["Expanded"];
connectionInfo.Description = (string)dataRow["Description"];
connectionInfo.Icon = (string)dataRow["Icon"];
connectionInfo.Panel = (string)dataRow["Panel"];
connectionInfo.Username = (string)dataRow["Username"];
connectionInfo.Domain = (string)dataRow["DomainName"];
connectionInfo.Password = DecryptValue((string)dataRow["Password"]);
connectionInfo.Password = (string)dataRow["Password"];
connectionInfo.Hostname = (string)dataRow["Hostname"];
connectionInfo.Protocol = (ProtocolType)Enum.Parse(typeof(ProtocolType), (string)dataRow["Protocol"]);
connectionInfo.PuttySession = (string)dataRow["PuttySession"];
@@ -110,10 +109,12 @@ namespace mRemoteNG.Config.Serializers.MsSql
connectionInfo.RedirectDiskDrives = (bool)dataRow["RedirectDiskDrives"];
connectionInfo.RedirectPorts = (bool)dataRow["RedirectPorts"];
connectionInfo.RedirectPrinters = (bool)dataRow["RedirectPrinters"];
connectionInfo.RedirectClipboard = (bool)dataRow["RedirectClipboard"];
connectionInfo.RedirectSmartCards = (bool)dataRow["RedirectSmartCards"];
connectionInfo.RedirectSound = (RdpProtocol.RDPSounds)Enum.Parse(typeof(RdpProtocol.RDPSounds), (string)dataRow["RedirectSound"]);
connectionInfo.SoundQuality = (RdpProtocol.RDPSoundQuality)Enum.Parse(typeof(RdpProtocol.RDPSoundQuality), (string)dataRow["SoundQuality"]);
connectionInfo.RedirectKeys = (bool)dataRow["RedirectKeys"];
connectionInfo.PleaseConnect = (bool)dataRow["Connected"];
connectionInfo.PreExtApp = (string)dataRow["PreExtApp"];
connectionInfo.PostExtApp = (string)dataRow["PostExtApp"];
connectionInfo.MacAddress = (string)dataRow["MacAddress"];
@@ -126,7 +127,7 @@ namespace mRemoteNG.Config.Serializers.MsSql
connectionInfo.VNCProxyIP = (string)dataRow["VNCProxyIP"];
connectionInfo.VNCProxyPort = (int)dataRow["VNCProxyPort"];
connectionInfo.VNCProxyUsername = (string)dataRow["VNCProxyUsername"];
connectionInfo.VNCProxyPassword = DecryptValue((string)dataRow["VNCProxyPassword"]);
connectionInfo.VNCProxyPassword = (string)dataRow["VNCProxyPassword"];
connectionInfo.VNCColors = (ProtocolVNC.Colors)Enum.Parse(typeof(ProtocolVNC.Colors), (string)dataRow["VNCColors"]);
connectionInfo.VNCSmartSizeMode = (ProtocolVNC.SmartSizeMode)Enum.Parse(typeof(ProtocolVNC.SmartSizeMode), (string)dataRow["VNCSmartSizeMode"]);
connectionInfo.VNCViewOnly = (bool)dataRow["VNCViewOnly"];
@@ -134,7 +135,7 @@ namespace mRemoteNG.Config.Serializers.MsSql
connectionInfo.RDGatewayHostname = (string)dataRow["RDGatewayHostname"];
connectionInfo.RDGatewayUseConnectionCredentials = (RdpProtocol.RDGatewayUseConnectionCredentials)Enum.Parse(typeof(RdpProtocol.RDGatewayUseConnectionCredentials), (string)dataRow["RDGatewayUseConnectionCredentials"]);
connectionInfo.RDGatewayUsername = (string)dataRow["RDGatewayUsername"];
connectionInfo.RDGatewayPassword = DecryptValue((string)dataRow["RDGatewayPassword"]);
connectionInfo.RDGatewayPassword = (string)dataRow["RDGatewayPassword"];
connectionInfo.RDGatewayDomain = (string)dataRow["RDGatewayDomain"];
connectionInfo.Inheritance.CacheBitmaps = (bool)dataRow["InheritCacheBitmaps"];
@@ -155,6 +156,7 @@ namespace mRemoteNG.Config.Serializers.MsSql
connectionInfo.Inheritance.RedirectKeys = (bool)dataRow["InheritRedirectKeys"];
connectionInfo.Inheritance.RedirectPorts = (bool)dataRow["InheritRedirectPorts"];
connectionInfo.Inheritance.RedirectPrinters = (bool)dataRow["InheritRedirectPrinters"];
connectionInfo.Inheritance.RedirectClipboard = (bool)dataRow["InheritRedirectClipboard"];
connectionInfo.Inheritance.RedirectSmartCards = (bool)dataRow["InheritRedirectSmartCards"];
connectionInfo.Inheritance.RedirectSound = (bool)dataRow["InheritRedirectSound"];
connectionInfo.Inheritance.SoundQuality = (bool)dataRow["InheritSoundQuality"];
@@ -193,26 +195,10 @@ namespace mRemoteNG.Config.Serializers.MsSql
connectionInfo.Inheritance.RDGatewayDomain = (bool)dataRow["InheritRDGatewayDomain"];
}
private string DecryptValue(string cipherText)
{
try
{
return _cryptographyProvider.Decrypt(cipherText, _decryptionKey);
}
catch (EncryptionException)
{
// value may not be encrypted
return cipherText;
}
}
private ConnectionTreeModel CreateNodeHierarchy(List<ConnectionInfo> connectionList, DataTable dataTable)
{
var connectionTreeModel = new ConnectionTreeModel();
var rootNode = new RootNodeInfo(RootNodeType.Connection, "0")
{
PasswordString = _decryptionKey.ConvertToUnsecureString()
};
var rootNode = new RootNodeInfo(RootNodeType.Connection, "0");
connectionTreeModel.AddRootNode(rootNode);
foreach (DataRow row in dataTable.Rows)

View File

@@ -1,31 +1,25 @@
using mRemoteNG.Connection;
using System;
using System.Data;
using System.Data.SqlTypes;
using System.Linq;
using mRemoteNG.Connection;
using mRemoteNG.Container;
using mRemoteNG.Security;
using mRemoteNG.Tree;
using mRemoteNG.Tree.Root;
using System;
using System.Data;
using System.Data.SqlTypes;
using System.Linq;
using System.Security;
using mRemoteNG.Tools;
namespace mRemoteNG.Config.Serializers.MsSql
namespace mRemoteNG.Config.Serializers
{
public class DataTableSerializer : ISerializer<ConnectionInfo,DataTable>
{
private readonly ICryptographyProvider _cryptographyProvider;
private readonly SecureString _encryptionKey;
private DataTable _dataTable;
private const string TableName = "tblCons";
private readonly SaveFilter _saveFilter;
private int _currentNodeIndex;
public DataTableSerializer(SaveFilter saveFilter, ICryptographyProvider cryptographyProvider, SecureString encryptionKey)
public DataTableSerializer(SaveFilter saveFilter)
{
_saveFilter = saveFilter.ThrowIfNull(nameof(saveFilter));
_cryptographyProvider = cryptographyProvider.ThrowIfNull(nameof(cryptographyProvider));
_encryptionKey = encryptionKey.ThrowIfNull(nameof(encryptionKey));
_saveFilter = saveFilter;
}
@@ -97,6 +91,7 @@ namespace mRemoteNG.Config.Serializers.MsSql
dataTable.Columns.Add("RedirectDiskDrives", typeof(bool));
dataTable.Columns.Add("RedirectPorts", typeof(bool));
dataTable.Columns.Add("RedirectPrinters", typeof(bool));
dataTable.Columns.Add("RedirectClipboard", typeof(bool));
dataTable.Columns.Add("RedirectSmartCards", typeof(bool));
dataTable.Columns.Add("RedirectSound", typeof(string));
dataTable.Columns.Add("RedirectKeys", typeof(bool));
@@ -141,6 +136,7 @@ namespace mRemoteNG.Config.Serializers.MsSql
dataTable.Columns.Add("InheritRedirectKeys", typeof(bool));
dataTable.Columns.Add("InheritRedirectPorts", typeof(bool));
dataTable.Columns.Add("InheritRedirectPrinters", typeof(bool));
dataTable.Columns.Add("InheritRedirectClipboard", typeof(bool));
dataTable.Columns.Add("InheritRedirectSmartCards", typeof(bool));
dataTable.Columns.Add("InheritRedirectSound", typeof(bool));
dataTable.Columns.Add("InheritResolution", typeof(bool));
@@ -210,15 +206,14 @@ namespace mRemoteNG.Config.Serializers.MsSql
dataRow["ParentID"] = connectionInfo.Parent?.ConstantID ?? "";
dataRow["PositionID"] = _currentNodeIndex;
dataRow["LastChange"] = (SqlDateTime)DateTime.Now;
dataRow["Expanded"] = false; // TODO: this column can eventually be removed. we now save this property locally
var info = connectionInfo as ContainerInfo;
dataRow["Expanded"] = info != null && info.IsExpanded;
dataRow["Description"] = connectionInfo.Description;
dataRow["Icon"] = connectionInfo.Icon;
dataRow["Panel"] = connectionInfo.Panel;
dataRow["Username"] = _saveFilter.SaveUsername ? connectionInfo.Username : "";
dataRow["DomainName"] = _saveFilter.SaveDomain ? connectionInfo.Domain : "";
dataRow["Password"] = _saveFilter.SavePassword
? _cryptographyProvider.Encrypt(connectionInfo.Password, _encryptionKey)
: "";
dataRow["Password"] = _saveFilter.SavePassword ? connectionInfo.Password : "";
dataRow["Hostname"] = connectionInfo.Hostname;
dataRow["Protocol"] = connectionInfo.Protocol;
dataRow["PuttySession"] = connectionInfo.PuttySession;
@@ -242,11 +237,12 @@ namespace mRemoteNG.Config.Serializers.MsSql
dataRow["RedirectDiskDrives"] = connectionInfo.RedirectDiskDrives;
dataRow["RedirectPorts"] = connectionInfo.RedirectPorts;
dataRow["RedirectPrinters"] = connectionInfo.RedirectPrinters;
dataRow["RedirectClipboard"] = connectionInfo.RedirectClipboard;
dataRow["RedirectSmartCards"] = connectionInfo.RedirectSmartCards;
dataRow["RedirectSound"] = connectionInfo.RedirectSound;
dataRow["SoundQuality"] = connectionInfo.SoundQuality;
dataRow["RedirectKeys"] = connectionInfo.RedirectKeys;
dataRow["Connected"] = false; // TODO: this column can eventually be removed. we now save this property locally
dataRow["Connected"] = connectionInfo.OpenConnections.Count > 0;
dataRow["PreExtApp"] = connectionInfo.PreExtApp;
dataRow["PostExtApp"] = connectionInfo.PostExtApp;
dataRow["MacAddress"] = connectionInfo.MacAddress;
@@ -259,14 +255,14 @@ namespace mRemoteNG.Config.Serializers.MsSql
dataRow["VNCProxyIP"] = connectionInfo.VNCProxyIP;
dataRow["VNCProxyPort"] = connectionInfo.VNCProxyPort;
dataRow["VNCProxyUsername"] = connectionInfo.VNCProxyUsername;
dataRow["VNCProxyPassword"] = _cryptographyProvider.Encrypt(connectionInfo.VNCProxyPassword, _encryptionKey);
dataRow["VNCProxyPassword"] = connectionInfo.VNCProxyPassword;
dataRow["VNCColors"] = connectionInfo.VNCColors;
dataRow["VNCSmartSizeMode"] = connectionInfo.VNCSmartSizeMode;
dataRow["VNCViewOnly"] = connectionInfo.VNCViewOnly;
dataRow["RDGatewayUsageMethod"] = connectionInfo.RDGatewayUsageMethod;
dataRow["RDGatewayHostname"] = connectionInfo.RDGatewayHostname;
dataRow["RDGatewayUseConnectionCredentials"] = connectionInfo.RDGatewayUseConnectionCredentials;
dataRow["RDGatewayUsername"] = _cryptographyProvider.Encrypt(connectionInfo.RDGatewayUsername, _encryptionKey);
dataRow["RDGatewayUsername"] = connectionInfo.RDGatewayUsername;
dataRow["RDGatewayPassword"] = connectionInfo.RDGatewayPassword;
dataRow["RDGatewayDomain"] = connectionInfo.RDGatewayDomain;
if (_saveFilter.SaveInheritance)
@@ -289,6 +285,7 @@ namespace mRemoteNG.Config.Serializers.MsSql
dataRow["InheritRedirectKeys"] = connectionInfo.Inheritance.RedirectKeys;
dataRow["InheritRedirectPorts"] = connectionInfo.Inheritance.RedirectPorts;
dataRow["InheritRedirectPrinters"] = connectionInfo.Inheritance.RedirectPrinters;
dataRow["InheritRedirectClipboard"] = connectionInfo.Inheritance.RedirectClipboard;
dataRow["InheritRedirectSmartCards"] = connectionInfo.Inheritance.RedirectSmartCards;
dataRow["InheritRedirectSound"] = connectionInfo.Inheritance.RedirectSound;
dataRow["InheritSoundQuality"] = connectionInfo.Inheritance.SoundQuality;
@@ -346,6 +343,7 @@ namespace mRemoteNG.Config.Serializers.MsSql
dataRow["InheritRedirectKeys"] = false;
dataRow["InheritRedirectPorts"] = false;
dataRow["InheritRedirectPrinters"] = false;
dataRow["InheritRedirectClipboard"] = false;
dataRow["InheritRedirectSmartCards"] = false;
dataRow["InheritRedirectSound"] = false;
dataRow["InheritSoundQuality"] = false;

View File

@@ -108,6 +108,9 @@ namespace mRemoteNG.Config.Serializers
case "redirectprinters":
connectionInfo.RedirectPrinters = value == "1";
break;
case "redirectclipboard":
connectionInfo.RedirectClipboard = value == "1";
break;
case "audiomode":
switch (value)
{

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 */
@@ -40,15 +40,11 @@ namespace mRemoteNG.Config.Serializers
private static void VerifySchemaVersion(XmlNode rdcManNode)
{
if (!int.TryParse(rdcManNode?.Attributes?["schemaVersion"]?.Value, out var version))
throw new FileFormatException("Could not find schema version attribute.");
if (version != 1 && version != 3)
_schemaVersion = Convert.ToInt32(rdcManNode?.Attributes?["schemaVersion"].Value);
if (_schemaVersion != 1 && _schemaVersion != 3)
{
throw new FileFormatException($"Unsupported schema version ({version}).");
throw (new FileFormatException($"Unsupported schema version ({_schemaVersion})."));
}
_schemaVersion = version;
}
private static void VerifyFileVersion(XmlNode rdcManNode)
@@ -118,8 +114,7 @@ namespace mRemoteNG.Config.Serializers
containerPropertiesNode = containerPropertiesNode.SelectSingleNode("./properties");
}
newContainer.Name = containerPropertiesNode?.SelectSingleNode("./name")?.InnerText ?? Language.strNewFolder;
if (bool.TryParse(containerPropertiesNode?.SelectSingleNode("./expanded")?.InnerText, out var expanded))
newContainer.IsExpanded = expanded;
newContainer.IsExpanded = bool.Parse(containerPropertiesNode?.SelectSingleNode("./expanded")?.InnerText ?? "false");
parentContainer.AddChild(newContainer);
return newContainer;
}
@@ -134,19 +129,11 @@ 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 ?? "";
var connectionDisplayName = propertiesNode?.SelectSingleNode("./displayName")?.InnerText;
connectionInfo.Name = !string.IsNullOrWhiteSpace(connectionDisplayName)
? connectionDisplayName
: string.IsNullOrWhiteSpace(connectionInfo.Hostname)
? connectionInfo.Name
: connectionInfo.Hostname;
connectionInfo.Name = propertiesNode?.SelectSingleNode("./displayName")?.InnerText ?? connectionInfo.Hostname;
connectionInfo.Description = propertiesNode?.SelectSingleNode("./comment")?.InnerText ?? string.Empty;
var logonCredentialsNode = xmlNode.SelectSingleNode("./logonCredentials");
@@ -178,12 +165,10 @@ namespace mRemoteNG.Config.Serializers
var connectionSettingsNode = xmlNode.SelectSingleNode("./connectionSettings");
if (connectionSettingsNode?.Attributes?["inherit"]?.Value == "None")
{
if (bool.TryParse(connectionSettingsNode.SelectSingleNode("./connectToConsole")?.InnerText, out var useConsole))
connectionInfo.UseConsoleSession = useConsole;
connectionInfo.UseConsoleSession = bool.Parse(connectionSettingsNode.SelectSingleNode("./connectToConsole")?.InnerText ?? "false");
// ./startProgram
// ./workingDir
if (int.TryParse(connectionSettingsNode.SelectSingleNode("./port")?.InnerText, out var port))
connectionInfo.Port = port;
connectionInfo.Port = Convert.ToInt32(connectionSettingsNode.SelectSingleNode("./port")?.InnerText);
}
else
{
@@ -194,16 +179,12 @@ 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
@@ -222,10 +203,15 @@ namespace mRemoteNG.Config.Serializers
var remoteDesktopNode = xmlNode.SelectSingleNode("./remoteDesktop");
if (remoteDesktopNode?.Attributes?["inherit"]?.Value == "None")
{
connectionInfo.Resolution =
Enum.TryParse<RdpProtocol.RDPResolutions>(remoteDesktopNode.SelectSingleNode("./size")?.InnerText.Replace(" ", ""), true, out var rdpResolution)
? rdpResolution
: RdpProtocol.RDPResolutions.FitToWindow;
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;
}
if (remoteDesktopNode.SelectSingleNode("./sameSizeAsClientArea")?.InnerText == "True")
{
@@ -237,8 +223,9 @@ namespace mRemoteNG.Config.Serializers
connectionInfo.Resolution = RdpProtocol.RDPResolutions.Fullscreen;
}
if (Enum.TryParse<RdpProtocol.RDPColors>(remoteDesktopNode.SelectSingleNode("./colorDepth")?.InnerText, true, out var rdpColors))
connectionInfo.Colors = rdpColors;
var colorDepth = remoteDesktopNode.SelectSingleNode("./colorDepth")?.InnerText;
if (colorDepth != null)
connectionInfo.Colors = (RdpProtocol.RDPColors)Enum.Parse(typeof(RdpProtocol.RDPColors), colorDepth);
}
else
{
@@ -287,17 +274,11 @@ namespace mRemoteNG.Config.Serializers
}
// ./redirectClipboard
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;
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");
connectionInfo.RedirectClipboard = bool.Parse(localResourcesNode?.SelectSingleNode("./redirectClipboard")?.InnerText ?? "false");
}
else
{
@@ -307,6 +288,7 @@ namespace mRemoteNG.Config.Serializers
connectionInfo.Inheritance.RedirectPorts = true;
connectionInfo.Inheritance.RedirectPrinters = true;
connectionInfo.Inheritance.RedirectSmartCards = true;
connectionInfo.Inheritance.RedirectClipboard = true;
}
var securitySettingsNode = xmlNode.SelectSingleNode("./securitySettings");

View File

@@ -0,0 +1,41 @@
using System;
using System.Data.SqlClient;
using System.Globalization;
using mRemoteNG.App;
using mRemoteNG.Config.DatabaseConnectors;
using mRemoteNG.Messages;
namespace mRemoteNG.Config.Serializers.Versioning
{
public class SqlDatabaseVersionRetriever
{
public Version GetDatabaseVersion(SqlDatabaseConnector sqlDatabaseConnector)
{
Version databaseVersion;
SqlDataReader sqlDataReader = null;
try
{
var sqlCommand = new SqlCommand("SELECT * FROM tblRoot", sqlDatabaseConnector.SqlConnection);
if (!sqlDatabaseConnector.IsConnected)
sqlDatabaseConnector.Connect();
sqlDataReader = sqlCommand.ExecuteReader();
if (!sqlDataReader.HasRows)
return new Version(); // assume new empty database
else
sqlDataReader.Read();
databaseVersion = new Version(Convert.ToString(sqlDataReader["confVersion"], CultureInfo.InvariantCulture));
}
catch (Exception ex)
{
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, $"Retrieving database version failed. {ex}");
throw;
}
finally
{
if (sqlDataReader != null && !sqlDataReader.IsClosed)
sqlDataReader.Close();
}
return databaseVersion;
}
}
}

View File

@@ -9,6 +9,7 @@ namespace mRemoteNG.Config.Serializers.Versioning
public class SqlDatabaseVersionVerifier
{
private readonly SqlDatabaseConnector _sqlDatabaseConnector;
private readonly SqlDatabaseVersionRetriever _versionRetriever;
public SqlDatabaseVersionVerifier(SqlDatabaseConnector sqlDatabaseConnector)
{
@@ -16,14 +17,15 @@ namespace mRemoteNG.Config.Serializers.Versioning
throw new ArgumentNullException(nameof(sqlDatabaseConnector));
_sqlDatabaseConnector = sqlDatabaseConnector;
_versionRetriever = new SqlDatabaseVersionRetriever();
}
public bool VerifyDatabaseVersion(Version dbVersion)
public bool VerifyDatabaseVersion()
{
var isVerified = false;
try
{
var databaseVersion = dbVersion;
var databaseVersion = _versionRetriever.GetDatabaseVersion(_sqlDatabaseConnector);
if (databaseVersion.Equals(new Version()))
{

View File

@@ -5,6 +5,7 @@ using mRemoteNG.UI.Window;
using System;
using System.IO;
using mRemoteNG.Messages;
using mRemoteNG.Tools;
using WeifenLuo.WinFormsUI.Docking;
namespace mRemoteNG.Config.Settings
@@ -13,16 +14,13 @@ namespace mRemoteNG.Config.Settings
{
private readonly FrmMain _mainForm;
private readonly MessageCollector _messageCollector;
private readonly Windows _windows;
public DockPanelLayoutLoader(FrmMain mainForm, MessageCollector messageCollector)
public DockPanelLayoutLoader(FrmMain mainForm, MessageCollector messageCollector, Windows windows)
{
if (mainForm == null)
throw new ArgumentNullException(nameof(mainForm));
if (messageCollector == null)
throw new ArgumentNullException(nameof(messageCollector));
_mainForm = mainForm;
_messageCollector = messageCollector;
_mainForm = mainForm.ThrowIfNull(nameof(mainForm));
_messageCollector = messageCollector.ThrowIfNull(nameof(messageCollector));
_windows = windows.ThrowIfNull(nameof(windows));
}
public void LoadPanelsFromXml()
@@ -69,16 +67,16 @@ namespace mRemoteNG.Config.Settings
try
{
if (persistString == typeof(ConfigWindow).ToString())
return Windows.ConfigForm;
return _windows.ConfigForm;
if (persistString == typeof(ConnectionTreeWindow).ToString())
return Windows.TreeForm;
return _windows.TreeForm;
if (persistString == typeof(ErrorAndInfoWindow).ToString())
return Windows.ErrorsForm;
return _windows.ErrorsForm;
if (persistString == typeof(ScreenshotManagerWindow).ToString())
return Windows.ScreenshotForm;
return _windows.ScreenshotForm;
}
catch (Exception ex)
{

View File

@@ -25,7 +25,7 @@ namespace mRemoteNG.Config.Settings
_dataProvider = dataProvider;
}
public void Save()
public void Save(DockPanel dockPanel)
{
try
{
@@ -34,7 +34,7 @@ namespace mRemoteNG.Config.Settings
Directory.CreateDirectory(SettingsFileInfo.SettingsPath);
}
var serializedLayout = _dockPanelSerializer.Serialize(FrmMain.Default.pnlDock);
var serializedLayout = _dockPanelSerializer.Serialize(dockPanel);
_dataProvider.Save(serializedLayout);
}
catch (Exception ex)

View File

@@ -4,6 +4,7 @@ using mRemoteNG.App.Info;
using mRemoteNG.UI.Forms;
using System.IO;
using System.Xml;
using mRemoteNG.Connection;
using mRemoteNG.Messages;
using mRemoteNG.Tools;
using mRemoteNG.UI.Controls;
@@ -12,22 +13,20 @@ namespace mRemoteNG.Config.Settings
{
public class ExternalAppsLoader
{
private readonly FrmMain _mainForm;
private readonly MessageCollector _messageCollector;
private readonly ExternalToolsToolStrip _externalToolsToolStrip;
private readonly IConnectionInitiator _connectionInitiator;
private readonly ExternalToolsService _externalToolsService;
private readonly IConnectionsService _connectionsService;
public ExternalAppsLoader(FrmMain mainForm, MessageCollector messageCollector, ExternalToolsToolStrip externalToolsToolStrip)
public ExternalAppsLoader(MessageCollector messageCollector, ExternalToolsToolStrip externalToolsToolStrip,
IConnectionInitiator connectionInitiator, ExternalToolsService externalToolsService, IConnectionsService connectionsService)
{
if (mainForm == null)
throw new ArgumentNullException(nameof(mainForm));
if (messageCollector == null)
throw new ArgumentNullException(nameof(messageCollector));
if (externalToolsToolStrip == null)
throw new ArgumentNullException(nameof(externalToolsToolStrip));
_mainForm = mainForm;
_messageCollector = messageCollector;
_externalToolsToolStrip = externalToolsToolStrip;
_messageCollector = messageCollector.ThrowIfNull(nameof(messageCollector));
_externalToolsToolStrip = externalToolsToolStrip.ThrowIfNull(nameof(externalToolsToolStrip));
_connectionInitiator = connectionInitiator.ThrowIfNull(nameof(connectionInitiator));
_externalToolsService = externalToolsService.ThrowIfNull(nameof(externalToolsService));
_connectionsService = connectionsService.ThrowIfNull(nameof(connectionsService));
}
@@ -48,7 +47,6 @@ namespace mRemoteNG.Config.Settings
{
_messageCollector.AddMessage(MessageClass.InformationMsg, $"Loading External Apps from: {oldPath}", true);
xDom.Load(oldPath);
}
#endif
else
@@ -65,7 +63,7 @@ namespace mRemoteNG.Config.Settings
foreach (XmlElement xEl in xDom.DocumentElement.ChildNodes)
{
var extA = new ExternalTool
var extA = new ExternalTool(_connectionInitiator, _connectionsService)
{
DisplayName = xEl.Attributes["DisplayName"].Value,
FileName = xEl.Attributes["FileName"].Value,
@@ -94,7 +92,7 @@ namespace mRemoteNG.Config.Settings
}
_messageCollector.AddMessage(MessageClass.InformationMsg, $"Adding External App: {extA.DisplayName} {extA.FileName} {extA.Arguments}", true);
Runtime.ExternalToolsService.ExternalTools.Add(extA);
_externalToolsService.ExternalTools.Add(extA);
}
_externalToolsToolStrip.SwitchToolBarText(mRemoteNG.Settings.Default.ExtAppsTBShowText);

View File

@@ -23,8 +23,8 @@ namespace mRemoteNG.Config.Settings
private readonly QuickConnectToolStrip _quickConnectToolStrip;
private readonly ExternalToolsToolStrip _externalToolsToolStrip;
private readonly MultiSshToolStrip _multiSshToolStrip;
private FrmMain MainForm { get; }
private readonly Func<NotificationAreaIcon> _notificationAreaIconBuilder;
private readonly FrmMain _frmMain;
public SettingsLoader(
@@ -33,29 +33,19 @@ namespace mRemoteNG.Config.Settings
QuickConnectToolStrip quickConnectToolStrip,
ExternalToolsToolStrip externalToolsToolStrip,
MultiSshToolStrip multiSshToolStrip,
ExternalAppsLoader externalAppsLoader,
Func<NotificationAreaIcon> notificationAreaIconBuilder,
MenuStrip mainMenu)
{
if (mainForm == null)
throw new ArgumentNullException(nameof(mainForm));
if (messageCollector == null)
throw new ArgumentNullException(nameof(messageCollector));
if (quickConnectToolStrip == null)
throw new ArgumentNullException(nameof(quickConnectToolStrip));
if (externalToolsToolStrip == null)
throw new ArgumentNullException(nameof(externalToolsToolStrip));
if (multiSshToolStrip == null)
throw new ArgumentNullException(nameof(multiSshToolStrip));
if (mainMenu == null)
throw new ArgumentNullException(nameof(mainMenu));
MainForm = mainForm;
_messageCollector = messageCollector;
_quickConnectToolStrip = quickConnectToolStrip;
_externalToolsToolStrip = externalToolsToolStrip;
_multiSshToolStrip = multiSshToolStrip;
_mainMenu = mainMenu;
_externalAppsLoader = new ExternalAppsLoader(MainForm, messageCollector, _externalToolsToolStrip);
}
_frmMain = mainForm.ThrowIfNull(nameof(mainForm));
_messageCollector = messageCollector.ThrowIfNull(nameof(messageCollector));
_quickConnectToolStrip = quickConnectToolStrip.ThrowIfNull(nameof(quickConnectToolStrip));
_externalToolsToolStrip = externalToolsToolStrip.ThrowIfNull(nameof(externalToolsToolStrip));
_multiSshToolStrip = multiSshToolStrip.ThrowIfNull(nameof(multiSshToolStrip));
_externalAppsLoader = externalAppsLoader.ThrowIfNull(nameof(externalAppsLoader));
_notificationAreaIconBuilder = notificationAreaIconBuilder.ThrowIfNull(nameof(notificationAreaIconBuilder));
_mainMenu = mainMenu.ThrowIfNull(nameof(mainMenu));
}
#region Public Methods
public void LoadSettings()
@@ -85,10 +75,10 @@ namespace mRemoteNG.Config.Settings
}
}
private static void SetAlwaysShowPanelTabs()
private void SetAlwaysShowPanelTabs()
{
if (mRemoteNG.Settings.Default.AlwaysShowPanelTabs)
FrmMain.Default.pnlDock.DocumentStyle = DocumentStyle.DockingWindow;
_frmMain.pnlDock.DocumentStyle = DocumentStyle.DockingWindow;
}
@@ -103,32 +93,32 @@ namespace mRemoteNG.Config.Settings
private void SetApplicationWindowPositionAndSize()
{
MainForm.WindowState = FormWindowState.Normal;
_frmMain.WindowState = FormWindowState.Normal;
if (mRemoteNG.Settings.Default.MainFormState == FormWindowState.Normal)
{
if (!mRemoteNG.Settings.Default.MainFormLocation.IsEmpty)
MainForm.Location = mRemoteNG.Settings.Default.MainFormLocation;
_frmMain.Location = mRemoteNG.Settings.Default.MainFormLocation;
if (!mRemoteNG.Settings.Default.MainFormSize.IsEmpty)
MainForm.Size = mRemoteNG.Settings.Default.MainFormSize;
_frmMain.Size = mRemoteNG.Settings.Default.MainFormSize;
}
else
{
if (!mRemoteNG.Settings.Default.MainFormRestoreLocation.IsEmpty)
MainForm.Location = mRemoteNG.Settings.Default.MainFormRestoreLocation;
_frmMain.Location = mRemoteNG.Settings.Default.MainFormRestoreLocation;
if (!mRemoteNG.Settings.Default.MainFormRestoreSize.IsEmpty)
MainForm.Size = mRemoteNG.Settings.Default.MainFormRestoreSize;
_frmMain.Size = mRemoteNG.Settings.Default.MainFormRestoreSize;
}
if (mRemoteNG.Settings.Default.MainFormState == FormWindowState.Maximized)
{
MainForm.WindowState = FormWindowState.Maximized;
_frmMain.WindowState = FormWindowState.Maximized;
}
// Make sure the form is visible on the screen
const int minHorizontal = 300;
const int minVertical = 150;
var screenBounds = Screen.FromHandle(MainForm.Handle).Bounds;
var newBounds = MainForm.Bounds;
var screenBounds = Screen.FromHandle(_frmMain.Handle).Bounds;
var newBounds = _frmMain.Bounds;
if (newBounds.Right < screenBounds.Left + minHorizontal)
newBounds.X = screenBounds.Left + minHorizontal - newBounds.Width;
@@ -139,29 +129,29 @@ namespace mRemoteNG.Config.Settings
if (newBounds.Top > screenBounds.Bottom - minVertical)
newBounds.Y = screenBounds.Bottom - minVertical;
MainForm.Location = newBounds.Location;
_frmMain.Location = newBounds.Location;
}
private void SetAutoSave()
{
if (mRemoteNG.Settings.Default.AutoSaveEveryMinutes <= 0) return;
MainForm.tmrAutoSave.Interval = mRemoteNG.Settings.Default.AutoSaveEveryMinutes * 60000;
MainForm.tmrAutoSave.Enabled = true;
_frmMain.tmrAutoSave.Interval = mRemoteNG.Settings.Default.AutoSaveEveryMinutes * 60000;
_frmMain.tmrAutoSave.Enabled = true;
}
private void SetKioskMode()
{
if (!mRemoteNG.Settings.Default.MainFormKiosk) return;
MainForm.Fullscreen.Value = true;
_frmMain.Fullscreen.Value = true;
}
private static void SetShowSystemTrayIcon()
private void SetShowSystemTrayIcon()
{
if (mRemoteNG.Settings.Default.ShowSystemTrayIcon)
Runtime.NotificationAreaIcon = new NotificationAreaIcon();
Runtime.NotificationAreaIcon = _notificationAreaIconBuilder();
}
private static void SetPuttyPath()
private void SetPuttyPath()
{
PuttyBase.PuttyPath = mRemoteNG.Settings.Default.UseCustomPuttyPath ? mRemoteNG.Settings.Default.CustomPuttyPath : GeneralAppInfo.PuttyPath;
}
@@ -265,15 +255,15 @@ namespace mRemoteNG.Config.Settings
switch (panel.ToLower())
{
case "top":
return MainForm.tsContainer.TopToolStripPanel;
return _frmMain.tsContainer.TopToolStripPanel;
case "bottom":
return MainForm.tsContainer.BottomToolStripPanel;
return _frmMain.tsContainer.BottomToolStripPanel;
case "left":
return MainForm.tsContainer.LeftToolStripPanel;
return _frmMain.tsContainer.LeftToolStripPanel;
case "right":
return MainForm.tsContainer.RightToolStripPanel;
return _frmMain.tsContainer.RightToolStripPanel;
default:
return MainForm.tsContainer.TopToolStripPanel;
return _frmMain.tsContainer.TopToolStripPanel;
}
}
@@ -283,4 +273,4 @@ namespace mRemoteNG.Config.Settings
}
#endregion
}
}
}

View File

@@ -6,12 +6,20 @@ using mRemoteNG.Config.DataProviders;
using mRemoteNG.Tools;
using mRemoteNG.UI.Controls;
using mRemoteNG.UI.Forms;
using WeifenLuo.WinFormsUI.Docking;
namespace mRemoteNG.Config.Settings
{
public static class SettingsSaver
public class SettingsSaver
{
public static void SaveSettings(
private readonly ExternalToolsService _externalToolsService;
public SettingsSaver(ExternalToolsService externalToolsService)
{
_externalToolsService = externalToolsService.ThrowIfNull(nameof(externalToolsService));
}
public void SaveSettings(
Control quickConnectToolStrip,
ExternalToolsToolStrip externalToolsToolStrip,
MultiSshToolStrip multiSshToolStrip,
@@ -19,7 +27,7 @@ namespace mRemoteNG.Config.Settings
{
try
{
var windowPlacement = new WindowPlacement(FrmMain.Default);
var windowPlacement = new WindowPlacement(frmMain);
if (frmMain.WindowState == FormWindowState.Minimized & windowPlacement.RestoreToMaximized)
{
frmMain.Opacity = 0;
@@ -53,7 +61,7 @@ namespace mRemoteNG.Config.Settings
mRemoteNG.Settings.Default.Save();
SaveDockPanelLayout();
SaveDockPanelLayout(frmMain.pnlDock);
SaveExternalApps();
}
catch (Exception ex)
@@ -62,7 +70,7 @@ namespace mRemoteNG.Config.Settings
}
}
private static void SaveExternalAppsToolbarLocation(ExternalToolsToolStrip externalToolsToolStrip)
private void SaveExternalAppsToolbarLocation(ExternalToolsToolStrip externalToolsToolStrip)
{
mRemoteNG.Settings.Default.ExtAppsTBLocation = externalToolsToolStrip.Location;
mRemoteNG.Settings.Default.ExtAppsTBVisible = externalToolsToolStrip.Visible;
@@ -74,7 +82,7 @@ namespace mRemoteNG.Config.Settings
}
}
private static void SaveQuickConnectToolbarLocation(Control quickConnectToolStrip)
private void SaveQuickConnectToolbarLocation(Control quickConnectToolStrip)
{
mRemoteNG.Settings.Default.QuickyTBLocation = quickConnectToolStrip.Location;
mRemoteNG.Settings.Default.QuickyTBVisible = quickConnectToolStrip.Visible;
@@ -85,7 +93,7 @@ namespace mRemoteNG.Config.Settings
}
}
private static void SaveMultiSshToolbarLocation(MultiSshToolStrip multiSshToolStrip)
private void SaveMultiSshToolbarLocation(MultiSshToolStrip multiSshToolStrip)
{
mRemoteNG.Settings.Default.MultiSshToolbarLocation = multiSshToolStrip.Location;
mRemoteNG.Settings.Default.MultiSshToolbarVisible = multiSshToolStrip.Visible;
@@ -96,20 +104,20 @@ namespace mRemoteNG.Config.Settings
}
}
private static void SaveDockPanelLayout()
private void SaveDockPanelLayout(DockPanel dockPanel)
{
var panelLayoutXmlFilePath = SettingsFileInfo.SettingsPath + "\\" + SettingsFileInfo.LayoutFileName;
var panelLayoutSaver = new DockPanelLayoutSaver(
new DockPanelLayoutSerializer(),
new FileDataProvider(panelLayoutXmlFilePath)
);
panelLayoutSaver.Save();
panelLayoutSaver.Save(dockPanel);
}
private static void SaveExternalApps()
private void SaveExternalApps()
{
var externalAppsSaver = new ExternalAppsSaver();
externalAppsSaver.Save(Runtime.ExternalToolsService.ExternalTools);
externalAppsSaver.Save(_externalToolsService.ExternalTools);
}
}
}

View File

@@ -57,6 +57,7 @@ namespace mRemoteNG.Connection
private bool _redirectKeys;
private bool _redirectDiskDrives;
private bool _redirectPrinters;
private bool _redirectClipboard;
private bool _redirectPorts;
private bool _redirectSmartCards;
private RdpProtocol.RDPSounds _redirectSound;
@@ -455,6 +456,16 @@ namespace mRemoteNG.Connection
set => SetField(ref _redirectPrinters, value, "RedirectPrinters");
}
[LocalizedAttributes.LocalizedCategory("strCategoryRedirect", 6),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameRedirectClipboard"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionRedirectClipboard"),
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]
public bool RedirectClipboard
{
get { return GetPropertyValue("RedirectClipboard", _redirectClipboard); }
set { SetField(ref _redirectClipboard, value, "RedirectClipboard"); }
}
[LocalizedAttributes.LocalizedCategory("strCategoryRedirect", 6),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameRedirectPorts"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionRedirectPorts"),
@@ -674,7 +685,7 @@ namespace mRemoteNG.Connection
PropertyChanged?.Invoke(sender, new PropertyChangedEventArgs(args.PropertyName));
}
protected void SetField<T>(ref T field, T value, string propertyName = null)
private void SetField<T>(ref T field, T value, string propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(field, value)) return;
field = value;

View File

@@ -313,9 +313,10 @@ namespace mRemoteNG.Connection
RedirectKeys = Settings.Default.ConDefaultRedirectKeys;
RedirectDiskDrives = Settings.Default.ConDefaultRedirectDiskDrives;
RedirectPrinters = Settings.Default.ConDefaultRedirectPrinters;
RedirectClipboard = Settings.Default.ConDefaultRedirectClipboard;
RedirectPorts = Settings.Default.ConDefaultRedirectPorts;
RedirectSmartCards = Settings.Default.ConDefaultRedirectSmartCards;
RedirectSound = (RdpProtocol.RDPSounds) Enum.Parse(typeof(RdpProtocol.RDPSounds), Settings.Default.ConDefaultRedirectSound);
RedirectSound = (RdpProtocol.RDPSounds) Enum.Parse(typeof(RdpProtocol.RDPSounds), Settings.Default.ConDefaultRedirectSound);
SoundQuality = (RdpProtocol.RDPSoundQuality)Enum.Parse(typeof(RdpProtocol.RDPSoundQuality), Settings.Default.ConDefaultSoundQuality);
}

View File

@@ -215,8 +215,13 @@ namespace mRemoteNG.Connection
LocalizedAttributes.LocalizedDisplayNameInheritAttribute("strPropertyNameRedirectPrinters"),
LocalizedAttributes.LocalizedDescriptionInheritAttribute("strPropertyDescriptionRedirectPrinters"),
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]public bool RedirectPrinters {get; set;}
[LocalizedAttributes.LocalizedCategory("strCategoryRedirect", 7),
[LocalizedAttributes.LocalizedCategory("strCategoryRedirect", 7),
LocalizedAttributes.LocalizedDisplayNameInheritAttribute("strPropertyNameRedirectClipboard"),
LocalizedAttributes.LocalizedDescriptionInheritAttribute("strPropertyDescriptionRedirectClipboard"),
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]public bool RedirectClipboard { get; set; }
[LocalizedAttributes.LocalizedCategory("strCategoryRedirect", 7),
LocalizedAttributes.LocalizedDisplayNameInheritAttribute("strPropertyNameRedirectPorts"),
LocalizedAttributes.LocalizedDescriptionInheritAttribute("strPropertyDescriptionRedirectPorts"),
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]public bool RedirectPorts {get; set;}

View File

@@ -1,28 +1,40 @@
using mRemoteNG.App;
using System;
using System.Windows.Forms;
using mRemoteNG.App;
using mRemoteNG.Connection.Protocol;
using mRemoteNG.Connection.Protocol.RDP;
using mRemoteNG.Container;
using mRemoteNG.Messages;
using mRemoteNG.Tools;
using mRemoteNG.UI;
using mRemoteNG.UI.Forms;
using mRemoteNG.UI.Panels;
using mRemoteNG.UI.Window;
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using TabPage = Crownwood.Magic.Controls.TabPage;
namespace mRemoteNG.Connection
{
public class ConnectionInitiator : IConnectionInitiator
{
private readonly PanelAdder _panelAdder = new PanelAdder();
private readonly List<string> _activeConnections = new List<string>();
public class ConnectionInitiator : IConnectionInitiator
{
private readonly WindowList _windowList;
private readonly ExternalToolsService _externalToolsService;
private readonly ProtocolFactory _protocolFactory;
private readonly FrmMain _frmMain;
/// <summary>
/// List of unique IDs of the currently active connections
/// This is a property because we have a circular dependency.
/// </summary>
public IEnumerable<string> ActiveConnections => _activeConnections;
public PanelAdder Adder { get; set; }
public ConnectionInitiator(WindowList windowList, ExternalToolsService externalToolsService, ProtocolFactory protocolFactory, FrmMain frmMain)
{
_frmMain = frmMain;
_windowList = windowList.ThrowIfNull(nameof(windowList));
_externalToolsService = externalToolsService.ThrowIfNull(nameof(externalToolsService));
_protocolFactory = protocolFactory.ThrowIfNull(nameof(protocolFactory));
}
public void OpenConnection(ContainerInfo containerInfo, ConnectionInfo.Force force = ConnectionInfo.Force.None)
{
@@ -60,7 +72,7 @@ namespace mRemoteNG.Connection
var connectionWindow = (ConnectionWindow)interfaceControl.FindForm();
connectionWindow?.Focus();
var findForm = (ConnectionWindow)interfaceControl.FindForm();
findForm?.Show(FrmMain.Default.pnlDock);
findForm?.Show(_frmMain.pnlDock);
var tabPage = (TabPage)interfaceControl.Parent;
tabPage.Selected = true;
return true;
@@ -99,8 +111,7 @@ namespace mRemoteNG.Connection
return;
}
var protocolFactory = new ProtocolFactory();
var newProtocol = protocolFactory.CreateProtocol(connectionInfo);
var newProtocol = _protocolFactory.CreateProtocol(connectionInfo);
var connectionPanel = SetConnectionPanel(connectionInfo, force);
if (string.IsNullOrEmpty(connectionPanel)) return;
@@ -125,8 +136,7 @@ namespace mRemoteNG.Connection
}
connectionInfo.OpenConnections.Add(newProtocol);
_activeConnections.Add(connectionInfo.ConstantID);
FrmMain.Default.SelectedConnection = connectionInfo;
_frmMain.SelectedConnection = connectionInfo;
}
catch (Exception ex)
{
@@ -134,19 +144,19 @@ namespace mRemoteNG.Connection
}
}
private static void StartPreConnectionExternalApp(ConnectionInfo connectionInfo)
private void StartPreConnectionExternalApp(ConnectionInfo connectionInfo)
{
if (connectionInfo.PreExtApp == "") return;
var extA = Runtime.ExternalToolsService.GetExtAppByName(connectionInfo.PreExtApp);
var extA = _externalToolsService.GetExtAppByName(connectionInfo.PreExtApp);
extA?.Start(connectionInfo);
}
private static InterfaceControl FindConnectionContainer(ConnectionInfo connectionInfo)
private InterfaceControl FindConnectionContainer(ConnectionInfo connectionInfo)
{
if (connectionInfo.OpenConnections.Count <= 0) return null;
for (var i = 0; i <= Runtime.WindowList.Count - 1; i++)
for (var i = 0; i <= _windowList.Count - 1; i++)
{
var window = Runtime.WindowList[i] as ConnectionWindow;
var window = _windowList[i] as ConnectionWindow;
var connectionWindow = window;
if (connectionWindow?.TabController == null) continue;
foreach (TabPage t in connectionWindow.TabController.TabPages)
@@ -162,12 +172,12 @@ namespace mRemoteNG.Connection
return null;
}
private static string SetConnectionPanel(ConnectionInfo connectionInfo, ConnectionInfo.Force force)
private string SetConnectionPanel(ConnectionInfo connectionInfo, ConnectionInfo.Force force)
{
var connectionPanel = "";
if (connectionInfo.Panel == "" || (force & ConnectionInfo.Force.OverridePanel) == ConnectionInfo.Force.OverridePanel | Settings.Default.AlwaysShowPanelSelectionDlg)
{
var frmPnl = new frmChoosePanel();
var frmPnl = new frmChoosePanel(Adder, _windowList);
if (frmPnl.ShowDialog() == DialogResult.OK)
{
connectionPanel = frmPnl.Panel;
@@ -186,24 +196,24 @@ namespace mRemoteNG.Connection
private Form SetConnectionForm(Form conForm, string connectionPanel)
{
var connectionForm = conForm ?? Runtime.WindowList.FromString(connectionPanel);
var connectionForm = conForm ?? _windowList.FromString(connectionPanel);
if (connectionForm == null)
connectionForm = _panelAdder.AddPanel(connectionPanel);
connectionForm = Adder.AddPanel(connectionPanel);
else
((ConnectionWindow)connectionForm).Show(FrmMain.Default.pnlDock);
((ConnectionWindow)connectionForm).Show(_frmMain.pnlDock);
connectionForm.Focus();
return connectionForm;
}
private static Control SetConnectionContainer(ConnectionInfo connectionInfo, Form connectionForm)
private Control SetConnectionContainer(ConnectionInfo connectionInfo, Form connectionForm)
{
Control connectionContainer = ((ConnectionWindow)connectionForm).AddConnectionTab(connectionInfo);
if (connectionInfo.Protocol != ProtocolType.IntApp) return connectionContainer;
var extT = Runtime.ExternalToolsService.GetExtAppByName(connectionInfo.ExtApp);
var extT = _externalToolsService.GetExtAppByName(connectionInfo.ExtApp);
if(extT == null) return connectionContainer;
@@ -275,11 +285,9 @@ namespace mRemoteNG.Connection
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, string.Format(Language.strConnenctionClosedByUser, connDetail, prot.InterfaceControl.Info.Protocol, Environment.UserName));
prot.InterfaceControl.Info.OpenConnections.Remove(prot);
if (_activeConnections.Contains(prot.InterfaceControl.Info.ConstantID))
_activeConnections.Remove(prot.InterfaceControl.Info.ConstantID);
if (prot.InterfaceControl.Info.PostExtApp == "") return;
var extA = Runtime.ExternalToolsService.GetExtAppByName(prot.InterfaceControl.Info.PostExtApp);
var extA = _externalToolsService.GetExtAppByName(prot.InterfaceControl.Info.PostExtApp);
extA?.Start(prot.InterfaceControl.Info);
}
catch (Exception ex)

View File

@@ -1,15 +1,14 @@
using System;
using System.IO;
using System.Security;
using System.Threading;
using System.Windows.Forms;
using mRemoteNG.App;
using mRemoteNG.App.Info;
using mRemoteNG.Config;
using mRemoteNG.Config.Connections;
using mRemoteNG.Config.Connections.Multiuser;
using mRemoteNG.Config.DataProviders;
using mRemoteNG.Config.DatabaseConnectors;
using mRemoteNG.Config.Putty;
using mRemoteNG.Config.Serializers.MsSql;
using mRemoteNG.Connection.Protocol;
using mRemoteNG.Messages;
using mRemoteNG.Security;
@@ -17,15 +16,17 @@ using mRemoteNG.Tools;
using mRemoteNG.Tree;
using mRemoteNG.Tree.Root;
using mRemoteNG.UI;
using mRemoteNG.UI.TaskDialog;
namespace mRemoteNG.Connection
{
public class ConnectionsService
public class ConnectionsService : IConnectionsService
{
private static readonly object SaveLock = new object();
private bool _showDialogWhenLoadingConnections;
private readonly PuttySessionsManager _puttySessionsManager;
private readonly IDataProvider<string> _localConnectionPropertiesDataProvider;
private readonly LocalConnectionPropertiesXmlSerializer _localConnectionPropertiesSerializer;
private readonly Import _import;
private readonly IWin32Window _dialogWindowParent;
private bool _batchingSaves = false;
private bool _saveRequested = false;
private bool _saveAsyncRequested = false;
@@ -35,18 +36,16 @@ namespace mRemoteNG.Connection
public string ConnectionFileName { get; private set; }
public RemoteConnectionsSyncronizer RemoteConnectionsSyncronizer { get; set; }
public DateTime LastSqlUpdate { get; set; }
public SecureString EncryptionKey { get; set; } = new RootNodeInfo(RootNodeType.Connection).PasswordString.ConvertToSecureString();
// TODO - this is only a property to break up a circular dependency. move to ctor when able
public DatabaseConnectorFactory DatabaseConnectorFactory { get; set; }
public ConnectionTreeModel ConnectionTreeModel { get; private set; }
public ConnectionsService(PuttySessionsManager puttySessionsManager)
public ConnectionsService(PuttySessionsManager puttySessionsManager, Import import, IWin32Window dialogWindowParent)
{
if (puttySessionsManager == null)
throw new ArgumentNullException(nameof(puttySessionsManager));
_puttySessionsManager = puttySessionsManager;
var path = SettingsFileInfo.SettingsPath;
_localConnectionPropertiesDataProvider = new FileDataProvider(Path.Combine(path, "LocalConnectionProperties.xml"));
_localConnectionPropertiesSerializer = new LocalConnectionPropertiesXmlSerializer();
_puttySessionsManager = puttySessionsManager.ThrowIfNull(nameof(puttySessionsManager));
_import = import.ThrowIfNull(nameof(import));
_dialogWindowParent = dialogWindowParent.ThrowIfNull(nameof(dialogWindowParent));
}
public void NewConnectionsFile(string filename)
@@ -114,18 +113,13 @@ namespace mRemoteNG.Connection
var oldConnectionTreeModel = ConnectionTreeModel;
var oldIsUsingDatabaseValue = UsingDatabase;
var connectionLoader = useDatabase
? (IConnectionsLoader)new SqlConnectionsLoader(_localConnectionPropertiesSerializer, _localConnectionPropertiesDataProvider)
: new XmlConnectionsLoader(connectionFileName);
var newConnectionTreeModel = connectionLoader.Load();
if (useDatabase)
LastSqlUpdate = DateTime.Now;
var newConnectionTreeModel = useDatabase
? new SqlConnectionsLoader(DatabaseConnectorFactory, this).Load()
: new XmlConnectionsLoader(connectionFileName, this, _dialogWindowParent).Load();
if (newConnectionTreeModel == null)
{
DialogFactory.ShowLoadConnectionsFailedDialog(connectionFileName, "Decrypting connection file failed", IsConnectionsFileLoaded);
DialogFactory.ShowLoadConnectionsFailedDialog(connectionFileName, "Decrypting connection file failed", IsConnectionsFileLoaded, this);
return;
}
@@ -142,7 +136,6 @@ namespace mRemoteNG.Connection
ConnectionTreeModel = newConnectionTreeModel;
UpdateCustomConsPathSetting(connectionFileName);
RaiseConnectionsLoadedEvent(oldConnectionTreeModel, newConnectionTreeModel, oldIsUsingDatabaseValue, useDatabase, connectionFileName);
Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, $"Connections loaded using {connectionLoader.GetType().Name}");
}
/// <summary>
@@ -171,19 +164,6 @@ namespace mRemoteNG.Connection
SaveConnections();
}
/// <summary>
/// All calls to <see cref="SaveConnections()"/> or <see cref="SaveConnectionsAsync"/>
/// will be deferred until the returned <see cref="DisposableAction"/> is disposed.
/// Once disposed, this will immediately executes a single <see cref="SaveConnections()"/>
/// or <see cref="SaveConnectionsAsync"/> if one has been requested.
/// Place this call in a 'using' block to represent a batched saving context.
/// </summary>
/// <returns></returns>
public DisposableAction BatchedSavingContext()
{
return new DisposableAction(BeginBatchingSaves, EndBatchingSaves);
}
/// <summary>
/// Saves the currently loaded <see cref="ConnectionTreeModel"/> with
/// no <see cref="SaveFilter"/>.
@@ -202,17 +182,7 @@ namespace mRemoteNG.Connection
/// <param name="saveFilter"></param>
/// <param name="connectionFileName"></param>
/// <param name="forceSave">Bypasses safety checks that prevent saving if a connection file isn't loaded.</param>
/// <param name="propertyNameTrigger">
/// Optional. The name of the property that triggered
/// this save.
/// </param>
public void SaveConnections(
ConnectionTreeModel connectionTreeModel,
bool useDatabase,
SaveFilter saveFilter,
string connectionFileName,
bool forceSave = false,
string propertyNameTrigger = "")
public void SaveConnections(ConnectionTreeModel connectionTreeModel, bool useDatabase, SaveFilter saveFilter, string connectionFileName, bool forceSave = false)
{
if (connectionTreeModel == null)
return;
@@ -232,13 +202,10 @@ namespace mRemoteNG.Connection
RemoteConnectionsSyncronizer?.Disable();
var previouslyUsingDatabase = UsingDatabase;
var saver = useDatabase
? (ISaver<ConnectionTreeModel>)new SqlConnectionsSaver(saveFilter, _localConnectionPropertiesSerializer,
_localConnectionPropertiesDataProvider)
: new XmlConnectionsSaver(connectionFileName, saveFilter);
saver.Save(connectionTreeModel, propertyNameTrigger);
if (useDatabase)
new SqlConnectionsSaver(saveFilter, this, DatabaseConnectorFactory).Save(connectionTreeModel);
else
new XmlConnectionsSaver(connectionFileName, saveFilter).Save(connectionTreeModel);
if (UsingDatabase)
LastSqlUpdate = DateTime.Now;
@@ -258,14 +225,7 @@ namespace mRemoteNG.Connection
}
}
/// <summary>
/// Save the currently loaded connections asynchronously
/// </summary>
/// <param name="propertyNameTrigger">
/// Optional. The name of the property that triggered
/// this save.
/// </param>
public void SaveConnectionsAsync(string propertyNameTrigger = "")
public void SaveConnectionsAsync()
{
if (_batchingSaves)
{
@@ -273,22 +233,170 @@ namespace mRemoteNG.Connection
return;
}
var t = new Thread(() =>
{
lock (SaveLock)
{
SaveConnections(
ConnectionTreeModel,
UsingDatabase,
new SaveFilter(),
ConnectionFileName,
propertyNameTrigger: propertyNameTrigger);
}
});
var t = new Thread(SaveConnectionsBGd);
t.SetApartmentState(ApartmentState.STA);
t.Start();
}
private void SaveConnectionsBGd()
{
lock (SaveLock)
{
SaveConnections();
}
}
public void LoadConnectionsAsync()
{
_showDialogWhenLoadingConnections = false;
var t = new Thread(LoadConnectionsBGd);
t.SetApartmentState(ApartmentState.STA);
t.Start();
}
private void LoadConnectionsBGd()
{
LoadConnections(_showDialogWhenLoadingConnections);
}
public void LoadConnections(bool withDialog = false)
{
var connectionFileName = "";
try
{
// disable sql update checking while we are loading updates
RemoteConnectionsSyncronizer?.Disable();
if (!Settings.Default.UseSQLServer)
{
if (withDialog)
{
var loadDialog = DialogFactory.BuildLoadConnectionsDialog();
if (loadDialog.ShowDialog() != DialogResult.OK) return;
connectionFileName = loadDialog.FileName;
}
else
{
connectionFileName = GetStartupConnectionFileName();
}
}
LoadConnections(Settings.Default.UseSQLServer, false, connectionFileName);
if (Settings.Default.UseSQLServer)
{
LastSqlUpdate = DateTime.Now;
}
else
{
if (connectionFileName == GetDefaultStartupConnectionFileName())
{
Settings.Default.LoadConsFromCustomLocation = false;
}
else
{
Settings.Default.LoadConsFromCustomLocation = true;
Settings.Default.CustomConsPath = connectionFileName;
}
}
// re-enable sql update checking after updates are loaded
RemoteConnectionsSyncronizer?.Enable();
}
catch (Exception ex)
{
if (Settings.Default.UseSQLServer)
{
Runtime.MessageCollector.AddExceptionMessage(Language.strLoadFromSqlFailed, ex);
var commandButtons = string.Join("|", Language.strCommandTryAgain, Language.strCommandOpenConnectionFile, string.Format(Language.strCommandExitProgram, Application.ProductName));
CTaskDialog.ShowCommandBox(Application.ProductName, Language.strLoadFromSqlFailed, Language.strLoadFromSqlFailedContent, MiscTools.GetExceptionMessageRecursive(ex), "", "", commandButtons, false, ESysIcons.Error, ESysIcons.Error);
switch (CTaskDialog.CommandButtonResult)
{
case 0:
LoadConnections(withDialog);
return;
case 1:
Settings.Default.UseSQLServer = false;
LoadConnections(true);
return;
default:
Application.Exit();
return;
}
}
if (ex is FileNotFoundException && !withDialog)
{
Runtime.MessageCollector.AddExceptionMessage(string.Format(Language.strConnectionsFileCouldNotBeLoadedNew, connectionFileName), ex, MessageClass.InformationMsg);
string[] commandButtons =
{
Language.ConfigurationCreateNew,
Language.ConfigurationCustomPath,
Language.ConfigurationImportFile,
Language.strMenuExit
};
var answered = false;
while (!answered)
{
try
{
CTaskDialog.ShowTaskDialogBox(
GeneralAppInfo.ProductName,
Language.ConnectionFileNotFound,
"", "", "", "", "",
string.Join(" | ", commandButtons),
ETaskDialogButtons.None,
ESysIcons.Question,
ESysIcons.Question);
switch (CTaskDialog.CommandButtonResult)
{
case 0:
NewConnectionsFile(connectionFileName);
answered = true;
break;
case 1:
LoadConnections(true);
answered = true;
break;
case 2:
NewConnectionsFile(connectionFileName);
_import.ImportFromFile(ConnectionTreeModel.RootNodes[0]);
answered = true;
break;
case 3:
Application.Exit();
answered = true;
break;
}
}
catch (Exception exc)
{
Runtime.MessageCollector.AddExceptionMessage(string.Format(Language.strConnectionsFileCouldNotBeLoadedNew, connectionFileName), exc, MessageClass.InformationMsg);
}
}
return;
}
Runtime.MessageCollector.AddExceptionStackTrace(string.Format(Language.strConnectionsFileCouldNotBeLoaded, connectionFileName), ex);
if (connectionFileName != GetStartupConnectionFileName())
{
LoadConnections(withDialog);
}
else
{
MessageBox.Show(_dialogWindowParent,
string.Format(Language.strErrorStartupConnectionFileLoad, Environment.NewLine, Application.ProductName, GetStartupConnectionFileName(), MiscTools.GetExceptionMessageRecursive(ex)),
@"Could not load startup file.", MessageBoxButtons.OK, MessageBoxIcon.Error);
Application.Exit();
}
}
}
public string GetStartupConnectionFileName()
{
return Settings.Default.LoadConsFromCustomLocation == false

View File

@@ -1,12 +1,9 @@
using mRemoteNG.Container;
using System.Collections.Generic;
namespace mRemoteNG.Connection
{
public interface IConnectionInitiator
{
IEnumerable<string> ActiveConnections { get; }
void OpenConnection(ConnectionInfo connectionInfo);
void OpenConnection(ContainerInfo containerInfo, ConnectionInfo.Force force = ConnectionInfo.Force.None);

View File

@@ -0,0 +1,39 @@
using System;
using System.Security;
using mRemoteNG.Config.Connections;
using mRemoteNG.Config.Connections.Multiuser;
using mRemoteNG.Config.DatabaseConnectors;
using mRemoteNG.Connection.Protocol;
using mRemoteNG.Security;
using mRemoteNG.Tree;
namespace mRemoteNG.Connection
{
public interface IConnectionsService
{
string ConnectionFileName { get; }
ConnectionTreeModel ConnectionTreeModel { get; }
DatabaseConnectorFactory DatabaseConnectorFactory { get; set; }
SecureString EncryptionKey { get; set; }
bool IsConnectionsFileLoaded { get; set; }
DateTime LastSqlUpdate { get; set; }
RemoteConnectionsSyncronizer RemoteConnectionsSyncronizer { get; set; }
bool UsingDatabase { get; }
event EventHandler<ConnectionsLoadedEventArgs> ConnectionsLoaded;
event EventHandler<ConnectionsSavedEventArgs> ConnectionsSaved;
ConnectionInfo CreateQuickConnect(string connectionString, ProtocolType protocol);
string GetDefaultStartupConnectionFileName();
string GetStartupConnectionFileName();
void LoadConnections(bool withDialog = false);
void LoadConnections(bool useDatabase, bool import, string connectionFileName);
void LoadConnectionsAsync();
void NewConnectionsFile(string filename);
void SaveConnections();
void SaveConnections(ConnectionTreeModel connectionTreeModel, bool useDatabase, SaveFilter saveFilter, string connectionFileName, bool forceSave = false);
void SaveConnectionsAsync();
void BeginBatchingSaves();
void EndBatchingSaves();
}
}

View File

@@ -17,12 +17,15 @@ namespace mRemoteNG.Connection.Protocol.ICA
{
private AxICAClient _icaClient;
private ConnectionInfo _info;
private readonly FrmMain _frmMain = FrmMain.Default;
private readonly FrmMain _frmMain;
private readonly IConnectionsService _connectionsService;
#region Public Methods
public IcaProtocol()
public IcaProtocol(FrmMain frmMain, IConnectionsService connectionsService)
{
try
_frmMain = frmMain.ThrowIfNull(nameof(frmMain));
_connectionsService = connectionsService.ThrowIfNull(nameof(connectionsService));
try
{
Control = new AxICAClient();
}
@@ -144,7 +147,7 @@ namespace mRemoteNG.Connection.Protocol.ICA
if (Settings.Default.DefaultPassword != "")
{
var cryptographyProvider = new LegacyRijndaelCryptographyProvider();
_icaClient.SetProp("ClearPassword", cryptographyProvider.Decrypt(Settings.Default.DefaultPassword, Runtime.EncryptionKey));
_icaClient.SetProp("ClearPassword", cryptographyProvider.Decrypt(Settings.Default.DefaultPassword, _connectionsService.EncryptionKey));
}
}
}

View File

@@ -11,19 +11,25 @@ namespace mRemoteNG.Connection.Protocol
{
public class IntegratedProgram : ProtocolBase
{
#region Private Fields
private readonly ExternalToolsService _externalToolsService;
private ExternalTool _externalTool;
private IntPtr _handle;
private Process _process;
#endregion
private readonly IConnectionsService _connectionsService;
#region Public Methods
public IntegratedProgram(ExternalToolsService externalToolsService, IConnectionsService connectionsService)
{
_externalToolsService = externalToolsService.ThrowIfNull(nameof(externalToolsService));
_connectionsService = connectionsService.ThrowIfNull(nameof(connectionsService));
}
#region Public Methods
public override bool Initialize()
{
if (InterfaceControl.Info == null)
return base.Initialize();
_externalTool = Runtime.ExternalToolsService.GetExtAppByName(InterfaceControl.Info.ExtApp);
_externalTool = _externalToolsService.GetExtAppByName(InterfaceControl.Info.ExtApp);
if (_externalTool == null)
{
@@ -54,7 +60,7 @@ namespace mRemoteNG.Connection.Protocol
return false;
}
var argParser = new ExternalToolArgumentParser(_externalTool.ConnectionInfo);
var argParser = new ExternalToolArgumentParser(_externalTool.ConnectionInfo, _connectionsService);
_process = new Process
{
StartInfo =

View File

@@ -7,11 +7,24 @@ using mRemoteNG.Connection.Protocol.SSH;
using mRemoteNG.Connection.Protocol.Telnet;
using mRemoteNG.Connection.Protocol.VNC;
using System;
using mRemoteNG.Tools;
using mRemoteNG.UI.Forms;
namespace mRemoteNG.Connection.Protocol
{
public class ProtocolFactory
{
private readonly ExternalToolsService _externalToolsService;
private readonly FrmMain _frmMain;
private readonly IConnectionsService _connectionsService;
public ProtocolFactory(ExternalToolsService externalToolsService, FrmMain frmMain, IConnectionsService connectionsService)
{
_externalToolsService = externalToolsService.ThrowIfNull(nameof(externalToolsService));
_frmMain = frmMain.ThrowIfNull(nameof(frmMain));
_connectionsService = connectionsService.ThrowIfNull(nameof(connectionsService));
}
public ProtocolBase CreateProtocol(ConnectionInfo connectionInfo)
{
var newProtocol = default(ProtocolBase);
@@ -19,7 +32,7 @@ namespace mRemoteNG.Connection.Protocol
switch (connectionInfo.Protocol)
{
case ProtocolType.RDP:
newProtocol = new RdpProtocol
newProtocol = new RdpProtocol(_frmMain, _connectionsService)
{
LoadBalanceInfoUseUtf8 = Settings.Default.RdpLoadBalanceInfoUseUtf8
};
@@ -29,19 +42,19 @@ namespace mRemoteNG.Connection.Protocol
newProtocol = new ProtocolVNC();
break;
case ProtocolType.SSH1:
newProtocol = new ProtocolSSH1();
newProtocol = new ProtocolSSH1(_connectionsService);
break;
case ProtocolType.SSH2:
newProtocol = new ProtocolSSH2();
newProtocol = new ProtocolSSH2(_connectionsService);
break;
case ProtocolType.Telnet:
newProtocol = new ProtocolTelnet();
newProtocol = new ProtocolTelnet(_connectionsService);
break;
case ProtocolType.Rlogin:
newProtocol = new ProtocolRlogin();
newProtocol = new ProtocolRlogin(_connectionsService);
break;
case ProtocolType.RAW:
newProtocol = new RawProtocol();
newProtocol = new RawProtocol(_connectionsService);
break;
case ProtocolType.HTTP:
newProtocol = new ProtocolHTTP(connectionInfo.RenderingEngine);
@@ -50,11 +63,11 @@ namespace mRemoteNG.Connection.Protocol
newProtocol = new ProtocolHTTPS(connectionInfo.RenderingEngine);
break;
case ProtocolType.ICA:
newProtocol = new IcaProtocol();
newProtocol = new IcaProtocol(_frmMain, _connectionsService);
((IcaProtocol) newProtocol).tmrReconnect.Elapsed += ((IcaProtocol) newProtocol).tmrReconnect_Elapsed;
break;
case ProtocolType.IntApp:
newProtocol = new IntegratedProgram();
newProtocol = new IntegratedProgram(_externalToolsService, _connectionsService);
if (connectionInfo.ExtApp == "")
{
throw (new Exception(Language.strNoExtAppDefined));

View File

@@ -16,6 +16,12 @@ namespace mRemoteNG.Connection.Protocol
{
private const int IDM_RECONF = 0x50; // PuTTY Settings Menu ID
private bool _isPuttyNg;
private readonly IConnectionsService _connectionsService;
public PuttyBase(IConnectionsService connectionsService)
{
_connectionsService = connectionsService;
}
#region Public Properties
@@ -99,7 +105,7 @@ namespace mRemoteNG.Connection.Protocol
if (Settings.Default.EmptyCredentials == "custom")
{
var cryptographyProvider = new LegacyRijndaelCryptographyProvider();
password = cryptographyProvider.Decrypt(Settings.Default.DefaultPassword, Runtime.EncryptionKey);
password = cryptographyProvider.Decrypt(Settings.Default.DefaultPassword, _connectionsService.EncryptionKey);
}
}

View File

@@ -2,7 +2,8 @@ namespace mRemoteNG.Connection.Protocol.RAW
{
public class RawProtocol : PuttyBase
{
public RawProtocol()
public RawProtocol(IConnectionsService connectionsService)
: base(connectionsService)
{
PuttyProtocol = Putty_Protocol.raw;
}

View File

@@ -30,7 +30,8 @@ namespace mRemoteNG.Connection.Protocol.RDP
private bool _loginComplete;
private bool _redirectKeys;
private bool _alertOnIdleDisconnect;
private readonly FrmMain _frmMain = FrmMain.Default;
private readonly FrmMain _frmMain;
private readonly IConnectionsService _connectionsService;
#region Properties
public bool SmartSize
@@ -92,8 +93,10 @@ namespace mRemoteNG.Connection.Protocol.RDP
#endregion
#region Constructors
public RdpProtocol()
public RdpProtocol(FrmMain frmMain, IConnectionsService connectionsService)
{
_frmMain = frmMain;
_connectionsService = connectionsService;
Control = new AxMsRdpClient8NotSafeForScripting();
}
#endregion
@@ -453,7 +456,7 @@ namespace mRemoteNG.Connection.Protocol.RDP
if (Settings.Default.DefaultPassword != "")
{
var cryptographyProvider = new LegacyRijndaelCryptographyProvider();
_rdpClient.AdvancedSettings2.ClearTextPassword = cryptographyProvider.Decrypt(Settings.Default.DefaultPassword, Runtime.EncryptionKey);
_rdpClient.AdvancedSettings2.ClearTextPassword = cryptographyProvider.Decrypt(Settings.Default.DefaultPassword, _connectionsService.EncryptionKey);
}
}
}
@@ -552,6 +555,7 @@ namespace mRemoteNG.Connection.Protocol.RDP
_rdpClient.AdvancedSettings2.RedirectPrinters = _connectionInfo.RedirectPrinters;
_rdpClient.AdvancedSettings2.RedirectSmartCards = _connectionInfo.RedirectSmartCards;
_rdpClient.SecuredSettings2.AudioRedirectionMode = (int)_connectionInfo.RedirectSound;
_rdpClient.AdvancedSettings.DisableRdpdr = _connectionInfo.RedirectClipboard ? 0 : 1;
}
catch (Exception ex)
{

View File

@@ -3,7 +3,8 @@ namespace mRemoteNG.Connection.Protocol.Rlogin
public class ProtocolRlogin : PuttyBase
{
public ProtocolRlogin()
public ProtocolRlogin(IConnectionsService connectionsService)
: base(connectionsService)
{
this.PuttyProtocol = Putty_Protocol.rlogin;
}

View File

@@ -5,7 +5,7 @@ namespace mRemoteNG.Connection.Protocol.SSH
public class ProtocolSSH1 : PuttyBase
{
public ProtocolSSH1()
public ProtocolSSH1(IConnectionsService connectionsService) : base(connectionsService)
{
this.PuttyProtocol = Putty_Protocol.ssh;
this.PuttySSHVersion = Putty_SSHVersion.ssh1;

View File

@@ -3,7 +3,7 @@ namespace mRemoteNG.Connection.Protocol.SSH
public class ProtocolSSH2 : PuttyBase
{
public ProtocolSSH2()
public ProtocolSSH2(IConnectionsService connectionsService) : base(connectionsService)
{
this.PuttyProtocol = Putty_Protocol.ssh;
this.PuttySSHVersion = Putty_SSHVersion.ssh2;

View File

@@ -3,7 +3,7 @@ namespace mRemoteNG.Connection.Protocol.Serial
public class ProtocolSerial : PuttyBase
{
public ProtocolSerial()
public ProtocolSerial(IConnectionsService connectionsService) : base(connectionsService)
{
this.PuttyProtocol = Putty_Protocol.serial;
}

View File

@@ -3,7 +3,7 @@ namespace mRemoteNG.Connection.Protocol.Telnet
public class ProtocolTelnet : PuttyBase
{
public ProtocolTelnet()
public ProtocolTelnet(IConnectionsService connectionsService) : base(connectionsService)
{
this.PuttyProtocol = Putty_Protocol.telnet;
}

View File

@@ -1,10 +1,18 @@
using mRemoteNG.Connection.Protocol;
using mRemoteNG.Tools;
namespace mRemoteNG.Connection
{
public class WebHelper
{
public static void GoToUrl(string url)
private readonly IConnectionInitiator _connectionInitiator;
public WebHelper(IConnectionInitiator connectionInitiator)
{
_connectionInitiator = connectionInitiator.ThrowIfNull(nameof(connectionInitiator));
}
public void GoToUrl(string url)
{
var connectionInfo = new ConnectionInfo();
connectionInfo.CopyFrom(DefaultConnectionInfo.Instance);
@@ -16,8 +24,7 @@ namespace mRemoteNG.Connection
if (string.IsNullOrEmpty(connectionInfo.Panel))
connectionInfo.Panel = Language.strGeneral;
connectionInfo.IsQuickConnect = true;
var connectionInitiator = new ConnectionInitiator();
connectionInitiator.OpenConnection(connectionInfo, ConnectionInfo.Force.DoNotJump);
_connectionInitiator.OpenConnection(connectionInfo, ConnectionInfo.Force.DoNotJump);
}
}
}

View File

@@ -12,19 +12,13 @@ namespace mRemoteNG.Container
[DefaultProperty("Name")]
public class ContainerInfo : ConnectionInfo, INotifyCollectionChanged
{
private bool _isExpanded;
[Browsable(false)]
[Browsable(false)]
public List<ConnectionInfo> Children { get; } = new List<ConnectionInfo>();
[Category(""), Browsable(false), ReadOnly(false), Bindable(false), DefaultValue(""), DesignOnly(false)]
public bool IsExpanded
{
get => _isExpanded;
set => SetField(ref _isExpanded, value, "IsExpanded");
}
[Category(""), Browsable(false), ReadOnly(false), Bindable(false), DefaultValue(""), DesignOnly(false)]
public bool IsExpanded { get; set; }
[Browsable(false)]
[Browsable(false)]
public override bool IsContainer { get { return true; } set {} }
public ContainerInfo(string uniqueId)

View File

@@ -9,6 +9,8 @@ namespace mRemoteNG.Credential
{
public class CredentialRecordTypeConverter : TypeConverter
{
public static ICredentialRepositoryList CredentialRepositoryList { get; set; }
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(Guid) ||
@@ -34,7 +36,7 @@ namespace mRemoteNG.Credential
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
if (!(value is Guid)) return base.ConvertFrom(context, culture, value);
var matchedCredentials = Runtime.CredentialProviderCatalog.GetCredentialRecords().Where(record => record.Id.Equals(value)).ToArray();
var matchedCredentials = CredentialRepositoryList.GetCredentialRecords().Where(record => record.Id.Equals(value)).ToArray();
return matchedCredentials.Any() ? matchedCredentials.First() : null;
}
}

View File

@@ -6,11 +6,19 @@ using mRemoteNG.Config.DataProviders;
using mRemoteNG.Config.Serializers.CredentialProviderSerializer;
using mRemoteNG.Config.Serializers.CredentialSerializer;
using mRemoteNG.Security.Factories;
using mRemoteNG.Tools;
namespace mRemoteNG.Credential
{
public class CredentialServiceFactory
{
private ICredentialRepositoryList _credentialRepositoryList;
public CredentialServiceFactory(ICredentialRepositoryList credentialRepositoryList)
{
_credentialRepositoryList = credentialRepositoryList.ThrowIfNull(nameof(credentialRepositoryList));
}
// When we get a true CompositionRoot we can move this to that class. We should only require 1 instance of this service at a time
public CredentialServiceFacade Build()
{
@@ -27,7 +35,7 @@ namespace mRemoteNG.Credential
new CredentialRepositoryListDeserializer(credRepoSerializer, credRepoDeserializer));
var repoListSaver = new CredentialRepositoryListSaver(repoListDataProvider);
return new CredentialServiceFacade(Runtime.CredentialProviderCatalog, repoListLoader, repoListSaver);
return new CredentialServiceFacade(_credentialRepositoryList, repoListLoader, repoListSaver);
}
}
}

View File

@@ -2,6 +2,7 @@
using System.Threading.Tasks;
using System.Windows.Forms;
using mRemoteNG.Messages.MessageWriters;
using mRemoteNG.Tools;
using mRemoteNG.UI.Forms;
using mRemoteNG.UI.Window;
using WeifenLuo.WinFormsUI.Docking;
@@ -13,13 +14,14 @@ namespace mRemoteNG.Messages.WriterDecorators
private readonly IMessageTypeFilteringOptions _filter;
private readonly IMessageWriter _decoratedWriter;
private readonly ErrorAndInfoWindow _messageWindow;
private readonly FrmMain _frmMain = FrmMain.Default;
private readonly FrmMain _frmMain;
public MessageFocusDecorator(ErrorAndInfoWindow messageWindow, IMessageTypeFilteringOptions filter, IMessageWriter decoratedWriter)
public MessageFocusDecorator(FrmMain frmMain, ErrorAndInfoWindow messageWindow, IMessageTypeFilteringOptions filter, IMessageWriter decoratedWriter)
{
_filter = filter ?? throw new ArgumentNullException(nameof(filter));
_messageWindow = messageWindow ?? throw new ArgumentNullException(nameof(messageWindow));
_decoratedWriter = decoratedWriter ?? throw new ArgumentNullException(nameof(decoratedWriter));
_frmMain = frmMain.ThrowIfNull(nameof(frmMain));
_filter = filter.ThrowIfNull(nameof(filter));
_messageWindow = messageWindow.ThrowIfNull(nameof(messageWindow));
_decoratedWriter = decoratedWriter.ThrowIfNull(nameof(decoratedWriter));
}
public async void Write(IMessage message)
@@ -91,4 +93,4 @@ namespace mRemoteNG.Messages.WriterDecorators
content.DockState == DockState.DockRightAutoHide;
}
}
}
}

View File

@@ -14,7 +14,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyDescription("Multi-protocol remote connections manager")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("mRemoteNG")]
[assembly: AssemblyCopyright("Copyright © 2019 mRemoteNG Dev Team; 2010-2013 Riley McArdle; 2007-2009 Felix Deimel")]
[assembly: AssemblyCopyright("Copyright © 2018 mRemoteNG Dev Team; 2010-2013 Riley McArdle; 2007-2009 Felix Deimel")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
@@ -33,5 +33,5 @@ using System.Runtime.InteropServices;
// by using the '*' as shown below:
// <Assembly: AssemblyVersion("1.0.*")>
[assembly: AssemblyVersion("1.76.15.*")]
[assembly: AssemblyVersion("1.77.0.*")]
[assembly: NeutralResourcesLanguage("en")]

View File

@@ -12,7 +12,11 @@ namespace mRemoteNG {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.9.0.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.7.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
@@ -563,6 +567,18 @@ namespace mRemoteNG {
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("False")]
public bool ConDefaultRedirectClipboard {
get {
return ((bool)(this["ConDefaultRedirectClipboard"]));
}
set {
this["ConDefaultRedirectClipboard"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("False")]
@@ -983,6 +999,18 @@ namespace mRemoteNG {
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("False")]
public bool InhDefaultRedirectClipboard {
get {
return ((bool)(this["InhDefaultRedirectClipboard"]));
}
set {
this["InhDefaultRedirectClipboard"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("False")]
@@ -2722,17 +2750,5 @@ namespace mRemoteNG {
this["StartUpPanelName"] = value;
}
}
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("False")]
public bool OverrideFIPSCheck {
get {
return ((bool)(this["OverrideFIPSCheck"]));
}
set {
this["OverrideFIPSCheck"] = value;
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More