readded forms and controls for the credential manager

This commit is contained in:
David Sparer
2018-12-27 14:13:51 -06:00
parent 1e66787422
commit 22ecf0d06f
35 changed files with 5032 additions and 3 deletions

View File

@@ -0,0 +1,135 @@
using System;
using System.Collections.Generic;
using System.Security;
using System.Xml.Linq;
using mRemoteNG.App;
using mRemoteNG.Config.Serializers.CredentialSerializer;
using mRemoteNG.Connection;
using mRemoteNG.Credential;
using mRemoteNG.Credential.Repositories;
using mRemoteNG.Security.Authentication;
using mRemoteNG.Security.Factories;
using mRemoteNG.Tools;
using mRemoteNG.Tree;
using System.Globalization;
namespace mRemoteNG.Config.Serializers.Versioning
{
public class XmlCredentialManagerUpgrader : IDeserializer<string, ConnectionTreeModel>
{
private readonly CredentialServiceFacade _credentialsService;
private readonly IDeserializer<string, ConnectionTreeModel> _decoratedDeserializer;
public string CredentialFilePath { get; set; }
public XmlCredentialManagerUpgrader(CredentialServiceFacade credentialsService, string credentialFilePath, IDeserializer<string, ConnectionTreeModel> decoratedDeserializer)
{
if (credentialsService == null)
throw new ArgumentNullException(nameof(credentialsService));
if (decoratedDeserializer == null)
throw new ArgumentNullException(nameof(decoratedDeserializer));
_credentialsService = credentialsService;
CredentialFilePath = credentialFilePath;
_decoratedDeserializer = decoratedDeserializer;
}
public ConnectionTreeModel Deserialize(string serializedData)
{
var serializedDataAsXDoc = EnsureConnectionXmlElementsHaveIds(serializedData);
var upgradeMap = UpgradeUserFilesForCredentialManager(serializedDataAsXDoc);
var serializedDataWithIds = $"{serializedDataAsXDoc.Declaration}{serializedDataAsXDoc}";
var connectionTreeModel = _decoratedDeserializer.Deserialize(serializedDataWithIds);
if (upgradeMap != null)
ApplyCredentialMapping(upgradeMap, connectionTreeModel.GetRecursiveChildList());
return connectionTreeModel;
}
private XDocument EnsureConnectionXmlElementsHaveIds(string serializedData)
{
var xdoc = XDocument.Parse(serializedData);
xdoc.Declaration = new XDeclaration("1.0", "utf-8", null);
var adapter = new ConfConsEnsureConnectionsHaveIds();
adapter.EnsureElementsHaveIds(xdoc);
return xdoc;
}
public static decimal? GetVersionFromConfiguration(XDocument xdoc)
{
var versionString = xdoc.Root?.Attribute("ConfVersion")?.Value;
return versionString != null
? (decimal?)decimal.Parse(versionString, CultureInfo.InvariantCulture)
: null;
}
public Dictionary<Guid, ICredentialRecord> UpgradeUserFilesForCredentialManager(XDocument xdoc)
{
if ((GetVersionFromConfiguration(xdoc) ?? 0) >= 2.7m)
{
return null;
}
var cryptoProvider = new CryptoProviderFactoryFromXml(xdoc.Root).Build();
var encryptedValue = xdoc.Root?.Attribute("Protected")?.Value;
var auth = new PasswordAuthenticator(cryptoProvider, encryptedValue, () => MiscTools.PasswordDialog("", false));
if (!auth.Authenticate(Runtime.EncryptionKey))
throw new Exception("Could not authenticate");
var newCredRepoKey = auth.LastAuthenticatedPassword;
var credentialHarvester = new CredentialHarvester();
var harvestedCredentials = credentialHarvester.Harvest(xdoc, newCredRepoKey);
var newCredentialRepository = BuildXmlCredentialRepo(newCredRepoKey);
AddHarvestedCredentialsToRepo(harvestedCredentials, newCredentialRepository);
newCredentialRepository.SaveCredentials(newCredRepoKey);
_credentialsService.AddRepository(newCredentialRepository);
return credentialHarvester.ConnectionToCredentialMap;
}
private ICredentialRepository BuildXmlCredentialRepo(SecureString newCredRepoKey)
{
var cryptoFromSettings = new CryptoProviderFactoryFromSettings();
var credRepoSerializer = new XmlCredentialPasswordEncryptorDecorator(
cryptoFromSettings.Build(),
new XmlCredentialRecordSerializer());
var credRepoDeserializer = new XmlCredentialPasswordDecryptorDecorator(new XmlCredentialRecordDeserializer());
var xmlRepoFactory = new XmlCredentialRepositoryFactory(credRepoSerializer, credRepoDeserializer);
var newRepo = xmlRepoFactory.Build(
new CredentialRepositoryConfig
{
Source = CredentialFilePath,
Title = "Converted Credentials",
TypeName = "Xml",
Key = newCredRepoKey
}
);
newRepo.LoadCredentials(newCredRepoKey);
return newRepo;
}
private void AddHarvestedCredentialsToRepo(IEnumerable<ICredentialRecord> harvestedCredentials, ICredentialRepository repo)
{
foreach (var credential in harvestedCredentials)
repo.CredentialRecords.Add(credential);
}
public void ApplyCredentialMapping(IDictionary<Guid, ICredentialRecord> map, IEnumerable<AbstractConnectionRecord> connectionRecords)
{
foreach (var connectionInfo in connectionRecords)
{
Guid id;
Guid.TryParse(connectionInfo.ConstantID, out id);
if (map.ContainsKey(id))
connectionInfo.CredentialRecordId = map[id].Id.Maybe();
}
}
}
}

View File

@@ -141,7 +141,7 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory("strCategoryConnection", 2),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameUsername"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionUsername")]
[Obsolete("Use the CredentialRecordId property")]
[Obsolete("Use the CredentialRecord property")]
[Browsable(false)]
public virtual string Username
{
@@ -153,7 +153,7 @@ namespace mRemoteNG.Connection
LocalizedAttributes.LocalizedDisplayName("strPropertyNamePassword"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionPassword"),
PasswordPropertyText(true)]
[Obsolete("Use the CredentialRecordId property")]
[Obsolete("Use the CredentialRecord property")]
[Browsable(false)]
public virtual string Password
{
@@ -164,7 +164,7 @@ namespace mRemoteNG.Connection
[LocalizedAttributes.LocalizedCategory("strCategoryConnection", 2),
LocalizedAttributes.LocalizedDisplayName("strPropertyNameDomain"),
LocalizedAttributes.LocalizedDescription("strPropertyDescriptionDomain")]
[Obsolete("Use the CredentialRecordId property")]
[Obsolete("Use the CredentialRecord property")]
[Browsable(false)]
public string Domain
{

View File

@@ -0,0 +1,349 @@
namespace mRemoteNG.UI.Forms
{
sealed partial class CompositeCredentialRepoUnlockerForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(CompositeCredentialRepoUnlockerForm));
this.objectListViewRepos = new Controls.Base.NGListView();
this.olvColumnName = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
this.olvColumnStatusIcon = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
this.labelUnlocking = new Controls.Base.NGLabel();
this.labelPassword = new Controls.Base.NGLabel();
this.buttonUnlock = new Controls.Base.NGButton();
this.buttonClose = new Controls.Base.NGButton();
this.labelRepoTitle = new Controls.Base.NGLabel();
this.textBoxType = new Controls.Base.NGTextBox();
this.textBoxTitle = new Controls.Base.NGTextBox();
this.labelRepoType = new Controls.Base.NGLabel();
this.textBoxSource = new Controls.Base.NGTextBox();
this.labelRepoSource = new Controls.Base.NGLabel();
this.textBoxId = new Controls.Base.NGTextBox();
this.labelId = new Controls.Base.NGLabel();
this.labelPasswordError = new Controls.Base.NGLabel();
this.imgPasswordError = new System.Windows.Forms.PictureBox();
this.imgUnlocked = new System.Windows.Forms.PictureBox();
this.labelUnlocked = new Controls.Base.NGLabel();
this.secureTextBoxPassword = new mRemoteNG.UI.Controls.SecureTextBox();
((System.ComponentModel.ISupportInitialize)(this.objectListViewRepos)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.imgPasswordError)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.imgUnlocked)).BeginInit();
this.SuspendLayout();
//
// objectListViewRepos
//
this.objectListViewRepos.AllColumns.Add(this.olvColumnName);
this.objectListViewRepos.AllColumns.Add(this.olvColumnStatusIcon);
this.objectListViewRepos.CellEditUseWholeCell = false;
this.objectListViewRepos.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.olvColumnName,
this.olvColumnStatusIcon});
this.objectListViewRepos.Cursor = System.Windows.Forms.Cursors.Default;
this.objectListViewRepos.Dock = System.Windows.Forms.DockStyle.Left;
this.objectListViewRepos.EmptyListMsg = "No Credential Repositories Found";
this.objectListViewRepos.HasCollapsibleGroups = false;
this.objectListViewRepos.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None;
this.objectListViewRepos.HideSelection = false;
this.objectListViewRepos.Location = new System.Drawing.Point(0, 0);
this.objectListViewRepos.MultiSelect = false;
this.objectListViewRepos.Name = "objectListViewRepos";
this.objectListViewRepos.SelectAllOnControlA = false;
this.objectListViewRepos.ShowGroups = false;
this.objectListViewRepos.Size = new System.Drawing.Size(175, 272);
this.objectListViewRepos.TabIndex = 3;
this.objectListViewRepos.UseCompatibleStateImageBehavior = false;
this.objectListViewRepos.UseOverlays = false;
this.objectListViewRepos.View = System.Windows.Forms.View.Details;
this.objectListViewRepos.SelectionChanged += new System.EventHandler(this.objectListViewRepos_SelectionChanged);
//
// olvColumnName
//
this.olvColumnName.FillsFreeSpace = true;
this.olvColumnName.Groupable = false;
this.olvColumnName.Hideable = false;
this.olvColumnName.IsEditable = false;
this.olvColumnName.Searchable = false;
this.olvColumnName.Sortable = false;
//
// olvColumnStatusIcon
//
this.olvColumnStatusIcon.Groupable = false;
this.olvColumnStatusIcon.IsEditable = false;
this.olvColumnStatusIcon.Searchable = false;
this.olvColumnStatusIcon.Sortable = false;
this.olvColumnStatusIcon.Text = "";
this.olvColumnStatusIcon.Width = 20;
//
// labelUnlocking
//
this.labelUnlocking.AutoSize = true;
this.labelUnlocking.Font = new System.Drawing.Font("Microsoft Sans Serif", 9.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.labelUnlocking.Location = new System.Drawing.Point(181, 9);
this.labelUnlocking.Name = "labelUnlocking";
this.labelUnlocking.Size = new System.Drawing.Size(77, 16);
this.labelUnlocking.TabIndex = 1;
this.labelUnlocking.Text = "Unlocking";
//
// labelPassword
//
this.labelPassword.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.labelPassword.AutoSize = true;
this.labelPassword.Location = new System.Drawing.Point(190, 174);
this.labelPassword.Name = "labelPassword";
this.labelPassword.Size = new System.Drawing.Size(53, 13);
this.labelPassword.TabIndex = 2;
this.labelPassword.Text = "Password";
//
// buttonUnlock
//
this.buttonUnlock.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonUnlock.Location = new System.Drawing.Point(386, 237);
this.buttonUnlock.Name = "buttonUnlock";
this.buttonUnlock.Size = new System.Drawing.Size(75, 23);
this.buttonUnlock.TabIndex = 1;
this.buttonUnlock.Text = "Unlock";
this.buttonUnlock.UseVisualStyleBackColor = true;
this.buttonUnlock.Click += new System.EventHandler(this.buttonUnlock_Click);
//
// buttonClose
//
this.buttonClose.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonClose.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.buttonClose.Location = new System.Drawing.Point(467, 237);
this.buttonClose.Name = "buttonClose";
this.buttonClose.Size = new System.Drawing.Size(75, 23);
this.buttonClose.TabIndex = 2;
this.buttonClose.Text = "Close";
this.buttonClose.UseVisualStyleBackColor = true;
this.buttonClose.Click += new System.EventHandler(this.buttonClose_Click);
//
// labelRepoTitle
//
this.labelRepoTitle.AutoSize = true;
this.labelRepoTitle.Location = new System.Drawing.Point(190, 64);
this.labelRepoTitle.Name = "labelRepoTitle";
this.labelRepoTitle.Size = new System.Drawing.Size(27, 13);
this.labelRepoTitle.TabIndex = 6;
this.labelRepoTitle.Text = "Title";
//
// textBoxType
//
this.textBoxType.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.textBoxType.Location = new System.Drawing.Point(237, 90);
this.textBoxType.Name = "textBoxType";
this.textBoxType.ReadOnly = true;
this.textBoxType.Size = new System.Drawing.Size(306, 20);
this.textBoxType.TabIndex = 9;
this.textBoxType.TabStop = false;
//
// textBoxTitle
//
this.textBoxTitle.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.textBoxTitle.Location = new System.Drawing.Point(237, 64);
this.textBoxTitle.Name = "textBoxTitle";
this.textBoxTitle.ReadOnly = true;
this.textBoxTitle.Size = new System.Drawing.Size(306, 20);
this.textBoxTitle.TabIndex = 8;
this.textBoxTitle.TabStop = false;
//
// labelRepoType
//
this.labelRepoType.AutoSize = true;
this.labelRepoType.Location = new System.Drawing.Point(190, 90);
this.labelRepoType.Name = "labelRepoType";
this.labelRepoType.Size = new System.Drawing.Size(31, 13);
this.labelRepoType.TabIndex = 7;
this.labelRepoType.Text = "Type";
//
// textBoxSource
//
this.textBoxSource.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.textBoxSource.Location = new System.Drawing.Point(237, 116);
this.textBoxSource.Multiline = true;
this.textBoxSource.Name = "textBoxSource";
this.textBoxSource.ReadOnly = true;
this.textBoxSource.Size = new System.Drawing.Size(306, 46);
this.textBoxSource.TabIndex = 11;
this.textBoxSource.TabStop = false;
//
// labelRepoSource
//
this.labelRepoSource.AutoSize = true;
this.labelRepoSource.Location = new System.Drawing.Point(190, 116);
this.labelRepoSource.Name = "labelRepoSource";
this.labelRepoSource.Size = new System.Drawing.Size(41, 13);
this.labelRepoSource.TabIndex = 10;
this.labelRepoSource.Text = "Source";
//
// textBoxId
//
this.textBoxId.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.textBoxId.Location = new System.Drawing.Point(237, 38);
this.textBoxId.Name = "textBoxId";
this.textBoxId.ReadOnly = true;
this.textBoxId.Size = new System.Drawing.Size(305, 20);
this.textBoxId.TabIndex = 13;
this.textBoxId.TabStop = false;
//
// labelId
//
this.labelId.AutoSize = true;
this.labelId.Location = new System.Drawing.Point(191, 38);
this.labelId.Name = "labelId";
this.labelId.Size = new System.Drawing.Size(18, 13);
this.labelId.TabIndex = 12;
this.labelId.Text = "ID";
//
// labelPasswordError
//
this.labelPasswordError.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.labelPasswordError.AutoSize = true;
this.labelPasswordError.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.labelPasswordError.ForeColor = System.Drawing.Color.DarkRed;
this.labelPasswordError.ImageAlign = System.Drawing.ContentAlignment.TopLeft;
this.labelPasswordError.Location = new System.Drawing.Point(191, 213);
this.labelPasswordError.Name = "labelPasswordError";
this.labelPasswordError.Size = new System.Drawing.Size(115, 13);
this.labelPasswordError.TabIndex = 14;
this.labelPasswordError.Text = "Incorrect password";
this.labelPasswordError.Visible = false;
//
// imgPasswordError
//
this.imgPasswordError.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.imgPasswordError.Image = global::mRemoteNG.Resources.exclamation;
this.imgPasswordError.Location = new System.Drawing.Point(176, 192);
this.imgPasswordError.Name = "imgPasswordError";
this.imgPasswordError.Size = new System.Drawing.Size(16, 16);
this.imgPasswordError.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize;
this.imgPasswordError.TabIndex = 15;
this.imgPasswordError.TabStop = false;
this.imgPasswordError.Visible = false;
//
// imgUnlocked
//
this.imgUnlocked.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.imgUnlocked.Image = global::mRemoteNG.Resources.tick;
this.imgUnlocked.Location = new System.Drawing.Point(188, 241);
this.imgUnlocked.Name = "imgUnlocked";
this.imgUnlocked.Size = new System.Drawing.Size(16, 16);
this.imgUnlocked.SizeMode = System.Windows.Forms.PictureBoxSizeMode.AutoSize;
this.imgUnlocked.TabIndex = 16;
this.imgUnlocked.TabStop = false;
this.imgUnlocked.Visible = false;
//
// labelUnlocked
//
this.labelUnlocked.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.labelUnlocked.AutoSize = true;
this.labelUnlocked.Location = new System.Drawing.Point(204, 242);
this.labelUnlocked.Name = "labelUnlocked";
this.labelUnlocked.Size = new System.Drawing.Size(174, 13);
this.labelUnlocked.TabIndex = 17;
this.labelUnlocked.Text = "The selected repository is unlocked";
this.labelUnlocked.Visible = false;
//
// secureTextBoxPassword
//
this.secureTextBoxPassword.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.secureTextBoxPassword.Location = new System.Drawing.Point(193, 190);
this.secureTextBoxPassword.Name = "secureTextBoxPassword";
this.secureTextBoxPassword.Size = new System.Drawing.Size(348, 20);
this.secureTextBoxPassword.TabIndex = 0;
this.secureTextBoxPassword.UseSystemPasswordChar = true;
//
// CompositeCredentialRepoUnlockerForm
//
this.AcceptButton = this.buttonUnlock;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.buttonClose;
this.ClientSize = new System.Drawing.Size(554, 272);
this.Controls.Add(this.labelUnlocked);
this.Controls.Add(this.imgUnlocked);
this.Controls.Add(this.imgPasswordError);
this.Controls.Add(this.labelPasswordError);
this.Controls.Add(this.textBoxId);
this.Controls.Add(this.labelId);
this.Controls.Add(this.textBoxSource);
this.Controls.Add(this.labelRepoSource);
this.Controls.Add(this.secureTextBoxPassword);
this.Controls.Add(this.textBoxType);
this.Controls.Add(this.buttonUnlock);
this.Controls.Add(this.textBoxTitle);
this.Controls.Add(this.buttonClose);
this.Controls.Add(this.labelPassword);
this.Controls.Add(this.labelRepoType);
this.Controls.Add(this.objectListViewRepos);
this.Controls.Add(this.labelUnlocking);
this.Controls.Add(this.labelRepoTitle);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MaximizeBox = false;
this.MinimizeBox = false;
this.MinimumSize = new System.Drawing.Size(500, 310);
this.Name = "CompositeCredentialRepoUnlockerForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "Unlock Credential Repository";
this.Shown += new System.EventHandler(this.CompositeCredentialRepoUnlockerForm_Shown);
((System.ComponentModel.ISupportInitialize)(this.objectListViewRepos)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.imgPasswordError)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.imgUnlocked)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private Controls.Base.NGListView objectListViewRepos;
private Controls.Base.NGLabel labelUnlocking;
private Controls.Base.NGLabel labelPassword;
private Controls.SecureTextBox secureTextBoxPassword;
private Controls.Base.NGButton buttonUnlock;
private Controls.Base.NGButton buttonClose;
private Controls.Base.NGLabel labelRepoTitle;
private Controls.Base.NGTextBox textBoxType;
private Controls.Base.NGTextBox textBoxTitle;
private Controls.Base.NGLabel labelRepoType;
private BrightIdeasSoftware.OLVColumn olvColumnName;
private Controls.Base.NGTextBox textBoxSource;
private Controls.Base.NGLabel labelRepoSource;
private Controls.Base.NGTextBox textBoxId;
private Controls.Base.NGLabel labelId;
private BrightIdeasSoftware.OLVColumn olvColumnStatusIcon;
private Controls.Base.NGLabel labelPasswordError;
private System.Windows.Forms.PictureBox imgPasswordError;
private System.Windows.Forms.PictureBox imgUnlocked;
private Controls.Base.NGLabel labelUnlocked;
}
}

