mirror of
https://github.com/mRemoteNG/mRemoteNG.git
synced 2026-02-17 22:11:48 +08:00
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
This commit is contained in:
@@ -1,4 +1,19 @@
|
||||
1.76.4 Alpha 6 (2018-xx-xx):
|
||||
1.76.5 (2018-xx-xx):
|
||||
|
||||
Fixes:
|
||||
------
|
||||
#1030: Exception thrown if importing from port scan and no tree node is selected
|
||||
#1020: BackupFileKeepCount setting not limiting backup file count
|
||||
#1004: Duplicating root or PuTTy node through hotkey causes unhandled exception
|
||||
#1002: Disabling filtering without clearing keyword leaves filtered state
|
||||
#1001: Connection tree context menu hotkeys stop working and disappear in some cases
|
||||
#999: Some hotkeys stop working if File menu was called when PuTTy Saved Sessions was selected
|
||||
#998: Can sometimes add connection under PuTTY Sessions node
|
||||
#991: Error when deleting host in filtered view
|
||||
#961: Connections file overwritten if correct decryption password not provided
|
||||
|
||||
|
||||
1.76.4 Alpha 6 (2018-06-03):
|
||||
|
||||
Features/Enhancements:
|
||||
----------------------
|
||||
@@ -6,6 +21,7 @@ Features/Enhancements:
|
||||
#942: Improved Russian translation of several items
|
||||
#924: Notification for "No Host Specified" when clicking folders in quick-connect menu
|
||||
#902: Menu bar can once again be moved. View -> "Lock toolbar positions" now also locks the menu position
|
||||
Added option for creating an empty panel on startup
|
||||
|
||||
Fixes:
|
||||
------
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -3,7 +3,7 @@
|
||||
License for use and distribution
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Copyright (C) 1999-2016 Igor Pavlov.
|
||||
Copyright (C) 1999-2018 Igor Pavlov.
|
||||
|
||||
7-Zip Extra files are under the GNU LGPL license.
|
||||
|
||||
|
||||
@@ -1,6 +1,25 @@
|
||||
7-Zip Extra history
|
||||
-------------------
|
||||
|
||||
This file contains only information about changes related to that package exclusively.
|
||||
The full history of changes is listed in history.txt in main 7-Zip program.
|
||||
|
||||
|
||||
18.05 2018-04-30
|
||||
-------------------------
|
||||
- The speed for LZMA/LZMA2 compressing was increased
|
||||
by 8% for fastest/fast compression levels and
|
||||
by 3% for normal/maximum compression levels.
|
||||
|
||||
|
||||
18.03 beta 2018-03-04
|
||||
-------------------------
|
||||
- The speed for single-thread LZMA/LZMA2 decoding
|
||||
was increased by 30% in x64 version and by 3% in x86 version.
|
||||
- 7-Zip now can use multi-threading for 7z/LZMA2 decoding,
|
||||
if there are multiple independent data chunks in LZMA2 stream.
|
||||
|
||||
|
||||
9.35 beta 2014-12-07
|
||||
------------------------------
|
||||
- SFX modules were moved to LZMA SDK package.
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
7-Zip Extra 16.02
|
||||
7-Zip Extra 18.05
|
||||
-----------------
|
||||
|
||||
7-Zip Extra is package of extra modules of 7-Zip.
|
||||
|
||||
7-Zip Copyright (C) 1999-2016 Igor Pavlov.
|
||||
7-Zip Copyright (C) 1999-2018 Igor Pavlov.
|
||||
|
||||
7-Zip is free software. Read License.txt for more information about license.
|
||||
|
||||
|
||||
@@ -13,13 +13,46 @@ param (
|
||||
)
|
||||
|
||||
Write-Output "===== Beginning $($PSCmdlet.MyInvocation.MyCommand) ====="
|
||||
$path_packageZipScript = Join-Path -Path $SolutionDir -ChildPath "Tools\build-relport.cmd"
|
||||
|
||||
if(-not [string]::IsNullOrEmpty($Env:APPVEYOR_BUILD_FOLDER)) {
|
||||
Write-Output "Too early to run via Appveyor - artifacts don't get generated properly. Exiting"
|
||||
Exit
|
||||
}
|
||||
|
||||
Write-Output "Solution Dir: '$($SolutionDir)'"
|
||||
Write-Output "Target Dir: '$($TargetDir)'"
|
||||
$ConfigurationName = $ConfigurationName.Trim()
|
||||
Write-Output "Config Name (tirmmed): '$($ConfigurationName)'"
|
||||
|
||||
|
||||
# Windows Sysinternals Sigcheck from http://technet.microsoft.com/en-us/sysinternals/bb897441
|
||||
$SIGCHECK="$($SolutionDir)Tools\exes\sigcheck.exe"
|
||||
$SEVENZIP="$($SolutionDir)Tools\7zip\7za.exe"
|
||||
|
||||
# Package Zip
|
||||
if ($ConfigurationName -match "Release" -and $ConfigurationName -match "Portable") {
|
||||
if ($ConfigurationName -eq "Release Portable") {
|
||||
Write-Output "Packaging Release Portable ZIP"
|
||||
& $path_packageZipScript
|
||||
|
||||
$version = & $SIGCHECK /accepteula -q -n "$($SolutionDir)mRemoteV1\bin\$($ConfigurationName)\mRemoteNG.exe"
|
||||
|
||||
Write-Output "Version is $($version)"
|
||||
|
||||
$PortableZip="$($SolutionDir)Release\mRemoteNG-Portable-$($version).zip"
|
||||
|
||||
Remove-Item -Recurse "$($SolutionDir)mRemoteV1\bin\package" -ErrorAction SilentlyContinue | Out-Null
|
||||
New-Item "$($SolutionDir)mRemoteV1\bin\package" -ItemType "directory" | Out-Null
|
||||
|
||||
Copy-Item "$($SolutionDir)mRemoteV1\Resources\PuTTYNG.exe" -Destination "$($SolutionDir)mRemoteV1\bin\package"
|
||||
|
||||
#Write-Output "$($SolutionDir)mRemoteV1\bin\$ConfigurationName"
|
||||
#Write-Output "$($SolutionDir)mRemoteV1\bin\package"
|
||||
Copy-Item "$($SolutionDir)mRemoteV1\bin\$ConfigurationName\*" -Destination "$($SolutionDir)mRemoteV1\bin\package" -Recurse -Force
|
||||
Copy-Item "$($SolutionDir)*.txt" -Destination "$($SolutionDir)mRemoteV1\bin\package"
|
||||
|
||||
Write-Output "Creating portable ZIP file $($PortableZip)"
|
||||
Remove-Item -Force $PortableZip -ErrorAction SilentlyContinue
|
||||
& $SEVENZIP a -bt -bd -bb1 -mx=9 -tzip -y -r $PortableZip "$($SolutionDir)mRemoteV1\bin\package\*.*"
|
||||
#& $SEVENZIP a -bt -mx=9 -tzip -y $PortableZip "$($SolutionDir)*.TXT"
|
||||
}
|
||||
else {
|
||||
Write-Output "We will not zip anything - this isnt a portable release build."
|
||||
|
||||
39
Tools/zip_portable_files_appv.ps1
Normal file
39
Tools/zip_portable_files_appv.ps1
Normal file
@@ -0,0 +1,39 @@
|
||||
if([string]::IsNullOrEmpty($Env:APPVEYOR_BUILD_FOLDER)) {
|
||||
Write-Output "NOT running via Appveyor - Exiting"
|
||||
Exit
|
||||
}
|
||||
|
||||
$appvDir = $Env:APPVEYOR_BUILD_FOLDER
|
||||
|
||||
Write-Output "Appveyor Build Dir: '$($appvDir)'"
|
||||
$ConfigurationName = $Env:CONFIGURATION.Trim()
|
||||
Write-Output "Config Name (tirmmed): '$($ConfigurationName)'"
|
||||
|
||||
|
||||
$SIGCHECK="$($SolutionDir)Tools\exes\sigcheck.exe"
|
||||
$SEVENZIP="$($SolutionDir)Tools\7zip\7za.exe"
|
||||
|
||||
if ($ConfigurationName -eq "Release Portable") {
|
||||
Write-Output "Packaging Release Portable ZIP"
|
||||
|
||||
$version = & $SIGCHECK /accepteula -q -n "$($SolutionDir)mRemoteV1\bin\$($ConfigurationName)\mRemoteNG.exe"
|
||||
|
||||
Write-Output "Version is $($version)"
|
||||
|
||||
$PortableZip="$($SolutionDir)Release\mRemoteNG-Portable-$($version).zip"
|
||||
|
||||
Remove-Item -Recurse "$($SolutionDir)mRemoteV1\bin\package" -ErrorAction SilentlyContinue | Out-Null
|
||||
New-Item "$($SolutionDir)mRemoteV1\bin\package" -ItemType "directory" | Out-Null
|
||||
|
||||
Copy-Item "$($SolutionDir)mRemoteV1\Resources\PuTTYNG.exe" -Destination "$($SolutionDir)mRemoteV1\bin\package"
|
||||
|
||||
Copy-Item "$($SolutionDir)mRemoteV1\bin\$ConfigurationName\*" -Destination "$($SolutionDir)mRemoteV1\bin\package" -Recurse -Force
|
||||
Copy-Item "$($SolutionDir)*.txt" -Destination "$($SolutionDir)mRemoteV1\bin\package"
|
||||
|
||||
Write-Output "Creating portable ZIP file $($PortableZip)"
|
||||
Remove-Item -Force $PortableZip -ErrorAction SilentlyContinue
|
||||
& $SEVENZIP a -bt -bd -bb1 -mx=9 -tzip -y -r $PortableZip "$($SolutionDir)mRemoteV1\bin\package\*.*"
|
||||
}
|
||||
else {
|
||||
Write-Output "We will not zip anything - this isnt a portable release build."
|
||||
}
|
||||
12
appveyor.yml
12
appveyor.yml
@@ -1,10 +1,11 @@
|
||||
version: 1.0.{build}
|
||||
version: 1.76.{build}
|
||||
pull_requests:
|
||||
do_not_increment_build_number: true
|
||||
image: Visual Studio 2017
|
||||
configuration:
|
||||
- Release
|
||||
- Release Portable
|
||||
- Release Installer
|
||||
platform: x86
|
||||
clone_depth: 1
|
||||
install:
|
||||
@@ -14,7 +15,14 @@ before_build:
|
||||
build:
|
||||
project: mRemoteV1.sln
|
||||
verbosity: normal
|
||||
after_build:
|
||||
- ps: "if([string]::IsNullOrEmpty($Env:APPVEYOR_BUILD_FOLDER)) {\n Write-Output \"NOT running via Appveyor - Exiting\"\n Exit\n}\n\n$appvDir = $Env:APPVEYOR_BUILD_FOLDER\n\nWrite-Output \"Appveyor Build Dir: '$($appvDir)'\"\n$ConfigurationName = $Env:CONFIGURATION.Trim()\nWrite-Output \"Config Name (tirmmed): '$($ConfigurationName)'\"\n\n\n$SIGCHECK=\"$($SolutionDir)Tools\\exes\\sigcheck.exe\"\n$SEVENZIP=\"$($SolutionDir)Tools\\7zip\\7za.exe\"\n\nif ($ConfigurationName -eq \"Release Portable\") {\n Write-Output \"Packaging Release Portable ZIP\"\n \n $version = & $SIGCHECK /accepteula -q -n \"$($SolutionDir)mRemoteV1\\bin\\$($ConfigurationName)\\mRemoteNG.exe\"\n\n Write-Output \"Version is $($version)\"\n\n $PortableZip=\"$($SolutionDir)Release\\mRemoteNG-Portable-$($version).zip\"\n\n Remove-Item -Recurse \"$($SolutionDir)mRemoteV1\\bin\\package\" -ErrorAction SilentlyContinue | Out-Null\n New-Item \"$($SolutionDir)mRemoteV1\\bin\\package\" -ItemType \"directory\" | Out-Null\n \n Copy-Item \"$($SolutionDir)mRemoteV1\\Resources\\PuTTYNG.exe\" -Destination \"$($SolutionDir)mRemoteV1\\bin\\package\"\n\n Copy-Item \"$($SolutionDir)mRemoteV1\\bin\\$ConfigurationName\\*\" -Destination \"$($SolutionDir)mRemoteV1\\bin\\package\" -Recurse -Force \n Copy-Item \"$($SolutionDir)*.txt\" -Destination \"$($SolutionDir)mRemoteV1\\bin\\package\"\n\n Write-Output \"Creating portable ZIP file $($PortableZip)\"\n Remove-Item -Force $PortableZip -ErrorAction SilentlyContinue\n & $SEVENZIP a -bt -bd -bb1 -mx=9 -tzip -y -r $PortableZip \"$($SolutionDir)mRemoteV1\\bin\\package\\*.*\"\n}\nelse {\n Write-Output \"We will not zip anything - this isnt a portable release build.\"\n}"
|
||||
test:
|
||||
assemblies:
|
||||
only:
|
||||
- mRemoteNGTests\bin\$(configuration)\mRemoteNGTests.dll
|
||||
- mRemoteNGTests\bin\$(configuration)\mRemoteNGTests.dll
|
||||
artifacts:
|
||||
- path: Release\*.msi
|
||||
name: mRemoteNG-installer.msi
|
||||
- path: Release\*.zip
|
||||
name: mRemoteNG-portable.zip
|
||||
@@ -5,7 +5,6 @@ using System.Windows.Forms;
|
||||
using System.Xml.Linq;
|
||||
using mRemoteNG.App;
|
||||
using mRemoteNG.Config.Putty;
|
||||
using mRemoteNG.Config.Serializers;
|
||||
using mRemoteNG.Config.Serializers.Xml;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Container;
|
||||
@@ -27,7 +26,7 @@ namespace mRemoteNGTests.Config.Serializers.ConnectionSerializers.Xml
|
||||
var connectionsService = new ConnectionsService(PuttySessionsManager.Instance,
|
||||
new Import(Substitute.For<IWin32Window>()),
|
||||
Substitute.For<IWin32Window>());
|
||||
_xmlConnectionsDeserializer = new XmlConnectionsDeserializer(connectionsService, Substitute.For<IWin32Window>(), password.ConvertToSecureString);
|
||||
_xmlConnectionsDeserializer = new XmlConnectionsDeserializer(connectionsService, Substitute.For<IWin32Window>(), () => password.ConvertToSecureString);
|
||||
_connectionTreeModel = _xmlConnectionsDeserializer.Deserialize(confCons);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using mRemoteNG.Security;
|
||||
using mRemoteNG.Security.Authentication;
|
||||
using mRemoteNG.Security.SymmetricEncryption;
|
||||
using mRemoteNG.Tools;
|
||||
using NUnit.Framework;
|
||||
|
||||
|
||||
@@ -9,35 +10,31 @@ namespace mRemoteNGTests.Security.Authentication
|
||||
{
|
||||
public class PasswordAuthenticatorTests
|
||||
{
|
||||
private PasswordAuthenticator _authenticator;
|
||||
private ICryptographyProvider _cryptographyProvider;
|
||||
private string _cipherText;
|
||||
private readonly SecureString _correctPassword = "9theCorrectPass#5".ConvertToSecureString();
|
||||
private readonly SecureString _wrongPassword = "wrongPassword".ConvertToSecureString();
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
var cryptoProvider = new AeadCryptographyProvider {KeyDerivationIterations = 10000};
|
||||
const string cipherText = "MPELiwk7+xeNlruIyt5uxTvVB+/RLVoLdUGnwY4CWCqwKe7T2IBwWo4oaKum5hdv7447g5m2nZsYPrfARSlotQB4r1KZQg==";
|
||||
_authenticator = new PasswordAuthenticator(cryptoProvider, cipherText);
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void Teardown()
|
||||
{
|
||||
_authenticator = null;
|
||||
_cryptographyProvider = new AeadCryptographyProvider {KeyDerivationIterations = 10000};
|
||||
_cipherText = "MPELiwk7+xeNlruIyt5uxTvVB+/RLVoLdUGnwY4CWCqwKe7T2IBwWo4oaKum5hdv7447g5m2nZsYPrfARSlotQB4r1KZQg==";
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AuthenticatingWithCorrectPasswordReturnsTrue()
|
||||
{
|
||||
var authenticated = _authenticator.Authenticate(_correctPassword);
|
||||
var authenticator = new PasswordAuthenticator(_cryptographyProvider, _cipherText, () => Optional<SecureString>.Empty);
|
||||
var authenticated = authenticator.Authenticate(_correctPassword);
|
||||
Assert.That(authenticated);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AuthenticatingWithWrongPasswordReturnsFalse()
|
||||
{
|
||||
var authenticated = _authenticator.Authenticate(_wrongPassword);
|
||||
var authenticator = new PasswordAuthenticator(_cryptographyProvider, _cipherText, () => Optional<SecureString>.Empty);
|
||||
var authenticated = authenticator.Authenticate(_wrongPassword);
|
||||
Assert.That(!authenticated);
|
||||
}
|
||||
|
||||
@@ -45,12 +42,15 @@ namespace mRemoteNGTests.Security.Authentication
|
||||
public void AuthenticationRequestorIsCalledWhenInitialPasswordIsWrong()
|
||||
{
|
||||
var wasCalled = false;
|
||||
_authenticator.AuthenticationRequestor = () =>
|
||||
|
||||
Optional<SecureString> AuthenticationRequestor()
|
||||
{
|
||||
wasCalled = true;
|
||||
return _correctPassword;
|
||||
};
|
||||
_authenticator.Authenticate(_wrongPassword);
|
||||
}
|
||||
|
||||
var authenticator = new PasswordAuthenticator(_cryptographyProvider, _cipherText, AuthenticationRequestor);
|
||||
authenticator.Authenticate(_wrongPassword);
|
||||
Assert.That(wasCalled);
|
||||
}
|
||||
|
||||
@@ -58,28 +58,30 @@ namespace mRemoteNGTests.Security.Authentication
|
||||
public void AuthenticationRequestorNotCalledWhenInitialPasswordIsCorrect()
|
||||
{
|
||||
var wasCalled = false;
|
||||
_authenticator.AuthenticationRequestor = () =>
|
||||
Optional<SecureString> AuthenticationRequestor()
|
||||
{
|
||||
wasCalled = true;
|
||||
return _correctPassword;
|
||||
};
|
||||
_authenticator.Authenticate(_correctPassword);
|
||||
}
|
||||
|
||||
var authenticator = new PasswordAuthenticator(_cryptographyProvider, _cipherText, AuthenticationRequestor);
|
||||
authenticator.Authenticate(_correctPassword);
|
||||
Assert.That(!wasCalled);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ProvidingCorrectPasswordToTheAuthenticationRequestorReturnsTrue()
|
||||
{
|
||||
_authenticator.AuthenticationRequestor = () => _correctPassword;
|
||||
var authenticated = _authenticator.Authenticate(_wrongPassword);
|
||||
var authenticator = new PasswordAuthenticator(_cryptographyProvider, _cipherText, () => _correctPassword);
|
||||
var authenticated = authenticator.Authenticate(_wrongPassword);
|
||||
Assert.That(authenticated);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AuthenticationFailsWhenAuthenticationRequestorGivenEmptyPassword()
|
||||
{
|
||||
_authenticator.AuthenticationRequestor = () => new SecureString();
|
||||
var authenticated = _authenticator.Authenticate(_wrongPassword);
|
||||
var authenticator = new PasswordAuthenticator(_cryptographyProvider, _cipherText, () => new SecureString());
|
||||
var authenticated = authenticator.Authenticate(_wrongPassword);
|
||||
Assert.That(!authenticated);
|
||||
}
|
||||
|
||||
@@ -87,27 +89,34 @@ namespace mRemoteNGTests.Security.Authentication
|
||||
public void AuthenticatorRespectsMaxAttempts()
|
||||
{
|
||||
var authAttempts = 0;
|
||||
_authenticator.AuthenticationRequestor = () =>
|
||||
Optional<SecureString> AuthenticationRequestor()
|
||||
{
|
||||
authAttempts++;
|
||||
return _wrongPassword;
|
||||
};
|
||||
_authenticator.Authenticate(_wrongPassword);
|
||||
Assert.That(authAttempts == _authenticator.MaxAttempts);
|
||||
}
|
||||
|
||||
var authenticator = new PasswordAuthenticator(_cryptographyProvider, _cipherText, AuthenticationRequestor);
|
||||
authenticator.Authenticate(_wrongPassword);
|
||||
Assert.That(authAttempts == authenticator.MaxAttempts);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AuthenticatorRespectsMaxAttemptsCustomValue()
|
||||
{
|
||||
const int customMaxAttempts = 5;
|
||||
_authenticator.MaxAttempts = customMaxAttempts;
|
||||
var authAttempts = 0;
|
||||
_authenticator.AuthenticationRequestor = () =>
|
||||
Optional<SecureString> AuthenticationRequestor()
|
||||
{
|
||||
authAttempts++;
|
||||
return _wrongPassword;
|
||||
};
|
||||
_authenticator.Authenticate(_wrongPassword);
|
||||
}
|
||||
|
||||
var authenticator =
|
||||
new PasswordAuthenticator(_cryptographyProvider, _cipherText, AuthenticationRequestor)
|
||||
{
|
||||
MaxAttempts = customMaxAttempts
|
||||
};
|
||||
authenticator.Authenticate(_wrongPassword);
|
||||
Assert.That(authAttempts == customMaxAttempts);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using mRemoteNG.Tree.Root;
|
||||
using mRemoteNG.Tree;
|
||||
using mRemoteNG.Tree.Root;
|
||||
using NUnit.Framework;
|
||||
|
||||
|
||||
@@ -46,5 +47,13 @@ namespace mRemoteNGTests.Tree
|
||||
_rootNodeInfo.PasswordString = password;
|
||||
Assert.That(_rootNodeInfo.PasswordString, Is.EqualTo(password));
|
||||
}
|
||||
|
||||
[TestCase(RootNodeType.Connection, TreeNodeType.Root)]
|
||||
[TestCase(RootNodeType.PuttySessions, TreeNodeType.PuttyRoot)]
|
||||
public void RootNodeHasCorrectTreeNodeType(RootNodeType rootNodeType, TreeNodeType expectedTreeNodeType)
|
||||
{
|
||||
var rootNode = new RootNodeInfo(rootNodeType);
|
||||
Assert.That(rootNode.GetTreeNodeType(), Is.EqualTo(expectedTreeNodeType));
|
||||
}
|
||||
}
|
||||
}
|
||||
188
mRemoteNGTests/UI/Controls/ConnectionTreeTests.cs
Normal file
188
mRemoteNGTests/UI/Controls/ConnectionTreeTests.cs
Normal file
@@ -0,0 +1,188 @@
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Container;
|
||||
using mRemoteNG.Tree;
|
||||
using mRemoteNG.Tree.Root;
|
||||
using mRemoteNG.UI.Controls;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace mRemoteNGTests.UI.Controls
|
||||
{
|
||||
public class ConnectionTreeTests
|
||||
{
|
||||
private ConnectionTreeSearchTextFilter _filter;
|
||||
private ConnectionTree _connectionTree;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_filter = new ConnectionTreeSearchTextFilter();
|
||||
_connectionTree = new ConnectionTree
|
||||
{
|
||||
UseFiltering = true
|
||||
};
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Apartment(ApartmentState.STA)]
|
||||
public void FilteringIsRetainedAndUpdatedWhenNodeDeleted()
|
||||
{
|
||||
// root
|
||||
// |- folder1
|
||||
// | |- con1
|
||||
// | |- dontshowme
|
||||
// |- folder2
|
||||
// |- con2
|
||||
var connectionTreeModel = new ConnectionTreeModel();
|
||||
var root = new RootNodeInfo(RootNodeType.Connection);
|
||||
var folder1 = new ContainerInfo {Name = "folder1"};
|
||||
var folder2 = new ContainerInfo {Name = "folder2"};
|
||||
var con1 = new ConnectionInfo {Name = "con1"};
|
||||
var con2 = new ConnectionInfo {Name = "con2"};
|
||||
var conDontShow = new ConnectionInfo {Name = "dontshowme" };
|
||||
root.AddChildRange(new []{folder1, folder2});
|
||||
folder1.AddChildRange(new []{con1, conDontShow});
|
||||
folder2.AddChild(con2);
|
||||
connectionTreeModel.AddRootNode(root);
|
||||
|
||||
_connectionTree.ConnectionTreeModel = connectionTreeModel;
|
||||
// ensure all folders expanded
|
||||
_connectionTree.ExpandAll();
|
||||
|
||||
// apply filtering on the tree
|
||||
_filter.FilterText = "con";
|
||||
_connectionTree.ModelFilter = _filter;
|
||||
|
||||
connectionTreeModel.DeleteNode(con1);
|
||||
|
||||
Assert.That(_connectionTree.IsFiltering, Is.True);
|
||||
Assert.That(_connectionTree.FilteredObjects, Does.Not.Contain(con1));
|
||||
Assert.That(_connectionTree.FilteredObjects, Does.Not.Contain(conDontShow));
|
||||
Assert.That(_connectionTree.FilteredObjects, Does.Contain(con2));
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Apartment(ApartmentState.STA)]
|
||||
public void CannotAddConnectionToPuttySessionNode()
|
||||
{
|
||||
var connectionTreeModel = new ConnectionTreeModel();
|
||||
var root = new RootNodeInfo(RootNodeType.Connection);
|
||||
var puttyRoot = new RootNodeInfo(RootNodeType.PuttySessions);
|
||||
connectionTreeModel.AddRootNode(root);
|
||||
connectionTreeModel.AddRootNode(puttyRoot);
|
||||
|
||||
_connectionTree.ConnectionTreeModel = connectionTreeModel;
|
||||
|
||||
_connectionTree.SelectedObject = puttyRoot;
|
||||
_connectionTree.AddConnection();
|
||||
|
||||
Assert.That(puttyRoot.Children, Is.Empty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Apartment(ApartmentState.STA)]
|
||||
public void CannotAddFolderToPuttySessionNode()
|
||||
{
|
||||
var connectionTreeModel = new ConnectionTreeModel();
|
||||
var root = new RootNodeInfo(RootNodeType.Connection);
|
||||
var puttyRoot = new RootNodeInfo(RootNodeType.PuttySessions);
|
||||
connectionTreeModel.AddRootNode(root);
|
||||
connectionTreeModel.AddRootNode(puttyRoot);
|
||||
|
||||
_connectionTree.ConnectionTreeModel = connectionTreeModel;
|
||||
|
||||
_connectionTree.SelectedObject = puttyRoot;
|
||||
_connectionTree.AddFolder();
|
||||
|
||||
Assert.That(puttyRoot.Children, Is.Empty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Apartment(ApartmentState.STA)]
|
||||
public void CannotDuplicateRootConnectionNode()
|
||||
{
|
||||
var connectionTreeModel = new ConnectionTreeModel();
|
||||
var root = new RootNodeInfo(RootNodeType.Connection);
|
||||
connectionTreeModel.AddRootNode(root);
|
||||
_connectionTree.ConnectionTreeModel = connectionTreeModel;
|
||||
|
||||
_connectionTree.SelectedObject = root;
|
||||
_connectionTree.DuplicateSelectedNode();
|
||||
|
||||
Assert.That(connectionTreeModel.RootNodes, Has.One.Items);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Apartment(ApartmentState.STA)]
|
||||
public void CannotDuplicateRootPuttyNode()
|
||||
{
|
||||
var connectionTreeModel = new ConnectionTreeModel();
|
||||
var puttyRoot = new RootNodeInfo(RootNodeType.PuttySessions);
|
||||
connectionTreeModel.AddRootNode(puttyRoot);
|
||||
_connectionTree.ConnectionTreeModel = connectionTreeModel;
|
||||
|
||||
_connectionTree.SelectedObject = puttyRoot;
|
||||
_connectionTree.DuplicateSelectedNode();
|
||||
|
||||
Assert.That(connectionTreeModel.RootNodes, Has.One.Items);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Apartment(ApartmentState.STA)]
|
||||
public void CannotDuplicatePuttyConnectionNode()
|
||||
{
|
||||
var connectionTreeModel = new ConnectionTreeModel();
|
||||
var puttyRoot = new RootNodeInfo(RootNodeType.PuttySessions);
|
||||
var puttyConnection = new PuttySessionInfo();
|
||||
puttyRoot.AddChild(puttyConnection);
|
||||
connectionTreeModel.AddRootNode(puttyRoot);
|
||||
_connectionTree.ConnectionTreeModel = connectionTreeModel;
|
||||
_connectionTree.ExpandAll();
|
||||
|
||||
_connectionTree.SelectedObject = puttyConnection;
|
||||
_connectionTree.DuplicateSelectedNode();
|
||||
|
||||
Assert.That(puttyRoot.Children, Has.One.Items);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Apartment(ApartmentState.STA)]
|
||||
public void DuplicatingWithNoNodeSelectedDoesNothing()
|
||||
{
|
||||
var connectionTreeModel = new ConnectionTreeModel();
|
||||
var puttyRoot = new RootNodeInfo(RootNodeType.PuttySessions);
|
||||
connectionTreeModel.AddRootNode(puttyRoot);
|
||||
_connectionTree.ConnectionTreeModel = connectionTreeModel;
|
||||
|
||||
_connectionTree.SelectedObject = null;
|
||||
_connectionTree.DuplicateSelectedNode();
|
||||
|
||||
Assert.That(connectionTreeModel.RootNodes, Has.One.Items);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Apartment(ApartmentState.STA)]
|
||||
public void ExpandingAllItemsUpdatesColumnWidthAppropriately()
|
||||
{
|
||||
var connectionTreeModel = new ConnectionTreeModel();
|
||||
var root = new RootNodeInfo(RootNodeType.Connection);
|
||||
connectionTreeModel.AddRootNode(root);
|
||||
ContainerInfo parent = root;
|
||||
foreach (var i in Enumerable.Repeat("", 8))
|
||||
{
|
||||
var newContainer = new ContainerInfo {IsExpanded = false};
|
||||
parent.AddChild(newContainer);
|
||||
parent = newContainer;
|
||||
}
|
||||
|
||||
_connectionTree.ConnectionTreeModel = connectionTreeModel;
|
||||
|
||||
var widthBefore = _connectionTree.Columns[0].Width;
|
||||
_connectionTree.ExpandAll();
|
||||
var widthAfter = _connectionTree.Columns[0].Width;
|
||||
|
||||
Assert.That(widthAfter, Is.GreaterThan(widthBefore));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -209,6 +209,7 @@
|
||||
<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">
|
||||
<SubType>Form</SubType>
|
||||
|
||||
@@ -33,16 +33,19 @@ Global
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Debug Portable|Any CPU.ActiveCfg = Debug Portable|x86
|
||||
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Debug Portable|Any CPU.Build.0 = Debug Portable|x86
|
||||
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Debug Portable|x86.ActiveCfg = Debug Portable|x86
|
||||
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Debug Portable|x86.Build.0 = Debug Portable|x86
|
||||
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Debug|Any CPU.ActiveCfg = Debug|x86
|
||||
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Debug|Any CPU.Build.0 = Debug|x86
|
||||
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Debug|x86.Build.0 = Debug|x86
|
||||
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Release Installer|Any CPU.ActiveCfg = Release Portable|x86
|
||||
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Release Installer|Any CPU.Build.0 = Release Portable|x86
|
||||
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Release Installer|Any CPU.ActiveCfg = Release|x86
|
||||
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Release Installer|Any CPU.Build.0 = Release|x86
|
||||
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Release Installer|x86.ActiveCfg = Release|x86
|
||||
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Release Installer|x86.Build.0 = Release|x86
|
||||
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Release Portable|Any CPU.ActiveCfg = Release Portable|x86
|
||||
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Release Portable|Any CPU.Build.0 = Release Portable|x86
|
||||
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Release Portable|x86.ActiveCfg = Release Portable|x86
|
||||
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Release Portable|x86.Build.0 = Release Portable|x86
|
||||
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Release|Any CPU.ActiveCfg = Release|x86
|
||||
@@ -50,24 +53,26 @@ Global
|
||||
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Release|x86.ActiveCfg = Release|x86
|
||||
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Release|x86.Build.0 = Release|x86
|
||||
{1453B37F-8621-499E-B0B2-6091F76DC0BB}.Debug Portable|Any CPU.ActiveCfg = Debug Portable|x86
|
||||
{1453B37F-8621-499E-B0B2-6091F76DC0BB}.Debug Portable|Any CPU.Build.0 = Debug Portable|x86
|
||||
{1453B37F-8621-499E-B0B2-6091F76DC0BB}.Debug Portable|x86.ActiveCfg = Debug Portable|x86
|
||||
{1453B37F-8621-499E-B0B2-6091F76DC0BB}.Debug Portable|x86.Build.0 = Debug Portable|x86
|
||||
{1453B37F-8621-499E-B0B2-6091F76DC0BB}.Debug|Any CPU.ActiveCfg = Debug|x86
|
||||
{1453B37F-8621-499E-B0B2-6091F76DC0BB}.Debug|Any CPU.Build.0 = Debug|x86
|
||||
{1453B37F-8621-499E-B0B2-6091F76DC0BB}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{1453B37F-8621-499E-B0B2-6091F76DC0BB}.Debug|x86.Build.0 = Debug|x86
|
||||
{1453B37F-8621-499E-B0B2-6091F76DC0BB}.Release Installer|Any CPU.ActiveCfg = Release Portable|x86
|
||||
{1453B37F-8621-499E-B0B2-6091F76DC0BB}.Release Installer|Any CPU.Build.0 = Release Portable|x86
|
||||
{1453B37F-8621-499E-B0B2-6091F76DC0BB}.Release Installer|Any CPU.ActiveCfg = Release|x86
|
||||
{1453B37F-8621-499E-B0B2-6091F76DC0BB}.Release Installer|Any CPU.Build.0 = Release|x86
|
||||
{1453B37F-8621-499E-B0B2-6091F76DC0BB}.Release Installer|x86.ActiveCfg = Release|x86
|
||||
{1453B37F-8621-499E-B0B2-6091F76DC0BB}.Release Installer|x86.Build.0 = Release|x86
|
||||
{1453B37F-8621-499E-B0B2-6091F76DC0BB}.Release Portable|Any CPU.ActiveCfg = Release Portable|x86
|
||||
{1453B37F-8621-499E-B0B2-6091F76DC0BB}.Release Portable|Any CPU.Build.0 = Release Portable|x86
|
||||
{1453B37F-8621-499E-B0B2-6091F76DC0BB}.Release Portable|x86.ActiveCfg = Release Portable|x86
|
||||
{1453B37F-8621-499E-B0B2-6091F76DC0BB}.Release Portable|x86.Build.0 = Release Portable|x86
|
||||
{1453B37F-8621-499E-B0B2-6091F76DC0BB}.Release|Any CPU.ActiveCfg = Release|x86
|
||||
{1453B37F-8621-499E-B0B2-6091F76DC0BB}.Release|Any CPU.Build.0 = Release|x86
|
||||
{1453B37F-8621-499E-B0B2-6091F76DC0BB}.Release|x86.ActiveCfg = Release|x86
|
||||
{1453B37F-8621-499E-B0B2-6091F76DC0BB}.Release|x86.Build.0 = Release|x86
|
||||
{5423D985-CB48-4344-B47F-E8C6D60C8B04}.Debug Portable|Any CPU.ActiveCfg = Release|x86
|
||||
{5423D985-CB48-4344-B47F-E8C6D60C8B04}.Debug Portable|Any CPU.Build.0 = Release|x86
|
||||
{5423D985-CB48-4344-B47F-E8C6D60C8B04}.Debug Portable|Any CPU.ActiveCfg = Debug|x86
|
||||
{5423D985-CB48-4344-B47F-E8C6D60C8B04}.Debug Portable|x86.ActiveCfg = Debug|x86
|
||||
{5423D985-CB48-4344-B47F-E8C6D60C8B04}.Debug|Any CPU.ActiveCfg = Debug|x86
|
||||
{5423D985-CB48-4344-B47F-E8C6D60C8B04}.Debug|x86.ActiveCfg = Debug|x86
|
||||
@@ -77,7 +82,6 @@ Global
|
||||
{5423D985-CB48-4344-B47F-E8C6D60C8B04}.Release Installer|x86.ActiveCfg = Release|x86
|
||||
{5423D985-CB48-4344-B47F-E8C6D60C8B04}.Release Installer|x86.Build.0 = Release|x86
|
||||
{5423D985-CB48-4344-B47F-E8C6D60C8B04}.Release Portable|Any CPU.ActiveCfg = Release|x86
|
||||
{5423D985-CB48-4344-B47F-E8C6D60C8B04}.Release Portable|Any CPU.Build.0 = Release|x86
|
||||
{5423D985-CB48-4344-B47F-E8C6D60C8B04}.Release Portable|x86.ActiveCfg = Release|x86
|
||||
{5423D985-CB48-4344-B47F-E8C6D60C8B04}.Release|Any CPU.ActiveCfg = Release|x86
|
||||
{5423D985-CB48-4344-B47F-E8C6D60C8B04}.Release|Any CPU.Build.0 = Release|x86
|
||||
@@ -86,8 +90,8 @@ Global
|
||||
{F0168B9F-6815-40DF-BA53-46CEE7683B68}.Debug Portable|x86.ActiveCfg = Debug Portable|x86
|
||||
{F0168B9F-6815-40DF-BA53-46CEE7683B68}.Debug|Any CPU.ActiveCfg = Debug|x86
|
||||
{F0168B9F-6815-40DF-BA53-46CEE7683B68}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{F0168B9F-6815-40DF-BA53-46CEE7683B68}.Release Installer|Any CPU.ActiveCfg = Release Portable|x86
|
||||
{F0168B9F-6815-40DF-BA53-46CEE7683B68}.Release Installer|Any CPU.Build.0 = Release Portable|x86
|
||||
{F0168B9F-6815-40DF-BA53-46CEE7683B68}.Release Installer|Any CPU.ActiveCfg = Release|x86
|
||||
{F0168B9F-6815-40DF-BA53-46CEE7683B68}.Release Installer|Any CPU.Build.0 = Release|x86
|
||||
{F0168B9F-6815-40DF-BA53-46CEE7683B68}.Release Installer|x86.ActiveCfg = Release|x86
|
||||
{F0168B9F-6815-40DF-BA53-46CEE7683B68}.Release Installer|x86.Build.0 = Release|x86
|
||||
{F0168B9F-6815-40DF-BA53-46CEE7683B68}.Release Portable|Any CPU.ActiveCfg = Release Portable|x86
|
||||
|
||||
@@ -20,10 +20,9 @@ namespace mRemoteNG.Config.Connections
|
||||
|
||||
private void ConnectionsServiceOnConnectionsLoaded(object sender, ConnectionsLoadedEventArgs connectionsLoadedEventArgs)
|
||||
{
|
||||
|
||||
|
||||
connectionsLoadedEventArgs.NewConnectionTreeModel.CollectionChanged += ConnectionTreeModelOnCollectionChanged;
|
||||
connectionsLoadedEventArgs.NewConnectionTreeModel.PropertyChanged += ConnectionTreeModelOnPropertyChanged;
|
||||
|
||||
foreach (var oldTree in connectionsLoadedEventArgs.PreviousConnectionTreeModel)
|
||||
{
|
||||
oldTree.CollectionChanged -= ConnectionTreeModelOnCollectionChanged;
|
||||
@@ -45,7 +44,8 @@ namespace mRemoteNG.Config.Connections
|
||||
{
|
||||
if (!mRemoteNG.Settings.Default.SaveConnectionsAfterEveryEdit)
|
||||
return;
|
||||
_connectionsService.SaveConnections();
|
||||
|
||||
_connectionsService.SaveConnectionsAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
using System.Security;
|
||||
using System.Windows.Forms;
|
||||
using mRemoteNG.Config.DataProviders;
|
||||
using mRemoteNG.Tools;
|
||||
using mRemoteNG.Tree;
|
||||
using mRemoteNG.Config.Serializers.Xml;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Tools;
|
||||
using mRemoteNG.Tree;
|
||||
|
||||
namespace mRemoteNG.Config.Connections
|
||||
{
|
||||
public class XmlConnectionsLoader
|
||||
public class XmlConnectionsLoader
|
||||
{
|
||||
private readonly IConnectionsService _connectionsService;
|
||||
private readonly string _connectionFilePath;
|
||||
@@ -29,7 +29,7 @@ namespace mRemoteNG.Config.Connections
|
||||
return deserializer.Deserialize(xmlString);
|
||||
}
|
||||
|
||||
private SecureString PromptForPassword()
|
||||
private Optional<SecureString> PromptForPassword()
|
||||
{
|
||||
return MiscTools.PasswordDialog("", false);
|
||||
}
|
||||
|
||||
@@ -1,26 +1,29 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace mRemoteNG.Config.DataProviders
|
||||
{
|
||||
public class FileBackupPruner
|
||||
{
|
||||
public void PruneBackupFiles(string baseName)
|
||||
public void PruneBackupFiles(string filePath, int maxBackupsToKeep)
|
||||
{
|
||||
var fileName = Path.GetFileName(baseName);
|
||||
var directoryName = Path.GetDirectoryName(baseName);
|
||||
var fileName = Path.GetFileName(filePath);
|
||||
var directoryName = Path.GetDirectoryName(filePath);
|
||||
|
||||
if (string.IsNullOrEmpty(fileName) || string.IsNullOrEmpty(directoryName)) return;
|
||||
if (string.IsNullOrEmpty(fileName) || string.IsNullOrEmpty(directoryName))
|
||||
return;
|
||||
|
||||
var searchPattern = string.Format(mRemoteNG.Settings.Default.BackupFileNameFormat, fileName, "*");
|
||||
var files = Directory.GetFiles(directoryName, searchPattern);
|
||||
|
||||
if (files.Length <= mRemoteNG.Settings.Default.BackupFileKeepCount) return;
|
||||
if (files.Length <= maxBackupsToKeep)
|
||||
return;
|
||||
|
||||
Array.Sort(files);
|
||||
Array.Resize(ref files, files.Length - mRemoteNG.Settings.Default.BackupFileKeepCount);
|
||||
var filesToDelete = files
|
||||
.OrderByDescending(s => s)
|
||||
.Skip(maxBackupsToKeep);
|
||||
|
||||
foreach (var file in files)
|
||||
foreach (var file in filesToDelete)
|
||||
{
|
||||
File.Delete(file);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ using mRemoteNG.UI.TaskDialog;
|
||||
|
||||
namespace mRemoteNG.Config.Serializers.Xml
|
||||
{
|
||||
public class XmlConnectionsDeserializer : IDeserializer<string, ConnectionTreeModel>
|
||||
public class XmlConnectionsDeserializer : IDeserializer<string, ConnectionTreeModel>
|
||||
{
|
||||
private readonly IConnectionsService _connectionsService;
|
||||
private XmlDocument _xmlDocument;
|
||||
@@ -32,9 +32,9 @@ namespace mRemoteNG.Config.Serializers.Xml
|
||||
private readonly RootNodeInfo _rootNodeInfo = new RootNodeInfo(RootNodeType.Connection);
|
||||
private readonly IWin32Window _dialogWindowParent;
|
||||
|
||||
public Func<SecureString> AuthenticationRequestor { get; set; }
|
||||
public Func<Optional<SecureString>> AuthenticationRequestor { get; set; }
|
||||
|
||||
public XmlConnectionsDeserializer(IConnectionsService connectionsService, IWin32Window dialogWindowParent, Func<SecureString> authenticationRequestor = null)
|
||||
public XmlConnectionsDeserializer(IConnectionsService connectionsService, IWin32Window dialogWindowParent, Func<Optional<SecureString>> authenticationRequestor = null)
|
||||
{
|
||||
_connectionsService = connectionsService.ThrowIfNull(nameof(connectionsService));
|
||||
_dialogWindowParent = dialogWindowParent.ThrowIfNull(nameof(dialogWindowParent));
|
||||
@@ -52,8 +52,6 @@ namespace mRemoteNG.Config.Serializers.Xml
|
||||
{
|
||||
LoadXmlConnectionData(xml);
|
||||
ValidateConnectionFileVersion();
|
||||
if (!import)
|
||||
_connectionsService.IsConnectionsFileLoaded = false;
|
||||
|
||||
var rootXmlElement = _xmlDocument.DocumentElement;
|
||||
InitializeRootNode(rootXmlElement);
|
||||
@@ -67,8 +65,6 @@ namespace mRemoteNG.Config.Serializers.Xml
|
||||
var protectedString = _xmlDocument.DocumentElement?.Attributes["Protected"].Value;
|
||||
if (!_decryptor.ConnectionsFileIsAuthentic(protectedString, _rootNodeInfo.PasswordString.ConvertToSecureString()))
|
||||
{
|
||||
mRemoteNG.Settings.Default.LoadConsFromCustomLocation = false;
|
||||
mRemoteNG.Settings.Default.CustomConsPath = "";
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Connection.Protocol;
|
||||
@@ -7,8 +9,6 @@ using mRemoteNG.Connection.Protocol.RDP;
|
||||
using mRemoteNG.Container;
|
||||
using mRemoteNG.Tree;
|
||||
using mRemoteNG.Tree.Root;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
|
||||
namespace mRemoteNG.Config.Serializers
|
||||
@@ -60,7 +60,7 @@ namespace mRemoteNG.Config.Serializers
|
||||
}
|
||||
else
|
||||
{
|
||||
var versionNode = rdcManNode.SelectSingleNode("./version")?.InnerText;
|
||||
var versionNode = rdcManNode?.SelectSingleNode("./version")?.InnerText;
|
||||
if (versionNode != null)
|
||||
{
|
||||
var version = new Version(versionNode);
|
||||
@@ -101,15 +101,16 @@ namespace mRemoteNG.Config.Serializers
|
||||
{
|
||||
if (_schemaVersion == 1)
|
||||
{
|
||||
// Program Verison 2.2 wraps all setting inside the Properties tags
|
||||
// Program Version 2.2 wraps all setting inside the Properties tags
|
||||
containerPropertiesNode = containerPropertiesNode.SelectSingleNode("./properties");
|
||||
}
|
||||
var newContainer = new ContainerInfo();
|
||||
var connectionInfo = ConnectionInfoFromXml(containerPropertiesNode);
|
||||
newContainer.CopyFrom(connectionInfo);
|
||||
|
||||
if (_schemaVersion == 3)
|
||||
{
|
||||
// Program Verison 2.7 wraps these properties
|
||||
// Program Version 2.7 wraps these properties
|
||||
containerPropertiesNode = containerPropertiesNode.SelectSingleNode("./properties");
|
||||
}
|
||||
newContainer.Name = containerPropertiesNode?.SelectSingleNode("./name")?.InnerText ?? Language.strNewFolder;
|
||||
@@ -130,20 +131,22 @@ namespace mRemoteNG.Config.Serializers
|
||||
|
||||
|
||||
var propertiesNode = xmlNode.SelectSingleNode("./properties");
|
||||
if (_schemaVersion == 1) propertiesNode = xmlNode; // Version 2.2 defines the container name at the root instead
|
||||
connectionInfo.Hostname = propertiesNode.SelectSingleNode("./name")?.InnerText;
|
||||
connectionInfo.Name = propertiesNode.SelectSingleNode("./displayName")?.InnerText ?? connectionInfo.Hostname;
|
||||
connectionInfo.Description = propertiesNode.SelectSingleNode("./comment")?.InnerText ?? String.Empty;
|
||||
if (_schemaVersion == 1) propertiesNode = xmlNode; // Version 2.2 defines the container name at the root instead
|
||||
connectionInfo.Hostname = propertiesNode?.SelectSingleNode("./name")?.InnerText ?? "";
|
||||
connectionInfo.Name = propertiesNode?.SelectSingleNode("./displayName")?.InnerText ?? connectionInfo.Hostname;
|
||||
connectionInfo.Description = propertiesNode?.SelectSingleNode("./comment")?.InnerText ?? string.Empty;
|
||||
|
||||
var logonCredentialsNode = xmlNode.SelectSingleNode("./logonCredentials");
|
||||
if (logonCredentialsNode?.Attributes?["inherit"].Value == "None")
|
||||
if (logonCredentialsNode?.Attributes?["inherit"]?.Value == "None")
|
||||
{
|
||||
connectionInfo.Username = logonCredentialsNode.SelectSingleNode("userName")?.InnerText;
|
||||
|
||||
var passwordNode = logonCredentialsNode.SelectSingleNode("./password");
|
||||
if (_schemaVersion == 1) // Version 2.2 allows clear text passwords
|
||||
{
|
||||
connectionInfo.Password = passwordNode?.Attributes?["storeAsClearText"].Value == "True" ? passwordNode.InnerText : DecryptRdcManPassword(passwordNode?.InnerText);
|
||||
connectionInfo.Password = passwordNode?.Attributes?["storeAsClearText"]?.Value == "True"
|
||||
? passwordNode.InnerText
|
||||
: DecryptRdcManPassword(passwordNode?.InnerText);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -160,7 +163,7 @@ namespace mRemoteNG.Config.Serializers
|
||||
}
|
||||
|
||||
var connectionSettingsNode = xmlNode.SelectSingleNode("./connectionSettings");
|
||||
if (connectionSettingsNode?.Attributes?["inherit"].Value == "None")
|
||||
if (connectionSettingsNode?.Attributes?["inherit"]?.Value == "None")
|
||||
{
|
||||
connectionInfo.UseConsoleSession = bool.Parse(connectionSettingsNode.SelectSingleNode("./connectToConsole")?.InnerText ?? "false");
|
||||
// ./startProgram
|
||||
@@ -174,7 +177,7 @@ namespace mRemoteNG.Config.Serializers
|
||||
}
|
||||
|
||||
var gatewaySettingsNode = xmlNode.SelectSingleNode("./gatewaySettings");
|
||||
if (gatewaySettingsNode?.Attributes?["inherit"].Value == "None")
|
||||
if (gatewaySettingsNode?.Attributes?["inherit"]?.Value == "None")
|
||||
{
|
||||
connectionInfo.RDGatewayUsageMethod = gatewaySettingsNode.SelectSingleNode("./enabled")?.InnerText == "True" ? RdpProtocol.RDGatewayUsageMethod.Always : RdpProtocol.RDGatewayUsageMethod.Never;
|
||||
connectionInfo.RDGatewayHostname = gatewaySettingsNode.SelectSingleNode("./hostName")?.InnerText;
|
||||
@@ -198,7 +201,7 @@ namespace mRemoteNG.Config.Serializers
|
||||
}
|
||||
|
||||
var remoteDesktopNode = xmlNode.SelectSingleNode("./remoteDesktop");
|
||||
if (remoteDesktopNode?.Attributes?["inherit"].Value == "None")
|
||||
if (remoteDesktopNode?.Attributes?["inherit"]?.Value == "None")
|
||||
{
|
||||
var resolutionString = remoteDesktopNode.SelectSingleNode("./size")?.InnerText.Replace(" ", "");
|
||||
try
|
||||
@@ -231,7 +234,7 @@ namespace mRemoteNG.Config.Serializers
|
||||
}
|
||||
|
||||
var localResourcesNode = xmlNode.SelectSingleNode("./localResources");
|
||||
if (localResourcesNode?.Attributes?["inherit"].Value == "None")
|
||||
if (localResourcesNode?.Attributes?["inherit"]?.Value == "None")
|
||||
{
|
||||
// ReSharper disable once SwitchStatementMissingSomeCases
|
||||
switch (localResourcesNode.SelectSingleNode("./audioRedirection")?.InnerText)
|
||||
@@ -271,10 +274,10 @@ namespace mRemoteNG.Config.Serializers
|
||||
}
|
||||
|
||||
// ./redirectClipboard
|
||||
connectionInfo.RedirectDiskDrives = bool.Parse(localResourcesNode.SelectSingleNode("./redirectDrives")?.InnerText ?? "false");
|
||||
connectionInfo.RedirectPorts = bool.Parse(localResourcesNode.SelectSingleNode("./redirectPorts")?.InnerText ?? "false");
|
||||
connectionInfo.RedirectPrinters = bool.Parse(localResourcesNode.SelectSingleNode("./redirectPrinters")?.InnerText ?? "false");
|
||||
connectionInfo.RedirectSmartCards = bool.Parse(localResourcesNode.SelectSingleNode("./redirectSmartCards")?.InnerText ?? "false");
|
||||
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");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -287,7 +290,7 @@ namespace mRemoteNG.Config.Serializers
|
||||
}
|
||||
|
||||
var securitySettingsNode = xmlNode.SelectSingleNode("./securitySettings");
|
||||
if (securitySettingsNode?.Attributes?["inherit"].Value == "None")
|
||||
if (securitySettingsNode?.Attributes?["inherit"]?.Value == "None")
|
||||
{
|
||||
// ReSharper disable once SwitchStatementMissingSomeCases
|
||||
switch (securitySettingsNode.SelectSingleNode("./authentication")?.InnerText)
|
||||
@@ -321,7 +324,7 @@ namespace mRemoteNG.Config.Serializers
|
||||
private static string DecryptRdcManPassword(string ciphertext)
|
||||
{
|
||||
if (string.IsNullOrEmpty(ciphertext))
|
||||
return null;
|
||||
return string.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
@@ -332,7 +335,7 @@ namespace mRemoteNG.Config.Serializers
|
||||
catch (Exception /*ex*/)
|
||||
{
|
||||
//Runtime.MessageCollector.AddExceptionMessage("RemoteDesktopConnectionManager.DecryptPassword() failed.", ex, logOnly: true);
|
||||
return null;
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ using mRemoteNG.Security;
|
||||
using mRemoteNG.Security.Authentication;
|
||||
using mRemoteNG.Security.Factories;
|
||||
using mRemoteNG.Security.SymmetricEncryption;
|
||||
using mRemoteNG.Tools;
|
||||
using mRemoteNG.Tree.Root;
|
||||
|
||||
namespace mRemoteNG.Config.Serializers
|
||||
@@ -13,7 +14,7 @@ namespace mRemoteNG.Config.Serializers
|
||||
private readonly ICryptographyProvider _cryptographyProvider;
|
||||
private readonly RootNodeInfo _rootNodeInfo;
|
||||
|
||||
public Func<SecureString> AuthenticationRequestor { get; set; }
|
||||
public Func<Optional<SecureString>> AuthenticationRequestor { get; set; }
|
||||
|
||||
public int KeyDerivationIterations
|
||||
{
|
||||
@@ -91,16 +92,14 @@ namespace mRemoteNG.Config.Serializers
|
||||
|
||||
private bool Authenticate(string cipherText, SecureString password)
|
||||
{
|
||||
var authenticator = new PasswordAuthenticator(_cryptographyProvider, cipherText)
|
||||
{
|
||||
AuthenticationRequestor = AuthenticationRequestor
|
||||
};
|
||||
|
||||
var authenticator = new PasswordAuthenticator(_cryptographyProvider, cipherText, AuthenticationRequestor);
|
||||
var authenticated = authenticator.Authenticate(password);
|
||||
|
||||
if (!authenticated) return authenticated;
|
||||
if (!authenticated)
|
||||
return false;
|
||||
|
||||
_rootNodeInfo.PasswordString = authenticator.LastAuthenticatedPassword.ConvertToUnsecureString();
|
||||
return authenticated;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -87,8 +87,8 @@ namespace mRemoteNG.Connection
|
||||
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionName")]
|
||||
public virtual string Name
|
||||
{
|
||||
get { return _name; }
|
||||
set { SetField(ref _name, value, "Name"); }
|
||||
get => _name;
|
||||
set => SetField(ref _name, value, "Name");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryDisplay"),
|
||||
@@ -96,8 +96,8 @@ namespace mRemoteNG.Connection
|
||||
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionDescription")]
|
||||
public virtual string Description
|
||||
{
|
||||
get { return GetPropertyValue("Description", _description); }
|
||||
set { SetField(ref _description, value, "Description"); }
|
||||
get => GetPropertyValue("Description", _description);
|
||||
set => SetField(ref _description, value, "Description");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryDisplay"),
|
||||
@@ -106,8 +106,8 @@ namespace mRemoteNG.Connection
|
||||
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionIcon")]
|
||||
public virtual string Icon
|
||||
{
|
||||
get { return GetPropertyValue("Icon", _icon); }
|
||||
set { SetField(ref _icon, value, "Icon"); }
|
||||
get => GetPropertyValue("Icon", _icon);
|
||||
set => SetField(ref _icon, value, "Icon");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryDisplay"),
|
||||
@@ -115,8 +115,8 @@ namespace mRemoteNG.Connection
|
||||
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionPanel")]
|
||||
public virtual string Panel
|
||||
{
|
||||
get { return GetPropertyValue("Panel", _panel); }
|
||||
set { SetField(ref _panel, value, "Panel"); }
|
||||
get => GetPropertyValue("Panel", _panel);
|
||||
set => SetField(ref _panel, value, "Panel");
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -126,8 +126,8 @@ namespace mRemoteNG.Connection
|
||||
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionAddress")]
|
||||
public virtual string Hostname
|
||||
{
|
||||
get { return _hostname.Trim(); }
|
||||
set { SetField(ref _hostname, value?.Trim(), "Hostname"); }
|
||||
get => _hostname.Trim();
|
||||
set => SetField(ref _hostname, value?.Trim(), "Hostname");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryConnection", 2),
|
||||
@@ -135,8 +135,8 @@ namespace mRemoteNG.Connection
|
||||
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionUsername")]
|
||||
public virtual string Username
|
||||
{
|
||||
get { return GetPropertyValue("Username", _username); }
|
||||
set { SetField(ref _username, value?.Trim(), "Username"); }
|
||||
get => GetPropertyValue("Username", _username);
|
||||
set => SetField(ref _username, value?.Trim(), "Username");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryConnection", 2),
|
||||
@@ -145,8 +145,8 @@ namespace mRemoteNG.Connection
|
||||
PasswordPropertyText(true)]
|
||||
public virtual string Password
|
||||
{
|
||||
get { return GetPropertyValue("Password", _password); }
|
||||
set { SetField(ref _password, value, "Password"); }
|
||||
get => GetPropertyValue("Password", _password);
|
||||
set => SetField(ref _password, value, "Password");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryConnection", 2),
|
||||
@@ -154,8 +154,8 @@ namespace mRemoteNG.Connection
|
||||
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionDomain")]
|
||||
public string Domain
|
||||
{
|
||||
get { return GetPropertyValue("Domain", _domain).Trim(); }
|
||||
set { SetField(ref _domain, value?.Trim(), "Domain"); }
|
||||
get => GetPropertyValue("Domain", _domain).Trim();
|
||||
set => SetField(ref _domain, value?.Trim(), "Domain");
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -166,8 +166,8 @@ namespace mRemoteNG.Connection
|
||||
TypeConverter(typeof(MiscTools.EnumTypeConverter))]
|
||||
public virtual ProtocolType Protocol
|
||||
{
|
||||
get { return GetPropertyValue("Protocol", _protocol); }
|
||||
set { SetField(ref _protocol, value, "Protocol"); }
|
||||
get => GetPropertyValue("Protocol", _protocol);
|
||||
set => SetField(ref _protocol, value, "Protocol");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 3),
|
||||
@@ -176,8 +176,8 @@ namespace mRemoteNG.Connection
|
||||
TypeConverter(typeof(ExternalToolsTypeConverter))]
|
||||
public string ExtApp
|
||||
{
|
||||
get { return GetPropertyValue("ExtApp", _extApp); }
|
||||
set { SetField(ref _extApp, value, "ExtApp"); }
|
||||
get => GetPropertyValue("ExtApp", _extApp);
|
||||
set => SetField(ref _extApp, value, "ExtApp");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 3),
|
||||
@@ -185,8 +185,8 @@ namespace mRemoteNG.Connection
|
||||
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionPort")]
|
||||
public virtual int Port
|
||||
{
|
||||
get { return GetPropertyValue("Port", _port); }
|
||||
set { SetField(ref _port, value, "Port"); }
|
||||
get => GetPropertyValue("Port", _port);
|
||||
set => SetField(ref _port, value, "Port");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 3),
|
||||
@@ -195,8 +195,8 @@ namespace mRemoteNG.Connection
|
||||
TypeConverter(typeof(Config.Putty.PuttySessionsManager.SessionList))]
|
||||
public virtual string PuttySession
|
||||
{
|
||||
get { return GetPropertyValue("PuttySession", _puttySession); }
|
||||
set { SetField(ref _puttySession, value, "PuttySession"); }
|
||||
get => GetPropertyValue("PuttySession", _puttySession);
|
||||
set => SetField(ref _puttySession, value, "PuttySession");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 3),
|
||||
@@ -205,8 +205,8 @@ namespace mRemoteNG.Connection
|
||||
TypeConverter(typeof(MiscTools.EnumTypeConverter))]
|
||||
public IcaProtocol.EncryptionStrength ICAEncryptionStrength
|
||||
{
|
||||
get { return GetPropertyValue("ICAEncryptionStrength", _icaEncryption); }
|
||||
set { SetField(ref _icaEncryption, value, "ICAEncryptionStrength"); }
|
||||
get => GetPropertyValue("ICAEncryptionStrength", _icaEncryption);
|
||||
set => SetField(ref _icaEncryption, value, "ICAEncryptionStrength");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 3),
|
||||
@@ -215,8 +215,8 @@ namespace mRemoteNG.Connection
|
||||
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]
|
||||
public bool UseConsoleSession
|
||||
{
|
||||
get { return GetPropertyValue("UseConsoleSession", _useConsoleSession); }
|
||||
set { SetField(ref _useConsoleSession, value, "UseConsoleSession"); }
|
||||
get => GetPropertyValue("UseConsoleSession", _useConsoleSession);
|
||||
set => SetField(ref _useConsoleSession, value, "UseConsoleSession");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 3),
|
||||
@@ -225,8 +225,8 @@ namespace mRemoteNG.Connection
|
||||
TypeConverter(typeof(MiscTools.EnumTypeConverter))]
|
||||
public RdpProtocol.AuthenticationLevel RDPAuthenticationLevel
|
||||
{
|
||||
get { return GetPropertyValue("RDPAuthenticationLevel", _rdpAuthenticationLevel); }
|
||||
set { SetField(ref _rdpAuthenticationLevel, value, "RDPAuthenticationLevel"); }
|
||||
get => GetPropertyValue("RDPAuthenticationLevel", _rdpAuthenticationLevel);
|
||||
set => SetField(ref _rdpAuthenticationLevel, value, "RDPAuthenticationLevel");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 3),
|
||||
@@ -234,7 +234,7 @@ namespace mRemoteNG.Connection
|
||||
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionRDPMinutesToIdleTimeout")]
|
||||
public virtual int RDPMinutesToIdleTimeout
|
||||
{
|
||||
get { return GetPropertyValue("RDPMinutesToIdleTimeout", _rdpMinutesToIdleTimeout); }
|
||||
get => GetPropertyValue("RDPMinutesToIdleTimeout", _rdpMinutesToIdleTimeout);
|
||||
set {
|
||||
if(value < 0)
|
||||
value = 0;
|
||||
@@ -249,8 +249,8 @@ namespace mRemoteNG.Connection
|
||||
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionRDPAlertIdleTimeout")]
|
||||
public bool RDPAlertIdleTimeout
|
||||
{
|
||||
get { return GetPropertyValue("RDPAlertIdleTimeout", _rdpAlertIdleTimeout); }
|
||||
set { SetField(ref _rdpAlertIdleTimeout, value, "RDPAlertIdleTimeout"); }
|
||||
get => GetPropertyValue("RDPAlertIdleTimeout", _rdpAlertIdleTimeout);
|
||||
set => SetField(ref _rdpAlertIdleTimeout, value, "RDPAlertIdleTimeout");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 3),
|
||||
@@ -258,8 +258,8 @@ namespace mRemoteNG.Connection
|
||||
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionLoadBalanceInfo")]
|
||||
public string LoadBalanceInfo
|
||||
{
|
||||
get { return GetPropertyValue("LoadBalanceInfo", _loadBalanceInfo).Trim(); }
|
||||
set { SetField(ref _loadBalanceInfo, value?.Trim(), "LoadBalanceInfo"); }
|
||||
get => GetPropertyValue("LoadBalanceInfo", _loadBalanceInfo).Trim();
|
||||
set => SetField(ref _loadBalanceInfo, value?.Trim(), "LoadBalanceInfo");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 3),
|
||||
@@ -268,8 +268,8 @@ namespace mRemoteNG.Connection
|
||||
TypeConverter(typeof(MiscTools.EnumTypeConverter))]
|
||||
public HTTPBase.RenderingEngine RenderingEngine
|
||||
{
|
||||
get { return GetPropertyValue("RenderingEngine", _renderingEngine); }
|
||||
set { SetField(ref _renderingEngine, value, "RenderingEngine"); }
|
||||
get => GetPropertyValue("RenderingEngine", _renderingEngine);
|
||||
set => SetField(ref _renderingEngine, value, "RenderingEngine");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryProtocol", 3),
|
||||
@@ -278,8 +278,8 @@ namespace mRemoteNG.Connection
|
||||
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]
|
||||
public bool UseCredSsp
|
||||
{
|
||||
get { return GetPropertyValue("UseCredSsp", _useCredSsp); }
|
||||
set { SetField(ref _useCredSsp, value, "UseCredSsp"); }
|
||||
get => GetPropertyValue("UseCredSsp", _useCredSsp);
|
||||
set => SetField(ref _useCredSsp, value, "UseCredSsp");
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -290,8 +290,8 @@ namespace mRemoteNG.Connection
|
||||
TypeConverter(typeof(MiscTools.EnumTypeConverter))]
|
||||
public RdpProtocol.RDGatewayUsageMethod RDGatewayUsageMethod
|
||||
{
|
||||
get { return GetPropertyValue("RDGatewayUsageMethod", _rdGatewayUsageMethod); }
|
||||
set { SetField(ref _rdGatewayUsageMethod, value, "RDGatewayUsageMethod"); }
|
||||
get => GetPropertyValue("RDGatewayUsageMethod", _rdGatewayUsageMethod);
|
||||
set => SetField(ref _rdGatewayUsageMethod, value, "RDGatewayUsageMethod");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryGateway", 4),
|
||||
@@ -299,8 +299,8 @@ namespace mRemoteNG.Connection
|
||||
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionRDGatewayHostname")]
|
||||
public string RDGatewayHostname
|
||||
{
|
||||
get { return GetPropertyValue("RDGatewayHostname", _rdGatewayHostname).Trim(); }
|
||||
set { SetField(ref _rdGatewayHostname, value?.Trim(), "RDGatewayHostname"); }
|
||||
get => GetPropertyValue("RDGatewayHostname", _rdGatewayHostname).Trim();
|
||||
set => SetField(ref _rdGatewayHostname, value?.Trim(), "RDGatewayHostname");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryGateway", 4),
|
||||
@@ -309,8 +309,8 @@ namespace mRemoteNG.Connection
|
||||
TypeConverter(typeof(MiscTools.EnumTypeConverter))]
|
||||
public RdpProtocol.RDGatewayUseConnectionCredentials RDGatewayUseConnectionCredentials
|
||||
{
|
||||
get { return GetPropertyValue("RDGatewayUseConnectionCredentials", _rdGatewayUseConnectionCredentials); }
|
||||
set { SetField(ref _rdGatewayUseConnectionCredentials, value, "RDGatewayUseConnectionCredentials"); }
|
||||
get => GetPropertyValue("RDGatewayUseConnectionCredentials", _rdGatewayUseConnectionCredentials);
|
||||
set => SetField(ref _rdGatewayUseConnectionCredentials, value, "RDGatewayUseConnectionCredentials");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryGateway", 4),
|
||||
@@ -318,8 +318,8 @@ namespace mRemoteNG.Connection
|
||||
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionRDGatewayUsername")]
|
||||
public string RDGatewayUsername
|
||||
{
|
||||
get { return GetPropertyValue("RDGatewayUsername", _rdGatewayUsername).Trim(); }
|
||||
set { SetField(ref _rdGatewayUsername, value?.Trim(), "RDGatewayUsername"); }
|
||||
get => GetPropertyValue("RDGatewayUsername", _rdGatewayUsername).Trim();
|
||||
set => SetField(ref _rdGatewayUsername, value?.Trim(), "RDGatewayUsername");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryGateway", 4),
|
||||
@@ -328,8 +328,8 @@ namespace mRemoteNG.Connection
|
||||
PasswordPropertyText(true)]
|
||||
public string RDGatewayPassword
|
||||
{
|
||||
get { return GetPropertyValue("RDGatewayPassword", _rdGatewayPassword); }
|
||||
set { SetField(ref _rdGatewayPassword, value, "RDGatewayPassword"); }
|
||||
get => GetPropertyValue("RDGatewayPassword", _rdGatewayPassword);
|
||||
set => SetField(ref _rdGatewayPassword, value, "RDGatewayPassword");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryGateway", 4),
|
||||
@@ -337,8 +337,8 @@ namespace mRemoteNG.Connection
|
||||
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionRDGatewayDomain")]
|
||||
public string RDGatewayDomain
|
||||
{
|
||||
get { return GetPropertyValue("RDGatewayDomain", _rdGatewayDomain).Trim(); }
|
||||
set { SetField(ref _rdGatewayDomain, value?.Trim(), "RDGatewayDomain"); }
|
||||
get => GetPropertyValue("RDGatewayDomain", _rdGatewayDomain).Trim();
|
||||
set => SetField(ref _rdGatewayDomain, value?.Trim(), "RDGatewayDomain");
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -349,8 +349,8 @@ namespace mRemoteNG.Connection
|
||||
TypeConverter(typeof(MiscTools.EnumTypeConverter))]
|
||||
public RdpProtocol.RDPResolutions Resolution
|
||||
{
|
||||
get { return GetPropertyValue("Resolution", _resolution); }
|
||||
set { SetField(ref _resolution, value, "Resolution"); }
|
||||
get => GetPropertyValue("Resolution", _resolution);
|
||||
set => SetField(ref _resolution, value, "Resolution");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryAppearance", 5),
|
||||
@@ -359,8 +359,8 @@ namespace mRemoteNG.Connection
|
||||
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]
|
||||
public bool AutomaticResize
|
||||
{
|
||||
get { return GetPropertyValue("AutomaticResize", _automaticResize); }
|
||||
set { SetField(ref _automaticResize, value, "AutomaticResize"); }
|
||||
get => GetPropertyValue("AutomaticResize", _automaticResize);
|
||||
set => SetField(ref _automaticResize, value, "AutomaticResize");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryAppearance", 5),
|
||||
@@ -369,8 +369,8 @@ namespace mRemoteNG.Connection
|
||||
TypeConverter(typeof(MiscTools.EnumTypeConverter))]
|
||||
public RdpProtocol.RDPColors Colors
|
||||
{
|
||||
get { return GetPropertyValue("Colors", _colors); }
|
||||
set { SetField(ref _colors, value, "Colors"); }
|
||||
get => GetPropertyValue("Colors", _colors);
|
||||
set => SetField(ref _colors, value, "Colors");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryAppearance", 5),
|
||||
@@ -379,8 +379,8 @@ namespace mRemoteNG.Connection
|
||||
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]
|
||||
public bool CacheBitmaps
|
||||
{
|
||||
get { return GetPropertyValue("CacheBitmaps", _cacheBitmaps); }
|
||||
set { SetField(ref _cacheBitmaps, value, "CacheBitmaps"); }
|
||||
get => GetPropertyValue("CacheBitmaps", _cacheBitmaps);
|
||||
set => SetField(ref _cacheBitmaps, value, "CacheBitmaps");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryAppearance", 5),
|
||||
@@ -389,8 +389,8 @@ namespace mRemoteNG.Connection
|
||||
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]
|
||||
public bool DisplayWallpaper
|
||||
{
|
||||
get { return GetPropertyValue("DisplayWallpaper", _displayWallpaper); }
|
||||
set { SetField(ref _displayWallpaper, value, "DisplayWallpaper"); }
|
||||
get => GetPropertyValue("DisplayWallpaper", _displayWallpaper);
|
||||
set => SetField(ref _displayWallpaper, value, "DisplayWallpaper");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryAppearance", 5),
|
||||
@@ -399,8 +399,8 @@ namespace mRemoteNG.Connection
|
||||
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]
|
||||
public bool DisplayThemes
|
||||
{
|
||||
get { return GetPropertyValue("DisplayThemes", _displayThemes); }
|
||||
set { SetField(ref _displayThemes, value, "DisplayThemes"); }
|
||||
get => GetPropertyValue("DisplayThemes", _displayThemes);
|
||||
set => SetField(ref _displayThemes, value, "DisplayThemes");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryAppearance", 5),
|
||||
@@ -409,8 +409,8 @@ namespace mRemoteNG.Connection
|
||||
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]
|
||||
public bool EnableFontSmoothing
|
||||
{
|
||||
get { return GetPropertyValue("EnableFontSmoothing", _enableFontSmoothing); }
|
||||
set { SetField(ref _enableFontSmoothing, value, "EnableFontSmoothing"); }
|
||||
get => GetPropertyValue("EnableFontSmoothing", _enableFontSmoothing);
|
||||
set => SetField(ref _enableFontSmoothing, value, "EnableFontSmoothing");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryAppearance", 5),
|
||||
@@ -419,8 +419,8 @@ namespace mRemoteNG.Connection
|
||||
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]
|
||||
public bool EnableDesktopComposition
|
||||
{
|
||||
get { return GetPropertyValue("EnableDesktopComposition", _enableDesktopComposition); }
|
||||
set { SetField(ref _enableDesktopComposition, value, "EnableDesktopComposition"); }
|
||||
get => GetPropertyValue("EnableDesktopComposition", _enableDesktopComposition);
|
||||
set => SetField(ref _enableDesktopComposition, value, "EnableDesktopComposition");
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -431,8 +431,8 @@ namespace mRemoteNG.Connection
|
||||
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]
|
||||
public bool RedirectKeys
|
||||
{
|
||||
get { return GetPropertyValue("RedirectKeys", _redirectKeys); }
|
||||
set { SetField(ref _redirectKeys, value, "RedirectKeys"); }
|
||||
get => GetPropertyValue("RedirectKeys", _redirectKeys);
|
||||
set => SetField(ref _redirectKeys, value, "RedirectKeys");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryRedirect", 6),
|
||||
@@ -441,8 +441,8 @@ namespace mRemoteNG.Connection
|
||||
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]
|
||||
public bool RedirectDiskDrives
|
||||
{
|
||||
get { return GetPropertyValue("RedirectDiskDrives", _redirectDiskDrives); }
|
||||
set { SetField(ref _redirectDiskDrives, value, "RedirectDiskDrives"); }
|
||||
get => GetPropertyValue("RedirectDiskDrives", _redirectDiskDrives);
|
||||
set => SetField(ref _redirectDiskDrives, value, "RedirectDiskDrives");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryRedirect", 6),
|
||||
@@ -451,8 +451,8 @@ namespace mRemoteNG.Connection
|
||||
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]
|
||||
public bool RedirectPrinters
|
||||
{
|
||||
get { return GetPropertyValue("RedirectPrinters", _redirectPrinters); }
|
||||
set { SetField(ref _redirectPrinters, value, "RedirectPrinters"); }
|
||||
get => GetPropertyValue("RedirectPrinters", _redirectPrinters);
|
||||
set => SetField(ref _redirectPrinters, value, "RedirectPrinters");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryRedirect", 6),
|
||||
@@ -461,8 +461,8 @@ namespace mRemoteNG.Connection
|
||||
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]
|
||||
public bool RedirectPorts
|
||||
{
|
||||
get { return GetPropertyValue("RedirectPorts", _redirectPorts); }
|
||||
set { SetField(ref _redirectPorts, value, "RedirectPorts"); }
|
||||
get => GetPropertyValue("RedirectPorts", _redirectPorts);
|
||||
set => SetField(ref _redirectPorts, value, "RedirectPorts");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryRedirect", 6),
|
||||
@@ -471,8 +471,8 @@ namespace mRemoteNG.Connection
|
||||
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]
|
||||
public bool RedirectSmartCards
|
||||
{
|
||||
get { return GetPropertyValue("RedirectSmartCards", _redirectSmartCards); }
|
||||
set { SetField(ref _redirectSmartCards, value, "RedirectSmartCards"); }
|
||||
get => GetPropertyValue("RedirectSmartCards", _redirectSmartCards);
|
||||
set => SetField(ref _redirectSmartCards, value, "RedirectSmartCards");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryRedirect", 6),
|
||||
@@ -481,8 +481,8 @@ namespace mRemoteNG.Connection
|
||||
TypeConverter(typeof(MiscTools.EnumTypeConverter))]
|
||||
public RdpProtocol.RDPSounds RedirectSound
|
||||
{
|
||||
get { return GetPropertyValue("RedirectSound", _redirectSound); }
|
||||
set { SetField(ref _redirectSound, value, "RedirectSound"); }
|
||||
get => GetPropertyValue("RedirectSound", _redirectSound);
|
||||
set => SetField(ref _redirectSound, value, "RedirectSound");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryRedirect", 6),
|
||||
@@ -491,8 +491,8 @@ namespace mRemoteNG.Connection
|
||||
TypeConverter(typeof(MiscTools.EnumTypeConverter))]
|
||||
public RdpProtocol.RDPSoundQuality SoundQuality
|
||||
{
|
||||
get { return GetPropertyValue("SoundQuality", _soundQuality); }
|
||||
set { SetField(ref _soundQuality, value, "SoundQuality"); }
|
||||
get => GetPropertyValue("SoundQuality", _soundQuality);
|
||||
set => SetField(ref _soundQuality, value, "SoundQuality");
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -506,8 +506,8 @@ namespace mRemoteNG.Connection
|
||||
TypeConverter(typeof(ExternalToolsTypeConverter))]
|
||||
public virtual string PreExtApp
|
||||
{
|
||||
get { return GetPropertyValue("PreExtApp", _preExtApp); }
|
||||
set { SetField(ref _preExtApp, value, "PreExtApp"); }
|
||||
get => GetPropertyValue("PreExtApp", _preExtApp);
|
||||
set => SetField(ref _preExtApp, value, "PreExtApp");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryMiscellaneous", 7),
|
||||
@@ -516,8 +516,8 @@ namespace mRemoteNG.Connection
|
||||
TypeConverter(typeof(ExternalToolsTypeConverter))]
|
||||
public virtual string PostExtApp
|
||||
{
|
||||
get { return GetPropertyValue("PostExtApp", _postExtApp); }
|
||||
set { SetField(ref _postExtApp, value, "PostExtApp"); }
|
||||
get => GetPropertyValue("PostExtApp", _postExtApp);
|
||||
set => SetField(ref _postExtApp, value, "PostExtApp");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryMiscellaneous", 7),
|
||||
@@ -525,8 +525,8 @@ namespace mRemoteNG.Connection
|
||||
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionMACAddress")]
|
||||
public virtual string MacAddress
|
||||
{
|
||||
get { return GetPropertyValue("MacAddress", _macAddress); }
|
||||
set { SetField(ref _macAddress, value, "MacAddress"); }
|
||||
get => GetPropertyValue("MacAddress", _macAddress);
|
||||
set => SetField(ref _macAddress, value, "MacAddress");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryMiscellaneous", 7),
|
||||
@@ -534,8 +534,8 @@ namespace mRemoteNG.Connection
|
||||
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionUser1")]
|
||||
public virtual string UserField
|
||||
{
|
||||
get { return GetPropertyValue("UserField", _userField); }
|
||||
set { SetField(ref _userField, value, "UserField"); }
|
||||
get => GetPropertyValue("UserField", _userField);
|
||||
set => SetField(ref _userField, value, "UserField");
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -547,8 +547,8 @@ namespace mRemoteNG.Connection
|
||||
TypeConverter(typeof(MiscTools.EnumTypeConverter))]
|
||||
public ProtocolVNC.Compression VNCCompression
|
||||
{
|
||||
get { return GetPropertyValue("VNCCompression", _vncCompression); }
|
||||
set { SetField(ref _vncCompression, value, "VNCCompression"); }
|
||||
get => GetPropertyValue("VNCCompression", _vncCompression);
|
||||
set => SetField(ref _vncCompression, value, "VNCCompression");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryAppearance", 5),
|
||||
@@ -558,8 +558,8 @@ namespace mRemoteNG.Connection
|
||||
TypeConverter(typeof(MiscTools.EnumTypeConverter))]
|
||||
public ProtocolVNC.Encoding VNCEncoding
|
||||
{
|
||||
get { return GetPropertyValue("VNCEncoding", _vncEncoding); }
|
||||
set { SetField(ref _vncEncoding, value, "VNCEncoding"); }
|
||||
get => GetPropertyValue("VNCEncoding", _vncEncoding);
|
||||
set => SetField(ref _vncEncoding, value, "VNCEncoding");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryConnection", 2),
|
||||
@@ -569,8 +569,8 @@ namespace mRemoteNG.Connection
|
||||
TypeConverter(typeof(MiscTools.EnumTypeConverter))]
|
||||
public ProtocolVNC.AuthMode VNCAuthMode
|
||||
{
|
||||
get { return GetPropertyValue("VNCAuthMode", _vncAuthMode); }
|
||||
set { SetField(ref _vncAuthMode, value, "VNCAuthMode"); }
|
||||
get => GetPropertyValue("VNCAuthMode", _vncAuthMode);
|
||||
set => SetField(ref _vncAuthMode, value, "VNCAuthMode");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryMiscellaneous", 7),
|
||||
@@ -580,8 +580,8 @@ namespace mRemoteNG.Connection
|
||||
TypeConverter(typeof(MiscTools.EnumTypeConverter))]
|
||||
public ProtocolVNC.ProxyType VNCProxyType
|
||||
{
|
||||
get { return GetPropertyValue("VNCProxyType", _vncProxyType); }
|
||||
set { SetField(ref _vncProxyType, value, "VNCProxyType"); }
|
||||
get => GetPropertyValue("VNCProxyType", _vncProxyType);
|
||||
set => SetField(ref _vncProxyType, value, "VNCProxyType");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryMiscellaneous", 7),
|
||||
@@ -590,8 +590,8 @@ namespace mRemoteNG.Connection
|
||||
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionVNCProxyAddress")]
|
||||
public string VNCProxyIP
|
||||
{
|
||||
get { return GetPropertyValue("VNCProxyIP", _vncProxyIp); }
|
||||
set { SetField(ref _vncProxyIp, value, "VNCProxyIP"); }
|
||||
get => GetPropertyValue("VNCProxyIP", _vncProxyIp);
|
||||
set => SetField(ref _vncProxyIp, value, "VNCProxyIP");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryMiscellaneous", 7),
|
||||
@@ -600,8 +600,8 @@ namespace mRemoteNG.Connection
|
||||
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionVNCProxyPort")]
|
||||
public int VNCProxyPort
|
||||
{
|
||||
get { return GetPropertyValue("VNCProxyPort", _vncProxyPort); }
|
||||
set { SetField(ref _vncProxyPort, value, "VNCProxyPort"); }
|
||||
get => GetPropertyValue("VNCProxyPort", _vncProxyPort);
|
||||
set => SetField(ref _vncProxyPort, value, "VNCProxyPort");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryMiscellaneous", 7),
|
||||
@@ -610,8 +610,8 @@ namespace mRemoteNG.Connection
|
||||
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionVNCProxyUsername")]
|
||||
public string VNCProxyUsername
|
||||
{
|
||||
get { return GetPropertyValue("VNCProxyUsername", _vncProxyUsername); }
|
||||
set { SetField(ref _vncProxyUsername, value, "VNCProxyUsername"); }
|
||||
get => GetPropertyValue("VNCProxyUsername", _vncProxyUsername);
|
||||
set => SetField(ref _vncProxyUsername, value, "VNCProxyUsername");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryMiscellaneous", 7),
|
||||
@@ -621,8 +621,8 @@ namespace mRemoteNG.Connection
|
||||
PasswordPropertyText(true)]
|
||||
public string VNCProxyPassword
|
||||
{
|
||||
get { return GetPropertyValue("VNCProxyPassword", _vncProxyPassword); }
|
||||
set { SetField(ref _vncProxyPassword, value, "VNCProxyPassword"); }
|
||||
get => GetPropertyValue("VNCProxyPassword", _vncProxyPassword);
|
||||
set => SetField(ref _vncProxyPassword, value, "VNCProxyPassword");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryAppearance", 5),
|
||||
@@ -632,8 +632,8 @@ namespace mRemoteNG.Connection
|
||||
TypeConverter(typeof(MiscTools.EnumTypeConverter))]
|
||||
public ProtocolVNC.Colors VNCColors
|
||||
{
|
||||
get { return GetPropertyValue("VNCColors", _vncColors); }
|
||||
set { SetField(ref _vncColors, value, "VNCColors"); }
|
||||
get => GetPropertyValue("VNCColors", _vncColors);
|
||||
set => SetField(ref _vncColors, value, "VNCColors");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryAppearance", 5),
|
||||
@@ -642,8 +642,8 @@ namespace mRemoteNG.Connection
|
||||
TypeConverter(typeof(MiscTools.EnumTypeConverter))]
|
||||
public ProtocolVNC.SmartSizeMode VNCSmartSizeMode
|
||||
{
|
||||
get { return GetPropertyValue("VNCSmartSizeMode", _vncSmartSizeMode); }
|
||||
set { SetField(ref _vncSmartSizeMode, value, "VNCSmartSizeMode"); }
|
||||
get => GetPropertyValue("VNCSmartSizeMode", _vncSmartSizeMode);
|
||||
set => SetField(ref _vncSmartSizeMode, value, "VNCSmartSizeMode");
|
||||
}
|
||||
|
||||
[LocalizedAttributes.LocalizedCategory("strCategoryAppearance", 5),
|
||||
@@ -652,8 +652,8 @@ namespace mRemoteNG.Connection
|
||||
TypeConverter(typeof(MiscTools.YesNoTypeConverter))]
|
||||
public bool VNCViewOnly
|
||||
{
|
||||
get { return GetPropertyValue("VNCViewOnly", _vncViewOnly); }
|
||||
set { SetField(ref _vncViewOnly, value, "VNCViewOnly"); }
|
||||
get => GetPropertyValue("VNCViewOnly", _vncViewOnly);
|
||||
set => SetField(ref _vncViewOnly, value, "VNCViewOnly");
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
@@ -665,7 +665,7 @@ namespace mRemoteNG.Connection
|
||||
|
||||
protected virtual TPropertyType GetPropertyValue<TPropertyType>(string propertyName, TPropertyType value)
|
||||
{
|
||||
return (TPropertyType)GetType().GetProperty(propertyName).GetValue(this, null);
|
||||
return (TPropertyType)GetType().GetProperty(propertyName)?.GetValue(this, null);
|
||||
}
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
@@ -674,12 +674,11 @@ namespace mRemoteNG.Connection
|
||||
PropertyChanged?.Invoke(sender, new PropertyChangedEventArgs(args.PropertyName));
|
||||
}
|
||||
|
||||
protected bool 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 false;
|
||||
if (EqualityComparer<T>.Default.Equals(field, value)) return;
|
||||
field = value;
|
||||
RaisePropertyChangedEvent(this, new PropertyChangedEventArgs(propertyName));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -173,9 +173,7 @@ namespace mRemoteNG.Connection
|
||||
return value;
|
||||
|
||||
var inheritedValue = GetInheritedPropertyValue<TPropertyType>(propertyName);
|
||||
if (inheritedValue.Equals(default(TPropertyType)))
|
||||
return value;
|
||||
return inheritedValue;
|
||||
return inheritedValue.Equals(default(TPropertyType)) ? value : inheritedValue;
|
||||
}
|
||||
|
||||
private bool ShouldThisPropertyBeInherited(string propertyName)
|
||||
|
||||
@@ -8,7 +8,6 @@ using mRemoteNG.App.Info;
|
||||
using mRemoteNG.Config.Connections;
|
||||
using mRemoteNG.Config.Connections.Multiuser;
|
||||
using mRemoteNG.Config.DatabaseConnectors;
|
||||
using mRemoteNG.Config.DataProviders;
|
||||
using mRemoteNG.Config.Putty;
|
||||
using mRemoteNG.Connection.Protocol;
|
||||
using mRemoteNG.Messages;
|
||||
@@ -17,7 +16,6 @@ using mRemoteNG.Tools;
|
||||
using mRemoteNG.Tree;
|
||||
using mRemoteNG.Tree.Root;
|
||||
using mRemoteNG.UI;
|
||||
using mRemoteNG.UI.Forms;
|
||||
using mRemoteNG.UI.TaskDialog;
|
||||
|
||||
namespace mRemoteNG.Connection
|
||||
@@ -29,6 +27,9 @@ namespace mRemoteNG.Connection
|
||||
private readonly PuttySessionsManager _puttySessionsManager;
|
||||
private readonly Import _import;
|
||||
private readonly IWin32Window _dialogWindowParent;
|
||||
private bool _batchingSaves = false;
|
||||
private bool _saveRequested = false;
|
||||
private bool _saveAsyncRequested = false;
|
||||
|
||||
public bool IsConnectionsFileLoaded { get; set; }
|
||||
public bool UsingDatabase { get; private set; }
|
||||
@@ -58,9 +59,8 @@ namespace mRemoteNG.Connection
|
||||
{
|
||||
var newConnectionsModel = new ConnectionTreeModel();
|
||||
newConnectionsModel.AddRootNode(new RootNodeInfo(RootNodeType.Connection));
|
||||
SaveConnections(newConnectionsModel, false, new SaveFilter(), filename);
|
||||
SaveConnections(newConnectionsModel, false, new SaveFilter(), filename, true);
|
||||
LoadConnections(false, false, filename);
|
||||
UpdateCustomConsPathSetting(filename);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -108,16 +108,24 @@ namespace mRemoteNG.Connection
|
||||
/// <param name="useDatabase"></param>
|
||||
/// <param name="import"></param>
|
||||
/// <param name="connectionFileName"></param>
|
||||
public ConnectionTreeModel LoadConnections(bool useDatabase, bool import, string connectionFileName)
|
||||
public void LoadConnections(bool useDatabase, bool import, string connectionFileName)
|
||||
{
|
||||
var oldConnectionTreeModel = ConnectionTreeModel;
|
||||
var oldIsUsingDatabaseValue = UsingDatabase;
|
||||
|
||||
var newConnectionTreeModel =
|
||||
(useDatabase
|
||||
var newConnectionTreeModel = useDatabase
|
||||
? new SqlConnectionsLoader(DatabaseConnectorFactory, this).Load()
|
||||
: new XmlConnectionsLoader(connectionFileName, this, _dialogWindowParent).Load())
|
||||
?? new ConnectionTreeModel();
|
||||
: new XmlConnectionsLoader(connectionFileName, this, _dialogWindowParent).Load();
|
||||
|
||||
if (newConnectionTreeModel == null)
|
||||
{
|
||||
DialogFactory.ShowLoadConnectionsFailedDialog(connectionFileName, "Decrypting connection file failed", IsConnectionsFileLoaded);
|
||||
return;
|
||||
}
|
||||
|
||||
IsConnectionsFileLoaded = true;
|
||||
ConnectionFileName = connectionFileName;
|
||||
UsingDatabase = useDatabase;
|
||||
|
||||
if (!import)
|
||||
{
|
||||
@@ -125,12 +133,24 @@ namespace mRemoteNG.Connection
|
||||
newConnectionTreeModel.RootNodes.AddRange(_puttySessionsManager.RootPuttySessionsNodes);
|
||||
}
|
||||
|
||||
IsConnectionsFileLoaded = true;
|
||||
ConnectionFileName = connectionFileName;
|
||||
UsingDatabase = useDatabase;
|
||||
ConnectionTreeModel = newConnectionTreeModel;
|
||||
UpdateCustomConsPathSetting(connectionFileName);
|
||||
RaiseConnectionsLoadedEvent(oldConnectionTreeModel, newConnectionTreeModel, oldIsUsingDatabaseValue, useDatabase, connectionFileName);
|
||||
return newConnectionTreeModel;
|
||||
}
|
||||
|
||||
public void BeginBatchingSaves()
|
||||
{
|
||||
_batchingSaves = true;
|
||||
}
|
||||
|
||||
public void EndBatchingSaves()
|
||||
{
|
||||
_batchingSaves = false;
|
||||
|
||||
if (_saveAsyncRequested)
|
||||
SaveConnectionsAsync();
|
||||
else if(_saveRequested)
|
||||
SaveConnections();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -139,8 +159,6 @@ namespace mRemoteNG.Connection
|
||||
/// </summary>
|
||||
public void SaveConnections()
|
||||
{
|
||||
if (!IsConnectionsFileLoaded)
|
||||
return;
|
||||
SaveConnections(ConnectionTreeModel, UsingDatabase, new SaveFilter(), ConnectionFileName);
|
||||
}
|
||||
|
||||
@@ -152,12 +170,24 @@ namespace mRemoteNG.Connection
|
||||
/// <param name="useDatabase"></param>
|
||||
/// <param name="saveFilter"></param>
|
||||
/// <param name="connectionFileName"></param>
|
||||
public void SaveConnections(ConnectionTreeModel connectionTreeModel, bool useDatabase, SaveFilter saveFilter, string connectionFileName)
|
||||
/// <param name="forceSave">Bypasses safety checks that prevent saving if a connection file isn't loaded.</param>
|
||||
public void SaveConnections(ConnectionTreeModel connectionTreeModel, bool useDatabase, SaveFilter saveFilter, string connectionFileName, bool forceSave = false)
|
||||
{
|
||||
if (connectionTreeModel == null) return;
|
||||
if (connectionTreeModel == null)
|
||||
return;
|
||||
|
||||
if (!forceSave && !IsConnectionsFileLoaded)
|
||||
return;
|
||||
|
||||
if (_batchingSaves)
|
||||
{
|
||||
_saveRequested = true;
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, "Saving connections...");
|
||||
RemoteConnectionsSyncronizer?.Disable();
|
||||
|
||||
var previouslyUsingDatabase = UsingDatabase;
|
||||
@@ -172,6 +202,7 @@ namespace mRemoteNG.Connection
|
||||
UsingDatabase = useDatabase;
|
||||
ConnectionFileName = connectionFileName;
|
||||
RaiseConnectionsSavedEvent(connectionTreeModel, previouslyUsingDatabase, UsingDatabase, connectionFileName);
|
||||
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, "Successfully saved connections");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -185,6 +216,12 @@ namespace mRemoteNG.Connection
|
||||
|
||||
public void SaveConnectionsAsync()
|
||||
{
|
||||
if (_batchingSaves)
|
||||
{
|
||||
_saveAsyncRequested = true;
|
||||
return;
|
||||
}
|
||||
|
||||
var t = new Thread(SaveConnectionsBGd);
|
||||
t.SetApartmentState(ApartmentState.STA);
|
||||
t.Start();
|
||||
@@ -233,12 +270,6 @@ namespace mRemoteNG.Connection
|
||||
{
|
||||
connectionFileName = GetStartupConnectionFileName();
|
||||
}
|
||||
|
||||
var backupFileCreator = new FileBackupCreator();
|
||||
backupFileCreator.CreateBackupFile(connectionFileName);
|
||||
|
||||
var backupPruner = new FileBackupPruner();
|
||||
backupPruner.PruneBackupFiles(connectionFileName);
|
||||
}
|
||||
|
||||
LoadConnections(Settings.Default.UseSQLServer, false, connectionFileName);
|
||||
@@ -356,12 +387,16 @@ namespace mRemoteNG.Connection
|
||||
|
||||
public string GetStartupConnectionFileName()
|
||||
{
|
||||
return Settings.Default.LoadConsFromCustomLocation == false ? GetDefaultStartupConnectionFileName() : Settings.Default.CustomConsPath;
|
||||
return Settings.Default.LoadConsFromCustomLocation == false
|
||||
? GetDefaultStartupConnectionFileName()
|
||||
: Settings.Default.CustomConsPath;
|
||||
}
|
||||
|
||||
public string GetDefaultStartupConnectionFileName()
|
||||
{
|
||||
return Runtime.IsPortableEdition ? GetDefaultStartupConnectionFileNamePortableEdition() : GetDefaultStartupConnectionFileNameNormalEdition();
|
||||
return Runtime.IsPortableEdition
|
||||
? GetDefaultStartupConnectionFileNamePortableEdition()
|
||||
: GetDefaultStartupConnectionFileNameNormalEdition();
|
||||
}
|
||||
|
||||
private void UpdateCustomConsPathSetting(string filename)
|
||||
|
||||
@@ -27,11 +27,11 @@ namespace mRemoteNG.Connection
|
||||
string GetDefaultStartupConnectionFileName();
|
||||
string GetStartupConnectionFileName();
|
||||
void LoadConnections(bool withDialog = false);
|
||||
ConnectionTreeModel LoadConnections(bool useDatabase, bool import, string connectionFileName);
|
||||
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);
|
||||
void SaveConnections(ConnectionTreeModel connectionTreeModel, bool useDatabase, SaveFilter saveFilter, string connectionFileName, bool forceSave = false);
|
||||
void SaveConnectionsAsync();
|
||||
}
|
||||
}
|
||||
@@ -33,5 +33,5 @@ using System.Runtime.InteropServices;
|
||||
// by using the '*' as shown below:
|
||||
// <Assembly: AssemblyVersion("1.0.*")>
|
||||
|
||||
[assembly: AssemblyVersion("1.76.3.*")]
|
||||
[assembly: AssemblyVersion("1.76.5.*")]
|
||||
[assembly: NeutralResourcesLanguage("en")]
|
||||
26
mRemoteV1/Properties/Settings.Designer.cs
generated
26
mRemoteV1/Properties/Settings.Designer.cs
generated
@@ -12,7 +12,7 @@ namespace mRemoteNG {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.5.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
@@ -2698,5 +2698,29 @@ namespace mRemoteNG {
|
||||
this["MultiSshToolbarVisible"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("False")]
|
||||
public bool CreateEmptyPanelOnStartUp {
|
||||
get {
|
||||
return ((bool)(this["CreateEmptyPanelOnStartUp"]));
|
||||
}
|
||||
set {
|
||||
this["CreateEmptyPanelOnStartUp"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[global::System.Configuration.UserScopedSettingAttribute()]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Configuration.DefaultSettingValueAttribute("General")]
|
||||
public string StartUpPanelName {
|
||||
get {
|
||||
return ((string)(this["StartUpPanelName"]));
|
||||
}
|
||||
set {
|
||||
this["StartUpPanelName"] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -671,5 +671,11 @@
|
||||
<Setting Name="MultiSshToolbarVisible" Type="System.Boolean" Scope="User">
|
||||
<Value Profile="(Default)">False</Value>
|
||||
</Setting>
|
||||
<Setting Name="CreateEmptyPanelOnStartUp" Type="System.Boolean" Scope="User">
|
||||
<Value Profile="(Default)">False</Value>
|
||||
</Setting>
|
||||
<Setting Name="StartUpPanelName" Type="System.String" Scope="User">
|
||||
<Value Profile="(Default)">General</Value>
|
||||
</Setting>
|
||||
</Settings>
|
||||
</SettingsFile>
|
||||
@@ -1646,6 +1646,15 @@ namespace mRemoteNG {
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Create an empty panel when mRemoteNG starts.
|
||||
/// </summary>
|
||||
internal static string strCreateEmptyPanelOnStartUp {
|
||||
get {
|
||||
return ResourceManager.GetString("strCreateEmptyPanelOnStartUp", resourceCulture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Looks up a localized string similar to Credential Editor.
|
||||
/// </summary>
|
||||
|
||||
@@ -2676,4 +2676,7 @@ This page will walk you through the process of upgrading your connections file o
|
||||
<data name="strLoadBalanceInfoUseUtf8" xml:space="preserve">
|
||||
<value>Use UTF8 encoding for RDP "Load Balance Info" property</value>
|
||||
</data>
|
||||
<data name="strCreateEmptyPanelOnStartUp" xml:space="preserve">
|
||||
<value>Create an empty panel when mRemoteNG starts</value>
|
||||
</data>
|
||||
</root>
|
||||
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Security;
|
||||
using mRemoteNG.Tools;
|
||||
|
||||
namespace mRemoteNG.Security.Authentication
|
||||
{
|
||||
@@ -7,15 +9,16 @@ namespace mRemoteNG.Security.Authentication
|
||||
{
|
||||
private readonly ICryptographyProvider _cryptographyProvider;
|
||||
private readonly string _cipherText;
|
||||
private readonly Func<Optional<SecureString>> _authenticationRequestor;
|
||||
|
||||
public Func<SecureString> AuthenticationRequestor { get; set; }
|
||||
public int MaxAttempts { get; set; } = 3;
|
||||
public SecureString LastAuthenticatedPassword { get; private set; }
|
||||
|
||||
public PasswordAuthenticator(ICryptographyProvider cryptographyProvider, string cipherText)
|
||||
public PasswordAuthenticator(ICryptographyProvider cryptographyProvider, string cipherText, Func<Optional<SecureString>> authenticationRequestor)
|
||||
{
|
||||
_cryptographyProvider = cryptographyProvider;
|
||||
_cipherText = cipherText;
|
||||
_cryptographyProvider = cryptographyProvider.ThrowIfNull(nameof(cryptographyProvider));
|
||||
_cipherText = cipherText.ThrowIfNullOrEmpty(nameof(cipherText));
|
||||
_authenticationRequestor = authenticationRequestor.ThrowIfNull(nameof(authenticationRequestor));
|
||||
}
|
||||
|
||||
public bool Authenticate(SecureString password)
|
||||
@@ -32,7 +35,11 @@ namespace mRemoteNG.Security.Authentication
|
||||
}
|
||||
catch
|
||||
{
|
||||
password = AuthenticationRequestor?.Invoke();
|
||||
var providedPassword = _authenticationRequestor();
|
||||
if (!providedPassword.Any())
|
||||
return false;
|
||||
|
||||
password = providedPassword.First();
|
||||
if (password == null || password.Length == 0) break;
|
||||
}
|
||||
attempts++;
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
using System.Security;
|
||||
using mRemoteNG.Tools;
|
||||
|
||||
namespace mRemoteNG.Security
|
||||
{
|
||||
public interface IKeyProvider
|
||||
{
|
||||
SecureString GetKey();
|
||||
Optional<SecureString> GetKey();
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ using static System.String;
|
||||
|
||||
namespace mRemoteNG.Tools
|
||||
{
|
||||
public static class MiscTools
|
||||
public static class MiscTools
|
||||
{
|
||||
public static Icon GetIconFromFile(string FileName)
|
||||
{
|
||||
@@ -34,7 +34,7 @@ namespace mRemoteNG.Tools
|
||||
}
|
||||
}
|
||||
|
||||
public static SecureString PasswordDialog(string passwordName = null, bool verify = true)
|
||||
public static Optional<SecureString> PasswordDialog(string passwordName = null, bool verify = true)
|
||||
{
|
||||
var passwordForm = new PasswordForm(passwordName, verify);
|
||||
return passwordForm.GetKey();
|
||||
|
||||
@@ -1,50 +1,152 @@
|
||||
using System.Collections;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace mRemoteNG.Tools
|
||||
{
|
||||
public class Optional<T> : IEnumerable<T>
|
||||
{
|
||||
private readonly T[] _maybe;
|
||||
/// <summary>
|
||||
/// Represents a type that may or may not have been assigned a value.
|
||||
/// A strongly typed collection that contains either 0 or 1 values.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The underlying type that may or may not have a value</typeparam>
|
||||
public class Optional<T> : IEnumerable<T>, IComparable<Optional<T>>
|
||||
{
|
||||
private readonly T[] _optional;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new empty instance of Optional
|
||||
/// </summary>
|
||||
public Optional()
|
||||
{
|
||||
_maybe = new T[0];
|
||||
_optional = new T[0];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new instance of Optional from the given value.
|
||||
/// If the value is null, the Optional will be empty
|
||||
/// </summary>
|
||||
public Optional(T value)
|
||||
{
|
||||
_maybe = value != null
|
||||
_optional = value != null
|
||||
? new[] {value}
|
||||
: new T[0];
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
public override string ToString()
|
||||
{
|
||||
return _optional.Any() ? _optional.First().ToString() : "";
|
||||
}
|
||||
|
||||
public static implicit operator Optional<T>(T value)
|
||||
{
|
||||
return new Optional<T>(value);
|
||||
}
|
||||
|
||||
public static Optional<TOut> FromNullable<TOut>(TOut? value) where TOut : struct
|
||||
{
|
||||
return value.HasValue
|
||||
? new Optional<TOut>(value.Value)
|
||||
: new Optional<TOut>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an empty <see cref="Optional{T}"/>
|
||||
/// </summary>
|
||||
public static Optional<T> Empty => new Optional<T>();
|
||||
|
||||
#region IEnumerable
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
|
||||
public IEnumerator<T> GetEnumerator()
|
||||
{
|
||||
return ((IEnumerable<T>)_maybe).GetEnumerator();
|
||||
return ((IEnumerable<T>)_optional).GetEnumerator();
|
||||
}
|
||||
#endregion
|
||||
|
||||
public override string ToString()
|
||||
#region IComparable
|
||||
/// <summary>
|
||||
/// Compares this <see cref="Optional{T}"/> to another instance
|
||||
/// of the same type. For purposes of comparison, empty Optional
|
||||
/// objects are treated like Null and will be valued lower than
|
||||
/// an Optional that contains a value. If both Optionals contain
|
||||
/// values, the values are compared directly.
|
||||
/// </summary>
|
||||
/// <param name="other"></param>
|
||||
public int CompareTo(Optional<T> other)
|
||||
{
|
||||
var otherHasAnything = other.Any();
|
||||
var thisHasAnything = _optional.Length > 0;
|
||||
|
||||
// both are empty, equivalent value
|
||||
if (!thisHasAnything && !otherHasAnything)
|
||||
return 0;
|
||||
// we are empty, they are greater value
|
||||
if (!thisHasAnything)
|
||||
return -1;
|
||||
// they are empty, we are greater value
|
||||
if (!otherHasAnything)
|
||||
return 1;
|
||||
// neither are empty, compare wrapped objects directly
|
||||
if (_optional[0] is IComparable<T>)
|
||||
return ((IComparable<T>)_optional[0]).CompareTo(other.First());
|
||||
|
||||
throw new ArgumentException(string.Format(
|
||||
"Cannot compare objects. Optional type {0} is not comparable to itself",
|
||||
typeof(T).FullName));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Override Equals and GetHashCode
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return _maybe.Any() ? _maybe.First().ToString() : "";
|
||||
if (ReferenceEquals(this, obj))
|
||||
return true;
|
||||
|
||||
var objAsOptional = obj as Optional<T>;
|
||||
if (objAsOptional != null)
|
||||
return Equals(objAsOptional);
|
||||
|
||||
if (obj is T)
|
||||
Equals((T)obj);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static implicit operator Optional<T>(T value)
|
||||
public bool Equals(Optional<T> other)
|
||||
{
|
||||
return new Optional<T>(value);
|
||||
var otherObj = other.FirstOrDefault();
|
||||
var thisObj = _optional.FirstOrDefault();
|
||||
if (thisObj == null && otherObj == null)
|
||||
return true;
|
||||
if (thisObj == null)
|
||||
return false;
|
||||
return thisObj.Equals(otherObj);
|
||||
}
|
||||
|
||||
public static Optional<TOut> FromNullable<TOut>(TOut? value) where TOut : struct
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return value.HasValue
|
||||
? new Optional<TOut>(value.Value)
|
||||
: new Optional<TOut>();
|
||||
return _optional != null
|
||||
? _optional.GetHashCode()
|
||||
: 0;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Operators
|
||||
|
||||
public static bool operator ==(Optional<T> left, Optional<T> right)
|
||||
{
|
||||
return Equals(left, right);
|
||||
}
|
||||
|
||||
public static bool operator !=(Optional<T> left, Optional<T> right)
|
||||
{
|
||||
return !Equals(left, right);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ using mRemoteNG.Tree.Root;
|
||||
|
||||
namespace mRemoteNG.Tree
|
||||
{
|
||||
public sealed class ConnectionTreeModel : INotifyCollectionChanged, INotifyPropertyChanged
|
||||
public sealed class ConnectionTreeModel : INotifyCollectionChanged, INotifyPropertyChanged
|
||||
{
|
||||
public List<ContainerInfo> RootNodes { get; } = new List<ContainerInfo>();
|
||||
|
||||
|
||||
@@ -66,7 +66,9 @@ namespace mRemoteNG.Tree.Root
|
||||
|
||||
public override TreeNodeType GetTreeNodeType()
|
||||
{
|
||||
return TreeNodeType.Root;
|
||||
return Type == RootNodeType.Connection
|
||||
? TreeNodeType.Root
|
||||
: TreeNodeType.PuttyRoot;
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -17,6 +17,9 @@ namespace mRemoteNG.Tree
|
||||
|
||||
public bool Confirm(ConnectionInfo deletionTarget)
|
||||
{
|
||||
if (deletionTarget == null)
|
||||
return false;
|
||||
|
||||
var deletionTargetAsContainer = deletionTarget as ContainerInfo;
|
||||
if (deletionTargetAsContainer != null)
|
||||
return deletionTargetAsContainer.HasChildren()
|
||||
|
||||
@@ -16,7 +16,7 @@ using mRemoteNG.Tree.Root;
|
||||
|
||||
namespace mRemoteNG.UI.Controls
|
||||
{
|
||||
public partial class ConnectionTree : TreeListView, IConnectionTree
|
||||
public partial class ConnectionTree : TreeListView, IConnectionTree
|
||||
{
|
||||
private readonly ConnectionTreeDragAndDropHandler _dragAndDropHandler = new ConnectionTreeDragAndDropHandler();
|
||||
private readonly PuttySessionsManager _puttySessionsManager = PuttySessionsManager.Instance;
|
||||
@@ -262,6 +262,9 @@ namespace mRemoteNG.UI.Controls
|
||||
|
||||
private void AddNode(ConnectionInfo newNode)
|
||||
{
|
||||
if (SelectedNode?.GetTreeNodeType() == TreeNodeType.PuttyRoot || SelectedNode?.GetTreeNodeType() == TreeNodeType.PuttySession)
|
||||
return;
|
||||
|
||||
// use root node if no node is selected
|
||||
ConnectionInfo parentNode = SelectedNode ?? GetRootConnectionNode();
|
||||
DefaultConnectionInfo.Instance.SaveTo(newNode);
|
||||
@@ -278,6 +281,13 @@ namespace mRemoteNG.UI.Controls
|
||||
|
||||
public void DuplicateSelectedNode()
|
||||
{
|
||||
if (SelectedNode == null)
|
||||
return;
|
||||
|
||||
var selectedNodeType = SelectedNode.GetTreeNodeType();
|
||||
if (selectedNodeType != TreeNodeType.Connection && selectedNodeType != TreeNodeType.Container)
|
||||
return;
|
||||
|
||||
var newNode = SelectedNode.Clone();
|
||||
SelectedNode.Parent.AddChildBelow(newNode, SelectedNode);
|
||||
newNode.Parent.SetChildBelow(newNode, SelectedNode);
|
||||
@@ -301,17 +311,53 @@ namespace mRemoteNG.UI.Controls
|
||||
if (sortTarget == null)
|
||||
sortTarget = GetRootConnectionNode();
|
||||
|
||||
Runtime.ConnectionsService.BeginBatchingSaves();
|
||||
|
||||
var sortTargetAsContainer = sortTarget as ContainerInfo;
|
||||
if (sortTargetAsContainer != null)
|
||||
sortTargetAsContainer.SortRecursive(sortDirection);
|
||||
else
|
||||
SelectedNode.Parent.SortRecursive(sortDirection);
|
||||
|
||||
Runtime.ConnectionsService.EndBatchingSaves();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Expands all tree objects and recalculates the
|
||||
/// column widths.
|
||||
/// </summary>
|
||||
public override void ExpandAll()
|
||||
{
|
||||
base.ExpandAll();
|
||||
AutoResizeColumn(Columns[0]);
|
||||
}
|
||||
|
||||
protected override void UpdateFiltering()
|
||||
{
|
||||
base.UpdateFiltering();
|
||||
AutoResizeColumn(Columns[0]);
|
||||
}
|
||||
|
||||
private void HandleCollectionChanged(object sender, NotifyCollectionChangedEventArgs args)
|
||||
{
|
||||
RefreshObject(sender);
|
||||
// disable filtering if necessary. prevents RefreshObjects from
|
||||
// throwing an exception
|
||||
var filteringEnabled = IsFiltering;
|
||||
var filter = ModelFilter;
|
||||
if (filteringEnabled)
|
||||
{
|
||||
ResetColumnFiltering();
|
||||
}
|
||||
|
||||
RefreshObject(sender);
|
||||
AutoResizeColumn(Columns[0]);
|
||||
|
||||
// turn filtering back on
|
||||
if (filteringEnabled)
|
||||
{
|
||||
ModelFilter = filter;
|
||||
UpdateFiltering();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnMouse_DoubleClick(object sender, MouseEventArgs mouseEventArgs)
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
using System.Windows.Forms;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows.Forms;
|
||||
using mRemoteNG.App;
|
||||
using mRemoteNG.App.Info;
|
||||
using mRemoteNG.Messages;
|
||||
using mRemoteNG.UI.TaskDialog;
|
||||
|
||||
namespace mRemoteNG.UI
|
||||
{
|
||||
@@ -15,5 +20,86 @@ namespace mRemoteNG.UI
|
||||
Filter = Language.strFiltermRemoteXML + @"|*.xml|" + Language.strFilterAll + @"|*.*"
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates and shows a dialog to either create a new connections file, load a different one,
|
||||
/// exit, or optionally cancel the operation.
|
||||
/// </summary>
|
||||
/// <param name="connectionFileName"></param>
|
||||
/// <param name="messageText"></param>
|
||||
/// <param name="showCancelButton"></param>
|
||||
public static void ShowLoadConnectionsFailedDialog(string connectionFileName, string messageText, bool showCancelButton)
|
||||
{
|
||||
var commandButtons = new List<string>
|
||||
{
|
||||
Language.ConfigurationCreateNew,
|
||||
Language.strOpenADifferentFile,
|
||||
Language.strMenuExit
|
||||
};
|
||||
|
||||
if (showCancelButton)
|
||||
commandButtons.Add(Language.strButtonCancel);
|
||||
|
||||
var answered = false;
|
||||
while (!answered)
|
||||
{
|
||||
try
|
||||
{
|
||||
CTaskDialog.ShowTaskDialogBox(
|
||||
GeneralAppInfo.ProductName,
|
||||
messageText,
|
||||
"", "", "", "", "",
|
||||
string.Join(" | ", commandButtons),
|
||||
ETaskDialogButtons.None,
|
||||
ESysIcons.Question,
|
||||
ESysIcons.Question);
|
||||
|
||||
switch (CTaskDialog.CommandButtonResult)
|
||||
{
|
||||
case 0: // New
|
||||
var saveAsDialog = ConnectionsSaveAsDialog();
|
||||
saveAsDialog.ShowDialog();
|
||||
Runtime.ConnectionsService.NewConnectionsFile(saveAsDialog.FileName);
|
||||
answered = true;
|
||||
break;
|
||||
case 1: // Load
|
||||
Runtime.LoadConnections(true);
|
||||
answered = true;
|
||||
break;
|
||||
case 2: // Exit
|
||||
Application.Exit();
|
||||
answered = true;
|
||||
break;
|
||||
case 3: // Cancel
|
||||
answered = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionMessage(
|
||||
string.Format(Language.strConnectionsFileCouldNotBeLoadedNew, connectionFileName),
|
||||
exception,
|
||||
MessageClass.WarningMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new dialog that allows the user to select an mRemoteNG
|
||||
/// connections file path. Don't forget to dispose the dialog when you
|
||||
/// are done!
|
||||
/// </summary>
|
||||
public static SaveFileDialog ConnectionsSaveAsDialog()
|
||||
{
|
||||
return new SaveFileDialog
|
||||
{
|
||||
CheckPathExists = true,
|
||||
InitialDirectory = ConnectionsFileInfo.DefaultConnectionsPath,
|
||||
FileName = ConnectionsFileInfo.DefaultConnectionsFile,
|
||||
OverwritePrompt = true,
|
||||
Filter = Language.strFiltermRemoteXML + @"|*.xml|" + Language.strFilterAll + @"|*.*"
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
48
mRemoteV1/UI/Forms/ExportForm.Designer.cs
generated
48
mRemoteV1/UI/Forms/ExportForm.Designer.cs
generated
@@ -9,27 +9,27 @@ namespace mRemoteNG.UI.Forms
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.btnCancel = new Controls.Base.NGButton();
|
||||
this.btnOK = new Controls.Base.NGButton();
|
||||
this.lblUncheckProperties = new Controls.Base.NGLabel();
|
||||
this.chkUsername = new Controls.Base.NGCheckBox();
|
||||
this.chkPassword = new Controls.Base.NGCheckBox();
|
||||
this.chkDomain = new Controls.Base.NGCheckBox();
|
||||
this.chkInheritance = new Controls.Base.NGCheckBox();
|
||||
this.txtFileName = new Controls.Base.NGTextBox();
|
||||
this.btnBrowse = new Controls.Base.NGButton();
|
||||
this.btnCancel = new mRemoteNG.UI.Controls.Base.NGButton();
|
||||
this.btnOK = new mRemoteNG.UI.Controls.Base.NGButton();
|
||||
this.lblUncheckProperties = new mRemoteNG.UI.Controls.Base.NGLabel();
|
||||
this.chkUsername = new mRemoteNG.UI.Controls.Base.NGCheckBox();
|
||||
this.chkPassword = new mRemoteNG.UI.Controls.Base.NGCheckBox();
|
||||
this.chkDomain = new mRemoteNG.UI.Controls.Base.NGCheckBox();
|
||||
this.chkInheritance = new mRemoteNG.UI.Controls.Base.NGCheckBox();
|
||||
this.txtFileName = new mRemoteNG.UI.Controls.Base.NGTextBox();
|
||||
this.btnBrowse = new mRemoteNG.UI.Controls.Base.NGButton();
|
||||
this.grpProperties = new System.Windows.Forms.GroupBox();
|
||||
this.chkAssignedCredential = new Controls.Base.NGCheckBox();
|
||||
this.chkAssignedCredential = new mRemoteNG.UI.Controls.Base.NGCheckBox();
|
||||
this.grpFile = new System.Windows.Forms.GroupBox();
|
||||
this.lblFileFormat = new Controls.Base.NGLabel();
|
||||
this.lblFileName = new Controls.Base.NGLabel();
|
||||
this.cboFileFormat = new Controls.Base.NGComboBox();
|
||||
this.lblFileFormat = new mRemoteNG.UI.Controls.Base.NGLabel();
|
||||
this.lblFileName = new mRemoteNG.UI.Controls.Base.NGLabel();
|
||||
this.cboFileFormat = new mRemoteNG.UI.Controls.Base.NGComboBox();
|
||||
this.grpItems = new System.Windows.Forms.GroupBox();
|
||||
this.lblSelectedConnection = new Controls.Base.NGLabel();
|
||||
this.lblSelectedFolder = new Controls.Base.NGLabel();
|
||||
this.rdoExportSelectedConnection = new Controls.Base.NGRadioButton();
|
||||
this.rdoExportSelectedFolder = new Controls.Base.NGRadioButton();
|
||||
this.rdoExportEverything = new Controls.Base.NGRadioButton();
|
||||
this.lblSelectedConnection = new mRemoteNG.UI.Controls.Base.NGLabel();
|
||||
this.lblSelectedFolder = new mRemoteNG.UI.Controls.Base.NGLabel();
|
||||
this.rdoExportSelectedConnection = new mRemoteNG.UI.Controls.Base.NGRadioButton();
|
||||
this.rdoExportSelectedFolder = new mRemoteNG.UI.Controls.Base.NGRadioButton();
|
||||
this.rdoExportEverything = new mRemoteNG.UI.Controls.Base.NGRadioButton();
|
||||
this.grpProperties.SuspendLayout();
|
||||
this.grpFile.SuspendLayout();
|
||||
this.grpItems.SuspendLayout();
|
||||
@@ -37,6 +37,7 @@ namespace mRemoteNG.UI.Forms
|
||||
//
|
||||
// btnCancel
|
||||
//
|
||||
this.btnCancel._mice = mRemoteNG.UI.Controls.Base.NGButton.MouseState.HOVER;
|
||||
this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
|
||||
this.btnCancel.Location = new System.Drawing.Point(447, 473);
|
||||
this.btnCancel.Name = "btnCancel";
|
||||
@@ -48,6 +49,7 @@ namespace mRemoteNG.UI.Forms
|
||||
//
|
||||
// btnOK
|
||||
//
|
||||
this.btnOK._mice = mRemoteNG.UI.Controls.Base.NGButton.MouseState.HOVER;
|
||||
this.btnOK.Location = new System.Drawing.Point(366, 473);
|
||||
this.btnOK.Name = "btnOK";
|
||||
this.btnOK.Size = new System.Drawing.Size(75, 23);
|
||||
@@ -67,6 +69,7 @@ namespace mRemoteNG.UI.Forms
|
||||
//
|
||||
// chkUsername
|
||||
//
|
||||
this.chkUsername._mice = mRemoteNG.UI.Controls.Base.NGCheckBox.MouseState.HOVER;
|
||||
this.chkUsername.AutoSize = true;
|
||||
this.chkUsername.Checked = true;
|
||||
this.chkUsername.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
@@ -79,6 +82,7 @@ namespace mRemoteNG.UI.Forms
|
||||
//
|
||||
// chkPassword
|
||||
//
|
||||
this.chkPassword._mice = mRemoteNG.UI.Controls.Base.NGCheckBox.MouseState.HOVER;
|
||||
this.chkPassword.AutoSize = true;
|
||||
this.chkPassword.Checked = true;
|
||||
this.chkPassword.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
@@ -91,6 +95,7 @@ namespace mRemoteNG.UI.Forms
|
||||
//
|
||||
// chkDomain
|
||||
//
|
||||
this.chkDomain._mice = mRemoteNG.UI.Controls.Base.NGCheckBox.MouseState.HOVER;
|
||||
this.chkDomain.AutoSize = true;
|
||||
this.chkDomain.Checked = true;
|
||||
this.chkDomain.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
@@ -103,6 +108,7 @@ namespace mRemoteNG.UI.Forms
|
||||
//
|
||||
// chkInheritance
|
||||
//
|
||||
this.chkInheritance._mice = mRemoteNG.UI.Controls.Base.NGCheckBox.MouseState.HOVER;
|
||||
this.chkInheritance.AutoSize = true;
|
||||
this.chkInheritance.Checked = true;
|
||||
this.chkInheritance.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
@@ -124,6 +130,7 @@ namespace mRemoteNG.UI.Forms
|
||||
//
|
||||
// btnBrowse
|
||||
//
|
||||
this.btnBrowse._mice = mRemoteNG.UI.Controls.Base.NGButton.MouseState.HOVER;
|
||||
this.btnBrowse.Location = new System.Drawing.Point(417, 46);
|
||||
this.btnBrowse.Name = "btnBrowse";
|
||||
this.btnBrowse.Size = new System.Drawing.Size(75, 23);
|
||||
@@ -149,6 +156,7 @@ namespace mRemoteNG.UI.Forms
|
||||
//
|
||||
// chkAssignedCredential
|
||||
//
|
||||
this.chkAssignedCredential._mice = mRemoteNG.UI.Controls.Base.NGCheckBox.MouseState.HOVER;
|
||||
this.chkAssignedCredential.AutoSize = true;
|
||||
this.chkAssignedCredential.Checked = true;
|
||||
this.chkAssignedCredential.CheckState = System.Windows.Forms.CheckState.Checked;
|
||||
@@ -158,6 +166,7 @@ namespace mRemoteNG.UI.Forms
|
||||
this.chkAssignedCredential.TabIndex = 5;
|
||||
this.chkAssignedCredential.Text = "Assigned Credential";
|
||||
this.chkAssignedCredential.UseVisualStyleBackColor = true;
|
||||
this.chkAssignedCredential.Visible = false;
|
||||
//
|
||||
// grpFile
|
||||
//
|
||||
@@ -193,7 +202,8 @@ namespace mRemoteNG.UI.Forms
|
||||
//
|
||||
// cboFileFormat
|
||||
//
|
||||
this.cboFileFormat.DropDownStyle = ComboBoxStyle.DropDownList;
|
||||
this.cboFileFormat._mice = mRemoteNG.UI.Controls.Base.NGComboBox.MouseState.HOVER;
|
||||
this.cboFileFormat.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||
this.cboFileFormat.FormattingEnabled = true;
|
||||
this.cboFileFormat.Location = new System.Drawing.Point(15, 100);
|
||||
this.cboFileFormat.Name = "cboFileFormat";
|
||||
|
||||
@@ -226,20 +226,21 @@ namespace mRemoteNG.UI.Forms
|
||||
|
||||
private void cboFileformat_SelectedIndexChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (SaveFormat == SaveFormat.mRXML)
|
||||
{
|
||||
chkUsername.Enabled = false;
|
||||
chkPassword.Enabled = false;
|
||||
chkDomain.Enabled = false;
|
||||
chkAssignedCredential.Enabled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
chkUsername.Enabled = true;
|
||||
chkPassword.Enabled = true;
|
||||
chkDomain.Enabled = true;
|
||||
chkAssignedCredential.Enabled = false;
|
||||
}
|
||||
// should only be active if we are using the credential manager feature
|
||||
//if (SaveFormat == SaveFormat.mRXML)
|
||||
//{
|
||||
// chkUsername.Enabled = false;
|
||||
// chkPassword.Enabled = false;
|
||||
// chkDomain.Enabled = false;
|
||||
// chkAssignedCredential.Enabled = true;
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// chkUsername.Enabled = true;
|
||||
// chkPassword.Enabled = true;
|
||||
// chkDomain.Enabled = true;
|
||||
// chkAssignedCredential.Enabled = false;
|
||||
//}
|
||||
}
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -38,6 +38,9 @@ namespace mRemoteNG.UI.Forms.OptionsPages
|
||||
this.chkShowLogonInfoOnTabs = new mRemoteNG.UI.Controls.Base.NGCheckBox();
|
||||
this.chkDoubleClickClosesTab = new mRemoteNG.UI.Controls.Base.NGCheckBox();
|
||||
this.chkShowProtocolOnTabs = new mRemoteNG.UI.Controls.Base.NGCheckBox();
|
||||
this.chkCreateEmptyPanelOnStart = new mRemoteNG.UI.Controls.Base.NGCheckBox();
|
||||
this.txtBoxPanelName = new mRemoteNG.UI.Controls.Base.NGTextBox();
|
||||
this.lblPanelName = new mRemoteNG.UI.Controls.Base.NGLabel();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// chkAlwaysShowPanelTabs
|
||||
@@ -117,10 +120,41 @@ namespace mRemoteNG.UI.Forms.OptionsPages
|
||||
this.chkShowProtocolOnTabs.Text = "Show protocols on tab names";
|
||||
this.chkShowProtocolOnTabs.UseVisualStyleBackColor = true;
|
||||
//
|
||||
// chkCreateEmptyPanelOnStart
|
||||
//
|
||||
this.chkCreateEmptyPanelOnStart._mice = mRemoteNG.UI.Controls.Base.NGCheckBox.MouseState.HOVER;
|
||||
this.chkCreateEmptyPanelOnStart.AutoSize = true;
|
||||
this.chkCreateEmptyPanelOnStart.Location = new System.Drawing.Point(3, 164);
|
||||
this.chkCreateEmptyPanelOnStart.Name = "chkCreateEmptyPanelOnStart";
|
||||
this.chkCreateEmptyPanelOnStart.Size = new System.Drawing.Size(253, 17);
|
||||
this.chkCreateEmptyPanelOnStart.TabIndex = 7;
|
||||
this.chkCreateEmptyPanelOnStart.Text = "Create an empty panel when mRemoteNG starts";
|
||||
this.chkCreateEmptyPanelOnStart.UseVisualStyleBackColor = true;
|
||||
this.chkCreateEmptyPanelOnStart.CheckedChanged += new System.EventHandler(this.chkCreateEmptyPanelOnStart_CheckedChanged);
|
||||
//
|
||||
// txtBoxPanelName
|
||||
//
|
||||
this.txtBoxPanelName.Location = new System.Drawing.Point(43, 200);
|
||||
this.txtBoxPanelName.Name = "txtBoxPanelName";
|
||||
this.txtBoxPanelName.Size = new System.Drawing.Size(213, 20);
|
||||
this.txtBoxPanelName.TabIndex = 8;
|
||||
//
|
||||
// lblPanelName
|
||||
//
|
||||
this.lblPanelName.AutoSize = true;
|
||||
this.lblPanelName.Location = new System.Drawing.Point(40, 184);
|
||||
this.lblPanelName.Name = "lblPanelName";
|
||||
this.lblPanelName.Size = new System.Drawing.Size(66, 13);
|
||||
this.lblPanelName.TabIndex = 9;
|
||||
this.lblPanelName.Text = "Panel name:";
|
||||
//
|
||||
// TabsPanelsPage
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.Controls.Add(this.lblPanelName);
|
||||
this.Controls.Add(this.txtBoxPanelName);
|
||||
this.Controls.Add(this.chkCreateEmptyPanelOnStart);
|
||||
this.Controls.Add(this.chkAlwaysShowPanelTabs);
|
||||
this.Controls.Add(this.chkIdentifyQuickConnectTabs);
|
||||
this.Controls.Add(this.chkOpenNewTabRightOfSelected);
|
||||
@@ -142,6 +176,8 @@ namespace mRemoteNG.UI.Forms.OptionsPages
|
||||
internal Controls.Base.NGCheckBox chkShowLogonInfoOnTabs;
|
||||
internal Controls.Base.NGCheckBox chkDoubleClickClosesTab;
|
||||
internal Controls.Base.NGCheckBox chkShowProtocolOnTabs;
|
||||
|
||||
}
|
||||
private Controls.Base.NGCheckBox chkCreateEmptyPanelOnStart;
|
||||
private Controls.Base.NGTextBox txtBoxPanelName;
|
||||
private Controls.Base.NGLabel lblPanelName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,8 @@ namespace mRemoteNG.UI.Forms.OptionsPages
|
||||
chkIdentifyQuickConnectTabs.Text = Language.strIdentifyQuickConnectTabs;
|
||||
chkDoubleClickClosesTab.Text = Language.strDoubleClickTabClosesIt;
|
||||
chkAlwaysShowPanelSelectionDlg.Text = Language.strAlwaysShowPanelSelection;
|
||||
chkCreateEmptyPanelOnStart.Text = Language.strCreateEmptyPanelOnStartUp;
|
||||
lblPanelName.Text = $"{Language.strPanelName}:";
|
||||
}
|
||||
|
||||
public override void LoadSettings()
|
||||
@@ -43,6 +45,9 @@ namespace mRemoteNG.UI.Forms.OptionsPages
|
||||
chkIdentifyQuickConnectTabs.Checked = Settings.Default.IdentifyQuickConnectTabs;
|
||||
chkDoubleClickClosesTab.Checked = Settings.Default.DoubleClickOnTabClosesIt;
|
||||
chkAlwaysShowPanelSelectionDlg.Checked = Settings.Default.AlwaysShowPanelSelectionDlg;
|
||||
chkCreateEmptyPanelOnStart.Checked = Settings.Default.CreateEmptyPanelOnStartUp;
|
||||
txtBoxPanelName.Text = Settings.Default.StartUpPanelName;
|
||||
UpdatePanelNameTextBox();
|
||||
}
|
||||
|
||||
public override void SaveSettings()
|
||||
@@ -58,8 +63,20 @@ namespace mRemoteNG.UI.Forms.OptionsPages
|
||||
Settings.Default.IdentifyQuickConnectTabs = chkIdentifyQuickConnectTabs.Checked;
|
||||
Settings.Default.DoubleClickOnTabClosesIt = chkDoubleClickClosesTab.Checked;
|
||||
Settings.Default.AlwaysShowPanelSelectionDlg = chkAlwaysShowPanelSelectionDlg.Checked;
|
||||
Settings.Default.CreateEmptyPanelOnStartUp = chkCreateEmptyPanelOnStart.Checked;
|
||||
Settings.Default.StartUpPanelName = txtBoxPanelName.Text;
|
||||
|
||||
Settings.Default.Save();
|
||||
}
|
||||
|
||||
private void UpdatePanelNameTextBox()
|
||||
{
|
||||
txtBoxPanelName.Enabled = chkCreateEmptyPanelOnStart.Checked;
|
||||
}
|
||||
|
||||
private void chkCreateEmptyPanelOnStart_CheckedChanged(object sender, System.EventArgs e)
|
||||
{
|
||||
UpdatePanelNameTextBox();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Security;
|
||||
using System.Windows.Forms;
|
||||
using mRemoteNG.Security;
|
||||
using mRemoteNG.Tools;
|
||||
|
||||
namespace mRemoteNG.UI.Forms
|
||||
{
|
||||
@@ -19,12 +20,12 @@ namespace mRemoteNG.UI.Forms
|
||||
Verify = verify;
|
||||
}
|
||||
|
||||
public SecureString GetKey()
|
||||
public Optional<SecureString> GetKey()
|
||||
{
|
||||
var dialog = ShowDialog();
|
||||
return dialog == DialogResult.OK
|
||||
? _password
|
||||
: new SecureString();
|
||||
: Optional<SecureString>.Empty;
|
||||
}
|
||||
|
||||
#region Event Handlers
|
||||
|
||||
2
mRemoteV1/UI/Forms/frmMain.Designer.cs
generated
2
mRemoteV1/UI/Forms/frmMain.Designer.cs
generated
@@ -190,7 +190,7 @@ namespace mRemoteNG.UI.Forms
|
||||
this.Controls.Add(this.tsContainer);
|
||||
this.Icon = global::mRemoteNG.Resources.mRemote_Icon;
|
||||
this.MainMenuStrip = this.msMain;
|
||||
this.MinimumSize = new System.Drawing.Size(1145, 610);
|
||||
this.MinimumSize = new System.Drawing.Size(400, 400);
|
||||
this.Name = "FrmMain";
|
||||
this.Opacity = 0D;
|
||||
this.Text = "mRemoteNG";
|
||||
|
||||
@@ -17,8 +17,8 @@ using mRemoteNG.App.Update;
|
||||
using mRemoteNG.Config;
|
||||
using mRemoteNG.Config.Connections;
|
||||
using mRemoteNG.Config.DatabaseConnectors;
|
||||
using mRemoteNG.Config.DataProviders;
|
||||
using mRemoteNG.Config.Putty;
|
||||
using mRemoteNG.Config.Serializers.Xml;
|
||||
using mRemoteNG.Config.Settings;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Connection.Protocol;
|
||||
@@ -40,7 +40,7 @@ using WeifenLuo.WinFormsUI.Docking;
|
||||
|
||||
namespace mRemoteNG.UI.Forms
|
||||
{
|
||||
public partial class FrmMain
|
||||
public partial class FrmMain
|
||||
{
|
||||
private static ClipboardchangeEventHandler _clipboardChangedEvent;
|
||||
private bool _inSizeMove;
|
||||
@@ -70,6 +70,7 @@ namespace mRemoteNG.UI.Forms
|
||||
private readonly AppUpdater _appUpdater;
|
||||
private readonly DatabaseConnectorFactory _databaseConnectorFactory;
|
||||
private readonly Screens _screens;
|
||||
private readonly FileBackupPruner _backupPruner;
|
||||
private readonly MessageCollector _messageCollector = Runtime.MessageCollector;
|
||||
|
||||
internal FullscreenHandler Fullscreen { get; set; }
|
||||
@@ -86,7 +87,8 @@ namespace mRemoteNG.UI.Forms
|
||||
var externalToolsService = new ExternalToolsService();
|
||||
_import = new Import(this);
|
||||
_connectionsService = new ConnectionsService(PuttySessionsManager.Instance, _import, this);
|
||||
_import.ConnectionsService = _connectionsService;
|
||||
_backupPruner = new FileBackupPruner();
|
||||
_import.ConnectionsService = _connectionsService;
|
||||
Func<SecureString> encryptionKeySelectionFunc = () => _connectionsService.EncryptionKey;
|
||||
_appUpdater = new AppUpdater(encryptionKeySelectionFunc);
|
||||
ExternalToolsTypeConverter.ExternalToolsService = externalToolsService;
|
||||
@@ -109,7 +111,7 @@ namespace mRemoteNG.UI.Forms
|
||||
Func<UpdateWindow> updateWindowBuilder = () => new UpdateWindow(new DockContent(), _shutdown, _appUpdater);
|
||||
_notificationAreaIconBuilder = () => new NotificationAreaIcon(this, _connectionInitiator, _shutdown, _connectionsService);
|
||||
Func<ExternalToolsWindow> externalToolsWindowBuilder = () => new ExternalToolsWindow(_connectionInitiator, externalToolsService, () => connectionTree.SelectedNode, this, _connectionsService);
|
||||
Func<PortScanWindow> portScanWindowBuilder = () => new PortScanWindow(() => connectionTreeWindow.SelectedNode, _import);
|
||||
Func<PortScanWindow> portScanWindowBuilder = () => new PortScanWindow(connectionTreeWindow, _import);
|
||||
Func<ActiveDirectoryImportWindow> activeDirectoryImportWindowBuilder = () => new ActiveDirectoryImportWindow(() => connectionTreeWindow.SelectedNode, _import, _connectionsService);
|
||||
_databaseConnectorFactory = new DatabaseConnectorFactory(encryptionKeySelectionFunc);
|
||||
_windows = new Windows(_connectionInitiator, connectionTreeWindow, configWindow, errorAndInfoWindow, screenshotManagerWindow,
|
||||
@@ -233,6 +235,7 @@ namespace mRemoteNG.UI.Forms
|
||||
SetDefaultLayout();
|
||||
|
||||
_connectionsService.ConnectionsLoaded += ConnectionsServiceOnConnectionsLoaded;
|
||||
_connectionsService.ConnectionsSaved += ConnectionsServiceOnConnectionsSaved;
|
||||
var credsAndConsSetup = new CredsAndConsSetup(_connectionsService);
|
||||
credsAndConsSetup.LoadCredsAndCons();
|
||||
|
||||
@@ -250,7 +253,13 @@ namespace mRemoteNG.UI.Forms
|
||||
|
||||
Opacity = 1;
|
||||
//Fix missing general panel at the first run
|
||||
_panelAdder.AddPanel();
|
||||
if (Settings.Default.CreateEmptyPanelOnStartUp)
|
||||
{
|
||||
var panelName = !string.IsNullOrEmpty(Settings.Default.StartUpPanelName)
|
||||
? Settings.Default.StartUpPanelName
|
||||
: Language.strNewPanel;
|
||||
_panelAdder.AddPanel(panelName);
|
||||
}
|
||||
}
|
||||
|
||||
private void ApplyLanguage()
|
||||
@@ -285,6 +294,14 @@ namespace mRemoteNG.UI.Forms
|
||||
UpdateWindowTitle();
|
||||
}
|
||||
|
||||
private void ConnectionsServiceOnConnectionsSaved(object sender, ConnectionsSavedEventArgs connectionsSavedEventArgs)
|
||||
{
|
||||
if (connectionsSavedEventArgs.UsingDatabase)
|
||||
return;
|
||||
|
||||
_backupPruner.PruneBackupFiles(connectionsSavedEventArgs.ConnectionFileName, Settings.Default.BackupFileKeepCount);
|
||||
}
|
||||
|
||||
private void SetMenuDependencies()
|
||||
{
|
||||
fileMenu.TreeWindow = _windows.TreeForm;
|
||||
|
||||
@@ -3,7 +3,6 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
using mRemoteNG.App;
|
||||
using mRemoteNG.App.Info;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Container;
|
||||
using mRemoteNG.Security;
|
||||
@@ -103,6 +102,7 @@ namespace mRemoteNG.UI.Menu
|
||||
Size = new System.Drawing.Size(37, 20);
|
||||
Text = Language.strMenuFile;
|
||||
//DropDownOpening += mMenFile_DropDownOpening;
|
||||
DropDownClosed += OnDropDownClosed;
|
||||
//
|
||||
// mMenFileNewConnection
|
||||
//
|
||||
@@ -352,6 +352,16 @@ namespace mRemoteNG.UI.Menu
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDropDownClosed(object sender, EventArgs eventArgs)
|
||||
{
|
||||
_mMenFileNewConnection.Enabled = true;
|
||||
_mMenFileNewFolder.Enabled = true;
|
||||
_mMenFileDelete.Enabled = true;
|
||||
_mMenFileRename.Enabled = true;
|
||||
_mMenFileDuplicate.Enabled = true;
|
||||
_mMenReconnectAll.Enabled = true;
|
||||
}
|
||||
|
||||
private void mMenFileNewConnection_Click(object sender, EventArgs e)
|
||||
{
|
||||
TreeWindow.ConnectionTree.AddConnection();
|
||||
@@ -364,13 +374,15 @@ namespace mRemoteNG.UI.Menu
|
||||
|
||||
private void mMenFileNew_Click(object sender, EventArgs e)
|
||||
{
|
||||
var saveFileDialog = ConnectionsSaveAsDialog();
|
||||
if (saveFileDialog.ShowDialog() != DialogResult.OK)
|
||||
using (var saveFileDialog = DialogFactory.ConnectionsSaveAsDialog())
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (saveFileDialog.ShowDialog() != DialogResult.OK)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ConnectionsService.NewConnectionsFile(saveFileDialog.FileName);
|
||||
}
|
||||
}
|
||||
|
||||
private void mMenFileLoad_Click(object sender, EventArgs e)
|
||||
@@ -399,15 +411,11 @@ namespace mRemoteNG.UI.Menu
|
||||
|
||||
private void mMenFileSaveAs_Click(object sender, EventArgs e)
|
||||
{
|
||||
using (var saveFileDialog = new SaveFileDialog())
|
||||
using (var saveFileDialog = DialogFactory.ConnectionsSaveAsDialog())
|
||||
{
|
||||
saveFileDialog.CheckPathExists = true;
|
||||
saveFileDialog.InitialDirectory = ConnectionsFileInfo.DefaultConnectionsPath;
|
||||
saveFileDialog.FileName = ConnectionsFileInfo.DefaultConnectionsFile;
|
||||
saveFileDialog.OverwritePrompt = true;
|
||||
saveFileDialog.Filter = $@"{Language.strFiltermRemoteXML}|*.xml|{Language.strFilterAll}|*.*";
|
||||
if (saveFileDialog.ShowDialog(FrmMain.Default) != DialogResult.OK)
|
||||
return;
|
||||
|
||||
if (saveFileDialog.ShowDialog(DialogWindowParent) != DialogResult.OK) return;
|
||||
var newFileName = saveFileDialog.FileName;
|
||||
|
||||
ConnectionsService.SaveConnections(ConnectionsService.ConnectionTreeModel, false, new SaveFilter(), newFileName);
|
||||
@@ -501,18 +509,6 @@ namespace mRemoteNG.UI.Menu
|
||||
{
|
||||
Shutdown.Quit();
|
||||
}
|
||||
|
||||
public static SaveFileDialog ConnectionsSaveAsDialog()
|
||||
{
|
||||
return new SaveFileDialog
|
||||
{
|
||||
CheckPathExists = true,
|
||||
InitialDirectory = ConnectionsFileInfo.DefaultConnectionsPath,
|
||||
FileName = ConnectionsFileInfo.DefaultConnectionsFile,
|
||||
OverwritePrompt = true,
|
||||
Filter = Language.strFiltermRemoteXML + @"|*.xml|" + Language.strFilterAll + @"|*.*"
|
||||
};
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@ using WeifenLuo.WinFormsUI.Docking;
|
||||
|
||||
namespace mRemoteNG.UI.Window
|
||||
{
|
||||
public class ConfigWindow : BaseWindow
|
||||
public class ConfigWindow : BaseWindow
|
||||
{
|
||||
private bool _originalPropertyGridToolStripItemCountValid;
|
||||
private int _originalPropertyGridToolStripItemCount;
|
||||
@@ -740,29 +740,32 @@ namespace mRemoteNG.UI.Window
|
||||
private void UpdateRootInfoNode(PropertyValueChangedEventArgs e)
|
||||
{
|
||||
var rootInfo = _pGrid.SelectedObject as RootNodeInfo;
|
||||
if (rootInfo == null) return;
|
||||
if (e.ChangedItem.PropertyDescriptor == null) return;
|
||||
// ReSharper disable once SwitchStatementMissingSomeCases
|
||||
switch (e.ChangedItem.PropertyDescriptor.Name)
|
||||
{
|
||||
case "Password":
|
||||
if (rootInfo.Password)
|
||||
{
|
||||
var passwordName = Settings.Default.UseSQLServer ? Language.strSQLServer.TrimEnd(':') : Path.GetFileName(_connectionsService.GetStartupConnectionFileName());
|
||||
if (rootInfo == null)
|
||||
return;
|
||||
|
||||
var password = MiscTools.PasswordDialog(passwordName);
|
||||
if (password.Length == 0)
|
||||
rootInfo.Password = false;
|
||||
else
|
||||
rootInfo.PasswordString = password.ConvertToUnsecureString();
|
||||
}
|
||||
else
|
||||
{
|
||||
rootInfo.PasswordString = "";
|
||||
}
|
||||
break;
|
||||
case "Name":
|
||||
break;
|
||||
if (e.ChangedItem.PropertyDescriptor?.Name != "Password")
|
||||
return;
|
||||
|
||||
if (rootInfo.Password)
|
||||
{
|
||||
var passwordName = Settings.Default.UseSQLServer
|
||||
? Language.strSQLServer.TrimEnd(':')
|
||||
: Path.GetFileName(_connectionsService.GetStartupConnectionFileName());
|
||||
|
||||
var password = MiscTools.PasswordDialog(passwordName);
|
||||
|
||||
// operation cancelled, dont set a password
|
||||
if (!password.Any() || password.First().Length == 0)
|
||||
{
|
||||
rootInfo.Password = false;
|
||||
return;
|
||||
}
|
||||
|
||||
rootInfo.PasswordString = password.First().ConvertToUnsecureString();
|
||||
}
|
||||
else
|
||||
{
|
||||
rootInfo.PasswordString = "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ using WeifenLuo.WinFormsUI.Docking;
|
||||
|
||||
namespace mRemoteNG.UI.Window
|
||||
{
|
||||
public partial class ConnectionTreeWindow
|
||||
public partial class ConnectionTreeWindow
|
||||
{
|
||||
private readonly IConnectionInitiator _connectionInitiator;
|
||||
private readonly IConnectionsService _connectionsService;
|
||||
@@ -44,11 +44,22 @@ namespace mRemoteNG.UI.Window
|
||||
InitializeComponent();
|
||||
SetMenuEventHandlers();
|
||||
SetConnectionTreeEventHandlers();
|
||||
Settings.Default.PropertyChanged += (sender, args) => SetConnectionTreeEventHandlers();
|
||||
Settings.Default.PropertyChanged += OnAppSettingsChanged;
|
||||
olvConnections.ModelFilter = _connectionTreeSearchTextFilter;
|
||||
}
|
||||
private void OnAppSettingsChanged(object o, PropertyChangedEventArgs propertyChangedEventArgs)
|
||||
{
|
||||
if (propertyChangedEventArgs.PropertyName == nameof(Settings.UseFilterSearch))
|
||||
{
|
||||
ConnectionTree.UseFiltering = Settings.Default.UseFilterSearch;
|
||||
ApplyFiltering();
|
||||
}
|
||||
|
||||
SetConnectionTreeEventHandlers();
|
||||
}
|
||||
|
||||
#region Form Stuff
|
||||
|
||||
#region Form Stuff
|
||||
private void Tree_Load(object sender, EventArgs e)
|
||||
{
|
||||
ApplyLanguage();
|
||||
@@ -100,8 +111,6 @@ namespace mRemoteNG.UI.Window
|
||||
private void SetConnectionTreeEventHandlers()
|
||||
{
|
||||
olvConnections.NodeDeletionConfirmer = new SelectedConnectionDeletionConfirmer(MessageBox.Show);
|
||||
olvConnections.BeforeLabelEdit += tvConnections_BeforeLabelEdit;
|
||||
olvConnections.AfterLabelEdit += tvConnections_AfterLabelEdit;
|
||||
olvConnections.KeyDown += tvConnections_KeyDown;
|
||||
olvConnections.KeyPress += tvConnections_KeyPress;
|
||||
SetTreePostSetupActions();
|
||||
@@ -177,24 +186,6 @@ namespace mRemoteNG.UI.Window
|
||||
{
|
||||
olvConnections.AddFolder();
|
||||
}
|
||||
|
||||
private void tvConnections_BeforeLabelEdit(object sender, LabelEditEventArgs e)
|
||||
{
|
||||
ConnectionTreeContextMenu.DisableShortcutKeys();
|
||||
}
|
||||
|
||||
private void tvConnections_AfterLabelEdit(object sender, LabelEditEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
ConnectionTreeContextMenu.EnableShortcutKeys();
|
||||
ConnectionTree.ConnectionTreeModel.RenameNode(SelectedNode, e.Label);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Runtime.MessageCollector.AddExceptionStackTrace("tvConnections_AfterLabelEdit (UI.Window.ConnectionTreeWindow) failed", ex);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Search
|
||||
@@ -243,25 +234,30 @@ namespace mRemoteNG.UI.Window
|
||||
}
|
||||
|
||||
private void txtSearch_TextChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (Settings.Default.UseFilterSearch)
|
||||
{
|
||||
if (txtSearch.Text == "" || txtSearch.Text == Language.strSearchPrompt)
|
||||
{
|
||||
olvConnections.UseFiltering = false;
|
||||
olvConnections.ResetColumnFiltering();
|
||||
return;
|
||||
}
|
||||
olvConnections.UseFiltering = true;
|
||||
_connectionTreeSearchTextFilter.FilterText = txtSearch.Text;
|
||||
olvConnections.ModelFilter = _connectionTreeSearchTextFilter;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (txtSearch.Text == "") return;
|
||||
olvConnections.NodeSearcher?.SearchByName(txtSearch.Text);
|
||||
JumpToNode(olvConnections.NodeSearcher?.CurrentMatch);
|
||||
}
|
||||
{
|
||||
ApplyFiltering();
|
||||
}
|
||||
|
||||
private void ApplyFiltering()
|
||||
{
|
||||
if (Settings.Default.UseFilterSearch)
|
||||
{
|
||||
if (txtSearch.Text == "" || txtSearch.Text == Language.strSearchPrompt)
|
||||
{
|
||||
olvConnections.UseFiltering = false;
|
||||
olvConnections.ResetColumnFiltering();
|
||||
return;
|
||||
}
|
||||
olvConnections.UseFiltering = true;
|
||||
_connectionTreeSearchTextFilter.FilterText = txtSearch.Text;
|
||||
olvConnections.ModelFilter = _connectionTreeSearchTextFilter;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (txtSearch.Text == "") return;
|
||||
olvConnections.NodeSearcher?.SearchByName(txtSearch.Text);
|
||||
JumpToNode(olvConnections.NodeSearcher?.CurrentMatch);
|
||||
}
|
||||
}
|
||||
|
||||
private void JumpToNode(ConnectionInfo connectionInfo)
|
||||
|
||||
@@ -10,47 +10,48 @@ namespace mRemoteNG.UI.Window
|
||||
{
|
||||
|
||||
#region Form Init
|
||||
internal TreeView tvIndex;
|
||||
|
||||
private TreeView tvIndex;
|
||||
internal ImageList imgListHelp;
|
||||
private System.ComponentModel.Container components;
|
||||
internal SplitContainer pnlSplitter;
|
||||
internal Label lblDocName;
|
||||
internal WebBrowser wbHelp;
|
||||
private SplitContainer pnlSplitter;
|
||||
private Label lblDocName;
|
||||
private WebBrowser wbHelp;
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
components = new System.ComponentModel.Container();
|
||||
Load += new EventHandler(Help_Load);
|
||||
Shown += new EventHandler(Help_Shown);
|
||||
TreeNode TreeNode1 = new TreeNode("Introduction");
|
||||
TreeNode TreeNode2 = new TreeNode("Prerequisites");
|
||||
TreeNode TreeNode3 = new TreeNode("Installation");
|
||||
TreeNode TreeNode4 = new TreeNode("Configuration");
|
||||
TreeNode TreeNode5 = new TreeNode("SQL Configuration");
|
||||
TreeNode TreeNode6 = new TreeNode("Command-Line Switches");
|
||||
TreeNode TreeNode7 = new TreeNode("Getting Started", new[] {TreeNode2, TreeNode3, TreeNode4, TreeNode5, TreeNode6});
|
||||
TreeNode TreeNode8 = new TreeNode("Main Menu");
|
||||
TreeNode TreeNode9 = new TreeNode("Connections");
|
||||
TreeNode TreeNode10 = new TreeNode("Config");
|
||||
TreeNode TreeNode11 = new TreeNode("Errors and Infos");
|
||||
TreeNode TreeNode12 = new TreeNode("Save As / Export");
|
||||
TreeNode TreeNode14 = new TreeNode("Screenshot Manager");
|
||||
TreeNode TreeNode15 = new TreeNode("Connection");
|
||||
TreeNode TreeNode16 = new TreeNode("Options");
|
||||
TreeNode TreeNode17 = new TreeNode("Update");
|
||||
TreeNode TreeNode18 = new TreeNode("SSH File Transfer");
|
||||
TreeNode TreeNode19 = new TreeNode("Quick Connect");
|
||||
TreeNode TreeNode20 = new TreeNode("Import From Active Directory");
|
||||
TreeNode TreeNode21 = new TreeNode("External Applications");
|
||||
TreeNode TreeNode22 = new TreeNode("Port Scan");
|
||||
TreeNode TreeNode23 = new TreeNode("User Interface", new[] {TreeNode8, TreeNode9, TreeNode10, TreeNode11, TreeNode12, TreeNode14, TreeNode15, TreeNode16, TreeNode17, TreeNode18, TreeNode19, TreeNode20, TreeNode21, TreeNode22});
|
||||
TreeNode TreeNode24 = new TreeNode("Quick Reference");
|
||||
TreeNode TreeNode25 = new TreeNode("Help", new[] {TreeNode1, TreeNode7, TreeNode23, TreeNode24});
|
||||
Load += Help_Load;
|
||||
Shown += Help_Shown;
|
||||
var TreeNode1 = new TreeNode("Introduction");
|
||||
var TreeNode2 = new TreeNode("Prerequisites");
|
||||
var TreeNode3 = new TreeNode("Installation");
|
||||
var TreeNode4 = new TreeNode("Configuration");
|
||||
var TreeNode5 = new TreeNode("SQL Configuration");
|
||||
var TreeNode6 = new TreeNode("Command-Line Switches");
|
||||
var TreeNode7 = new TreeNode("Getting Started", new[] {TreeNode2, TreeNode3, TreeNode4, TreeNode5, TreeNode6});
|
||||
var TreeNode8 = new TreeNode("Main Menu");
|
||||
var TreeNode9 = new TreeNode("Connections");
|
||||
var TreeNode10 = new TreeNode("Config");
|
||||
var TreeNode11 = new TreeNode("Errors and Infos");
|
||||
var TreeNode12 = new TreeNode("Save As / Export");
|
||||
var TreeNode14 = new TreeNode("Screenshot Manager");
|
||||
var TreeNode15 = new TreeNode("Connection");
|
||||
var TreeNode16 = new TreeNode("Options");
|
||||
var TreeNode17 = new TreeNode("Update");
|
||||
var TreeNode18 = new TreeNode("SSH File Transfer");
|
||||
var TreeNode19 = new TreeNode("Quick Connect");
|
||||
var TreeNode20 = new TreeNode("Import From Active Directory");
|
||||
var TreeNode21 = new TreeNode("External Applications");
|
||||
var TreeNode22 = new TreeNode("Port Scan");
|
||||
var TreeNode23 = new TreeNode("User Interface", new[] {TreeNode8, TreeNode9, TreeNode10, TreeNode11, TreeNode12, TreeNode14, TreeNode15, TreeNode16, TreeNode17, TreeNode18, TreeNode19, TreeNode20, TreeNode21, TreeNode22});
|
||||
var TreeNode24 = new TreeNode("Quick Reference");
|
||||
var TreeNode25 = new TreeNode("Help", new[] {TreeNode1, TreeNode7, TreeNode23, TreeNode24});
|
||||
wbHelp = new WebBrowser();
|
||||
wbHelp.DocumentTitleChanged += new EventHandler(wbHelp_DocumentTitleChanged);
|
||||
wbHelp.DocumentTitleChanged += wbHelp_DocumentTitleChanged;
|
||||
tvIndex = new TreeView();
|
||||
tvIndex.NodeMouseClick += new TreeNodeMouseClickEventHandler(tvIndex_NodeMouseClick);
|
||||
tvIndex.AfterSelect += new TreeViewEventHandler(tvIndex_AfterSelect);
|
||||
tvIndex.NodeMouseClick += tvIndex_NodeMouseClick;
|
||||
tvIndex.AfterSelect += tvIndex_AfterSelect;
|
||||
imgListHelp = new ImageList(components);
|
||||
pnlSplitter = new SplitContainer();
|
||||
lblDocName = new Label();
|
||||
@@ -80,75 +81,27 @@ namespace mRemoteNG.UI.Window
|
||||
tvIndex.HideSelection = false;
|
||||
tvIndex.Location = new System.Drawing.Point(1, 1);
|
||||
tvIndex.Name = "tvIndex";
|
||||
TreeNode1.Name = "Node0";
|
||||
TreeNode1.Tag = "Introduction";
|
||||
TreeNode1.Text = "Introduction";
|
||||
TreeNode2.Name = "Node0";
|
||||
TreeNode2.Tag = "Prerequisites";
|
||||
TreeNode2.Text = "Prerequisites";
|
||||
TreeNode3.Name = "Node3";
|
||||
TreeNode3.Tag = "Installation";
|
||||
TreeNode3.Text = "Installation";
|
||||
TreeNode4.Name = "Node4";
|
||||
TreeNode4.Tag = "Configuration";
|
||||
TreeNode4.Text = "Configuration";
|
||||
TreeNode5.Name = "Node0";
|
||||
TreeNode5.Tag = "ConfigurationSQL";
|
||||
TreeNode5.Text = "SQL Configuration";
|
||||
TreeNode6.Name = "Node5";
|
||||
TreeNode6.Tag = "CMDSwitches";
|
||||
TreeNode6.Text = "Command-Line Switches";
|
||||
TreeNode7.Name = "Node1";
|
||||
TreeNode7.Text = "Getting Started";
|
||||
TreeNode8.Name = "Node7";
|
||||
TreeNode8.Tag = "MainMenu";
|
||||
TreeNode8.Text = "Main Menu";
|
||||
TreeNode9.Name = "Node8";
|
||||
TreeNode9.Tag = "Connections";
|
||||
TreeNode9.Text = "Connections";
|
||||
TreeNode10.Name = "Node9";
|
||||
TreeNode10.Tag = "Config";
|
||||
TreeNode10.Text = "Config";
|
||||
TreeNode11.Name = "Node10";
|
||||
TreeNode11.Tag = "ErrorsAndInfos";
|
||||
TreeNode11.Text = "Errors and Infos";
|
||||
TreeNode12.Name = "Node11";
|
||||
TreeNode12.Tag = "SaveAsExport";
|
||||
TreeNode12.Text = "Save As / Export";
|
||||
TreeNode14.Name = "Node13";
|
||||
TreeNode14.Tag = "ScreenshotManager";
|
||||
TreeNode14.Text = "Screenshot Manager";
|
||||
TreeNode15.Name = "Node14";
|
||||
TreeNode15.Tag = "Connection";
|
||||
TreeNode15.Text = "Connection";
|
||||
TreeNode16.Name = "Node15";
|
||||
TreeNode16.Tag = "Options";
|
||||
TreeNode16.Text = "Options";
|
||||
TreeNode17.Name = "Node16";
|
||||
TreeNode17.Tag = "Update";
|
||||
TreeNode17.Text = "Update";
|
||||
TreeNode18.Name = "Node17";
|
||||
TreeNode18.Tag = "SSHFileTransfer";
|
||||
TreeNode18.Text = "SSH File Transfer";
|
||||
TreeNode19.Name = "Node18";
|
||||
TreeNode19.Tag = "QuickConnect";
|
||||
TreeNode19.Text = "Quick Connect";
|
||||
TreeNode20.Name = "Node19";
|
||||
TreeNode20.Tag = "ImportFromAD";
|
||||
TreeNode20.Text = "Import From Active Directory";
|
||||
TreeNode21.Name = "Node1";
|
||||
TreeNode21.Tag = "ExternalTools";
|
||||
TreeNode21.Text = "External Tools";
|
||||
TreeNode22.Name = "Node0";
|
||||
TreeNode22.Tag = "PortScan";
|
||||
TreeNode22.Text = "Port Scan";
|
||||
TreeNode23.Name = "Node6";
|
||||
TreeNode23.Text = "User Interface";
|
||||
TreeNode24.Name = "Node20";
|
||||
TreeNode24.Tag = "QuickReference";
|
||||
TreeNode24.Text = "Quick Reference";
|
||||
TreeNode25.Name = "Node0";
|
||||
TreeNode25.Text = "Help";
|
||||
TreeNode25.Tag = "Index";
|
||||
tvIndex.Nodes.AddRange(new[] {TreeNode25});
|
||||
tvIndex.ShowRootLines = false;
|
||||
@@ -193,7 +146,7 @@ namespace mRemoteNG.UI.Window
|
||||
lblDocName.Name = "lblDocName";
|
||||
lblDocName.Size = new System.Drawing.Size(327, 35);
|
||||
lblDocName.TabIndex = 2;
|
||||
lblDocName.Text = "Introduction";
|
||||
lblDocName.Text = @"Introduction";
|
||||
lblDocName.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
||||
//
|
||||
//Help
|
||||
@@ -201,9 +154,8 @@ namespace mRemoteNG.UI.Window
|
||||
ClientSize = new System.Drawing.Size(542, 323);
|
||||
Controls.Add(pnlSplitter);
|
||||
Icon = Resources.Help_Icon;
|
||||
Name = "Help";
|
||||
TabText = "Help";
|
||||
Text = "Help";
|
||||
TabText = @"Help";
|
||||
Text = @"Help";
|
||||
pnlSplitter.Panel1.ResumeLayout(false);
|
||||
pnlSplitter.Panel2.ResumeLayout(false);
|
||||
pnlSplitter.ResumeLayout(false);
|
||||
@@ -245,7 +197,7 @@ namespace mRemoteNG.UI.Window
|
||||
|
||||
private void tvIndex_AfterSelect(object sender, TreeViewEventArgs e)
|
||||
{
|
||||
if ((string)e.Node.Tag != "" && e.Node.Tag != null)
|
||||
if (!string.IsNullOrEmpty((string)e.Node.Tag))
|
||||
{
|
||||
wbHelp.Navigate(GeneralAppInfo.HomePath + "\\Help\\" + Convert.ToString(e.Node.Tag) +".htm");
|
||||
}
|
||||
@@ -263,7 +215,7 @@ namespace mRemoteNG.UI.Window
|
||||
imgListHelp.Images.Add("Help", Resources.Help);
|
||||
}
|
||||
|
||||
private void SetImages(TreeNode node)
|
||||
private static void SetImages(TreeNode node)
|
||||
{
|
||||
node.ImageIndex = 2;
|
||||
node.SelectedImageIndex = 2;
|
||||
|
||||
16
mRemoteV1/UI/Window/PortScanWindow.Designer.cs
generated
16
mRemoteV1/UI/Window/PortScanWindow.Designer.cs
generated
@@ -88,7 +88,7 @@ namespace mRemoteNG.UI.Window
|
||||
this.ipStart.Location = new System.Drawing.Point(5, 19);
|
||||
this.ipStart.Name = "ipStart";
|
||||
this.ipStart.Size = new System.Drawing.Size(130, 20);
|
||||
this.ipStart.TabIndex = 10;
|
||||
this.ipStart.TabIndex = 1;
|
||||
this.ipStart.ToolTipText = "";
|
||||
//
|
||||
// ipEnd
|
||||
@@ -96,7 +96,7 @@ namespace mRemoteNG.UI.Window
|
||||
this.ipEnd.Location = new System.Drawing.Point(155, 19);
|
||||
this.ipEnd.Name = "ipEnd";
|
||||
this.ipEnd.Size = new System.Drawing.Size(130, 20);
|
||||
this.ipEnd.TabIndex = 15;
|
||||
this.ipEnd.TabIndex = 2;
|
||||
this.ipEnd.ToolTipText = "";
|
||||
//
|
||||
// lblStartIP
|
||||
@@ -126,7 +126,7 @@ namespace mRemoteNG.UI.Window
|
||||
this.btnScan.Location = new System.Drawing.Point(769, 5);
|
||||
this.btnScan.Name = "btnScan";
|
||||
this.btnScan.Size = new System.Drawing.Size(110, 55);
|
||||
this.btnScan.TabIndex = 20;
|
||||
this.btnScan.TabIndex = 6;
|
||||
this.btnScan.Text = "&Scan";
|
||||
this.btnScan.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
|
||||
this.btnScan.UseVisualStyleBackColor = true;
|
||||
@@ -222,7 +222,7 @@ namespace mRemoteNG.UI.Window
|
||||
this.btnImport.Location = new System.Drawing.Point(800, 5);
|
||||
this.btnImport.Name = "btnImport";
|
||||
this.btnImport.Size = new System.Drawing.Size(80, 40);
|
||||
this.btnImport.TabIndex = 101;
|
||||
this.btnImport.TabIndex = 8;
|
||||
this.btnImport.Text = "&Import";
|
||||
this.btnImport.UseVisualStyleBackColor = true;
|
||||
this.btnImport.Click += new System.EventHandler(this.btnImport_Click);
|
||||
@@ -244,7 +244,7 @@ namespace mRemoteNG.UI.Window
|
||||
this.cbProtocol.Location = new System.Drawing.Point(5, 25);
|
||||
this.cbProtocol.Name = "cbProtocol";
|
||||
this.cbProtocol.Size = new System.Drawing.Size(122, 21);
|
||||
this.cbProtocol.TabIndex = 28;
|
||||
this.cbProtocol.TabIndex = 7;
|
||||
//
|
||||
// lblOnlyImport
|
||||
//
|
||||
@@ -360,7 +360,7 @@ namespace mRemoteNG.UI.Window
|
||||
0});
|
||||
this.numericSelectorTimeout.Name = "numericSelectorTimeout";
|
||||
this.numericSelectorTimeout.Size = new System.Drawing.Size(67, 22);
|
||||
this.numericSelectorTimeout.TabIndex = 17;
|
||||
this.numericSelectorTimeout.TabIndex = 5;
|
||||
//
|
||||
// lblTimeout
|
||||
//
|
||||
@@ -381,7 +381,7 @@ namespace mRemoteNG.UI.Window
|
||||
0});
|
||||
this.portEnd.Name = "portEnd";
|
||||
this.portEnd.Size = new System.Drawing.Size(67, 22);
|
||||
this.portEnd.TabIndex = 15;
|
||||
this.portEnd.TabIndex = 4;
|
||||
this.portEnd.Enter += new System.EventHandler(this.portEnd_Enter);
|
||||
//
|
||||
// portStart
|
||||
@@ -394,7 +394,7 @@ namespace mRemoteNG.UI.Window
|
||||
0});
|
||||
this.portStart.Name = "portStart";
|
||||
this.portStart.Size = new System.Drawing.Size(67, 22);
|
||||
this.portStart.TabIndex = 5;
|
||||
this.portStart.TabIndex = 3;
|
||||
this.portStart.Enter += new System.EventHandler(this.portStart_Enter);
|
||||
//
|
||||
// Label2
|
||||
|
||||
@@ -1,25 +1,26 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows.Forms;
|
||||
using System.Linq;
|
||||
using mRemoteNG.App;
|
||||
using mRemoteNG.Connection;
|
||||
using mRemoteNG.Connection.Protocol;
|
||||
using mRemoteNG.Container;
|
||||
using mRemoteNG.Messages;
|
||||
using mRemoteNG.Tools;
|
||||
using mRemoteNG.Tree.Root;
|
||||
using WeifenLuo.WinFormsUI.Docking;
|
||||
|
||||
namespace mRemoteNG.UI.Window
|
||||
{
|
||||
public partial class PortScanWindow
|
||||
public partial class PortScanWindow
|
||||
{
|
||||
private readonly Func<ConnectionInfo> _getSelectedConnectionFunc;
|
||||
private readonly ConnectionTreeWindow _connectionTreeWindow;
|
||||
private readonly Import _import;
|
||||
|
||||
#region Constructors
|
||||
public PortScanWindow(Func<ConnectionInfo> getSelectedConnectionFunc, Import import)
|
||||
public PortScanWindow(ConnectionTreeWindow connectionTreeWindow, Import import)
|
||||
{
|
||||
_getSelectedConnectionFunc = getSelectedConnectionFunc;
|
||||
_connectionTreeWindow = connectionTreeWindow.ThrowIfNull(nameof(connectionTreeWindow));
|
||||
_import = import.ThrowIfNull(nameof(import));
|
||||
InitializeComponent();
|
||||
|
||||
@@ -136,8 +137,6 @@ namespace mRemoteNG.UI.Window
|
||||
{
|
||||
ProtocolType protocol = (ProtocolType)Enum.Parse(typeof(ProtocolType), Convert.ToString(cbProtocol.SelectedItem), true);
|
||||
importSelectedHosts(protocol);
|
||||
DialogResult = DialogResult.OK;
|
||||
Close();
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -263,11 +262,28 @@ namespace mRemoteNG.UI.Window
|
||||
return;
|
||||
}
|
||||
|
||||
var selectedNode = _getSelectedConnectionFunc();
|
||||
var selectedTreeNodeAsContainer = selectedNode as ContainerInfo ?? selectedNode.Parent;
|
||||
_import.ImportFromPortScan(hosts, protocol, selectedTreeNodeAsContainer);
|
||||
var destinationContainer = GetDestinationContainerForImportedHosts();
|
||||
_import.ImportFromPortScan(hosts, protocol, destinationContainer);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines where the imported hosts will be placed
|
||||
/// in the connection tree.
|
||||
/// </summary>
|
||||
private ContainerInfo GetDestinationContainerForImportedHosts()
|
||||
{
|
||||
var selectedNode = _connectionTreeWindow.SelectedNode
|
||||
?? _connectionTreeWindow.ConnectionTree.ConnectionTreeModel.RootNodes.OfType<RootNodeInfo>().First();
|
||||
|
||||
// if a putty node is selected, place imported connections in the root connection node
|
||||
if (selectedNode is RootPuttySessionsNodeInfo || selectedNode is PuttySessionInfo)
|
||||
selectedNode = _connectionTreeWindow.ConnectionTree.ConnectionTreeModel.RootNodes.OfType<RootNodeInfo>().First();
|
||||
|
||||
// if the selected node is a connection, use its parent container
|
||||
var selectedTreeNodeAsContainer = selectedNode as ContainerInfo ?? selectedNode.Parent;
|
||||
return selectedTreeNodeAsContainer;
|
||||
}
|
||||
|
||||
private void importVNCToolStripMenuItem_Click(object sender, EventArgs e)
|
||||
{
|
||||
importSelectedHosts(ProtocolType.VNC);
|
||||
|
||||
@@ -692,6 +692,12 @@
|
||||
<setting name="MultiSshToolbarVisible" serializeAs="String">
|
||||
<value>False</value>
|
||||
</setting>
|
||||
<setting name="CreateEmptyPanelOnStartUp" serializeAs="String">
|
||||
<value>False</value>
|
||||
</setting>
|
||||
<setting name="StartUpPanelName" serializeAs="String">
|
||||
<value>General</value>
|
||||
</setting>
|
||||
</mRemoteNG.Settings>
|
||||
</userSettings>
|
||||
<applicationSettings>
|
||||
|
||||
Reference in New Issue
Block a user