Update issue #346

Status: Fixed
I have now added password verification dialogs to all password fields.

git-svn-id: https://duplicati.googlecode.com/svn/trunk@674 59da171f-624f-0410-aa54-27559c288bec
This commit is contained in:
kenneth.skovhede@gmail.com
2011-01-15 15:40:33 +00:00
parent 5d27ff8d6c
commit e2f7c2afac
16 changed files with 805 additions and 30 deletions
+5 -2
View File
@@ -120,7 +120,10 @@ namespace Duplicati.GUI
private void OKBtn_Click(object sender, EventArgs e)
{
foreach(TabPage tab in TabContainer.TabPages)
if (UseCommonPassword.Checked && !CommonPassword.VerifyPasswordIfChanged())
return;
foreach (TabPage tab in TabContainer.TabPages)
if (tab.Tag as Library.Interface.ISettingsControl != null)
{
try
@@ -197,7 +200,7 @@ namespace Duplicati.GUI
TempPath.Text = m_settings.TempPath;
UseCommonPassword.Checked = m_settings.UseCommonPassword;
CommonPassword.Text = m_settings.CommonPassword;
CommonPassword.Text = CommonPassword.InitialPassword = m_settings.CommonPassword;
CommonPassword.AskToEnterNewPassword = !string.IsNullOrEmpty(CommonPassword.Text);
if (EncryptionModule.Items.Count > 0)
@@ -141,6 +141,13 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup
m_hasGeneratedNewPassword = false;
}
if (EnablePassword.Checked && !Password.VerifyPasswordIfChanged())
{
args.Cancel = true;
return;
}
m_settings["Password:SettingsChanged"] = m_settingsChanged;
m_settings["Password:WarnedChanged"] = m_warnedChanged;
m_settings["Password:NewPasswordGenerated"] = m_hasGeneratedNewPassword;
@@ -175,7 +182,7 @@ namespace Duplicati.GUI.Wizard_pages.Add_backup
if (!m_valuesAutoLoaded)
{
EnablePassword.Checked = !string.IsNullOrEmpty(m_wrapper.BackupPassword) || (m_wrapper.PrimayAction == WizardSettingsWrapper.MainAction.Add || m_wrapper.PrimayAction == WizardSettingsWrapper.MainAction.RestoreSetup || m_wrapper.PrimayAction == WizardSettingsWrapper.MainAction.Restore);
Password.Text = m_wrapper.BackupPassword;
Password.Text = Password.InitialPassword = m_wrapper.BackupPassword;
Password.AskToEnterNewPassword = !string.IsNullOrEmpty(m_wrapper.BackupPassword);
@@ -34,7 +34,7 @@ namespace Duplicati.Library.Backend
this.label3 = new System.Windows.Forms.Label();
this.Username = new System.Windows.Forms.TextBox();
this.API_KEY = new Duplicati.Winforms.Controls.PasswordControl();
this.BucketName = new System.Windows.Forms.TextBox();
this.ContainerName = new System.Windows.Forms.TextBox();
this.SignUpLink = new System.Windows.Forms.LinkLabel();
this.label4 = new System.Windows.Forms.Label();
this.TestConnection = new System.Windows.Forms.Button();
@@ -74,9 +74,9 @@ namespace Duplicati.Library.Backend
//
// BucketName
//
resources.ApplyResources(this.BucketName, "BucketName");
this.BucketName.Name = "BucketName";
this.BucketName.TextChanged += new System.EventHandler(this.BucketName_TextChanged);
resources.ApplyResources(this.ContainerName, "BucketName");
this.ContainerName.Name = "BucketName";
this.ContainerName.TextChanged += new System.EventHandler(this.ContainerName_TextChanged);
//
// SignUpLink
//
@@ -112,7 +112,7 @@ namespace Duplicati.Library.Backend
this.Controls.Add(this.TestConnection);
this.Controls.Add(this.label4);
this.Controls.Add(this.SignUpLink);
this.Controls.Add(this.BucketName);
this.Controls.Add(this.ContainerName);
this.Controls.Add(this.API_KEY);
this.Controls.Add(this.Username);
this.Controls.Add(this.label3);
@@ -132,7 +132,7 @@ namespace Duplicati.Library.Backend
private System.Windows.Forms.Label label3;
private System.Windows.Forms.TextBox Username;
private Duplicati.Winforms.Controls.PasswordControl API_KEY;
private System.Windows.Forms.TextBox BucketName;
private System.Windows.Forms.TextBox ContainerName;
private System.Windows.Forms.LinkLabel SignUpLink;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.Button TestConnection;
@@ -33,6 +33,7 @@ namespace Duplicati.Library.Backend
private const string ACCESS_KEY = "Access Key";
private const string CONTAINER_NAME = "Container name";
private const string HASTESTED = "UI: Has tested";
private const string INITIALPASSWORD = "UI: Temp password";
private const string LOGIN_PAGE = "https://www.rackspacecloud.com/signup";
private IDictionary<string, string> m_options;
@@ -74,17 +75,26 @@ namespace Duplicati.Library.Backend
}
Save();
m_options.Remove(INITIALPASSWORD);
return true;
}
private void Save()
{
string initialPwd;
bool hasInitial = m_options.TryGetValue(INITIALPASSWORD, out initialPwd);
m_options.Clear();
m_options[HASTESTED] = m_hasTested.ToString();
m_options[USERNAME] = Username.Text;
m_options[ACCESS_KEY] = API_KEY.Text;
m_options[CONTAINER_NAME] = BucketName.Text;
m_options[CONTAINER_NAME] = ContainerName.Text;
if (hasInitial)
m_options[INITIALPASSWORD] = initialPwd;
}
void CloudFilesUI_Load(object sender, EventArgs args)
@@ -94,9 +104,12 @@ namespace Duplicati.Library.Backend
if (m_options.ContainsKey(ACCESS_KEY))
API_KEY.Text = m_options[ACCESS_KEY];
if (m_options.ContainsKey(CONTAINER_NAME))
BucketName.Text = m_options[CONTAINER_NAME];
ContainerName.Text = m_options[CONTAINER_NAME];
API_KEY.AskToEnterNewPassword = !string.IsNullOrEmpty(API_KEY.Text);
if (!m_options.ContainsKey(INITIALPASSWORD))
m_options[INITIALPASSWORD] = m_options.ContainsKey(ACCESS_KEY) ? m_options[ACCESS_KEY] : "";
API_KEY.AskToEnterNewPassword = !string.IsNullOrEmpty(m_options[INITIALPASSWORD]);
API_KEY.InitialPassword = m_options[INITIALPASSWORD];
if (!m_options.ContainsKey(HASTESTED) || !bool.TryParse(m_options[HASTESTED], out m_hasTested))
m_hasTested = false;
@@ -116,12 +129,15 @@ namespace Duplicati.Library.Backend
return false;
}
if (BucketName.Text.Trim().Length <= 0)
if (ContainerName.Text.Trim().Length <= 0)
{
MessageBox.Show(this, Strings.CloudFilesUI.EmptyContainerNameError, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Information);
return false;
}
if (!API_KEY.VerifyPasswordIfChanged())
return false;
return true;
}
@@ -182,12 +198,7 @@ namespace Duplicati.Library.Backend
m_hasTested = false;
}
private void BucketName_TextChanged(object sender, EventArgs e)
{
m_hasTested = false;
}
private void UseEuroBuckets_CheckedChanged(object sender, EventArgs e)
private void ContainerName_TextChanged(object sender, EventArgs e)
{
m_hasTested = false;
}
+15 -1
View File
@@ -45,6 +45,7 @@ namespace Duplicati.Library.Backend
private const string HASWARNEDPATH = "UI: HasWarnedPath";
private const string HASWARNEDUSERNAME = "UI: HasWarnedUsername";
private const string HASWARNEDPASSWORD = "UI: HasWarnedPassword";
private const string INITIALPASSWORD = "UI: Temp password";
private bool m_warnedPassword = false;
private bool m_warnedUsername = false;
@@ -92,6 +93,8 @@ namespace Duplicati.Library.Backend
SaveSettings();
m_options.Remove(INITIALPASSWORD);
return true;
}
@@ -156,11 +159,17 @@ namespace Duplicati.Library.Backend
}
}
if (Password.Text.Length > 0 && !Password.VerifyPasswordIfChanged())
return false;
return true;
}
private void SaveSettings()
{
string initialPwd;
bool hasInitial = m_options.TryGetValue(INITIALPASSWORD, out initialPwd);
m_options.Clear();
m_options[HASTESTED] = m_hasTested.ToString();
m_options[HASWARNEDPATH] = m_warnedPath.ToString();
@@ -175,6 +184,8 @@ namespace Duplicati.Library.Backend
m_options[USE_SSL] = UseSSL.Checked.ToString();
m_options[ACCEPT_ANY_CERTIFICATE] = AcceptAnyHash.Checked.ToString();
m_options[ACCEPT_SPECIFIC_CERTIFICATE] = AcceptSpecifiedHash.Checked ? SpecifiedHash.Text : "";
if (hasInitial)
m_options[INITIALPASSWORD] = initialPwd;
}
private void LoadSettings()
@@ -188,7 +199,10 @@ namespace Duplicati.Library.Backend
if (m_options.ContainsKey(PASSWORD))
Password.Text = m_options[PASSWORD];
Password.AskToEnterNewPassword = !string.IsNullOrEmpty(Password.Text);
if (!m_options.ContainsKey(INITIALPASSWORD))
m_options[INITIALPASSWORD] = m_options.ContainsKey(PASSWORD) ? m_options[PASSWORD] : "";
Password.AskToEnterNewPassword = !string.IsNullOrEmpty(m_options[INITIALPASSWORD]);
Password.InitialPassword = m_options[INITIALPASSWORD];
bool b;
if (!m_options.ContainsKey(PASSIVE) || !bool.TryParse(m_options[PASSIVE], out b))
+21 -4
View File
@@ -35,6 +35,7 @@ namespace Duplicati.Library.Backend
private const string USERNAME = "Username";
private const string PASSWORD = "Password";
private const string CHECKED_EMPTY = "UI: Checked empty";
private const string INITIALPASSWORD = "UI: Temp password";
private bool m_hasCheckedEmpty = false;
@@ -51,6 +52,9 @@ namespace Duplicati.Library.Backend
internal bool Save(bool validate)
{
string initialPwd;
bool hasInitial = m_options.TryGetValue(INITIALPASSWORD, out initialPwd);
string targetpath;
if (UsePath.Checked)
targetpath = TargetFolder.Text;
@@ -60,10 +64,14 @@ namespace Duplicati.Library.Backend
if (m_hasCheckedEmpty && m_options.ContainsKey(DESTINATION_FOLDER) && targetpath != m_options[DESTINATION_FOLDER])
m_hasCheckedEmpty = false;
m_options.Clear();
m_options[CHECKED_EMPTY] = m_hasCheckedEmpty.ToString();
m_options[DESTINATION_FOLDER] = targetpath;
if (hasInitial)
m_options[INITIALPASSWORD] = initialPwd;
if (UseCredentials.Checked)
{
m_options[USERNAME] = Username.Text;
@@ -76,15 +84,20 @@ namespace Duplicati.Library.Backend
}
if (!validate)
return false;
return false;
if (UseCredentials.Checked)
{
if (!Duplicati.Library.Backend.File.PreAuthenticate(targetpath, Username.Text, Password.Text))
{
MessageBox.Show(this, Strings.FileUI.AuthenticationError, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
if (Password.Text.Length > 0 && !Password.VerifyPasswordIfChanged())
return false;
}
try
{
if (targetpath.Trim().Length == 0)
@@ -144,6 +157,8 @@ namespace Duplicati.Library.Backend
return false;
}
m_options.Remove(INITIALPASSWORD);
return true;
}
@@ -172,14 +187,16 @@ namespace Duplicati.Library.Backend
if (m_options.ContainsKey(DESTINATION_FOLDER))
TargetFolder.Text = m_options[DESTINATION_FOLDER];
UseCredentials.Checked = m_options.ContainsKey(USERNAME) && !string.IsNullOrEmpty(m_options[USERNAME]);
if (m_options.ContainsKey(USERNAME))
Username.Text = m_options[USERNAME];
if (m_options.ContainsKey(PASSWORD))
Password.Text = m_options[PASSWORD];
Password.AskToEnterNewPassword = !string.IsNullOrEmpty(Password.Text);
if (!m_options.ContainsKey(INITIALPASSWORD))
m_options[INITIALPASSWORD] = m_options.ContainsKey(PASSWORD) ? m_options[PASSWORD] : "";
Password.AskToEnterNewPassword = !string.IsNullOrEmpty(m_options[INITIALPASSWORD]);
Password.InitialPassword = m_options[INITIALPASSWORD];
if (!m_options.ContainsKey(CHECKED_EMPTY) || !bool.TryParse(m_options[CHECKED_EMPTY], out m_hasCheckedEmpty))
m_hasCheckedEmpty = false;
+16 -2
View File
@@ -42,6 +42,7 @@ namespace Duplicati.Library.Backend
private const string HASSUGGESTEDPREFIX = "UI: Has suggested prefix";
private const string HASSUGGESTEDLOWERCASE = "UI: Has suggested lowercase";
private const string HASWARNEDINVALIDBUCKETNAME = "UI: Has warned invalid bucket name";
private const string INITIALPASSWORD = "UI: Temp password";
private const string S3_PATH = "s3.amazonaws.com";
@@ -101,11 +102,16 @@ namespace Duplicati.Library.Backend
tmp[AWS_ID.Text] = AWS_KEY.Text;
S3CommonOptions.EncodeAccounts(tmp, m_applicationSettings);
m_options.Remove(INITIALPASSWORD);
return true;
}
private void Save()
{
string initialPwd;
bool hasInitial = m_options.TryGetValue(INITIALPASSWORD, out initialPwd);
m_options.Clear();
m_options[HASTESTED] = m_hasTested.ToString();
m_options[HASCREATEDBUCKET] = m_hasCreatedbucket.ToString();
@@ -131,9 +137,11 @@ namespace Duplicati.Library.Backend
m_options[BUCKET_NAME] = bucketname;
}
bucketname = m_options[BUCKET_NAME];
m_options[SUBDOMAIN] = (bucketname.ToLower() == bucketname && S3.IsValidHostname(bucketname)).ToString();
if (hasInitial)
m_options[INITIALPASSWORD] = initialPwd;
}
void S3UI_Load(object sender, EventArgs args)
@@ -151,7 +159,10 @@ namespace Duplicati.Library.Backend
if (m_options.ContainsKey(PREFIX) && !string.IsNullOrEmpty(m_options[PREFIX]))
BucketName.Text += "/" + m_options[PREFIX];
AWS_KEY.AskToEnterNewPassword = !string.IsNullOrEmpty(AWS_KEY.Text);
if (!m_options.ContainsKey(INITIALPASSWORD))
m_options[INITIALPASSWORD] = m_options.ContainsKey(ACCESS_KEY) ? m_options[ACCESS_KEY] : "";
AWS_KEY.AskToEnterNewPassword = !string.IsNullOrEmpty(m_options[INITIALPASSWORD]);
AWS_KEY.InitialPassword = m_options[INITIALPASSWORD];
bool b;
@@ -313,6 +324,9 @@ namespace Duplicati.Library.Backend
m_hasWarnedInvalidBucketname = true;
}
if (!AWS_KEY.VerifyPasswordIfChanged())
return false;
if (checkForBucket)
return EnsureBucketForMono();
else
+18 -3
View File
@@ -42,6 +42,7 @@ namespace Duplicati.Library.Backend
private const string HAS_WARNED_PATH = "UI: Has warned path";
private const string HAS_TESTED = "UI: Has tested";
private const string HAS_WARNED_NO_SFTP = "UI: Has warned SFTP";
private const string INITIALPASSWORD = "UI: Temp password";
private bool m_warnedPath = false;
private bool m_hasTested = false;
@@ -87,11 +88,18 @@ namespace Duplicati.Library.Backend
}
Save();
m_options.Remove(INITIALPASSWORD);
return true;
}
private void Save()
{
string initialPwd;
bool hasInitial = m_options.TryGetValue(INITIALPASSWORD, out initialPwd);
m_options.Clear();
m_options[HAS_TESTED] = m_hasTested.ToString();
m_options[HAS_WARNED_PATH] = m_warnedPath.ToString();
m_options[HAS_WARNED_NO_SFTP] = m_warnedNoSFTP.ToString();
@@ -105,6 +113,8 @@ namespace Duplicati.Library.Backend
m_options[DEBUG_ENABLED] = GenerateDebugOutput.Checked.ToString();
m_options[USE_UNMANAGED_SSH] = UseUnmanagedSSH.Checked.ToString();
m_options[SSH_KEYFILE] = Keyfile.Text;
if (hasInitial)
m_options[INITIALPASSWORD] = initialPwd;
}
void SSHUI_PageLoad(object sender, EventArgs args)
@@ -140,8 +150,11 @@ namespace Duplicati.Library.Backend
if (m_options.ContainsKey(SSH_KEYFILE))
Keyfile.Text = m_options[SSH_KEYFILE];
Password.AskToEnterNewPassword = !string.IsNullOrEmpty(Password.Text);
if (!m_options.ContainsKey(INITIALPASSWORD))
m_options[INITIALPASSWORD] = m_options.ContainsKey(PASSWORD) ? m_options[PASSWORD] : "";
Password.AskToEnterNewPassword = !string.IsNullOrEmpty(m_options[INITIALPASSWORD]);
Password.InitialPassword = m_options[INITIALPASSWORD];
Port.Value = port;
GenerateDebugOutput.Checked = debug;
UseUnmanagedSSH.Checked = useUnmanaged;
@@ -247,7 +260,6 @@ namespace Duplicati.Library.Backend
catch { }
return false;
}
if (!m_warnedPath && Path.Text.Trim().Length == 0)
@@ -297,6 +309,9 @@ namespace Duplicati.Library.Backend
}
}
if (UsePassword.Checked && !Password.VerifyPasswordIfChanged())
return false;
return true;
}
+18 -1
View File
@@ -48,6 +48,7 @@ namespace Duplicati.Library.Backend
private const string HAS_WARNED_PATH = "UI: Has warned path";
private const string HAS_WARNED_LEADING_SLASH = "UI: Has warned leading slash";
private const string HAS_TESTED = "UI: Has tested";
private const string INITIALPASSWORD = "UI: Temp password";
private bool m_warnedPassword = false;
private bool m_warnedUsername = false;
@@ -95,6 +96,9 @@ namespace Duplicati.Library.Backend
}
Save();
m_options.Remove(INITIALPASSWORD);
return true;
}
@@ -109,7 +113,10 @@ namespace Duplicati.Library.Backend
if (m_options.ContainsKey(PASSWORD))
Password.Text = m_options[PASSWORD];
Password.AskToEnterNewPassword = !string.IsNullOrEmpty(Password.Text);
if (!m_options.ContainsKey(INITIALPASSWORD))
m_options[INITIALPASSWORD] = m_options.ContainsKey(PASSWORD) ? m_options[PASSWORD] : "";
Password.AskToEnterNewPassword = !string.IsNullOrEmpty(m_options[INITIALPASSWORD]);
Password.InitialPassword = m_options[INITIALPASSWORD];
int port;
if (!m_options.ContainsKey(PORT) || !int.TryParse(m_options[PORT], out port))
@@ -229,6 +236,10 @@ namespace Duplicati.Library.Backend
}
m_warnedPassword = true;
}
if (Password.Text.Length > 0 && !Password.VerifyPasswordIfChanged())
return false;
}
if (UseSSL.Checked && AcceptSpecifiedHash.Checked)
@@ -255,6 +266,9 @@ namespace Duplicati.Library.Backend
private void Save()
{
string initialPwd;
bool hasInitial = m_options.TryGetValue(INITIALPASSWORD, out initialPwd);
m_options.Clear();
m_options[HAS_TESTED] = m_hasTested.ToString();
m_options[HAS_WARNED_PATH] = m_warnedPath.ToString();
@@ -281,6 +295,9 @@ namespace Duplicati.Library.Backend
m_options[USE_SSL] = UseSSL.Checked.ToString();
m_options[ACCEPT_ANY_CERTIFICATE] = AcceptAnyHash.Checked.ToString();
m_options[ACCEPT_SPECIFIC_CERTIFICATE] = AcceptSpecifiedHash.Checked ? SpecifiedHash.Text : "";
if (hasInitial)
m_options[INITIALPASSWORD] = initialPwd;
}
private void TestConnection_Click(object sender, EventArgs e)
@@ -56,6 +56,12 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="PasswordConfirmationDialog.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="PasswordConfirmationDialog.Designer.cs">
<DependentUpon>PasswordConfirmationDialog.cs</DependentUpon>
</Compile>
<Compile Include="PasswordControl.cs">
<SubType>UserControl</SubType>
</Compile>
@@ -68,6 +74,11 @@
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Strings\PasswordConfirmationDialog.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>PasswordConfirmationDialog.resx</DependentUpon>
</Compile>
<Compile Include="Strings\PasswordControl.Designer.cs">
<DependentUpon>PasswordControl.resx</DependentUpon>
<AutoGen>True</AutoGen>
@@ -76,6 +87,9 @@
<Service Include="{94E38DFF-614B-4cbd-B67C-F211BB35CE8B}" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="PasswordConfirmationDialog.resx">
<DependentUpon>PasswordConfirmationDialog.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="PasswordControl.resx">
<DependentUpon>PasswordControl.cs</DependentUpon>
</EmbeddedResource>
@@ -83,6 +97,10 @@
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<EmbeddedResource Include="Strings\PasswordConfirmationDialog.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>PasswordConfirmationDialog.Designer.cs</LastGenOutput>
</EmbeddedResource>
<EmbeddedResource Include="Strings\PasswordControl.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>PasswordControl.Designer.cs</LastGenOutput>
@@ -0,0 +1,99 @@
namespace Duplicati.Winforms.Controls
{
partial class PasswordConfirmationDialog
{
/// <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(PasswordConfirmationDialog));
this.label1 = new System.Windows.Forms.Label();
this.Password = new System.Windows.Forms.TextBox();
this.panel1 = new System.Windows.Forms.Panel();
this.OKBtn = new System.Windows.Forms.Button();
this.CancelBtn = new System.Windows.Forms.Button();
this.panel1.SuspendLayout();
this.SuspendLayout();
//
// label1
//
resources.ApplyResources(this.label1, "label1");
this.label1.Name = "label1";
//
// Password
//
resources.ApplyResources(this.Password, "Password");
this.Password.Name = "Password";
this.Password.UseSystemPasswordChar = true;
//
// panel1
//
this.panel1.Controls.Add(this.CancelBtn);
this.panel1.Controls.Add(this.OKBtn);
resources.ApplyResources(this.panel1, "panel1");
this.panel1.Name = "panel1";
//
// OKBtn
//
resources.ApplyResources(this.OKBtn, "OKBtn");
this.OKBtn.Name = "OKBtn";
this.OKBtn.UseVisualStyleBackColor = true;
this.OKBtn.Click += new System.EventHandler(this.OKBtn_Click);
//
// CancelBtn
//
resources.ApplyResources(this.CancelBtn, "CancelBtn");
this.CancelBtn.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.CancelBtn.Name = "CancelBtn";
this.CancelBtn.UseVisualStyleBackColor = true;
//
// PasswordConfirmationDialog
//
this.AcceptButton = this.OKBtn;
resources.ApplyResources(this, "$this");
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.CancelBtn;
this.Controls.Add(this.panel1);
this.Controls.Add(this.Password);
this.Controls.Add(this.label1);
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "PasswordConfirmationDialog";
this.panel1.ResumeLayout(false);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox Password;
private System.Windows.Forms.Panel panel1;
private System.Windows.Forms.Button CancelBtn;
private System.Windows.Forms.Button OKBtn;
}
}
@@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace Duplicati.Winforms.Controls
{
public partial class PasswordConfirmationDialog : Form
{
private string m_previousPassword;
public PasswordConfirmationDialog(string previousPassword)
{
InitializeComponent();
m_previousPassword = previousPassword;
}
private void OKBtn_Click(object sender, EventArgs e)
{
if (m_previousPassword != Password.Text)
{
MessageBox.Show(this, Strings.PasswordConfirmationDialog.PasswordDoNotMatchError, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
else
{
this.DialogResult = DialogResult.OK;
this.Close();
}
}
}
}
@@ -0,0 +1,291 @@
<?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=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="mscorlib" name="mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="label1.AutoSize" type="System.Boolean, mscorlib">
<value>True</value>
</data>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="label1.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
<value>Top</value>
</data>
<assembly alias="System.Drawing" name="System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="label1.Location" type="System.Drawing.Point, System.Drawing">
<value>8, 8</value>
</data>
<data name="label1.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
<value>3, 8, 3, 8</value>
</data>
<data name="label1.Padding" type="System.Windows.Forms.Padding, System.Windows.Forms">
<value>0, 0, 0, 8</value>
</data>
<data name="label1.Size" type="System.Drawing.Size, System.Drawing">
<value>53, 21</value>
</data>
<data name="label1.TabIndex" type="System.Int32, mscorlib">
<value>0</value>
</data>
<data name="label1.Text" xml:space="preserve">
<value>Password</value>
</data>
<data name="&gt;&gt;label1.Name" xml:space="preserve">
<value>label1</value>
</data>
<data name="&gt;&gt;label1.Type" xml:space="preserve">
<value>System.Windows.Forms.Label, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;label1.Parent" xml:space="preserve">
<value>$this</value>
</data>
<data name="&gt;&gt;label1.ZOrder" xml:space="preserve">
<value>2</value>
</data>
<data name="Password.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
<value>Top</value>
</data>
<data name="Password.Location" type="System.Drawing.Point, System.Drawing">
<value>8, 29</value>
</data>
<data name="Password.Margin" type="System.Windows.Forms.Padding, System.Windows.Forms">
<value>3, 0, 3, 0</value>
</data>
<data name="Password.Size" type="System.Drawing.Size, System.Drawing">
<value>309, 20</value>
</data>
<data name="Password.TabIndex" type="System.Int32, mscorlib">
<value>1</value>
</data>
<data name="&gt;&gt;Password.Name" xml:space="preserve">
<value>Password</value>
</data>
<data name="&gt;&gt;Password.Type" xml:space="preserve">
<value>System.Windows.Forms.TextBox, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;Password.Parent" xml:space="preserve">
<value>$this</value>
</data>
<data name="&gt;&gt;Password.ZOrder" xml:space="preserve">
<value>1</value>
</data>
<data name="CancelBtn.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
<value>None</value>
</data>
<data name="CancelBtn.ImeMode" type="System.Windows.Forms.ImeMode, System.Windows.Forms">
<value>NoControl</value>
</data>
<data name="CancelBtn.Location" type="System.Drawing.Point, System.Drawing">
<value>160, 8</value>
</data>
<data name="CancelBtn.Size" type="System.Drawing.Size, System.Drawing">
<value>75, 23</value>
</data>
<data name="CancelBtn.TabIndex" type="System.Int32, mscorlib">
<value>1</value>
</data>
<data name="CancelBtn.Text" xml:space="preserve">
<value>Cancel</value>
</data>
<data name="&gt;&gt;CancelBtn.Name" xml:space="preserve">
<value>CancelBtn</value>
</data>
<data name="&gt;&gt;CancelBtn.Type" xml:space="preserve">
<value>System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;CancelBtn.Parent" xml:space="preserve">
<value>panel1</value>
</data>
<data name="&gt;&gt;CancelBtn.ZOrder" xml:space="preserve">
<value>0</value>
</data>
<data name="OKBtn.Anchor" type="System.Windows.Forms.AnchorStyles, System.Windows.Forms">
<value>None</value>
</data>
<data name="OKBtn.Location" type="System.Drawing.Point, System.Drawing">
<value>72, 8</value>
</data>
<data name="OKBtn.Size" type="System.Drawing.Size, System.Drawing">
<value>75, 23</value>
</data>
<data name="OKBtn.TabIndex" type="System.Int32, mscorlib">
<value>0</value>
</data>
<data name="OKBtn.Text" xml:space="preserve">
<value>OK</value>
</data>
<data name="&gt;&gt;OKBtn.Name" xml:space="preserve">
<value>OKBtn</value>
</data>
<data name="&gt;&gt;OKBtn.Type" xml:space="preserve">
<value>System.Windows.Forms.Button, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;OKBtn.Parent" xml:space="preserve">
<value>panel1</value>
</data>
<data name="&gt;&gt;OKBtn.ZOrder" xml:space="preserve">
<value>1</value>
</data>
<data name="panel1.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
<value>Bottom</value>
</data>
<data name="panel1.Location" type="System.Drawing.Point, System.Drawing">
<value>8, 55</value>
</data>
<data name="panel1.Size" type="System.Drawing.Size, System.Drawing">
<value>309, 37</value>
</data>
<data name="panel1.TabIndex" type="System.Int32, mscorlib">
<value>2</value>
</data>
<data name="&gt;&gt;panel1.Name" xml:space="preserve">
<value>panel1</value>
</data>
<data name="&gt;&gt;panel1.Type" xml:space="preserve">
<value>System.Windows.Forms.Panel, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;panel1.Parent" xml:space="preserve">
<value>$this</value>
</data>
<data name="&gt;&gt;panel1.ZOrder" xml:space="preserve">
<value>0</value>
</data>
<metadata name="$this.Localizable" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
<data name="$this.AutoScaleDimensions" type="System.Drawing.SizeF, System.Drawing">
<value>6, 13</value>
</data>
<data name="$this.ClientSize" type="System.Drawing.Size, System.Drawing">
<value>325, 100</value>
</data>
<data name="$this.Padding" type="System.Windows.Forms.Padding, System.Windows.Forms">
<value>8, 8, 8, 8</value>
</data>
<data name="$this.StartPosition" type="System.Windows.Forms.FormStartPosition, System.Windows.Forms">
<value>CenterParent</value>
</data>
<data name="$this.Text" xml:space="preserve">
<value>Please confirm the password</value>
</data>
<data name="&gt;&gt;$this.Name" xml:space="preserve">
<value>PasswordConfirmationDialog</value>
</data>
<data name="&gt;&gt;$this.Type" xml:space="preserve">
<value>System.Windows.Forms.Form, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
</root>
@@ -31,6 +31,11 @@ namespace Duplicati.Winforms.Controls
/// </summary>
private bool m_askToEnterNewPassword = false;
/// <summary>
/// The original password assigned to the control
/// </summary>
private string m_initialPassword = null;
/// <summary>
/// An event that is raised when the password changed
/// </summary>
@@ -71,6 +76,18 @@ namespace Duplicati.Winforms.Controls
}
}
/// <summary>
/// Gets or sets the initial password, used to check if the password was changed
/// </summary>
public string InitialPassword
{
get { return m_initialPassword; }
set
{
m_initialPassword = value;
}
}
/// <summary>
/// A value that determines if the user can only clear the password,
/// and not reveal the original password
@@ -218,5 +235,26 @@ namespace Duplicati.Winforms.Controls
try { TextBox.Focus(); }
catch { }
}
/// <summary>
/// A helper method that asks the user to verify the password if it was changed and is not show
/// </summary>
/// <returns>True if the password was verified, false otherwise</returns>
public bool VerifyPasswordIfChanged()
{
if (!ShowPassword.Checked && (string.IsNullOrEmpty(m_initialPassword) != string.IsNullOrEmpty(m_password) || m_initialPassword != m_password))
{
PasswordConfirmationDialog dlg = new PasswordConfirmationDialog(m_password);
if (dlg.ShowDialog(this) == DialogResult.OK)
{
m_initialPassword = m_password;
return true;
}
else
return false;
}
else
return true;
}
}
}
@@ -0,0 +1,72 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:2.0.50727.4952
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Duplicati.Winforms.Controls.Strings {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "2.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class PasswordConfirmationDialog {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal PasswordConfirmationDialog() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Duplicati.Winforms.Controls.Strings.PasswordConfirmationDialog", typeof(PasswordConfirmationDialog).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to The password that you have entered does not match the previously entered password.
/// </summary>
internal static string PasswordDoNotMatchError {
get {
return ResourceManager.GetString("PasswordDoNotMatchError", resourceCulture);
}
}
}
}
@@ -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=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="PasswordDoNotMatchError" xml:space="preserve">
<value>The password that you have entered does not match the previously entered password</value>
</data>
</root>