View File

@@ -0,0 +1,150 @@
using System;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using mRemoteNG.Credential;
using mRemoteNG.Credential.Repositories;
namespace mRemoteNG.UI.Forms
{
public sealed partial class CompositeCredentialRepoUnlockerForm : Form
{
private readonly CompositeRepositoryUnlocker _repositoryUnlocker;
public CompositeCredentialRepoUnlockerForm(CompositeRepositoryUnlocker repositoryUnlocker)
{
if (repositoryUnlocker == null)
throw new ArgumentNullException(nameof(repositoryUnlocker));
_repositoryUnlocker = repositoryUnlocker;
InitializeComponent();
SetupListView();
ApplyLanguage();
ApplyTheme();
Themes.ThemeManager.getInstance().ThemeChanged += ApplyTheme;
}
private void ApplyTheme()
{
if (!Themes.ThemeManager.getInstance().ThemingActive) return;
BackColor = Themes.ThemeManager.getInstance().ActiveTheme.ExtendedPalette.getColor("Dialog_Background");
ForeColor = Themes.ThemeManager.getInstance().ActiveTheme.ExtendedPalette.getColor("Dialog_Foreground");
}
private void buttonUnlock_Click(object sender, EventArgs e)
{
try
{
_repositoryUnlocker.Unlock(secureTextBoxPassword.SecString);
SelectNextLockedRepo();
}
catch (Exception exception)
{
Console.WriteLine(exception);
ShowPasswordError(true);
}
finally
{
secureTextBoxPassword.Clear();
}
}
private void buttonClose_Click(object sender, EventArgs e)
{
Close();
}
private void SelectNextLockedRepo()
{
_repositoryUnlocker.SelectNextLockedRepository();
objectListViewRepos.SelectedObject = _repositoryUnlocker.SelectedRepository;
}
private void objectListViewRepos_SelectionChanged(object sender, EventArgs e)
{
objectListViewRepos.RefreshObjects(_repositoryUnlocker.Repositories.ToList());
var selectedRepo = objectListViewRepos.SelectedObject as ICredentialRepository;
_repositoryUnlocker.SelectedRepository = selectedRepo;
ShowRepoDetails(selectedRepo);
ShowPasswordError(false);
UnlockRequired(!selectedRepo?.IsLoaded ?? false);
}
private void ShowRepoDetails(ICredentialRepository repo)
{
textBoxId.Text = repo?.Config.Id.ToString() ?? "";
textBoxTitle.Text = repo?.Config.Title ?? "";
textBoxType.Text = repo?.Config.TypeName ?? "";
textBoxSource.Text = repo?.Config.Source ?? "";
}
private void UnlockRequired(bool isUnlockRequired)
{
buttonUnlock.Enabled = isUnlockRequired;
secureTextBoxPassword.Enabled = isUnlockRequired;
imgUnlocked.Visible = objectListViewRepos.SelectedObject != null && !isUnlockRequired;
labelUnlocked.Visible = objectListViewRepos.SelectedObject != null && !isUnlockRequired;
}
private void ShowPasswordError(bool shouldErrorBeActive)
{
labelPasswordError.Visible = shouldErrorBeActive;
imgPasswordError.Visible = shouldErrorBeActive;
secureTextBoxPassword.BackColor = shouldErrorBeActive ? Color.MistyRose : SystemColors.Window;
}
#region Setup
private void SetupListView()
{
olvColumnName.AspectGetter = rowObject => ((ICredentialRepository)rowObject).Config.Title;
olvColumnStatusIcon.AspectGetter = rowObject => string.Empty;
olvColumnStatusIcon.ImageGetter = rowObject => ((ICredentialRepository)rowObject).IsLoaded ? "unlocked" : "locked";
objectListViewRepos.SmallImageList = SetupImageList();
}
private ImageList SetupImageList()
{
var imageList = new ImageList
{
ColorDepth = ColorDepth.Depth32Bit,
ImageSize = new Size(16, 16),
TransparentColor = Color.Transparent
};
imageList.Images.Add(Resources.arrow_left);
imageList.Images.SetKeyName(0, "unlocking");
imageList.Images.Add(Resources.tick);
imageList.Images.SetKeyName(1, "unlocked");
imageList.Images.Add(Resources._lock);
imageList.Images.SetKeyName(2, "locked");
return imageList;
}
private void CompositeCredentialRepoUnlockerForm_Shown(object sender, EventArgs e)
{
PopulateListView();
objectListViewRepos.SelectedIndex = 0;
}
private void PopulateListView()
{
objectListViewRepos.SetObjects(_repositoryUnlocker.Repositories);
}
private void ApplyLanguage()
{
Text = Language.UnlockCredentialRepository;
labelUnlocking.Text = Language.Unlocking;
labelId.Text = Language.strID;
labelRepoTitle.Text = Language.strTitle;
labelRepoType.Text = Language.strType;
labelRepoSource.Text = Language.Source;
labelPassword.Text = Language.strTitlePassword;
labelPasswordError.Text = Language.IncorrectPassword;
labelUnlocked.Text = Language.RepositoryIsUnlocked;
buttonUnlock.Text = Language.Unlock;
buttonClose.Text = Language.strButtonClose;
}
#endregion
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,138 @@
using mRemoteNG.Themes;
namespace mRemoteNG.UI.Forms
{
partial class CredentialManagerForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(CredentialManagerForm));
this.panelMain = new System.Windows.Forms.Panel();
this.olvPageList = new Controls.Base.NGListView();
this.olvColumnPage = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
this.pnlBottom = new System.Windows.Forms.Panel();
this.buttonClose = new Controls.Base.NGButton();
((System.ComponentModel.ISupportInitialize)(this.olvPageList)).BeginInit();
this.pnlBottom.SuspendLayout();
this.SuspendLayout();
//
// panelMain
//
this.panelMain.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.panelMain.Location = new System.Drawing.Point(152, 0);
this.panelMain.Name = "panelMain";
this.panelMain.Size = new System.Drawing.Size(555, 375);
this.panelMain.TabIndex = 4;
//
// olvPageList
//
this.olvPageList.AllColumns.Add(this.olvColumnPage);
this.olvPageList.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)));
this.olvPageList.CellEditUseWholeCell = false;
this.olvPageList.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.olvColumnPage});
this.olvPageList.Cursor = System.Windows.Forms.Cursors.Default;
this.olvPageList.FullRowSelect = true;
this.olvPageList.HasCollapsibleGroups = false;
this.olvPageList.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None;
this.olvPageList.HideSelection = false;
this.olvPageList.IsSearchOnSortColumn = false;
this.olvPageList.Location = new System.Drawing.Point(0, 0);
this.olvPageList.MultiSelect = false;
this.olvPageList.Name = "olvPageList";
this.olvPageList.RowHeight = 30;
this.olvPageList.SelectAllOnControlA = false;
this.olvPageList.ShowFilterMenuOnRightClick = false;
this.olvPageList.ShowGroups = false;
this.olvPageList.ShowHeaderInAllViews = false;
this.olvPageList.Size = new System.Drawing.Size(154, 424);
this.olvPageList.TabIndex = 5;
this.olvPageList.UseCompatibleStateImageBehavior = false;
this.olvPageList.View = System.Windows.Forms.View.Details;
//
// olvColumnPage
//
this.olvColumnPage.AspectName = "PageName";
this.olvColumnPage.CellVerticalAlignment = System.Drawing.StringAlignment.Center;
this.olvColumnPage.FillsFreeSpace = true;
this.olvColumnPage.Groupable = false;
this.olvColumnPage.Hideable = false;
this.olvColumnPage.IsEditable = false;
this.olvColumnPage.Searchable = false;
this.olvColumnPage.Sortable = false;
//
// pnlBottom
//
this.pnlBottom.Controls.Add(this.buttonClose);
this.pnlBottom.Dock = System.Windows.Forms.DockStyle.Bottom;
this.pnlBottom.Location = new System.Drawing.Point(0, 374);
this.pnlBottom.Name = "pnlBottom";
this.pnlBottom.Size = new System.Drawing.Size(707, 50);
this.pnlBottom.TabIndex = 6;
//
// buttonClose
//
this.buttonClose.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonClose.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.buttonClose.Location = new System.Drawing.Point(620, 15);
this.buttonClose.Name = "buttonClose";
this.buttonClose.Size = new System.Drawing.Size(75, 23);
this.buttonClose.TabIndex = 1;
this.buttonClose.Text = "Close";
this.buttonClose.UseVisualStyleBackColor = true;
this.buttonClose.Click += new System.EventHandler(this.buttonClose_Click);
//
// CredentialManagerForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(707, 424);
this.Controls.Add(this.olvPageList);
this.Controls.Add(this.panelMain);
this.Controls.Add(this.pnlBottom);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MaximizeBox = false;
this.Name = "CredentialManagerForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
this.Text = "Credential Manager";
((System.ComponentModel.ISupportInitialize)(this.olvPageList)).EndInit();
this.pnlBottom.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Panel panelMain;
private Controls.Base.NGListView olvPageList;
private System.Windows.Forms.Panel pnlBottom;
private Controls.Base.NGButton buttonClose;
private BrightIdeasSoftware.OLVColumn olvColumnPage;
}
}

