mirror of
https://github.com/mRemoteNG/mRemoteNG.git
synced 2026-02-26 03:58:45 +08:00
Compare commits
256 Commits
refactor_r
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9e70dce626 | ||
|
|
52d1b9a270 | ||
|
|
068f5942e7 | ||
|
|
703cefaf19 | ||
|
|
3d32557177 | ||
|
|
ea1f72b8b7 | ||
|
|
993b6759cc | ||
|
|
c0b07307f5 | ||
|
|
15f23769d6 | ||
|
|
2d175fd575 | ||
|
|
bdeb4b4dcc | ||
|
|
bdfbb57504 | ||
|
|
38d1c756f3 | ||
|
|
6c89913bc6 | ||
|
|
efa72cb697 | ||
|
|
a31fec5fb9 | ||
|
|
ed81030976 | ||
|
|
54322ca949 | ||
|
|
738b159e95 | ||
|
|
e8f2e4f50c | ||
|
|
5cd201440e | ||
|
|
5c6c76b898 | ||
|
|
4847ce054b | ||
|
|
ec42fe7d7d | ||
|
|
07a20ed5ad | ||
|
|
08201b0f00 | ||
|
|
92416b4661 | ||
|
|
75e0b8f4c2 | ||
|
|
8d29ff2d61 | ||
|
|
eea79da1ae | ||
|
|
cb5447f86e | ||
|
|
8cb31ad524 | ||
|
|
6ca52a0db1 | ||
|
|
25e30672c8 | ||
|
|
abcab2aadf | ||
|
|
19bb8f7595 | ||
|
|
0427956e8b | ||
|
|
78bf40282a | ||
|
|
6c6a82f8e6 | ||
|
|
4b9cc7be08 | ||
|
|
dc2d6b8160 | ||
|
|
083456e33a | ||
|
|
80e43e8634 | ||
|
|
e99b8ed453 | ||
|
|
4aba36b756 | ||
|
|
2ebf654973 | ||
|
|
f560fb86d8 | ||
|
|
8ab221e5a8 | ||
|
|
21e51c8455 | ||
|
|
3234896caf | ||
|
|
b00dd1c5f5 | ||
|
|
992a3f9d1c | ||
|
|
d1a7a37909 | ||
|
|
1c12b52ada | ||
|
|
722fe40899 | ||
|
|
b2e7ebf43d | ||
|
|
3ed8e768aa | ||
|
|
d362691389 | ||
|
|
4b7c54d5b5 | ||
|
|
ec80a5aa70 | ||
|
|
0c95f178ca | ||
|
|
e0405b15df | ||
|
|
e029f30acf | ||
|
|
44ed836b7c | ||
|
|
00401201d1 | ||
|
|
20f46bea61 | ||
|
|
a5d22d287c | ||
|
|
793095900b | ||
|
|
f10e54e47b | ||
|
|
704e0c1dc1 | ||
|
|
0c79a9acde | ||
|
|
ebfc2715e7 | ||
|
|
b0dbc9dc18 | ||
|
|
507cdf75a5 | ||
|
|
8f8492b0be | ||
|
|
457e715188 | ||
|
|
1724521ebf | ||
|
|
b0fb3596aa | ||
|
|
fb228d72b1 | ||
|
|
916361a3be | ||
|
|
408c40f699 | ||
|
|
4173f6d775 | ||
|
|
e6f3c22064 | ||
|
|
a013518eac | ||
|
|
9c88cacb3d | ||
|
|
d49bf04b15 | ||
|
|
1dbd5dc5bc | ||
|
|
c103706a54 | ||
|
|
b0a027df52 | ||
|
|
868641378a | ||
|
|
11baae3107 | ||
|
|
ed8125042e | ||
|
|
25b2655d0f | ||
|
|
145a264154 | ||
|
|
3e33170ae0 | ||
|
|
d18bf68f0e | ||
|
|
368917e108 | ||
|
|
cdea4c3911 | ||
|
|
b4b9b55bbf | ||
|
|
6092c63df4 | ||
|
|
fda5132184 | ||
|
|
6a9fb25a18 | ||
|
|
18d7344690 | ||
|
|
ba50cf20a0 | ||
|
|
7bd6e126e2 | ||
|
|
f7521c81d5 | ||
|
|
f483a2dc2f | ||
|
|
9769d5af06 | ||
|
|
0a2dc3563e | ||
|
|
e9f0157b2b | ||
|
|
e8e566fcdd | ||
|
|
72b7d22cef | ||
|
|
f79da476fd | ||
|
|
ef31b7844c | ||
|
|
f1ed1bf115 | ||
|
|
23ea028965 | ||
|
|
42046a614f | ||
|
|
36055f56e6 | ||
|
|
b693cb30fc | ||
|
|
20377d4ff5 | ||
|
|
570d732b0e | ||
|
|
d9d2b1de70 | ||
|
|
0a7eaaf36f | ||
|
|
36dd3e496d | ||
|
|
83fd914d7b | ||
|
|
281c6b13fa | ||
|
|
00b7b1221c | ||
|
|
56cbf0ff3f | ||
|
|
f852a4d341 | ||
|
|
7c8c7d482a | ||
|
|
9e95ae2cb0 | ||
|
|
0d2d935f17 | ||
|
|
eeb320a825 | ||
|
|
9452d4dbe3 | ||
|
|
03d2387cdd | ||
|
|
61b325ccb9 | ||
|
|
e57de9a4de | ||
|
|
96946f3a1e | ||
|
|
8cd6fb7ae2 | ||
|
|
a5afa90790 | ||
|
|
f634eb8d37 | ||
|
|
694b61a67b | ||
|
|
88f0d00a15 | ||
|
|
e31088fd2e | ||
|
|
1d7bb63710 | ||
|
|
af1ed5349f | ||
|
|
9dcf71dc31 | ||
|
|
8bf9af0ed8 | ||
|
|
aecfad5871 | ||
|
|
3edd155898 | ||
|
|
2c419c0b2e | ||
|
|
2fb67e7042 | ||
|
|
29483b2625 | ||
|
|
7fc59e79f3 | ||
|
|
79b3e21148 | ||
|
|
ee91117010 | ||
|
|
0548037ff3 | ||
|
|
46002632bb | ||
|
|
9659ac1611 | ||
|
|
bbc497e68d | ||
|
|
d7ec7574ad | ||
|
|
2f476d9e61 | ||
|
|
c74f37f0de | ||
|
|
d27a62cbfc | ||
|
|
8029e491a3 | ||
|
|
fe56268421 | ||
|
|
2db6fabbe9 | ||
|
|
035e89801a | ||
|
|
3bdcf655fd | ||
|
|
284755f298 | ||
|
|
ad5eed96e7 | ||
|
|
431c830ea0 | ||
|
|
da047427a5 | ||
|
|
69da1dca5f | ||
|
|
cc61501f63 | ||
|
|
4ced2d3392 | ||
|
|
7c72bfdf6b | ||
|
|
b8878e1458 | ||
|
|
abd40cec1b | ||
|
|
cc18da4f28 | ||
|
|
1a39039162 | ||
|
|
cf9dd72ea5 | ||
|
|
b7cdf81665 | ||
|
|
8497a05fd1 | ||
|
|
7db4eec45c | ||
|
|
cd822b545a | ||
|
|
e872581d3c | ||
|
|
defe9e094c | ||
|
|
5662735cb8 | ||
|
|
8646dce21b | ||
|
|
99a3eabbaf | ||
|
|
c57bd386f2 | ||
|
|
f2a52b03df | ||
|
|
860e1ccfaa | ||
|
|
49967b38d4 | ||
|
|
36038fff6d | ||
|
|
c5958954b0 | ||
|
|
d0d63016ca | ||
|
|
35f2484adf | ||
|
|
c2cf496ded | ||
|
|
8a172f02a9 | ||
|
|
f27935ea61 | ||
|
|
043df0aec3 | ||
|
|
63a2e18760 | ||
|
|
c3ced7ed03 | ||
|
|
f597e14b3d | ||
|
|
aff4ba9115 | ||
|
|
554e0805e3 | ||
|
|
f4efa74a23 | ||
|
|
ddc19587fa | ||
|
|
5f1232727e | ||
|
|
9c373e8f0a | ||
|
|
83942d788f | ||
|
|
73d6fec6f3 | ||
|
|
a37b5deaa1 | ||
|
|
3b9de847e7 | ||
|
|
924f1f1e48 | ||
|
|
7bdebbe25b | ||
|
|
8f46c25dc9 | ||
|
|
8bb4a03639 | ||
|
|
7b5bc5e057 | ||
|
|
35582a5e6a | ||
|
|
20340fd31f | ||
|
|
d6d7664b48 | ||
|
|
ce97e63876 | ||
|
|
378b98ff89 | ||
|
|
ce31199e57 | ||
|
|
227f3b2924 | ||
|
|
5076f1354c | ||
|
|
e5a34388ae | ||
|
|
6a5f65c018 | ||
|
|
6d5f41b3d8 | ||
|
|
64f10ead63 | ||
|
|
575dae446f | ||
|
|
9b438576f2 | ||
|
|
cbd32f1a07 | ||
|
|
516182ec40 | ||
|
|
4ad3a68d80 | ||
|
|
2f9ba32c07 | ||
|
|
dfc45a2904 | ||
|
|
563fdffb67 | ||
|
|
f2e9c5e2c0 | ||
|
|
86a591364c | ||
|
|
2a82485f81 | ||
|
|
e13549d361 | ||
|
|
a85c1bd7d3 | ||
|
|
946679f490 | ||
|
|
b6f27eac18 | ||
|
|
2cc82145a3 | ||
|
|
2dae0f2d8e | ||
|
|
412f6edc36 | ||
|
|
764791b8e5 | ||
|
|
bd20d6ae7d | ||
|
|
8db0bf7bea | ||
|
|
cff6aa72fc | ||
|
|
63ddf06057 |
38
.github/ISSUE_TEMPLATE.md
vendored
38
.github/ISSUE_TEMPLATE.md
vendored
@@ -1,16 +1,30 @@
|
|||||||
<!--
|
<!--- Provide a general summary of the issue in the Title above -->
|
||||||
Only file GitHub issues for bugs and feature requests. All other topics will be closed.
|
|
||||||
|
|
||||||
Before opening an issue, please search for a duplicate or closed issue.
|
## Expected Behavior
|
||||||
Please provide as much detail as possible for us to fix your issue.
|
<!--- If you're describing a bug, tell us what should happen -->
|
||||||
-->
|
<!--- If you're suggesting a change/improvement, tell us how it should work -->
|
||||||
|
|
||||||
<!-- Bug -->
|
## Current Behavior
|
||||||
|Detail|Value|
|
<!--- If describing a bug, tell us what happens instead of the expected behavior -->
|
||||||
|--:|---|
|
<!--- If suggesting a change/improvement, explain the difference from current behavior -->
|
||||||
|Operating system | Windows 10 x64 |
|
|
||||||
|mRemoteNG version| 1.75.7008 |
|
|
||||||
|
|
||||||
|
## Possible Solution
|
||||||
|
<!--- Not obligatory, but suggest a fix/reason for the bug, -->
|
||||||
|
<!--- or ideas how to implement the addition or change -->
|
||||||
|
|
||||||
<!-- Feature Request -->
|
## Steps to Reproduce (for bugs)
|
||||||
<!-- If you file a feature request, please delete the bug section -->
|
<!--- Provide an unambiguous set of steps to reproduce -->
|
||||||
|
<!--- this bug. Include code to reproduce, if relevant -->
|
||||||
|
1.
|
||||||
|
2.
|
||||||
|
3.
|
||||||
|
4.
|
||||||
|
|
||||||
|
## Context
|
||||||
|
<!--- How has this issue affected you? What are you trying to accomplish? -->
|
||||||
|
<!--- Providing context helps us come up with a solution that is most useful in the real world -->
|
||||||
|
|
||||||
|
## Your Environment
|
||||||
|
<!--- Include as many relevant details about the environment you experienced the bug in -->
|
||||||
|
* Version used:
|
||||||
|
* Operating System and version (e.g. Windows 10 1709 x64):
|
||||||
|
|||||||
33
.github/PULL_REQUEST_TEMPLATE.md
vendored
33
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,4 +1,29 @@
|
|||||||
<!--
|
<!--- Provide a general summary of your changes in the Title above -->
|
||||||
Please provide as much detail as possible with what your pull request does.
|
|
||||||
Include a reference to a filed issue if it exists.
|
## Description
|
||||||
-->
|
<!--- Describe your changes in detail -->
|
||||||
|
|
||||||
|
## Motivation and Context
|
||||||
|
<!--- Why is this change required? What problem does it solve? -->
|
||||||
|
<!--- If it fixes an open issue, please link to the issue here. -->
|
||||||
|
|
||||||
|
## How Has This Been Tested?
|
||||||
|
<!--- Please describe in detail how you tested your changes. -->
|
||||||
|
<!--- Include details of your testing environment, and the tests you ran to -->
|
||||||
|
<!--- see how your change affects other areas of the code, etc. -->
|
||||||
|
|
||||||
|
## Screenshots (if appropriate):
|
||||||
|
|
||||||
|
## Types of changes
|
||||||
|
<!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: -->
|
||||||
|
- [ ] Bug fix (non-breaking change which fixes an issue)
|
||||||
|
- [ ] New feature (non-breaking change which adds functionality)
|
||||||
|
- [ ] Breaking change (fix or feature that would cause existing functionality to change)
|
||||||
|
|
||||||
|
## Checklist:
|
||||||
|
<!--- Go over all the following points, and put an `x` in all the boxes that apply. -->
|
||||||
|
<!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->
|
||||||
|
- [ ] My code follows the code style of this project.
|
||||||
|
- [ ] My change requires a change to the documentation.
|
||||||
|
- [ ] I have updated the documentation accordingly.
|
||||||
|
- [ ] I have read the **CONTRIBUTING** document.
|
||||||
|
|||||||
192
CHANGELOG.TXT
192
CHANGELOG.TXT
@@ -1,12 +1,200 @@
|
|||||||
1.76.0 Alpha 3 (2018-xx-xx):
|
1.76.20 (2019-04-12):
|
||||||
|
|
||||||
|
Fixes:
|
||||||
|
------
|
||||||
|
#1401: Connections corrupted when importing RDC Manager files that are missing certain fields
|
||||||
|
|
||||||
|
|
||||||
|
1.76.19 (2019-04-04):
|
||||||
|
|
||||||
|
Fixes:
|
||||||
|
------
|
||||||
|
#1374: Vertical Scroll Bar missing in PuTTYNG after 0.70.0.1 & 0.71 updates
|
||||||
|
|
||||||
|
|
||||||
|
1.76.18 (2019-03-20):
|
||||||
|
|
||||||
|
Fixes:
|
||||||
|
------
|
||||||
|
#1365: PuTTY window not centered after 0.71 update
|
||||||
|
|
||||||
|
|
||||||
|
1.76.17 (2019-03-20):
|
||||||
|
|
||||||
|
Fixes:
|
||||||
|
------
|
||||||
|
#1362: Updated PuTTYNG to 0.71
|
||||||
|
|
||||||
|
|
||||||
|
1.76.16 (2019-03-14):
|
||||||
|
|
||||||
|
Fixes:
|
||||||
|
------
|
||||||
|
#1347: Remote Desktop Gateway username field encrypted instead of password
|
||||||
|
|
||||||
|
|
||||||
|
1.76.15 (2019-03-09):
|
||||||
|
|
||||||
|
Fixes:
|
||||||
|
------
|
||||||
|
#1303: Exception on first connection with new SQL server database
|
||||||
|
#1304: Resolved several issues with importing multiple RDP Manager v2.7 files
|
||||||
|
|
||||||
|
Features/Enhancements:
|
||||||
|
----------------------
|
||||||
|
Importing multiple files now only causes 1 save event, rather than 1 per file imported.
|
||||||
|
|
||||||
|
|
||||||
|
1.76.14 (2019-02-08):
|
||||||
|
|
||||||
|
Features/Enhancements:
|
||||||
|
----------------------
|
||||||
|
#222: Allow FIPS to be enabled
|
||||||
|
|
||||||
|
|
||||||
|
1.76.13 (2018-12-22):
|
||||||
|
|
||||||
|
Changes:
|
||||||
|
--------
|
||||||
|
#222: Pre-Release Test build for running on systems with FIPS Enabled
|
||||||
|
|
||||||
|
|
||||||
|
1.76.12 (2018-11-08):
|
||||||
|
|
||||||
|
Features/Enhancements:
|
||||||
|
----------------------
|
||||||
|
#1180: Allow saving certain connection properties locally when using database
|
||||||
|
|
||||||
|
Fixes:
|
||||||
|
------
|
||||||
|
#1181: Connections sometimes dont immediately load when switching to sql feature
|
||||||
|
#1173: Fixed memory leak when loading connections multiple times
|
||||||
|
#1168: Autohide Connection and Config tab won't open when ssh connection active
|
||||||
|
#1134: Fixed issue where opening a connection opens same connection on other clients when using database feature
|
||||||
|
#449: Encrypt passwords saved to database
|
||||||
|
|
||||||
|
|
||||||
|
1.76.11 (2018-10-18):
|
||||||
|
|
||||||
|
Fixes:
|
||||||
|
------
|
||||||
|
#1139: Feature "Reconnect to previously opened sessions" not working
|
||||||
|
#1136: Putty window not maximized
|
||||||
|
|
||||||
|
|
||||||
|
1.76.10 (2018-10-07):
|
||||||
|
|
||||||
|
Fixes:
|
||||||
|
------
|
||||||
|
#1124: Enabling themes causes an exception
|
||||||
|
|
||||||
|
|
||||||
|
1.76.9 (2018-10-07):
|
||||||
|
|
||||||
|
Fixes:
|
||||||
|
------
|
||||||
|
#1117: Duplicate panel created when "Reconnect on Startup" and "Create Empty Panel" settings enabled
|
||||||
|
#1115: Exception when changing from xml data storage to SQL
|
||||||
|
#1110: Pressing Delete button during connection rename attempts to delete the connection instead of the text
|
||||||
|
#1106: Inheritance does not work when parent has C# default type set
|
||||||
|
#1092: Invalid Cast Exceptions loading default connectioninfo
|
||||||
|
#1091: Minor themeing issues
|
||||||
|
#853: Added some additional safety checks and logging to help address RDP crashes
|
||||||
|
|
||||||
|
|
||||||
|
1.76.8 (2018-08-25):
|
||||||
|
|
||||||
|
Fixes:
|
||||||
|
------
|
||||||
|
#1088: Delete and Launch buttons are not disabled when last external tool deleted
|
||||||
|
#1087: 'Save connections after every edit' setting not honored
|
||||||
|
#1082: Connections not given GUID if Id is empty in connection xml
|
||||||
|
|
||||||
|
|
||||||
|
1.76.7 (2018-08-22):
|
||||||
|
|
||||||
|
Fixes:
|
||||||
|
------
|
||||||
|
#1076: Wrong object selected when duplicating connection then switching between properties and inheritance in config window
|
||||||
|
#1068: Fixed some toolbar positioning bugs
|
||||||
|
|
||||||
|
|
||||||
|
1.76.6 (2018-08-03):
|
||||||
|
|
||||||
|
Fixes:
|
||||||
|
------
|
||||||
|
#1062: Entering correct password when starting app does not load connections file
|
||||||
|
|
||||||
|
1.76.5 (2018-08-02):
|
||||||
|
|
||||||
|
Fixes:
|
||||||
|
------
|
||||||
|
#1057: Hitting F2 with no connection node selected caused unhandled exception
|
||||||
|
#1052: 'Switch to notification panel' feature does not always switch
|
||||||
|
#1051: Tooltips always displayed regardless of 'Show description tooltips in connection tree' setting
|
||||||
|
#1050: Config window retains access to previously selected node after loading new connections file
|
||||||
|
#1045: Config window shows several incorrect properties for HTTPS connections
|
||||||
|
#1040: Canceling "select panel" form does not cancel
|
||||||
|
#1039: Set default theme when themes disabled
|
||||||
|
#1038: Unable to add connection with active filter
|
||||||
|
#1036: Exception when themes are active and options page closed on Connections then reopened
|
||||||
|
#1034: Connection context menu not being translated
|
||||||
|
#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
|
||||||
|
#971: Portable Settings now apply to any machine they are used on
|
||||||
|
#961: Connections file overwritten if correct decryption password not provided
|
||||||
|
#893: Removed unneeded files from build/package
|
||||||
|
#868: if statement returned the same value
|
||||||
|
#762: Increased button size to fit locaized text
|
||||||
|
|
||||||
|
|
||||||
|
1.76.4 Alpha 6 (2018-06-03):
|
||||||
|
|
||||||
|
Features/Enhancements:
|
||||||
|
----------------------
|
||||||
|
#948: Fixed issue where many menu item translations were not being used
|
||||||
|
#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:
|
||||||
|
------
|
||||||
|
#938: Minor layout improvements on the Port Scan screen
|
||||||
|
#916: Default properties were not being saved
|
||||||
|
|
||||||
|
|
||||||
|
1.76.3 Alpha 5 (2018-03-14):
|
||||||
|
|
||||||
|
Fixes:
|
||||||
|
------
|
||||||
|
#911: Csv exports sometimes do not include all fields
|
||||||
|
#807: Inheritance is sometimes turned on for nodes under root Connections node
|
||||||
|
|
||||||
|
|
||||||
|
1.76.2 Alpha 4 (2018-03-03):
|
||||||
|
|
||||||
|
Fixes:
|
||||||
|
------
|
||||||
|
#899: DoNotPlay is Case Sensitive in XML Serialization
|
||||||
|
|
||||||
|
|
||||||
|
1.76.1 Alpha 3 (2018-02-24):
|
||||||
|
|
||||||
Features/Enhancements:
|
Features/Enhancements:
|
||||||
----------------------
|
----------------------
|
||||||
#625: Added ability to import mRemoteNG formatted CSV files
|
#625: Added ability to import mRemoteNG formatted CSV files
|
||||||
|
#648: The port scan ping timeout is now configurable
|
||||||
|
|
||||||
Fixes:
|
Fixes:
|
||||||
------
|
------
|
||||||
|
Fixed a few Xml serialization bugs that would occur if boolean values weren't capitalized
|
||||||
|
|
||||||
|
|
||||||
1.76.0 Alpha 2 (2018-02-01):
|
1.76.0 Alpha 2 (2018-02-01):
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ github.com/DamianBis
|
|||||||
github.com/pfjason
|
github.com/pfjason
|
||||||
github.com/sirLoaf
|
github.com/sirLoaf
|
||||||
github.com/Fyers
|
github.com/Fyers
|
||||||
|
Vladimir Semenov (github.com/sli-pro)
|
||||||
|
Stephan (github.com/st-schuler)
|
||||||
|
|
||||||
|
|
||||||
Past Contributors
|
Past Contributors
|
||||||
@@ -59,6 +61,8 @@ Lukas Plachy (github.com/rheingold)
|
|||||||
Gyuha Shin
|
Gyuha Shin
|
||||||
Stefan (github.com/polluks)
|
Stefan (github.com/polluks)
|
||||||
github.com/emazv72
|
github.com/emazv72
|
||||||
|
Vladimir Semenov (github.com/sli-pro)
|
||||||
|
Marco Sousa (github.com/marcomsousa)
|
||||||
|
|
||||||
|
|
||||||
Included Source Code
|
Included Source Code
|
||||||
|
|||||||
8
Jenkinsfile
vendored
8
Jenkinsfile
vendored
@@ -1,8 +1,8 @@
|
|||||||
|
#!groovy
|
||||||
node('windows') {
|
node('windows') {
|
||||||
def jobDir = pwd()
|
def jobDir = pwd()
|
||||||
def solutionFilePath = "\"${jobDir}\\mRemoteV1.sln\""
|
def solutionFilePath = "\"${jobDir}\\mRemoteV1.sln\""
|
||||||
def vsToolsDir = "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\Common7\\Tools"
|
def msBuild = "C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Community\\MSBuild\\15.0\\Bin\\msbuild.exe"
|
||||||
def vsExtensionsDir = "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\Common7\\IDE\\CommonExtensions\\Microsoft\\TestWindow"
|
|
||||||
def nunitConsolePath = "${jobDir}\\packages\\NUnit.ConsoleRunner.3.7.0\\tools\\nunit3-console.exe"
|
def nunitConsolePath = "${jobDir}\\packages\\NUnit.ConsoleRunner.3.7.0\\tools\\nunit3-console.exe"
|
||||||
def openCoverPath = "${jobDir}\\packages\\OpenCover.4.6.519\\tools\\OpenCover.Console.exe"
|
def openCoverPath = "${jobDir}\\packages\\OpenCover.4.6.519\\tools\\OpenCover.Console.exe"
|
||||||
def reportGeneratorPath = "${jobDir}\\packages\\ReportGenerator.3.0.2\\tools\\ReportGenerator.exe"
|
def reportGeneratorPath = "${jobDir}\\packages\\ReportGenerator.3.0.2\\tools\\ReportGenerator.exe"
|
||||||
@@ -24,11 +24,11 @@ node('windows') {
|
|||||||
}
|
}
|
||||||
|
|
||||||
stage ('Build mRemoteNG (Normal)') {
|
stage ('Build mRemoteNG (Normal)') {
|
||||||
bat "\"${vsToolsDir}\\VsDevCmd.bat\" && msbuild.exe /nologo /p:Platform=x86 \"${jobDir}\\mRemoteV1.sln\""
|
bat "\"${msBuild}\" /nologo /p:Platform=x86 \"${jobDir}\\mRemoteV1.sln\""
|
||||||
}
|
}
|
||||||
|
|
||||||
stage ('Build mRemoteNG (Portable)') {
|
stage ('Build mRemoteNG (Portable)') {
|
||||||
bat "\"${vsToolsDir}\\VsDevCmd.bat\" && msbuild.exe /nologo /p:Configuration=\"Debug Portable\";Platform=x86 \"${jobDir}\\mRemoteV1.sln\""
|
bat "\"${msBuild}\" /nologo /p:Configuration=\"Debug Portable\";Platform=x86 \"${jobDir}\\mRemoteV1.sln\""
|
||||||
}
|
}
|
||||||
|
|
||||||
stage ('Run Unit Tests (Normal, w/coverage)') {
|
stage ('Run Unit Tests (Normal, w/coverage)') {
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
node('windows') {
|
node('windows') {
|
||||||
def jobDir = pwd()
|
def jobDir = pwd()
|
||||||
def solutionFilePath = "\"${jobDir}\\mRemoteV1.sln\""
|
def solutionFilePath = "\"${jobDir}\\mRemoteV1.sln\""
|
||||||
def vsToolsDir = "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\Common7\\Tools"
|
def msBuild = "C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Community\\MSBuild\\15.0\\Bin\\msbuild.exe"
|
||||||
def vsExtensionsDir = "C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\Common7\\IDE\\CommonExtensions\\Microsoft\\TestWindow"
|
def nunitConsolePath = "${jobDir}\\packages\\NUnit.ConsoleRunner.3.7.0\\tools\\nunit3-console.exe"
|
||||||
def nunitTestAdapterPath = "C:\\Users\\Administrator\\AppData\\Local\\Microsoft\\VisualStudio\\14.0\\Extensions"
|
def openCoverPath = "${jobDir}\\packages\\OpenCover.4.6.519\\tools\\OpenCover.Console.exe"
|
||||||
|
def testResultFilePrefix = "TestResult"
|
||||||
|
def testResultFileNormal = "${testResultFilePrefix}_UnitTests_normal.xml"
|
||||||
|
def testResultFilePortable = "${testResultFilePrefix}_UnitTests_portable.xml"
|
||||||
|
def coverageReport = "code_coverage_report.xml"
|
||||||
|
|
||||||
|
|
||||||
stage ('Clean output dir') {
|
stage ('Clean output dir') {
|
||||||
@@ -32,23 +36,23 @@ node('windows') {
|
|||||||
withCredentials([file(credentialsId: '9b674d57-6792-48e3-984a-4d1bab2abb64', variable: 'CODE_SIGNING_CERT')]) {
|
withCredentials([file(credentialsId: '9b674d57-6792-48e3-984a-4d1bab2abb64', variable: 'CODE_SIGNING_CERT')]) {
|
||||||
withCredentials([usernamePassword(credentialsId: '05b7449b-05c0-490f-8661-236242526e62', passwordVariable: 'MRNG_CERT_PASSWORD', usernameVariable: 'NO_USERNAME')]) {
|
withCredentials([usernamePassword(credentialsId: '05b7449b-05c0-490f-8661-236242526e62', passwordVariable: 'MRNG_CERT_PASSWORD', usernameVariable: 'NO_USERNAME')]) {
|
||||||
stage ('Build mRemoteNG (Normal - MSI)') {
|
stage ('Build mRemoteNG (Normal - MSI)') {
|
||||||
bat "\"${vsToolsDir}\\VsDevCmd.bat\" && msbuild.exe /nologo /t:Clean,Build /p:Configuration=\"Release Installer\" /p:Platform=x86 /p:CertPath=\"${env.CODE_SIGNING_CERT}\" /p:CertPassword=${env.MRNG_CERT_PASSWORD} \"${jobDir}\\mRemoteV1.sln\""
|
bat "\"${msBuild}\" /nologo /t:Clean,Build /p:Configuration=\"Release Installer\" /p:Platform=x86 /p:CertPath=\"${env.CODE_SIGNING_CERT}\" /p:CertPassword=${env.MRNG_CERT_PASSWORD} \"${jobDir}\\mRemoteV1.sln\""
|
||||||
archiveArtifacts artifacts: "Release\\*.msi", caseSensitive: false, onlyIfSuccessful: true, fingerprint: true
|
archiveArtifacts artifacts: "Release\\*.msi", caseSensitive: false, onlyIfSuccessful: true, fingerprint: true
|
||||||
}
|
}
|
||||||
|
|
||||||
stage ('Build mRemoteNG (Portable)') {
|
stage ('Build mRemoteNG (Portable)') {
|
||||||
bat "\"${vsToolsDir}\\VsDevCmd.bat\" && msbuild.exe /nologo /t:Clean,Build /p:Configuration=\"Release Portable\" /p:Platform=x86 /p:CertPath=\"${env.CODE_SIGNING_CERT}\" /p:CertPassword=${env.MRNG_CERT_PASSWORD} \"${jobDir}\\mRemoteV1.sln\""
|
bat "\"${msBuild}\" /nologo /t:Clean,Build /p:Configuration=\"Release Portable\" /p:Platform=x86 /p:CertPath=\"${env.CODE_SIGNING_CERT}\" /p:CertPassword=${env.MRNG_CERT_PASSWORD} \"${jobDir}\\mRemoteV1.sln\""
|
||||||
archiveArtifacts artifacts: "Release\\*.zip", caseSensitive: false, onlyIfSuccessful: true, fingerprint: true
|
archiveArtifacts artifacts: "Release\\*.zip", caseSensitive: false, onlyIfSuccessful: true, fingerprint: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stage ('Run Unit Tests (Normal - MSI)') {
|
stage ('Run Unit Tests (Normal - MSI)') {
|
||||||
bat "\"${vsToolsDir}\\VsDevCmd.bat\" && VSTest.Console.exe /logger:trx /TestAdapterPath:${nunitTestAdapterPath} \"${jobDir}\\mRemoteNGTests\\bin\\Release\\mRemoteNGTests.dll\""
|
bat "\"${nunitConsolePath}\" \"${jobDir}\\mRemoteNGTests\\bin\\release\\mRemoteNGTests.dll\" --result=${testResultFileNormal} --x86"
|
||||||
}
|
}
|
||||||
|
|
||||||
stage ('Run Unit Tests (Portable)') {
|
stage ('Run Unit Tests (Portable)') {
|
||||||
bat "\"${vsToolsDir}\\VsDevCmd.bat\" && VSTest.Console.exe /logger:trx /TestAdapterPath:${nunitTestAdapterPath} \"${jobDir}\\mRemoteNGTests\\bin\\Release Portable\\mRemoteNGTests.dll\""
|
bat "\"${nunitConsolePath}\" \"${jobDir}\\mRemoteNGTests\\bin\\release portable\\mRemoteNGTests.dll\" --result=${testResultFilePortable} --x86"
|
||||||
}
|
}
|
||||||
|
|
||||||
stage ('Generate UpdateCheck Files') {
|
stage ('Generate UpdateCheck Files') {
|
||||||
@@ -58,11 +62,10 @@ node('windows') {
|
|||||||
|
|
||||||
stage ('Publish to GitHub') {
|
stage ('Publish to GitHub') {
|
||||||
withCredentials([string(credentialsId: '5443a369-dbe8-42d3-b4e8-04d0b4e9039a', variable: 'GH_AUTH_TOKEN')]) {
|
withCredentials([string(credentialsId: '5443a369-dbe8-42d3-b4e8-04d0b4e9039a', variable: 'GH_AUTH_TOKEN')]) {
|
||||||
def zipPath = "${jobDir}\\Release\\*.zip"
|
def releaseFolder = "${jobDir}\\Release"
|
||||||
def msiPath = "${jobDir}\\Release\\*.msi"
|
|
||||||
// because batch files suck at handling newline characters, we have to convert to base64 in groovy and back to text in powershell
|
// because batch files suck at handling newline characters, we have to convert to base64 in groovy and back to text in powershell
|
||||||
def base64Description = env.ReleaseDescription.bytes.encodeBase64().toString()
|
def base64Description = env.ReleaseDescription.bytes.encodeBase64().toString()
|
||||||
bat "powershell -ExecutionPolicy Bypass -File \"${jobDir}\\Tools\\publish_to_github.ps1\" -Owner \"mRemoteNG\" -Repository \"mRemoteNG\" -ReleaseTitle \"${env.ReleaseTitle}\" -TagName \"${env.TagName}\" -TargetCommitish \"${env.TargetBranch}\" -Description \"${base64Description}\" -IsDraft ${env.IsDraft} -IsPrerelease ${env.IsPreRelease} -ZipFilePath \"${zipPath}\" -MsiFilePath \"${msiPath}\" -AuthToken \"${env.GH_AUTH_TOKEN}\" -DescriptionIsBase64Encoded"
|
bat "powershell -ExecutionPolicy Bypass -File \"${jobDir}\\Tools\\publish_to_github.ps1\" -Owner \"mRemoteNG\" -Repository \"mRemoteNG\" -ReleaseTitle \"${env.ReleaseTitle}\" -TagName \"${env.TagName}\" -TargetCommitish \"${env.TargetBranch}\" -Description \"${base64Description}\" -IsDraft ${env.IsDraft} -IsPrerelease ${env.IsPreRelease} -ReleaseFolderPath \"${releaseFolder}\" -AuthToken \"${env.GH_AUTH_TOKEN}\" -DescriptionIsBase64Encoded"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,9 +10,9 @@
|
|||||||
|
|
||||||
| Update Channel | Build Status | Downloads |
|
| Update Channel | Build Status | Downloads |
|
||||||
| ---------------|--------------|-----------|
|
| ---------------|--------------|-----------|
|
||||||
| Stable | [](https://ci.appveyor.com/project/mremoteng/mremoteng/branch/master) | [](https://github.com/mRemoteNG/mRemoteNG/releases/tag/v1.75.7011) |
|
| Stable | [](https://ci.appveyor.com/project/mremoteng/mremoteng/branch/master) | [](https://github.com/mRemoteNG/mRemoteNG/releases/tag/v1.75.7012) |
|
||||||
| Beta | | [](https://github.com/mRemoteNG/mRemoteNG/releases/tag/v1.75.7011) |
|
| Beta | | [](https://github.com/mRemoteNG/mRemoteNG/releases/tag/v1.75.7012) |
|
||||||
| Development | [](https://ci.appveyor.com/project/mremoteng/mremoteng/branch/develop) | [](https://github.com/mRemoteNG/mRemoteNG/releases/tag/v1.76Alpha2) |
|
| Development | [](https://ci.appveyor.com/project/mremoteng/mremoteng/branch/develop) | [](https://github.com/mRemoteNG/mRemoteNG/releases/tag/v1.76Alpha5) |
|
||||||
|
|
||||||
mRemoteNG is the next generation of mRemote, a full-featured, multi-tab remote connections manager.
|
mRemoteNG is the next generation of mRemote, a full-featured, multi-tab remote connections manager.
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -3,7 +3,7 @@
|
|||||||
License for use and distribution
|
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.
|
7-Zip Extra files are under the GNU LGPL license.
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,25 @@
|
|||||||
7-Zip Extra history
|
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
|
9.35 beta 2014-12-07
|
||||||
------------------------------
|
------------------------------
|
||||||
- SFX modules were moved to LZMA SDK package.
|
- 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 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.
|
7-Zip is free software. Read License.txt for more information about license.
|
||||||
|
|
||||||
|
|||||||
114
Tools/CreateBulkConnections_ConfCons2_6.ps1
Normal file
114
Tools/CreateBulkConnections_ConfCons2_6.ps1
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
#####################################
|
||||||
|
# Author: David Sparer
|
||||||
|
# Summary:
|
||||||
|
# This is intended to be a template for creating connections in bulk. This uses the serializers directly from the mRemoteNG binaries.
|
||||||
|
# You will still need to create the connection info objects, but the library will handle serialization. It is expected that you
|
||||||
|
# are familiar with PowerShell. If this is not the case, reach out to the mRemoteNG community for help.
|
||||||
|
# Usage:
|
||||||
|
# Replace or modify the examples that are shown toward the end of the script to create your own connection info objects.
|
||||||
|
#####################################
|
||||||
|
|
||||||
|
$EncryptionKey = (Get-Credential -Message "Enter the encryption key you would like to use. This must match the encryption key used by the rest of the confCons file." -UserName "DontNeedUsername").Password
|
||||||
|
$PathToMrngFolder = ""
|
||||||
|
|
||||||
|
if ($PathToMrngFolder -eq "") {
|
||||||
|
Write-Error -Message 'You must set the $PathToMrngFolder variable in this script to the folder which contains mRemoteNG.exe'
|
||||||
|
}
|
||||||
|
|
||||||
|
$assembly = [System.Reflection.Assembly]::LoadFile((Join-Path -Path $PathToMrngFolder -ChildPath "mRemoteNG.exe"))
|
||||||
|
$assembly = [System.Reflection.Assembly]::LoadFile((Join-Path -Path $PathToMrngFolder -ChildPath "BouncyCastle.Crypto.dll"))
|
||||||
|
|
||||||
|
function New-mRemoteNGXmlSerializer {
|
||||||
|
[CmdletBinding()]
|
||||||
|
param (
|
||||||
|
[SecureString]
|
||||||
|
$EncryptionKey
|
||||||
|
)
|
||||||
|
|
||||||
|
PROCESS {
|
||||||
|
$cryptoProvider = New-Object -TypeName mRemoteNG.Security.SymmetricEncryption.AeadCryptographyProvider
|
||||||
|
$saveFilter = New-Object -TypeName mRemoteNG.Security.SaveFilter -ArgumentList @($false)
|
||||||
|
$xmlSerializer = New-Object -TypeName mRemoteNG.Config.Serializers.XmlConnectionNodeSerializer -ArgumentList @($cryptoProvider, $encryptionKey, $saveFilter)
|
||||||
|
Write-Output $xmlSerializer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function New-mRemoteNGConnectionInfo {
|
||||||
|
[CmdletBinding()]
|
||||||
|
param ()
|
||||||
|
|
||||||
|
PROCESS {
|
||||||
|
$connectionInfo = New-Object -TypeName mRemoteNG.Connection.ConnectionInfo
|
||||||
|
Write-Output $connectionInfo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function New-mRemoteNGContainerInfo {
|
||||||
|
[CmdletBinding()]
|
||||||
|
param ()
|
||||||
|
|
||||||
|
PROCESS {
|
||||||
|
$connectionInfo = New-Object -TypeName mRemoteNG.Container.ContainerInfo
|
||||||
|
Write-Output $connectionInfo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Setup the services needed to do serialization
|
||||||
|
$xmlSerializer = New-mRemoteNGXmlSerializer -EncryptionKey $EncryptionKey
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#----------------------------------------------------------------
|
||||||
|
# Example 1: serialize many connections, no containers
|
||||||
|
# Here you can define the number of connection info objects to create
|
||||||
|
# You can also provide a list of desired hostnames and iterate over those
|
||||||
|
$xml = ""
|
||||||
|
foreach($i in 1..5)
|
||||||
|
{
|
||||||
|
$connectionInfo = New-mRemoteNGConnectionInfo
|
||||||
|
|
||||||
|
# Set connection info properties
|
||||||
|
$connectionInfo.Name = "server-$i"
|
||||||
|
$connectionInfo.Hostname = "some-win-server-$i"
|
||||||
|
$connectionInfo.Protocol = [mRemoteNG.Connection.Protocol.ProtocolType]::RDP
|
||||||
|
$connectionInfo.Inheritance.Username = $true
|
||||||
|
$connectionInfo.Inheritance.Domain = $true
|
||||||
|
$connectionInfo.Inheritance.Password = $true
|
||||||
|
|
||||||
|
$serializedConnection = $xmlSerializer.SerializeConnectionInfo($connectionInfo).ToString()
|
||||||
|
$xml += $serializedConnection + [System.Environment]::NewLine
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Output $xml
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#----------------------------------------------------------------
|
||||||
|
# Example 2: serialize a container which has connections
|
||||||
|
# You can also create containers and add connections to them, which will be nested correctly when serialized
|
||||||
|
$xml = ""
|
||||||
|
$container = New-mRemoteNGContainerInfo
|
||||||
|
$container.Name = "ProductionServers"
|
||||||
|
$serializedContainer = $xmlSerializer.SerializeConnectionInfo($container)
|
||||||
|
|
||||||
|
foreach($i in 1..3)
|
||||||
|
{
|
||||||
|
$connectionInfo = New-mRemoteNGConnectionInfo
|
||||||
|
|
||||||
|
# Set connection info properties
|
||||||
|
$connectionInfo.Name = "server-$i"
|
||||||
|
$connectionInfo.Hostname = "some-linux-server-$i"
|
||||||
|
$connectionInfo.Protocol = [mRemoteNG.Connection.Protocol.ProtocolType]::SSH2
|
||||||
|
$connectionInfo.Inheritance.Username = $true
|
||||||
|
$connectionInfo.Inheritance.Domain = $true
|
||||||
|
$connectionInfo.Inheritance.Password = $true
|
||||||
|
|
||||||
|
# serialize the connection
|
||||||
|
$serializedConnection = $xmlSerializer.SerializeConnectionInfo($connectionInfo)
|
||||||
|
# add the connection to the container
|
||||||
|
$serializedContainer.Add($serializedConnection)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Call ToString() on the top-level container to get the XML of it and all its children
|
||||||
|
Write-Output $serializedContainer.ToString()
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
$githubUrl = 'https://api.github.com'
|
$githubUrl = 'https://api.github.com'
|
||||||
|
# GitHub doesn't support the default powershell protocol (TLS 1.0)
|
||||||
|
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||||
|
|
||||||
function Publish-GitHubRelease {
|
function Publish-GitHubRelease {
|
||||||
param (
|
param (
|
||||||
@@ -170,13 +171,27 @@ function Upload-GitHubReleaseAsset {
|
|||||||
[string]
|
[string]
|
||||||
[Parameter(Mandatory=$true)]
|
[Parameter(Mandatory=$true)]
|
||||||
# The OAuth2 token to use for authentication.
|
# The OAuth2 token to use for authentication.
|
||||||
$AuthToken
|
$AuthToken,
|
||||||
|
|
||||||
|
[string]
|
||||||
|
# A short description label for the asset
|
||||||
|
$Label = ""
|
||||||
)
|
)
|
||||||
|
|
||||||
$UploadUri = $UploadUri -replace "(\{[\w,\?]*\})$"
|
$UploadUri = $UploadUri -replace "(\{[\w,\?]*\})$"
|
||||||
$file = Get-Item -Path $FilePath
|
$files = Get-Item -Path $FilePath
|
||||||
|
|
||||||
$req_uploadZipAsset = Invoke-WebRequest -Uri "$($UploadUri)?name=$($file.Name)" -Method Post -Headers @{"Authorization"="token $AuthToken"} -ContentType $ContentType -InFile $file.FullName -ErrorAction Stop
|
$labelParam = ""
|
||||||
|
if ($Label -ne "") {
|
||||||
|
$labelParam = "&label=$Label"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get-Item could produce an array of files if a wildcard is provided. (C:\*.txt)
|
||||||
|
# Upload each matching item individually
|
||||||
|
foreach ($file in $files) {
|
||||||
|
Write-Output "Uploading asset to GitHub release: '$($file.FullName)'"
|
||||||
|
$req_uploadZipAsset = Invoke-WebRequest -Uri "$($UploadUri)?name=$($file.Name)$labelParam" -Method Post -Headers @{"Authorization"="token $AuthToken"} -ContentType $ContentType -InFile $file.FullName -ErrorAction Stop
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -45,5 +45,6 @@ Format-Table -AutoSize -Wrap -InputObject @{
|
|||||||
& "$PSScriptRoot\verify_LargeAddressAware.ps1" -TargetDir $TargetDir -TargetFileName $TargetFileName
|
& "$PSScriptRoot\verify_LargeAddressAware.ps1" -TargetDir $TargetDir -TargetFileName $TargetFileName
|
||||||
& "$PSScriptRoot\tidy_files_for_release.ps1" -TargetDir $TargetDir -ConfigurationName $ConfigurationName
|
& "$PSScriptRoot\tidy_files_for_release.ps1" -TargetDir $TargetDir -ConfigurationName $ConfigurationName
|
||||||
& "$PSScriptRoot\sign_binaries.ps1" -TargetDir $TargetDir -CertificatePath $CertificatePath -CertificatePassword $CertificatePassword -ConfigurationName $ConfigurationName -Exclude $ExcludeFromSigning
|
& "$PSScriptRoot\sign_binaries.ps1" -TargetDir $TargetDir -CertificatePath $CertificatePath -CertificatePassword $CertificatePassword -ConfigurationName $ConfigurationName -Exclude $ExcludeFromSigning
|
||||||
& "$PSScriptRoot\verify_binary_signatures.ps1" -TargetDir $TargetDir -ConfigurationName $ConfigurationName
|
& "$PSScriptRoot\verify_binary_signatures.ps1" -TargetDir $TargetDir -ConfigurationName $ConfigurationName -CertificatePath $CertificatePath
|
||||||
|
& "$PSScriptRoot\zip_symbols.ps1" -SolutionDir $SolutionDir -TargetDir $TargetDir -ConfigurationName $ConfigurationName
|
||||||
& "$PSScriptRoot\zip_portable_files.ps1" -SolutionDir $SolutionDir -TargetDir $TargetDir -ConfigurationName $ConfigurationName
|
& "$PSScriptRoot\zip_portable_files.ps1" -SolutionDir $SolutionDir -TargetDir $TargetDir -ConfigurationName $ConfigurationName
|
||||||
@@ -43,13 +43,8 @@ param (
|
|||||||
|
|
||||||
[string]
|
[string]
|
||||||
[Parameter(Mandatory=$true)]
|
[Parameter(Mandatory=$true)]
|
||||||
# Path to the zip file to upload with the release
|
# Path to the folder which contains release assets to upload
|
||||||
$ZipFilePath,
|
$ReleaseFolderPath,
|
||||||
|
|
||||||
[string]
|
|
||||||
[Parameter(Mandatory=$true)]
|
|
||||||
#Path to the msi file to upload with the release
|
|
||||||
$MsiFilePath,
|
|
||||||
|
|
||||||
[string]
|
[string]
|
||||||
[Parameter(Mandatory=$true)]
|
[Parameter(Mandatory=$true)]
|
||||||
@@ -70,7 +65,17 @@ if ($DescriptionIsBase64Encoded) {
|
|||||||
. "$PSScriptRoot\github_functions.ps1"
|
. "$PSScriptRoot\github_functions.ps1"
|
||||||
|
|
||||||
|
|
||||||
|
$releaseFolderItems = Get-ChildItem -Path $ReleaseFolderPath
|
||||||
|
$mrngPortablePath = ($releaseFolderItems | ?{$_.Name -match "portable-[\d\.]+\.zip"}).FullName
|
||||||
|
$mrngNormalPath = ($releaseFolderItems | ?{$_.Name -match "installer-[\d\.]+\.msi"}).FullName
|
||||||
|
$mrngPortableSymbolsPath = ($releaseFolderItems | ?{$_.Name -match "mremoteng-portable-symbols-[\d\.]+\.zip"}).FullName
|
||||||
|
$mrngNormalSymbolsPath = ($releaseFolderItems | ?{$_.Name -match "mremoteng-symbols-[\d\.]+\.zip"}).FullName
|
||||||
|
|
||||||
|
|
||||||
$release = Publish-GitHubRelease -Owner $Owner -Repository $Repository -ReleaseTitle $ReleaseTitle -TagName $TagName -TargetCommitish $TargetCommitish -Description $Description -IsDraft ([bool]::Parse($IsDraft)) -IsPrerelease ([bool]::Parse($IsPrerelease)) -AuthToken $AuthToken
|
$release = Publish-GitHubRelease -Owner $Owner -Repository $Repository -ReleaseTitle $ReleaseTitle -TagName $TagName -TargetCommitish $TargetCommitish -Description $Description -IsDraft ([bool]::Parse($IsDraft)) -IsPrerelease ([bool]::Parse($IsPrerelease)) -AuthToken $AuthToken
|
||||||
$zipUpload = Upload-GitHubReleaseAsset -UploadUri $release.upload_url -FilePath $ZipFilePath -ContentType "application/zip" -AuthToken $AuthToken
|
$zipUpload = Upload-GitHubReleaseAsset -UploadUri $release.upload_url -FilePath $mrngPortablePath -ContentType "application/zip" -AuthToken $AuthToken -Label "Portable Edition (zip)"
|
||||||
$msiUpload = Upload-GitHubReleaseAsset -UploadUri $release.upload_url -FilePath $MsiFilePath -ContentType "application/octet-stream" -AuthToken $AuthToken
|
$msiUpload = Upload-GitHubReleaseAsset -UploadUri $release.upload_url -FilePath $mrngNormalPath -ContentType "application/octet-stream" -AuthToken $AuthToken -Label "Normal Edition (msi)"
|
||||||
|
|
||||||
|
$portableEditionSymbols = Upload-GitHubReleaseAsset -UploadUri $release.upload_url -FilePath $mrngPortableSymbolsPath -ContentType "application/zip" -AuthToken $AuthToken -Label "Portable Edition Debug Symbols"
|
||||||
|
$normalEditionSymbols = Upload-GitHubReleaseAsset -UploadUri $release.upload_url -FilePath $mrngNormalSymbolsPath -ContentType "application/zip" -AuthToken $AuthToken -Label "Normal Edition Debug Symbols"
|
||||||
Write-Output (Get-GitHubRelease -Owner $Owner -Repository $Repository -ReleaseId $release.id -AuthToken $AuthToken)
|
Write-Output (Get-GitHubRelease -Owner $Owner -Repository $Repository -ReleaseId $release.id -AuthToken $AuthToken)
|
||||||
@@ -9,7 +9,7 @@ Write-Host $SolutionDir
|
|||||||
Write-Host $renameTarget
|
Write-Host $renameTarget
|
||||||
|
|
||||||
$targetVersionedFile = "$SolutionDir\mRemoteV1\bin\Release\mRemoteNG.exe"
|
$targetVersionedFile = "$SolutionDir\mRemoteV1\bin\Release\mRemoteNG.exe"
|
||||||
$version = &"$SolutionDir\Tools\sigcheck.exe" /accepteula -q -n $targetVersionedFile
|
$version = &"$SolutionDir\Tools\exes\sigcheck.exe" /accepteula -q -n $targetVersionedFile
|
||||||
|
|
||||||
|
|
||||||
$renameTargetFileObject = Get-Item -Path $renameTarget -ErrorAction SilentlyContinue
|
$renameTargetFileObject = Get-Item -Path $renameTarget -ErrorAction SilentlyContinue
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ if ($ConfigurationName -match "Release") {
|
|||||||
Write-Output "Removing unnecessary files from Release versions"
|
Write-Output "Removing unnecessary files from Release versions"
|
||||||
Remove-Item -Path (Join-Path -Path $TargetDir -ChildPath "app.publish") -Recurse -Force
|
Remove-Item -Path (Join-Path -Path $TargetDir -ChildPath "app.publish") -Recurse -Force
|
||||||
$filesToDelete = Get-ChildItem -Path $TargetDir -Recurse -Include @(
|
$filesToDelete = Get-ChildItem -Path $TargetDir -Recurse -Include @(
|
||||||
"*.pdb",
|
|
||||||
"*.publish",
|
"*.publish",
|
||||||
"*.xml",
|
"*.xml",
|
||||||
"*.backup",
|
"*.backup",
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ param (
|
|||||||
$ConfigurationName,
|
$ConfigurationName,
|
||||||
|
|
||||||
[string]
|
[string]
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
# The code signing certificate to use when signing the files.
|
# The code signing certificate to use when signing the files.
|
||||||
$CertificatePath
|
$CertificatePath
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -13,13 +13,49 @@ param (
|
|||||||
)
|
)
|
||||||
|
|
||||||
Write-Output "===== Beginning $($PSCmdlet.MyInvocation.MyCommand) ====="
|
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
|
# Package Zip
|
||||||
if ($ConfigurationName -match "Release" -and $ConfigurationName -match "Portable") {
|
if ($ConfigurationName -eq "Release Portable") {
|
||||||
Write-Output "Packaging Release Portable ZIP"
|
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"
|
||||||
|
|
||||||
|
$tempFolderPath = Join-Path -Path $SolutionDir -ChildPath "mRemoteV1\bin\package"
|
||||||
|
Remove-Item -Recurse $tempFolderPath -ErrorAction SilentlyContinue | Out-Null
|
||||||
|
New-Item $tempFolderPath -ItemType "directory" | Out-Null
|
||||||
|
|
||||||
|
Copy-Item "$($SolutionDir)mRemoteV1\Resources\PuTTYNG.exe" -Destination $tempFolderPath
|
||||||
|
|
||||||
|
#Write-Output "$($SolutionDir)mRemoteV1\bin\$ConfigurationName"
|
||||||
|
#Write-Output "$($SolutionDir)mRemoteV1\bin\package"
|
||||||
|
Copy-Item "$($SolutionDir)mRemoteV1\bin\$ConfigurationName\*" -Destination $tempFolderPath -Recurse -Force
|
||||||
|
# Delete any PDB files that accidentally get copied into the temp folder
|
||||||
|
Get-ChildItem -Path $tempFolderPath -Filter "*.pdb" | Remove-Item
|
||||||
|
Copy-Item "$($SolutionDir)*.txt" -Destination $tempFolderPath
|
||||||
|
|
||||||
|
Write-Output "Creating portable ZIP file $($PortableZip)"
|
||||||
|
Remove-Item -Force $PortableZip -ErrorAction SilentlyContinue
|
||||||
|
& $SEVENZIP a -bt -bd -bb1 -mx=9 -tzip -y -r $PortableZip (Join-Path -Path $tempFolderPath -ChildPath "*.*")
|
||||||
|
#& $SEVENZIP a -bt -mx=9 -tzip -y $PortableZip "$($SolutionDir)*.TXT"
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Write-Output "We will not zip anything - this isnt a portable release build."
|
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."
|
||||||
|
}
|
||||||
56
Tools/zip_symbols.ps1
Normal file
56
Tools/zip_symbols.ps1
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
param (
|
||||||
|
[string]
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
$SolutionDir,
|
||||||
|
|
||||||
|
[string]
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
$TargetDir,
|
||||||
|
|
||||||
|
[string]
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
$ConfigurationName
|
||||||
|
)
|
||||||
|
|
||||||
|
Write-Output "===== Beginning $($PSCmdlet.MyInvocation.MyCommand) ====="
|
||||||
|
|
||||||
|
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 (trimmed): '$($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") {
|
||||||
|
Write-Output "Packaging debug symbols"
|
||||||
|
|
||||||
|
$version = & $SIGCHECK /accepteula -q -n "$($SolutionDir)mRemoteV1\bin\$($ConfigurationName)\mRemoteNG.exe"
|
||||||
|
|
||||||
|
Write-Output "Version is $($version)"
|
||||||
|
|
||||||
|
if ($ConfigurationName -match "Portable") {
|
||||||
|
$zipFilePrefix = "mRemoteNG-Portable-symbols"
|
||||||
|
} else {
|
||||||
|
$zipFilePrefix = "mRemoteNG-symbols"
|
||||||
|
}
|
||||||
|
|
||||||
|
$outputZipPath="$($SolutionDir)Release\$zipFilePrefix-$($version).zip"
|
||||||
|
|
||||||
|
Write-Output "Creating debug symbols ZIP file $($outputZipPath)"
|
||||||
|
Remove-Item -Force $outputZipPath -ErrorAction SilentlyContinue
|
||||||
|
& $SEVENZIP a -bt -bd -bb1 -mx=9 -tzip -y -r $outputZipPath (Join-Path -Path $TargetDir -ChildPath "*.pdb")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Output "We will not package debug symbols - this isnt a release build."
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Output ""
|
||||||
10
appveyor.yml
10
appveyor.yml
@@ -1,10 +1,11 @@
|
|||||||
version: 1.0.{build}
|
version: 1.76.{build}
|
||||||
pull_requests:
|
pull_requests:
|
||||||
do_not_increment_build_number: true
|
do_not_increment_build_number: true
|
||||||
image: Visual Studio 2017
|
image: Visual Studio 2017
|
||||||
configuration:
|
configuration:
|
||||||
- Release
|
- Release
|
||||||
- Release Portable
|
- Release Portable
|
||||||
|
- Release Installer
|
||||||
platform: x86
|
platform: x86
|
||||||
clone_depth: 1
|
clone_depth: 1
|
||||||
install:
|
install:
|
||||||
@@ -14,7 +15,14 @@ before_build:
|
|||||||
build:
|
build:
|
||||||
project: mRemoteV1.sln
|
project: mRemoteV1.sln
|
||||||
verbosity: normal
|
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:
|
test:
|
||||||
assemblies:
|
assemblies:
|
||||||
only:
|
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
|
||||||
47
mRemoteNGTests/App/ImportTests.cs
Normal file
47
mRemoteNGTests/App/ImportTests.cs
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
using System.IO;
|
||||||
|
using mRemoteNG.App;
|
||||||
|
using mRemoteNG.Config.Putty;
|
||||||
|
using mRemoteNG.Connection;
|
||||||
|
using mRemoteNG.Container;
|
||||||
|
using mRemoteNGTests.Properties;
|
||||||
|
using mRemoteNGTests.TestHelpers;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace mRemoteNGTests.App
|
||||||
|
{
|
||||||
|
public class ImportTests
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void ErrorHandlerCalledWhenUnsupportedFileExtensionFound()
|
||||||
|
{
|
||||||
|
using (FileTestHelpers.DisposableTempFile(out var file, ".blah"))
|
||||||
|
{
|
||||||
|
var conService = new ConnectionsService(PuttySessionsManager.Instance);
|
||||||
|
var container = new ContainerInfo();
|
||||||
|
var exceptionOccurred = false;
|
||||||
|
|
||||||
|
Import.HeadlessFileImport(new []{file}, container, conService, s => exceptionOccurred = true);
|
||||||
|
|
||||||
|
Assert.That(exceptionOccurred);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void AnErrorInOneFileDoNotPreventOtherFilesFromProcessing()
|
||||||
|
{
|
||||||
|
using (FileTestHelpers.DisposableTempFile(out var badFile, ".blah"))
|
||||||
|
using (FileTestHelpers.DisposableTempFile(out var rdpFile, ".rdp"))
|
||||||
|
{
|
||||||
|
File.AppendAllText(rdpFile, Resources.test_remotedesktopconnection_rdp);
|
||||||
|
var conService = new ConnectionsService(PuttySessionsManager.Instance);
|
||||||
|
var container = new ContainerInfo();
|
||||||
|
var exceptionCount = 0;
|
||||||
|
|
||||||
|
Import.HeadlessFileImport(new[] { badFile, rdpFile }, container, conService, s => exceptionCount++);
|
||||||
|
|
||||||
|
Assert.That(exceptionCount, Is.EqualTo(1));
|
||||||
|
Assert.That(container.Children, Has.One.Items);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ using System.Security;
|
|||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
using mRemoteNG.Config;
|
using mRemoteNG.Config;
|
||||||
using mRemoteNG.Config.Serializers;
|
using mRemoteNG.Config.Serializers;
|
||||||
|
using mRemoteNG.Config.Serializers.Xml;
|
||||||
using mRemoteNG.Connection;
|
using mRemoteNG.Connection;
|
||||||
using mRemoteNG.Container;
|
using mRemoteNG.Container;
|
||||||
using mRemoteNG.Security;
|
using mRemoteNG.Security;
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using mRemoteNG.Config.Serializers;
|
using mRemoteNG.Config.Serializers.Csv;
|
||||||
using mRemoteNG.Config.Serializers.MiscSerializers;
|
|
||||||
using mRemoteNG.Connection;
|
using mRemoteNG.Connection;
|
||||||
using mRemoteNG.Connection.Protocol;
|
using mRemoteNG.Connection.Protocol;
|
||||||
using mRemoteNG.Connection.Protocol.Http;
|
using mRemoteNG.Connection.Protocol.Http;
|
||||||
@@ -11,28 +10,29 @@ using mRemoteNG.Connection.Protocol.RDP;
|
|||||||
using mRemoteNG.Connection.Protocol.VNC;
|
using mRemoteNG.Connection.Protocol.VNC;
|
||||||
using mRemoteNG.Credential;
|
using mRemoteNG.Credential;
|
||||||
using mRemoteNG.Security;
|
using mRemoteNG.Security;
|
||||||
|
using mRemoteNGTests.TestHelpers;
|
||||||
using NSubstitute;
|
using NSubstitute;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
namespace mRemoteNGTests.Config.Serializers.MiscSerializers
|
namespace mRemoteNGTests.Config.Serializers.ConnectionSerializers.Csv
|
||||||
{
|
{
|
||||||
public class CsvConnectionsDeserializerMremotengFormatTests
|
public class CsvConnectionsDeserializerMremotengFormatTests
|
||||||
{
|
{
|
||||||
private CsvConnectionsDeserializerMremotengFormat _deserializer;
|
private CsvConnectionsDeserializerMremotengFormat _deserializer;
|
||||||
private ICredentialRepositoryList _credentialRepositoryList;
|
private CsvConnectionsSerializerMremotengFormat _serializer;
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
_deserializer = new CsvConnectionsDeserializerMremotengFormat();
|
_deserializer = new CsvConnectionsDeserializerMremotengFormat();
|
||||||
_credentialRepositoryList = Substitute.For<ICredentialRepositoryList>();
|
var credentialRepositoryList = Substitute.For<ICredentialRepositoryList>();
|
||||||
|
_serializer = new CsvConnectionsSerializerMremotengFormat(new SaveFilter(), credentialRepositoryList);
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCaseSource(typeof(DeserializationTestSource), nameof(DeserializationTestSource.ConnectionPropertyTestCases))]
|
[TestCaseSource(typeof(DeserializationTestSource), nameof(DeserializationTestSource.ConnectionPropertyTestCases))]
|
||||||
public object ConnectionPropertiesDeserializedCorrectly(string propertyToCheck)
|
public object ConnectionPropertiesDeserializedCorrectly(string propertyToCheck)
|
||||||
{
|
{
|
||||||
var serializer = new CsvConnectionsSerializerMremotengFormat(new SaveFilter(), _credentialRepositoryList);
|
var csv = _serializer.Serialize(GetTestConnection());
|
||||||
var csv = serializer.Serialize(GetTestConnection());
|
|
||||||
var deserializedConnections = _deserializer.Deserialize(csv);
|
var deserializedConnections = _deserializer.Deserialize(csv);
|
||||||
var connection = deserializedConnections.GetRecursiveChildList().FirstOrDefault();
|
var connection = deserializedConnections.GetRecursiveChildList().FirstOrDefault();
|
||||||
var propertyValue = typeof(ConnectionInfo).GetProperty(propertyToCheck)?.GetValue(connection);
|
var propertyValue = typeof(ConnectionInfo).GetProperty(propertyToCheck)?.GetValue(connection);
|
||||||
@@ -42,14 +42,29 @@ namespace mRemoteNGTests.Config.Serializers.MiscSerializers
|
|||||||
[TestCaseSource(typeof(DeserializationTestSource), nameof(DeserializationTestSource.InheritanceTestCases))]
|
[TestCaseSource(typeof(DeserializationTestSource), nameof(DeserializationTestSource.InheritanceTestCases))]
|
||||||
public object InheritancePropertiesDeserializedCorrectly(string propertyToCheck)
|
public object InheritancePropertiesDeserializedCorrectly(string propertyToCheck)
|
||||||
{
|
{
|
||||||
var serializer = new CsvConnectionsSerializerMremotengFormat(new SaveFilter(), _credentialRepositoryList);
|
var csv = _serializer.Serialize(GetTestConnectionWithAllInherited());
|
||||||
var csv = serializer.Serialize(GetTestConnectionWithAllInherited());
|
|
||||||
var deserializedConnections = _deserializer.Deserialize(csv);
|
var deserializedConnections = _deserializer.Deserialize(csv);
|
||||||
var connection = deserializedConnections.GetRecursiveChildList().FirstOrDefault();
|
var connection = deserializedConnections.GetRecursiveChildList().FirstOrDefault();
|
||||||
|
connection?.RemoveParent();
|
||||||
var propertyValue = typeof(ConnectionInfoInheritance).GetProperty(propertyToCheck)?.GetValue(connection?.Inheritance);
|
var propertyValue = typeof(ConnectionInfoInheritance).GetProperty(propertyToCheck)?.GetValue(connection?.Inheritance);
|
||||||
return propertyValue;
|
return propertyValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TreeStructureDeserializedCorrectly()
|
||||||
|
{
|
||||||
|
//Root
|
||||||
|
// |- folder1
|
||||||
|
// | |- Con1
|
||||||
|
// |- Con2
|
||||||
|
var treeModel = new ConnectionTreeModelBuilder().Build();
|
||||||
|
var csv = _serializer.Serialize(treeModel);
|
||||||
|
var deserializedConnections = _deserializer.Deserialize(csv);
|
||||||
|
var con1 = deserializedConnections.GetRecursiveChildList().First(info => info.Name == "Con1");
|
||||||
|
var folder1 = deserializedConnections.GetRecursiveChildList().First(info => info.Name == "folder1");
|
||||||
|
Assert.That(con1.Parent, Is.EqualTo(folder1));
|
||||||
|
}
|
||||||
|
|
||||||
internal static ConnectionInfo GetTestConnection()
|
internal static ConnectionInfo GetTestConnection()
|
||||||
{
|
{
|
||||||
return new ConnectionInfo
|
return new ConnectionInfo
|
||||||
@@ -82,9 +97,9 @@ namespace mRemoteNGTests.Config.Serializers.MiscSerializers
|
|||||||
UseCredSsp = true,
|
UseCredSsp = true,
|
||||||
RenderingEngine = HTTPBase.RenderingEngine.Gecko,
|
RenderingEngine = HTTPBase.RenderingEngine.Gecko,
|
||||||
ICAEncryptionStrength = IcaProtocol.EncryptionStrength.Encr40Bit,
|
ICAEncryptionStrength = IcaProtocol.EncryptionStrength.Encr40Bit,
|
||||||
RDPAuthenticationLevel = RdpAuthenticationLevel.WarnOnFailedAuth,
|
RDPAuthenticationLevel = RdpProtocol.AuthenticationLevel.WarnOnFailedAuth,
|
||||||
Colors = RdpColors.Colors16Bit,
|
Colors = RdpProtocol.RDPColors.Colors16Bit,
|
||||||
Resolution = RdpResolutions.Res1366x768,
|
Resolution = RdpProtocol.RDPResolutions.Res1366x768,
|
||||||
AutomaticResize = true,
|
AutomaticResize = true,
|
||||||
DisplayWallpaper = true,
|
DisplayWallpaper = true,
|
||||||
DisplayThemes = true,
|
DisplayThemes = true,
|
||||||
@@ -95,7 +110,7 @@ namespace mRemoteNGTests.Config.Serializers.MiscSerializers
|
|||||||
RedirectPorts = true,
|
RedirectPorts = true,
|
||||||
RedirectPrinters = true,
|
RedirectPrinters = true,
|
||||||
RedirectSmartCards = true,
|
RedirectSmartCards = true,
|
||||||
RedirectSound = RdpSounds.LeaveAtRemoteComputer,
|
RedirectSound = RdpProtocol.RDPSounds.LeaveAtRemoteComputer,
|
||||||
RedirectKeys = true,
|
RedirectKeys = true,
|
||||||
VNCCompression = ProtocolVNC.Compression.Comp4,
|
VNCCompression = ProtocolVNC.Compression.Comp4,
|
||||||
VNCEncoding = ProtocolVNC.Encoding.EncRRE,
|
VNCEncoding = ProtocolVNC.Encoding.EncRRE,
|
||||||
@@ -105,8 +120,8 @@ namespace mRemoteNGTests.Config.Serializers.MiscSerializers
|
|||||||
VNCColors = ProtocolVNC.Colors.Col8Bit,
|
VNCColors = ProtocolVNC.Colors.Col8Bit,
|
||||||
VNCSmartSizeMode = ProtocolVNC.SmartSizeMode.SmartSAspect,
|
VNCSmartSizeMode = ProtocolVNC.SmartSizeMode.SmartSAspect,
|
||||||
VNCViewOnly = true,
|
VNCViewOnly = true,
|
||||||
RDGatewayUsageMethod = RDGatewayUsageMethod.Detect,
|
RDGatewayUsageMethod = RdpProtocol.RDGatewayUsageMethod.Detect,
|
||||||
RDGatewayUseConnectionCredentials = RDGatewayUseConnectionCredentials.SmartCard
|
RDGatewayUseConnectionCredentials = RdpProtocol.RDGatewayUseConnectionCredentials.SmartCard
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,13 +1,17 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using mRemoteNG.Config.Serializers;
|
using mRemoteNG.Config.Serializers;
|
||||||
|
using mRemoteNG.Config.Serializers.Csv;
|
||||||
using mRemoteNG.Connection;
|
using mRemoteNG.Connection;
|
||||||
|
using mRemoteNG.Container;
|
||||||
using mRemoteNG.Credential;
|
using mRemoteNG.Credential;
|
||||||
using mRemoteNG.Security;
|
using mRemoteNG.Security;
|
||||||
using mRemoteNG.Tree;
|
using mRemoteNG.Tree;
|
||||||
|
using mRemoteNGTests.TestHelpers;
|
||||||
using NSubstitute;
|
using NSubstitute;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
namespace mRemoteNGTests.Config.Serializers.MiscSerializers
|
namespace mRemoteNGTests.Config.Serializers.ConnectionSerializers.Csv
|
||||||
{
|
{
|
||||||
public class CsvConnectionsSerializerMremotengFormatTests
|
public class CsvConnectionsSerializerMremotengFormatTests
|
||||||
{
|
{
|
||||||
@@ -28,6 +32,24 @@ namespace mRemoteNGTests.Config.Serializers.MiscSerializers
|
|||||||
_credentialRepositoryList.GetCredentialRecord(new Guid()).ReturnsForAnyArgs(credRecord);
|
_credentialRepositoryList.GetCredentialRecord(new Guid()).ReturnsForAnyArgs(credRecord);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void SerializesNodeId()
|
||||||
|
{
|
||||||
|
var serializer = new CsvConnectionsSerializerMremotengFormat(new SaveFilter(), _credentialRepositoryList);
|
||||||
|
var connectionInfo = BuildConnectionInfo();
|
||||||
|
var csv = serializer.Serialize(connectionInfo);
|
||||||
|
Assert.That(csv, Does.Match(connectionInfo.ConstantID));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void DoesntSerializeTheRootNode()
|
||||||
|
{
|
||||||
|
var serializer = new CsvConnectionsSerializerMremotengFormat(new SaveFilter(), _credentialRepositoryList);
|
||||||
|
var treeModel = new ConnectionTreeModelBuilder().Build();
|
||||||
|
var csv = serializer.Serialize(treeModel);
|
||||||
|
Assert.That(csv, Does.Not.Match($"{treeModel.RootNodes[0].ConstantID};.*;{TreeNodeType.Root}"));
|
||||||
|
}
|
||||||
|
|
||||||
[TestCase(Username)]
|
[TestCase(Username)]
|
||||||
[TestCase(Domain)]
|
[TestCase(Domain)]
|
||||||
[TestCase(Password)]
|
[TestCase(Password)]
|
||||||
@@ -82,6 +104,32 @@ namespace mRemoteNGTests.Config.Serializers.MiscSerializers
|
|||||||
Assert.Throws<ArgumentNullException>(() => serializer.Serialize((ConnectionTreeModel)null));
|
Assert.Throws<ArgumentNullException>(() => serializer.Serialize((ConnectionTreeModel)null));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void FoldersAreSerialized()
|
||||||
|
{
|
||||||
|
var serializer = new CsvConnectionsSerializerMremotengFormat(new SaveFilter(), _credentialRepositoryList);
|
||||||
|
var container = BuildContainer();
|
||||||
|
var csv = serializer.Serialize(container);
|
||||||
|
Assert.That(csv, Does.Match(container.Name));
|
||||||
|
Assert.That(csv, Does.Match(container.Username));
|
||||||
|
Assert.That(csv, Does.Match(container.Domain));
|
||||||
|
Assert.That(csv, Does.Match(container.Password));
|
||||||
|
Assert.That(csv, Does.Contain(TreeNodeType.Container.ToString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void SerializationIncludesRawInheritedValuesIfObjectInheritsFromParentOutsideOfSerializationScope()
|
||||||
|
{
|
||||||
|
var serializer = new CsvConnectionsSerializerMremotengFormat(new SaveFilter(), _credentialRepositoryList);
|
||||||
|
var treeModel = new ConnectionTreeModelBuilder().Build();
|
||||||
|
var serializationTarget = treeModel.GetRecursiveChildList().First(info => info.Name == "folder3");
|
||||||
|
var csv = serializer.Serialize(serializationTarget);
|
||||||
|
var lineWithFolder3 = csv.Split(new[] {Environment.NewLine}, StringSplitOptions.None).First(s => s.Contains(serializationTarget.Name));
|
||||||
|
Assert.That(lineWithFolder3, Does.Contain(serializationTarget.Username));
|
||||||
|
Assert.That(lineWithFolder3, Does.Contain(serializationTarget.Domain));
|
||||||
|
Assert.That(lineWithFolder3, Does.Contain(serializationTarget.Password));
|
||||||
|
}
|
||||||
|
|
||||||
private ConnectionInfo BuildConnectionInfo()
|
private ConnectionInfo BuildConnectionInfo()
|
||||||
{
|
{
|
||||||
return new ConnectionInfo
|
return new ConnectionInfo
|
||||||
@@ -93,5 +141,16 @@ namespace mRemoteNGTests.Config.Serializers.MiscSerializers
|
|||||||
Inheritance = {Colors = true}
|
Inheritance = {Colors = true}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ContainerInfo BuildContainer()
|
||||||
|
{
|
||||||
|
return new ContainerInfo
|
||||||
|
{
|
||||||
|
Name = "MyFolder",
|
||||||
|
Username = "BlahBlah1",
|
||||||
|
Domain = "aklkskkksh8",
|
||||||
|
Password = "qweraslkdjf87"
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Text;
|
||||||
|
using System.Xml;
|
||||||
|
using System.Xml.Schema;
|
||||||
|
using mRemoteNG.Config.Serializers.Xml;
|
||||||
|
using mRemoteNG.Security;
|
||||||
|
using mRemoteNG.Security.SymmetricEncryption;
|
||||||
|
using mRemoteNG.Tree;
|
||||||
|
using mRemoteNG.Tree.Root;
|
||||||
|
using mRemoteNGTests.TestHelpers;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace mRemoteNGTests.Config.Serializers.ConnectionSerializers.Xml
|
||||||
|
{
|
||||||
|
public class ValidateXmlSchemas
|
||||||
|
{
|
||||||
|
private XmlConnectionsSerializer _serializer;
|
||||||
|
private ConnectionTreeModel _connectionTreeModel;
|
||||||
|
private ICryptographyProvider _cryptographyProvider;
|
||||||
|
private XmlReaderSettings _xmlReaderSettings;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
_connectionTreeModel = new ConnectionTreeModelBuilder().Build();
|
||||||
|
_cryptographyProvider = new AeadCryptographyProvider();
|
||||||
|
var connectionNodeSerializer = new XmlConnectionNodeSerializer26(
|
||||||
|
_cryptographyProvider,
|
||||||
|
_connectionTreeModel.RootNodes.OfType<RootNodeInfo>().First().PasswordString.ConvertToSecureString(),
|
||||||
|
new SaveFilter());
|
||||||
|
_serializer = new XmlConnectionsSerializer(_cryptographyProvider, connectionNodeSerializer);
|
||||||
|
_xmlReaderSettings = new XmlReaderSettings
|
||||||
|
{
|
||||||
|
ValidationType = ValidationType.Schema,
|
||||||
|
ValidationFlags = XmlSchemaValidationFlags.ProcessInlineSchema |
|
||||||
|
XmlSchemaValidationFlags.ProcessSchemaLocation |
|
||||||
|
XmlSchemaValidationFlags.ReportValidationWarnings
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ValidateSchema()
|
||||||
|
{
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
var xml = _serializer.Serialize(_connectionTreeModel);
|
||||||
|
|
||||||
|
var schemaFile = GetTargetPath("mremoteng_confcons_v2_6.xsd");
|
||||||
|
_xmlReaderSettings.Schemas.Add("http://mremoteng.org", schemaFile);
|
||||||
|
_xmlReaderSettings.ValidationEventHandler += (sender, args) =>
|
||||||
|
{
|
||||||
|
sb.AppendLine($"{args.Severity}: {args.Message}");
|
||||||
|
};
|
||||||
|
|
||||||
|
using (var stream = GenerateStreamFromString(xml))
|
||||||
|
{
|
||||||
|
var reader = XmlReader.Create(stream, _xmlReaderSettings);
|
||||||
|
while (reader.Read()) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.That(sb.ToString(), Is.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetTargetPath(string fileName, [CallerFilePath] string sourceFilePath = "")
|
||||||
|
{
|
||||||
|
const string debugOrRelease =
|
||||||
|
#if DEBUG
|
||||||
|
"Debug";
|
||||||
|
#else
|
||||||
|
"Release";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const string normalOrPortable =
|
||||||
|
#if PORTABLE
|
||||||
|
" Portable";
|
||||||
|
#else
|
||||||
|
"";
|
||||||
|
#endif
|
||||||
|
var path = Path.GetDirectoryName(sourceFilePath);
|
||||||
|
var filePath = $@"{path}\..\..\..\..\bin\{debugOrRelease}{normalOrPortable}\Schemas\{fileName}";
|
||||||
|
return filePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Stream GenerateStreamFromString(string s)
|
||||||
|
{
|
||||||
|
var stream = new MemoryStream();
|
||||||
|
var writer = new StreamWriter(stream);
|
||||||
|
writer.Write(s);
|
||||||
|
writer.Flush();
|
||||||
|
stream.Position = 0;
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using mRemoteNG.Config.Serializers;
|
using mRemoteNG.Config.Serializers.Xml;
|
||||||
using mRemoteNG.Connection;
|
using mRemoteNG.Connection;
|
||||||
using mRemoteNG.Container;
|
using mRemoteNG.Container;
|
||||||
using mRemoteNG.Security;
|
using mRemoteNG.Security;
|
||||||
@@ -9,7 +9,7 @@ using mRemoteNG.Tree;
|
|||||||
using mRemoteNGTests.Properties;
|
using mRemoteNGTests.Properties;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
namespace mRemoteNGTests.Config.Serializers.ConnectionSerializers
|
namespace mRemoteNGTests.Config.Serializers.ConnectionSerializers.Xml
|
||||||
{
|
{
|
||||||
public class XmlConnectionsDeserializerTests
|
public class XmlConnectionsDeserializerTests
|
||||||
{
|
{
|
||||||
@@ -18,7 +18,7 @@ namespace mRemoteNGTests.Config.Serializers.ConnectionSerializers
|
|||||||
|
|
||||||
public void Setup(string confCons, string password)
|
public void Setup(string confCons, string password)
|
||||||
{
|
{
|
||||||
_xmlConnectionsDeserializer = new XmlConnectionsDeserializer(password.ConvertToSecureString);
|
_xmlConnectionsDeserializer = new XmlConnectionsDeserializer(() => password.ConvertToSecureString());
|
||||||
_connectionTreeModel = _xmlConnectionsDeserializer.Deserialize(confCons);
|
_connectionTreeModel = _xmlConnectionsDeserializer.Deserialize(confCons);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,6 +104,14 @@ namespace mRemoteNGTests.Config.Serializers.ConnectionSerializers
|
|||||||
Assert.That(folder22.Inheritance.Username, Is.True);
|
Assert.That(folder22.Inheritance.Username, Is.True);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestCaseSource(typeof(XmlConnectionsDeserializerFixtureData), nameof(XmlConnectionsDeserializerFixtureData.FixtureParams))]
|
||||||
|
public void ExpandedPropertyGetsDeserialized(Datagram testData)
|
||||||
|
{
|
||||||
|
Setup(testData.ConfCons, testData.Password);
|
||||||
|
var folder1 = GetFolderNamed("Folder1", _connectionTreeModel.GetRecursiveChildList());
|
||||||
|
Assert.That(folder1.IsExpanded, Is.True);
|
||||||
|
}
|
||||||
|
|
||||||
private bool ContainsNodeNamed(string name, IEnumerable<ConnectionInfo> list)
|
private bool ContainsNodeNamed(string name, IEnumerable<ConnectionInfo> list)
|
||||||
{
|
{
|
||||||
return list.Any(node => node.Name == name);
|
return list.Any(node => node.Name == name);
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Xml.XPath;
|
using System.Xml.XPath;
|
||||||
using mRemoteNG.Config.Serializers;
|
using mRemoteNG.Config.Serializers;
|
||||||
|
using mRemoteNG.Config.Serializers.Xml;
|
||||||
using mRemoteNG.Connection;
|
using mRemoteNG.Connection;
|
||||||
using mRemoteNG.Container;
|
using mRemoteNG.Container;
|
||||||
using mRemoteNG.Security;
|
using mRemoteNG.Security;
|
||||||
@@ -9,7 +10,7 @@ using mRemoteNG.Tree;
|
|||||||
using mRemoteNG.Tree.Root;
|
using mRemoteNG.Tree.Root;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
namespace mRemoteNGTests.Config.Serializers.ConnectionSerializers
|
namespace mRemoteNGTests.Config.Serializers.ConnectionSerializers.Xml
|
||||||
{
|
{
|
||||||
public class XmlConnectionsDocumentCompilerTests
|
public class XmlConnectionsDocumentCompilerTests
|
||||||
{
|
{
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
using mRemoteNG.Config.Serializers;
|
using mRemoteNG.Config.Serializers;
|
||||||
|
using mRemoteNG.Config.Serializers.Xml;
|
||||||
using mRemoteNG.Connection;
|
using mRemoteNG.Connection;
|
||||||
using mRemoteNG.Container;
|
using mRemoteNG.Container;
|
||||||
using mRemoteNG.Security;
|
using mRemoteNG.Security;
|
||||||
@@ -9,7 +10,7 @@ using mRemoteNG.Tree;
|
|||||||
using mRemoteNG.Tree.Root;
|
using mRemoteNG.Tree.Root;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
namespace mRemoteNGTests.Config.Serializers.ConnectionSerializers
|
namespace mRemoteNGTests.Config.Serializers.ConnectionSerializers.Xml
|
||||||
{
|
{
|
||||||
public class XmlConnectionsDocumentEncryptorTests
|
public class XmlConnectionsDocumentEncryptorTests
|
||||||
{
|
{
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
using System.Xml;
|
using System.Xml;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
using mRemoteNG.Config.Serializers;
|
using mRemoteNG.Config.Serializers;
|
||||||
|
using mRemoteNG.Config.Serializers.Xml;
|
||||||
using mRemoteNG.Connection;
|
using mRemoteNG.Connection;
|
||||||
using mRemoteNG.Container;
|
using mRemoteNG.Container;
|
||||||
using mRemoteNG.Security;
|
using mRemoteNG.Security;
|
||||||
@@ -10,7 +11,7 @@ using mRemoteNG.Tree;
|
|||||||
using mRemoteNG.Tree.Root;
|
using mRemoteNG.Tree.Root;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
namespace mRemoteNGTests.Config.Serializers.ConnectionSerializers
|
namespace mRemoteNGTests.Config.Serializers.ConnectionSerializers.Xml
|
||||||
{
|
{
|
||||||
public class XmlConnectionsSerializerTests
|
public class XmlConnectionsSerializerTests
|
||||||
{
|
{
|
||||||
@@ -55,7 +56,7 @@ namespace mRemoteNGTests.Config.Serializers.ConnectionSerializers
|
|||||||
[TestCase("Username", "")]
|
[TestCase("Username", "")]
|
||||||
[TestCase("Domain", "")]
|
[TestCase("Domain", "")]
|
||||||
[TestCase("Password", "")]
|
[TestCase("Password", "")]
|
||||||
[TestCase("InheritAutomaticResize", "False")]
|
[TestCase("InheritAutomaticResize", "false")]
|
||||||
public void SerializerRespectsSaveFilterSettings(string attributeName, string expectedValue)
|
public void SerializerRespectsSaveFilterSettings(string attributeName, string expectedValue)
|
||||||
{
|
{
|
||||||
var connectionNodeSerializer = new XmlConnectionNodeSerializer26(
|
var connectionNodeSerializer = new XmlConnectionNodeSerializer26(
|
||||||
@@ -2,13 +2,14 @@
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Xml.Linq;
|
using System.Xml.Linq;
|
||||||
using mRemoteNG.Config.Serializers;
|
using mRemoteNG.Config.Serializers;
|
||||||
|
using mRemoteNG.Config.Serializers.Xml;
|
||||||
using mRemoteNG.Security;
|
using mRemoteNG.Security;
|
||||||
using mRemoteNG.Security.Factories;
|
using mRemoteNG.Security.Factories;
|
||||||
using mRemoteNG.Security.SymmetricEncryption;
|
using mRemoteNG.Security.SymmetricEncryption;
|
||||||
using mRemoteNG.Tree.Root;
|
using mRemoteNG.Tree.Root;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
namespace mRemoteNGTests.Config.Serializers.ConnectionSerializers
|
namespace mRemoteNGTests.Config.Serializers.ConnectionSerializers.Xml
|
||||||
{
|
{
|
||||||
public class XmlRootNodeSerializerTests
|
public class XmlRootNodeSerializerTests
|
||||||
{
|
{
|
||||||
@@ -75,7 +76,7 @@ namespace mRemoteNGTests.Config.Serializers.ConnectionSerializers
|
|||||||
{
|
{
|
||||||
var element = _rootNodeSerializer.SerializeRootNodeInfo(_rootNodeInfo, _cryptographyProvider, fullFileEncryption);
|
var element = _rootNodeSerializer.SerializeRootNodeInfo(_rootNodeInfo, _cryptographyProvider, fullFileEncryption);
|
||||||
var attributeValue = element.Attribute(XName.Get("FullFileEncryption"))?.Value;
|
var attributeValue = element.Attribute(XName.Get("FullFileEncryption"))?.Value;
|
||||||
Assert.That(attributeValue, Is.EqualTo(fullFileEncryption.ToString()));
|
Assert.That(bool.Parse(attributeValue), Is.EqualTo(fullFileEncryption));
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase("", "ThisIsNotProtected")]
|
[TestCase("", "ThisIsNotProtected")]
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
using System.Data;
|
using System.Data;
|
||||||
using System.Linq;
|
using System.Security;
|
||||||
using mRemoteNG.Config.Serializers;
|
using mRemoteNG.Config.Serializers.MsSql;
|
||||||
using mRemoteNG.Connection;
|
using mRemoteNG.Connection;
|
||||||
using mRemoteNG.Security;
|
using mRemoteNG.Security;
|
||||||
|
using mRemoteNG.Security.SymmetricEncryption;
|
||||||
using mRemoteNG.Tree;
|
using mRemoteNG.Tree;
|
||||||
using mRemoteNGTests.TestHelpers;
|
using mRemoteNGTests.TestHelpers;
|
||||||
|
using NSubstitute;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
namespace mRemoteNGTests.Config.Serializers
|
namespace mRemoteNGTests.Config.Serializers
|
||||||
@@ -12,30 +14,37 @@ namespace mRemoteNGTests.Config.Serializers
|
|||||||
public class DataTableDeserializerTests
|
public class DataTableDeserializerTests
|
||||||
{
|
{
|
||||||
private DataTableDeserializer _deserializer;
|
private DataTableDeserializer _deserializer;
|
||||||
|
private ICryptographyProvider _cryptographyProvider;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
_cryptographyProvider = new LegacyRijndaelCryptographyProvider();
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void WeCanDeserializeATree()
|
public void WeCanDeserializeATree()
|
||||||
{
|
{
|
||||||
var model = CreateConnectionTreeModel();
|
var model = CreateConnectionTreeModel();
|
||||||
var dataTable = CreateDataTable(model.RootNodes[0]);
|
var dataTable = CreateDataTable(model.RootNodes[0]);
|
||||||
_deserializer = new DataTableDeserializer();
|
_deserializer = new DataTableDeserializer(_cryptographyProvider, new SecureString());
|
||||||
var output = _deserializer.Deserialize(dataTable);
|
var output = _deserializer.Deserialize(dataTable);
|
||||||
Assert.That(output.GetRecursiveChildList().Count(), Is.EqualTo(model.GetRecursiveChildList().Count()));
|
Assert.That(output.GetRecursiveChildList().Count, Is.EqualTo(model.GetRecursiveChildList().Count));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void WeCanDeserializeASingleEntry()
|
public void WeCanDeserializeASingleEntry()
|
||||||
{
|
{
|
||||||
var dataTable = CreateDataTable(new ConnectionInfo());
|
var dataTable = CreateDataTable(new ConnectionInfo());
|
||||||
_deserializer = new DataTableDeserializer();
|
_deserializer = new DataTableDeserializer(_cryptographyProvider, new SecureString());
|
||||||
var output = _deserializer.Deserialize(dataTable);
|
var output = _deserializer.Deserialize(dataTable);
|
||||||
Assert.That(output.GetRecursiveChildList().Count(), Is.EqualTo(1));
|
Assert.That(output.GetRecursiveChildList().Count, Is.EqualTo(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private DataTable CreateDataTable(ConnectionInfo tableContent)
|
private DataTable CreateDataTable(ConnectionInfo tableContent)
|
||||||
{
|
{
|
||||||
var serializer = new DataTableSerializer(new SaveFilter());
|
var serializer = new DataTableSerializer(new SaveFilter(), _cryptographyProvider, new SecureString());
|
||||||
return serializer.Serialize(tableContent);
|
return serializer.Serialize(tableContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,15 @@
|
|||||||
using mRemoteNG.Config.Serializers;
|
using System.Linq;
|
||||||
|
using System.Security;
|
||||||
|
using mRemoteNG.Config.Serializers;
|
||||||
|
using mRemoteNG.Config.Serializers.MsSql;
|
||||||
using mRemoteNG.Connection;
|
using mRemoteNG.Connection;
|
||||||
using mRemoteNG.Container;
|
using mRemoteNG.Container;
|
||||||
using mRemoteNG.Security;
|
using mRemoteNG.Security;
|
||||||
|
using mRemoteNG.Security.SymmetricEncryption;
|
||||||
using mRemoteNG.Tree;
|
using mRemoteNG.Tree;
|
||||||
using mRemoteNG.Tree.Root;
|
using mRemoteNG.Tree.Root;
|
||||||
using mRemoteNGTests.TestHelpers;
|
using mRemoteNGTests.TestHelpers;
|
||||||
|
using NSubstitute;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
namespace mRemoteNGTests.Config.Serializers
|
namespace mRemoteNGTests.Config.Serializers
|
||||||
@@ -18,7 +23,10 @@ namespace mRemoteNGTests.Config.Serializers
|
|||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
_saveFilter = new SaveFilter();
|
_saveFilter = new SaveFilter();
|
||||||
_dataTableSerializer = new DataTableSerializer(_saveFilter);
|
_dataTableSerializer = new DataTableSerializer(
|
||||||
|
_saveFilter,
|
||||||
|
new LegacyRijndaelCryptographyProvider(),
|
||||||
|
new SecureString());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -26,7 +34,7 @@ namespace mRemoteNGTests.Config.Serializers
|
|||||||
{
|
{
|
||||||
var model = CreateConnectionTreeModel();
|
var model = CreateConnectionTreeModel();
|
||||||
var dataTable = _dataTableSerializer.Serialize(model);
|
var dataTable = _dataTableSerializer.Serialize(model);
|
||||||
Assert.That(dataTable.Rows.Count, Is.EqualTo(3));
|
Assert.That(dataTable.Rows.Count, Is.EqualTo(model.GetRecursiveChildList().Count()));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
|||||||
@@ -18,9 +18,9 @@ namespace mRemoteNGTests.Config.Serializers.MiscSerializers
|
|||||||
private const string ExpectedDomain = "myspecialdomain";
|
private const string ExpectedDomain = "myspecialdomain";
|
||||||
private const string ExpectedGatewayHostname = "gatewayhostname.domain.com";
|
private const string ExpectedGatewayHostname = "gatewayhostname.domain.com";
|
||||||
private const int ExpectedPort = 9933;
|
private const int ExpectedPort = 9933;
|
||||||
private const RdpColors ExpectedColors = RdpColors.Colors24Bit;
|
private const RdpProtocol.RDPColors ExpectedColors = RdpProtocol.RDPColors.Colors24Bit;
|
||||||
private const bool ExpectedBitmapCaching = false;
|
private const bool ExpectedBitmapCaching = false;
|
||||||
private const RdpResolutions ExpectedResolutionMode = RdpResolutions.FitToWindow;
|
private const RdpProtocol.RDPResolutions ExpectedResolutionMode = RdpProtocol.RDPResolutions.FitToWindow;
|
||||||
private const bool ExpectedWallpaperDisplay = true;
|
private const bool ExpectedWallpaperDisplay = true;
|
||||||
private const bool ExpectedThemesDisplay = true;
|
private const bool ExpectedThemesDisplay = true;
|
||||||
private const bool ExpectedFontSmoothing = true;
|
private const bool ExpectedFontSmoothing = true;
|
||||||
@@ -29,7 +29,7 @@ namespace mRemoteNGTests.Config.Serializers.MiscSerializers
|
|||||||
private const bool ExpectedDriveRedirection = true;
|
private const bool ExpectedDriveRedirection = true;
|
||||||
private const bool ExpectedPortRedirection = true;
|
private const bool ExpectedPortRedirection = true;
|
||||||
private const bool ExpectedPrinterRedirection = true;
|
private const bool ExpectedPrinterRedirection = true;
|
||||||
private const RdpSounds ExpectedSoundRedirection = RdpSounds.BringToThisComputer;
|
private const RdpProtocol.RDPSounds ExpectedSoundRedirection = RdpProtocol.RDPSounds.BringToThisComputer;
|
||||||
|
|
||||||
|
|
||||||
[OneTimeSetUp]
|
[OneTimeSetUp]
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
using System.IO;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using mRemoteNG.Config.Serializers;
|
using mRemoteNG.Config.Serializers;
|
||||||
|
using mRemoteNG.Connection;
|
||||||
using mRemoteNG.Connection.Protocol;
|
using mRemoteNG.Connection.Protocol;
|
||||||
using mRemoteNG.Connection.Protocol.RDP;
|
using mRemoteNG.Connection.Protocol.RDP;
|
||||||
using mRemoteNG.Container;
|
using mRemoteNG.Container;
|
||||||
using mRemoteNG.Tree;
|
|
||||||
using mRemoteNGTests.Properties;
|
using mRemoteNGTests.Properties;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
@@ -14,7 +16,6 @@ namespace mRemoteNGTests.Config.Serializers.MiscSerializers
|
|||||||
{
|
{
|
||||||
private string _connectionFileContents;
|
private string _connectionFileContents;
|
||||||
private RemoteDesktopConnectionManagerDeserializer _deserializer;
|
private RemoteDesktopConnectionManagerDeserializer _deserializer;
|
||||||
private ConnectionTreeModel _connectionTreeModel;
|
|
||||||
private const string ExpectedName = "server1_displayname";
|
private const string ExpectedName = "server1_displayname";
|
||||||
private const string ExpectedHostname = "server1";
|
private const string ExpectedHostname = "server1";
|
||||||
private const string ExpectedDescription = "Comment text here";
|
private const string ExpectedDescription = "Comment text here";
|
||||||
@@ -23,20 +24,20 @@ namespace mRemoteNGTests.Config.Serializers.MiscSerializers
|
|||||||
private const string ExpectedPassword = "passwordHere!";
|
private const string ExpectedPassword = "passwordHere!";
|
||||||
private const bool ExpectedUseConsoleSession = true;
|
private const bool ExpectedUseConsoleSession = true;
|
||||||
private const int ExpectedPort = 9933;
|
private const int ExpectedPort = 9933;
|
||||||
private const RDGatewayUsageMethod ExpectedGatewayUsageMethod = RDGatewayUsageMethod.Always;
|
private const RdpProtocol.RDGatewayUsageMethod ExpectedGatewayUsageMethod = RdpProtocol.RDGatewayUsageMethod.Always;
|
||||||
private const string ExpectedGatewayHostname = "gatewayserverhost.innerdomain.net";
|
private const string ExpectedGatewayHostname = "gatewayserverhost.innerdomain.net";
|
||||||
private const string ExpectedGatewayUsername = "gatewayusername";
|
private const string ExpectedGatewayUsername = "gatewayusername";
|
||||||
private const string ExpectedGatewayDomain = "innerdomain";
|
private const string ExpectedGatewayDomain = "innerdomain";
|
||||||
private const string ExpectedGatewayPassword = "gatewayPassword123";
|
private const string ExpectedGatewayPassword = "gatewayPassword123";
|
||||||
private const RdpResolutions ExpectedRdpResolution = RdpResolutions.FitToWindow;
|
private const RdpProtocol.RDPResolutions ExpectedRdpResolution = RdpProtocol.RDPResolutions.FitToWindow;
|
||||||
private const RdpColors ExpectedRdpColorDepth = RdpColors.Colors24Bit;
|
private const RdpProtocol.RDPColors ExpectedRdpColorDepth = RdpProtocol.RDPColors.Colors24Bit;
|
||||||
private const RdpSounds ExpectedAudioRedirection = RdpSounds.DoNotPlay;
|
private const RdpProtocol.RDPSounds ExpectedAudioRedirection = RdpProtocol.RDPSounds.DoNotPlay;
|
||||||
private const bool ExpectedKeyRedirection = true;
|
private const bool ExpectedKeyRedirection = true;
|
||||||
private const bool ExpectedSmartcardRedirection = true;
|
private const bool ExpectedSmartcardRedirection = true;
|
||||||
private const bool ExpectedDriveRedirection = true;
|
private const bool ExpectedDriveRedirection = true;
|
||||||
private const bool ExpectedPortRedirection = true;
|
private const bool ExpectedPortRedirection = true;
|
||||||
private const bool ExpectedPrinterRedirection = true;
|
private const bool ExpectedPrinterRedirection = true;
|
||||||
private const RdpAuthenticationLevel ExpectedAuthLevel = RdpAuthenticationLevel.WarnOnFailedAuth;
|
private const RdpProtocol.AuthenticationLevel ExpectedAuthLevel = RdpProtocol.AuthenticationLevel.WarnOnFailedAuth;
|
||||||
|
|
||||||
|
|
||||||
[OneTimeSetUp]
|
[OneTimeSetUp]
|
||||||
@@ -44,262 +45,77 @@ namespace mRemoteNGTests.Config.Serializers.MiscSerializers
|
|||||||
{
|
{
|
||||||
_connectionFileContents = Resources.test_rdcman_v2_7_schema3;
|
_connectionFileContents = Resources.test_rdcman_v2_7_schema3;
|
||||||
_deserializer = new RemoteDesktopConnectionManagerDeserializer();
|
_deserializer = new RemoteDesktopConnectionManagerDeserializer();
|
||||||
_connectionTreeModel = _deserializer.Deserialize(_connectionFileContents);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void ConnectionTreeModelHasARootNode()
|
public void ConnectionTreeModelHasARootNode()
|
||||||
{
|
{
|
||||||
var numberOfRootNodes = _connectionTreeModel.RootNodes.Count;
|
var connectionTreeModel = _deserializer.Deserialize(_connectionFileContents);
|
||||||
|
var numberOfRootNodes = connectionTreeModel.RootNodes.Count;
|
||||||
Assert.That(numberOfRootNodes, Is.GreaterThan(0));
|
Assert.That(numberOfRootNodes, Is.GreaterThan(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void RootNodeHasContents()
|
public void RootNodeHasContents()
|
||||||
{
|
{
|
||||||
var rootNodeContents = _connectionTreeModel.RootNodes.First().Children;
|
var connectionTreeModel = _deserializer.Deserialize(_connectionFileContents);
|
||||||
|
var rootNodeContents = connectionTreeModel.RootNodes.First().Children;
|
||||||
Assert.That(rootNodeContents, Is.Not.Empty);
|
Assert.That(rootNodeContents, Is.Not.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void AllSubRootFoldersImported()
|
public void AllSubRootFoldersImported()
|
||||||
{
|
{
|
||||||
var rootNode = _connectionTreeModel.RootNodes.First();
|
var connectionTreeModel = _deserializer.Deserialize(_connectionFileContents);
|
||||||
|
var rootNode = connectionTreeModel.RootNodes.First();
|
||||||
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
|
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
|
||||||
var rootNodeContents = importedRdcmanRootNode.Children.Count(node => node.Name == "Group1" || node.Name == "Group2");
|
var rootNodeContents = importedRdcmanRootNode.Children.Count(node => node.Name == "Group1" || node.Name == "Group2");
|
||||||
Assert.That(rootNodeContents, Is.EqualTo(2));
|
Assert.That(rootNodeContents, Is.EqualTo(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[TestCaseSource(nameof(ExpectedPropertyValues))]
|
||||||
public void ConnectionDisplayNameImported()
|
public void PropertiesWithValuesAreCorrectlyImported(Func<ConnectionInfo, object> propSelector, object expectedValue)
|
||||||
{
|
{
|
||||||
var rootNode = _connectionTreeModel.RootNodes.First();
|
var connectionTreeModel = _deserializer.Deserialize(_connectionFileContents);
|
||||||
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
|
|
||||||
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
|
var connection = connectionTreeModel
|
||||||
var connection = group1.Children.First();
|
.GetRecursiveChildList()
|
||||||
Assert.That(connection.Name, Is.EqualTo(ExpectedName));
|
.OfType<ContainerInfo>()
|
||||||
|
.First(node => node.Name == "Group1")
|
||||||
|
.Children
|
||||||
|
.First();
|
||||||
|
|
||||||
|
Assert.That(propSelector(connection), Is.EqualTo(expectedValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[TestCaseSource(nameof(NullPropertyValues))]
|
||||||
public void ConnectionHostnameImported()
|
public void PropertiesWithoutValuesAreIgnored(Func<ConnectionInfo, object> propSelector)
|
||||||
{
|
{
|
||||||
var rootNode = _connectionTreeModel.RootNodes.First();
|
var connectionTreeModel = _deserializer.Deserialize(Resources.test_rdcman_v2_7_schema3_empty_values);
|
||||||
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
|
|
||||||
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
|
var importedConnection = connectionTreeModel
|
||||||
var connection = group1.Children.First();
|
.GetRecursiveChildList()
|
||||||
Assert.That(connection.Hostname, Is.EqualTo(ExpectedHostname));
|
.OfType<ContainerInfo>()
|
||||||
|
.First(node => node.Name == "Group1")
|
||||||
|
.Children
|
||||||
|
.First();
|
||||||
|
|
||||||
|
Assert.That(propSelector(importedConnection), Is.EqualTo(propSelector(new ConnectionInfo())));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[TestCaseSource(nameof(NullPropertyValues))]
|
||||||
public void ConnectionDescriptionImported()
|
public void NonExistantPropertiesAreIgnored(Func<ConnectionInfo, object> propSelector)
|
||||||
{
|
{
|
||||||
var rootNode = _connectionTreeModel.RootNodes.First();
|
var connectionTreeModel = _deserializer.Deserialize(Resources.test_rdcman_v2_7_schema3_null_values);
|
||||||
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
|
|
||||||
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
|
|
||||||
var connection = group1.Children.First();
|
|
||||||
Assert.That(connection.Description, Is.EqualTo(ExpectedDescription));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
var importedConnection = connectionTreeModel
|
||||||
public void ConnectionUsernameImported()
|
.GetRecursiveChildList()
|
||||||
{
|
.OfType<ContainerInfo>()
|
||||||
var rootNode = _connectionTreeModel.RootNodes.First();
|
.First(node => node.Name == "Group1")
|
||||||
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
|
.Children
|
||||||
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
|
.First();
|
||||||
var connection = group1.Children.First();
|
|
||||||
Assert.That(connection.Username, Is.EqualTo(ExpectedUsername));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
Assert.That(propSelector(importedConnection), Is.EqualTo(propSelector(new ConnectionInfo())));
|
||||||
public void ConnectionDomainImported()
|
|
||||||
{
|
|
||||||
var rootNode = _connectionTreeModel.RootNodes.First();
|
|
||||||
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
|
|
||||||
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
|
|
||||||
var connection = group1.Children.First();
|
|
||||||
Assert.That(connection.Domain, Is.EqualTo(ExpectedDomain));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Since password is encrypted with a machine key, cant test decryption on another machine
|
|
||||||
//[Test]
|
|
||||||
//public void ConnectionPasswordImported()
|
|
||||||
//{
|
|
||||||
// var rootNode = _connectionTreeModel.RootNodes.First();
|
|
||||||
// var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
|
|
||||||
// var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
|
|
||||||
// var connection = group1.Children.First();
|
|
||||||
// Assert.That(connection.Password, Is.EqualTo(ExpectedPassword));
|
|
||||||
//}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void ConnectionProtocolSetToRdp()
|
|
||||||
{
|
|
||||||
var rootNode = _connectionTreeModel.RootNodes.First();
|
|
||||||
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
|
|
||||||
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
|
|
||||||
var connection = group1.Children.First();
|
|
||||||
Assert.That(connection.Protocol, Is.EqualTo(ProtocolType.RDP));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void ConnectionUseConsoleSessionImported()
|
|
||||||
{
|
|
||||||
var rootNode = _connectionTreeModel.RootNodes.First();
|
|
||||||
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
|
|
||||||
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
|
|
||||||
var connection = group1.Children.First();
|
|
||||||
Assert.That(connection.UseConsoleSession, Is.EqualTo(ExpectedUseConsoleSession));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void ConnectionPortImported()
|
|
||||||
{
|
|
||||||
var rootNode = _connectionTreeModel.RootNodes.First();
|
|
||||||
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
|
|
||||||
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
|
|
||||||
var connection = group1.Children.First();
|
|
||||||
Assert.That(connection.Port, Is.EqualTo(ExpectedPort));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void ConnectionGatewayUsageMethodImported()
|
|
||||||
{
|
|
||||||
var rootNode = _connectionTreeModel.RootNodes.First();
|
|
||||||
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
|
|
||||||
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
|
|
||||||
var connection = group1.Children.First();
|
|
||||||
Assert.That(connection.RDGatewayUsageMethod, Is.EqualTo(ExpectedGatewayUsageMethod));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void ConnectionGatewayHostnameImported()
|
|
||||||
{
|
|
||||||
var rootNode = _connectionTreeModel.RootNodes.First();
|
|
||||||
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
|
|
||||||
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
|
|
||||||
var connection = group1.Children.First();
|
|
||||||
Assert.That(connection.RDGatewayHostname, Is.EqualTo(ExpectedGatewayHostname));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void ConnectionGatewayUsernameImported()
|
|
||||||
{
|
|
||||||
var rootNode = _connectionTreeModel.RootNodes.First();
|
|
||||||
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
|
|
||||||
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
|
|
||||||
var connection = group1.Children.First();
|
|
||||||
Assert.That(connection.RDGatewayUsername, Is.EqualTo(ExpectedGatewayUsername));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Since password is encrypted with a machine key, cant test decryption on another machine
|
|
||||||
//[Test]
|
|
||||||
//public void ConnectionGatewayPasswordImported()
|
|
||||||
//{
|
|
||||||
// var rootNode = _connectionTreeModel.RootNodes.First();
|
|
||||||
// var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
|
|
||||||
// var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
|
|
||||||
// var connection = group1.Children.First();
|
|
||||||
// Assert.That(connection.RDGatewayPassword, Is.EqualTo(ExpectedGatewayPassword));
|
|
||||||
//}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void ConnectionGatewayDomainImported()
|
|
||||||
{
|
|
||||||
var rootNode = _connectionTreeModel.RootNodes.First();
|
|
||||||
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
|
|
||||||
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
|
|
||||||
var connection = group1.Children.First();
|
|
||||||
Assert.That(connection.RDGatewayDomain, Is.EqualTo(ExpectedGatewayDomain));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void ConnectionResolutionImported()
|
|
||||||
{
|
|
||||||
var rootNode = _connectionTreeModel.RootNodes.First();
|
|
||||||
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
|
|
||||||
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
|
|
||||||
var connection = group1.Children.First();
|
|
||||||
Assert.That(connection.Resolution, Is.EqualTo(ExpectedRdpResolution));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void ConnectionColorDepthImported()
|
|
||||||
{
|
|
||||||
var rootNode = _connectionTreeModel.RootNodes.First();
|
|
||||||
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
|
|
||||||
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
|
|
||||||
var connection = group1.Children.First();
|
|
||||||
Assert.That(connection.Colors, Is.EqualTo(ExpectedRdpColorDepth));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void ConnectionAudioRedirectionImported()
|
|
||||||
{
|
|
||||||
var rootNode = _connectionTreeModel.RootNodes.First();
|
|
||||||
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
|
|
||||||
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
|
|
||||||
var connection = group1.Children.First();
|
|
||||||
Assert.That(connection.RedirectSound, Is.EqualTo(ExpectedAudioRedirection));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void ConnectionKeyRedirectionImported()
|
|
||||||
{
|
|
||||||
var rootNode = _connectionTreeModel.RootNodes.First();
|
|
||||||
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
|
|
||||||
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
|
|
||||||
var connection = group1.Children.First();
|
|
||||||
Assert.That(connection.RedirectKeys, Is.EqualTo(ExpectedKeyRedirection));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void ConnectionDriveRedirectionImported()
|
|
||||||
{
|
|
||||||
var rootNode = _connectionTreeModel.RootNodes.First();
|
|
||||||
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
|
|
||||||
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
|
|
||||||
var connection = group1.Children.First();
|
|
||||||
Assert.That(connection.RedirectDiskDrives, Is.EqualTo(ExpectedDriveRedirection));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void ConnectionPortRedirectionImported()
|
|
||||||
{
|
|
||||||
var rootNode = _connectionTreeModel.RootNodes.First();
|
|
||||||
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
|
|
||||||
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
|
|
||||||
var connection = group1.Children.First();
|
|
||||||
Assert.That(connection.RedirectPorts, Is.EqualTo(ExpectedPortRedirection));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void ConnectionPrinterRedirectionImported()
|
|
||||||
{
|
|
||||||
var rootNode = _connectionTreeModel.RootNodes.First();
|
|
||||||
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
|
|
||||||
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
|
|
||||||
var connection = group1.Children.First();
|
|
||||||
Assert.That(connection.RedirectPrinters, Is.EqualTo(ExpectedPrinterRedirection));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void ConnectionSmartcardRedirectionImported()
|
|
||||||
{
|
|
||||||
var rootNode = _connectionTreeModel.RootNodes.First();
|
|
||||||
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
|
|
||||||
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
|
|
||||||
var connection = group1.Children.First();
|
|
||||||
Assert.That(connection.RedirectSmartCards, Is.EqualTo(ExpectedSmartcardRedirection));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void ConnectionauthenticationLevelImported()
|
|
||||||
{
|
|
||||||
var rootNode = _connectionTreeModel.RootNodes.First();
|
|
||||||
var importedRdcmanRootNode = rootNode.Children.OfType<ContainerInfo>().First();
|
|
||||||
var group1 = importedRdcmanRootNode.Children.OfType<ContainerInfo>().First(node => node.Name == "Group1");
|
|
||||||
var connection = group1.Children.First();
|
|
||||||
Assert.That(connection.RDPAuthenticationLevel, Is.EqualTo(ExpectedAuthLevel));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -322,5 +138,61 @@ namespace mRemoteNGTests.Config.Serializers.MiscSerializers
|
|||||||
var badFileContents = Resources.test_rdcman_noversion;
|
var badFileContents = Resources.test_rdcman_noversion;
|
||||||
Assert.That(() => _deserializer.Deserialize(badFileContents), Throws.TypeOf<FileFormatException>());
|
Assert.That(() => _deserializer.Deserialize(badFileContents), Throws.TypeOf<FileFormatException>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<TestCaseData> ExpectedPropertyValues()
|
||||||
|
{
|
||||||
|
return new[]
|
||||||
|
{
|
||||||
|
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Name), ExpectedName).SetName(nameof(ConnectionInfo.Name)),
|
||||||
|
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Hostname), ExpectedHostname).SetName(nameof(ConnectionInfo.Hostname)),
|
||||||
|
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Description), ExpectedDescription).SetName(nameof(ConnectionInfo.Description)),
|
||||||
|
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Username), ExpectedUsername).SetName(nameof(ConnectionInfo.Username)),
|
||||||
|
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Domain), ExpectedDomain).SetName(nameof(ConnectionInfo.Domain)),
|
||||||
|
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Protocol), ProtocolType.RDP).SetName(nameof(ConnectionInfo.Protocol)),
|
||||||
|
new TestCaseData((Func<ConnectionInfo,object>)(con => con.UseConsoleSession), ExpectedUseConsoleSession).SetName(nameof(ConnectionInfo.UseConsoleSession)),
|
||||||
|
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Port), ExpectedPort).SetName(nameof(ConnectionInfo.Port)),
|
||||||
|
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RDGatewayUsageMethod), ExpectedGatewayUsageMethod).SetName(nameof(ConnectionInfo.RDGatewayUsageMethod)),
|
||||||
|
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RDGatewayHostname), ExpectedGatewayHostname).SetName(nameof(ConnectionInfo.RDGatewayHostname)),
|
||||||
|
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RDGatewayUsername), ExpectedGatewayUsername).SetName(nameof(ConnectionInfo.RDGatewayUsername)),
|
||||||
|
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RDGatewayDomain), ExpectedGatewayDomain).SetName(nameof(ConnectionInfo.RDGatewayDomain)),
|
||||||
|
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Resolution), ExpectedRdpResolution).SetName(nameof(ConnectionInfo.Resolution)),
|
||||||
|
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Colors), ExpectedRdpColorDepth).SetName(nameof(ConnectionInfo.Colors)),
|
||||||
|
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RedirectSound), ExpectedAudioRedirection).SetName(nameof(ConnectionInfo.RedirectSound)),
|
||||||
|
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RedirectKeys), ExpectedKeyRedirection).SetName(nameof(ConnectionInfo.RedirectKeys)),
|
||||||
|
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RDPAuthenticationLevel), ExpectedAuthLevel).SetName(nameof(ConnectionInfo.RDPAuthenticationLevel)),
|
||||||
|
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RedirectSmartCards), ExpectedSmartcardRedirection).SetName(nameof(ConnectionInfo.RedirectSmartCards)),
|
||||||
|
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RedirectPrinters), ExpectedPrinterRedirection).SetName(nameof(ConnectionInfo.RedirectPrinters)),
|
||||||
|
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RedirectPorts), ExpectedPortRedirection).SetName(nameof(ConnectionInfo.RedirectPorts)),
|
||||||
|
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RedirectDiskDrives), ExpectedDriveRedirection).SetName(nameof(ConnectionInfo.RedirectDiskDrives)),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<TestCaseData> NullPropertyValues()
|
||||||
|
{
|
||||||
|
return new[]
|
||||||
|
{
|
||||||
|
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Name)).SetName(nameof(ConnectionInfo.Name)),
|
||||||
|
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Hostname)).SetName(nameof(ConnectionInfo.Hostname)),
|
||||||
|
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Description)).SetName(nameof(ConnectionInfo.Description)),
|
||||||
|
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Username)).SetName(nameof(ConnectionInfo.Username)),
|
||||||
|
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Domain)).SetName(nameof(ConnectionInfo.Domain)),
|
||||||
|
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Protocol)).SetName(nameof(ConnectionInfo.Protocol)),
|
||||||
|
new TestCaseData((Func<ConnectionInfo,object>)(con => con.UseConsoleSession)).SetName(nameof(ConnectionInfo.UseConsoleSession)),
|
||||||
|
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Port)).SetName(nameof(ConnectionInfo.Port)),
|
||||||
|
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RDGatewayUsageMethod)).SetName(nameof(ConnectionInfo.RDGatewayUsageMethod)),
|
||||||
|
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RDGatewayHostname)).SetName(nameof(ConnectionInfo.RDGatewayHostname)),
|
||||||
|
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RDGatewayUsername)).SetName(nameof(ConnectionInfo.RDGatewayUsername)),
|
||||||
|
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RDGatewayDomain)).SetName(nameof(ConnectionInfo.RDGatewayDomain)),
|
||||||
|
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Resolution)).SetName(nameof(ConnectionInfo.Resolution)),
|
||||||
|
new TestCaseData((Func<ConnectionInfo,object>)(con => con.Colors)).SetName(nameof(ConnectionInfo.Colors)),
|
||||||
|
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RedirectSound)).SetName(nameof(ConnectionInfo.RedirectSound)),
|
||||||
|
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RedirectKeys)).SetName(nameof(ConnectionInfo.RedirectKeys)),
|
||||||
|
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RDPAuthenticationLevel)).SetName(nameof(ConnectionInfo.RDPAuthenticationLevel)),
|
||||||
|
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RedirectSmartCards)).SetName(nameof(ConnectionInfo.RedirectSmartCards)),
|
||||||
|
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RedirectPrinters)).SetName(nameof(ConnectionInfo.RedirectPrinters)),
|
||||||
|
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RedirectPorts)).SetName(nameof(ConnectionInfo.RedirectPorts)),
|
||||||
|
new TestCaseData((Func<ConnectionInfo,object>)(con => con.RedirectDiskDrives)).SetName(nameof(ConnectionInfo.RedirectDiskDrives)),
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -23,20 +23,20 @@ namespace mRemoteNGTests.Config.Serializers.MiscSerializers
|
|||||||
private const string ExpectedPassword = "passwordHere!";
|
private const string ExpectedPassword = "passwordHere!";
|
||||||
private const bool ExpectedUseConsoleSession = true;
|
private const bool ExpectedUseConsoleSession = true;
|
||||||
private const int ExpectedPort = 9933;
|
private const int ExpectedPort = 9933;
|
||||||
private const RDGatewayUsageMethod ExpectedGatewayUsageMethod = RDGatewayUsageMethod.Always;
|
private const RdpProtocol.RDGatewayUsageMethod ExpectedGatewayUsageMethod = RdpProtocol.RDGatewayUsageMethod.Always;
|
||||||
private const string ExpectedGatewayHostname = "gatewayserverhost.innerdomain.net";
|
private const string ExpectedGatewayHostname = "gatewayserverhost.innerdomain.net";
|
||||||
private const string ExpectedGatewayUsername = "gatewayusername";
|
private const string ExpectedGatewayUsername = "gatewayusername";
|
||||||
private const string ExpectedGatewayDomain = "innerdomain";
|
private const string ExpectedGatewayDomain = "innerdomain";
|
||||||
private const string ExpectedGatewayPassword = "gatewayPassword123";
|
private const string ExpectedGatewayPassword = "gatewayPassword123";
|
||||||
private const RdpResolutions ExpectedRdpResolution = RdpResolutions.FitToWindow;
|
private const RdpProtocol.RDPResolutions ExpectedRdpResolution = RdpProtocol.RDPResolutions.FitToWindow;
|
||||||
private const RdpColors ExpectedRdpColorDepth = RdpColors.Colors24Bit;
|
private const RdpProtocol.RDPColors ExpectedRdpColorDepth = RdpProtocol.RDPColors.Colors24Bit;
|
||||||
private const RdpSounds ExpectedAudioRedirection = RdpSounds.DoNotPlay;
|
private const RdpProtocol.RDPSounds ExpectedAudioRedirection = RdpProtocol.RDPSounds.DoNotPlay;
|
||||||
private const bool ExpectedKeyRedirection = true;
|
private const bool ExpectedKeyRedirection = true;
|
||||||
private const bool ExpectedSmartcardRedirection = true;
|
private const bool ExpectedSmartcardRedirection = true;
|
||||||
private const bool ExpectedDriveRedirection = true;
|
private const bool ExpectedDriveRedirection = true;
|
||||||
private const bool ExpectedPortRedirection = true;
|
private const bool ExpectedPortRedirection = true;
|
||||||
private const bool ExpectedPrinterRedirection = true;
|
private const bool ExpectedPrinterRedirection = true;
|
||||||
private const RdpAuthenticationLevel ExpectedAuthLevel = RdpAuthenticationLevel.AuthRequired;
|
private const RdpProtocol.AuthenticationLevel ExpectedAuthLevel = RdpProtocol.AuthenticationLevel.AuthRequired;
|
||||||
|
|
||||||
|
|
||||||
[OneTimeSetUp]
|
[OneTimeSetUp]
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using mRemoteNG.Connection;
|
using System;
|
||||||
|
using mRemoteNG.Connection;
|
||||||
using mRemoteNG.Connection.Protocol;
|
using mRemoteNG.Connection.Protocol;
|
||||||
using mRemoteNG.Connection.Protocol.Http;
|
using mRemoteNG.Connection.Protocol.Http;
|
||||||
using mRemoteNG.Connection.Protocol.ICA;
|
using mRemoteNG.Connection.Protocol.ICA;
|
||||||
@@ -12,7 +13,11 @@ namespace mRemoteNGTests.Connection
|
|||||||
public class AbstractConnectionInfoDataTests
|
public class AbstractConnectionInfoDataTests
|
||||||
{
|
{
|
||||||
#pragma warning disable 618
|
#pragma warning disable 618
|
||||||
private class TestAbstractConnectionInfoData : AbstractConnectionRecord {}
|
private class TestAbstractConnectionInfoData : AbstractConnectionRecord {
|
||||||
|
public TestAbstractConnectionInfoData() : base(Guid.NewGuid().ToString())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
#pragma warning restore 618
|
#pragma warning restore 618
|
||||||
private TestAbstractConnectionInfoData _testAbstractConnectionInfoData;
|
private TestAbstractConnectionInfoData _testAbstractConnectionInfoData;
|
||||||
|
|
||||||
@@ -160,7 +165,7 @@ namespace mRemoteNGTests.Connection
|
|||||||
{
|
{
|
||||||
var wasCalled = false;
|
var wasCalled = false;
|
||||||
_testAbstractConnectionInfoData.PropertyChanged += (sender, args) => wasCalled = true;
|
_testAbstractConnectionInfoData.PropertyChanged += (sender, args) => wasCalled = true;
|
||||||
_testAbstractConnectionInfoData.RDPAuthenticationLevel = RdpAuthenticationLevel.AuthRequired;
|
_testAbstractConnectionInfoData.RDPAuthenticationLevel = RdpProtocol.AuthenticationLevel.AuthRequired;
|
||||||
Assert.That(wasCalled, Is.True);
|
Assert.That(wasCalled, Is.True);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -196,7 +201,7 @@ namespace mRemoteNGTests.Connection
|
|||||||
{
|
{
|
||||||
var wasCalled = false;
|
var wasCalled = false;
|
||||||
_testAbstractConnectionInfoData.PropertyChanged += (sender, args) => wasCalled = true;
|
_testAbstractConnectionInfoData.PropertyChanged += (sender, args) => wasCalled = true;
|
||||||
_testAbstractConnectionInfoData.RDGatewayUsageMethod = RDGatewayUsageMethod.Always;
|
_testAbstractConnectionInfoData.RDGatewayUsageMethod = RdpProtocol.RDGatewayUsageMethod.Always;
|
||||||
Assert.That(wasCalled, Is.True);
|
Assert.That(wasCalled, Is.True);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,7 +219,7 @@ namespace mRemoteNGTests.Connection
|
|||||||
{
|
{
|
||||||
var wasCalled = false;
|
var wasCalled = false;
|
||||||
_testAbstractConnectionInfoData.PropertyChanged += (sender, args) => wasCalled = true;
|
_testAbstractConnectionInfoData.PropertyChanged += (sender, args) => wasCalled = true;
|
||||||
_testAbstractConnectionInfoData.RDGatewayUseConnectionCredentials = RDGatewayUseConnectionCredentials.SmartCard;
|
_testAbstractConnectionInfoData.RDGatewayUseConnectionCredentials = RdpProtocol.RDGatewayUseConnectionCredentials.SmartCard;
|
||||||
Assert.That(wasCalled, Is.True);
|
Assert.That(wasCalled, Is.True);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,7 +255,7 @@ namespace mRemoteNGTests.Connection
|
|||||||
{
|
{
|
||||||
var wasCalled = false;
|
var wasCalled = false;
|
||||||
_testAbstractConnectionInfoData.PropertyChanged += (sender, args) => wasCalled = true;
|
_testAbstractConnectionInfoData.PropertyChanged += (sender, args) => wasCalled = true;
|
||||||
_testAbstractConnectionInfoData.Resolution = RdpResolutions.Res1366x768;
|
_testAbstractConnectionInfoData.Resolution = RdpProtocol.RDPResolutions.Res1366x768;
|
||||||
Assert.That(wasCalled, Is.True);
|
Assert.That(wasCalled, Is.True);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,7 +273,7 @@ namespace mRemoteNGTests.Connection
|
|||||||
{
|
{
|
||||||
var wasCalled = false;
|
var wasCalled = false;
|
||||||
_testAbstractConnectionInfoData.PropertyChanged += (sender, args) => wasCalled = true;
|
_testAbstractConnectionInfoData.PropertyChanged += (sender, args) => wasCalled = true;
|
||||||
_testAbstractConnectionInfoData.Colors = RdpColors.Colors16Bit;
|
_testAbstractConnectionInfoData.Colors = RdpProtocol.RDPColors.Colors16Bit;
|
||||||
Assert.That(wasCalled, Is.True);
|
Assert.That(wasCalled, Is.True);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -367,7 +372,7 @@ namespace mRemoteNGTests.Connection
|
|||||||
{
|
{
|
||||||
var wasCalled = false;
|
var wasCalled = false;
|
||||||
_testAbstractConnectionInfoData.PropertyChanged += (sender, args) => wasCalled = true;
|
_testAbstractConnectionInfoData.PropertyChanged += (sender, args) => wasCalled = true;
|
||||||
_testAbstractConnectionInfoData.RedirectSound = RdpSounds.DoNotPlay;
|
_testAbstractConnectionInfoData.RedirectSound = RdpProtocol.RDPSounds.DoNotPlay;
|
||||||
Assert.That(wasCalled, Is.True);
|
Assert.That(wasCalled, Is.True);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
using mRemoteNG.Connection;
|
using mRemoteNG.Connection;
|
||||||
|
using mRemoteNG.Container;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using System.Reflection;
|
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
namespace mRemoteNGTests.Connection
|
namespace mRemoteNGTests.Connection
|
||||||
{
|
{
|
||||||
@@ -74,6 +75,22 @@ namespace mRemoteNGTests.Connection
|
|||||||
Assert.That(hasEverythingInheritedProperty, Is.False);
|
Assert.That(hasEverythingInheritedProperty, Is.False);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void AlwaysReturnInheritedValueIfRequested()
|
||||||
|
{
|
||||||
|
var expectedSetting = false;
|
||||||
|
|
||||||
|
var container = new ContainerInfo { AutomaticResize = expectedSetting };
|
||||||
|
var con1 = new ConnectionInfo
|
||||||
|
{
|
||||||
|
AutomaticResize = true,
|
||||||
|
Inheritance = {AutomaticResize = true}
|
||||||
|
};
|
||||||
|
container.AddChild(con1);
|
||||||
|
|
||||||
|
Assert.That(con1.AutomaticResize, Is.EqualTo(expectedSetting));
|
||||||
|
}
|
||||||
|
|
||||||
private bool AllInheritancePropertiesAreTrue()
|
private bool AllInheritancePropertiesAreTrue()
|
||||||
{
|
{
|
||||||
var allPropertiesTrue = true;
|
var allPropertiesTrue = true;
|
||||||
|
|||||||
@@ -27,22 +27,6 @@ namespace mRemoteNGTests.Connection
|
|||||||
_connectionInfo = null;
|
_connectionInfo = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void CreatingConnectionInfoWithParentSetsTheParentProperty()
|
|
||||||
{
|
|
||||||
var container = new ContainerInfo();
|
|
||||||
var connectionInfo = new ConnectionInfo(container);
|
|
||||||
Assert.That(connectionInfo.Parent, Is.EqualTo(container));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void CreatingConnectionInfoWithParentAddsToTheParentsChildList()
|
|
||||||
{
|
|
||||||
var container = new ContainerInfo();
|
|
||||||
var connectionInfo = new ConnectionInfo(container);
|
|
||||||
Assert.That(container.Children, Does.Contain(connectionInfo));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void CopyCreatesMemberwiseCopy()
|
public void CopyCreatesMemberwiseCopy()
|
||||||
{
|
{
|
||||||
@@ -59,6 +43,20 @@ namespace mRemoteNGTests.Connection
|
|||||||
Assert.That(clonedConnection.Parent, Is.Null);
|
Assert.That(clonedConnection.Parent, Is.Null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CloneAlsoCopiesInheritanceObject()
|
||||||
|
{
|
||||||
|
var clonedConnection = _connectionInfo.Clone();
|
||||||
|
Assert.That(clonedConnection.Inheritance, Is.Not.EqualTo(_connectionInfo.Inheritance));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CloneCorrectlySetsParentOfInheritanceObject()
|
||||||
|
{
|
||||||
|
var clonedConnection = _connectionInfo.Clone();
|
||||||
|
Assert.That(clonedConnection.Inheritance.Parent, Is.EqualTo(clonedConnection));
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void CopyFromCopiesProperties()
|
public void CopyFromCopiesProperties()
|
||||||
{
|
{
|
||||||
@@ -81,7 +79,7 @@ namespace mRemoteNGTests.Connection
|
|||||||
{
|
{
|
||||||
var eventWasCalled = false;
|
var eventWasCalled = false;
|
||||||
_connectionInfo.PropertyChanged += (sender, args) => eventWasCalled = true;
|
_connectionInfo.PropertyChanged += (sender, args) => eventWasCalled = true;
|
||||||
_connectionInfo.OpenConnections.Add(new ProtocolSSH2(_connectionInfo));
|
_connectionInfo.OpenConnections.Add(new ProtocolSSH2());
|
||||||
Assert.That(eventWasCalled);
|
Assert.That(eventWasCalled);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,7 +88,7 @@ namespace mRemoteNGTests.Connection
|
|||||||
{
|
{
|
||||||
var nameOfModifiedProperty = "";
|
var nameOfModifiedProperty = "";
|
||||||
_connectionInfo.PropertyChanged += (sender, args) => nameOfModifiedProperty = args.PropertyName;
|
_connectionInfo.PropertyChanged += (sender, args) => nameOfModifiedProperty = args.PropertyName;
|
||||||
_connectionInfo.OpenConnections.Add(new ProtocolSSH2(_connectionInfo));
|
_connectionInfo.OpenConnections.Add(new ProtocolSSH2());
|
||||||
Assert.That(nameOfModifiedProperty, Is.EqualTo("OpenConnections"));
|
Assert.That(nameOfModifiedProperty, Is.EqualTo("OpenConnections"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
using mRemoteNG.Connection;
|
using System.Collections.Generic;
|
||||||
using mRemoteNG.Connection.Protocol;
|
using System.Reflection;
|
||||||
|
using mRemoteNG.Connection;
|
||||||
|
using mRemoteNGTests.TestHelpers;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
|
||||||
@@ -7,67 +9,54 @@ namespace mRemoteNGTests.Connection
|
|||||||
{
|
{
|
||||||
public class DefaultConnectionInfoTests
|
public class DefaultConnectionInfoTests
|
||||||
{
|
{
|
||||||
private string _testDomain = "somedomain";
|
private ConnectionInfo _randomizedConnectionInfo;
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
DefaultConnectionInfo.Instance.Domain = "";
|
_randomizedConnectionInfo = ConnectionInfoHelpers.GetRandomizedConnectionInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[TestCaseSource(nameof(GetConnectionInfoProperties))]
|
||||||
public void LoadingDefaultInfoUpdatesAllProperties()
|
public void LoadingDefaultInfoUpdatesAllProperties(PropertyInfo property)
|
||||||
{
|
{
|
||||||
var connectionInfoSource = new ConnectionInfo { Domain = _testDomain };
|
DefaultConnectionInfo.Instance.LoadFrom(_randomizedConnectionInfo);
|
||||||
DefaultConnectionInfo.Instance.LoadFrom(connectionInfoSource);
|
var valueInDestination = property.GetValue(DefaultConnectionInfo.Instance);
|
||||||
Assert.That(DefaultConnectionInfo.Instance.Domain, Is.EqualTo(_testDomain));
|
var valueInSource = property.GetValue(_randomizedConnectionInfo);
|
||||||
|
Assert.That(valueInDestination, Is.EqualTo(valueInSource));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[TestCaseSource(nameof(GetConnectionInfoProperties))]
|
||||||
public void SavingDefaultConnectionInfoExportsAllProperties()
|
public void SavingDefaultConnectionInfoExportsAllProperties(PropertyInfo property)
|
||||||
{
|
{
|
||||||
var saveTarget = new ConnectionInfo();
|
var saveTarget = new ConnectionInfo();
|
||||||
DefaultConnectionInfo.Instance.Domain = _testDomain;
|
var randomizedValue = property.GetValue(_randomizedConnectionInfo);
|
||||||
|
property.SetValue(DefaultConnectionInfo.Instance, randomizedValue);
|
||||||
DefaultConnectionInfo.Instance.SaveTo(saveTarget);
|
DefaultConnectionInfo.Instance.SaveTo(saveTarget);
|
||||||
Assert.That(saveTarget.Domain, Is.EqualTo(_testDomain));
|
var valueInDestination = property.GetValue(saveTarget);
|
||||||
|
var valueInSource = property.GetValue(DefaultConnectionInfo.Instance);
|
||||||
|
Assert.That(valueInDestination, Is.EqualTo(valueInSource));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[TestCaseSource(nameof(GetConnectionInfoProperties))]
|
||||||
public void CanSaveEnumValuesToString()
|
public void CanSaveDefaultConnectionToModelWithAllStringProperties(PropertyInfo property)
|
||||||
{
|
{
|
||||||
const ProtocolType targetProtocol = ProtocolType.RAW;
|
var saveTarget = new SerializableConnectionInfoAllPropertiesOfType<string>();
|
||||||
var saveTarget = new AllStringPropertySaveTarget();
|
|
||||||
DefaultConnectionInfo.Instance.Protocol = targetProtocol;
|
// randomize default connnection values to ensure we dont get false passing tests
|
||||||
|
var randomizedValue = property.GetValue(_randomizedConnectionInfo);
|
||||||
|
property.SetValue(DefaultConnectionInfo.Instance, randomizedValue);
|
||||||
|
|
||||||
DefaultConnectionInfo.Instance.SaveTo(saveTarget);
|
DefaultConnectionInfo.Instance.SaveTo(saveTarget);
|
||||||
Assert.That(saveTarget.Protocol, Is.EqualTo(targetProtocol.ToString()));
|
|
||||||
|
var valueInSource = property.GetValue(DefaultConnectionInfo.Instance).ToString();
|
||||||
|
var valueInDestination = saveTarget.GetType().GetProperty(property.Name).GetValue(saveTarget).ToString();
|
||||||
|
Assert.That(valueInDestination, Is.EqualTo(valueInSource));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
private static IEnumerable<PropertyInfo> GetConnectionInfoProperties()
|
||||||
public void CanSaveIntegerValuesToString()
|
|
||||||
{
|
{
|
||||||
const int targetValue = 123;
|
return new ConnectionInfo().GetSerializableProperties();
|
||||||
var saveTarget = new AllStringPropertySaveTarget();
|
|
||||||
DefaultConnectionInfo.Instance.RDPMinutesToIdleTimeout = targetValue;
|
|
||||||
DefaultConnectionInfo.Instance.SaveTo(saveTarget);
|
|
||||||
Assert.That(saveTarget.RDPMinutesToIdleTimeout, Is.EqualTo(targetValue.ToString()));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void CanSaveStringValuesToString()
|
|
||||||
{
|
|
||||||
const string targetName = "hello";
|
|
||||||
var saveTarget = new AllStringPropertySaveTarget();
|
|
||||||
DefaultConnectionInfo.Instance.Username = targetName;
|
|
||||||
DefaultConnectionInfo.Instance.SaveTo(saveTarget);
|
|
||||||
Assert.That(saveTarget.Username, Is.EqualTo(targetName));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private class AllStringPropertySaveTarget
|
|
||||||
{
|
|
||||||
public string Username { get; set; }
|
|
||||||
public string Protocol { get; set; }
|
|
||||||
public string RDPMinutesToIdleTimeout { get; set; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
using mRemoteNG.Connection;
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using mRemoteNG.Connection;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
|
||||||
@@ -6,28 +8,32 @@ namespace mRemoteNGTests.Connection
|
|||||||
{
|
{
|
||||||
public class DefaultConnectionInheritanceTests
|
public class DefaultConnectionInheritanceTests
|
||||||
{
|
{
|
||||||
[SetUp]
|
[TestCaseSource(nameof(GetInheritanceProperties))]
|
||||||
public void Setup()
|
public void LoadingDefaultInheritanceUpdatesAllProperties(PropertyInfo property)
|
||||||
{
|
|
||||||
DefaultConnectionInheritance.Instance.TurnOffInheritanceCompletely();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void LoadingDefaultInheritanceUpdatesAllProperties()
|
|
||||||
{
|
{
|
||||||
var inheritanceSource = new ConnectionInfoInheritance(new object(), true);
|
var inheritanceSource = new ConnectionInfoInheritance(new object(), true);
|
||||||
inheritanceSource.TurnOnInheritanceCompletely();
|
inheritanceSource.TurnOnInheritanceCompletely();
|
||||||
|
DefaultConnectionInheritance.Instance.TurnOffInheritanceCompletely();
|
||||||
|
|
||||||
DefaultConnectionInheritance.Instance.LoadFrom(inheritanceSource);
|
DefaultConnectionInheritance.Instance.LoadFrom(inheritanceSource);
|
||||||
Assert.That(DefaultConnectionInheritance.Instance.EverythingInherited, Is.True);
|
|
||||||
|
var valueInDestination = property.GetValue(DefaultConnectionInheritance.Instance);
|
||||||
|
var valueInSource = property.GetValue(inheritanceSource);
|
||||||
|
Assert.That(valueInDestination, Is.EqualTo(valueInSource));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[TestCaseSource(nameof(GetInheritanceProperties))]
|
||||||
public void SavingDefaultInheritanceExportsAllProperties()
|
public void SavingDefaultInheritanceExportsAllProperties(PropertyInfo property)
|
||||||
{
|
{
|
||||||
var inheritanceDestination = new ConnectionInfoInheritance(new object(), true);
|
var saveTarget = new ConnectionInfoInheritance(new object(), true);
|
||||||
DefaultConnectionInheritance.Instance.AutomaticResize = true;
|
saveTarget.TurnOffInheritanceCompletely();
|
||||||
DefaultConnectionInheritance.Instance.SaveTo(inheritanceDestination);
|
DefaultConnectionInheritance.Instance.TurnOnInheritanceCompletely();
|
||||||
Assert.That(inheritanceDestination.AutomaticResize, Is.True);
|
|
||||||
|
DefaultConnectionInheritance.Instance.SaveTo(saveTarget);
|
||||||
|
|
||||||
|
var valueInDestination = property.GetValue(saveTarget);
|
||||||
|
var valueInSource = property.GetValue(DefaultConnectionInheritance.Instance);
|
||||||
|
Assert.That(valueInDestination, Is.EqualTo(valueInSource));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -38,12 +44,20 @@ namespace mRemoteNGTests.Connection
|
|||||||
Assert.That(inheritanceInstance.Domain, Is.True);
|
Assert.That(inheritanceInstance.Domain, Is.True);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[TestCaseSource(nameof(GetInheritanceProperties))]
|
||||||
public void NewInheritanceInstancesCreatedWithAllDefaultInheritanceValues()
|
public void NewInheritanceInstancesCreatedWithAllDefaultInheritanceValues(PropertyInfo property)
|
||||||
{
|
{
|
||||||
DefaultConnectionInheritance.Instance.TurnOnInheritanceCompletely();
|
DefaultConnectionInheritance.Instance.TurnOnInheritanceCompletely();
|
||||||
var inheritanceInstance = new ConnectionInfoInheritance(new object());
|
var inheritanceInstance = new ConnectionInfoInheritance(new object());
|
||||||
Assert.That(inheritanceInstance.EverythingInherited, Is.True);
|
|
||||||
|
var valueInDestination = property.GetValue(inheritanceInstance);
|
||||||
|
var valueInSource = property.GetValue(DefaultConnectionInheritance.Instance);
|
||||||
|
Assert.That(valueInDestination, Is.EqualTo(valueInSource));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<PropertyInfo> GetInheritanceProperties()
|
||||||
|
{
|
||||||
|
return new ConnectionInfoInheritance(new object(), true).GetProperties();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using mRemoteNG.App;
|
using System.Collections.ObjectModel;
|
||||||
|
using mRemoteNG.App;
|
||||||
using mRemoteNG.Connection;
|
using mRemoteNG.Connection;
|
||||||
using mRemoteNG.Connection.Protocol;
|
using mRemoteNG.Connection.Protocol;
|
||||||
using mRemoteNG.Tools;
|
using mRemoteNG.Tools;
|
||||||
@@ -19,13 +20,13 @@ namespace mRemoteNGTests.Connection.Protocol
|
|||||||
TryIntegrate = true
|
TryIntegrate = true
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void CanStartExternalApp()
|
public void CanStartExternalApp()
|
||||||
{
|
{
|
||||||
SetExternalToolList(_extTool);
|
SetExternalToolList(_extTool);
|
||||||
var connectionInfo = new ConnectionInfo { ExtApp = _extTool.DisplayName };
|
var sut = new IntegratedProgram();
|
||||||
var sut = new IntegratedProgram(connectionInfo);
|
sut.InterfaceControl = BuildInterfaceControl("notepad", sut);
|
||||||
sut.InterfaceControl = BuildInterfaceControl(sut);
|
|
||||||
sut.Initialize();
|
sut.Initialize();
|
||||||
var appStarted = sut.Connect();
|
var appStarted = sut.Connect();
|
||||||
sut.Disconnect();
|
sut.Disconnect();
|
||||||
@@ -36,9 +37,8 @@ namespace mRemoteNGTests.Connection.Protocol
|
|||||||
public void ConnectingToExternalAppThatDoesntExistDoesNothing()
|
public void ConnectingToExternalAppThatDoesntExistDoesNothing()
|
||||||
{
|
{
|
||||||
SetExternalToolList(_extTool);
|
SetExternalToolList(_extTool);
|
||||||
var connectionInfo = new ConnectionInfo { ExtApp = "doesntExist" };
|
var sut = new IntegratedProgram();
|
||||||
var sut = new IntegratedProgram(connectionInfo);
|
sut.InterfaceControl = BuildInterfaceControl("doesntExist", sut);
|
||||||
sut.InterfaceControl = BuildInterfaceControl(sut);
|
|
||||||
var appInitialized = sut.Initialize();
|
var appInitialized = sut.Initialize();
|
||||||
Assert.That(appInitialized, Is.False);
|
Assert.That(appInitialized, Is.False);
|
||||||
}
|
}
|
||||||
@@ -48,10 +48,11 @@ namespace mRemoteNGTests.Connection.Protocol
|
|||||||
Runtime.ExternalToolsService.ExternalTools = new FullyObservableCollection<ExternalTool> {externalTool};
|
Runtime.ExternalToolsService.ExternalTools = new FullyObservableCollection<ExternalTool> {externalTool};
|
||||||
}
|
}
|
||||||
|
|
||||||
private InterfaceControl BuildInterfaceControl(ProtocolBase sut)
|
private InterfaceControl BuildInterfaceControl(string extAppName, ProtocolBase sut)
|
||||||
{
|
{
|
||||||
var connectionWindow = new ConnectionWindow(new DockContent());
|
var connectionWindow = new ConnectionWindow(new DockContent());
|
||||||
return new InterfaceControl(connectionWindow, sut);
|
var connectionInfo = new ConnectionInfo {ExtApp = extAppName};
|
||||||
|
return new InterfaceControl(connectionWindow, sut, connectionInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using mRemoteNG.Connection;
|
|
||||||
using mRemoteNG.Connection.Protocol;
|
using mRemoteNG.Connection.Protocol;
|
||||||
using mRemoteNG.Connection.Protocol.SSH;
|
using mRemoteNG.Connection.Protocol.SSH;
|
||||||
using mRemoteNG.Connection.Protocol.Telnet;
|
using mRemoteNG.Connection.Protocol.Telnet;
|
||||||
@@ -22,9 +21,9 @@ namespace mRemoteNGTests.Connection.Protocol
|
|||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
_protocolList = new ProtocolList();
|
_protocolList = new ProtocolList();
|
||||||
_protocol1 = new ProtocolTelnet(new ConnectionInfo());
|
_protocol1 = new ProtocolTelnet();
|
||||||
_protocol2 = new ProtocolSSH2(new ConnectionInfo());
|
_protocol2 = new ProtocolSSH2();
|
||||||
_protocol3 = new ProtocolVNC(new ConnectionInfo());
|
_protocol3 = new ProtocolVNC();
|
||||||
}
|
}
|
||||||
|
|
||||||
[TearDown]
|
[TearDown]
|
||||||
|
|||||||
18
mRemoteNGTests/Container/RootNodeInfoTests.cs
Normal file
18
mRemoteNGTests/Container/RootNodeInfoTests.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using mRemoteNG.Connection;
|
||||||
|
using mRemoteNG.Tree.Root;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace mRemoteNGTests.Container
|
||||||
|
{
|
||||||
|
public class RootNodeInfoTests
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void InheritanceIsDisabledForNodesDirectlyUnderRootNode()
|
||||||
|
{
|
||||||
|
var rootNode = new RootNodeInfo(RootNodeType.Connection);
|
||||||
|
var con1 = new ConnectionInfo { Inheritance = { Password = true } };
|
||||||
|
rootNode.AddChild(con1);
|
||||||
|
Assert.That(con1.Inheritance.Password, Is.False);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,8 @@
|
|||||||
using System.Linq;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Xml.Linq;
|
||||||
using mRemoteNG.Config.Serializers;
|
using mRemoteNG.Config.Serializers;
|
||||||
|
using mRemoteNG.Config.Serializers.Xml;
|
||||||
using mRemoteNG.Connection;
|
using mRemoteNG.Connection;
|
||||||
using mRemoteNG.Container;
|
using mRemoteNG.Container;
|
||||||
using mRemoteNG.Security;
|
using mRemoteNG.Security;
|
||||||
@@ -28,20 +31,19 @@ namespace mRemoteNGTests.IntegrationTests
|
|||||||
_originalModel.RootNodes.OfType<RootNodeInfo>().First().PasswordString.ConvertToSecureString(),
|
_originalModel.RootNodes.OfType<RootNodeInfo>().First().PasswordString.ConvertToSecureString(),
|
||||||
new SaveFilter());
|
new SaveFilter());
|
||||||
_serializer = new XmlConnectionsSerializer(cryptoProvider, nodeSerializer);
|
_serializer = new XmlConnectionsSerializer(cryptoProvider, nodeSerializer);
|
||||||
|
_deserializer = new XmlConnectionsDeserializer();
|
||||||
}
|
}
|
||||||
|
|
||||||
[TearDown]
|
[TearDown]
|
||||||
public void Teardown()
|
public void Teardown()
|
||||||
{
|
{
|
||||||
_serializer = null;
|
_serializer = null;
|
||||||
_deserializer = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void SerializeThenDeserialize()
|
public void SerializeThenDeserialize()
|
||||||
{
|
{
|
||||||
var serializedContent = _serializer.Serialize(_originalModel);
|
var serializedContent = _serializer.Serialize(_originalModel);
|
||||||
_deserializer = new XmlConnectionsDeserializer();
|
|
||||||
var deserializedModel = _deserializer.Deserialize(serializedContent);
|
var deserializedModel = _deserializer.Deserialize(serializedContent);
|
||||||
var nodeNamesFromDeserializedModel = deserializedModel.GetRecursiveChildList().Select(node => node.Name);
|
var nodeNamesFromDeserializedModel = deserializedModel.GetRecursiveChildList().Select(node => node.Name);
|
||||||
var nodeNamesFromOriginalModel = _originalModel.GetRecursiveChildList().Select(node => node.Name);
|
var nodeNamesFromOriginalModel = _originalModel.GetRecursiveChildList().Select(node => node.Name);
|
||||||
@@ -53,7 +55,6 @@ namespace mRemoteNGTests.IntegrationTests
|
|||||||
{
|
{
|
||||||
_serializer.UseFullEncryption = true;
|
_serializer.UseFullEncryption = true;
|
||||||
var serializedContent = _serializer.Serialize(_originalModel);
|
var serializedContent = _serializer.Serialize(_originalModel);
|
||||||
_deserializer = new XmlConnectionsDeserializer();
|
|
||||||
var deserializedModel = _deserializer.Deserialize(serializedContent);
|
var deserializedModel = _deserializer.Deserialize(serializedContent);
|
||||||
var nodeNamesFromDeserializedModel = deserializedModel.GetRecursiveChildList().Select(node => node.Name);
|
var nodeNamesFromDeserializedModel = deserializedModel.GetRecursiveChildList().Select(node => node.Name);
|
||||||
var nodeNamesFromOriginalModel = _originalModel.GetRecursiveChildList().Select(node => node.Name);
|
var nodeNamesFromOriginalModel = _originalModel.GetRecursiveChildList().Select(node => node.Name);
|
||||||
@@ -65,7 +66,6 @@ namespace mRemoteNGTests.IntegrationTests
|
|||||||
{
|
{
|
||||||
var originalConnectionInfo = new ConnectionInfo {Name = "con1", Description = "£°úg¶┬ä" };
|
var originalConnectionInfo = new ConnectionInfo {Name = "con1", Description = "£°úg¶┬ä" };
|
||||||
var serializedContent = _serializer.Serialize(originalConnectionInfo);
|
var serializedContent = _serializer.Serialize(originalConnectionInfo);
|
||||||
_deserializer = new XmlConnectionsDeserializer();
|
|
||||||
var deserializedModel = _deserializer.Deserialize(serializedContent);
|
var deserializedModel = _deserializer.Deserialize(serializedContent);
|
||||||
var deserializedConnectionInfo = deserializedModel.GetRecursiveChildList().First(node => node.Name == originalConnectionInfo.Name);
|
var deserializedConnectionInfo = deserializedModel.GetRecursiveChildList().First(node => node.Name == originalConnectionInfo.Name);
|
||||||
Assert.That(deserializedConnectionInfo.Description, Is.EqualTo(originalConnectionInfo.Description));
|
Assert.That(deserializedConnectionInfo.Description, Is.EqualTo(originalConnectionInfo.Description));
|
||||||
@@ -83,13 +83,26 @@ namespace mRemoteNGTests.IntegrationTests
|
|||||||
new SaveFilter());
|
new SaveFilter());
|
||||||
_serializer = new XmlConnectionsSerializer(cryptoProvider, nodeSerializer);
|
_serializer = new XmlConnectionsSerializer(cryptoProvider, nodeSerializer);
|
||||||
var serializedContent = _serializer.Serialize(_originalModel);
|
var serializedContent = _serializer.Serialize(_originalModel);
|
||||||
_deserializer = new XmlConnectionsDeserializer();
|
|
||||||
var deserializedModel = _deserializer.Deserialize(serializedContent);
|
var deserializedModel = _deserializer.Deserialize(serializedContent);
|
||||||
var nodeNamesFromDeserializedModel = deserializedModel.GetRecursiveChildList().Select(node => node.Name);
|
var nodeNamesFromDeserializedModel = deserializedModel.GetRecursiveChildList().Select(node => node.Name);
|
||||||
var nodeNamesFromOriginalModel = _originalModel.GetRecursiveChildList().Select(node => node.Name);
|
var nodeNamesFromOriginalModel = _originalModel.GetRecursiveChildList().Select(node => node.Name);
|
||||||
Assert.That(nodeNamesFromDeserializedModel, Is.EquivalentTo(nodeNamesFromOriginalModel));
|
Assert.That(nodeNamesFromDeserializedModel, Is.EquivalentTo(nodeNamesFromOriginalModel));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void GuidCreatedIfNonExistedInXml()
|
||||||
|
{
|
||||||
|
var originalConnectionInfo = new ConnectionInfo { Name = "con1" };
|
||||||
|
var serializedContent = _serializer.Serialize(originalConnectionInfo);
|
||||||
|
|
||||||
|
// remove GUID from connection xml
|
||||||
|
serializedContent = serializedContent.Replace(originalConnectionInfo.ConstantID, "");
|
||||||
|
|
||||||
|
var deserializedModel = _deserializer.Deserialize(serializedContent);
|
||||||
|
var deserializedConnectionInfo = deserializedModel.GetRecursiveChildList().First(node => node.Name == originalConnectionInfo.Name);
|
||||||
|
Assert.That(Guid.TryParse(deserializedConnectionInfo.ConstantID, out var guid));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private ConnectionTreeModel SetupConnectionTreeModel()
|
private ConnectionTreeModel SetupConnectionTreeModel()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -34,8 +34,9 @@
|
|||||||
|
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
using NUnit.Extensions.Forms;
|
||||||
|
|
||||||
namespace NUnit.Extensions.Forms
|
namespace mRemoteNGTests
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A ControlTester for testing List Views.
|
/// A ControlTester for testing List Views.
|
||||||
|
|||||||
52
mRemoteNGTests/Properties/Resources.Designer.cs
generated
52
mRemoteNGTests/Properties/Resources.Designer.cs
generated
@@ -298,6 +298,58 @@ namespace mRemoteNGTests.Properties {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to <?xml version="1.0" encoding="utf-8"?>
|
||||||
|
///<RDCMan programVersion="2.7" schemaVersion="3">
|
||||||
|
/// <file>
|
||||||
|
/// <credentialsProfiles />
|
||||||
|
/// <properties>
|
||||||
|
/// <expanded>True</expanded>
|
||||||
|
/// <name>test_RDCMan_connections</name>
|
||||||
|
/// </properties>
|
||||||
|
/// <smartGroup>
|
||||||
|
/// <properties>
|
||||||
|
/// <expanded>False</expanded>
|
||||||
|
/// <name>AllServers</name>
|
||||||
|
/// </properties>
|
||||||
|
/// <ruleGroup operator="All">
|
||||||
|
/// <rule>
|
||||||
|
/// <property>DisplayName</property>
|
||||||
|
/// <operator>Matches</operator>
|
||||||
|
/// [rest of string was truncated]";.
|
||||||
|
/// </summary>
|
||||||
|
internal static string test_rdcman_v2_7_schema3_empty_values {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("test_rdcman_v2_7_schema3_empty_values", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Looks up a localized string similar to <?xml version="1.0" encoding="utf-8"?>
|
||||||
|
///<RDCMan programVersion="2.7" schemaVersion="3">
|
||||||
|
/// <file>
|
||||||
|
/// <credentialsProfiles />
|
||||||
|
/// <properties>
|
||||||
|
/// <expanded>True</expanded>
|
||||||
|
/// <name>test_RDCMan_connections</name>
|
||||||
|
/// </properties>
|
||||||
|
/// <smartGroup>
|
||||||
|
/// <properties>
|
||||||
|
/// <expanded>False</expanded>
|
||||||
|
/// <name>AllServers</name>
|
||||||
|
/// </properties>
|
||||||
|
/// <ruleGroup operator="All">
|
||||||
|
/// <rule>
|
||||||
|
/// <property>DisplayName</property>
|
||||||
|
/// <operator>Matches</operator>
|
||||||
|
/// [rest of string was truncated]";.
|
||||||
|
/// </summary>
|
||||||
|
internal static string test_rdcman_v2_7_schema3_null_values {
|
||||||
|
get {
|
||||||
|
return ResourceManager.GetString("test_rdcman_v2_7_schema3_null_values", resourceCulture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Looks up a localized string similar to screen mode id:i:1
|
/// Looks up a localized string similar to screen mode id:i:1
|
||||||
///use multimon:i:0
|
///use multimon:i:0
|
||||||
|
|||||||
@@ -172,6 +172,12 @@
|
|||||||
<data name="test_rdcman_v2_7_schema3" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
<data name="test_rdcman_v2_7_schema3" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
<value>..\Resources\test_RDCMan_v2_7_schema3.rdg;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
<value>..\Resources\test_RDCMan_v2_7_schema3.rdg;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="test_rdcman_v2_7_schema3_empty_values" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
|
<value>..\Resources\test_rdcman_v2_7_schema3_empty_values.rdg;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
||||||
|
</data>
|
||||||
|
<data name="test_rdcman_v2_7_schema3_null_values" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
|
<value>..\Resources\test_rdcman_v2_7_schema3_null_values.rdg;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
|
||||||
|
</data>
|
||||||
<data name="test_remotedesktopconnection_rdp" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
<data name="test_remotedesktopconnection_rdp" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
<value>..\Resources\test_remotedesktopconnection.rdp;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16</value>
|
<value>..\Resources\test_remotedesktopconnection.rdp;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-16</value>
|
||||||
</data>
|
</data>
|
||||||
|
|||||||
@@ -0,0 +1,95 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RDCMan programVersion="2.7" schemaVersion="3">
|
||||||
|
<file>
|
||||||
|
<credentialsProfiles />
|
||||||
|
<properties>
|
||||||
|
<expanded>True</expanded>
|
||||||
|
<name>test_RDCMan_connections</name>
|
||||||
|
</properties>
|
||||||
|
<smartGroup>
|
||||||
|
<properties>
|
||||||
|
<expanded>False</expanded>
|
||||||
|
<name>AllServers</name>
|
||||||
|
</properties>
|
||||||
|
<ruleGroup operator="All">
|
||||||
|
<rule>
|
||||||
|
<property>DisplayName</property>
|
||||||
|
<operator>Matches</operator>
|
||||||
|
<value>server</value>
|
||||||
|
</rule>
|
||||||
|
</ruleGroup>
|
||||||
|
</smartGroup>
|
||||||
|
<group>
|
||||||
|
<properties>
|
||||||
|
<expanded>True</expanded>
|
||||||
|
<name>Group1</name>
|
||||||
|
</properties>
|
||||||
|
<server>
|
||||||
|
<properties>
|
||||||
|
<displayName></displayName>
|
||||||
|
<name></name>
|
||||||
|
<comment></comment>
|
||||||
|
</properties>
|
||||||
|
<logonCredentials inherit="None">
|
||||||
|
<profileName scope="Local"></profileName>
|
||||||
|
<userName></userName>
|
||||||
|
<password></password>
|
||||||
|
<domain></domain>
|
||||||
|
</logonCredentials>
|
||||||
|
<connectionSettings inherit="None">
|
||||||
|
<connectToConsole></connectToConsole>
|
||||||
|
<startProgram />
|
||||||
|
<workingDir />
|
||||||
|
<port></port>
|
||||||
|
<loadBalanceInfo />
|
||||||
|
</connectionSettings>
|
||||||
|
<gatewaySettings inherit="None">
|
||||||
|
<enabled></enabled>
|
||||||
|
<hostName></hostName>
|
||||||
|
<logonMethod></logonMethod>
|
||||||
|
<localBypass></localBypass>
|
||||||
|
<credSharing></credSharing>
|
||||||
|
<profileName scope="Local"></profileName>
|
||||||
|
<userName></userName>
|
||||||
|
<password />
|
||||||
|
<domain></domain>
|
||||||
|
</gatewaySettings>
|
||||||
|
<remoteDesktop inherit="None">
|
||||||
|
<sameSizeAsClientArea></sameSizeAsClientArea>
|
||||||
|
<fullScreen></fullScreen>
|
||||||
|
<colorDepth></colorDepth>
|
||||||
|
</remoteDesktop>
|
||||||
|
<localResources inherit="None">
|
||||||
|
<audioRedirection></audioRedirection>
|
||||||
|
<audioRedirectionQuality></audioRedirectionQuality>
|
||||||
|
<audioCaptureRedirection></audioCaptureRedirection>
|
||||||
|
<keyboardHook></keyboardHook>
|
||||||
|
<redirectClipboard></redirectClipboard>
|
||||||
|
<redirectDrives></redirectDrives>
|
||||||
|
<redirectDrivesList>
|
||||||
|
<item></item>
|
||||||
|
<item></item>
|
||||||
|
<item></item>
|
||||||
|
<item></item>
|
||||||
|
<item></item>
|
||||||
|
</redirectDrivesList>
|
||||||
|
<redirectPrinters></redirectPrinters>
|
||||||
|
<redirectPorts></redirectPorts>
|
||||||
|
<redirectSmartCards></redirectSmartCards>
|
||||||
|
<redirectPnpDevices></redirectPnpDevices>
|
||||||
|
</localResources>
|
||||||
|
<displaySettings inherit="None">
|
||||||
|
<thumbnailScale></thumbnailScale>
|
||||||
|
<smartSizeDockedWindows></smartSizeDockedWindows>
|
||||||
|
<smartSizeUndockedWindows></smartSizeUndockedWindows>
|
||||||
|
</displaySettings>
|
||||||
|
<securitySettings inherit="None">
|
||||||
|
<authentication></authentication>
|
||||||
|
</securitySettings>
|
||||||
|
</server>
|
||||||
|
</group>
|
||||||
|
</file>
|
||||||
|
<connected />
|
||||||
|
<favorites />
|
||||||
|
<recentlyUsed />
|
||||||
|
</RDCMan>
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RDCMan programVersion="2.7" schemaVersion="3">
|
||||||
|
<file>
|
||||||
|
<credentialsProfiles />
|
||||||
|
<properties>
|
||||||
|
<expanded>True</expanded>
|
||||||
|
<name>test_RDCMan_connections</name>
|
||||||
|
</properties>
|
||||||
|
<smartGroup>
|
||||||
|
<properties>
|
||||||
|
<expanded>False</expanded>
|
||||||
|
<name>AllServers</name>
|
||||||
|
</properties>
|
||||||
|
<ruleGroup operator="All">
|
||||||
|
<rule>
|
||||||
|
<property>DisplayName</property>
|
||||||
|
<operator>Matches</operator>
|
||||||
|
<value>server</value>
|
||||||
|
</rule>
|
||||||
|
</ruleGroup>
|
||||||
|
</smartGroup>
|
||||||
|
<group>
|
||||||
|
<properties>
|
||||||
|
<expanded>True</expanded>
|
||||||
|
<name>Group1</name>
|
||||||
|
</properties>
|
||||||
|
<server>
|
||||||
|
<properties>
|
||||||
|
</properties>
|
||||||
|
<logonCredentials inherit="None">
|
||||||
|
</logonCredentials>
|
||||||
|
<connectionSettings inherit="None">
|
||||||
|
</connectionSettings>
|
||||||
|
<gatewaySettings inherit="None">
|
||||||
|
</gatewaySettings>
|
||||||
|
<remoteDesktop inherit="None">
|
||||||
|
</remoteDesktop>
|
||||||
|
<localResources inherit="None">
|
||||||
|
</localResources>
|
||||||
|
<displaySettings inherit="None">
|
||||||
|
</displaySettings>
|
||||||
|
<securitySettings inherit="None">
|
||||||
|
</securitySettings>
|
||||||
|
</server>
|
||||||
|
</group>
|
||||||
|
</file>
|
||||||
|
<connected />
|
||||||
|
<favorites />
|
||||||
|
<recentlyUsed />
|
||||||
|
</RDCMan>
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
using mRemoteNG.Security;
|
using mRemoteNG.Security;
|
||||||
using mRemoteNG.Security.Authentication;
|
using mRemoteNG.Security.Authentication;
|
||||||
using mRemoteNG.Security.SymmetricEncryption;
|
using mRemoteNG.Security.SymmetricEncryption;
|
||||||
|
using mRemoteNG.Tools;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
|
||||||
@@ -9,35 +10,31 @@ namespace mRemoteNGTests.Security.Authentication
|
|||||||
{
|
{
|
||||||
public class PasswordAuthenticatorTests
|
public class PasswordAuthenticatorTests
|
||||||
{
|
{
|
||||||
private PasswordAuthenticator _authenticator;
|
private ICryptographyProvider _cryptographyProvider;
|
||||||
|
private string _cipherText;
|
||||||
private readonly SecureString _correctPassword = "9theCorrectPass#5".ConvertToSecureString();
|
private readonly SecureString _correctPassword = "9theCorrectPass#5".ConvertToSecureString();
|
||||||
private readonly SecureString _wrongPassword = "wrongPassword".ConvertToSecureString();
|
private readonly SecureString _wrongPassword = "wrongPassword".ConvertToSecureString();
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
var cryptoProvider = new AeadCryptographyProvider {KeyDerivationIterations = 10000};
|
_cryptographyProvider = new AeadCryptographyProvider {KeyDerivationIterations = 10000};
|
||||||
const string cipherText = "MPELiwk7+xeNlruIyt5uxTvVB+/RLVoLdUGnwY4CWCqwKe7T2IBwWo4oaKum5hdv7447g5m2nZsYPrfARSlotQB4r1KZQg==";
|
_cipherText = "MPELiwk7+xeNlruIyt5uxTvVB+/RLVoLdUGnwY4CWCqwKe7T2IBwWo4oaKum5hdv7447g5m2nZsYPrfARSlotQB4r1KZQg==";
|
||||||
_authenticator = new PasswordAuthenticator(cryptoProvider, cipherText);
|
|
||||||
}
|
|
||||||
|
|
||||||
[TearDown]
|
|
||||||
public void Teardown()
|
|
||||||
{
|
|
||||||
_authenticator = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void AuthenticatingWithCorrectPasswordReturnsTrue()
|
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);
|
Assert.That(authenticated);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void AuthenticatingWithWrongPasswordReturnsFalse()
|
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);
|
Assert.That(!authenticated);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,12 +42,15 @@ namespace mRemoteNGTests.Security.Authentication
|
|||||||
public void AuthenticationRequestorIsCalledWhenInitialPasswordIsWrong()
|
public void AuthenticationRequestorIsCalledWhenInitialPasswordIsWrong()
|
||||||
{
|
{
|
||||||
var wasCalled = false;
|
var wasCalled = false;
|
||||||
_authenticator.AuthenticationRequestor = () =>
|
|
||||||
|
Optional<SecureString> AuthenticationRequestor()
|
||||||
{
|
{
|
||||||
wasCalled = true;
|
wasCalled = true;
|
||||||
return _correctPassword;
|
return _correctPassword;
|
||||||
};
|
}
|
||||||
_authenticator.Authenticate(_wrongPassword);
|
|
||||||
|
var authenticator = new PasswordAuthenticator(_cryptographyProvider, _cipherText, AuthenticationRequestor);
|
||||||
|
authenticator.Authenticate(_wrongPassword);
|
||||||
Assert.That(wasCalled);
|
Assert.That(wasCalled);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,28 +58,30 @@ namespace mRemoteNGTests.Security.Authentication
|
|||||||
public void AuthenticationRequestorNotCalledWhenInitialPasswordIsCorrect()
|
public void AuthenticationRequestorNotCalledWhenInitialPasswordIsCorrect()
|
||||||
{
|
{
|
||||||
var wasCalled = false;
|
var wasCalled = false;
|
||||||
_authenticator.AuthenticationRequestor = () =>
|
Optional<SecureString> AuthenticationRequestor()
|
||||||
{
|
{
|
||||||
wasCalled = true;
|
wasCalled = true;
|
||||||
return _correctPassword;
|
return _correctPassword;
|
||||||
};
|
}
|
||||||
_authenticator.Authenticate(_correctPassword);
|
|
||||||
|
var authenticator = new PasswordAuthenticator(_cryptographyProvider, _cipherText, AuthenticationRequestor);
|
||||||
|
authenticator.Authenticate(_correctPassword);
|
||||||
Assert.That(!wasCalled);
|
Assert.That(!wasCalled);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void ProvidingCorrectPasswordToTheAuthenticationRequestorReturnsTrue()
|
public void ProvidingCorrectPasswordToTheAuthenticationRequestorReturnsTrue()
|
||||||
{
|
{
|
||||||
_authenticator.AuthenticationRequestor = () => _correctPassword;
|
var authenticator = new PasswordAuthenticator(_cryptographyProvider, _cipherText, () => _correctPassword);
|
||||||
var authenticated = _authenticator.Authenticate(_wrongPassword);
|
var authenticated = authenticator.Authenticate(_wrongPassword);
|
||||||
Assert.That(authenticated);
|
Assert.That(authenticated);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void AuthenticationFailsWhenAuthenticationRequestorGivenEmptyPassword()
|
public void AuthenticationFailsWhenAuthenticationRequestorGivenEmptyPassword()
|
||||||
{
|
{
|
||||||
_authenticator.AuthenticationRequestor = () => new SecureString();
|
var authenticator = new PasswordAuthenticator(_cryptographyProvider, _cipherText, () => new SecureString());
|
||||||
var authenticated = _authenticator.Authenticate(_wrongPassword);
|
var authenticated = authenticator.Authenticate(_wrongPassword);
|
||||||
Assert.That(!authenticated);
|
Assert.That(!authenticated);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,27 +89,34 @@ namespace mRemoteNGTests.Security.Authentication
|
|||||||
public void AuthenticatorRespectsMaxAttempts()
|
public void AuthenticatorRespectsMaxAttempts()
|
||||||
{
|
{
|
||||||
var authAttempts = 0;
|
var authAttempts = 0;
|
||||||
_authenticator.AuthenticationRequestor = () =>
|
Optional<SecureString> AuthenticationRequestor()
|
||||||
{
|
{
|
||||||
authAttempts++;
|
authAttempts++;
|
||||||
return _wrongPassword;
|
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]
|
[Test]
|
||||||
public void AuthenticatorRespectsMaxAttemptsCustomValue()
|
public void AuthenticatorRespectsMaxAttemptsCustomValue()
|
||||||
{
|
{
|
||||||
const int customMaxAttempts = 5;
|
const int customMaxAttempts = 5;
|
||||||
_authenticator.MaxAttempts = customMaxAttempts;
|
|
||||||
var authAttempts = 0;
|
var authAttempts = 0;
|
||||||
_authenticator.AuthenticationRequestor = () =>
|
Optional<SecureString> AuthenticationRequestor()
|
||||||
{
|
{
|
||||||
authAttempts++;
|
authAttempts++;
|
||||||
return _wrongPassword;
|
return _wrongPassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
var authenticator =
|
||||||
|
new PasswordAuthenticator(_cryptographyProvider, _cipherText, AuthenticationRequestor)
|
||||||
|
{
|
||||||
|
MaxAttempts = customMaxAttempts
|
||||||
};
|
};
|
||||||
_authenticator.Authenticate(_wrongPassword);
|
authenticator.Authenticate(_wrongPassword);
|
||||||
Assert.That(authAttempts == customMaxAttempts);
|
Assert.That(authAttempts == customMaxAttempts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
132
mRemoteNGTests/TestHelpers/ConnectionInfoHelpers.cs
Normal file
132
mRemoteNGTests/TestHelpers/ConnectionInfoHelpers.cs
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
using System;
|
||||||
|
using mRemoteNG.Connection;
|
||||||
|
using mRemoteNG.Connection.Protocol;
|
||||||
|
using mRemoteNG.Connection.Protocol.Http;
|
||||||
|
using mRemoteNG.Connection.Protocol.ICA;
|
||||||
|
using mRemoteNG.Connection.Protocol.RDP;
|
||||||
|
using mRemoteNG.Connection.Protocol.VNC;
|
||||||
|
|
||||||
|
namespace mRemoteNGTests.TestHelpers
|
||||||
|
{
|
||||||
|
internal static class ConnectionInfoHelpers
|
||||||
|
{
|
||||||
|
private static readonly Random _random = new Random();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a <see cref="ConnectionInfo"/> object with randomized
|
||||||
|
/// values in all fields.
|
||||||
|
/// </summary>
|
||||||
|
internal static ConnectionInfo GetRandomizedConnectionInfo(bool randomizeInheritance = false)
|
||||||
|
{
|
||||||
|
var connectionInfo = new ConnectionInfo
|
||||||
|
{
|
||||||
|
// string types
|
||||||
|
Name = RandomString(),
|
||||||
|
Hostname = RandomString(),
|
||||||
|
Description = RandomString(),
|
||||||
|
Domain = RandomString(),
|
||||||
|
ExtApp = RandomString(),
|
||||||
|
Icon = RandomString(),
|
||||||
|
LoadBalanceInfo = RandomString(),
|
||||||
|
MacAddress = RandomString(),
|
||||||
|
Panel = RandomString(),
|
||||||
|
Password = RandomString(),
|
||||||
|
PostExtApp = RandomString(),
|
||||||
|
PreExtApp = RandomString(),
|
||||||
|
PuttySession = RandomString(),
|
||||||
|
RDGatewayHostname = RandomString(),
|
||||||
|
RDGatewayUsername = RandomString(),
|
||||||
|
RDGatewayDomain = RandomString(),
|
||||||
|
RDGatewayPassword = RandomString(),
|
||||||
|
UserField = RandomString(),
|
||||||
|
Username = RandomString(),
|
||||||
|
VNCProxyIP = RandomString(),
|
||||||
|
VNCProxyPassword = RandomString(),
|
||||||
|
VNCProxyUsername = RandomString(),
|
||||||
|
|
||||||
|
// bool types
|
||||||
|
AutomaticResize = RandomBool(),
|
||||||
|
CacheBitmaps = RandomBool(),
|
||||||
|
DisplayThemes = RandomBool(),
|
||||||
|
DisplayWallpaper = RandomBool(),
|
||||||
|
EnableDesktopComposition = RandomBool(),
|
||||||
|
EnableFontSmoothing = RandomBool(),
|
||||||
|
IsContainer = RandomBool(),
|
||||||
|
IsDefault = RandomBool(),
|
||||||
|
IsQuickConnect = RandomBool(),
|
||||||
|
PleaseConnect = RandomBool(),
|
||||||
|
RDPAlertIdleTimeout = RandomBool(),
|
||||||
|
RedirectDiskDrives = RandomBool(),
|
||||||
|
RedirectKeys = RandomBool(),
|
||||||
|
RedirectPorts = RandomBool(),
|
||||||
|
RedirectPrinters = RandomBool(),
|
||||||
|
RedirectSmartCards = RandomBool(),
|
||||||
|
UseConsoleSession = RandomBool(),
|
||||||
|
UseCredSsp = RandomBool(),
|
||||||
|
VNCViewOnly = RandomBool(),
|
||||||
|
|
||||||
|
// ints
|
||||||
|
Port = RandomInt(),
|
||||||
|
RDPMinutesToIdleTimeout = RandomInt(),
|
||||||
|
VNCProxyPort = RandomInt(),
|
||||||
|
|
||||||
|
// enums
|
||||||
|
Colors = RandomEnum<RdpProtocol.RDPColors>(),
|
||||||
|
ICAEncryptionStrength = RandomEnum<IcaProtocol.EncryptionStrength> (),
|
||||||
|
Protocol = RandomEnum<ProtocolType>(),
|
||||||
|
RDGatewayUsageMethod = RandomEnum<RdpProtocol.RDGatewayUsageMethod>(),
|
||||||
|
RDGatewayUseConnectionCredentials = RandomEnum<RdpProtocol.RDGatewayUseConnectionCredentials>(),
|
||||||
|
RDPAuthenticationLevel = RandomEnum<RdpProtocol.AuthenticationLevel>(),
|
||||||
|
RedirectSound = RandomEnum<RdpProtocol.RDPSounds>(),
|
||||||
|
RenderingEngine = RandomEnum<HTTPBase.RenderingEngine>(),
|
||||||
|
Resolution = RandomEnum<RdpProtocol.RDPResolutions>(),
|
||||||
|
SoundQuality = RandomEnum<RdpProtocol.RDPSoundQuality>(),
|
||||||
|
VNCAuthMode = RandomEnum<ProtocolVNC.AuthMode>(),
|
||||||
|
VNCColors = RandomEnum<ProtocolVNC.Colors>(),
|
||||||
|
VNCCompression = RandomEnum<ProtocolVNC.Compression>(),
|
||||||
|
VNCEncoding = RandomEnum<ProtocolVNC.Encoding>(),
|
||||||
|
VNCProxyType = RandomEnum<ProtocolVNC.ProxyType>(),
|
||||||
|
VNCSmartSizeMode = RandomEnum<ProtocolVNC.SmartSizeMode>(),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (randomizeInheritance)
|
||||||
|
connectionInfo.Inheritance = GetRandomizedInheritance(connectionInfo);
|
||||||
|
|
||||||
|
return connectionInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static ConnectionInfoInheritance GetRandomizedInheritance(ConnectionInfo parent)
|
||||||
|
{
|
||||||
|
var inheritance = new ConnectionInfoInheritance(parent, true);
|
||||||
|
foreach (var property in inheritance.GetProperties())
|
||||||
|
{
|
||||||
|
property.SetValue(inheritance, RandomBool());
|
||||||
|
}
|
||||||
|
return inheritance;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static string RandomString()
|
||||||
|
{
|
||||||
|
return Guid.NewGuid().ToString("N");
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static bool RandomBool()
|
||||||
|
{
|
||||||
|
return _random.Next() % 2 == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static int RandomInt()
|
||||||
|
{
|
||||||
|
return _random.Next();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static T RandomEnum<T>() where T : struct, IConvertible
|
||||||
|
{
|
||||||
|
if (!typeof(T).IsEnum)
|
||||||
|
throw new ArgumentException("T must be an enum");
|
||||||
|
|
||||||
|
var values = Enum.GetValues(typeof(T));
|
||||||
|
return (T)values.GetValue(_random.Next(values.Length));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,17 +7,52 @@ namespace mRemoteNGTests.TestHelpers
|
|||||||
{
|
{
|
||||||
public class ConnectionTreeModelBuilder
|
public class ConnectionTreeModelBuilder
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Builds a tree which looks like:
|
||||||
|
/// Root
|
||||||
|
/// |- folder1
|
||||||
|
/// | |- con1
|
||||||
|
/// |- con2
|
||||||
|
/// |- folder2
|
||||||
|
/// |- folder3
|
||||||
|
/// |- con3
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
public ConnectionTreeModel Build()
|
public ConnectionTreeModel Build()
|
||||||
{
|
{
|
||||||
var model = new ConnectionTreeModel();
|
var model = new ConnectionTreeModel();
|
||||||
var root = new RootNodeInfo(RootNodeType.Connection);
|
var root = new RootNodeInfo(RootNodeType.Connection);
|
||||||
var folder1 = new ContainerInfo { Name = "folder1", Username = "user1", Domain = "domain1", Password = "password1" };
|
var folder1 = new ContainerInfo { Name = "folder1", Username = "user1", Domain = "domain1", Password = "password1" };
|
||||||
|
var folder2 = new ContainerInfo { Name = "folder2", Username = "user2", Domain = "domain2", Password = "password2" };
|
||||||
|
var folder3 = new ContainerInfo
|
||||||
|
{
|
||||||
|
Name = "folder3",
|
||||||
|
Inheritance =
|
||||||
|
{
|
||||||
|
Username = true,
|
||||||
|
Domain = true,
|
||||||
|
Password = true
|
||||||
|
}
|
||||||
|
};
|
||||||
var con1 = new ConnectionInfo { Name = "Con1", Username = "user1", Domain = "domain1", Password = "password1" };
|
var con1 = new ConnectionInfo { Name = "Con1", Username = "user1", Domain = "domain1", Password = "password1" };
|
||||||
var con2 = new ConnectionInfo { Name = "Con2", Username = "user2", Domain = "domain2", Password = "password2" };
|
var con2 = new ConnectionInfo { Name = "Con2", Username = "user2", Domain = "domain2", Password = "password2" };
|
||||||
|
var con3 = new ContainerInfo
|
||||||
|
{
|
||||||
|
Name = "con3",
|
||||||
|
Inheritance =
|
||||||
|
{
|
||||||
|
Username = true,
|
||||||
|
Domain = true,
|
||||||
|
Password = true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
root.AddChild(folder1);
|
root.AddChild(folder1);
|
||||||
root.AddChild(con2);
|
root.AddChild(con2);
|
||||||
folder1.AddChild(con1);
|
folder1.AddChild(con1);
|
||||||
|
root.AddChild(folder2);
|
||||||
|
folder2.AddChild(folder3);
|
||||||
|
folder3.AddChild(con3);
|
||||||
model.AddRootNode(root);
|
model.AddRootNode(root);
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
|
using mRemoteNG.Tools;
|
||||||
|
|
||||||
namespace mRemoteNGTests.TestHelpers
|
namespace mRemoteNGTests.TestHelpers
|
||||||
{
|
{
|
||||||
@@ -18,9 +19,17 @@ namespace mRemoteNGTests.TestHelpers
|
|||||||
File.Delete(file);
|
File.Delete(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string NewTempFilePath()
|
public static void DeleteDirectory(string directory)
|
||||||
|
{
|
||||||
|
if (Directory.Exists(directory))
|
||||||
|
Directory.Delete(directory, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string NewTempFilePath(string extension = "")
|
||||||
{
|
{
|
||||||
var newPath = Path.Combine(GetTestSpecificTempDirectory(), Path.GetRandomFileName());
|
var newPath = Path.Combine(GetTestSpecificTempDirectory(), Path.GetRandomFileName());
|
||||||
|
if (!string.IsNullOrWhiteSpace(extension))
|
||||||
|
newPath = newPath + extension;
|
||||||
var folderPath = Path.GetDirectoryName(newPath);
|
var folderPath = Path.GetDirectoryName(newPath);
|
||||||
if (!Directory.Exists(folderPath))
|
if (!Directory.Exists(folderPath))
|
||||||
Directory.CreateDirectory(folderPath);
|
Directory.CreateDirectory(folderPath);
|
||||||
@@ -35,5 +44,15 @@ namespace mRemoteNGTests.TestHelpers
|
|||||||
{
|
{
|
||||||
return Path.Combine(Path.GetTempPath(), "mRemoteNGTests", Path.GetRandomFileName());
|
return Path.Combine(Path.GetTempPath(), "mRemoteNGTests", Path.GetRandomFileName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static DisposableAction DisposableTempFile(out string filePath, string extension = "")
|
||||||
|
{
|
||||||
|
var file = NewTempFilePath(extension);
|
||||||
|
filePath = file;
|
||||||
|
File.AppendAllText(file, "");
|
||||||
|
return new DisposableAction(
|
||||||
|
() => {},
|
||||||
|
() => DeleteDirectory(Path.GetDirectoryName(file)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
namespace mRemoteNGTests.TestHelpers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A ConnectionInfo that has only the serializable properties as string types.
|
||||||
|
/// Only used for testing.
|
||||||
|
/// </summary>
|
||||||
|
internal class SerializableConnectionInfoAllPropertiesOfType<TType>
|
||||||
|
{
|
||||||
|
public TType Description { get; set; }
|
||||||
|
public TType Icon { get; set; }
|
||||||
|
public TType Panel { get; set; }
|
||||||
|
public TType Username { get; set; }
|
||||||
|
public TType Password { get; set; }
|
||||||
|
public TType Domain { get; set; }
|
||||||
|
public TType Protocol { get; set; }
|
||||||
|
public TType ExtApp { get; set; }
|
||||||
|
public TType PuttySession { get; set; }
|
||||||
|
public TType ICAEncryptionStrength { get; set; }
|
||||||
|
public TType UseConsoleSession { get; set; }
|
||||||
|
public TType RDPAuthenticationLevel { get; set; }
|
||||||
|
public TType RDPMinutesToIdleTimeout { get; set; }
|
||||||
|
public TType RDPAlertIdleTimeout { get; set; }
|
||||||
|
public TType LoadBalanceInfo { get; set; }
|
||||||
|
public TType RenderingEngine { get; set; }
|
||||||
|
public TType UseCredSsp { get; set; }
|
||||||
|
public TType RDGatewayUsageMethod { get; set; }
|
||||||
|
public TType RDGatewayHostname { get; set; }
|
||||||
|
public TType RDGatewayUseConnectionCredentials { get; set; }
|
||||||
|
public TType RDGatewayUsername { get; set; }
|
||||||
|
public TType RDGatewayPassword { get; set; }
|
||||||
|
public TType RDGatewayDomain { get; set; }
|
||||||
|
public TType Resolution { get; set; }
|
||||||
|
public TType AutomaticResize { get; set; }
|
||||||
|
public TType Colors { get; set; }
|
||||||
|
public TType CacheBitmaps { get; set; }
|
||||||
|
public TType DisplayWallpaper { get; set; }
|
||||||
|
public TType DisplayThemes { get; set; }
|
||||||
|
public TType EnableFontSmoothing { get; set; }
|
||||||
|
public TType EnableDesktopComposition { get; set; }
|
||||||
|
public TType RedirectKeys { get; set; }
|
||||||
|
public TType RedirectDiskDrives { get; set; }
|
||||||
|
public TType RedirectPrinters { get; set; }
|
||||||
|
public TType RedirectPorts { get; set; }
|
||||||
|
public TType RedirectSmartCards { get; set; }
|
||||||
|
public TType RedirectSound { get; set; }
|
||||||
|
public TType SoundQuality { get; set; }
|
||||||
|
public TType PreExtApp { get; set; }
|
||||||
|
public TType PostExtApp { get; set; }
|
||||||
|
public TType MacAddress { get; set; }
|
||||||
|
public TType UserField { get; set; }
|
||||||
|
public TType VNCCompression { get; set; }
|
||||||
|
public TType VNCEncoding { get; set; }
|
||||||
|
public TType VNCAuthMode { get; set; }
|
||||||
|
public TType VNCProxyType { get; set; }
|
||||||
|
public TType VNCProxyIP { get; set; }
|
||||||
|
public TType VNCProxyPort { get; set; }
|
||||||
|
public TType VNCProxyUsername { get; set; }
|
||||||
|
public TType VNCProxyPassword { get; set; }
|
||||||
|
public TType VNCColors { get; set; }
|
||||||
|
public TType VNCSmartSizeMode { get; set; }
|
||||||
|
public TType VNCViewOnly { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
42
mRemoteNGTests/Tools/DisposableActionTests.cs
Normal file
42
mRemoteNGTests/Tools/DisposableActionTests.cs
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
using mRemoteNG.Tools;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace mRemoteNGTests.Tools
|
||||||
|
{
|
||||||
|
public class DisposableActionTests
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void InitializerActionRunsWhenObjectIsCreated()
|
||||||
|
{
|
||||||
|
var initializerRan = false;
|
||||||
|
new DisposableAction(() => initializerRan = true, () => { });
|
||||||
|
|
||||||
|
Assert.That(initializerRan);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void DisposalActionRunsWhenDisposeIsCalled()
|
||||||
|
{
|
||||||
|
var disposeActionRan = false;
|
||||||
|
var action = new DisposableAction(() => {}, () => disposeActionRan = true);
|
||||||
|
|
||||||
|
Assert.That(disposeActionRan, Is.False);
|
||||||
|
action.Dispose();
|
||||||
|
Assert.That(disposeActionRan, Is.True);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void DisposeActionOnlyExecutedOnceWhenCallingDisposeMultipleTimes()
|
||||||
|
{
|
||||||
|
var invokeCount = 0;
|
||||||
|
var action = new DisposableAction(() => { }, () => invokeCount++);
|
||||||
|
|
||||||
|
action.Dispose();
|
||||||
|
action.Dispose();
|
||||||
|
action.Dispose();
|
||||||
|
action.Dispose();
|
||||||
|
action.Dispose();
|
||||||
|
Assert.That(invokeCount, Is.EqualTo(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,12 +3,12 @@ using NUnit.Framework;
|
|||||||
|
|
||||||
namespace mRemoteNGTests.Tools
|
namespace mRemoteNGTests.Tools
|
||||||
{
|
{
|
||||||
public class MaybeTests
|
public class OptionalTests
|
||||||
{
|
{
|
||||||
[Test]
|
[Test]
|
||||||
public void MaybeReturnsEmptyListWhenGivenNullValue()
|
public void MaybeReturnsEmptyListWhenGivenNullValue()
|
||||||
{
|
{
|
||||||
var sut = new Maybe<object>(null);
|
var sut = new Optional<object>(null);
|
||||||
Assert.That(sut, Is.Empty);
|
Assert.That(sut, Is.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ namespace mRemoteNGTests.Tools
|
|||||||
public void MaybeReturnsValueIfNotNull()
|
public void MaybeReturnsValueIfNotNull()
|
||||||
{
|
{
|
||||||
var expected = new object();
|
var expected = new object();
|
||||||
var sut = new Maybe<object>(expected);
|
var sut = new Optional<object>(expected);
|
||||||
Assert.That(sut, Has.Member(expected));
|
Assert.That(sut, Has.Member(expected));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,6 +104,14 @@ namespace mRemoteNGTests.Tree
|
|||||||
_con4 = new ConnectionInfo { Name = "con4", Description="description6", Hostname="hostname6" };
|
_con4 = new ConnectionInfo { Name = "con4", Description="description6", Hostname="hostname6" };
|
||||||
_con5 = new ConnectionInfo { Name = "con5", Description="description7", Hostname="hostname7" };
|
_con5 = new ConnectionInfo { Name = "con5", Description="description7", Hostname="hostname7" };
|
||||||
|
|
||||||
|
_folder1.Inheritance.TurnOffInheritanceCompletely();
|
||||||
|
_con1.Inheritance.TurnOffInheritanceCompletely();
|
||||||
|
_con2.Inheritance.TurnOffInheritanceCompletely();
|
||||||
|
_folder2.Inheritance.TurnOffInheritanceCompletely();
|
||||||
|
_con3.Inheritance.TurnOffInheritanceCompletely();
|
||||||
|
_con4.Inheritance.TurnOffInheritanceCompletely();
|
||||||
|
_con5.Inheritance.TurnOffInheritanceCompletely();
|
||||||
|
|
||||||
connectionTreeModel.AddRootNode(root);
|
connectionTreeModel.AddRootNode(root);
|
||||||
root.AddChildRange(new [] { _folder1, _folder2, _con5 });
|
root.AddChildRange(new [] { _folder1, _folder2, _con5 });
|
||||||
_folder1.AddChildRange(new [] { _con1, _con2 });
|
_folder1.AddChildRange(new [] { _con1, _con2 });
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using mRemoteNG.Tree.Root;
|
using mRemoteNG.Tree;
|
||||||
|
using mRemoteNG.Tree.Root;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
|
||||||
@@ -46,5 +47,13 @@ namespace mRemoteNGTests.Tree
|
|||||||
_rootNodeInfo.PasswordString = password;
|
_rootNodeInfo.PasswordString = password;
|
||||||
Assert.That(_rootNodeInfo.PasswordString, Is.EqualTo(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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
202
mRemoteNGTests/UI/Controls/ConnectionTreeTests.cs
Normal file
202
mRemoteNGTests/UI/Controls/ConnectionTreeTests.cs
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
[Apartment(ApartmentState.STA)]
|
||||||
|
public void RenamingNodeWithNothingSelectedDoesNothing()
|
||||||
|
{
|
||||||
|
var connectionTreeModel = new ConnectionTreeModel();
|
||||||
|
var root = new RootNodeInfo(RootNodeType.Connection);
|
||||||
|
connectionTreeModel.AddRootNode(root);
|
||||||
|
|
||||||
|
_connectionTree.ConnectionTreeModel = connectionTreeModel;
|
||||||
|
_connectionTree.SelectedObject = null;
|
||||||
|
|
||||||
|
Assert.DoesNotThrow(() => _connectionTree.RenameSelectedNode());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,224 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using mRemoteNG.Connection;
|
||||||
|
using mRemoteNG.Connection.Protocol;
|
||||||
|
using mRemoteNG.Connection.Protocol.RDP;
|
||||||
|
using mRemoteNG.Connection.Protocol.VNC;
|
||||||
|
using mRemoteNG.Container;
|
||||||
|
using mRemoteNG.Tree.Root;
|
||||||
|
using mRemoteNG.UI.Window;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace mRemoteNGTests.UI.Window.ConfigWindowTests
|
||||||
|
{
|
||||||
|
public class ConfigWindowGeneralTests
|
||||||
|
{
|
||||||
|
private ConfigWindow _configWindow;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
_configWindow = new ConfigWindow
|
||||||
|
{
|
||||||
|
PropertiesVisible = true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCaseSource(nameof(ConnectionInfoGeneralTestCases))]
|
||||||
|
public void PropertyGridShowCorrectPropertiesForConnectionInfo(ConnectionInfo connectionInfo, IEnumerable<string> expectedVisibleProperties)
|
||||||
|
{
|
||||||
|
_configWindow.SelectedTreeNode = connectionInfo;
|
||||||
|
Assert.That(_configWindow.VisibleObjectProperties, Is.EquivalentTo(expectedVisibleProperties));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void PropertyGridShowCorrectPropertiesForRootConnectionInfo()
|
||||||
|
{
|
||||||
|
var expectedVisibleProperties = new[]
|
||||||
|
{
|
||||||
|
nameof(RootNodeInfo.Name),
|
||||||
|
nameof(RootNodeInfo.Password),
|
||||||
|
};
|
||||||
|
|
||||||
|
_configWindow.SelectedTreeNode = new RootNodeInfo(RootNodeType.Connection);
|
||||||
|
Assert.That(_configWindow.VisibleObjectProperties, Is.EquivalentTo(expectedVisibleProperties));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void PropertyGridShowCorrectPropertiesForRootPuttyInfo()
|
||||||
|
{
|
||||||
|
var expectedVisibleProperties = new[]
|
||||||
|
{
|
||||||
|
nameof(RootNodeInfo.Name),
|
||||||
|
};
|
||||||
|
|
||||||
|
_configWindow.SelectedTreeNode = new RootPuttySessionsNodeInfo();
|
||||||
|
Assert.That(_configWindow.VisibleObjectProperties, Is.EquivalentTo(expectedVisibleProperties));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<TestCaseData> ConnectionInfoGeneralTestCases()
|
||||||
|
{
|
||||||
|
var protocolTypes = typeof(ProtocolType).GetEnumValues().OfType<ProtocolType>();
|
||||||
|
var testCases = new List<TestCaseData>();
|
||||||
|
|
||||||
|
foreach (var protocol in protocolTypes)
|
||||||
|
{
|
||||||
|
var expectedPropertyListConnection = BuildExpectedConnectionInfoPropertyList(protocol, false);
|
||||||
|
var connectionInfo = ConstructConnectionInfo(protocol, false);
|
||||||
|
var testCaseConnection = new TestCaseData(connectionInfo, expectedPropertyListConnection)
|
||||||
|
.SetName(protocol + ", ConnectionInfo");
|
||||||
|
testCases.Add(testCaseConnection);
|
||||||
|
|
||||||
|
var expectedPropertyListContainer = BuildExpectedConnectionInfoPropertyList(protocol, true);
|
||||||
|
var containerInfo = ConstructConnectionInfo(protocol, true);
|
||||||
|
var testCaseContainer = new TestCaseData(containerInfo, expectedPropertyListContainer)
|
||||||
|
.SetName(protocol + ", ContainerInfo");
|
||||||
|
testCases.Add(testCaseContainer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return testCases;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static ConnectionInfo ConstructConnectionInfo(ProtocolType protocol, bool isContainer)
|
||||||
|
{
|
||||||
|
// build connection info. set certain connection properties so
|
||||||
|
// that toggled properties are hidden in the property grid. We
|
||||||
|
// will test those separately in the special protocol tests.
|
||||||
|
var node = isContainer
|
||||||
|
? new ContainerInfo()
|
||||||
|
: new ConnectionInfo();
|
||||||
|
|
||||||
|
node.Protocol = protocol;
|
||||||
|
node.Resolution = RdpProtocol.RDPResolutions.Res800x600;
|
||||||
|
node.RDGatewayUsageMethod = RdpProtocol.RDGatewayUsageMethod.Never;
|
||||||
|
node.RDGatewayUseConnectionCredentials = RdpProtocol.RDGatewayUseConnectionCredentials.Yes;
|
||||||
|
node.RedirectSound = RdpProtocol.RDPSounds.DoNotPlay;
|
||||||
|
node.VNCAuthMode = ProtocolVNC.AuthMode.AuthVNC;
|
||||||
|
node.VNCProxyType = ProtocolVNC.ProxyType.ProxyNone;
|
||||||
|
node.Inheritance.TurnOffInheritanceCompletely();
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static List<string> BuildExpectedConnectionInfoPropertyList(ProtocolType protocol, bool isContainer)
|
||||||
|
{
|
||||||
|
var expectedProperties = new List<string>
|
||||||
|
{
|
||||||
|
nameof(ConnectionInfo.Name),
|
||||||
|
nameof(ConnectionInfo.Description),
|
||||||
|
nameof(ConnectionInfo.Icon),
|
||||||
|
nameof(ConnectionInfo.Panel),
|
||||||
|
nameof(ConnectionInfo.Protocol),
|
||||||
|
nameof(ConnectionInfo.PreExtApp),
|
||||||
|
nameof(ConnectionInfo.PostExtApp),
|
||||||
|
nameof(ConnectionInfo.MacAddress),
|
||||||
|
nameof(ConnectionInfo.UserField),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!isContainer)
|
||||||
|
{
|
||||||
|
expectedProperties.AddRange(new []
|
||||||
|
{
|
||||||
|
nameof(ConnectionInfo.Hostname),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (protocol)
|
||||||
|
{
|
||||||
|
case ProtocolType.RDP:
|
||||||
|
expectedProperties.AddRange(new []
|
||||||
|
{
|
||||||
|
nameof(ConnectionInfo.Username),
|
||||||
|
nameof(ConnectionInfo.Password),
|
||||||
|
nameof(ConnectionInfo.Domain),
|
||||||
|
nameof(ConnectionInfo.Port),
|
||||||
|
nameof(ConnectionInfo.UseConsoleSession),
|
||||||
|
nameof(ConnectionInfo.RDPAuthenticationLevel),
|
||||||
|
nameof(ConnectionInfo.RDPMinutesToIdleTimeout),
|
||||||
|
nameof(ConnectionInfo.LoadBalanceInfo),
|
||||||
|
nameof(ConnectionInfo.UseCredSsp),
|
||||||
|
nameof(ConnectionInfo.RDGatewayUsageMethod),
|
||||||
|
nameof(ConnectionInfo.Resolution),
|
||||||
|
nameof(ConnectionInfo.Colors),
|
||||||
|
nameof(ConnectionInfo.CacheBitmaps),
|
||||||
|
nameof(ConnectionInfo.DisplayWallpaper),
|
||||||
|
nameof(ConnectionInfo.DisplayThemes),
|
||||||
|
nameof(ConnectionInfo.EnableFontSmoothing),
|
||||||
|
nameof(ConnectionInfo.EnableDesktopComposition),
|
||||||
|
nameof(ConnectionInfo.RedirectKeys),
|
||||||
|
nameof(ConnectionInfo.RedirectDiskDrives),
|
||||||
|
nameof(ConnectionInfo.RedirectPrinters),
|
||||||
|
nameof(ConnectionInfo.RedirectPorts),
|
||||||
|
nameof(ConnectionInfo.RedirectSmartCards),
|
||||||
|
nameof(ConnectionInfo.RedirectSound),
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case ProtocolType.VNC:
|
||||||
|
expectedProperties.AddRange(new []
|
||||||
|
{
|
||||||
|
nameof(ConnectionInfo.Password),
|
||||||
|
nameof(ConnectionInfo.Port),
|
||||||
|
nameof(ConnectionInfo.VNCSmartSizeMode),
|
||||||
|
nameof(ConnectionInfo.VNCViewOnly),
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case ProtocolType.SSH1:
|
||||||
|
case ProtocolType.SSH2:
|
||||||
|
expectedProperties.AddRange(new []
|
||||||
|
{
|
||||||
|
nameof(ConnectionInfo.Username),
|
||||||
|
nameof(ConnectionInfo.Password),
|
||||||
|
nameof(ConnectionInfo.Port),
|
||||||
|
nameof(ConnectionInfo.PuttySession)
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case ProtocolType.Telnet:
|
||||||
|
case ProtocolType.Rlogin:
|
||||||
|
case ProtocolType.RAW:
|
||||||
|
expectedProperties.AddRange(new[]
|
||||||
|
{
|
||||||
|
nameof(ConnectionInfo.Port),
|
||||||
|
nameof(ConnectionInfo.PuttySession),
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case ProtocolType.HTTP:
|
||||||
|
case ProtocolType.HTTPS:
|
||||||
|
expectedProperties.AddRange(new []
|
||||||
|
{
|
||||||
|
nameof(ConnectionInfo.Username),
|
||||||
|
nameof(ConnectionInfo.Password),
|
||||||
|
nameof(ConnectionInfo.Port),
|
||||||
|
nameof(ConnectionInfo.RenderingEngine),
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case ProtocolType.ICA:
|
||||||
|
expectedProperties.AddRange(new []
|
||||||
|
{
|
||||||
|
nameof(ConnectionInfo.Username),
|
||||||
|
nameof(ConnectionInfo.Password),
|
||||||
|
nameof(ConnectionInfo.Domain),
|
||||||
|
nameof(ConnectionInfo.ICAEncryptionStrength),
|
||||||
|
nameof(ConnectionInfo.Resolution),
|
||||||
|
nameof(ConnectionInfo.Colors),
|
||||||
|
nameof(ConnectionInfo.CacheBitmaps),
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case ProtocolType.IntApp:
|
||||||
|
expectedProperties.AddRange(new[]
|
||||||
|
{
|
||||||
|
nameof(ConnectionInfo.Username),
|
||||||
|
nameof(ConnectionInfo.Password),
|
||||||
|
nameof(ConnectionInfo.Domain),
|
||||||
|
nameof(ConnectionInfo.Port),
|
||||||
|
nameof(ConnectionInfo.ExtApp),
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(protocol), protocol, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return expectedProperties;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
using mRemoteNG.Connection;
|
||||||
|
using mRemoteNG.Connection.Protocol;
|
||||||
|
using mRemoteNG.Connection.Protocol.RDP;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace mRemoteNGTests.UI.Window.ConfigWindowTests
|
||||||
|
{
|
||||||
|
public class ConfigWindowRdpSpecialTests : ConfigWindowSpecialTestsBase
|
||||||
|
{
|
||||||
|
protected override ProtocolType Protocol => ProtocolType.RDP;
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void PropertyShownWhenActive_RdpMinutesToIdleTimeout()
|
||||||
|
{
|
||||||
|
ConnectionInfo.RDPMinutesToIdleTimeout = 1;
|
||||||
|
ExpectedPropertyList.Add(nameof(mRemoteNG.Connection.ConnectionInfo.RDPAlertIdleTimeout));
|
||||||
|
|
||||||
|
RunVerification();
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase(RdpProtocol.RDGatewayUsageMethod.Always)]
|
||||||
|
[TestCase(RdpProtocol.RDGatewayUsageMethod.Detect)]
|
||||||
|
public void RdGatewayPropertiesShown_WhenRdGatewayUsageMethodIsNotNever(RdpProtocol.RDGatewayUsageMethod gatewayUsageMethod)
|
||||||
|
{
|
||||||
|
ConnectionInfo.RDGatewayUsageMethod = gatewayUsageMethod;
|
||||||
|
ConnectionInfo.RDGatewayUseConnectionCredentials = RdpProtocol.RDGatewayUseConnectionCredentials.Yes;
|
||||||
|
ExpectedPropertyList.AddRange(new []
|
||||||
|
{
|
||||||
|
nameof(mRemoteNG.Connection.ConnectionInfo.RDGatewayHostname),
|
||||||
|
nameof(mRemoteNG.Connection.ConnectionInfo.RDGatewayUseConnectionCredentials)
|
||||||
|
});
|
||||||
|
|
||||||
|
RunVerification();
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase(RdpProtocol.RDGatewayUseConnectionCredentials.No)]
|
||||||
|
[TestCase(RdpProtocol.RDGatewayUseConnectionCredentials.SmartCard)]
|
||||||
|
public void RdGatewayPropertiesShown_WhenRDGatewayUseConnectionCredentialsIsNotYes(RdpProtocol.RDGatewayUseConnectionCredentials useConnectionCredentials)
|
||||||
|
{
|
||||||
|
ConnectionInfo.RDGatewayUsageMethod = RdpProtocol.RDGatewayUsageMethod.Always;
|
||||||
|
ConnectionInfo.RDGatewayUseConnectionCredentials = useConnectionCredentials;
|
||||||
|
ExpectedPropertyList.AddRange(new []
|
||||||
|
{
|
||||||
|
nameof(mRemoteNG.Connection.ConnectionInfo.RDGatewayHostname),
|
||||||
|
nameof(mRemoteNG.Connection.ConnectionInfo.RDGatewayUsername),
|
||||||
|
nameof(mRemoteNG.Connection.ConnectionInfo.RDGatewayPassword),
|
||||||
|
nameof(mRemoteNG.Connection.ConnectionInfo.RDGatewayDomain),
|
||||||
|
nameof(mRemoteNG.Connection.ConnectionInfo.RDGatewayUseConnectionCredentials)
|
||||||
|
});
|
||||||
|
|
||||||
|
RunVerification();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void SoundQualityPropertyShown_WhenRdpSoundsSetToBringToThisComputer()
|
||||||
|
{
|
||||||
|
ConnectionInfo.RedirectSound = RdpProtocol.RDPSounds.BringToThisComputer;
|
||||||
|
ExpectedPropertyList.Add(nameof(mRemoteNG.Connection.ConnectionInfo.SoundQuality));
|
||||||
|
|
||||||
|
RunVerification();
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase(RdpProtocol.RDPResolutions.FitToWindow)]
|
||||||
|
[TestCase(RdpProtocol.RDPResolutions.Fullscreen)]
|
||||||
|
public void AutomaticResizePropertyShown_WhenResolutionIsDynamic(RdpProtocol.RDPResolutions resolution)
|
||||||
|
{
|
||||||
|
ConnectionInfo.Resolution = resolution;
|
||||||
|
ExpectedPropertyList.Add(nameof(mRemoteNG.Connection.ConnectionInfo.AutomaticResize));
|
||||||
|
|
||||||
|
RunVerification();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using mRemoteNG.Connection;
|
||||||
|
using mRemoteNG.Connection.Protocol;
|
||||||
|
using mRemoteNG.UI.Window;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace mRemoteNGTests.UI.Window.ConfigWindowTests
|
||||||
|
{
|
||||||
|
public abstract class ConfigWindowSpecialTestsBase
|
||||||
|
{
|
||||||
|
protected abstract ProtocolType Protocol { get; }
|
||||||
|
protected bool TestAgainstContainerInfo { get; set; } = false;
|
||||||
|
protected ConfigWindow ConfigWindow;
|
||||||
|
protected ConnectionInfo ConnectionInfo;
|
||||||
|
protected List<string> ExpectedPropertyList;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public virtual void Setup()
|
||||||
|
{
|
||||||
|
ConnectionInfo = ConfigWindowGeneralTests.ConstructConnectionInfo(Protocol, TestAgainstContainerInfo);
|
||||||
|
ExpectedPropertyList = ConfigWindowGeneralTests.BuildExpectedConnectionInfoPropertyList(Protocol, TestAgainstContainerInfo);
|
||||||
|
|
||||||
|
ConfigWindow = new ConfigWindow
|
||||||
|
{
|
||||||
|
PropertiesVisible = true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RunVerification()
|
||||||
|
{
|
||||||
|
ConfigWindow.SelectedTreeNode = ConnectionInfo;
|
||||||
|
Assert.That(
|
||||||
|
ConfigWindow.VisibleObjectProperties,
|
||||||
|
Is.EquivalentTo(ExpectedPropertyList));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
using mRemoteNG.Connection.Protocol;
|
||||||
|
using mRemoteNG.Connection.Protocol.VNC;
|
||||||
|
using NUnit.Framework;
|
||||||
|
|
||||||
|
namespace mRemoteNGTests.UI.Window.ConfigWindowTests
|
||||||
|
{
|
||||||
|
public class ConfigWindowVncSpecialTests : ConfigWindowSpecialTestsBase
|
||||||
|
{
|
||||||
|
protected override ProtocolType Protocol => ProtocolType.VNC;
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void UserDomainPropertiesShown_WhenAuthModeIsWindows()
|
||||||
|
{
|
||||||
|
ConnectionInfo.VNCAuthMode = ProtocolVNC.AuthMode.AuthWin;
|
||||||
|
ExpectedPropertyList.AddRange(new []
|
||||||
|
{
|
||||||
|
nameof(ConnectionInfo.Username),
|
||||||
|
nameof(ConnectionInfo.Domain),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase(ProtocolVNC.ProxyType.ProxyHTTP)]
|
||||||
|
[TestCase(ProtocolVNC.ProxyType.ProxySocks5)]
|
||||||
|
[TestCase(ProtocolVNC.ProxyType.ProxyUltra)]
|
||||||
|
public void ProxyPropertiesShown_WhenProxyModeIsNotNone(ProtocolVNC.ProxyType proxyType)
|
||||||
|
{
|
||||||
|
ConnectionInfo.VNCProxyType = proxyType;
|
||||||
|
ExpectedPropertyList.AddRange(new[]
|
||||||
|
{
|
||||||
|
nameof(ConnectionInfo.VNCProxyIP),
|
||||||
|
nameof(ConnectionInfo.VNCProxyPort),
|
||||||
|
nameof(ConnectionInfo.VNCProxyUsername),
|
||||||
|
nameof(ConnectionInfo.VNCProxyPassword),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -108,12 +108,14 @@
|
|||||||
</Otherwise>
|
</Otherwise>
|
||||||
</Choose>
|
</Choose>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="App\ImportTests.cs" />
|
||||||
<Compile Include="App\UpdaterTests.cs" />
|
<Compile Include="App\UpdaterTests.cs" />
|
||||||
<Compile Include="BinaryFileTests.cs" />
|
<Compile Include="BinaryFileTests.cs" />
|
||||||
<Compile Include="Config\Connections\Multiuser\ConnectionsUpdateAvailableEventArgsTests.cs" />
|
<Compile Include="Config\Connections\Multiuser\ConnectionsUpdateAvailableEventArgsTests.cs" />
|
||||||
<Compile Include="Config\DataProviders\FileBackupCreatorTests.cs" />
|
<Compile Include="Config\DataProviders\FileBackupCreatorTests.cs" />
|
||||||
<Compile Include="Config\DataProviders\FileDataProviderTests.cs" />
|
<Compile Include="Config\DataProviders\FileDataProviderTests.cs" />
|
||||||
<Compile Include="Config\DataProviders\FileDataProviderWithRollingBackupTests.cs" />
|
<Compile Include="Config\DataProviders\FileDataProviderWithRollingBackupTests.cs" />
|
||||||
|
<Compile Include="Config\Serializers\ConnectionSerializers\Xml\ValidateXmlSchemas.cs" />
|
||||||
<Compile Include="Config\Serializers\DataTableDeserializerTests.cs" />
|
<Compile Include="Config\Serializers\DataTableDeserializerTests.cs" />
|
||||||
<Compile Include="Config\CredentialHarvesterTests.cs" />
|
<Compile Include="Config\CredentialHarvesterTests.cs" />
|
||||||
<Compile Include="Config\CredentialRecordLoaderTests.cs" />
|
<Compile Include="Config\CredentialRecordLoaderTests.cs" />
|
||||||
@@ -121,21 +123,21 @@
|
|||||||
<Compile Include="Config\Serializers\CredentialProviderSerializerTests.cs" />
|
<Compile Include="Config\Serializers\CredentialProviderSerializerTests.cs" />
|
||||||
<Compile Include="Config\Serializers\CredentialSerializers\XmlCredentialPasswordDecryptorDecoratorTests.cs" />
|
<Compile Include="Config\Serializers\CredentialSerializers\XmlCredentialPasswordDecryptorDecoratorTests.cs" />
|
||||||
<Compile Include="Config\Serializers\CredentialSerializers\XmlCredentialPasswordEncryptorDecoratorTests.cs" />
|
<Compile Include="Config\Serializers\CredentialSerializers\XmlCredentialPasswordEncryptorDecoratorTests.cs" />
|
||||||
<Compile Include="Config\Serializers\MiscSerializers\CsvConnectionsDeserializerMremotengFormatTests.cs" />
|
<Compile Include="Config\Serializers\ConnectionSerializers\Csv\CsvConnectionsDeserializerMremotengFormatTests.cs" />
|
||||||
<Compile Include="Config\Serializers\MiscSerializers\CsvConnectionsSerializerMremotengFormatTests.cs" />
|
<Compile Include="Config\Serializers\ConnectionSerializers\Csv\CsvConnectionsSerializerMremotengFormatTests.cs" />
|
||||||
<Compile Include="Config\Serializers\DataTableSerializerTests.cs" />
|
<Compile Include="Config\Serializers\DataTableSerializerTests.cs" />
|
||||||
<Compile Include="Config\Serializers\MiscSerializers\PortScanDeserializerTests.cs" />
|
<Compile Include="Config\Serializers\MiscSerializers\PortScanDeserializerTests.cs" />
|
||||||
<Compile Include="Config\Serializers\MiscSerializers\PuttyConnectionManagerDeserializerTests.cs" />
|
<Compile Include="Config\Serializers\MiscSerializers\PuttyConnectionManagerDeserializerTests.cs" />
|
||||||
<Compile Include="Config\Serializers\ConnectionSerializers\XmlConnectionsDeserializerTests.cs" />
|
<Compile Include="Config\Serializers\ConnectionSerializers\Xml\XmlConnectionsDeserializerTests.cs" />
|
||||||
<Compile Include="Config\Serializers\MiscSerializers\RemoteDesktopConnectionDeserializerTests.cs" />
|
<Compile Include="Config\Serializers\MiscSerializers\RemoteDesktopConnectionDeserializerTests.cs" />
|
||||||
<Compile Include="Config\Serializers\MiscSerializers\RemoteDesktopConnectionManager27DeserializerTests.cs" />
|
<Compile Include="Config\Serializers\MiscSerializers\RemoteDesktopConnectionManager27DeserializerTests.cs" />
|
||||||
<Compile Include="Config\Serializers\MiscSerializers\RemoteDesktopConnectionManagerDeserializerTests.cs" />
|
<Compile Include="Config\Serializers\MiscSerializers\RemoteDesktopConnectionManagerDeserializerTests.cs" />
|
||||||
<Compile Include="Config\Serializers\ConnectionSerializers\XmlConnectionsDocumentCompilerTests.cs" />
|
<Compile Include="Config\Serializers\ConnectionSerializers\Xml\XmlConnectionsDocumentCompilerTests.cs" />
|
||||||
<Compile Include="Config\Serializers\ConnectionSerializers\XmlConnectionsDocumentEncryptorTests.cs" />
|
<Compile Include="Config\Serializers\ConnectionSerializers\Xml\XmlConnectionsDocumentEncryptorTests.cs" />
|
||||||
<Compile Include="Config\Serializers\ConnectionSerializers\XmlConnectionsSerializerTests.cs" />
|
<Compile Include="Config\Serializers\ConnectionSerializers\Xml\XmlConnectionsSerializerTests.cs" />
|
||||||
<Compile Include="Config\Serializers\CredentialSerializers\XmlCredentialRecordDeserializerTests.cs" />
|
<Compile Include="Config\Serializers\CredentialSerializers\XmlCredentialRecordDeserializerTests.cs" />
|
||||||
<Compile Include="Config\Serializers\CredentialSerializers\XmlCredentialSerializerTests.cs" />
|
<Compile Include="Config\Serializers\CredentialSerializers\XmlCredentialSerializerTests.cs" />
|
||||||
<Compile Include="Config\Serializers\ConnectionSerializers\XmlRootNodeSerializerTests.cs" />
|
<Compile Include="Config\Serializers\ConnectionSerializers\Xml\XmlRootNodeSerializerTests.cs" />
|
||||||
<Compile Include="Config\Serializers\Versioning\SqlVersion22To23UpgraderTests.cs" />
|
<Compile Include="Config\Serializers\Versioning\SqlVersion22To23UpgraderTests.cs" />
|
||||||
<Compile Include="Config\Serializers\Versioning\SqlVersion23To24UpgraderTests.cs" />
|
<Compile Include="Config\Serializers\Versioning\SqlVersion23To24UpgraderTests.cs" />
|
||||||
<Compile Include="Config\Serializers\Versioning\SqlVersion24To25UpgraderTests.cs" />
|
<Compile Include="Config\Serializers\Versioning\SqlVersion24To25UpgraderTests.cs" />
|
||||||
@@ -145,6 +147,7 @@
|
|||||||
<Compile Include="Connection\ConnectionInfoComparerTests.cs" />
|
<Compile Include="Connection\ConnectionInfoComparerTests.cs" />
|
||||||
<Compile Include="Connection\Protocol\IntegratedProgramTests.cs" />
|
<Compile Include="Connection\Protocol\IntegratedProgramTests.cs" />
|
||||||
<Compile Include="Connection\Protocol\ProtocolListTests.cs" />
|
<Compile Include="Connection\Protocol\ProtocolListTests.cs" />
|
||||||
|
<Compile Include="Container\RootNodeInfoTests.cs" />
|
||||||
<Compile Include="Credential\CompositeRepositoryUnlockerTests.cs" />
|
<Compile Include="Credential\CompositeRepositoryUnlockerTests.cs" />
|
||||||
<Compile Include="Credential\CredentialChangedEventArgsTests.cs" />
|
<Compile Include="Credential\CredentialChangedEventArgsTests.cs" />
|
||||||
<Compile Include="Credential\CredentialDeletionMsgBoxConfirmerTests.cs" />
|
<Compile Include="Credential\CredentialDeletionMsgBoxConfirmerTests.cs" />
|
||||||
@@ -168,12 +171,15 @@
|
|||||||
<Compile Include="Security\PasswordCreation\PasswordLengthConstraintTests.cs" />
|
<Compile Include="Security\PasswordCreation\PasswordLengthConstraintTests.cs" />
|
||||||
<Compile Include="Security\RandomGeneratorTests.cs" />
|
<Compile Include="Security\RandomGeneratorTests.cs" />
|
||||||
<Compile Include="Security\SecureStringExtensionsTests.cs" />
|
<Compile Include="Security\SecureStringExtensionsTests.cs" />
|
||||||
|
<Compile Include="TestHelpers\ConnectionInfoHelpers.cs" />
|
||||||
<Compile Include="TestHelpers\ConnectionTreeModelBuilder.cs" />
|
<Compile Include="TestHelpers\ConnectionTreeModelBuilder.cs" />
|
||||||
<Compile Include="Security\XmlCryptoProviderBuilderTests.cs" />
|
<Compile Include="Security\XmlCryptoProviderBuilderTests.cs" />
|
||||||
<Compile Include="TestHelpers\FileTestHelpers.cs" />
|
<Compile Include="TestHelpers\FileTestHelpers.cs" />
|
||||||
|
<Compile Include="TestHelpers\SerializableConnectionInfoAllPropertiesOfType.cs" />
|
||||||
|
<Compile Include="Tools\DisposableActionTests.cs" />
|
||||||
<Compile Include="Tools\ExternalToolsArgumentParserTests.cs" />
|
<Compile Include="Tools\ExternalToolsArgumentParserTests.cs" />
|
||||||
<Compile Include="Tools\FullyObservableCollectionTests.cs" />
|
<Compile Include="Tools\FullyObservableCollectionTests.cs" />
|
||||||
<Compile Include="Tools\MaybeTests.cs" />
|
<Compile Include="Tools\OptionalTests.cs" />
|
||||||
<Compile Include="Tree\ClickHandlers\TreeNodeCompositeClickHandlerTests.cs" />
|
<Compile Include="Tree\ClickHandlers\TreeNodeCompositeClickHandlerTests.cs" />
|
||||||
<Compile Include="Tree\ConnectionTreeDragAndDropHandlerTests.cs" />
|
<Compile Include="Tree\ConnectionTreeDragAndDropHandlerTests.cs" />
|
||||||
<Compile Include="Tree\ConnectionTreeModelTests.cs" />
|
<Compile Include="Tree\ConnectionTreeModelTests.cs" />
|
||||||
@@ -203,6 +209,7 @@
|
|||||||
<Compile Include="Tree\RootNodeInfoTests.cs" />
|
<Compile Include="Tree\RootNodeInfoTests.cs" />
|
||||||
<Compile Include="Tree\ClickHandlers\SwitchToConnectionClickHandlerTests.cs" />
|
<Compile Include="Tree\ClickHandlers\SwitchToConnectionClickHandlerTests.cs" />
|
||||||
<Compile Include="Tree\SelectedConnectionDeletionConfirmerTests.cs" />
|
<Compile Include="Tree\SelectedConnectionDeletionConfirmerTests.cs" />
|
||||||
|
<Compile Include="UI\Controls\ConnectionTreeTests.cs" />
|
||||||
<Compile Include="UI\Controls\PageSequenceTests.cs" />
|
<Compile Include="UI\Controls\PageSequenceTests.cs" />
|
||||||
<Compile Include="UI\Controls\SecureTextBoxTestForm.cs">
|
<Compile Include="UI\Controls\SecureTextBoxTestForm.cs">
|
||||||
<SubType>Form</SubType>
|
<SubType>Form</SubType>
|
||||||
@@ -227,6 +234,10 @@
|
|||||||
<Compile Include="UI\Forms\OptionsFormSetupAndTeardown.cs" />
|
<Compile Include="UI\Forms\OptionsFormSetupAndTeardown.cs" />
|
||||||
<Compile Include="UI\Forms\PasswordFormTests.cs" />
|
<Compile Include="UI\Forms\PasswordFormTests.cs" />
|
||||||
<Compile Include="UI\WindowListTests.cs" />
|
<Compile Include="UI\WindowListTests.cs" />
|
||||||
|
<Compile Include="UI\Window\ConfigWindowTests\ConfigWindowGeneralTests.cs" />
|
||||||
|
<Compile Include="UI\Window\ConfigWindowTests\ConfigWindowRdpSpecialTests.cs" />
|
||||||
|
<Compile Include="UI\Window\ConfigWindowTests\ConfigWindowSpecialTestsBase.cs" />
|
||||||
|
<Compile Include="UI\Window\ConfigWindowTests\ConfigWindowVncSpecialTests.cs" />
|
||||||
<Compile Include="UI\Window\ConnectionTreeWindowTests.cs" />
|
<Compile Include="UI\Window\ConnectionTreeWindowTests.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -256,6 +267,8 @@
|
|||||||
<None Include="Resources\test_rdcman_v2_2_badschemaversion.rdg" />
|
<None Include="Resources\test_rdcman_v2_2_badschemaversion.rdg" />
|
||||||
<None Include="Resources\test_rdcman_v2_2_schema1.rdg" />
|
<None Include="Resources\test_rdcman_v2_2_schema1.rdg" />
|
||||||
<None Include="Resources\test_RDCMan_v2_7_schema3.rdg" />
|
<None Include="Resources\test_RDCMan_v2_7_schema3.rdg" />
|
||||||
|
<None Include="Resources\test_rdcman_v2_7_schema3_empty_values.rdg" />
|
||||||
|
<None Include="Resources\test_rdcman_v2_7_schema3_null_values.rdg" />
|
||||||
<None Include="Resources\test_remotedesktopconnection.rdp" />
|
<None Include="Resources\test_remotedesktopconnection.rdp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -33,16 +33,19 @@ Global
|
|||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
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.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.ActiveCfg = Debug Portable|x86
|
||||||
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Debug Portable|x86.Build.0 = 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.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.ActiveCfg = Debug|x86
|
||||||
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Debug|x86.Build.0 = 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.ActiveCfg = Release|x86
|
||||||
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Release Installer|Any CPU.Build.0 = Release Portable|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.ActiveCfg = Release|x86
|
||||||
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Release Installer|x86.Build.0 = 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.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.ActiveCfg = Release Portable|x86
|
||||||
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Release Portable|x86.Build.0 = 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
|
{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.ActiveCfg = Release|x86
|
||||||
{4934A491-40BC-4E5B-9166-EA1169A220F6}.Release|x86.Build.0 = 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.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.ActiveCfg = Debug Portable|x86
|
||||||
{1453B37F-8621-499E-B0B2-6091F76DC0BB}.Debug Portable|x86.Build.0 = 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.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.ActiveCfg = Debug|x86
|
||||||
{1453B37F-8621-499E-B0B2-6091F76DC0BB}.Debug|x86.Build.0 = 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.ActiveCfg = Release|x86
|
||||||
{1453B37F-8621-499E-B0B2-6091F76DC0BB}.Release Installer|Any CPU.Build.0 = Release Portable|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.ActiveCfg = Release|x86
|
||||||
{1453B37F-8621-499E-B0B2-6091F76DC0BB}.Release Installer|x86.Build.0 = 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.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.ActiveCfg = Release Portable|x86
|
||||||
{1453B37F-8621-499E-B0B2-6091F76DC0BB}.Release Portable|x86.Build.0 = 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.ActiveCfg = Release|x86
|
||||||
{1453B37F-8621-499E-B0B2-6091F76DC0BB}.Release|Any CPU.Build.0 = 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.ActiveCfg = Release|x86
|
||||||
{1453B37F-8621-499E-B0B2-6091F76DC0BB}.Release|x86.Build.0 = 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.ActiveCfg = Debug|x86
|
||||||
{5423D985-CB48-4344-B47F-E8C6D60C8B04}.Debug Portable|Any CPU.Build.0 = Release|x86
|
|
||||||
{5423D985-CB48-4344-B47F-E8C6D60C8B04}.Debug Portable|x86.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|Any CPU.ActiveCfg = Debug|x86
|
||||||
{5423D985-CB48-4344-B47F-E8C6D60C8B04}.Debug|x86.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.ActiveCfg = Release|x86
|
||||||
{5423D985-CB48-4344-B47F-E8C6D60C8B04}.Release Installer|x86.Build.0 = 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.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 Portable|x86.ActiveCfg = Release|x86
|
||||||
{5423D985-CB48-4344-B47F-E8C6D60C8B04}.Release|Any CPU.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
|
{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 Portable|x86.ActiveCfg = Debug Portable|x86
|
||||||
{F0168B9F-6815-40DF-BA53-46CEE7683B68}.Debug|Any CPU.ActiveCfg = Debug|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}.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.ActiveCfg = Release|x86
|
||||||
{F0168B9F-6815-40DF-BA53-46CEE7683B68}.Release Installer|Any CPU.Build.0 = Release Portable|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.ActiveCfg = Release|x86
|
||||||
{F0168B9F-6815-40DF-BA53-46CEE7683B68}.Release Installer|x86.Build.0 = 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
|
{F0168B9F-6815-40DF-BA53-46CEE7683B68}.Release Portable|Any CPU.ActiveCfg = Release Portable|x86
|
||||||
|
|||||||
@@ -19,12 +19,28 @@ namespace mRemoteNG.App
|
|||||||
|
|
||||||
private static void CheckFipsPolicy(MessageCollector messageCollector)
|
private static void CheckFipsPolicy(MessageCollector messageCollector)
|
||||||
{
|
{
|
||||||
|
if (Settings.Default.OverrideFIPSCheck)
|
||||||
|
{
|
||||||
|
messageCollector.AddMessage(MessageClass.InformationMsg, "OverrideFIPSCheck is set. Will skip check...", true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
messageCollector.AddMessage(MessageClass.InformationMsg, "Checking FIPS Policy...", true);
|
messageCollector.AddMessage(MessageClass.InformationMsg, "Checking FIPS Policy...", true);
|
||||||
if (!FipsPolicyEnabledForServer2003() && !FipsPolicyEnabledForServer2008AndNewer()) return;
|
if (!FipsPolicyEnabledForServer2003() && !FipsPolicyEnabledForServer2008AndNewer()) return;
|
||||||
var errorText = string.Format(Language.strErrorFipsPolicyIncompatible, GeneralAppInfo.ProductName,
|
|
||||||
GeneralAppInfo.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
var errorText = string.Format(Language.strErrorFipsPolicyIncompatible, GeneralAppInfo.ProductName);
|
||||||
messageCollector.AddMessage(MessageClass.ErrorMsg, errorText, true);
|
messageCollector.AddMessage(MessageClass.ErrorMsg, errorText, true);
|
||||||
MessageBox.Show(FrmMain.Default, errorText);
|
|
||||||
|
var ShouldIStayOrShouldIGo = CTaskDialog.MessageBox(Application.ProductName, Language.strCompatibilityProblemDetected, errorText, "", "", Language.strCheckboxDoNotShowThisMessageAgain, ETaskDialogButtons.OkCancel, ESysIcons.Warning, ESysIcons.Warning);
|
||||||
|
if (CTaskDialog.VerificationChecked && ShouldIStayOrShouldIGo == DialogResult.OK)
|
||||||
|
{
|
||||||
|
messageCollector.AddMessage(MessageClass.ErrorMsg, "User requests that FIPS check be overridden", true);
|
||||||
|
Settings.Default.OverrideFIPSCheck = true;
|
||||||
|
Settings.Default.Save();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ShouldIStayOrShouldIGo == DialogResult.Cancel)
|
||||||
Environment.Exit(1);
|
Environment.Exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ using System.Windows.Forms;
|
|||||||
using mRemoteNG.Config.Connections;
|
using mRemoteNG.Config.Connections;
|
||||||
using mRemoteNG.Config.DataProviders;
|
using mRemoteNG.Config.DataProviders;
|
||||||
using mRemoteNG.Config.Serializers;
|
using mRemoteNG.Config.Serializers;
|
||||||
|
using mRemoteNG.Config.Serializers.Csv;
|
||||||
|
using mRemoteNG.Config.Serializers.Xml;
|
||||||
using mRemoteNG.Connection;
|
using mRemoteNG.Connection;
|
||||||
using mRemoteNG.Container;
|
using mRemoteNG.Container;
|
||||||
using mRemoteNG.Security;
|
using mRemoteNG.Security;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using mRemoteNG.Config.Import;
|
using mRemoteNG.Config.Import;
|
||||||
|
using mRemoteNG.Connection;
|
||||||
using mRemoteNG.Connection.Protocol;
|
using mRemoteNG.Connection.Protocol;
|
||||||
using mRemoteNG.Container;
|
using mRemoteNG.Container;
|
||||||
using mRemoteNG.Tools;
|
using mRemoteNG.Tools;
|
||||||
@@ -35,7 +36,29 @@ namespace mRemoteNG.App
|
|||||||
if (openFileDialog.ShowDialog() != DialogResult.OK)
|
if (openFileDialog.ShowDialog() != DialogResult.OK)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
foreach (var fileName in openFileDialog.FileNames)
|
HeadlessFileImport(
|
||||||
|
openFileDialog.FileNames,
|
||||||
|
importDestinationContainer,
|
||||||
|
Runtime.ConnectionsService,
|
||||||
|
fileName => MessageBox.Show(string.Format(Language.strImportFileFailedContent, fileName), Language.strImportFileFailedMainInstruction,
|
||||||
|
MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Runtime.MessageCollector.AddExceptionMessage("Unable to import file.", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void HeadlessFileImport(
|
||||||
|
IEnumerable<string> filePaths,
|
||||||
|
ContainerInfo importDestinationContainer,
|
||||||
|
ConnectionsService connectionsService,
|
||||||
|
Action<string> exceptionAction = null)
|
||||||
|
{
|
||||||
|
using (connectionsService.BatchedSavingContext())
|
||||||
|
{
|
||||||
|
foreach (var fileName in filePaths)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -44,27 +67,21 @@ namespace mRemoteNG.App
|
|||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
MessageBox.Show(string.Format(Language.strImportFileFailedContent, fileName), Language.strImportFileFailedMainInstruction,
|
exceptionAction?.Invoke(fileName);
|
||||||
MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);
|
Runtime.MessageCollector.AddExceptionMessage($"Error occurred while importing file '{fileName}'.", ex);
|
||||||
Runtime.MessageCollector.AddExceptionMessage("Unable to import file.", ex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Runtime.ConnectionsService.SaveConnectionsAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Runtime.MessageCollector.AddExceptionMessage("Unable to import file.", ex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ImportFromActiveDirectory(string ldapPath, ContainerInfo importDestinationContainer, bool importSubOu)
|
public static void ImportFromActiveDirectory(string ldapPath, ContainerInfo importDestinationContainer, bool importSubOu)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
{
|
||||||
|
using (Runtime.ConnectionsService.BatchedSavingContext())
|
||||||
{
|
{
|
||||||
ActiveDirectoryImporter.Import(ldapPath, importDestinationContainer, importSubOu);
|
ActiveDirectoryImporter.Import(ldapPath, importDestinationContainer, importSubOu);
|
||||||
Runtime.ConnectionsService.SaveConnectionsAsync();
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -75,10 +92,12 @@ namespace mRemoteNG.App
|
|||||||
public static void ImportFromPortScan(IEnumerable<ScanHost> hosts, ProtocolType protocol, ContainerInfo importDestinationContainer)
|
public static void ImportFromPortScan(IEnumerable<ScanHost> hosts, ProtocolType protocol, ContainerInfo importDestinationContainer)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
{
|
||||||
|
using (Runtime.ConnectionsService.BatchedSavingContext())
|
||||||
{
|
{
|
||||||
var importer = new PortScanImporter(protocol);
|
var importer = new PortScanImporter(protocol);
|
||||||
importer.Import(hosts, importDestinationContainer);
|
importer.Import(hosts, importDestinationContainer);
|
||||||
Runtime.ConnectionsService.SaveConnectionsAsync();
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,14 +2,15 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
using mRemoteNG.Connection;
|
||||||
|
|
||||||
namespace mRemoteNG.App.Info
|
namespace mRemoteNG.App.Info
|
||||||
{
|
{
|
||||||
public static class SettingsFileInfo
|
public static class SettingsFileInfo
|
||||||
{
|
{
|
||||||
private static readonly string ExePath = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
|
private static readonly string ExePath = Path.GetDirectoryName(Assembly.GetAssembly(typeof(ConnectionInfo))?.Location);
|
||||||
|
|
||||||
public static string SettingsPath { get; } = Runtime.IsPortableEdition ? ExePath : Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\" + Application.ProductName;
|
public static string SettingsPath => Runtime.IsPortableEdition ? ExePath : Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\" + Application.ProductName;
|
||||||
public static string LayoutFileName { get; } = "pnlLayout.xml";
|
public static string LayoutFileName { get; } = "pnlLayout.xml";
|
||||||
public static string ExtAppsFilesName { get; } = "extApps.xml";
|
public static string ExtAppsFilesName { get; } = "extApps.xml";
|
||||||
public static string ThemesFileName { get; } = "Themes.xml";
|
public static string ThemesFileName { get; } = "Themes.xml";
|
||||||
|
|||||||
@@ -1,11 +1,4 @@
|
|||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Security;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Windows.Forms;
|
|
||||||
using mRemoteNG.App.Info;
|
using mRemoteNG.App.Info;
|
||||||
using mRemoteNG.Config.Connections.Multiuser;
|
|
||||||
using mRemoteNG.Config.DataProviders;
|
|
||||||
using mRemoteNG.Config.Putty;
|
using mRemoteNG.Config.Putty;
|
||||||
using mRemoteNG.Connection;
|
using mRemoteNG.Connection;
|
||||||
using mRemoteNG.Credential;
|
using mRemoteNG.Credential;
|
||||||
@@ -17,6 +10,11 @@ using mRemoteNG.Tree.Root;
|
|||||||
using mRemoteNG.UI;
|
using mRemoteNG.UI;
|
||||||
using mRemoteNG.UI.Forms;
|
using mRemoteNG.UI.Forms;
|
||||||
using mRemoteNG.UI.TaskDialog;
|
using mRemoteNG.UI.TaskDialog;
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Security;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
|
||||||
namespace mRemoteNG.App
|
namespace mRemoteNG.App
|
||||||
{
|
{
|
||||||
@@ -45,19 +43,23 @@ namespace mRemoteNG.App
|
|||||||
#region Connections Loading/Saving
|
#region Connections Loading/Saving
|
||||||
public static void LoadConnectionsAsync()
|
public static void LoadConnectionsAsync()
|
||||||
{
|
{
|
||||||
_withDialog = false;
|
|
||||||
|
|
||||||
var t = new Thread(LoadConnectionsBGd);
|
var t = new Thread(LoadConnectionsBGd);
|
||||||
t.SetApartmentState(ApartmentState.STA);
|
t.SetApartmentState(ApartmentState.STA);
|
||||||
t.Start();
|
t.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool _withDialog;
|
|
||||||
private static void LoadConnectionsBGd()
|
private static void LoadConnectionsBGd()
|
||||||
{
|
{
|
||||||
LoadConnections(_withDialog);
|
LoadConnections();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="withDialog">
|
||||||
|
/// Should we show the file selection dialog to allow the user to select
|
||||||
|
/// a connection file
|
||||||
|
/// </param>
|
||||||
public static void LoadConnections(bool withDialog = false)
|
public static void LoadConnections(bool withDialog = false)
|
||||||
{
|
{
|
||||||
var connectionFileName = "";
|
var connectionFileName = "";
|
||||||
@@ -67,44 +69,27 @@ namespace mRemoteNG.App
|
|||||||
// disable sql update checking while we are loading updates
|
// disable sql update checking while we are loading updates
|
||||||
ConnectionsService.RemoteConnectionsSyncronizer?.Disable();
|
ConnectionsService.RemoteConnectionsSyncronizer?.Disable();
|
||||||
|
|
||||||
if (!Settings.Default.UseSQLServer)
|
|
||||||
{
|
|
||||||
if (withDialog)
|
if (withDialog)
|
||||||
{
|
{
|
||||||
var loadDialog = DialogFactory.BuildLoadConnectionsDialog();
|
var loadDialog = DialogFactory.BuildLoadConnectionsDialog();
|
||||||
if (loadDialog.ShowDialog() != DialogResult.OK) return;
|
if (loadDialog.ShowDialog() != DialogResult.OK)
|
||||||
|
return;
|
||||||
|
|
||||||
connectionFileName = loadDialog.FileName;
|
connectionFileName = loadDialog.FileName;
|
||||||
|
Settings.Default.UseSQLServer = false;
|
||||||
|
Settings.Default.Save();
|
||||||
}
|
}
|
||||||
else
|
else if (!Settings.Default.UseSQLServer)
|
||||||
{
|
{
|
||||||
connectionFileName = ConnectionsService.GetStartupConnectionFileName();
|
connectionFileName = ConnectionsService.GetStartupConnectionFileName();
|
||||||
}
|
}
|
||||||
|
|
||||||
var backupFileCreator = new FileBackupCreator();
|
|
||||||
backupFileCreator.CreateBackupFile(connectionFileName);
|
|
||||||
|
|
||||||
var backupPruner = new FileBackupPruner();
|
|
||||||
backupPruner.PruneBackupFiles(connectionFileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
ConnectionsService.LoadConnections(Settings.Default.UseSQLServer, false, connectionFileName);
|
ConnectionsService.LoadConnections(Settings.Default.UseSQLServer, false, connectionFileName);
|
||||||
|
|
||||||
if (Settings.Default.UseSQLServer)
|
if (Settings.Default.UseSQLServer)
|
||||||
{
|
{
|
||||||
ConnectionsService.LastSqlUpdate = DateTime.Now;
|
ConnectionsService.LastSqlUpdate = DateTime.Now;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
if (connectionFileName == ConnectionsService.GetDefaultStartupConnectionFileName())
|
|
||||||
{
|
|
||||||
Settings.Default.LoadConsFromCustomLocation = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Settings.Default.LoadConsFromCustomLocation = true;
|
|
||||||
Settings.Default.CustomConsPath = connectionFileName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// re-enable sql update checking after updates are loaded
|
// re-enable sql update checking after updates are loaded
|
||||||
ConnectionsService.RemoteConnectionsSyncronizer?.Enable();
|
ConnectionsService.RemoteConnectionsSyncronizer?.Enable();
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
using mRemoteNG.UI.Forms;
|
using System;
|
||||||
using mRemoteNG.UI.Window;
|
|
||||||
using System;
|
|
||||||
using mRemoteNG.Messages;
|
using mRemoteNG.Messages;
|
||||||
using mRemoteNG.UI;
|
using mRemoteNG.UI;
|
||||||
|
using mRemoteNG.UI.Forms;
|
||||||
|
using mRemoteNG.UI.Window;
|
||||||
|
|
||||||
namespace mRemoteNG.App
|
namespace mRemoteNG.App
|
||||||
{
|
{
|
||||||
@@ -15,8 +15,14 @@ namespace mRemoteNG.App
|
|||||||
private static PortScanWindow _portscanForm;
|
private static PortScanWindow _portscanForm;
|
||||||
private static UltraVNCWindow _ultravncscForm;
|
private static UltraVNCWindow _ultravncscForm;
|
||||||
private static ComponentsCheckWindow _componentscheckForm;
|
private static ComponentsCheckWindow _componentscheckForm;
|
||||||
|
private static ConnectionTreeWindow _treeForm;
|
||||||
|
|
||||||
|
internal static ConnectionTreeWindow TreeForm
|
||||||
|
{
|
||||||
|
get => _treeForm ?? (_treeForm = new ConnectionTreeWindow());
|
||||||
|
set => _treeForm = value;
|
||||||
|
}
|
||||||
|
|
||||||
internal static ConnectionTreeWindow TreeForm { get; set; } = new ConnectionTreeWindow();
|
|
||||||
internal static ConfigWindow ConfigForm { get; set; } = new ConfigWindow();
|
internal static ConfigWindow ConfigForm { get; set; } = new ConfigWindow();
|
||||||
internal static ErrorAndInfoWindow ErrorsForm { get; set; } = new ErrorAndInfoWindow();
|
internal static ErrorAndInfoWindow ErrorsForm { get; set; } = new ErrorAndInfoWindow();
|
||||||
internal static ScreenshotManagerWindow ScreenshotForm { get; set; } = new ScreenshotManagerWindow();
|
internal static ScreenshotManagerWindow ScreenshotForm { get; set; } = new ScreenshotManagerWindow();
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ namespace mRemoteNG.Config.Connections
|
|||||||
/// The previous <see cref="ConnectionTreeModel"/> that is being
|
/// The previous <see cref="ConnectionTreeModel"/> that is being
|
||||||
/// unloaded.
|
/// unloaded.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Maybe<ConnectionTreeModel> PreviousConnectionTreeModel { get; }
|
public Optional<ConnectionTreeModel> PreviousConnectionTreeModel { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// True if the previous <see cref="ConnectionTreeModel"/> was loaded from
|
/// True if the previous <see cref="ConnectionTreeModel"/> was loaded from
|
||||||
@@ -37,7 +37,7 @@ namespace mRemoteNG.Config.Connections
|
|||||||
public string NewSourcePath { get; }
|
public string NewSourcePath { get; }
|
||||||
|
|
||||||
public ConnectionsLoadedEventArgs(
|
public ConnectionsLoadedEventArgs(
|
||||||
Maybe<ConnectionTreeModel> previousTreeModelModel, ConnectionTreeModel newTreeModelModel,
|
Optional<ConnectionTreeModel> previousTreeModelModel, ConnectionTreeModel newTreeModelModel,
|
||||||
bool previousSourceWasDatabase, bool newSourceIsDatabase,
|
bool previousSourceWasDatabase, bool newSourceIsDatabase,
|
||||||
string newSourcePath)
|
string newSourcePath)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using mRemoteNG.App;
|
using mRemoteNG.App;
|
||||||
using mRemoteNG.Config.DataProviders;
|
using mRemoteNG.Config.DataProviders;
|
||||||
using mRemoteNG.Config.Serializers;
|
using mRemoteNG.Config.Serializers;
|
||||||
|
using mRemoteNG.Config.Serializers.Csv;
|
||||||
using mRemoteNG.Security;
|
using mRemoteNG.Security;
|
||||||
using mRemoteNG.Tree;
|
using mRemoteNG.Tree;
|
||||||
|
|
||||||
@@ -23,7 +24,7 @@ namespace mRemoteNG.Config.Connections
|
|||||||
_saveFilter = saveFilter;
|
_saveFilter = saveFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Save(ConnectionTreeModel connectionTreeModel)
|
public void Save(ConnectionTreeModel connectionTreeModel, string propertyNameTrigger = "")
|
||||||
{
|
{
|
||||||
var csvConnectionsSerializer = new CsvConnectionsSerializerMremotengFormat(_saveFilter, Runtime.CredentialProviderCatalog);
|
var csvConnectionsSerializer = new CsvConnectionsSerializerMremotengFormat(_saveFilter, Runtime.CredentialProviderCatalog);
|
||||||
var dataProvider = new FileDataProvider(_connectionFileName);
|
var dataProvider = new FileDataProvider(_connectionFileName);
|
||||||
|
|||||||
9
mRemoteV1/Config/Connections/IConnectionsLoader.cs
Normal file
9
mRemoteV1/Config/Connections/IConnectionsLoader.cs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
using mRemoteNG.Tree;
|
||||||
|
|
||||||
|
namespace mRemoteNG.Config.Connections
|
||||||
|
{
|
||||||
|
public interface IConnectionsLoader
|
||||||
|
{
|
||||||
|
ConnectionTreeModel Load();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using mRemoteNG.App;
|
||||||
|
using System;
|
||||||
using System.Timers;
|
using System.Timers;
|
||||||
using mRemoteNG.App;
|
|
||||||
// ReSharper disable ArrangeAccessorOwnerBody
|
// ReSharper disable ArrangeAccessorOwnerBody
|
||||||
|
|
||||||
namespace mRemoteNG.Config.Connections.Multiuser
|
namespace mRemoteNG.Config.Connections.Multiuser
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
using mRemoteNG.App;
|
using mRemoteNG.App;
|
||||||
|
using mRemoteNG.Config.Connections.Multiuser;
|
||||||
|
using mRemoteNG.Config.DatabaseConnectors;
|
||||||
using mRemoteNG.Messages;
|
using mRemoteNG.Messages;
|
||||||
using System;
|
using System;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
using System.Data.SqlClient;
|
using System.Data.SqlClient;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using mRemoteNG.Config.Connections.Multiuser;
|
|
||||||
using mRemoteNG.Config.DatabaseConnectors;
|
|
||||||
|
|
||||||
namespace mRemoteNG.Config.Connections
|
namespace mRemoteNG.Config.Connections
|
||||||
{
|
{
|
||||||
@@ -13,7 +13,7 @@ namespace mRemoteNG.Config.Connections
|
|||||||
{
|
{
|
||||||
private readonly SqlDatabaseConnector _sqlConnector;
|
private readonly SqlDatabaseConnector _sqlConnector;
|
||||||
private readonly SqlCommand _sqlQuery;
|
private readonly SqlCommand _sqlQuery;
|
||||||
private DateTime _lastUpdateTime;
|
private DateTime LastUpdateTime => Runtime.ConnectionsService.LastSqlUpdate;
|
||||||
private DateTime _lastDatabaseUpdateTime;
|
private DateTime _lastDatabaseUpdateTime;
|
||||||
|
|
||||||
|
|
||||||
@@ -21,7 +21,6 @@ namespace mRemoteNG.Config.Connections
|
|||||||
{
|
{
|
||||||
_sqlConnector = DatabaseConnectorFactory.SqlDatabaseConnectorFromSettings();
|
_sqlConnector = DatabaseConnectorFactory.SqlDatabaseConnectorFromSettings();
|
||||||
_sqlQuery = new SqlCommand("SELECT * FROM tblUpdate", _sqlConnector.SqlConnection);
|
_sqlQuery = new SqlCommand("SELECT * FROM tblUpdate", _sqlConnector.SqlConnection);
|
||||||
_lastUpdateTime = default(DateTime);
|
|
||||||
_lastDatabaseUpdateTime = default(DateTime);
|
_lastDatabaseUpdateTime = default(DateTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,14 +57,14 @@ namespace mRemoteNG.Config.Connections
|
|||||||
private bool DatabaseIsMoreUpToDateThanUs()
|
private bool DatabaseIsMoreUpToDateThanUs()
|
||||||
{
|
{
|
||||||
var lastUpdateInDb = GetLastUpdateTimeFromDbResponse();
|
var lastUpdateInDb = GetLastUpdateTimeFromDbResponse();
|
||||||
var IAmTheLastoneUpdated = CheckIfIAmTheLastOneUpdated(lastUpdateInDb);
|
var amTheLastoneUpdated = CheckIfIAmTheLastOneUpdated(lastUpdateInDb);
|
||||||
return (lastUpdateInDb > _lastUpdateTime && !IAmTheLastoneUpdated);
|
return (lastUpdateInDb > LastUpdateTime && !amTheLastoneUpdated);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool CheckIfIAmTheLastOneUpdated(DateTime lastUpdateInDb)
|
private bool CheckIfIAmTheLastOneUpdated(DateTime lastUpdateInDb)
|
||||||
{
|
{
|
||||||
DateTime LastSqlUpdateWithoutMilliseconds = new DateTime(Runtime.ConnectionsService.LastSqlUpdate.Ticks - (Runtime.ConnectionsService.LastSqlUpdate.Ticks % TimeSpan.TicksPerSecond), Runtime.ConnectionsService.LastSqlUpdate.Kind);
|
DateTime lastSqlUpdateWithoutMilliseconds = new DateTime(LastUpdateTime.Ticks - (LastUpdateTime.Ticks % TimeSpan.TicksPerSecond), LastUpdateTime.Kind);
|
||||||
return lastUpdateInDb == LastSqlUpdateWithoutMilliseconds;
|
return lastUpdateInDb == lastSqlUpdateWithoutMilliseconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
private DateTime GetLastUpdateTimeFromDbResponse()
|
private DateTime GetLastUpdateTimeFromDbResponse()
|
||||||
@@ -104,10 +103,9 @@ namespace mRemoteNG.Config.Connections
|
|||||||
public event ConnectionsUpdateAvailableEventHandler ConnectionsUpdateAvailable;
|
public event ConnectionsUpdateAvailableEventHandler ConnectionsUpdateAvailable;
|
||||||
private void RaiseConnectionsUpdateAvailableEvent()
|
private void RaiseConnectionsUpdateAvailableEvent()
|
||||||
{
|
{
|
||||||
|
Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, "Remote connection update is available");
|
||||||
var args = new ConnectionsUpdateAvailableEventArgs(_sqlConnector, _lastDatabaseUpdateTime);
|
var args = new ConnectionsUpdateAvailableEventArgs(_sqlConnector, _lastDatabaseUpdateTime);
|
||||||
ConnectionsUpdateAvailable?.Invoke(this, args);
|
ConnectionsUpdateAvailable?.Invoke(this, args);
|
||||||
if(args.Handled)
|
|
||||||
_lastUpdateTime = _lastDatabaseUpdateTime;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using mRemoteNG.Connection;
|
using mRemoteNG.Connection;
|
||||||
|
using mRemoteNG.UI.Forms;
|
||||||
|
|
||||||
namespace mRemoteNG.Config.Connections
|
namespace mRemoteNG.Config.Connections
|
||||||
{
|
{
|
||||||
@@ -20,10 +21,9 @@ namespace mRemoteNG.Config.Connections
|
|||||||
|
|
||||||
private void ConnectionsServiceOnConnectionsLoaded(object sender, ConnectionsLoadedEventArgs connectionsLoadedEventArgs)
|
private void ConnectionsServiceOnConnectionsLoaded(object sender, ConnectionsLoadedEventArgs connectionsLoadedEventArgs)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
connectionsLoadedEventArgs.NewConnectionTreeModel.CollectionChanged += ConnectionTreeModelOnCollectionChanged;
|
connectionsLoadedEventArgs.NewConnectionTreeModel.CollectionChanged += ConnectionTreeModelOnCollectionChanged;
|
||||||
connectionsLoadedEventArgs.NewConnectionTreeModel.PropertyChanged += ConnectionTreeModelOnPropertyChanged;
|
connectionsLoadedEventArgs.NewConnectionTreeModel.PropertyChanged += ConnectionTreeModelOnPropertyChanged;
|
||||||
|
|
||||||
foreach (var oldTree in connectionsLoadedEventArgs.PreviousConnectionTreeModel)
|
foreach (var oldTree in connectionsLoadedEventArgs.PreviousConnectionTreeModel)
|
||||||
{
|
{
|
||||||
oldTree.CollectionChanged -= ConnectionTreeModelOnCollectionChanged;
|
oldTree.CollectionChanged -= ConnectionTreeModelOnCollectionChanged;
|
||||||
@@ -33,7 +33,7 @@ namespace mRemoteNG.Config.Connections
|
|||||||
|
|
||||||
private void ConnectionTreeModelOnPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs)
|
private void ConnectionTreeModelOnPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs)
|
||||||
{
|
{
|
||||||
SaveConnectionOnEdit();
|
SaveConnectionOnEdit(propertyChangedEventArgs.PropertyName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ConnectionTreeModelOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs)
|
private void ConnectionTreeModelOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs)
|
||||||
@@ -41,11 +41,14 @@ namespace mRemoteNG.Config.Connections
|
|||||||
SaveConnectionOnEdit();
|
SaveConnectionOnEdit();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SaveConnectionOnEdit()
|
private void SaveConnectionOnEdit(string propertyName = "")
|
||||||
{
|
{
|
||||||
if (!mRemoteNG.Settings.Default.SaveConnectionsAfterEveryEdit)
|
if (!mRemoteNG.Settings.Default.SaveConnectionsAfterEveryEdit)
|
||||||
return;
|
return;
|
||||||
_connectionsService.SaveConnections();
|
if (FrmMain.Default.IsClosing)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_connectionsService.SaveConnectionsAsync(propertyName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,22 +1,96 @@
|
|||||||
using mRemoteNG.Config.DatabaseConnectors;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Security;
|
||||||
|
using mRemoteNG.Config.DatabaseConnectors;
|
||||||
using mRemoteNG.Config.DataProviders;
|
using mRemoteNG.Config.DataProviders;
|
||||||
using mRemoteNG.Config.Serializers;
|
using mRemoteNG.Config.Serializers;
|
||||||
|
using mRemoteNG.Config.Serializers.MsSql;
|
||||||
using mRemoteNG.Config.Serializers.Versioning;
|
using mRemoteNG.Config.Serializers.Versioning;
|
||||||
|
using mRemoteNG.Container;
|
||||||
|
using mRemoteNG.Security;
|
||||||
|
using mRemoteNG.Security.Authentication;
|
||||||
|
using mRemoteNG.Security.SymmetricEncryption;
|
||||||
|
using mRemoteNG.Tools;
|
||||||
using mRemoteNG.Tree;
|
using mRemoteNG.Tree;
|
||||||
|
using mRemoteNG.Tree.Root;
|
||||||
|
|
||||||
namespace mRemoteNG.Config.Connections
|
namespace mRemoteNG.Config.Connections
|
||||||
{
|
{
|
||||||
public class SqlConnectionsLoader
|
public class SqlConnectionsLoader : IConnectionsLoader
|
||||||
{
|
{
|
||||||
|
private readonly IDeserializer<string, IEnumerable<LocalConnectionPropertiesModel>> _localConnectionPropertiesDeserializer;
|
||||||
|
private readonly IDataProvider<string> _dataProvider;
|
||||||
|
|
||||||
|
public Func<Optional<SecureString>> AuthenticationRequestor { get; set; } =
|
||||||
|
() => MiscTools.PasswordDialog("", false);
|
||||||
|
|
||||||
|
public SqlConnectionsLoader(
|
||||||
|
IDeserializer<string, IEnumerable<LocalConnectionPropertiesModel>> localConnectionPropertiesDeserializer,
|
||||||
|
IDataProvider<string> dataProvider)
|
||||||
|
{
|
||||||
|
_localConnectionPropertiesDeserializer = localConnectionPropertiesDeserializer.ThrowIfNull(nameof(localConnectionPropertiesDeserializer));
|
||||||
|
_dataProvider = dataProvider.ThrowIfNull(nameof(dataProvider));
|
||||||
|
}
|
||||||
|
|
||||||
public ConnectionTreeModel Load()
|
public ConnectionTreeModel Load()
|
||||||
{
|
{
|
||||||
var connector = DatabaseConnectorFactory.SqlDatabaseConnectorFromSettings();
|
var connector = DatabaseConnectorFactory.SqlDatabaseConnectorFromSettings();
|
||||||
var dataProvider = new SqlDataProvider(connector);
|
var dataProvider = new SqlDataProvider(connector);
|
||||||
|
var metaDataRetriever = new SqlDatabaseMetaDataRetriever();
|
||||||
var databaseVersionVerifier = new SqlDatabaseVersionVerifier(connector);
|
var databaseVersionVerifier = new SqlDatabaseVersionVerifier(connector);
|
||||||
databaseVersionVerifier.VerifyDatabaseVersion();
|
var cryptoProvider = new LegacyRijndaelCryptographyProvider();
|
||||||
|
|
||||||
|
var metaData = metaDataRetriever.GetDatabaseMetaData(connector) ??
|
||||||
|
HandleFirstRun(metaDataRetriever, connector);
|
||||||
|
var decryptionKey = GetDecryptionKey(metaData);
|
||||||
|
|
||||||
|
if (!decryptionKey.Any())
|
||||||
|
throw new Exception("Could not load SQL connections");
|
||||||
|
|
||||||
|
databaseVersionVerifier.VerifyDatabaseVersion(metaData.ConfVersion);
|
||||||
var dataTable = dataProvider.Load();
|
var dataTable = dataProvider.Load();
|
||||||
var deserializer = new DataTableDeserializer();
|
var deserializer = new DataTableDeserializer(cryptoProvider, decryptionKey.First());
|
||||||
return deserializer.Deserialize(dataTable);
|
var connectionTree = deserializer.Deserialize(dataTable);
|
||||||
|
ApplyLocalConnectionProperties(connectionTree.RootNodes.First(i => i is RootNodeInfo));
|
||||||
|
return connectionTree;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<SecureString> GetDecryptionKey(SqlConnectionListMetaData metaData)
|
||||||
|
{
|
||||||
|
var cryptographyProvider = new LegacyRijndaelCryptographyProvider();
|
||||||
|
var cipherText = metaData.Protected;
|
||||||
|
var authenticator = new PasswordAuthenticator(cryptographyProvider, cipherText, AuthenticationRequestor);
|
||||||
|
var authenticated = authenticator.Authenticate(new RootNodeInfo(RootNodeType.Connection).DefaultPassword.ConvertToSecureString());
|
||||||
|
|
||||||
|
if (authenticated)
|
||||||
|
return authenticator.LastAuthenticatedPassword;
|
||||||
|
return Optional<SecureString>.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ApplyLocalConnectionProperties(ContainerInfo rootNode)
|
||||||
|
{
|
||||||
|
var localPropertiesXml = _dataProvider.Load();
|
||||||
|
var localConnectionProperties = _localConnectionPropertiesDeserializer.Deserialize(localPropertiesXml);
|
||||||
|
|
||||||
|
rootNode
|
||||||
|
.GetRecursiveChildList()
|
||||||
|
.Join(localConnectionProperties,
|
||||||
|
con => con.ConstantID,
|
||||||
|
locals => locals.ConnectionId,
|
||||||
|
(con, locals) => new {Connection = con, LocalProperties = locals})
|
||||||
|
.ForEach(x =>
|
||||||
|
{
|
||||||
|
x.Connection.PleaseConnect = x.LocalProperties.Connected;
|
||||||
|
if (x.Connection is ContainerInfo container)
|
||||||
|
container.IsExpanded = x.LocalProperties.Expanded;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private SqlConnectionListMetaData HandleFirstRun(SqlDatabaseMetaDataRetriever metaDataRetriever, SqlDatabaseConnector connector)
|
||||||
|
{
|
||||||
|
metaDataRetriever.WriteDatabaseMetaData(new RootNodeInfo(RootNodeType.Connection), connector);
|
||||||
|
return metaDataRetriever.GetDatabaseMetaData(connector);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,14 +1,16 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Data.SqlClient;
|
using System.Data.SqlClient;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Security;
|
|
||||||
using mRemoteNG.App;
|
using mRemoteNG.App;
|
||||||
using mRemoteNG.App.Info;
|
using mRemoteNG.App.Info;
|
||||||
using mRemoteNG.Config.DatabaseConnectors;
|
using mRemoteNG.Config.DatabaseConnectors;
|
||||||
using mRemoteNG.Config.DataProviders;
|
using mRemoteNG.Config.DataProviders;
|
||||||
using mRemoteNG.Config.Serializers;
|
using mRemoteNG.Config.Serializers;
|
||||||
|
using mRemoteNG.Config.Serializers.MsSql;
|
||||||
using mRemoteNG.Config.Serializers.Versioning;
|
using mRemoteNG.Config.Serializers.Versioning;
|
||||||
|
using mRemoteNG.Connection;
|
||||||
using mRemoteNG.Container;
|
using mRemoteNG.Container;
|
||||||
using mRemoteNG.Messages;
|
using mRemoteNG.Messages;
|
||||||
using mRemoteNG.Security;
|
using mRemoteNG.Security;
|
||||||
@@ -21,42 +23,88 @@ namespace mRemoteNG.Config.Connections
|
|||||||
{
|
{
|
||||||
public class SqlConnectionsSaver : ISaver<ConnectionTreeModel>
|
public class SqlConnectionsSaver : ISaver<ConnectionTreeModel>
|
||||||
{
|
{
|
||||||
private SecureString _password = Runtime.EncryptionKey;
|
|
||||||
private readonly SaveFilter _saveFilter;
|
private readonly SaveFilter _saveFilter;
|
||||||
|
private readonly ISerializer<IEnumerable<LocalConnectionPropertiesModel>, string> _localPropertiesSerializer;
|
||||||
|
private readonly IDataProvider<string> _dataProvider;
|
||||||
|
|
||||||
public SqlConnectionsSaver(SaveFilter saveFilter)
|
public SqlConnectionsSaver(
|
||||||
|
SaveFilter saveFilter,
|
||||||
|
ISerializer<IEnumerable<LocalConnectionPropertiesModel>, string> localPropertieSerializer,
|
||||||
|
IDataProvider<string> localPropertiesDataProvider)
|
||||||
{
|
{
|
||||||
if (saveFilter == null)
|
if (saveFilter == null)
|
||||||
throw new ArgumentNullException(nameof(saveFilter));
|
throw new ArgumentNullException(nameof(saveFilter));
|
||||||
_saveFilter = saveFilter;
|
_saveFilter = saveFilter;
|
||||||
|
_localPropertiesSerializer = localPropertieSerializer.ThrowIfNull(nameof(localPropertieSerializer));
|
||||||
|
_dataProvider = localPropertiesDataProvider.ThrowIfNull(nameof(localPropertiesDataProvider));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Save(ConnectionTreeModel connectionTreeModel)
|
public void Save(ConnectionTreeModel connectionTreeModel, string propertyNameTrigger = "")
|
||||||
{
|
{
|
||||||
|
var rootTreeNode = connectionTreeModel.RootNodes.OfType<RootNodeInfo>().First();
|
||||||
|
|
||||||
|
UpdateLocalConnectionProperties(rootTreeNode);
|
||||||
|
|
||||||
|
if (PropertyIsLocalOnly(propertyNameTrigger))
|
||||||
|
{
|
||||||
|
Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg,
|
||||||
|
$"Property {propertyNameTrigger} is local only. Not saving to database.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (SqlUserIsReadOnly())
|
if (SqlUserIsReadOnly())
|
||||||
{
|
{
|
||||||
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, "Trying to save connection tree but the SQL read only checkbox is checked, aborting!");
|
Runtime.MessageCollector.AddMessage(MessageClass.InformationMsg, "Trying to save connection tree but the SQL read only checkbox is checked, aborting!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
using (var sqlConnector = DatabaseConnectorFactory.SqlDatabaseConnectorFromSettings())
|
using (var sqlConnector = DatabaseConnectorFactory.SqlDatabaseConnectorFromSettings())
|
||||||
{
|
{
|
||||||
sqlConnector.Connect();
|
sqlConnector.Connect();
|
||||||
var databaseVersionVerifier = new SqlDatabaseVersionVerifier(sqlConnector);
|
var databaseVersionVerifier = new SqlDatabaseVersionVerifier(sqlConnector);
|
||||||
|
var metaDataRetriever = new SqlDatabaseMetaDataRetriever();
|
||||||
|
var metaData = metaDataRetriever.GetDatabaseMetaData(sqlConnector);
|
||||||
|
|
||||||
if (!databaseVersionVerifier.VerifyDatabaseVersion())
|
if (!databaseVersionVerifier.VerifyDatabaseVersion(metaData.ConfVersion))
|
||||||
{
|
{
|
||||||
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, Language.strErrorConnectionListSaveFailed);
|
Runtime.MessageCollector.AddMessage(MessageClass.ErrorMsg, Language.strErrorConnectionListSaveFailed);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var rootTreeNode = connectionTreeModel.RootNodes.OfType<RootNodeInfo>().First();
|
metaDataRetriever.WriteDatabaseMetaData(rootTreeNode, sqlConnector);
|
||||||
|
|
||||||
UpdateRootNodeTable(rootTreeNode, sqlConnector);
|
|
||||||
UpdateConnectionsTable(rootTreeNode, sqlConnector);
|
UpdateConnectionsTable(rootTreeNode, sqlConnector);
|
||||||
UpdateUpdatesTable(sqlConnector);
|
UpdateUpdatesTable(sqlConnector);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, "Saved connections to database");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines if a given property name should be only saved
|
||||||
|
/// locally.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="property">
|
||||||
|
/// The name of the property that triggered the save event
|
||||||
|
/// </param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private bool PropertyIsLocalOnly(string property)
|
||||||
|
{
|
||||||
|
return property == nameof(ConnectionInfo.OpenConnections) ||
|
||||||
|
property == nameof(ContainerInfo.IsExpanded);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateLocalConnectionProperties(ContainerInfo rootNode)
|
||||||
|
{
|
||||||
|
var a = rootNode.GetRecursiveChildList().Select(info => new LocalConnectionPropertiesModel
|
||||||
|
{
|
||||||
|
ConnectionId = info.ConstantID,
|
||||||
|
Connected = info.OpenConnections.Count > 0,
|
||||||
|
Expanded = info is ContainerInfo c && c.IsExpanded
|
||||||
|
});
|
||||||
|
|
||||||
|
var serializedProperties = _localPropertiesSerializer.Serialize(a);
|
||||||
|
_dataProvider.Save(serializedProperties);
|
||||||
|
Runtime.MessageCollector.AddMessage(MessageClass.DebugMsg, "Saved local connection properties");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateRootNodeTable(RootNodeInfo rootTreeNode, SqlDatabaseConnector sqlDatabaseConnector)
|
private void UpdateRootNodeTable(RootNodeInfo rootTreeNode, SqlDatabaseConnector sqlDatabaseConnector)
|
||||||
@@ -67,17 +115,17 @@ namespace mRemoteNG.Config.Connections
|
|||||||
{
|
{
|
||||||
if (rootTreeNode.Password)
|
if (rootTreeNode.Password)
|
||||||
{
|
{
|
||||||
_password = rootTreeNode.PasswordString.ConvertToSecureString();
|
var password = rootTreeNode.PasswordString.ConvertToSecureString();
|
||||||
strProtected = cryptographyProvider.Encrypt("ThisIsProtected", _password);
|
strProtected = cryptographyProvider.Encrypt("ThisIsProtected", password);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
strProtected = cryptographyProvider.Encrypt("ThisIsNotProtected", _password);
|
strProtected = cryptographyProvider.Encrypt("ThisIsNotProtected", Runtime.EncryptionKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
strProtected = cryptographyProvider.Encrypt("ThisIsNotProtected", _password);
|
strProtected = cryptographyProvider.Encrypt("ThisIsNotProtected", Runtime.EncryptionKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
var sqlQuery = new SqlCommand("DELETE FROM tblRoot", sqlDatabaseConnector.SqlConnection);
|
var sqlQuery = new SqlCommand("DELETE FROM tblRoot", sqlDatabaseConnector.SqlConnection);
|
||||||
@@ -99,13 +147,15 @@ namespace mRemoteNG.Config.Connections
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateConnectionsTable(ContainerInfo rootTreeNode, SqlDatabaseConnector sqlDatabaseConnector)
|
private void UpdateConnectionsTable(RootNodeInfo rootTreeNode, SqlDatabaseConnector sqlDatabaseConnector)
|
||||||
{
|
{
|
||||||
var sqlQuery = new SqlCommand("DELETE FROM tblCons", sqlDatabaseConnector.SqlConnection);
|
var cryptoProvider = new LegacyRijndaelCryptographyProvider();
|
||||||
sqlQuery.ExecuteNonQuery();
|
var serializer = new DataTableSerializer(_saveFilter, cryptoProvider, rootTreeNode.PasswordString.ConvertToSecureString());
|
||||||
var serializer = new DataTableSerializer(_saveFilter);
|
|
||||||
var dataTable = serializer.Serialize(rootTreeNode);
|
var dataTable = serializer.Serialize(rootTreeNode);
|
||||||
var dataProvider = new SqlDataProvider(sqlDatabaseConnector);
|
var dataProvider = new SqlDataProvider(sqlDatabaseConnector);
|
||||||
|
|
||||||
|
var sqlQuery = new SqlCommand("DELETE FROM tblCons", sqlDatabaseConnector.SqlConnection);
|
||||||
|
sqlQuery.ExecuteNonQuery();
|
||||||
dataProvider.Save(dataTable);
|
dataProvider.Save(dataTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
using System;
|
using mRemoteNG.Config.DataProviders;
|
||||||
using System.Security;
|
using mRemoteNG.Config.Serializers.Xml;
|
||||||
using mRemoteNG.Config.DataProviders;
|
|
||||||
using mRemoteNG.Config.Serializers;
|
|
||||||
using mRemoteNG.Tools;
|
using mRemoteNG.Tools;
|
||||||
using mRemoteNG.Tree;
|
using mRemoteNG.Tree;
|
||||||
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Security;
|
||||||
|
|
||||||
namespace mRemoteNG.Config.Connections
|
namespace mRemoteNG.Config.Connections
|
||||||
{
|
{
|
||||||
public class XmlConnectionsLoader
|
public class XmlConnectionsLoader : IConnectionsLoader
|
||||||
{
|
{
|
||||||
private readonly string _connectionFilePath;
|
private readonly string _connectionFilePath;
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ namespace mRemoteNG.Config.Connections
|
|||||||
return deserializer.Deserialize(xmlString);
|
return deserializer.Deserialize(xmlString);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SecureString PromptForPassword()
|
private Optional<SecureString> PromptForPassword()
|
||||||
{
|
{
|
||||||
var password = MiscTools.PasswordDialog("", false);
|
var password = MiscTools.PasswordDialog("", false);
|
||||||
return password;
|
return password;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.Linq;
|
|||||||
using mRemoteNG.App;
|
using mRemoteNG.App;
|
||||||
using mRemoteNG.Config.DataProviders;
|
using mRemoteNG.Config.DataProviders;
|
||||||
using mRemoteNG.Config.Serializers;
|
using mRemoteNG.Config.Serializers;
|
||||||
|
using mRemoteNG.Config.Serializers.Xml;
|
||||||
using mRemoteNG.Security;
|
using mRemoteNG.Security;
|
||||||
using mRemoteNG.Security.Factories;
|
using mRemoteNG.Security.Factories;
|
||||||
using mRemoteNG.Tree;
|
using mRemoteNG.Tree;
|
||||||
@@ -26,7 +27,7 @@ namespace mRemoteNG.Config.Connections
|
|||||||
_saveFilter = saveFilter;
|
_saveFilter = saveFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Save(ConnectionTreeModel connectionTreeModel)
|
public void Save(ConnectionTreeModel connectionTreeModel, string propertyNameTrigger = "")
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ namespace mRemoteNG.Config
|
|||||||
_dataProvider = dataProvider;
|
_dataProvider = dataProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Save(IEnumerable<ICredentialRepository> repositories)
|
public void Save(IEnumerable<ICredentialRepository> repositories, string propertyNameTrigger = "")
|
||||||
{
|
{
|
||||||
var serializer = new CredentialRepositoryListSerializer();
|
var serializer = new CredentialRepositoryListSerializer();
|
||||||
var data = serializer.Serialize(repositories);
|
var data = serializer.Serialize(repositories);
|
||||||
|
|||||||
@@ -1,26 +1,29 @@
|
|||||||
using System;
|
using System.IO;
|
||||||
using System.IO;
|
using System.Linq;
|
||||||
|
|
||||||
namespace mRemoteNG.Config.DataProviders
|
namespace mRemoteNG.Config.DataProviders
|
||||||
{
|
{
|
||||||
public class FileBackupPruner
|
public class FileBackupPruner
|
||||||
{
|
{
|
||||||
public void PruneBackupFiles(string baseName)
|
public void PruneBackupFiles(string filePath, int maxBackupsToKeep)
|
||||||
{
|
{
|
||||||
var fileName = Path.GetFileName(baseName);
|
var fileName = Path.GetFileName(filePath);
|
||||||
var directoryName = Path.GetDirectoryName(baseName);
|
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 searchPattern = string.Format(mRemoteNG.Settings.Default.BackupFileNameFormat, fileName, "*");
|
||||||
var files = Directory.GetFiles(directoryName, searchPattern);
|
var files = Directory.GetFiles(directoryName, searchPattern);
|
||||||
|
|
||||||
if (files.Length <= mRemoteNG.Settings.Default.BackupFileKeepCount) return;
|
if (files.Length <= maxBackupsToKeep)
|
||||||
|
return;
|
||||||
|
|
||||||
Array.Sort(files);
|
var filesToDelete = files
|
||||||
Array.Resize(ref files, files.Length - mRemoteNG.Settings.Default.BackupFileKeepCount);
|
.OrderByDescending(s => s)
|
||||||
|
.Skip(maxBackupsToKeep);
|
||||||
|
|
||||||
foreach (var file in files)
|
foreach (var file in filesToDelete)
|
||||||
{
|
{
|
||||||
File.Delete(file);
|
File.Delete(file);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,6 @@
|
|||||||
{
|
{
|
||||||
public interface ISaver<in T>
|
public interface ISaver<in T>
|
||||||
{
|
{
|
||||||
void Save(T model);
|
void Save(T model, string propertyNameTrigger = "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using mRemoteNG.App;
|
using mRemoteNG.App;
|
||||||
using mRemoteNG.Config.DataProviders;
|
using mRemoteNG.Config.DataProviders;
|
||||||
using mRemoteNG.Config.Serializers.MiscSerializers;
|
using mRemoteNG.Config.Serializers.Csv;
|
||||||
using mRemoteNG.Container;
|
using mRemoteNG.Container;
|
||||||
using mRemoteNG.Messages;
|
using mRemoteNG.Messages;
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.Linq;
|
|||||||
using mRemoteNG.App;
|
using mRemoteNG.App;
|
||||||
using mRemoteNG.Config.DataProviders;
|
using mRemoteNG.Config.DataProviders;
|
||||||
using mRemoteNG.Config.Serializers;
|
using mRemoteNG.Config.Serializers;
|
||||||
|
using mRemoteNG.Config.Serializers.Xml;
|
||||||
using mRemoteNG.Container;
|
using mRemoteNG.Container;
|
||||||
using mRemoteNG.Messages;
|
using mRemoteNG.Messages;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using mRemoteNG.Tools;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
|
using mRemoteNG.Tools;
|
||||||
using mRemoteNG.Tree.Root;
|
using mRemoteNG.Tree.Root;
|
||||||
// ReSharper disable ArrangeAccessorOwnerBody
|
// ReSharper disable ArrangeAccessorOwnerBody
|
||||||
|
|
||||||
@@ -35,10 +35,12 @@ namespace mRemoteNG.Config.Putty
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void AddSessionsFromProvider(AbstractPuttySessionsProvider provider)
|
private void AddSessionsFromProvider(AbstractPuttySessionsProvider puttySessionProvider)
|
||||||
{
|
{
|
||||||
var rootTreeNode = provider.RootInfo;
|
puttySessionProvider.ThrowIfNull(nameof(puttySessionProvider));
|
||||||
provider.GetSessions();
|
|
||||||
|
var rootTreeNode = puttySessionProvider.RootInfo;
|
||||||
|
puttySessionProvider.GetSessions();
|
||||||
|
|
||||||
if (!RootPuttySessionsNodes.Contains(rootTreeNode) && rootTreeNode.HasChildren())
|
if (!RootPuttySessionsNodes.Contains(rootTreeNode) && rootTreeNode.HasChildren())
|
||||||
RootPuttySessionsNodes.Add(rootTreeNode);
|
RootPuttySessionsNodes.Add(rootTreeNode);
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
using Microsoft.Win32;
|
|
||||||
using mRemoteNG.App;
|
|
||||||
using mRemoteNG.Connection;
|
|
||||||
using mRemoteNG.Connection.Protocol;
|
|
||||||
using mRemoteNG.Messages;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Management;
|
using System.Management;
|
||||||
using System.Security.Principal;
|
using System.Security.Principal;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Web;
|
using System.Web;
|
||||||
|
using Microsoft.Win32;
|
||||||
|
using mRemoteNG.App;
|
||||||
|
using mRemoteNG.Connection;
|
||||||
|
using mRemoteNG.Connection.Protocol;
|
||||||
|
using mRemoteNG.Messages;
|
||||||
|
|
||||||
|
|
||||||
namespace mRemoteNG.Config.Putty
|
namespace mRemoteNG.Config.Putty
|
||||||
@@ -40,6 +40,9 @@ namespace mRemoteNG.Config.Putty
|
|||||||
|
|
||||||
public override PuttySessionInfo GetSession(string sessionName)
|
public override PuttySessionInfo GetSession(string sessionName)
|
||||||
{
|
{
|
||||||
|
if (string.IsNullOrEmpty(sessionName))
|
||||||
|
return null;
|
||||||
|
|
||||||
var sessionsKey = Registry.CurrentUser.OpenSubKey(PuttySessionsKey);
|
var sessionsKey = Registry.CurrentUser.OpenSubKey(PuttySessionsKey);
|
||||||
var sessionKey = sessionsKey?.OpenSubKey(sessionName);
|
var sessionKey = sessionsKey?.OpenSubKey(sessionName);
|
||||||
if (sessionKey == null) return null;
|
if (sessionKey == null) return null;
|
||||||
@@ -50,10 +53,15 @@ namespace mRemoteNG.Config.Putty
|
|||||||
{
|
{
|
||||||
PuttySession = sessionName,
|
PuttySession = sessionName,
|
||||||
Name = sessionName,
|
Name = sessionName,
|
||||||
Hostname = Convert.ToString(sessionKey.GetValue("HostName")),
|
Hostname = sessionKey.GetValue("HostName")?.ToString() ?? "",
|
||||||
Username = Convert.ToString(sessionKey.GetValue("UserName"))
|
Username = sessionKey.GetValue("UserName")?.ToString() ?? ""
|
||||||
};
|
};
|
||||||
var protocol = Convert.ToString(sessionKey.GetValue("Protocol")) ?? "ssh";
|
|
||||||
|
|
||||||
|
var protocol = string.IsNullOrEmpty(sessionKey.GetValue("Protocol")?.ToString())
|
||||||
|
? "ssh"
|
||||||
|
: sessionKey.GetValue("Protocol").ToString();
|
||||||
|
|
||||||
switch (protocol.ToLowerInvariant())
|
switch (protocol.ToLowerInvariant())
|
||||||
{
|
{
|
||||||
case "raw":
|
case "raw":
|
||||||
@@ -65,16 +73,15 @@ namespace mRemoteNG.Config.Putty
|
|||||||
case "serial":
|
case "serial":
|
||||||
return null;
|
return null;
|
||||||
case "ssh":
|
case "ssh":
|
||||||
var sshVersionObject = sessionKey.GetValue("SshProt");
|
int.TryParse(sessionKey.GetValue("SshProt")?.ToString(), out var sshVersion);
|
||||||
if (sshVersionObject != null)
|
/* Per PUTTY.H in PuTTYNG & PuTTYNG Upstream (PuTTY proper currently)
|
||||||
{
|
* expect 0 for SSH1, 3 for SSH2 ONLY
|
||||||
var sshVersion = Convert.ToInt32(sshVersionObject);
|
* 1 for SSH1 with a 2 fallback
|
||||||
sessionInfo.Protocol = sshVersion >= 2 ? ProtocolType.SSH2 : ProtocolType.SSH1;
|
* 2 for SSH2 with a 1 fallback
|
||||||
}
|
*
|
||||||
else
|
* default to SSH2 if any other value is received
|
||||||
{
|
*/
|
||||||
sessionInfo.Protocol = ProtocolType.SSH2;
|
sessionInfo.Protocol = sshVersion == 1 || sshVersion == 0 ? ProtocolType.SSH1 : ProtocolType.SSH2;
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case "telnet":
|
case "telnet":
|
||||||
sessionInfo.Protocol = ProtocolType.Telnet;
|
sessionInfo.Protocol = ProtocolType.Telnet;
|
||||||
@@ -82,7 +89,12 @@ namespace mRemoteNG.Config.Putty
|
|||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
sessionInfo.Port = Convert.ToInt32(sessionKey.GetValue("PortNumber"));
|
|
||||||
|
int.TryParse(sessionKey.GetValue("PortNumber")?.ToString(), out var portNumber);
|
||||||
|
if (portNumber == default(int))
|
||||||
|
sessionInfo.SetDefaultPort();
|
||||||
|
else
|
||||||
|
sessionInfo.Port = portNumber;
|
||||||
|
|
||||||
return sessionInfo;
|
return sessionInfo;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ namespace mRemoteNG.Config.Putty
|
|||||||
foreach (var sessionName in Directory.GetFiles(sessionsFolderPath))
|
foreach (var sessionName in Directory.GetFiles(sessionsFolderPath))
|
||||||
{
|
{
|
||||||
var sessionFileName = Path.GetFileName(sessionName);
|
var sessionFileName = Path.GetFileName(sessionName);
|
||||||
|
// ReSharper disable once ConstantConditionalAccessQualifier
|
||||||
sessionNames.Add(raw ? sessionFileName : System.Web.HttpUtility.UrlDecode(sessionFileName?.Replace("+", "%2B")));
|
sessionNames.Add(raw ? sessionFileName : System.Web.HttpUtility.UrlDecode(sessionFileName?.Replace("+", "%2B")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,9 +126,6 @@ namespace mRemoteNG.Config.Putty
|
|||||||
|
|
||||||
public override void StartWatcher()
|
public override void StartWatcher()
|
||||||
{
|
{
|
||||||
PuttySessionsRegistryProvider.StartWatcher();
|
|
||||||
PuttySessionsRegistryProvider.PuttySessionChanged += OnRegistrySessionChanged;
|
|
||||||
|
|
||||||
if (_eventWatcher != null)
|
if (_eventWatcher != null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -136,8 +134,13 @@ namespace mRemoteNG.Config.Putty
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var sessionsFolderPath = GetSessionsFolderPath();
|
var sessionsFolderPath = GetSessionsFolderPath();
|
||||||
if (Directory.Exists(sessionsFolderPath))
|
|
||||||
|
if (!Directory.Exists(sessionsFolderPath))
|
||||||
{
|
{
|
||||||
|
Runtime.MessageCollector.AddMessage(MessageClass.WarningMsg, $"XmingPortablePuttySessions.Watcher.StartWatching() failed: '{sessionsFolderPath}' does not exist.", true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_eventWatcher = new FileSystemWatcher(sessionsFolderPath)
|
_eventWatcher = new FileSystemWatcher(sessionsFolderPath)
|
||||||
{
|
{
|
||||||
NotifyFilter = NotifyFilters.FileName | NotifyFilters.LastWrite
|
NotifyFilter = NotifyFilters.FileName | NotifyFilters.LastWrite
|
||||||
@@ -147,7 +150,6 @@ namespace mRemoteNG.Config.Putty
|
|||||||
_eventWatcher.Deleted += OnFileSystemEventArrived;
|
_eventWatcher.Deleted += OnFileSystemEventArrived;
|
||||||
_eventWatcher.Renamed += OnFileSystemEventArrived;
|
_eventWatcher.Renamed += OnFileSystemEventArrived;
|
||||||
_eventWatcher.EnableRaisingEvents = true;
|
_eventWatcher.EnableRaisingEvents = true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -173,7 +175,8 @@ namespace mRemoteNG.Config.Putty
|
|||||||
private static string GetPuttyConfPath()
|
private static string GetPuttyConfPath()
|
||||||
{
|
{
|
||||||
var puttyPath = mRemoteNG.Settings.Default.UseCustomPuttyPath ? mRemoteNG.Settings.Default.CustomPuttyPath : App.Info.GeneralAppInfo.PuttyPath;
|
var puttyPath = mRemoteNG.Settings.Default.UseCustomPuttyPath ? mRemoteNG.Settings.Default.CustomPuttyPath : App.Info.GeneralAppInfo.PuttyPath;
|
||||||
return Path.Combine(Path.GetDirectoryName(puttyPath), "putty.conf");
|
puttyPath = Path.GetDirectoryName(puttyPath);
|
||||||
|
return string.IsNullOrEmpty(puttyPath) ? null : Path.Combine(puttyPath, "putty.conf");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetSessionsFolderPath()
|
private static string GetSessionsFolderPath()
|
||||||
@@ -200,6 +203,9 @@ namespace mRemoteNG.Config.Putty
|
|||||||
|
|
||||||
private static PuttySessionInfo ModifyRegistrySessionInfo(PuttySessionInfo sessionInfo)
|
private static PuttySessionInfo ModifyRegistrySessionInfo(PuttySessionInfo sessionInfo)
|
||||||
{
|
{
|
||||||
|
if (sessionInfo == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
sessionInfo.Name = string.Format(RegistrySessionNameFormat, sessionInfo.Name);
|
sessionInfo.Name = string.Format(RegistrySessionNameFormat, sessionInfo.Name);
|
||||||
sessionInfo.PuttySession = string.Format(RegistrySessionNameFormat, sessionInfo.PuttySession);
|
sessionInfo.PuttySession = string.Format(RegistrySessionNameFormat, sessionInfo.PuttySession);
|
||||||
return sessionInfo;
|
return sessionInfo;
|
||||||
|
|||||||
@@ -11,16 +11,16 @@ using mRemoteNG.Container;
|
|||||||
using mRemoteNG.Tree;
|
using mRemoteNG.Tree;
|
||||||
using mRemoteNG.Tree.Root;
|
using mRemoteNG.Tree.Root;
|
||||||
|
|
||||||
namespace mRemoteNG.Config.Serializers.MiscSerializers
|
namespace mRemoteNG.Config.Serializers.Csv
|
||||||
{
|
{
|
||||||
public class CsvConnectionsDeserializerMremotengFormat : IDeserializer<string, ConnectionTreeModel>
|
public class CsvConnectionsDeserializerMremotengFormat : IDeserializer<string, ConnectionTreeModel>
|
||||||
{
|
{
|
||||||
public ConnectionTreeModel Deserialize(string serializedData)
|
public ConnectionTreeModel Deserialize(string serializedData)
|
||||||
{
|
{
|
||||||
var root = new RootNodeInfo(RootNodeType.Connection);
|
|
||||||
|
|
||||||
var lines = serializedData.Split(new []{"\r\n", "\r", "\n"}, StringSplitOptions.RemoveEmptyEntries);
|
var lines = serializedData.Split(new []{"\r\n", "\r", "\n"}, StringSplitOptions.RemoveEmptyEntries);
|
||||||
var csvHeaders = new List<string>();
|
var csvHeaders = new List<string>();
|
||||||
|
// used to map a connectioninfo to it's parent's GUID
|
||||||
|
var parentMapping = new Dictionary<ConnectionInfo, string>();
|
||||||
|
|
||||||
for (var lineNumber = 0; lineNumber < lines.Length; lineNumber++)
|
for (var lineNumber = 0; lineNumber < lines.Length; lineNumber++)
|
||||||
{
|
{
|
||||||
@@ -30,39 +30,61 @@ namespace mRemoteNG.Config.Serializers.MiscSerializers
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
var connectionInfo = ParseConnectionInfo(csvHeaders, line);
|
var connectionInfo = ParseConnectionInfo(csvHeaders, line);
|
||||||
var folder = ParseConnectionFolder(line[csvHeaders.IndexOf("Folder")], root);
|
parentMapping.Add(connectionInfo, line[csvHeaders.IndexOf("Parent")]);
|
||||||
folder.AddChild(connectionInfo);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var root = CreateTreeStructure(parentMapping);
|
||||||
var connectionTreeModel = new ConnectionTreeModel();
|
var connectionTreeModel = new ConnectionTreeModel();
|
||||||
connectionTreeModel.AddRootNode(root);
|
connectionTreeModel.AddRootNode(root);
|
||||||
return connectionTreeModel;
|
return connectionTreeModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ContainerInfo ParseConnectionFolder(string folderString, ContainerInfo rootContainer)
|
private RootNodeInfo CreateTreeStructure(Dictionary<ConnectionInfo, string> parentMapping)
|
||||||
{
|
{
|
||||||
var containerNames = folderString.Split('\\');
|
var root = new RootNodeInfo(RootNodeType.Connection);
|
||||||
var parentContainer = rootContainer;
|
|
||||||
|
|
||||||
for (var i = containerNames.Length - 2; i >= 0; i--)
|
foreach (var node in parentMapping)
|
||||||
{
|
{
|
||||||
var containerName = containerNames[i];
|
// no parent mapped, add to root
|
||||||
var container = parentContainer.Children.OfType<ContainerInfo>().FirstOrDefault(info => info.Name == containerName);
|
if (string.IsNullOrEmpty(node.Value))
|
||||||
if (container == null)
|
|
||||||
{
|
{
|
||||||
container = new ContainerInfo {Name = containerName};
|
root.AddChild(node.Key);
|
||||||
parentContainer.AddChild(container);
|
continue;
|
||||||
}
|
|
||||||
parentContainer = container;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return parentContainer;
|
// search for parent in the list by GUID
|
||||||
|
var parent = parentMapping
|
||||||
|
.Keys
|
||||||
|
.OfType<ContainerInfo>()
|
||||||
|
.FirstOrDefault(info => info.ConstantID == node.Value);
|
||||||
|
|
||||||
|
if (parent != null)
|
||||||
|
{
|
||||||
|
parent.AddChild(node.Key);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
root.AddChild(node.Key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ConnectionInfo ParseConnectionInfo(IList<string> headers, string[] connectionCsv)
|
private ConnectionInfo ParseConnectionInfo(IList<string> headers, string[] connectionCsv)
|
||||||
{
|
{
|
||||||
var connectionRecord = new ConnectionInfo();
|
var nodeType = headers.Contains("NodeType")
|
||||||
|
? (TreeNodeType)Enum.Parse(typeof(TreeNodeType), connectionCsv[headers.IndexOf("NodeType")], true)
|
||||||
|
: TreeNodeType.Connection;
|
||||||
|
|
||||||
|
var nodeId = headers.Contains("Id")
|
||||||
|
? connectionCsv[headers.IndexOf("Id")]
|
||||||
|
: Guid.NewGuid().ToString();
|
||||||
|
|
||||||
|
var connectionRecord = nodeType == TreeNodeType.Connection
|
||||||
|
? new ConnectionInfo(nodeId)
|
||||||
|
: new ContainerInfo(nodeId);
|
||||||
|
|
||||||
connectionRecord.Name = headers.Contains("Name") ? connectionCsv[headers.IndexOf("Name")] : "";
|
connectionRecord.Name = headers.Contains("Name") ? connectionCsv[headers.IndexOf("Name")] : "";
|
||||||
connectionRecord.Description = headers.Contains("Description") ? connectionCsv[headers.IndexOf("Description")] : "";
|
connectionRecord.Description = headers.Contains("Description") ? connectionCsv[headers.IndexOf("Description")] : "";
|
||||||
@@ -131,21 +153,21 @@ namespace mRemoteNG.Config.Serializers.MiscSerializers
|
|||||||
|
|
||||||
if (headers.Contains("RDPAuthenticationLevel"))
|
if (headers.Contains("RDPAuthenticationLevel"))
|
||||||
{
|
{
|
||||||
RdpAuthenticationLevel value;
|
RdpProtocol.AuthenticationLevel value;
|
||||||
if (Enum.TryParse(connectionCsv[headers.IndexOf("RDPAuthenticationLevel")], out value))
|
if (Enum.TryParse(connectionCsv[headers.IndexOf("RDPAuthenticationLevel")], out value))
|
||||||
connectionRecord.RDPAuthenticationLevel = value;
|
connectionRecord.RDPAuthenticationLevel = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (headers.Contains("Colors"))
|
if (headers.Contains("Colors"))
|
||||||
{
|
{
|
||||||
RdpColors value;
|
RdpProtocol.RDPColors value;
|
||||||
if (Enum.TryParse(connectionCsv[headers.IndexOf("Colors")], out value))
|
if (Enum.TryParse(connectionCsv[headers.IndexOf("Colors")], out value))
|
||||||
connectionRecord.Colors = value;
|
connectionRecord.Colors = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (headers.Contains("Resolution"))
|
if (headers.Contains("Resolution"))
|
||||||
{
|
{
|
||||||
RdpResolutions value;
|
RdpProtocol.RDPResolutions value;
|
||||||
if (Enum.TryParse(connectionCsv[headers.IndexOf("Resolution")], out value))
|
if (Enum.TryParse(connectionCsv[headers.IndexOf("Resolution")], out value))
|
||||||
connectionRecord.Resolution = value;
|
connectionRecord.Resolution = value;
|
||||||
}
|
}
|
||||||
@@ -222,7 +244,7 @@ namespace mRemoteNG.Config.Serializers.MiscSerializers
|
|||||||
|
|
||||||
if (headers.Contains("RedirectSound"))
|
if (headers.Contains("RedirectSound"))
|
||||||
{
|
{
|
||||||
RdpSounds value;
|
RdpProtocol.RDPSounds value;
|
||||||
if (Enum.TryParse(connectionCsv[headers.IndexOf("RedirectSound")], out value))
|
if (Enum.TryParse(connectionCsv[headers.IndexOf("RedirectSound")], out value))
|
||||||
connectionRecord.RedirectSound = value;
|
connectionRecord.RedirectSound = value;
|
||||||
}
|
}
|
||||||
@@ -292,14 +314,14 @@ namespace mRemoteNG.Config.Serializers.MiscSerializers
|
|||||||
|
|
||||||
if (headers.Contains("RDGatewayUsageMethod"))
|
if (headers.Contains("RDGatewayUsageMethod"))
|
||||||
{
|
{
|
||||||
RDGatewayUsageMethod value;
|
RdpProtocol.RDGatewayUsageMethod value;
|
||||||
if (Enum.TryParse(connectionCsv[headers.IndexOf("RDGatewayUsageMethod")], out value))
|
if (Enum.TryParse(connectionCsv[headers.IndexOf("RDGatewayUsageMethod")], out value))
|
||||||
connectionRecord.RDGatewayUsageMethod = value;
|
connectionRecord.RDGatewayUsageMethod = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (headers.Contains("RDGatewayUseConnectionCredentials"))
|
if (headers.Contains("RDGatewayUseConnectionCredentials"))
|
||||||
{
|
{
|
||||||
RDGatewayUseConnectionCredentials value;
|
RdpProtocol.RDGatewayUseConnectionCredentials value;
|
||||||
if (Enum.TryParse(connectionCsv[headers.IndexOf("RDGatewayUseConnectionCredentials")], out value))
|
if (Enum.TryParse(connectionCsv[headers.IndexOf("RDGatewayUseConnectionCredentials")], out value))
|
||||||
connectionRecord.RDGatewayUseConnectionCredentials = value;
|
connectionRecord.RDGatewayUseConnectionCredentials = value;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,211 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using mRemoteNG.Connection;
|
||||||
|
using mRemoteNG.Container;
|
||||||
|
using mRemoteNG.Credential;
|
||||||
|
using mRemoteNG.Security;
|
||||||
|
using mRemoteNG.Tools;
|
||||||
|
using mRemoteNG.Tree;
|
||||||
|
using mRemoteNG.Tree.Root;
|
||||||
|
|
||||||
|
namespace mRemoteNG.Config.Serializers.Csv
|
||||||
|
{
|
||||||
|
public class CsvConnectionsSerializerMremotengFormat : ISerializer<ConnectionInfo,string>
|
||||||
|
{
|
||||||
|
private readonly SaveFilter _saveFilter;
|
||||||
|
private readonly ICredentialRepositoryList _credentialRepositoryList;
|
||||||
|
|
||||||
|
public CsvConnectionsSerializerMremotengFormat(SaveFilter saveFilter, ICredentialRepositoryList credentialRepositoryList)
|
||||||
|
{
|
||||||
|
saveFilter.ThrowIfNull(nameof(saveFilter));
|
||||||
|
credentialRepositoryList.ThrowIfNull(nameof(credentialRepositoryList));
|
||||||
|
|
||||||
|
_saveFilter = saveFilter;
|
||||||
|
_credentialRepositoryList = credentialRepositoryList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Serialize(ConnectionTreeModel connectionTreeModel)
|
||||||
|
{
|
||||||
|
connectionTreeModel.ThrowIfNull(nameof(connectionTreeModel));
|
||||||
|
|
||||||
|
var rootNode = connectionTreeModel.RootNodes.First(node => node is RootNodeInfo);
|
||||||
|
return Serialize(rootNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Serialize(ConnectionInfo serializationTarget)
|
||||||
|
{
|
||||||
|
serializationTarget.ThrowIfNull(nameof(serializationTarget));
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
|
||||||
|
WriteCsvHeader(sb);
|
||||||
|
SerializeNodesRecursive(serializationTarget, sb);
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WriteCsvHeader(StringBuilder sb)
|
||||||
|
{
|
||||||
|
sb.Append("Name;Id;Parent;NodeType;Description;Icon;Panel;");
|
||||||
|
if (_saveFilter.SaveUsername)
|
||||||
|
sb.Append("Username;");
|
||||||
|
if (_saveFilter.SavePassword)
|
||||||
|
sb.Append("Password;");
|
||||||
|
if (_saveFilter.SaveDomain)
|
||||||
|
sb.Append("Domain;");
|
||||||
|
sb.Append("Hostname;Protocol;PuttySession;Port;ConnectToConsole;UseCredSsp;RenderingEngine;ICAEncryptionStrength;RDPAuthenticationLevel;LoadBalanceInfo;Colors;Resolution;AutomaticResize;DisplayWallpaper;DisplayThemes;EnableFontSmoothing;EnableDesktopComposition;CacheBitmaps;RedirectDiskDrives;RedirectPorts;RedirectPrinters;RedirectSmartCards;RedirectSound;RedirectKeys;PreExtApp;PostExtApp;MacAddress;UserField;ExtApp;VNCCompression;VNCEncoding;VNCAuthMode;VNCProxyType;VNCProxyIP;VNCProxyPort;VNCProxyUsername;VNCProxyPassword;VNCColors;VNCSmartSizeMode;VNCViewOnly;RDGatewayUsageMethod;RDGatewayHostname;RDGatewayUseConnectionCredentials;RDGatewayUsername;RDGatewayPassword;RDGatewayDomain;");
|
||||||
|
if (_saveFilter.SaveInheritance)
|
||||||
|
sb.Append("InheritCacheBitmaps;InheritColors;InheritDescription;InheritDisplayThemes;InheritDisplayWallpaper;InheritEnableFontSmoothing;InheritEnableDesktopComposition;InheritDomain;InheritIcon;InheritPanel;InheritPassword;InheritPort;InheritProtocol;InheritPuttySession;InheritRedirectDiskDrives;InheritRedirectKeys;InheritRedirectPorts;InheritRedirectPrinters;InheritRedirectSmartCards;InheritRedirectSound;InheritResolution;InheritAutomaticResize;InheritUseConsoleSession;InheritUseCredSsp;InheritRenderingEngine;InheritUsername;InheritICAEncryptionStrength;InheritRDPAuthenticationLevel;InheritLoadBalanceInfo;InheritPreExtApp;InheritPostExtApp;InheritMacAddress;InheritUserField;InheritExtApp;InheritVNCCompression;InheritVNCEncoding;InheritVNCAuthMode;InheritVNCProxyType;InheritVNCProxyIP;InheritVNCProxyPort;InheritVNCProxyUsername;InheritVNCProxyPassword;InheritVNCColors;InheritVNCSmartSizeMode;InheritVNCViewOnly;InheritRDGatewayUsageMethod;InheritRDGatewayHostname;InheritRDGatewayUseConnectionCredentials;InheritRDGatewayUsername;InheritRDGatewayPassword;InheritRDGatewayDomain;InheritRDPAlertIdleTimeout;InheritRDPMinutesToIdleTimeout;InheritSoundQuality");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SerializeNodesRecursive(ConnectionInfo node, StringBuilder sb)
|
||||||
|
{
|
||||||
|
var nodeAsContainer = node as ContainerInfo;
|
||||||
|
if (nodeAsContainer != null)
|
||||||
|
{
|
||||||
|
foreach (var child in nodeAsContainer.Children)
|
||||||
|
{
|
||||||
|
SerializeNodesRecursive(child, sb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// dont serialize the root node
|
||||||
|
if (node is RootNodeInfo)
|
||||||
|
return;
|
||||||
|
|
||||||
|
SerializeConnectionInfo(node, sb);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SerializeConnectionInfo(ConnectionInfo con, StringBuilder sb)
|
||||||
|
{
|
||||||
|
sb.AppendLine();
|
||||||
|
sb.Append(FormatForCsv(con.Name))
|
||||||
|
.Append(FormatForCsv(con.ConstantID))
|
||||||
|
.Append(FormatForCsv(con.Parent?.ConstantID ?? ""))
|
||||||
|
.Append(FormatForCsv(con.GetTreeNodeType()))
|
||||||
|
.Append(FormatForCsv(con.Description))
|
||||||
|
.Append(FormatForCsv(con.Icon))
|
||||||
|
.Append(FormatForCsv(con.Panel));
|
||||||
|
|
||||||
|
if (_saveFilter.SaveUsername)
|
||||||
|
sb.Append(FormatForCsv(con.Username));
|
||||||
|
|
||||||
|
if (_saveFilter.SavePassword)
|
||||||
|
sb.Append(FormatForCsv(con.Password));
|
||||||
|
|
||||||
|
if (_saveFilter.SaveDomain)
|
||||||
|
sb.Append(FormatForCsv(con.Domain));
|
||||||
|
|
||||||
|
sb.Append(FormatForCsv(con.Hostname))
|
||||||
|
.Append(FormatForCsv(con.Protocol))
|
||||||
|
.Append(FormatForCsv(con.PuttySession))
|
||||||
|
.Append(FormatForCsv(con.Port))
|
||||||
|
.Append(FormatForCsv(con.UseConsoleSession))
|
||||||
|
.Append(FormatForCsv(con.UseCredSsp))
|
||||||
|
.Append(FormatForCsv(con.RenderingEngine))
|
||||||
|
.Append(FormatForCsv(con.ICAEncryptionStrength))
|
||||||
|
.Append(FormatForCsv(con.RDPAuthenticationLevel))
|
||||||
|
.Append(FormatForCsv(con.LoadBalanceInfo))
|
||||||
|
.Append(FormatForCsv(con.Colors))
|
||||||
|
.Append(FormatForCsv(con.Resolution))
|
||||||
|
.Append(FormatForCsv(con.AutomaticResize))
|
||||||
|
.Append(FormatForCsv(con.DisplayWallpaper))
|
||||||
|
.Append(FormatForCsv(con.DisplayThemes))
|
||||||
|
.Append(FormatForCsv(con.EnableFontSmoothing))
|
||||||
|
.Append(FormatForCsv(con.EnableDesktopComposition))
|
||||||
|
.Append(FormatForCsv(con.CacheBitmaps))
|
||||||
|
.Append(FormatForCsv(con.RedirectDiskDrives))
|
||||||
|
.Append(FormatForCsv(con.RedirectPorts))
|
||||||
|
.Append(FormatForCsv(con.RedirectPrinters))
|
||||||
|
.Append(FormatForCsv(con.RedirectSmartCards))
|
||||||
|
.Append(FormatForCsv(con.RedirectSound))
|
||||||
|
.Append(FormatForCsv(con.RedirectKeys))
|
||||||
|
.Append(FormatForCsv(con.PreExtApp))
|
||||||
|
.Append(FormatForCsv(con.PostExtApp))
|
||||||
|
.Append(FormatForCsv(con.MacAddress))
|
||||||
|
.Append(FormatForCsv(con.UserField))
|
||||||
|
.Append(FormatForCsv(con.ExtApp))
|
||||||
|
.Append(FormatForCsv(con.VNCCompression))
|
||||||
|
.Append(FormatForCsv(con.VNCEncoding))
|
||||||
|
.Append(FormatForCsv(con.VNCAuthMode))
|
||||||
|
.Append(FormatForCsv(con.VNCProxyType))
|
||||||
|
.Append(FormatForCsv(con.VNCProxyIP))
|
||||||
|
.Append(FormatForCsv(con.VNCProxyPort))
|
||||||
|
.Append(FormatForCsv(con.VNCProxyUsername))
|
||||||
|
.Append(FormatForCsv(con.VNCProxyPassword))
|
||||||
|
.Append(FormatForCsv(con.VNCColors))
|
||||||
|
.Append(FormatForCsv(con.VNCSmartSizeMode))
|
||||||
|
.Append(FormatForCsv(con.VNCViewOnly))
|
||||||
|
.Append(FormatForCsv(con.RDGatewayUsageMethod))
|
||||||
|
.Append(FormatForCsv(con.RDGatewayHostname))
|
||||||
|
.Append(FormatForCsv(con.RDGatewayUseConnectionCredentials))
|
||||||
|
.Append(FormatForCsv(con.RDGatewayUsername))
|
||||||
|
.Append(FormatForCsv(con.RDGatewayPassword))
|
||||||
|
.Append(FormatForCsv(con.RDGatewayDomain));
|
||||||
|
|
||||||
|
|
||||||
|
if (!_saveFilter.SaveInheritance)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sb.Append(FormatForCsv(con.Inheritance.CacheBitmaps))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.Colors))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.Description))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.DisplayThemes))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.DisplayWallpaper))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.EnableFontSmoothing))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.EnableDesktopComposition))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.Domain))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.Icon))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.Panel))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.Password))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.Port))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.Protocol))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.PuttySession))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.RedirectDiskDrives))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.RedirectKeys))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.RedirectPorts))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.RedirectPrinters))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.RedirectSmartCards))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.RedirectSound))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.Resolution))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.AutomaticResize))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.UseConsoleSession))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.UseCredSsp))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.RenderingEngine))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.Username))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.ICAEncryptionStrength))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.RDPAuthenticationLevel))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.LoadBalanceInfo))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.PreExtApp))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.PostExtApp))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.MacAddress))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.UserField))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.ExtApp))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.VNCCompression))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.VNCEncoding))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.VNCAuthMode))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.VNCProxyType))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.VNCProxyIP))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.VNCProxyPort))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.VNCProxyUsername))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.VNCProxyPassword))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.VNCColors))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.VNCSmartSizeMode))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.VNCViewOnly))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.RDGatewayUsageMethod))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.RDGatewayHostname))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.RDGatewayUseConnectionCredentials))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.RDGatewayUsername))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.RDGatewayPassword))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.RDGatewayDomain))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.RDPAlertIdleTimeout))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.RDPMinutesToIdleTimeout))
|
||||||
|
.Append(FormatForCsv(con.Inheritance.SoundQuality));
|
||||||
|
}
|
||||||
|
|
||||||
|
private string FormatForCsv(object value)
|
||||||
|
{
|
||||||
|
var cleanedString = value.ToString().Replace(";", "");
|
||||||
|
return cleanedString + ";";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,4 @@
|
|||||||
using System;
|
using mRemoteNG.App;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Data;
|
|
||||||
using System.Linq;
|
|
||||||
using mRemoteNG.App;
|
|
||||||
using mRemoteNG.Connection;
|
using mRemoteNG.Connection;
|
||||||
using mRemoteNG.Connection.Protocol;
|
using mRemoteNG.Connection.Protocol;
|
||||||
using mRemoteNG.Connection.Protocol.Http;
|
using mRemoteNG.Connection.Protocol.Http;
|
||||||
@@ -12,11 +8,28 @@ using mRemoteNG.Connection.Protocol.VNC;
|
|||||||
using mRemoteNG.Container;
|
using mRemoteNG.Container;
|
||||||
using mRemoteNG.Tree;
|
using mRemoteNG.Tree;
|
||||||
using mRemoteNG.Tree.Root;
|
using mRemoteNG.Tree.Root;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Data;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Security;
|
||||||
|
using mRemoteNG.Security;
|
||||||
|
using mRemoteNG.Security.SymmetricEncryption;
|
||||||
|
using mRemoteNG.Tools;
|
||||||
|
|
||||||
namespace mRemoteNG.Config.Serializers
|
namespace mRemoteNG.Config.Serializers.MsSql
|
||||||
{
|
{
|
||||||
public class DataTableDeserializer : IDeserializer<DataTable, ConnectionTreeModel>
|
public class DataTableDeserializer : IDeserializer<DataTable, ConnectionTreeModel>
|
||||||
{
|
{
|
||||||
|
private readonly ICryptographyProvider _cryptographyProvider;
|
||||||
|
private readonly SecureString _decryptionKey;
|
||||||
|
|
||||||
|
public DataTableDeserializer(ICryptographyProvider cryptographyProvider, SecureString decryptionKey)
|
||||||
|
{
|
||||||
|
_cryptographyProvider = cryptographyProvider.ThrowIfNull(nameof(cryptographyProvider));
|
||||||
|
_decryptionKey = decryptionKey.ThrowIfNull(nameof(decryptionKey));
|
||||||
|
}
|
||||||
|
|
||||||
public ConnectionTreeModel Deserialize(DataTable table)
|
public ConnectionTreeModel Deserialize(DataTable table)
|
||||||
{
|
{
|
||||||
var connectionList = CreateNodesFromTable(table);
|
var connectionList = CreateNodesFromTable(table);
|
||||||
@@ -46,14 +59,16 @@ namespace mRemoteNG.Config.Serializers
|
|||||||
|
|
||||||
private ConnectionInfo DeserializeConnectionInfo(DataRow row)
|
private ConnectionInfo DeserializeConnectionInfo(DataRow row)
|
||||||
{
|
{
|
||||||
var connectionInfo = new ConnectionInfo();
|
var connectionId = row["ConstantID"] as string ?? Guid.NewGuid().ToString();
|
||||||
|
var connectionInfo = new ConnectionInfo(connectionId);
|
||||||
PopulateConnectionInfoFromDatarow(row, connectionInfo);
|
PopulateConnectionInfoFromDatarow(row, connectionInfo);
|
||||||
return connectionInfo;
|
return connectionInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ContainerInfo DeserializeContainerInfo(DataRow row)
|
private ContainerInfo DeserializeContainerInfo(DataRow row)
|
||||||
{
|
{
|
||||||
var containerInfo = new ContainerInfo();
|
var containerId = row["ConstantID"] as string ?? Guid.NewGuid().ToString();
|
||||||
|
var containerInfo = new ContainerInfo(containerId);
|
||||||
PopulateConnectionInfoFromDatarow(row, containerInfo);
|
PopulateConnectionInfoFromDatarow(row, containerInfo);
|
||||||
return containerInfo;
|
return containerInfo;
|
||||||
}
|
}
|
||||||
@@ -61,22 +76,17 @@ namespace mRemoteNG.Config.Serializers
|
|||||||
private void PopulateConnectionInfoFromDatarow(DataRow dataRow, ConnectionInfo connectionInfo)
|
private void PopulateConnectionInfoFromDatarow(DataRow dataRow, ConnectionInfo connectionInfo)
|
||||||
{
|
{
|
||||||
connectionInfo.Name = (string)dataRow["Name"];
|
connectionInfo.Name = (string)dataRow["Name"];
|
||||||
connectionInfo.ConstantID = (string)dataRow["ConstantID"];
|
|
||||||
|
|
||||||
// This throws a NPE - Parent is a connectionInfo object which will be null at this point.
|
// This throws a NPE - Parent is a connectionInfo object which will be null at this point.
|
||||||
// The Parent object is linked properly later in CreateNodeHierarchy()
|
// The Parent object is linked properly later in CreateNodeHierarchy()
|
||||||
//connectionInfo.Parent.ConstantID = (string)dataRow["ParentID"];
|
//connectionInfo.Parent.ConstantID = (string)dataRow["ParentID"];
|
||||||
|
|
||||||
var info = connectionInfo as ContainerInfo;
|
|
||||||
if(info != null)
|
|
||||||
info.IsExpanded = (bool)dataRow["Expanded"];
|
|
||||||
|
|
||||||
connectionInfo.Description = (string)dataRow["Description"];
|
connectionInfo.Description = (string)dataRow["Description"];
|
||||||
connectionInfo.Icon = (string)dataRow["Icon"];
|
connectionInfo.Icon = (string)dataRow["Icon"];
|
||||||
connectionInfo.Panel = (string)dataRow["Panel"];
|
connectionInfo.Panel = (string)dataRow["Panel"];
|
||||||
connectionInfo.Username = (string)dataRow["Username"];
|
connectionInfo.Username = (string)dataRow["Username"];
|
||||||
connectionInfo.Domain = (string)dataRow["DomainName"];
|
connectionInfo.Domain = (string)dataRow["DomainName"];
|
||||||
connectionInfo.Password = (string)dataRow["Password"];
|
connectionInfo.Password = DecryptValue((string)dataRow["Password"]);
|
||||||
connectionInfo.Hostname = (string)dataRow["Hostname"];
|
connectionInfo.Hostname = (string)dataRow["Hostname"];
|
||||||
connectionInfo.Protocol = (ProtocolType)Enum.Parse(typeof(ProtocolType), (string)dataRow["Protocol"]);
|
connectionInfo.Protocol = (ProtocolType)Enum.Parse(typeof(ProtocolType), (string)dataRow["Protocol"]);
|
||||||
connectionInfo.PuttySession = (string)dataRow["PuttySession"];
|
connectionInfo.PuttySession = (string)dataRow["PuttySession"];
|
||||||
@@ -85,12 +95,12 @@ namespace mRemoteNG.Config.Serializers
|
|||||||
connectionInfo.UseCredSsp = (bool)dataRow["UseCredSsp"];
|
connectionInfo.UseCredSsp = (bool)dataRow["UseCredSsp"];
|
||||||
connectionInfo.RenderingEngine = (HTTPBase.RenderingEngine)Enum.Parse(typeof(HTTPBase.RenderingEngine), (string)dataRow["RenderingEngine"]);
|
connectionInfo.RenderingEngine = (HTTPBase.RenderingEngine)Enum.Parse(typeof(HTTPBase.RenderingEngine), (string)dataRow["RenderingEngine"]);
|
||||||
connectionInfo.ICAEncryptionStrength = (IcaProtocol.EncryptionStrength)Enum.Parse(typeof(IcaProtocol.EncryptionStrength), (string)dataRow["ICAEncryptionStrength"]);
|
connectionInfo.ICAEncryptionStrength = (IcaProtocol.EncryptionStrength)Enum.Parse(typeof(IcaProtocol.EncryptionStrength), (string)dataRow["ICAEncryptionStrength"]);
|
||||||
connectionInfo.RDPAuthenticationLevel = (RdpAuthenticationLevel)Enum.Parse(typeof(RdpAuthenticationLevel), (string)dataRow["RDPAuthenticationLevel"]);
|
connectionInfo.RDPAuthenticationLevel = (RdpProtocol.AuthenticationLevel)Enum.Parse(typeof(RdpProtocol.AuthenticationLevel), (string)dataRow["RDPAuthenticationLevel"]);
|
||||||
connectionInfo.RDPMinutesToIdleTimeout = (int)dataRow["RDPMinutesToIdleTimeout"];
|
connectionInfo.RDPMinutesToIdleTimeout = (int)dataRow["RDPMinutesToIdleTimeout"];
|
||||||
connectionInfo.RDPAlertIdleTimeout = (bool)dataRow["RDPAlertIdleTimeout"];
|
connectionInfo.RDPAlertIdleTimeout = (bool)dataRow["RDPAlertIdleTimeout"];
|
||||||
connectionInfo.LoadBalanceInfo = (string)dataRow["LoadBalanceInfo"];
|
connectionInfo.LoadBalanceInfo = (string)dataRow["LoadBalanceInfo"];
|
||||||
connectionInfo.Colors = (RdpColors)Enum.Parse(typeof(RdpColors) ,(string)dataRow["Colors"]);
|
connectionInfo.Colors = (RdpProtocol.RDPColors)Enum.Parse(typeof(RdpProtocol.RDPColors) ,(string)dataRow["Colors"]);
|
||||||
connectionInfo.Resolution = (RdpResolutions)Enum.Parse(typeof(RdpResolutions), (string)dataRow["Resolution"]);
|
connectionInfo.Resolution = (RdpProtocol.RDPResolutions)Enum.Parse(typeof(RdpProtocol.RDPResolutions), (string)dataRow["Resolution"]);
|
||||||
connectionInfo.AutomaticResize = (bool)dataRow["AutomaticResize"];
|
connectionInfo.AutomaticResize = (bool)dataRow["AutomaticResize"];
|
||||||
connectionInfo.DisplayWallpaper = (bool)dataRow["DisplayWallpaper"];
|
connectionInfo.DisplayWallpaper = (bool)dataRow["DisplayWallpaper"];
|
||||||
connectionInfo.DisplayThemes = (bool)dataRow["DisplayThemes"];
|
connectionInfo.DisplayThemes = (bool)dataRow["DisplayThemes"];
|
||||||
@@ -101,10 +111,9 @@ namespace mRemoteNG.Config.Serializers
|
|||||||
connectionInfo.RedirectPorts = (bool)dataRow["RedirectPorts"];
|
connectionInfo.RedirectPorts = (bool)dataRow["RedirectPorts"];
|
||||||
connectionInfo.RedirectPrinters = (bool)dataRow["RedirectPrinters"];
|
connectionInfo.RedirectPrinters = (bool)dataRow["RedirectPrinters"];
|
||||||
connectionInfo.RedirectSmartCards = (bool)dataRow["RedirectSmartCards"];
|
connectionInfo.RedirectSmartCards = (bool)dataRow["RedirectSmartCards"];
|
||||||
connectionInfo.RedirectSound = (RdpSounds)Enum.Parse(typeof(RdpSounds), (string)dataRow["RedirectSound"]);
|
connectionInfo.RedirectSound = (RdpProtocol.RDPSounds)Enum.Parse(typeof(RdpProtocol.RDPSounds), (string)dataRow["RedirectSound"]);
|
||||||
connectionInfo.SoundQuality = (RdpSoundQuality)Enum.Parse(typeof(RdpSoundQuality), (string)dataRow["SoundQuality"]);
|
connectionInfo.SoundQuality = (RdpProtocol.RDPSoundQuality)Enum.Parse(typeof(RdpProtocol.RDPSoundQuality), (string)dataRow["SoundQuality"]);
|
||||||
connectionInfo.RedirectKeys = (bool)dataRow["RedirectKeys"];
|
connectionInfo.RedirectKeys = (bool)dataRow["RedirectKeys"];
|
||||||
connectionInfo.PleaseConnect = (bool)dataRow["Connected"];
|
|
||||||
connectionInfo.PreExtApp = (string)dataRow["PreExtApp"];
|
connectionInfo.PreExtApp = (string)dataRow["PreExtApp"];
|
||||||
connectionInfo.PostExtApp = (string)dataRow["PostExtApp"];
|
connectionInfo.PostExtApp = (string)dataRow["PostExtApp"];
|
||||||
connectionInfo.MacAddress = (string)dataRow["MacAddress"];
|
connectionInfo.MacAddress = (string)dataRow["MacAddress"];
|
||||||
@@ -117,15 +126,15 @@ namespace mRemoteNG.Config.Serializers
|
|||||||
connectionInfo.VNCProxyIP = (string)dataRow["VNCProxyIP"];
|
connectionInfo.VNCProxyIP = (string)dataRow["VNCProxyIP"];
|
||||||
connectionInfo.VNCProxyPort = (int)dataRow["VNCProxyPort"];
|
connectionInfo.VNCProxyPort = (int)dataRow["VNCProxyPort"];
|
||||||
connectionInfo.VNCProxyUsername = (string)dataRow["VNCProxyUsername"];
|
connectionInfo.VNCProxyUsername = (string)dataRow["VNCProxyUsername"];
|
||||||
connectionInfo.VNCProxyPassword = (string)dataRow["VNCProxyPassword"];
|
connectionInfo.VNCProxyPassword = DecryptValue((string)dataRow["VNCProxyPassword"]);
|
||||||
connectionInfo.VNCColors = (ProtocolVNC.Colors)Enum.Parse(typeof(ProtocolVNC.Colors), (string)dataRow["VNCColors"]);
|
connectionInfo.VNCColors = (ProtocolVNC.Colors)Enum.Parse(typeof(ProtocolVNC.Colors), (string)dataRow["VNCColors"]);
|
||||||
connectionInfo.VNCSmartSizeMode = (ProtocolVNC.SmartSizeMode)Enum.Parse(typeof(ProtocolVNC.SmartSizeMode), (string)dataRow["VNCSmartSizeMode"]);
|
connectionInfo.VNCSmartSizeMode = (ProtocolVNC.SmartSizeMode)Enum.Parse(typeof(ProtocolVNC.SmartSizeMode), (string)dataRow["VNCSmartSizeMode"]);
|
||||||
connectionInfo.VNCViewOnly = (bool)dataRow["VNCViewOnly"];
|
connectionInfo.VNCViewOnly = (bool)dataRow["VNCViewOnly"];
|
||||||
connectionInfo.RDGatewayUsageMethod = (RDGatewayUsageMethod)Enum.Parse(typeof(RDGatewayUsageMethod), (string)dataRow["RDGatewayUsageMethod"]);
|
connectionInfo.RDGatewayUsageMethod = (RdpProtocol.RDGatewayUsageMethod)Enum.Parse(typeof(RdpProtocol.RDGatewayUsageMethod), (string)dataRow["RDGatewayUsageMethod"]);
|
||||||
connectionInfo.RDGatewayHostname = (string)dataRow["RDGatewayHostname"];
|
connectionInfo.RDGatewayHostname = (string)dataRow["RDGatewayHostname"];
|
||||||
connectionInfo.RDGatewayUseConnectionCredentials = (RDGatewayUseConnectionCredentials)Enum.Parse(typeof(RDGatewayUseConnectionCredentials), (string)dataRow["RDGatewayUseConnectionCredentials"]);
|
connectionInfo.RDGatewayUseConnectionCredentials = (RdpProtocol.RDGatewayUseConnectionCredentials)Enum.Parse(typeof(RdpProtocol.RDGatewayUseConnectionCredentials), (string)dataRow["RDGatewayUseConnectionCredentials"]);
|
||||||
connectionInfo.RDGatewayUsername = (string)dataRow["RDGatewayUsername"];
|
connectionInfo.RDGatewayUsername = (string)dataRow["RDGatewayUsername"];
|
||||||
connectionInfo.RDGatewayPassword = (string)dataRow["RDGatewayPassword"];
|
connectionInfo.RDGatewayPassword = DecryptValue((string)dataRow["RDGatewayPassword"]);
|
||||||
connectionInfo.RDGatewayDomain = (string)dataRow["RDGatewayDomain"];
|
connectionInfo.RDGatewayDomain = (string)dataRow["RDGatewayDomain"];
|
||||||
|
|
||||||
connectionInfo.Inheritance.CacheBitmaps = (bool)dataRow["InheritCacheBitmaps"];
|
connectionInfo.Inheritance.CacheBitmaps = (bool)dataRow["InheritCacheBitmaps"];
|
||||||
@@ -184,10 +193,26 @@ namespace mRemoteNG.Config.Serializers
|
|||||||
connectionInfo.Inheritance.RDGatewayDomain = (bool)dataRow["InheritRDGatewayDomain"];
|
connectionInfo.Inheritance.RDGatewayDomain = (bool)dataRow["InheritRDGatewayDomain"];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string DecryptValue(string cipherText)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return _cryptographyProvider.Decrypt(cipherText, _decryptionKey);
|
||||||
|
}
|
||||||
|
catch (EncryptionException)
|
||||||
|
{
|
||||||
|
// value may not be encrypted
|
||||||
|
return cipherText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private ConnectionTreeModel CreateNodeHierarchy(List<ConnectionInfo> connectionList, DataTable dataTable)
|
private ConnectionTreeModel CreateNodeHierarchy(List<ConnectionInfo> connectionList, DataTable dataTable)
|
||||||
{
|
{
|
||||||
var connectionTreeModel = new ConnectionTreeModel();
|
var connectionTreeModel = new ConnectionTreeModel();
|
||||||
var rootNode = new RootNodeInfo(RootNodeType.Connection) {ConstantID = "0"};
|
var rootNode = new RootNodeInfo(RootNodeType.Connection, "0")
|
||||||
|
{
|
||||||
|
PasswordString = _decryptionKey.ConvertToUnsecureString()
|
||||||
|
};
|
||||||
connectionTreeModel.AddRootNode(rootNode);
|
connectionTreeModel.AddRootNode(rootNode);
|
||||||
|
|
||||||
foreach (DataRow row in dataTable.Rows)
|
foreach (DataRow row in dataTable.Rows)
|
||||||
@@ -1,25 +1,31 @@
|
|||||||
using System;
|
using mRemoteNG.Connection;
|
||||||
using System.Data;
|
|
||||||
using System.Data.SqlTypes;
|
|
||||||
using System.Linq;
|
|
||||||
using mRemoteNG.Connection;
|
|
||||||
using mRemoteNG.Container;
|
using mRemoteNG.Container;
|
||||||
using mRemoteNG.Security;
|
using mRemoteNG.Security;
|
||||||
using mRemoteNG.Tree;
|
using mRemoteNG.Tree;
|
||||||
using mRemoteNG.Tree.Root;
|
using mRemoteNG.Tree.Root;
|
||||||
|
using System;
|
||||||
|
using System.Data;
|
||||||
|
using System.Data.SqlTypes;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Security;
|
||||||
|
using mRemoteNG.Tools;
|
||||||
|
|
||||||
namespace mRemoteNG.Config.Serializers
|
namespace mRemoteNG.Config.Serializers.MsSql
|
||||||
{
|
{
|
||||||
public class DataTableSerializer : ISerializer<ConnectionInfo,DataTable>
|
public class DataTableSerializer : ISerializer<ConnectionInfo,DataTable>
|
||||||
{
|
{
|
||||||
|
private readonly ICryptographyProvider _cryptographyProvider;
|
||||||
|
private readonly SecureString _encryptionKey;
|
||||||
private DataTable _dataTable;
|
private DataTable _dataTable;
|
||||||
private const string TableName = "tblCons";
|
private const string TableName = "tblCons";
|
||||||
private readonly SaveFilter _saveFilter;
|
private readonly SaveFilter _saveFilter;
|
||||||
private int _currentNodeIndex;
|
private int _currentNodeIndex;
|
||||||
|
|
||||||
public DataTableSerializer(SaveFilter saveFilter)
|
public DataTableSerializer(SaveFilter saveFilter, ICryptographyProvider cryptographyProvider, SecureString encryptionKey)
|
||||||
{
|
{
|
||||||
_saveFilter = saveFilter;
|
_saveFilter = saveFilter.ThrowIfNull(nameof(saveFilter));
|
||||||
|
_cryptographyProvider = cryptographyProvider.ThrowIfNull(nameof(cryptographyProvider));
|
||||||
|
_encryptionKey = encryptionKey.ThrowIfNull(nameof(encryptionKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -204,14 +210,15 @@ namespace mRemoteNG.Config.Serializers
|
|||||||
dataRow["ParentID"] = connectionInfo.Parent?.ConstantID ?? "";
|
dataRow["ParentID"] = connectionInfo.Parent?.ConstantID ?? "";
|
||||||
dataRow["PositionID"] = _currentNodeIndex;
|
dataRow["PositionID"] = _currentNodeIndex;
|
||||||
dataRow["LastChange"] = (SqlDateTime)DateTime.Now;
|
dataRow["LastChange"] = (SqlDateTime)DateTime.Now;
|
||||||
var info = connectionInfo as ContainerInfo;
|
dataRow["Expanded"] = false; // TODO: this column can eventually be removed. we now save this property locally
|
||||||
dataRow["Expanded"] = info != null && info.IsExpanded;
|
|
||||||
dataRow["Description"] = connectionInfo.Description;
|
dataRow["Description"] = connectionInfo.Description;
|
||||||
dataRow["Icon"] = connectionInfo.Icon;
|
dataRow["Icon"] = connectionInfo.Icon;
|
||||||
dataRow["Panel"] = connectionInfo.Panel;
|
dataRow["Panel"] = connectionInfo.Panel;
|
||||||
dataRow["Username"] = _saveFilter.SaveUsername ? connectionInfo.Username : "";
|
dataRow["Username"] = _saveFilter.SaveUsername ? connectionInfo.Username : "";
|
||||||
dataRow["DomainName"] = _saveFilter.SaveDomain ? connectionInfo.Domain : "";
|
dataRow["DomainName"] = _saveFilter.SaveDomain ? connectionInfo.Domain : "";
|
||||||
dataRow["Password"] = _saveFilter.SavePassword ? connectionInfo.Password : "";
|
dataRow["Password"] = _saveFilter.SavePassword
|
||||||
|
? _cryptographyProvider.Encrypt(connectionInfo.Password, _encryptionKey)
|
||||||
|
: "";
|
||||||
dataRow["Hostname"] = connectionInfo.Hostname;
|
dataRow["Hostname"] = connectionInfo.Hostname;
|
||||||
dataRow["Protocol"] = connectionInfo.Protocol;
|
dataRow["Protocol"] = connectionInfo.Protocol;
|
||||||
dataRow["PuttySession"] = connectionInfo.PuttySession;
|
dataRow["PuttySession"] = connectionInfo.PuttySession;
|
||||||
@@ -239,7 +246,7 @@ namespace mRemoteNG.Config.Serializers
|
|||||||
dataRow["RedirectSound"] = connectionInfo.RedirectSound;
|
dataRow["RedirectSound"] = connectionInfo.RedirectSound;
|
||||||
dataRow["SoundQuality"] = connectionInfo.SoundQuality;
|
dataRow["SoundQuality"] = connectionInfo.SoundQuality;
|
||||||
dataRow["RedirectKeys"] = connectionInfo.RedirectKeys;
|
dataRow["RedirectKeys"] = connectionInfo.RedirectKeys;
|
||||||
dataRow["Connected"] = connectionInfo.OpenConnections.Count > 0;
|
dataRow["Connected"] = false; // TODO: this column can eventually be removed. we now save this property locally
|
||||||
dataRow["PreExtApp"] = connectionInfo.PreExtApp;
|
dataRow["PreExtApp"] = connectionInfo.PreExtApp;
|
||||||
dataRow["PostExtApp"] = connectionInfo.PostExtApp;
|
dataRow["PostExtApp"] = connectionInfo.PostExtApp;
|
||||||
dataRow["MacAddress"] = connectionInfo.MacAddress;
|
dataRow["MacAddress"] = connectionInfo.MacAddress;
|
||||||
@@ -252,7 +259,7 @@ namespace mRemoteNG.Config.Serializers
|
|||||||
dataRow["VNCProxyIP"] = connectionInfo.VNCProxyIP;
|
dataRow["VNCProxyIP"] = connectionInfo.VNCProxyIP;
|
||||||
dataRow["VNCProxyPort"] = connectionInfo.VNCProxyPort;
|
dataRow["VNCProxyPort"] = connectionInfo.VNCProxyPort;
|
||||||
dataRow["VNCProxyUsername"] = connectionInfo.VNCProxyUsername;
|
dataRow["VNCProxyUsername"] = connectionInfo.VNCProxyUsername;
|
||||||
dataRow["VNCProxyPassword"] = connectionInfo.VNCProxyPassword;
|
dataRow["VNCProxyPassword"] = _cryptographyProvider.Encrypt(connectionInfo.VNCProxyPassword, _encryptionKey);
|
||||||
dataRow["VNCColors"] = connectionInfo.VNCColors;
|
dataRow["VNCColors"] = connectionInfo.VNCColors;
|
||||||
dataRow["VNCSmartSizeMode"] = connectionInfo.VNCSmartSizeMode;
|
dataRow["VNCSmartSizeMode"] = connectionInfo.VNCSmartSizeMode;
|
||||||
dataRow["VNCViewOnly"] = connectionInfo.VNCViewOnly;
|
dataRow["VNCViewOnly"] = connectionInfo.VNCViewOnly;
|
||||||
@@ -260,7 +267,7 @@ namespace mRemoteNG.Config.Serializers
|
|||||||
dataRow["RDGatewayHostname"] = connectionInfo.RDGatewayHostname;
|
dataRow["RDGatewayHostname"] = connectionInfo.RDGatewayHostname;
|
||||||
dataRow["RDGatewayUseConnectionCredentials"] = connectionInfo.RDGatewayUseConnectionCredentials;
|
dataRow["RDGatewayUseConnectionCredentials"] = connectionInfo.RDGatewayUseConnectionCredentials;
|
||||||
dataRow["RDGatewayUsername"] = connectionInfo.RDGatewayUsername;
|
dataRow["RDGatewayUsername"] = connectionInfo.RDGatewayUsername;
|
||||||
dataRow["RDGatewayPassword"] = connectionInfo.RDGatewayPassword;
|
dataRow["RDGatewayPassword"] = _cryptographyProvider.Encrypt(connectionInfo.RDGatewayPassword, _encryptionKey);
|
||||||
dataRow["RDGatewayDomain"] = connectionInfo.RDGatewayDomain;
|
dataRow["RDGatewayDomain"] = connectionInfo.RDGatewayDomain;
|
||||||
if (_saveFilter.SaveInheritance)
|
if (_saveFilter.SaveInheritance)
|
||||||
{
|
{
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
namespace mRemoteNG.Config.Serializers.MsSql
|
||||||
|
{
|
||||||
|
public class LocalConnectionPropertiesModel
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The unique Id of this tree node
|
||||||
|
/// </summary>
|
||||||
|
public string ConnectionId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether this connection is connected
|
||||||
|
/// </summary>
|
||||||
|
public bool Connected { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates whether this container is expanded in the tree
|
||||||
|
/// </summary>
|
||||||
|
public bool Expanded { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Xml;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
|
||||||
|
namespace mRemoteNG.Config.Serializers.MsSql
|
||||||
|
{
|
||||||
|
public class LocalConnectionPropertiesXmlSerializer :
|
||||||
|
ISerializer<IEnumerable<LocalConnectionPropertiesModel>, string>,
|
||||||
|
IDeserializer<string, IEnumerable<LocalConnectionPropertiesModel>>
|
||||||
|
{
|
||||||
|
public string Serialize(IEnumerable<LocalConnectionPropertiesModel> models)
|
||||||
|
{
|
||||||
|
var localConnections = models
|
||||||
|
.Select(m => new XElement("Node",
|
||||||
|
new XAttribute("ConnectionId", m.ConnectionId),
|
||||||
|
new XAttribute("Connected", m.Connected),
|
||||||
|
new XAttribute("Expanded", m.Expanded)));
|
||||||
|
|
||||||
|
var root = new XElement("LocalConnections", localConnections);
|
||||||
|
var xdoc = new XDocument(new XDeclaration("1.0", "utf-8", null), root);
|
||||||
|
return WriteXmlToString(xdoc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<LocalConnectionPropertiesModel> Deserialize(string serializedData)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(serializedData))
|
||||||
|
return Enumerable.Empty<LocalConnectionPropertiesModel>();
|
||||||
|
|
||||||
|
var xdoc = XDocument.Parse(serializedData);
|
||||||
|
return xdoc
|
||||||
|
.Descendants("Node")
|
||||||
|
.Where(e => e.Attribute("ConnectionId") != null)
|
||||||
|
.Select(e => new LocalConnectionPropertiesModel
|
||||||
|
{
|
||||||
|
ConnectionId = e.Attribute("ConnectionId")?.Value,
|
||||||
|
Connected = bool.Parse(e.Attribute("Connected")?.Value ?? "False"),
|
||||||
|
Expanded = bool.Parse(e.Attribute("Expanded")?.Value ?? "False")
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string WriteXmlToString(XNode xmlDocument)
|
||||||
|
{
|
||||||
|
string xmlString;
|
||||||
|
var xmlWriterSettings = new XmlWriterSettings { Indent = true, IndentChars = " ", Encoding = Encoding.UTF8 };
|
||||||
|
var memoryStream = new MemoryStream();
|
||||||
|
using (var xmlTextWriter = XmlWriter.Create(memoryStream, xmlWriterSettings))
|
||||||
|
{
|
||||||
|
xmlDocument.WriteTo(xmlTextWriter);
|
||||||
|
xmlTextWriter.Flush();
|
||||||
|
var streamReader = new StreamReader(memoryStream, Encoding.UTF8, true);
|
||||||
|
memoryStream.Seek(0, SeekOrigin.Begin);
|
||||||
|
xmlString = streamReader.ReadToEnd();
|
||||||
|
}
|
||||||
|
return xmlString;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
using System.Security;
|
||||||
|
|
||||||
|
namespace mRemoteNG.Config.Serializers.MsSql
|
||||||
|
{
|
||||||
|
public class SqlConnectionListMetaData
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string Protected { get; set; }
|
||||||
|
public bool Export { get; set; }
|
||||||
|
public Version ConfVersion { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user