View File

@@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using mRemoteNG.UI.Forms.CredentialManagerPages;
using mRemoteNG.Themes;
namespace mRemoteNG.UI.Forms
{
public partial class CredentialManagerForm : Form
{
private readonly IEnumerable<UserControl> _pageControls;
public CredentialManagerForm(IEnumerable<UserControl> pageControls)
{
if (pageControls == null)
throw new ArgumentNullException(nameof(pageControls));
_pageControls = pageControls;
InitializeComponent();
ThemeManager.getInstance().ThemeChanged += ApplyTheme;
ApplyTheme();
ApplyLanguage();
SetupListView();
olvPageList.SelectedIndex = 0;
}
private void SetupListView()
{
olvColumnPage.ImageGetter = ImageGetter;
olvPageList.SelectionChanged += (sender, args) => ShowPage(olvPageList.SelectedObject as Control);
olvPageList.SetObjects(_pageControls);
}
private void ShowPage(Control page)
{
if (page == null) return;
panelMain.Controls.Clear();
panelMain.Controls.Add(page);
page.Dock = DockStyle.Fill;
}
private object ImageGetter(object rowObject)
{
var page = rowObject as ICredentialManagerPage;
return page?.PageIcon;
}
private void ApplyTheme()
{
if (!ThemeManager.getInstance().ThemingActive) return;
BackColor = ThemeManager.getInstance().ActiveTheme.ExtendedPalette.getColor("Dialog_Background");
ForeColor = ThemeManager.getInstance().ActiveTheme.ExtendedPalette.getColor("Dialog_Foreground");
}
private void ApplyLanguage()
{
Text = Language.strCredentialManager;
buttonClose.Text = Language.strButtonClose;
}
private void buttonClose_Click(object sender, EventArgs e)
{
Close();
}
}
}

View File

@@ -0,0 +1,145 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAABAAEAEBAAAAAAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAA
AAA+ncp7NpbR5TOQzOsyi8vtO5XCh////wH///8B////Af///wH///8B////Af///wH///8B////Af//
/wH///8BQqzhzcTr9/9/4fb/n+b3/zKKye86kLqR////Af///wH///8B////Af///wH///8B////Af//
/wH///8B////AUSw4//G9Pv/Q9bx/0jb9f+C4fX/MYjI8TmNt5n///8B////Af///wH///8B////Af//
/wH///8B////Af///wFEsOPzu+/6/znR8f8oxe7/Ttz2/4Xi9/8yi8rvOYu1m////wH///8B////Af//
/wH///8B////Af///wH///8BRLDj//D8/v+w7vr/Q9j0/yjI7v9B1/T/ieL3/zKLy+04iLKj////Af//
/wH///8B////Af///wH///8B////AUSw45dEsOP/RLDj/6vq+f9O2PP/K8nv/z3W8/+K4ff/MorK7zOD
uN0pfdb/LIXY/zaOwcv///8B////Af///wH///8B////AUSw4//x/P7/u/H7/3vk9v8o0vD/N9T1/4Pg
9v8+qeP/oPP8/6n1/P8rgtf/NYu/z////wH///8B////Af///wFEsOOXRLDj/0Wy4/92xer/rO76/znW
8v9N2/X/ZeT3/zzO8v8yye//he/7/yuB1/81iLvV////Af///wH///8B////Af///wFEsOMDRLDjl2/E
6v+A5ff/PdHx/13b9f9p3/b/UNfz/zTN7/+F7/v/KX/W/zSGutn///8B////Af///wH///8B////AUSw
4//V9/z/ief4/37k9/9+5Pf/fuT3/4Ll9/9H1vL/OM7w/671/P8pfNb/////Af///wH///8B////Af//
/wFEsOP/vvL7/37k9/9+5Pf/geX3/5Tp+P+88fv/i9rz/0nd9f/B+P3/MJDa/////wH///8B////Af//
/wH///8BRLDj/974/P+N5/j/fuT3/5Tp+P+86fj/RLDj/0Ks4//u/P7/Mpjd/zmVyL////8B////Af//
/wH///8B////AUSw45dEsOP/zvX8/43n+P+h7Pn/RLDj/0Sw4///////OaHf/zmVyL////8B////Af//
/wH///8B////Af///wH///8BRLDjl0Sw4//O9fz/nuv5/77y+//+////RLDj/0Kr353///8B////Af//
/wH///8B////Af///wH///8B////Af///wFEsOOXRLDj/974/P/e+Pz/RLDj/0Sw45f///8B////Af//
/wH///8B////Af///wH///8B////Af///wH///8B////AUSw45dEsOP/RLDj/0Sw45f///8B////Af//
/wH///8BAAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA
//8AAP//AAD//w==
</value>
</data>
</root>

View File

@@ -0,0 +1,226 @@
using mRemoteNG.Themes;
namespace mRemoteNG.UI.Forms.CredentialManagerPages
{
sealed partial class CredentialEditorPage
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.labelId = new Controls.Base.NGLabel();
this.textBoxId = new Controls.Base.NGTextBox();
this.buttonCancel = new Controls.Base.NGButton();
this.buttonAccept = new Controls.Base.NGButton();
this.labelPassword = new Controls.Base.NGLabel();
this.textBoxPassword = new mRemoteNG.UI.Controls.SecureTextBox();
this.labelDomain = new Controls.Base.NGLabel();
this.textBoxDomain = new Controls.Base.NGTextBox();
this.labelUsername = new Controls.Base.NGLabel();
this.textBoxUsername = new Controls.Base.NGTextBox();
this.labelTitle = new Controls.Base.NGLabel();
this.textBoxTitle = new Controls.Base.NGTextBox();
this.labelRepositoryName = new Controls.Base.NGLabel();
this.textBoxRepositoryName = new Controls.Base.NGTextBox();
this.SuspendLayout();
//
// labelId
//
this.labelId.AutoSize = true;
this.labelId.Location = new System.Drawing.Point(3, 35);
this.labelId.Name = "labelId";
this.labelId.Size = new System.Drawing.Size(16, 13);
this.labelId.TabIndex = 23;
this.labelId.Text = "Id";
//
// textBoxId
//
this.textBoxId.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.textBoxId.Location = new System.Drawing.Point(89, 35);
this.textBoxId.Name = "textBoxId";
this.textBoxId.ReadOnly = true;
this.textBoxId.Size = new System.Drawing.Size(208, 20);
this.textBoxId.TabIndex = 22;
//
// buttonCancel
//
this.buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.buttonCancel.Location = new System.Drawing.Point(222, 174);
this.buttonCancel.Name = "buttonCancel";
this.buttonCancel.Size = new System.Drawing.Size(75, 23);
this.buttonCancel.TabIndex = 21;
this.buttonCancel.Text = "Cancel";
this.buttonCancel.UseVisualStyleBackColor = true;
this.buttonCancel.Click += new System.EventHandler(this.buttonCancel_Click);
//
// buttonAccept
//
this.buttonAccept.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonAccept.Location = new System.Drawing.Point(141, 174);
this.buttonAccept.Name = "buttonAccept";
this.buttonAccept.Size = new System.Drawing.Size(75, 23);
this.buttonAccept.TabIndex = 20;
this.buttonAccept.Text = "Accept";
this.buttonAccept.UseVisualStyleBackColor = true;
this.buttonAccept.Click += new System.EventHandler(this.buttonAccept_Click_1);
//
// labelPassword
//
this.labelPassword.AutoSize = true;
this.labelPassword.Location = new System.Drawing.Point(3, 139);
this.labelPassword.Name = "labelPassword";
this.labelPassword.Size = new System.Drawing.Size(53, 13);
this.labelPassword.TabIndex = 19;
this.labelPassword.Text = "Password";
//
// textBoxPassword
//
this.textBoxPassword.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.textBoxPassword.Location = new System.Drawing.Point(89, 139);
this.textBoxPassword.Name = "textBoxPassword";
this.textBoxPassword.PasswordChar = '•';
this.textBoxPassword.Size = new System.Drawing.Size(208, 20);
this.textBoxPassword.TabIndex = 18;
//
// labelDomain
//
this.labelDomain.AutoSize = true;
this.labelDomain.Location = new System.Drawing.Point(3, 113);
this.labelDomain.Name = "labelDomain";
this.labelDomain.Size = new System.Drawing.Size(43, 13);
this.labelDomain.TabIndex = 17;
this.labelDomain.Text = "Domain";
//
// textBoxDomain
//
this.textBoxDomain.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.textBoxDomain.Location = new System.Drawing.Point(89, 113);
this.textBoxDomain.Name = "textBoxDomain";
this.textBoxDomain.Size = new System.Drawing.Size(208, 20);
this.textBoxDomain.TabIndex = 16;
//
// labelUsername
//
this.labelUsername.AutoSize = true;
this.labelUsername.Location = new System.Drawing.Point(3, 87);
this.labelUsername.Name = "labelUsername";
this.labelUsername.Size = new System.Drawing.Size(55, 13);
this.labelUsername.TabIndex = 15;
this.labelUsername.Text = "Username";
//
// textBoxUsername
//
this.textBoxUsername.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.textBoxUsername.Location = new System.Drawing.Point(89, 87);
this.textBoxUsername.Name = "textBoxUsername";
this.textBoxUsername.Size = new System.Drawing.Size(208, 20);
this.textBoxUsername.TabIndex = 14;
//
// labelTitle
//
this.labelTitle.AutoSize = true;
this.labelTitle.Location = new System.Drawing.Point(3, 61);
this.labelTitle.Name = "labelTitle";
this.labelTitle.Size = new System.Drawing.Size(27, 13);
this.labelTitle.TabIndex = 13;
this.labelTitle.Text = "Title";
//
// textBoxTitle
//
this.textBoxTitle.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.textBoxTitle.Location = new System.Drawing.Point(89, 61);
this.textBoxTitle.Name = "textBoxTitle";
this.textBoxTitle.Size = new System.Drawing.Size(208, 20);
this.textBoxTitle.TabIndex = 12;
//
// labelRepositoryName
//
this.labelRepositoryName.AutoSize = true;
this.labelRepositoryName.Location = new System.Drawing.Point(3, 9);
this.labelRepositoryName.Name = "labelRepositoryName";
this.labelRepositoryName.Size = new System.Drawing.Size(57, 13);
this.labelRepositoryName.TabIndex = 24;
this.labelRepositoryName.Text = "Repository";
//
// textBoxRepositoryName
//
this.textBoxRepositoryName.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.textBoxRepositoryName.Location = new System.Drawing.Point(89, 9);
this.textBoxRepositoryName.Name = "textBoxRepositoryName";
this.textBoxRepositoryName.ReadOnly = true;
this.textBoxRepositoryName.Size = new System.Drawing.Size(208, 20);
this.textBoxRepositoryName.TabIndex = 25;
//
// CredentialEditorPage
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.textBoxRepositoryName);
this.Controls.Add(this.labelRepositoryName);
this.Controls.Add(this.labelId);
this.Controls.Add(this.textBoxId);
this.Controls.Add(this.buttonCancel);
this.Controls.Add(this.buttonAccept);
this.Controls.Add(this.labelPassword);
this.Controls.Add(this.textBoxPassword);
this.Controls.Add(this.labelDomain);
this.Controls.Add(this.textBoxDomain);
this.Controls.Add(this.labelUsername);
this.Controls.Add(this.textBoxUsername);
this.Controls.Add(this.labelTitle);
this.Controls.Add(this.textBoxTitle);
this.MinimumSize = new System.Drawing.Size(300, 200);
this.Name = "CredentialEditorPage";
this.Size = new System.Drawing.Size(300, 200);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private Controls.Base.NGLabel labelId;
private Controls.Base.NGTextBox textBoxId;
private Controls.Base.NGButton buttonCancel;
private Controls.Base.NGButton buttonAccept;
private Controls.Base.NGLabel labelPassword;
private Controls.SecureTextBox textBoxPassword;
private Controls.Base.NGLabel labelDomain;
private Controls.Base.NGTextBox textBoxDomain;
private Controls.Base.NGLabel labelUsername;
private Controls.Base.NGTextBox textBoxUsername;
private Controls.Base.NGLabel labelTitle;
private Controls.Base.NGTextBox textBoxTitle;
private Controls.Base.NGLabel labelRepositoryName;
private Controls.Base.NGTextBox textBoxRepositoryName;
}
}

View File

@@ -0,0 +1,73 @@
using System;
using System.Windows.Forms;
using mRemoteNG.Credential;
using mRemoteNG.Security;
using mRemoteNG.UI.Controls.PageSequence;
namespace mRemoteNG.UI.Forms.CredentialManagerPages
{
public sealed partial class CredentialEditorPage : SequencedControl
{
private readonly ICredentialRecord _credentialRecord;
private readonly ICredentialRepository _credentialRepository;
public CredentialEditorPage(ICredentialRecord credentialRecord, ICredentialRepository credentialRepository)
{
if (credentialRecord == null)
throw new ArgumentNullException(nameof(credentialRecord));
if (credentialRepository == null)
throw new ArgumentNullException(nameof(credentialRepository));
InitializeComponent();
ApplyTheme();
ApplyLanguage();
_credentialRecord = credentialRecord;
_credentialRepository = credentialRepository;
FillInForm();
Dock = DockStyle.Fill;
}
private void ApplyLanguage()
{
Text = Language.strCredentialEditor;
labelId.Text = Language.strID;
labelTitle.Text = Language.strTitle;
labelUsername.Text = Language.strPropertyNameUsername;
labelDomain.Text = Language.strPropertyNameDomain;
labelPassword.Text = Language.strPropertyNamePassword;
buttonAccept.Text = Language.strAccept;
buttonCancel.Text = Language.strButtonCancel;
}
private void FillInForm()
{
textBoxRepositoryName.Text = _credentialRepository.Config.Title;
textBoxId.Text = _credentialRecord.Id.ToString();
textBoxTitle.Text = _credentialRecord.Title;
textBoxUsername.Text = _credentialRecord.Username;
textBoxDomain.Text = _credentialRecord.Domain;
textBoxPassword.Text = _credentialRecord.Password.ConvertToUnsecureString();
}
private void SaveFormToCredential()
{
_credentialRecord.Title = textBoxTitle.Text;
_credentialRecord.Username = textBoxUsername.Text;
_credentialRecord.Domain = textBoxDomain.Text;
_credentialRecord.Password = textBoxPassword.Text.ConvertToSecureString();
}
private void buttonAccept_Click_1(object sender, EventArgs e)
{
SaveFormToCredential();
if (!_credentialRepository.CredentialRecords.Contains(_credentialRecord))
_credentialRepository.CredentialRecords.Add(_credentialRecord);
RaiseNextPageEvent();
}
private void buttonCancel_Click(object sender, EventArgs e)
{
RaisePreviousPageEvent();
}
}
}

View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -0,0 +1,108 @@
using mRemoteNG.Themes;
namespace mRemoteNG.UI.Forms.CredentialManagerPages
{
sealed partial class CredentialListPage
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.buttonAdd = new Controls.Base.NGButton();
this.buttonRemove = new Controls.Base.NGButton();
this.buttonEdit = new Controls.Base.NGButton();
this.credentialRecordListView = new mRemoteNG.UI.Controls.CredentialRecordListView();
this.SuspendLayout();
//
// buttonAdd
//
this.buttonAdd.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonAdd.Image = global::mRemoteNG.Resources.key_add;
this.buttonAdd.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
this.buttonAdd.Location = new System.Drawing.Point(71, 241);
this.buttonAdd.Name = "buttonAdd";
this.buttonAdd.Size = new System.Drawing.Size(99, 32);
this.buttonAdd.TabIndex = 3;
this.buttonAdd.Text = "Add";
this.buttonAdd.UseVisualStyleBackColor = true;
this.buttonAdd.Click += new System.EventHandler(this.buttonAdd_Click);
//
// buttonRemove
//
this.buttonRemove.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonRemove.Enabled = false;
this.buttonRemove.Image = global::mRemoteNG.Resources.key_delete;
this.buttonRemove.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
this.buttonRemove.Location = new System.Drawing.Point(281, 241);
this.buttonRemove.Name = "buttonRemove";
this.buttonRemove.Size = new System.Drawing.Size(99, 32);
this.buttonRemove.TabIndex = 4;
this.buttonRemove.Text = "Remove";
this.buttonRemove.UseVisualStyleBackColor = true;
this.buttonRemove.Click += new System.EventHandler(this.buttonRemove_Click);
//
// buttonEdit
//
this.buttonEdit.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonEdit.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
this.buttonEdit.Location = new System.Drawing.Point(176, 241);
this.buttonEdit.Name = "buttonEdit";
this.buttonEdit.Size = new System.Drawing.Size(99, 32);
this.buttonEdit.TabIndex = 5;
this.buttonEdit.Text = "Edit";
this.buttonEdit.UseVisualStyleBackColor = true;
this.buttonEdit.Click += new System.EventHandler(this.buttonEdit_Click);
//
// credentialRecordListView
//
this.credentialRecordListView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.credentialRecordListView.Location = new System.Drawing.Point(0, 0);
this.credentialRecordListView.Name = "credentialRecordListView";
this.credentialRecordListView.Size = new System.Drawing.Size(383, 235);
this.credentialRecordListView.TabIndex = 6;
//
// CredentialListPage
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.credentialRecordListView);
this.Controls.Add(this.buttonEdit);
this.Controls.Add(this.buttonAdd);
this.Controls.Add(this.buttonRemove);
this.Name = "CredentialListPage";
this.Size = new System.Drawing.Size(383, 276);
this.ResumeLayout(false);
}
#endregion
private Controls.Base.NGButton buttonAdd;
private Controls.Base.NGButton buttonRemove;
private Controls.Base.NGButton buttonEdit;
private Controls.CredentialRecordListView credentialRecordListView;
}
}

View File

@@ -0,0 +1,148 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using BrightIdeasSoftware;
using mRemoteNG.Credential;
using mRemoteNG.Tree;
using mRemoteNG.UI.Controls.PageSequence;
namespace mRemoteNG.UI.Forms.CredentialManagerPages
{
public sealed partial class CredentialListPage : SequencedControl, ICredentialManagerPage
{
private readonly ICredentialRepositoryList _credentialRepositoryList;
public string PageName { get; } = Language.strCategoryCredentials;
public Image PageIcon { get; } = Resources.key;
public IConfirm<IEnumerable<ICredentialRecord>> DeletionConfirmer { get; set; } = new AlwaysConfirmYes();
public CredentialListPage(ICredentialRepositoryList credentialRepositoryList)
{
if (credentialRepositoryList == null)
throw new ArgumentNullException(nameof(credentialRepositoryList));
_credentialRepositoryList = credentialRepositoryList;
InitializeComponent();
ApplyTheme();
ApplyLanguage();
credentialRecordListView.CellClick += HandleCellDoubleClick;
credentialRecordListView.SelectionChanged += ObjectListView1OnSelectionChanged;
credentialRecordListView.KeyDown += ObjectListView1OnEnterPressed;
credentialRecordListView.KeyDown += OnAPressed;
credentialRecordListView.KeyDown += OnDeletePressed;
credentialRecordListView.CredentialRepositoryList = _credentialRepositoryList;
}
private void ApplyLanguage()
{
Text = Language.strCredentialManager;
buttonAdd.Text = Language.strAdd;
buttonRemove.Text = Language.strRemove;
}
private void RemoveSelectedCredential()
{
var selectedCredential = credentialRecordListView.SelectedObject;
if (!DeletionConfirmer.Confirm(new[] { selectedCredential.Key })) return;
selectedCredential.Value.CredentialRecords.Remove(selectedCredential.Key);
RaiseCredentialsChangedEvent(this);
}
private void RemoveSelectedCredentials()
{
var selectedCredentials = credentialRecordListView.SelectedObjects.ToArray();
if (!DeletionConfirmer.Confirm(selectedCredentials.Select(i => i.Key))) return;
foreach(var item in selectedCredentials)
item.Value.CredentialRecords.Remove(item.Key);
RaiseCredentialsChangedEvent(this);
}
private void HandleCellDoubleClick(object sender, CellClickEventArgs cellClickEventArgs)
{
if (cellClickEventArgs.ClickCount < 2) return;
EditCredential(credentialRecordListView.SelectedObject);
}
private void AddCredential()
{
var sequence = new PageSequence(Parent,
this,
new CredentialRepositorySelectionPage(_credentialRepositoryList),
new SequencedControl(),
this
);
RaiseNextPageEvent();
}
private void EditCredential(KeyValuePair<ICredentialRecord, ICredentialRepository> credentialAndRepository)
{
if (credentialAndRepository.Key == null || credentialAndRepository.Value == null) return;
var sequence = new PageSequence(Parent,
this,
new CredentialEditorPage(credentialAndRepository.Key, credentialAndRepository.Value),
this
);
RaiseNextPageEvent();
}
private void buttonAdd_Click(object sender, EventArgs e)
{
AddCredential();
}
private void buttonEdit_Click(object sender, EventArgs e)
{
EditCredential(credentialRecordListView.SelectedObject);
}
private void buttonRemove_Click(object sender, EventArgs e)
{
if (credentialRecordListView.MultipleObjectsSelected)
RemoveSelectedCredentials();
else
RemoveSelectedCredential();
}
private void ObjectListView1OnEnterPressed(object sender, KeyEventArgs keyEventArgs)
{
if (keyEventArgs.KeyCode != Keys.Enter) return;
EditCredential(credentialRecordListView.SelectedObject);
keyEventArgs.Handled = true;
keyEventArgs.SuppressKeyPress = true;
}
private void OnAPressed(object sender, KeyEventArgs keyEventArgs)
{
if (keyEventArgs.KeyCode != Keys.A) return;
AddCredential();
keyEventArgs.Handled = true;
keyEventArgs.SuppressKeyPress = true;
}
private void OnDeletePressed(object sender, KeyEventArgs keyEventArgs)
{
if (keyEventArgs.KeyCode != Keys.Delete) return;
if (credentialRecordListView.MultipleObjectsSelected)
RemoveSelectedCredentials();
else
RemoveSelectedCredential();
keyEventArgs.Handled = true;
keyEventArgs.SuppressKeyPress = true;
}
private void ObjectListView1OnSelectionChanged(object sender, EventArgs eventArgs)
{
buttonRemove.Enabled = credentialRecordListView.SelectedObjects.Any();
}
public event EventHandler CredentialsChanged;
private void RaiseCredentialsChangedEvent(object sender)
{
CredentialsChanged?.Invoke(sender, EventArgs.Empty);
}
}
}

View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -0,0 +1,131 @@
using mRemoteNG.Credential.Repositories;
using mRemoteNG.Themes;
namespace mRemoteNG.UI.Forms.CredentialManagerPages
{
sealed partial class CredentialRepositoriesPage
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
CredentialRepositoryList credentialRepositoryList1 = new CredentialRepositoryList();
this.buttonAdd = new Controls.Base.NGButton();
this.buttonRemove = new Controls.Base.NGButton();
this.buttonEdit = new Controls.Base.NGButton();
this.credentialRepositoryListView = new mRemoteNG.UI.Controls.CredentialRepositoryListView();
this.buttonToggleLoad = new Controls.Base.NGButton();
this.SuspendLayout();
//
// buttonAdd
//
this.buttonAdd.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonAdd.Image = global::mRemoteNG.Resources.key_add;
this.buttonAdd.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
this.buttonAdd.Location = new System.Drawing.Point(105, 237);
this.buttonAdd.Name = "buttonAdd";
this.buttonAdd.Size = new System.Drawing.Size(99, 32);
this.buttonAdd.TabIndex = 5;
this.buttonAdd.Text = "Add";
this.buttonAdd.UseVisualStyleBackColor = true;
this.buttonAdd.Click += new System.EventHandler(this.buttonAdd_Click);
//
// buttonRemove
//
this.buttonRemove.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonRemove.Enabled = false;
this.buttonRemove.Image = global::mRemoteNG.Resources.key_delete;
this.buttonRemove.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
this.buttonRemove.Location = new System.Drawing.Point(315, 237);
this.buttonRemove.Name = "buttonRemove";
this.buttonRemove.Size = new System.Drawing.Size(99, 32);
this.buttonRemove.TabIndex = 6;
this.buttonRemove.Text = "Remove";
this.buttonRemove.UseVisualStyleBackColor = true;
this.buttonRemove.Click += new System.EventHandler(this.buttonRemove_Click);
//
// buttonEdit
//
this.buttonEdit.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonEdit.Enabled = false;
this.buttonEdit.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
this.buttonEdit.Location = new System.Drawing.Point(210, 237);
this.buttonEdit.Name = "buttonEdit";
this.buttonEdit.Size = new System.Drawing.Size(99, 32);
this.buttonEdit.TabIndex = 8;
this.buttonEdit.Text = "Edit";
this.buttonEdit.UseVisualStyleBackColor = true;
this.buttonEdit.Click += new System.EventHandler(this.buttonEdit_Click);
//
// credentialRepositoryListView
//
this.credentialRepositoryListView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.credentialRepositoryListView.CredentialRepositoryList = credentialRepositoryList1;
this.credentialRepositoryListView.DoubleClickHandler = null;
this.credentialRepositoryListView.Location = new System.Drawing.Point(0, 0);
this.credentialRepositoryListView.Name = "credentialRepositoryListView";
this.credentialRepositoryListView.RepositoryFilter = null;
this.credentialRepositoryListView.Size = new System.Drawing.Size(417, 231);
this.credentialRepositoryListView.TabIndex = 9;
//
// buttonToggleLoad
//
this.buttonToggleLoad.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonToggleLoad.Enabled = false;
this.buttonToggleLoad.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
this.buttonToggleLoad.Location = new System.Drawing.Point(3, 237);
this.buttonToggleLoad.Name = "buttonToggleLoad";
this.buttonToggleLoad.Size = new System.Drawing.Size(99, 32);
this.buttonToggleLoad.TabIndex = 10;
this.buttonToggleLoad.Text = "Load";
this.buttonToggleLoad.UseVisualStyleBackColor = true;
this.buttonToggleLoad.Click += new System.EventHandler(this.buttonToggleLoad_Click);
//
// CredentialRepositoriesPage
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.buttonToggleLoad);
this.Controls.Add(this.credentialRepositoryListView);
this.Controls.Add(this.buttonEdit);
this.Controls.Add(this.buttonAdd);
this.Controls.Add(this.buttonRemove);
this.Name = "CredentialRepositoriesPage";
this.Size = new System.Drawing.Size(417, 272);
this.ResumeLayout(false);
}
#endregion
private Controls.Base.NGButton buttonAdd;
private Controls.Base.NGButton buttonRemove;
private Controls.Base.NGButton buttonEdit;
private Controls.CredentialRepositoryListView credentialRepositoryListView;
private Controls.Base.NGButton buttonToggleLoad;
}
}

View File

@@ -0,0 +1,112 @@
using System;
using System.Drawing;
using System.Windows.Forms;
using mRemoteNG.Credential;
using mRemoteNG.Credential.Repositories;
using mRemoteNG.UI.Controls;
using mRemoteNG.UI.Controls.PageSequence;
using mRemoteNG.UI.Forms.CredentialManagerPages.CredentialRepositoryEditorPages;
using mRemoteNG.UI.Forms.CredentialManagerPages.CredentialRepositorySelectors;
namespace mRemoteNG.UI.Forms.CredentialManagerPages
{
public sealed partial class CredentialRepositoriesPage : SequencedControl, ICredentialManagerPage
{
private readonly ICredentialRepositoryList _providerCatalog;
private readonly UnlockerFormFactory _unlockerFactory;
public string PageName { get; } = "Sources";
public Image PageIcon { get; } = Resources.folder_key;
public CredentialRepositoriesPage(ICredentialRepositoryList providerCatalog, UnlockerFormFactory unlockerFactory)
{
if (providerCatalog == null)
throw new ArgumentNullException(nameof(providerCatalog));
if (unlockerFactory == null)
throw new ArgumentNullException(nameof(unlockerFactory));
_providerCatalog = providerCatalog;
_unlockerFactory = unlockerFactory;
InitializeComponent();
ApplyTheme();
credentialRepositoryListView.CredentialRepositoryList = providerCatalog;
credentialRepositoryListView.SelectionChanged += (sender, args) => UpdateUi();
credentialRepositoryListView.DoubleClickHandler = EditRepository;
}
private void UpdateUi()
{
var selectedRepository = credentialRepositoryListView.SelectedRepository;
buttonRemove.Enabled = selectedRepository != null;
buttonEdit.Enabled = selectedRepository != null;
buttonToggleLoad.Enabled = selectedRepository != null;
UpdateLoadToggleButton(selectedRepository);
}
private void buttonAdd_Click(object sender, EventArgs e)
{
var addRepoSequence = new PageSequence(Parent,
this,
new CredentialRepositoryTypeSelectionPage(
new ISelectionTarget<ICredentialRepositoryConfig>[]
{
new XmlCredentialRepositorySelector(),
//new KeePassRepositorySelector()
},
_providerCatalog
)
{ Dock = DockStyle.Fill },
new SequencedControl(),
this
);
RaiseNextPageEvent();
}
private void buttonEdit_Click(object sender, EventArgs e)
{
var selectedRepository = credentialRepositoryListView.SelectedRepository;
if (selectedRepository == null) return;
EditRepository(selectedRepository);
}
private bool EditRepository(ICredentialRepository repository)
{
if (!repository.IsLoaded) return false;
var editorPage = CredentialRepositoryPageEditorFactory.BuildXmlCredentialRepositoryEditorPage(repository.Config, _providerCatalog);
var pageSequence = new PageSequence(Parent,
this,
editorPage,
this
);
RaiseNextPageEvent();
return true;
}
private void buttonRemove_Click(object sender, EventArgs e)
{
var selectedRepository = credentialRepositoryListView.SelectedRepository;
if (selectedRepository == null) return;
if (_providerCatalog.Contains(selectedRepository.Config.Id))
_providerCatalog.RemoveProvider(selectedRepository);
}
private void UpdateLoadToggleButton(ICredentialRepository selectedRepository)
{
if (selectedRepository == null) return;
buttonToggleLoad.Text = selectedRepository.IsLoaded ? "Unload" : "Load";
}
private void buttonToggleLoad_Click(object sender, EventArgs e)
{
var selectedRepository = credentialRepositoryListView.SelectedRepository;
if (selectedRepository.IsLoaded)
selectedRepository.UnloadCredentials();
else
_unlockerFactory.Build(new[] {selectedRepository}).ShowDialog(this);
credentialRepositoryListView.RefreshObjects();
UpdateUi();
}
}
}

View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -0,0 +1,15 @@
using System.Windows.Forms;
using mRemoteNG.Credential;
using mRemoteNG.Credential.Repositories;
using mRemoteNG.UI.Controls.PageSequence;
namespace mRemoteNG.UI.Forms.CredentialManagerPages.CredentialRepositoryEditorPages
{
public class CredentialRepositoryPageEditorFactory
{
public static SequencedControl BuildXmlCredentialRepositoryEditorPage<T>(T config, ICredentialRepositoryList repositoryList) where T : ICredentialRepositoryConfig
{
return new XmlCredentialRepositoryEditorPage(config, repositoryList) {Dock = DockStyle.Fill};
}
}
}

View File

@@ -0,0 +1,198 @@
using mRemoteNG.Themes;
namespace mRemoteNG.UI.Forms.CredentialManagerPages.CredentialRepositoryEditorPages
{
partial class XmlCredentialRepositoryEditorPage
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.labelPageTitle = new Controls.Base.NGLabel();
this.buttonBrowseFiles = new Controls.Base.NGButton();
this.labelFilePath = new Controls.Base.NGLabel();
this.textBoxFilePath = new Controls.Base.NGTextBox();
this.selectFilePathDialog = new System.Windows.Forms.SaveFileDialog();
this.buttonConfirm = new Controls.Base.NGButton();
this.textBoxId = new Controls.Base.NGTextBox();
this.labelId = new Controls.Base.NGLabel();
this.buttonBack = new Controls.Base.NGButton();
this.newPasswordBoxes = new mRemoteNG.UI.Controls.NewPasswordWithVerification();
this.textBoxTitle = new Controls.Base.NGTextBox();
this.labelTitle = new Controls.Base.NGLabel();
this.SuspendLayout();
//
// labelPageTitle
//
this.labelPageTitle.AutoSize = true;
this.labelPageTitle.Location = new System.Drawing.Point(29, 6);
this.labelPageTitle.Name = "labelPageTitle";
this.labelPageTitle.Size = new System.Drawing.Size(132, 13);
this.labelPageTitle.TabIndex = 0;
this.labelPageTitle.Text = "XML Credential Repository";
//
// buttonBrowseFiles
//
this.buttonBrowseFiles.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.buttonBrowseFiles.Location = new System.Drawing.Point(276, 166);
this.buttonBrowseFiles.Name = "buttonBrowseFiles";
this.buttonBrowseFiles.Size = new System.Drawing.Size(75, 23);
this.buttonBrowseFiles.TabIndex = 1;
this.buttonBrowseFiles.Text = "Browse";
this.buttonBrowseFiles.UseVisualStyleBackColor = true;
this.buttonBrowseFiles.Click += new System.EventHandler(this.buttonBrowseFiles_Click);
//
// labelFilePath
//
this.labelFilePath.AutoSize = true;
this.labelFilePath.Location = new System.Drawing.Point(29, 124);
this.labelFilePath.Name = "labelFilePath";
this.labelFilePath.Size = new System.Drawing.Size(48, 13);
this.labelFilePath.TabIndex = 2;
this.labelFilePath.Text = "File Path";
//
// textBoxFilePath
//
this.textBoxFilePath.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.textBoxFilePath.Location = new System.Drawing.Point(32, 140);
this.textBoxFilePath.Name = "textBoxFilePath";
this.textBoxFilePath.Size = new System.Drawing.Size(319, 20);
this.textBoxFilePath.TabIndex = 3;
//
// selectFilePathDialog
//
this.selectFilePathDialog.DefaultExt = "xml";
this.selectFilePathDialog.Filter = "XML|*.xml";
//
// buttonConfirm
//
this.buttonConfirm.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonConfirm.Location = new System.Drawing.Point(266, 279);
this.buttonConfirm.Name = "buttonConfirm";
this.buttonConfirm.Size = new System.Drawing.Size(75, 23);
this.buttonConfirm.TabIndex = 9;
this.buttonConfirm.Text = "Confirm";
this.buttonConfirm.UseVisualStyleBackColor = true;
this.buttonConfirm.Click += new System.EventHandler(this.buttonConfirm_Click);
//
// textBoxId
//
this.textBoxId.Location = new System.Drawing.Point(32, 51);
this.textBoxId.Name = "textBoxId";
this.textBoxId.ReadOnly = true;
this.textBoxId.Size = new System.Drawing.Size(238, 20);
this.textBoxId.TabIndex = 10;
this.textBoxId.TabStop = false;
//
// labelId
//
this.labelId.AutoSize = true;
this.labelId.Location = new System.Drawing.Point(29, 35);
this.labelId.Name = "labelId";
this.labelId.Size = new System.Drawing.Size(18, 13);
this.labelId.TabIndex = 11;
this.labelId.Text = "ID";
//
// buttonBack
//
this.buttonBack.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonBack.Location = new System.Drawing.Point(185, 279);
this.buttonBack.Name = "buttonBack";
this.buttonBack.Size = new System.Drawing.Size(75, 23);
this.buttonBack.TabIndex = 12;
this.buttonBack.Text = "Back";
this.buttonBack.UseVisualStyleBackColor = true;
this.buttonBack.Click += new System.EventHandler(this.buttonBack_Click);
//
// newPasswordBoxes
//
this.newPasswordBoxes.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.newPasswordBoxes.Location = new System.Drawing.Point(32, 192);
this.newPasswordBoxes.MinimumSize = new System.Drawing.Size(0, 100);
this.newPasswordBoxes.Name = "newPasswordBoxes";
this.newPasswordBoxes.PasswordChar = '\0';
this.newPasswordBoxes.Size = new System.Drawing.Size(319, 100);
this.newPasswordBoxes.TabIndex = 13;
this.newPasswordBoxes.UseSystemPasswordChar = true;
//
// textBoxTitle
//
this.textBoxTitle.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.textBoxTitle.Location = new System.Drawing.Point(32, 97);
this.textBoxTitle.Name = "textBoxTitle";
this.textBoxTitle.Size = new System.Drawing.Size(319, 20);
this.textBoxTitle.TabIndex = 15;
//
// labelTitle
//
this.labelTitle.AutoSize = true;
this.labelTitle.Location = new System.Drawing.Point(29, 81);
this.labelTitle.Name = "labelTitle";
this.labelTitle.Size = new System.Drawing.Size(27, 13);
this.labelTitle.TabIndex = 14;
this.labelTitle.Text = "Title";
//
// XmlCredentialRepositoryEditorPage
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.textBoxTitle);
this.Controls.Add(this.labelTitle);
this.Controls.Add(this.buttonBack);
this.Controls.Add(this.labelId);
this.Controls.Add(this.textBoxId);
this.Controls.Add(this.buttonConfirm);
this.Controls.Add(this.textBoxFilePath);
this.Controls.Add(this.labelFilePath);
this.Controls.Add(this.buttonBrowseFiles);
this.Controls.Add(this.labelPageTitle);
this.Controls.Add(this.newPasswordBoxes);
this.MinimumSize = new System.Drawing.Size(300, 260);
this.Name = "XmlCredentialRepositoryEditorPage";
this.Size = new System.Drawing.Size(354, 305);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private Controls.Base.NGLabel labelPageTitle;
private Controls.Base.NGButton buttonBrowseFiles;
private Controls.Base.NGLabel labelFilePath;
private Controls.Base.NGTextBox textBoxFilePath;
private System.Windows.Forms.SaveFileDialog selectFilePathDialog;
private Controls.Base.NGButton buttonConfirm;
private Controls.Base.NGTextBox textBoxId;
private Controls.Base.NGLabel labelId;
private Controls.Base.NGButton buttonBack;
private Controls.NewPasswordWithVerification newPasswordBoxes;
private Controls.Base.NGTextBox textBoxTitle;
private Controls.Base.NGLabel labelTitle;
}
}

View File

@@ -0,0 +1,96 @@
using System;
using System.Windows.Forms;
using mRemoteNG.Config;
using mRemoteNG.Config.DataProviders;
using mRemoteNG.Config.Serializers.CredentialSerializer;
using mRemoteNG.Credential;
using mRemoteNG.Credential.Repositories;
using mRemoteNG.Security.Factories;
using mRemoteNG.UI.Controls.PageSequence;
namespace mRemoteNG.UI.Forms.CredentialManagerPages.CredentialRepositoryEditorPages
{
public partial class XmlCredentialRepositoryEditorPage : SequencedControl
{
private readonly ICredentialRepositoryConfig _repositoryConfig;
private readonly ICredentialRepositoryList _repositoryList;
public XmlCredentialRepositoryEditorPage(ICredentialRepositoryConfig repositoryConfig, ICredentialRepositoryList repositoryList)
{
if (repositoryConfig == null)
throw new ArgumentNullException(nameof(repositoryConfig));
if (repositoryList == null)
throw new ArgumentNullException(nameof(repositoryList));
_repositoryConfig = repositoryConfig;
_repositoryList = repositoryList;
InitializeComponent();
PopulateFields();
}
private void PopulateFields()
{
textBoxId.Text = _repositoryConfig.Id.ToString();
textBoxTitle.Text = _repositoryConfig.Title;
textBoxFilePath.Text = _repositoryConfig.Source;
newPasswordBoxes.SetPassword(_repositoryConfig.Key);
}
private void SaveValuesToConfig()
{
_repositoryConfig.Title = textBoxTitle.Text;
_repositoryConfig.Source = textBoxFilePath.Text;
_repositoryConfig.Key = newPasswordBoxes.SecureString;
}
private void buttonBrowseFiles_Click(object sender, EventArgs e)
{
if (!string.IsNullOrEmpty(_repositoryConfig.Source))
selectFilePathDialog.FileName = _repositoryConfig.Source;
var dialogResult = selectFilePathDialog.ShowDialog(this);
if (dialogResult == DialogResult.OK)
{
textBoxFilePath.Text = selectFilePathDialog.FileName;
}
}
private void buttonConfirm_Click(object sender, EventArgs e)
{
if (!AllRequiredFieldsFilledOut()) return;
SaveValuesToConfig();
if (!_repositoryList.Contains(_repositoryConfig.Id))
{
var newCredentialRepository = BuildXmlRepoFromSettings(_repositoryConfig);
_repositoryList.AddProvider(newCredentialRepository);
newCredentialRepository.SaveCredentials(_repositoryConfig.Key);
}
RaiseNextPageEvent();
}
private ICredentialRepository BuildXmlRepoFromSettings(ICredentialRepositoryConfig config)
{
var cryptoFromSettings = new CryptoProviderFactoryFromSettings();
var credRepoDataProvider = new FileDataProvider(config.Source);
var credRepoSerializer = new XmlCredentialPasswordEncryptorDecorator(
cryptoFromSettings.Build(),
new XmlCredentialRecordSerializer());
var credRepoDeserializer = new XmlCredentialPasswordDecryptorDecorator(new XmlCredentialRecordDeserializer());
return new XmlCredentialRepository(
config,
new CredentialRecordSaver(credRepoDataProvider, credRepoSerializer),
new CredentialRecordLoader(credRepoDataProvider, credRepoDeserializer)
);
}
private bool AllRequiredFieldsFilledOut()
{
return newPasswordBoxes.PasswordsMatch && !string.IsNullOrEmpty(textBoxFilePath.Text);
}
private void buttonBack_Click(object sender, EventArgs e)
{
RaisePreviousPageEvent();
}
}
}

View File

@@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="selectFilePathDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>

View File

@@ -0,0 +1,93 @@
using mRemoteNG.Credential.Repositories;
using mRemoteNG.Themes;
namespace mRemoteNG.UI.Forms.CredentialManagerPages
{
sealed partial class CredentialRepositorySelectionPage
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
CredentialRepositoryList credentialRepositoryList1 = new CredentialRepositoryList();
this.credentialRepositoryListView = new mRemoteNG.UI.Controls.CredentialRepositoryListView();
this.buttonContinue = new Controls.Base.NGButton();
this.buttonBack = new Controls.Base.NGButton();
this.SuspendLayout();
//
// credentialRepositoryListView
//
this.credentialRepositoryListView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.credentialRepositoryListView.CredentialRepositoryList = credentialRepositoryList1;
this.credentialRepositoryListView.DoubleClickHandler = null;
this.credentialRepositoryListView.Location = new System.Drawing.Point(0, 0);
this.credentialRepositoryListView.Name = "credentialRepositoryListView";
this.credentialRepositoryListView.Size = new System.Drawing.Size(368, 137);
this.credentialRepositoryListView.TabIndex = 0;
//
// buttonContinue
//
this.buttonContinue.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonContinue.Location = new System.Drawing.Point(278, 143);
this.buttonContinue.Name = "buttonContinue";
this.buttonContinue.Size = new System.Drawing.Size(75, 23);
this.buttonContinue.TabIndex = 1;
this.buttonContinue.Text = "Continue";
this.buttonContinue.UseVisualStyleBackColor = true;
this.buttonContinue.Click += new System.EventHandler(this.buttonContinue_Click);
//
// buttonBack
//
this.buttonBack.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonBack.Location = new System.Drawing.Point(197, 143);
this.buttonBack.Name = "buttonBack";
this.buttonBack.Size = new System.Drawing.Size(75, 23);
this.buttonBack.TabIndex = 2;
this.buttonBack.Text = "Back";
this.buttonBack.UseVisualStyleBackColor = true;
this.buttonBack.Click += new System.EventHandler(this.buttonBack_Click);
//
// CredentialRepositorySelectionPage
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.buttonBack);
this.Controls.Add(this.buttonContinue);
this.Controls.Add(this.credentialRepositoryListView);
this.Name = "CredentialRepositorySelectionPage";
this.Size = new System.Drawing.Size(368, 169);
this.ResumeLayout(false);
}
#endregion
private Controls.CredentialRepositoryListView credentialRepositoryListView;
private Controls.Base.NGButton buttonContinue;
private Controls.Base.NGButton buttonBack;
}
}

View File

@@ -0,0 +1,49 @@
using System;
using System.Windows.Forms;
using mRemoteNG.Credential;
using mRemoteNG.UI.Controls.PageSequence;
namespace mRemoteNG.UI.Forms.CredentialManagerPages
{
public sealed partial class CredentialRepositorySelectionPage : SequencedControl
{
public CredentialRepositorySelectionPage(ICredentialRepositoryList credentialRepositoryList)
{
if (credentialRepositoryList == null)
throw new ArgumentNullException(nameof(credentialRepositoryList));
InitializeComponent();
ApplyTheme();
Dock = DockStyle.Fill;
credentialRepositoryListView.RepositoryFilter = repository => repository.IsLoaded;
credentialRepositoryListView.CredentialRepositoryList = credentialRepositoryList;
credentialRepositoryListView.DoubleClickHandler = DoubleClickHandler;
}
private void Continue(ICredentialRepository credentialRepository)
{
var newCred = new CredentialRecord();
var newCredPage = new CredentialEditorPage(newCred, credentialRepository);
RaisePageReplacementEvent(newCredPage, RelativePagePosition.NextPage);
RaiseNextPageEvent();
}
private bool DoubleClickHandler(ICredentialRepository credentialRepository)
{
if (credentialRepository == null) return false;
Continue(credentialRepository);
return true;
}
private void buttonContinue_Click(object sender, EventArgs e)
{
if (credentialRepositoryListView.SelectedRepository == null) return;
Continue(credentialRepositoryListView.SelectedRepository);
}
private void buttonBack_Click(object sender, EventArgs e)
{
RaisePreviousPageEvent();
}
}
}

View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -0,0 +1,13 @@
using System.Drawing;
using mRemoteNG.Credential.Repositories;
using mRemoteNG.UI.Controls;
namespace mRemoteNG.UI.Forms.CredentialManagerPages.CredentialRepositorySelectors
{
public class KeePassRepositorySelector : ISelectionTarget<ICredentialRepositoryConfig>
{
public string Text { get; set; } = "KeePass";
public Image Image { get; } = Resources.keepass_32x32;
public ICredentialRepositoryConfig Config { get; } = new CredentialRepositoryConfig {TypeName = "KeePass"};
}
}

View File

@@ -0,0 +1,13 @@
using System.Drawing;
using mRemoteNG.Credential.Repositories;
using mRemoteNG.UI.Controls;
namespace mRemoteNG.UI.Forms.CredentialManagerPages.CredentialRepositorySelectors
{
public class XmlCredentialRepositorySelector : ISelectionTarget<ICredentialRepositoryConfig>
{
public string Text { get; set; } = "XML";
public Image Image { get; } = Resources.xml;
public ICredentialRepositoryConfig Config { get; } = new CredentialRepositoryConfig {TypeName = "Xml"};
}
}

View File

@@ -0,0 +1,135 @@
using mRemoteNG.Themes;
namespace mRemoteNG.UI.Forms.CredentialManagerPages
{
sealed partial class CredentialRepositoryTypeSelectionPage
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.buttonContinue = new Controls.Base.NGButton();
this.objectListView = new Controls.Base.NGListView();
this.olvColumnName = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
this.imageListLarge = new System.Windows.Forms.ImageList(this.components);
this.buttonBack = new Controls.Base.NGButton();
((System.ComponentModel.ISupportInitialize)(this.objectListView)).BeginInit();
this.SuspendLayout();
//
// buttonContinue
//
this.buttonContinue.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonContinue.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
this.buttonContinue.Location = new System.Drawing.Point(333, 312);
this.buttonContinue.Name = "buttonContinue";
this.buttonContinue.Size = new System.Drawing.Size(75, 23);
this.buttonContinue.TabIndex = 4;
this.buttonContinue.Text = "Continue";
this.buttonContinue.UseVisualStyleBackColor = true;
this.buttonContinue.Click += new System.EventHandler(this.buttonContinue_Click);
//
// objectListView
//
this.objectListView.AllColumns.Add(this.olvColumnName);
this.objectListView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.objectListView.CellEditUseWholeCell = false;
this.objectListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.olvColumnName});
this.objectListView.CopySelectionOnControlC = false;
this.objectListView.CopySelectionOnControlCUsesDragSource = false;
this.objectListView.Cursor = System.Windows.Forms.Cursors.Default;
this.objectListView.FullRowSelect = true;
this.objectListView.HasCollapsibleGroups = false;
this.objectListView.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.None;
this.objectListView.HideSelection = false;
this.objectListView.LargeImageList = this.imageListLarge;
this.objectListView.Location = new System.Drawing.Point(0, 0);
this.objectListView.MultiSelect = false;
this.objectListView.Name = "objectListView";
this.objectListView.SelectAllOnControlA = false;
this.objectListView.SelectColumnsOnRightClick = false;
this.objectListView.SelectColumnsOnRightClickBehaviour = BrightIdeasSoftware.ObjectListView.ColumnSelectBehaviour.None;
this.objectListView.ShowFilterMenuOnRightClick = false;
this.objectListView.ShowHeaderInAllViews = false;
this.objectListView.Size = new System.Drawing.Size(422, 297);
this.objectListView.Sorting = System.Windows.Forms.SortOrder.Ascending;
this.objectListView.TabIndex = 5;
this.objectListView.UseCompatibleStateImageBehavior = false;
this.objectListView.View = System.Windows.Forms.View.LargeIcon;
//
// olvColumnName
//
this.olvColumnName.AspectName = "Text";
this.olvColumnName.FillsFreeSpace = true;
this.olvColumnName.Groupable = false;
this.olvColumnName.ImageAspectName = "";
this.olvColumnName.IsEditable = false;
this.olvColumnName.Searchable = false;
this.olvColumnName.ShowTextInHeader = false;
//
// imageListLarge
//
this.imageListLarge.ColorDepth = System.Windows.Forms.ColorDepth.Depth8Bit;
this.imageListLarge.ImageSize = new System.Drawing.Size(32, 32);
this.imageListLarge.TransparentColor = System.Drawing.Color.Transparent;
//
// buttonBack
//
this.buttonBack.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonBack.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
this.buttonBack.Location = new System.Drawing.Point(252, 312);
this.buttonBack.Name = "buttonBack";
this.buttonBack.Size = new System.Drawing.Size(75, 23);
this.buttonBack.TabIndex = 6;
this.buttonBack.Text = "Back";
this.buttonBack.UseVisualStyleBackColor = true;
this.buttonBack.Click += new System.EventHandler(this.buttonBack_Click);
//
// CredentialRepositorySelectionPage
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.buttonBack);
this.Controls.Add(this.objectListView);
this.Controls.Add(this.buttonContinue);
this.Name = "CredentialRepositorySelectionPage";
this.Size = new System.Drawing.Size(422, 338);
((System.ComponentModel.ISupportInitialize)(this.objectListView)).EndInit();
this.ResumeLayout(false);
}
#endregion
private Controls.Base.NGButton buttonContinue;
private Controls.Base.NGListView objectListView;
private BrightIdeasSoftware.OLVColumn olvColumnName;
private System.Windows.Forms.ImageList imageListLarge;
private Controls.Base.NGButton buttonBack;
}
}

View File

@@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using BrightIdeasSoftware;
using mRemoteNG.Credential;
using mRemoteNG.Credential.Repositories;
using mRemoteNG.UI.Controls;
using mRemoteNG.UI.Controls.PageSequence;
using mRemoteNG.UI.Forms.CredentialManagerPages.CredentialRepositoryEditorPages;
namespace mRemoteNG.UI.Forms.CredentialManagerPages
{
public sealed partial class CredentialRepositoryTypeSelectionPage : SequencedControl
{
private readonly ICredentialRepositoryList _repositoryList;
public CredentialRepositoryTypeSelectionPage(IEnumerable<ISelectionTarget<ICredentialRepositoryConfig>> selectionTargets, ICredentialRepositoryList repositoryList)
{
if (selectionTargets == null)
throw new ArgumentNullException(nameof(selectionTargets));
if (repositoryList == null)
throw new ArgumentNullException(nameof(repositoryList));
_repositoryList = repositoryList;
InitializeComponent();
ApplyTheme();
SetupListView(selectionTargets);
}
private void SetupListView(IEnumerable<ISelectionTarget<ICredentialRepositoryConfig>> selectionTargets)
{
olvColumnName.ImageGetter = ImageGetter;
objectListView.MouseDoubleClick += ObjectListViewOnMouseDoubleClick;
objectListView.SetObjects(selectionTargets);
}
private object ImageGetter(object rowObject)
{
var selection = rowObject as ISelectionTarget<ICredentialRepositoryConfig>;
if (selection == null) return "";
var imgHash = selection.Image.GetHashCode().ToString();
if (!objectListView.LargeImageList.Images.ContainsKey(imgHash))
objectListView.LargeImageList.Images.Add(imgHash, selection.Image);
return imgHash;
}
private void ObjectListViewOnMouseDoubleClick(object sender, MouseEventArgs mouseEventArgs)
{
if (mouseEventArgs.Clicks < 2) return;
OLVColumn column;
var listItem = objectListView.GetItemAt(mouseEventArgs.X, mouseEventArgs.Y, out column);
var clickedNode = listItem.RowObject as ISelectionTarget<ICredentialRepositoryConfig>;
if (clickedNode == null) return;
NextPage(clickedNode);
}
private void buttonContinue_Click(object sender, EventArgs e)
{
var selection = objectListView.SelectedObject as ISelectionTarget<ICredentialRepositoryConfig>;
if (selection == null) return;
NextPage(selection);
}
private void NextPage(ISelectionTarget<ICredentialRepositoryConfig> selection)
{
var editorPage = BuildEditorPage(selection);
RaisePageReplacementEvent(editorPage, RelativePagePosition.NextPage);
RaiseNextPageEvent();
}
private SequencedControl BuildEditorPage(ISelectionTarget<ICredentialRepositoryConfig> selection)
{
var editorPage = CredentialRepositoryPageEditorFactory.BuildXmlCredentialRepositoryEditorPage(selection.Config, _repositoryList);
editorPage.Dock = DockStyle.Fill;
return editorPage;
}
private void buttonBack_Click(object sender, EventArgs e)
{
RaisePreviousPageEvent();
}
}
}

View File

@@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="imageListLarge.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>

View File

@@ -0,0 +1,11 @@
using System.Drawing;
namespace mRemoteNG.UI.Forms.CredentialManagerPages
{
public interface ICredentialManagerPage
{
string PageName { get; }
Image PageIcon { get; }
}
}

View File

@@ -0,0 +1,318 @@
namespace mRemoteNG.UI.Forms
{
partial class CredentialManagerUpgradeForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(CredentialManagerUpgradeForm));
this.newCredRepoPathDialog = new System.Windows.Forms.SaveFileDialog();
this.tabControl = new mRemoteNG.UI.Controls.HeadlessTabControl();
this.tabPageWelcome = new System.Windows.Forms.TabPage();
this.textBoxConfConPathTab1 = new Controls.Base.NGTextBox();
this.labelConfConsPathHeaderOnTab1 = new Controls.Base.NGLabel();
this.buttonExit = new Controls.Base.NGButton();
this.labelDescriptionOfUpgrade = new Controls.Base.NGLabel();
this.buttonPerformUpgrade = new Controls.Base.NGButton();
this.buttonNewFile = new Controls.Base.NGButton();
this.buttonOpenFile = new Controls.Base.NGButton();
this.tabPageUpgradeOptions = new System.Windows.Forms.TabPage();
this.textBoxConfConPathTab2 = new Controls.Base.NGTextBox();
this.buttonNewRepoPathBrowse = new Controls.Base.NGButton();
this.labelWhereToSaveCredFile = new Controls.Base.NGLabel();
this.textBoxCredRepoPath = new Controls.Base.NGTextBox();
this.buttonExecuteUpgrade = new Controls.Base.NGButton();
this.labelSetPassword = new Controls.Base.NGLabel();
this.newPasswordWithVerification1 = new mRemoteNG.UI.Controls.NewPasswordWithVerification();
this.labelConfConsPathHeaderOnTab2 = new Controls.Base.NGLabel();
this.buttonBack = new Controls.Base.NGButton();
this.newConnectionsFileDialog = new System.Windows.Forms.SaveFileDialog();
this.tabControl.SuspendLayout();
this.tabPageWelcome.SuspendLayout();
this.tabPageUpgradeOptions.SuspendLayout();
this.SuspendLayout();
//
// newCredRepoPathDialog
//
this.newCredRepoPathDialog.Filter = "Xml|*.xml|All files|*.*";
this.newCredRepoPathDialog.Title = "New credential repository path";
//
// tabControl
//
this.tabControl.Controls.Add(this.tabPageWelcome);
this.tabControl.Controls.Add(this.tabPageUpgradeOptions);
this.tabControl.Dock = System.Windows.Forms.DockStyle.Fill;
this.tabControl.ItemSize = new System.Drawing.Size(60, 20);
this.tabControl.Location = new System.Drawing.Point(0, 0);
this.tabControl.Name = "tabControl";
this.tabControl.SelectedIndex = 0;
this.tabControl.Size = new System.Drawing.Size(420, 402);
this.tabControl.TabIndex = 5;
//
// tabPageWelcome
//
this.tabPageWelcome.BackColor = System.Drawing.SystemColors.Control;
this.tabPageWelcome.Controls.Add(this.textBoxConfConPathTab1);
this.tabPageWelcome.Controls.Add(this.labelConfConsPathHeaderOnTab1);
this.tabPageWelcome.Controls.Add(this.buttonExit);
this.tabPageWelcome.Controls.Add(this.labelDescriptionOfUpgrade);
this.tabPageWelcome.Controls.Add(this.buttonPerformUpgrade);
this.tabPageWelcome.Controls.Add(this.buttonNewFile);
this.tabPageWelcome.Controls.Add(this.buttonOpenFile);
this.tabPageWelcome.Location = new System.Drawing.Point(4, 24);
this.tabPageWelcome.Name = "tabPageWelcome";
this.tabPageWelcome.Padding = new System.Windows.Forms.Padding(3);
this.tabPageWelcome.Size = new System.Drawing.Size(412, 374);
this.tabPageWelcome.TabIndex = 0;
this.tabPageWelcome.Text = "welcomePage";
//
// textBoxConfConPathTab1
//
this.textBoxConfConPathTab1.Location = new System.Drawing.Point(30, 177);
this.textBoxConfConPathTab1.Multiline = true;
this.textBoxConfConPathTab1.Name = "textBoxConfConPathTab1";
this.textBoxConfConPathTab1.ReadOnly = true;
this.textBoxConfConPathTab1.Size = new System.Drawing.Size(376, 55);
this.textBoxConfConPathTab1.TabIndex = 6;
//
// labelConfConsPathHeaderOnTab1
//
this.labelConfConsPathHeaderOnTab1.AutoSize = true;
this.labelConfConsPathHeaderOnTab1.Location = new System.Drawing.Point(10, 161);
this.labelConfConsPathHeaderOnTab1.Name = "labelConfConsPathHeaderOnTab1";
this.labelConfConsPathHeaderOnTab1.Size = new System.Drawing.Size(104, 13);
this.labelConfConsPathHeaderOnTab1.TabIndex = 5;
this.labelConfConsPathHeaderOnTab1.Text = "Connection file path:";
//
// buttonExit
//
this.buttonExit.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.buttonExit.Location = new System.Drawing.Point(142, 343);
this.buttonExit.Name = "buttonExit";
this.buttonExit.Size = new System.Drawing.Size(139, 23);
this.buttonExit.TabIndex = 4;
this.buttonExit.Text = "Exit";
this.buttonExit.UseVisualStyleBackColor = true;
this.buttonExit.Click += new System.EventHandler(this.buttonExit_Click);
//
// labelDescriptionOfUpgrade
//
this.labelDescriptionOfUpgrade.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.labelDescriptionOfUpgrade.Location = new System.Drawing.Point(6, 20);
this.labelDescriptionOfUpgrade.Name = "labelDescriptionOfUpgrade";
this.labelDescriptionOfUpgrade.Size = new System.Drawing.Size(400, 141);
this.labelDescriptionOfUpgrade.TabIndex = 0;
this.labelDescriptionOfUpgrade.Text = resources.GetString("labelDescriptionOfUpgrade.Text");
//
// buttonPerformUpgrade
//
this.buttonPerformUpgrade.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.buttonPerformUpgrade.Location = new System.Drawing.Point(142, 256);
this.buttonPerformUpgrade.Name = "buttonPerformUpgrade";
this.buttonPerformUpgrade.Size = new System.Drawing.Size(139, 23);
this.buttonPerformUpgrade.TabIndex = 1;
this.buttonPerformUpgrade.Text = "Upgrade";
this.buttonPerformUpgrade.UseVisualStyleBackColor = true;
this.buttonPerformUpgrade.Click += new System.EventHandler(this.buttonPerformUpgrade_Click);
//
// buttonNewFile
//
this.buttonNewFile.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.buttonNewFile.DialogResult = System.Windows.Forms.DialogResult.Abort;
this.buttonNewFile.Location = new System.Drawing.Point(142, 314);
this.buttonNewFile.Name = "buttonNewFile";
this.buttonNewFile.Size = new System.Drawing.Size(139, 23);
this.buttonNewFile.TabIndex = 3;
this.buttonNewFile.Text = "Create and open new file";
this.buttonNewFile.UseVisualStyleBackColor = true;
this.buttonNewFile.Click += new System.EventHandler(this.buttonNewFile_Click);
//
// buttonOpenFile
//
this.buttonOpenFile.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.buttonOpenFile.Location = new System.Drawing.Point(142, 285);
this.buttonOpenFile.Name = "buttonOpenFile";
this.buttonOpenFile.Size = new System.Drawing.Size(139, 23);
this.buttonOpenFile.TabIndex = 2;
this.buttonOpenFile.Text = "Open a different file";
this.buttonOpenFile.UseVisualStyleBackColor = true;
this.buttonOpenFile.Click += new System.EventHandler(this.buttonOpenFile_Click);
//
// tabPageUpgradeOptions
//
this.tabPageUpgradeOptions.BackColor = System.Drawing.SystemColors.Control;
this.tabPageUpgradeOptions.Controls.Add(this.textBoxConfConPathTab2);
this.tabPageUpgradeOptions.Controls.Add(this.buttonNewRepoPathBrowse);
this.tabPageUpgradeOptions.Controls.Add(this.labelWhereToSaveCredFile);
this.tabPageUpgradeOptions.Controls.Add(this.textBoxCredRepoPath);
this.tabPageUpgradeOptions.Controls.Add(this.buttonExecuteUpgrade);
this.tabPageUpgradeOptions.Controls.Add(this.labelSetPassword);
this.tabPageUpgradeOptions.Controls.Add(this.newPasswordWithVerification1);
this.tabPageUpgradeOptions.Controls.Add(this.labelConfConsPathHeaderOnTab2);
this.tabPageUpgradeOptions.Controls.Add(this.buttonBack);
this.tabPageUpgradeOptions.Location = new System.Drawing.Point(4, 24);
this.tabPageUpgradeOptions.Name = "tabPageUpgradeOptions";
this.tabPageUpgradeOptions.Padding = new System.Windows.Forms.Padding(3);
this.tabPageUpgradeOptions.Size = new System.Drawing.Size(412, 374);
this.tabPageUpgradeOptions.TabIndex = 1;
this.tabPageUpgradeOptions.Text = "upgradePage";
//
// textBoxConfConPathTab2
//
this.textBoxConfConPathTab2.Location = new System.Drawing.Point(27, 32);
this.textBoxConfConPathTab2.Multiline = true;
this.textBoxConfConPathTab2.Name = "textBoxConfConPathTab2";
this.textBoxConfConPathTab2.ReadOnly = true;
this.textBoxConfConPathTab2.Size = new System.Drawing.Size(377, 41);
this.textBoxConfConPathTab2.TabIndex = 9;
//
// buttonNewRepoPathBrowse
//
this.buttonNewRepoPathBrowse.Location = new System.Drawing.Point(329, 143);
this.buttonNewRepoPathBrowse.Name = "buttonNewRepoPathBrowse";
this.buttonNewRepoPathBrowse.Size = new System.Drawing.Size(75, 23);
this.buttonNewRepoPathBrowse.TabIndex = 8;
this.buttonNewRepoPathBrowse.Text = "Browse";
this.buttonNewRepoPathBrowse.UseVisualStyleBackColor = true;
this.buttonNewRepoPathBrowse.Click += new System.EventHandler(this.buttonNewRepoPathBrowse_Click);
//
// labelWhereToSaveCredFile
//
this.labelWhereToSaveCredFile.AutoSize = true;
this.labelWhereToSaveCredFile.Location = new System.Drawing.Point(14, 98);
this.labelWhereToSaveCredFile.Name = "labelWhereToSaveCredFile";
this.labelWhereToSaveCredFile.Size = new System.Drawing.Size(228, 13);
this.labelWhereToSaveCredFile.TabIndex = 7;
this.labelWhereToSaveCredFile.Text = "Where should we save the new credential file?";
//
// textBoxCredRepoPath
//
this.textBoxCredRepoPath.Location = new System.Drawing.Point(27, 117);
this.textBoxCredRepoPath.Name = "textBoxCredRepoPath";
this.textBoxCredRepoPath.Size = new System.Drawing.Size(377, 20);
this.textBoxCredRepoPath.TabIndex = 6;
//
// buttonExecuteUpgrade
//
this.buttonExecuteUpgrade.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonExecuteUpgrade.DialogResult = System.Windows.Forms.DialogResult.OK;
this.buttonExecuteUpgrade.Location = new System.Drawing.Point(329, 343);
this.buttonExecuteUpgrade.Name = "buttonExecuteUpgrade";
this.buttonExecuteUpgrade.Size = new System.Drawing.Size(75, 23);
this.buttonExecuteUpgrade.TabIndex = 5;
this.buttonExecuteUpgrade.Text = "Upgrade";
this.buttonExecuteUpgrade.UseVisualStyleBackColor = true;
//
// labelSetPassword
//
this.labelSetPassword.AutoSize = true;
this.labelSetPassword.Location = new System.Drawing.Point(13, 194);
this.labelSetPassword.Name = "labelSetPassword";
this.labelSetPassword.Size = new System.Drawing.Size(201, 13);
this.labelSetPassword.TabIndex = 4;
this.labelSetPassword.Text = "Set password for the credential repository";
//
// newPasswordWithVerification1
//
this.newPasswordWithVerification1.Location = new System.Drawing.Point(27, 220);
this.newPasswordWithVerification1.MinimumSize = new System.Drawing.Size(0, 100);
this.newPasswordWithVerification1.Name = "newPasswordWithVerification1";
this.newPasswordWithVerification1.PasswordChar = '\0';
this.newPasswordWithVerification1.Size = new System.Drawing.Size(377, 100);
this.newPasswordWithVerification1.TabIndex = 3;
this.newPasswordWithVerification1.UseSystemPasswordChar = false;
//
// labelConfConsPathHeaderOnTab2
//
this.labelConfConsPathHeaderOnTab2.AutoSize = true;
this.labelConfConsPathHeaderOnTab2.Location = new System.Drawing.Point(6, 16);
this.labelConfConsPathHeaderOnTab2.Name = "labelConfConsPathHeaderOnTab2";
this.labelConfConsPathHeaderOnTab2.Size = new System.Drawing.Size(85, 13);
this.labelConfConsPathHeaderOnTab2.TabIndex = 1;
this.labelConfConsPathHeaderOnTab2.Text = "Connections file:";
//
// buttonBack
//
this.buttonBack.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonBack.Location = new System.Drawing.Point(248, 343);
this.buttonBack.Name = "buttonBack";
this.buttonBack.Size = new System.Drawing.Size(75, 23);
this.buttonBack.TabIndex = 0;
this.buttonBack.Text = "Back";
this.buttonBack.UseVisualStyleBackColor = true;
this.buttonBack.Click += new System.EventHandler(this.buttonBack_Click);
//
// newConnectionsFileDialog
//
this.newConnectionsFileDialog.Filter = "Xml|*.xml|All files|*.*";
this.newConnectionsFileDialog.Title = "Create new connection file";
//
// CredentialManagerUpgradeForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(420, 402);
this.ControlBox = false;
this.Controls.Add(this.tabControl);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.Name = "CredentialManagerUpgradeForm";
this.ShowInTaskbar = false;
this.Text = "Credential Manager Upgrade";
this.tabControl.ResumeLayout(false);
this.tabPageWelcome.ResumeLayout(false);
this.tabPageWelcome.PerformLayout();
this.tabPageUpgradeOptions.ResumeLayout(false);
this.tabPageUpgradeOptions.PerformLayout();
this.ResumeLayout(false);
}
#endregion
private Controls.Base.NGLabel labelDescriptionOfUpgrade;
private Controls.Base.NGButton buttonPerformUpgrade;
private Controls.Base.NGButton buttonOpenFile;
private Controls.Base.NGButton buttonNewFile;
private Controls.Base.NGButton buttonExit;
private mRemoteNG.UI.Controls.HeadlessTabControl tabControl;
private System.Windows.Forms.TabPage tabPageWelcome;
private System.Windows.Forms.TabPage tabPageUpgradeOptions;
private Controls.Base.NGButton buttonBack;
private Controls.Base.NGLabel labelConfConsPathHeaderOnTab2;
private Controls.Base.NGButton buttonExecuteUpgrade;
private Controls.Base.NGLabel labelSetPassword;
private Controls.NewPasswordWithVerification newPasswordWithVerification1;
private Controls.Base.NGLabel labelWhereToSaveCredFile;
private Controls.Base.NGTextBox textBoxCredRepoPath;
private System.Windows.Forms.SaveFileDialog newCredRepoPathDialog;
private Controls.Base.NGButton buttonNewRepoPathBrowse;
private Controls.Base.NGLabel labelConfConsPathHeaderOnTab1;
private Controls.Base.NGTextBox textBoxConfConPathTab1;
private Controls.Base.NGTextBox textBoxConfConPathTab2;
private System.Windows.Forms.SaveFileDialog newConnectionsFileDialog;
}
}

View File

@@ -0,0 +1,126 @@
using System;
using System.Windows.Forms;
using System.Xml.Linq;
using mRemoteNG.App;
using mRemoteNG.Config.Serializers;
using mRemoteNG.Config.Serializers.Versioning;
using mRemoteNG.Tree;
namespace mRemoteNG.UI.Forms
{
public partial class CredentialManagerUpgradeForm : Form, IDeserializer<string, ConnectionTreeModel>
{
private string _connectionFilePath;
private string _newCredentialRepoPath;
public XmlCredentialManagerUpgrader DecoratedDeserializer { get; set; }
public string ConnectionFilePath
{
get { return _connectionFilePath; }
set
{
_connectionFilePath = value;
UpdateUi();
}
}
public string NewCredentialRepoPath
{
get { return _newCredentialRepoPath; }
set
{
_newCredentialRepoPath = value;
UpdateUi();
}
}
public CredentialManagerUpgradeForm()
{
InitializeComponent();
ApplyLanguage();
UpdateUi();
}
public ConnectionTreeModel Deserialize(string serializedData)
{
var xdoc = XDocument.Parse(serializedData);
if (!WeCanUpgradeFromThisVersion(xdoc))
return DecoratedDeserializer.Deserialize(serializedData);
var result = ShowDialog();
if (result != DialogResult.OK) return new ConnectionTreeModel();
DecoratedDeserializer.CredentialFilePath = NewCredentialRepoPath;
return DecoratedDeserializer.Deserialize(serializedData);
}
private bool WeCanUpgradeFromThisVersion(XDocument xdoc)
{
return XmlCredentialManagerUpgrader.GetVersionFromConfiguration(xdoc) < 2.8m;
}
private void ApplyLanguage()
{
// tab 1
labelDescriptionOfUpgrade.Text = Language.strCredentialManagerUpgradeDescription;
labelConfConsPathHeaderOnTab1.Text = $@"{Language.strConnectionFilePath}:";
buttonPerformUpgrade.Text = Language.strUpgrade;
buttonOpenFile.Text = Language.strOpenADifferentFile;
buttonNewFile.Text = Language.strCreateAndOpenNewFile;
buttonExit.Text = Language.strMenuExit;
// tab 2
labelConfConsPathHeaderOnTab2.Text = $@"{Language.strConnectionFilePath}:";
labelWhereToSaveCredFile.Text = "Where should we save the new credential file?";
labelSetPassword.Text = "Set password for the credential repository";
buttonNewRepoPathBrowse.Text = Language.strButtonBrowse;
buttonBack.Text = Language.strBack;
buttonExecuteUpgrade.Text = Language.strUpgrade;
}
private void UpdateUi()
{
textBoxConfConPathTab1.Text = ConnectionFilePath;
textBoxConfConPathTab2.Text = ConnectionFilePath;
textBoxCredRepoPath.Text = NewCredentialRepoPath;
}
private void buttonPerformUpgrade_Click(object sender, EventArgs e)
{
tabControl.SelectedTab = tabPageUpgradeOptions;
}
private void buttonOpenFile_Click(object sender, EventArgs e)
{
var loadConnectionsDialog = DialogFactory.BuildLoadConnectionsDialog();
var dialogResult = loadConnectionsDialog.ShowDialog(this);
if (dialogResult == DialogResult.OK)
ConnectionFilePath = loadConnectionsDialog.FileName;
}
private void buttonNewFile_Click(object sender, EventArgs e)
{
var dialogResult = newConnectionsFileDialog.ShowDialog(this);
if (dialogResult != DialogResult.OK) return;
Runtime.ConnectionsService.NewConnectionsFile(newConnectionsFileDialog.FileName);
Close();
}
private void buttonExit_Click(object sender, EventArgs e)
{
Shutdown.Quit();
}
private void buttonNewRepoPathBrowse_Click(object sender, EventArgs e)
{
var dialogResult = newCredRepoPathDialog.ShowDialog(this);
if (dialogResult == DialogResult.OK)
NewCredentialRepoPath = newCredRepoPathDialog.FileName;
}
private void buttonBack_Click(object sender, EventArgs e)
{
tabControl.SelectedTab = tabPageWelcome;
}
}
}

View File

@@ -0,0 +1,131 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="newCredRepoPathDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<data name="labelDescriptionOfUpgrade.Text" xml:space="preserve">
<value>In v1.76 we have introduced a credential management system. This feature requires a significant change in how we store and interact with credentials within mRemoteNG. You will be required to perform a one-way upgrade of your mRemoteNG connections file.
This page will walk you through the process of upgrading your connections file or give you a chance to open a different connections file if you do not want to perform the upgrade.</value>
</data>
<metadata name="newConnectionsFileDialog.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>193, 21</value>
</metadata>
</root>

View File

@@ -0,0 +1,16 @@
using System.Collections.Generic;
using mRemoteNG.Credential;
using mRemoteNG.Credential.Repositories;
namespace mRemoteNG.UI.Forms
{
public class UnlockerFormFactory
{
public CompositeCredentialRepoUnlockerForm Build(IEnumerable<ICredentialRepository> repositories)
{
return new CompositeCredentialRepoUnlockerForm(
new CompositeRepositoryUnlocker(repositories)
);
}
}
}

View File

@@ -188,6 +188,7 @@
<Compile Include="Config\Serializers\Versioning\SqlVersion24To25Upgrader.cs" />
<Compile Include="Config\Serializers\Versioning\SqlVersion25To26Upgrader.cs" />
<Compile Include="Config\Serializers\Versioning\SqlVersion26To27Upgrader.cs" />
<Compile Include="Config\Serializers\Versioning\XmlCredentialManagerUpgrader.cs" />
<Compile Include="Config\Serializers\XmlConnectionsDecryptor.cs" />
<Compile Include="Config\DataProviders\FileDataProviderWithRollingBackup.cs" />
<Compile Include="Config\DataProviders\SqlDataProvider.cs" />
@@ -490,6 +491,64 @@
<Compile Include="UI\DisplayProperties.cs" />
<Compile Include="UI\FontOverrider.cs" />
<Compile Include="UI\FormExtensions.cs" />
<Compile Include="UI\Forms\CompositeCredentialRepoUnlockerForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="UI\Forms\CompositeCredentialRepoUnlockerForm.Designer.cs">
<DependentUpon>CompositeCredentialRepoUnlockerForm.cs</DependentUpon>
</Compile>
<Compile Include="UI\Forms\CredentialManagerForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="UI\Forms\CredentialManagerForm.Designer.cs">
<DependentUpon>CredentialManagerForm.cs</DependentUpon>
</Compile>
<Compile Include="UI\Forms\CredentialManagerPages\CredentialEditorPage.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="UI\Forms\CredentialManagerPages\CredentialEditorPage.Designer.cs">
<DependentUpon>CredentialEditorPage.cs</DependentUpon>
</Compile>
<Compile Include="UI\Forms\CredentialManagerPages\CredentialListPage.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="UI\Forms\CredentialManagerPages\CredentialListPage.Designer.cs">
<DependentUpon>CredentialListPage.cs</DependentUpon>
</Compile>
<Compile Include="UI\Forms\CredentialManagerPages\CredentialRepositoriesPage.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="UI\Forms\CredentialManagerPages\CredentialRepositoriesPage.Designer.cs">
<DependentUpon>CredentialRepositoriesPage.cs</DependentUpon>
</Compile>
<Compile Include="UI\Forms\CredentialManagerPages\CredentialRepositoryEditorPages\CredentialRepositoryPageEditorFactory.cs" />
<Compile Include="UI\Forms\CredentialManagerPages\CredentialRepositoryEditorPages\XmlCredentialRepositoryEditorPage.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="UI\Forms\CredentialManagerPages\CredentialRepositoryEditorPages\XmlCredentialRepositoryEditorPage.Designer.cs">
<DependentUpon>XmlCredentialRepositoryEditorPage.cs</DependentUpon>
</Compile>
<Compile Include="UI\Forms\CredentialManagerPages\CredentialRepositorySelectionPage.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="UI\Forms\CredentialManagerPages\CredentialRepositorySelectionPage.Designer.cs">
<DependentUpon>CredentialRepositorySelectionPage.cs</DependentUpon>
</Compile>
<Compile Include="UI\Forms\CredentialManagerPages\CredentialRepositorySelectors\KeePassRepositorySelector.cs" />
<Compile Include="UI\Forms\CredentialManagerPages\CredentialRepositorySelectors\XmlCredentialRepositorySelector.cs" />
<Compile Include="UI\Forms\CredentialManagerPages\CredentialRepositoryTypeSelectionPage.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="UI\Forms\CredentialManagerPages\CredentialRepositoryTypeSelectionPage.Designer.cs">
<DependentUpon>CredentialRepositoryTypeSelectionPage.cs</DependentUpon>
</Compile>
<Compile Include="UI\Forms\CredentialManagerPages\ICredentialManagerPage.cs" />
<Compile Include="UI\Forms\CredentialManagerUpgradeForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="UI\Forms\CredentialManagerUpgradeForm.Designer.cs">
<DependentUpon>CredentialManagerUpgradeForm.cs</DependentUpon>
</Compile>
<Compile Include="UI\Forms\FrmOptions.cs">
<SubType>Form</SubType>
</Compile>
@@ -670,6 +729,7 @@
<Compile Include="UI\Forms\UnhandledExceptionWindow.Designer.cs">
<DependentUpon>UnhandledExceptionWindow.cs</DependentUpon>
</Compile>
<Compile Include="UI\Forms\UnlockerFormFactory.cs" />
<Compile Include="UI\GraphicsUtilities\GdiPlusGraphicsProvider.cs" />
<Compile Include="UI\GraphicsUtilities\IGraphicsProvider.cs" />
<Compile Include="UI\Menu\HelpMenu.cs">
@@ -798,6 +858,33 @@
<EmbeddedResource Include="UI\Controls\NewPasswordWithVerification.resx">
<DependentUpon>NewPasswordWithVerification.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="UI\Forms\CompositeCredentialRepoUnlockerForm.resx">
<DependentUpon>CompositeCredentialRepoUnlockerForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="UI\Forms\CredentialManagerForm.resx">
<DependentUpon>CredentialManagerForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="UI\Forms\CredentialManagerPages\CredentialEditorPage.resx">
<DependentUpon>CredentialEditorPage.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="UI\Forms\CredentialManagerPages\CredentialListPage.resx">
<DependentUpon>CredentialListPage.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="UI\Forms\CredentialManagerPages\CredentialRepositoriesPage.resx">
<DependentUpon>CredentialRepositoriesPage.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="UI\Forms\CredentialManagerPages\CredentialRepositoryEditorPages\XmlCredentialRepositoryEditorPage.resx">
<DependentUpon>XmlCredentialRepositoryEditorPage.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="UI\Forms\CredentialManagerPages\CredentialRepositorySelectionPage.resx">
<DependentUpon>CredentialRepositorySelectionPage.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="UI\Forms\CredentialManagerPages\CredentialRepositoryTypeSelectionPage.resx">
<DependentUpon>CredentialRepositoryTypeSelectionPage.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="UI\Forms\CredentialManagerUpgradeForm.resx">
<DependentUpon>CredentialManagerUpgradeForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="UI\Forms\FrmChoosePanel.resx">
<DependentUpon>FrmChoosePanel.cs</DependentUpon>
<SubType>Designer</SubType>