--- a/CryptableMailItem.cs Thu May 10 15:04:25 2018 +0200
+++ b/CryptableMailItem.cs Thu May 17 11:21:56 2018 +0200
@@ -97,12 +97,6 @@
public delegate void OriginallyEncryptedStatusUpdateHandler(object sender, EventArgs e);
public event OriginallyEncryptedStatusUpdateHandler OriginallyEncryptedStatusUpdated;
- /// <summary>
- /// Event handler for when a sync message is being detected during decryption.
- /// </summary>
- public delegate void SyncMessageReceivedHandler(object sender, CryptableMailItem.SyncMessageEventArgs e);
- public static event SyncMessageReceivedHandler SyncMessageReceived;
-
private pEpRating _LastProcessedRating;
private Globals.ReturnStatus _LastProcessedStatus;
@@ -1227,9 +1221,18 @@
// Wait for the other thread to finish
if (isAlreadyBeingDecrypted)
{
- Log.Verbose("ProcessAndGetRating: Waiting for other decryption thread to finish. " + entryId);
- Thread.Sleep(sleepTime);
- curWaitTime += sleepTime;
+ // Do not process multiple times if it is an automatic message
+ if (this.internalMailItem.GetIsAutoConsume())
+ {
+ curWaitTime = maxWaitTime + 1;
+ Log.Verbose("ProcessAndGetRating: Setting timeout for AutoConsume message.");
+ }
+ else
+ {
+ Log.Verbose("ProcessAndGetRating: Waiting for other decryption thread to finish. " + entryId);
+ Thread.Sleep(sleepTime);
+ curWaitTime += sleepTime;
+ }
}
}
while ((isAlreadyBeingDecrypted) && (curWaitTime < maxWaitTime));
@@ -1443,14 +1446,13 @@
// Process mail item
sts1 = PEPMessage.Create(this.internalMailItem, out message);
- // Block while KeySyncWizard is open and Trustwords haven't been accepted
- while ((KeySyncWizard.Wizard?.State == KeySyncWizard.WizardState.Step2) &&
- (message.Direction == pEpMsgDirection.pEpDirIncoming) &&
- (message.To?.Count == 1) &&
- (message.From?.EqualsByAddress(message.To[0]) == true))
+ // If Key Import Wizard is open, add mail to list to process later
+ if ((KeySyncWizard.Wizard?.IsVisible == true) &&
+ (message.Direction == pEpMsgDirection.pEpDirIncoming) &&
+ (message.To?.Count == 1) &&
+ (message.From?.EqualsByAddress(message.To[0]) == true))
{
- Log.Verbose("ProcessAndGetRating: KeySyncWizard in Step 2. Blocking decryption.");
- Thread.Sleep(100);
+ KeySyncWizard.Wizard?.AddToReceivedSyncMessages(message);
}
// Process
@@ -1491,9 +1493,6 @@
}
else
{
- // Check for sync message
- this.CheckForSyncMessage((processedRating == pEpRating.pEpRatingUnencrypted) ? message : processedMessage, decryptionFlags);
-
// Save processed message data to Outlook
if (processedMessage != null)
{
@@ -1839,85 +1838,6 @@
*************************************************************/
/// <summary>
- /// Checks if the key sync wizard is open or the message is a sync message.
- /// If this is true, the message will get processed further, either raising
- /// the respective event or opening the wizard.
- /// </summary>
- /// <param name="message">The message to check.</param>
- /// <param name="flags">The decrypt flags.</param>
- private void CheckForSyncMessage(PEPMessage message, pEpDecryptFlags flags)
- {
- try
- {
- /* To determine whether the processed message is a sync message:
- * 1. Is incoming (do not process sent messages)
- * 2. Has the KeyImport header (in case of pEp sync) and the header is not
- * the own fingerprint.
- * - or -
- * 3. a. The WizardType is PGP
- * b. The message has one To recipient that is also the From recipient
- * c. The From recipient is an own identity (seems actually unnecessary)
- */
- if ((KeySyncWizard.Wizard?.Type == KeySyncWizard.WizardType.PGP) ||
- (message?.KeyImport?.Equals(KeySyncWizard.Wizard?.Myself?.Fingerprint) == false))
- {
- if ((message.To.Count == 1) &&
- (message.To[0].EqualsByAddress(message.From)) &&
- (PEPIdentity.GetIsOwnIdentity(message.From.Address)))
- {
- Log.Verbose("CheckForSyncMessage: Sync message found.");
-
- if ((KeySyncWizard.Wizard?.Type != KeySyncWizard.WizardType.PGP) &&
- (KeySyncWizard.Wizard?.IsVisible == false) &&
- (message.Rating < pEpRating.pEpRatingTrusted))
- {
- Log.Verbose("CheckForSyncMessage: Wizard not open yet.");
-
- // Get own identity
- PEPIdentity myself = null;
- try
- {
- pEpIdentity _myself = message.To[0].ToCOMType();
- myself = new PEPIdentity(ThisAddIn.PEPEngine.Myself(_myself));
- }
- catch (Exception ex)
- {
- myself = null;
- Log.Verbose("CheckForSyncMessage: Error getting own identity. " + ex.ToString());
- }
-
- // Only open if not sent to myself. Check again if not open
- if ((myself?.Fingerprint?.Equals(message?.KeyImport) == false) &&
- (KeySyncWizard.Wizard?.IsVisible == false))
- {
- // Marshall to main thread and create new wizard
- KeySyncWizard.Wizard?.Dispatcher?.Invoke(new Action(() =>
- {
- KeySyncWizard.Wizard = new KeySyncWizard(KeySyncWizard.WizardType.pEp, false, message.To[0], message.KeyImport);
- KeySyncWizard.Wizard.Show();
- Log.Verbose("CheckForSyncMessage: Wizard opened.");
- }));
- }
- }
- else
- {
- Log.Verbose("CheckForSyncMessage: Wizard already open or message rating is trusted. Invoking sync message received event.");
- CryptableMailItem.SyncMessageReceived?.Invoke(this, new SyncMessageEventArgs(message, flags));
- }
- }
- else
- {
- Log.Warning("CheckForSyncMessage: PGP Wizard open or message with KeyImport header, but message doesn't meet formal criteria.");
- }
- }
- }
- catch (Exception ex)
- {
- Log.Error("CheckForSyncMessage: Error detecting if sync message. " + ex.ToString());
- }
- }
-
- /// <summary>
/// Releases all resources and disconnects internal events.
/// The internal mail item will NOT be released -- this is managed externally.
/// </summary>
@@ -2168,27 +2088,6 @@
}
/// <summary>
- /// Class used to store the arguments in the SyncMessageReceived event.
- /// </summary>
- internal class SyncMessageEventArgs : EventArgs
- {
- public PEPMessage Message = null;
- public pEpDecryptFlags Flags = pEpDecryptFlags.pEpDecryptFlagsNone;
-
- /// <summary>
- /// Constructs a new SyncMessageEventArgs with the given arguments.
- /// </summary>
- /// <param name="message">The message that has been received.</param>
- /// <param name="flags">The decryption flags of the received message.</param>
- public SyncMessageEventArgs(PEPMessage message,
- pEpDecryptFlags flags)
- {
- this.Message = message;
- this.Flags = flags;
- }
- }
-
- /// <summary>
/// Class used to store an entry in the encrypted conversation cache.
/// This will identify the original parent encrypted mail item.
/// </summary>
--- a/MsgProcessor.cs Thu May 10 15:04:25 2018 +0200
+++ b/MsgProcessor.cs Thu May 17 11:21:56 2018 +0200
@@ -13,6 +13,12 @@
/// </summary>
internal class MsgProcessor : IDisposable
{
+ /// <summary>
+ /// Event handler for when a sync message is being detected during decryption.
+ /// </summary>
+ public delegate void SyncMessageReceivedHandler(object sender, MsgProcessor.SyncMessageEventArgs e);
+ public static event SyncMessageReceivedHandler SyncMessageReceived;
+
public delegate void ProcessingCompletedHandler(object sender, ProcessingCompletedEventArgs e);
/// <summary>
@@ -114,6 +120,93 @@
*************************************************************/
/// <summary>
+ /// Checks if the key sync wizard is open or the message is a sync message.
+ /// If this is true, the message will get processed further, either raising
+ /// the respective event or opening the wizard.
+ /// </summary>
+ /// <param name="message">The message to check.</param>
+ /// <param name="flags">The decrypt flags.</param>
+ private void CheckForSyncMessage(PEPMessage message, ref pEpDecryptFlags flags)
+ {
+ try
+ {
+ /* To determine whether the processed message is a sync message:
+ * 1. Is incoming (do not process sent messages)
+ * 2. Has the KeyImport header (in case of pEp sync) and the header is not
+ * the own fingerprint.
+ * - or -
+ * 3. a. The WizardType is PGP
+ * b. The message has one To recipient that is also the From recipient
+ * c. The From recipient is an own identity (seems actually unnecessary)
+ */
+ if ((KeySyncWizard.Wizard?.Type == KeySyncWizard.WizardType.PGP) ||
+ (message?.KeyImport?.Equals(KeySyncWizard.Wizard?.Myself?.Fingerprint) == false))
+ {
+ if ((message.To.Count == 1) &&
+ (message.To[0].EqualsByAddress(message.From)) &&
+ (PEPIdentity.GetIsOwnIdentity(message.From.Address)))
+ {
+ Log.Verbose("CheckForSyncMessage: Sync message found.");
+
+ if ((KeySyncWizard.Wizard?.Type != KeySyncWizard.WizardType.PGP) &&
+ (KeySyncWizard.Wizard?.IsVisible == false) &&
+ (message.Rating < pEpRating.pEpRatingTrusted))
+ {
+ Log.Verbose("CheckForSyncMessage: Wizard not open yet.");
+
+ // Get own identity
+ PEPIdentity myself = null;
+ try
+ {
+ pEpIdentity _myself = message.To[0].ToCOMType();
+ myself = new PEPIdentity(ThisAddIn.PEPEngine.Myself(_myself));
+ }
+ catch (Exception ex)
+ {
+ myself = null;
+ Log.Verbose("CheckForSyncMessage: Error getting own identity. " + ex.ToString());
+ }
+
+ // Only open if not sent to myself. Check again if not open
+ if ((myself?.Fingerprint?.Equals(message?.KeyImport) == false) &&
+ (KeySyncWizard.Wizard?.IsVisible == false))
+ {
+ // Marshall to main thread and create new wizard
+ KeySyncWizard.Wizard?.Dispatcher?.Invoke(new Action(() =>
+ {
+ KeySyncWizard.Wizard = new KeySyncWizard(KeySyncWizard.WizardType.pEp, false, message.To[0], message.KeyImport);
+ KeySyncWizard.Wizard.Show();
+ Log.Verbose("CheckForSyncMessage: Wizard opened.");
+ }));
+ }
+ }
+ else
+ {
+ Log.Verbose("CheckForSyncMessage: Wizard already open or message rating is trusted. Invoking sync message received event.");
+ MsgProcessor.SyncMessageReceived?.Invoke(this, new SyncMessageEventArgs(message, flags));
+ }
+
+ // Delete message if necessary
+ if ((KeySyncWizard.Wizard?.Type == KeySyncWizard.WizardType.pEp) &&
+ (string.IsNullOrEmpty(message?.KeyImport) == false) &&
+ (KeySyncWizard.Wizard?.Myself?.Fingerprint?.Equals(message?.KeyImport) == false))
+ {
+ flags = (flags | pEpDecryptFlags.pEpDecryptFlagConsume);
+ }
+ }
+ else
+ {
+ Log.Warning("CheckForSyncMessage: PGP Wizard open or message with KeyImport header, but message doesn't meet formal criteria.");
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ Log.Error("CheckForSyncMessage: Error detecting if sync message. " + ex.ToString());
+ }
+ }
+
+ /// <summary>
/// Starts the processing of the mail item which can result in decryption or encryption of the message.
/// This will also return the latest message rating.
/// </summary>
@@ -493,14 +586,6 @@
Log.Verbose("ProcessSentMessage: Started");
- // Check if we have an extra key for sync messages and add it
- if (string.IsNullOrEmpty(KeySyncWizard.Wizard?.Partner?.Fingerprint) == false)
- {
- List<string> eKeys = extraKeys?.ToList<string>() ?? new List<string>();
- eKeys.Add(KeySyncWizard.Wizard.Partner.Fingerprint);
- extraKeys = eKeys.ToArray<string>();
- }
-
// Force the working message to outgoing direction.
// This protects mostly for outgoing rating calculation which requires it.
// However, if the message is ever incoming direction here, a failure occured elsewhere.
@@ -867,6 +952,19 @@
/// <summary>
/// Decrypts the given pEp message.
+ /// This is a wrapper for special cases where we don't need the actual result.
+ /// </summary>
+ /// <param name="sourceMessage">The message to decrypt.</param>
+ /// <returns>True if decryption was considered successful, otherwise false.</returns>
+ public bool Decrypt(PEPMessage sourceMessage)
+ {
+ PEPMessage outMessage;
+
+ return this.Decrypt(sourceMessage, out outMessage);
+ }
+
+ /// <summary>
+ /// Decrypts the given pEp message.
/// This is a wrapper for special cases where we don't need to take care of
/// rating, key list or flags.
/// </summary>
@@ -974,7 +1072,10 @@
{
destMessage = null;
keyList = new string[0];
- }
+ }
+
+ // Check for sync message
+ this.CheckForSyncMessage((rating == pEpRating.pEpRatingUnencrypted) ? sourceMessage : destMessage, ref flags);
Log.SensitiveData("Decrypt: Complete. " + sourceMessage?.Id);
@@ -1251,5 +1352,26 @@
this.ProcessedStatus = Globals.ReturnStatus.Success;
}
}
+
+ /// <summary>
+ /// Class used to store the arguments in the SyncMessageReceived event.
+ /// </summary>
+ internal class SyncMessageEventArgs : EventArgs
+ {
+ public PEPMessage Message = null;
+ public pEpDecryptFlags Flags = pEpDecryptFlags.pEpDecryptFlagsNone;
+
+ /// <summary>
+ /// Constructs a new SyncMessageEventArgs with the given arguments.
+ /// </summary>
+ /// <param name="message">The message that has been received.</param>
+ /// <param name="flags">The decryption flags of the received message.</param>
+ public SyncMessageEventArgs(PEPMessage message,
+ pEpDecryptFlags flags)
+ {
+ this.Message = message;
+ this.Flags = flags;
+ }
+ }
}
}
--- a/PEPSettings.cs Thu May 10 15:04:25 2018 +0200
+++ b/PEPSettings.cs Thu May 17 11:21:56 2018 +0200
@@ -1846,7 +1846,6 @@
protected bool _IsSyncEnabled;
protected string _SentFolderEntryId;
protected string _SmtpAddress;
- protected string _StoreId;
protected string _Type;
protected string _UserName;
--- a/Properties/Resources.Designer.cs Thu May 10 15:04:25 2018 +0200
+++ b/Properties/Resources.Designer.cs Thu May 17 11:21:56 2018 +0200
@@ -701,6 +701,24 @@
}
/// <summary>
+ /// Looks up a localized string similar to Back.
+ /// </summary>
+ public static string KeySyncWizard_BackButtonText {
+ get {
+ return ResourceManager.GetString("KeySyncWizard_BackButtonText", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to An error occured. Your key could not be imported correctly. Please try again..
+ /// </summary>
+ public static string KeySyncWizard_ErrorExplanationText {
+ get {
+ return ResourceManager.GetString("KeySyncWizard_ErrorExplanationText", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to Error.
/// </summary>
public static string KeySyncWizard_ErrorText {
@@ -710,6 +728,15 @@
}
/// <summary>
+ /// Looks up a localized string similar to Export my private key to the other device.
+ /// </summary>
+ public static string KeySyncWizard_ExportOwnPrivateKey {
+ get {
+ return ResourceManager.GetString("KeySyncWizard_ExportOwnPrivateKey", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to Finish.
/// </summary>
public static string KeySyncWizard_Finish {
@@ -728,6 +755,89 @@
}
/// <summary>
+ /// Looks up a localized string similar to The key import process has been initialized. Please make sure to have the device up and running from which you want to import the key..
+ /// </summary>
+ public static string KeySyncWizard_PEPStep1ExplanationText {
+ get {
+ return ResourceManager.GetString("KeySyncWizard_PEPStep1ExplanationText", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to If you initiated a key import for the following account, please click Start.
+ ///
+ ///If this was not you, please cancel..
+ /// </summary>
+ public static string KeySyncWizard_PEPStep1NonInitiatorExplanationText {
+ get {
+ return ResourceManager.GetString("KeySyncWizard_PEPStep1NonInitiatorExplanationText", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Please compare the following Trustwords with the ones on your other device and confirm if they match..
+ /// </summary>
+ public static string KeySyncWizard_PEPStep2ExplanationText {
+ get {
+ return ResourceManager.GetString("KeySyncWizard_PEPStep2ExplanationText", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Importing key....
+ /// </summary>
+ public static string KeySyncWizard_PEPStep3ExplanationText {
+ get {
+ return ResourceManager.GetString("KeySyncWizard_PEPStep3ExplanationText", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Key import successful!.
+ /// </summary>
+ public static string KeySyncWizard_PEPStep4ExplanationText {
+ get {
+ return ResourceManager.GetString("KeySyncWizard_PEPStep4ExplanationText", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Key successfully exported!.
+ /// </summary>
+ public static string KeySyncWizard_PEPSuccessExport {
+ get {
+ return ResourceManager.GetString("KeySyncWizard_PEPSuccessExport", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Key successfully imported!.
+ /// </summary>
+ public static string KeySyncWizard_PEPSuccessImport {
+ get {
+ return ResourceManager.GetString("KeySyncWizard_PEPSuccessImport", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to The key from your other device will now also be used to decrypt messages..
+ /// </summary>
+ public static string KeySyncWizard_PEPSuccessOtherKeyUsed {
+ get {
+ return ResourceManager.GetString("KeySyncWizard_PEPSuccessOtherKeyUsed", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to The key from your other device will now be used as your default private key..
+ /// </summary>
+ public static string KeySyncWizard_PEPSuccessOtherKeyUsedAsDefault {
+ get {
+ return ResourceManager.GetString("KeySyncWizard_PEPSuccessOtherKeyUsedAsDefault", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to To proceed with the Key Import, please import the attached public p≡p key and reply with a message that:
///
///1. has your public PGP key attached and
@@ -749,98 +859,56 @@
}
/// <summary>
- /// Looks up a localized string similar to The key import process has been initialized. Please make sure to have the device up and running from which you want to import the key..
+ /// Looks up a localized string similar to A message with your public p≡p key has been sent to yourself. Please open this message on your PGP device and import your public p≡p key into your keychain..
/// </summary>
- public static string KeySyncWizard_Step1PEPExplanationText {
+ public static string KeySyncWizard_PGPStep1ExplanationText {
get {
- return ResourceManager.GetString("KeySyncWizard_Step1PEPExplanationText", resourceCulture);
+ return ResourceManager.GetString("KeySyncWizard_PGPStep1ExplanationText", resourceCulture);
}
}
/// <summary>
- /// Looks up a localized string similar to Please import your public p≡p key on your PGP device and reply with a message that:
- ///
- ///1. has your public PGP key attached and
- ///2. is encrypted with the p≡p key you just imported.
+ /// Looks up a localized string similar to In your PGP device, create an answer message to the one you received from p≡p and attach your public PGP key..
/// </summary>
- public static string KeySyncWizard_Step1PGPExplanationText {
+ public static string KeySyncWizard_PGPStep2ExplanationText {
get {
- return ResourceManager.GetString("KeySyncWizard_Step1PGPExplanationText", resourceCulture);
+ return ResourceManager.GetString("KeySyncWizard_PGPStep2ExplanationText", resourceCulture);
}
}
/// <summary>
- /// Looks up a localized string similar to A message with your public key has been sent to yourself..
+ /// Looks up a localized string similar to Encrypt the answer message with the public p≡p key you just imported and send it..
/// </summary>
- public static string KeySyncWizard_Step1PGPSubtitleText {
+ public static string KeySyncWizard_PGPStep3ExplanationText {
get {
- return ResourceManager.GetString("KeySyncWizard_Step1PGPSubtitleText", resourceCulture);
- }
- }
-
- /// <summary>
- /// Looks up a localized string similar to Please compare the following Trustwords with the ones on your other device and confirm if they match..
- /// </summary>
- public static string KeySyncWizard_Step2PEPExplanationText {
- get {
- return ResourceManager.GetString("KeySyncWizard_Step2PEPExplanationText", resourceCulture);
+ return ResourceManager.GetString("KeySyncWizard_PGPStep3ExplanationText", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Please compare the PGP fingerprints of the below keys with the ones on your PGP device and confirm if they match..
/// </summary>
- public static string KeySyncWizard_Step2PGPExplanationText {
+ public static string KeySyncWizard_PGPStep5ExplanationText {
get {
- return ResourceManager.GetString("KeySyncWizard_Step2PGPExplanationText", resourceCulture);
- }
- }
-
- /// <summary>
- /// Looks up a localized string similar to Importing key....
- /// </summary>
- public static string KeySyncWizard_Step3PEPExplanationText {
- get {
- return ResourceManager.GetString("KeySyncWizard_Step3PEPExplanationText", resourceCulture);
+ return ResourceManager.GetString("KeySyncWizard_PGPStep5ExplanationText", resourceCulture);
}
}
/// <summary>
- /// Looks up a localized string similar to Please send now another reply message that:
- ///
- ///1. has your private PGP key attached and
- ///2. is encrypted with the p≡p key you just imported.
+ /// Looks up a localized string similar to In your PGP device, create another answer message to the one you received from p≡p. This time, please attach your private PGP key..
/// </summary>
- public static string KeySyncWizard_Step3PGPExplanationText {
+ public static string KeySyncWizard_PGPStep6ExplanationText {
get {
- return ResourceManager.GetString("KeySyncWizard_Step3PGPExplanationText", resourceCulture);
+ return ResourceManager.GetString("KeySyncWizard_PGPStep6ExplanationText", resourceCulture);
}
}
/// <summary>
- /// Looks up a localized string similar to An error occured. Your key could not be imported correctly. Please try again..
- /// </summary>
- public static string KeySyncWizard_Step4ErrorExplanationText {
- get {
- return ResourceManager.GetString("KeySyncWizard_Step4ErrorExplanationText", resourceCulture);
- }
- }
-
- /// <summary>
- /// Looks up a localized string similar to The key from your other device will now be used as your default private key..
+ /// Looks up a localized string similar to Encrypt the answer message again with the public p≡p key and send it..
/// </summary>
- public static string KeySyncWizard_Step4PEPSuccessInitiatorExplanationText {
+ public static string KeySyncWizard_PGPStep7ExplanationText {
get {
- return ResourceManager.GetString("KeySyncWizard_Step4PEPSuccessInitiatorExplanationText", resourceCulture);
- }
- }
-
- /// <summary>
- /// Looks up a localized string similar to The key from the other device can now be used to decrypt messages..
- /// </summary>
- public static string KeySyncWizard_Step4PEPSuccessNonInitiatorExplanationText {
- get {
- return ResourceManager.GetString("KeySyncWizard_Step4PEPSuccessNonInitiatorExplanationText", resourceCulture);
+ return ResourceManager.GetString("KeySyncWizard_PGPStep7ExplanationText", resourceCulture);
}
}
@@ -849,9 +917,27 @@
///
///Your private PGP key has been successfully imported and will now be used as default p≡p key..
/// </summary>
- public static string KeySyncWizard_Step4SuccessExplanationText {
+ public static string KeySyncWizard_PGPSuccessExplanationText {
+ get {
+ return ResourceManager.GetString("KeySyncWizard_PGPSuccessExplanationText", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Use the imported key as default key.
+ /// </summary>
+ public static string KeySyncWizard_SetImportedKeyAsDefault {
get {
- return ResourceManager.GetString("KeySyncWizard_Step4SuccessExplanationText", resourceCulture);
+ return ResourceManager.GetString("KeySyncWizard_SetImportedKeyAsDefault", resourceCulture);
+ }
+ }
+
+ /// <summary>
+ /// Looks up a localized string similar to Start.
+ /// </summary>
+ public static string KeySyncWizard_Start {
+ get {
+ return ResourceManager.GetString("KeySyncWizard_Start", resourceCulture);
}
}
--- a/Properties/Resources.de.resx Thu May 10 15:04:25 2018 +0200
+++ b/Properties/Resources.de.resx Thu May 17 11:21:56 2018 +0200
@@ -651,7 +651,7 @@
<value>Die Mailgröße überschreitet die zulässige Größenbeschränkung für die Verschlüsselung.</value>
</data>
<data name="Handshake_WrongFingerprint" xml:space="preserve">
- <value>Falscher Fingerprint</value>
+ <value>Falscher Fingerabdruck</value>
</data>
<data name="Handshake_TrustwordsExpanderTooltipFull" xml:space="preserve">
<value>Vollversion der Trustwords anzeigen</value>
@@ -722,22 +722,16 @@
<data name="KeySyncWizard_Finish" xml:space="preserve">
<value>Fertig stellen</value>
</data>
- <data name="KeySyncWizard_Step1PGPExplanationText" xml:space="preserve">
- <value>Bitte importieren Sie Ihren öffentlichen p≡p-Schlüssel auf Ihrem PGP-Gerät und senden Sie eine Antwortnachricht:
-
-1. an die Sie Ihren öffentlichen PGP-Schlüssel anhängen und
-2. die Sie mit dem gerade importierten p≡p-Schlüssel verschlüsseln</value>
+ <data name="KeySyncWizard_PGPStep1ExplanationText" xml:space="preserve">
+ <value>Eine Nachricht mit Ihrem öffentlichen p≡p-Schlüssel wurde an Sie selbst versendet. Bitte öffnen Sie die Nachricht auf Ihrem PGP-Gerät und importieren Sie den Schlüssel in Ihren PGP-Schlüsselring.</value>
</data>
- <data name="KeySyncWizard_Step2PGPExplanationText" xml:space="preserve">
- <value>Bitte vergleichen Sie die PGP-Fingerabdrücke Ihrer beiden Schlüssel mit denjenigen auf Ihrem PGP-Gerät und bestätigen Sie, wenn sie übereinstimmen.</value>
+ <data name="KeySyncWizard_PGPStep2ExplanationText" xml:space="preserve">
+ <value>Erstellen Sie auf Ihrem PGP-Gerät eine Antwortnachricht auf die Nachricht, die Sie von p≡p erhalten haben und hängen Sie Ihren öffentlichen PGP-Schlüssel an.</value>
</data>
- <data name="KeySyncWizard_Step3PGPExplanationText" xml:space="preserve">
- <value>Senden Sie nun bitte eine weitere Antwortnachricht:
-
-1. an die Sie Ihren privaten PGP-Schlüssel anhängen und
-2. die Sie mit dem gerade importierten p≡p-Schlüssel verschlüsseln </value>
+ <data name="KeySyncWizard_PGPStep3ExplanationText" xml:space="preserve">
+ <value>Verschlüsseln Sie die Antwortnachricht mit dem öffentlichen p≡p-Schlüssel, den Sie gerade importiert haben und versenden Sie sie.</value>
</data>
- <data name="KeySyncWizard_Step4SuccessExplanationText" xml:space="preserve">
+ <data name="KeySyncWizard_PGPSuccessExplanationText" xml:space="preserve">
<value>Schlüsselimport erfolgreich
Ihr privater PGP-Schlüssel wurde erfolgreich importiert und wird nun standardmäßig auch als p≡p-Schlüssel verwendet.</value>
@@ -745,23 +739,23 @@
<data name="KeySyncWizard_WindowTitle" xml:space="preserve">
<value>Schlüsselimport</value>
</data>
- <data name="KeySyncWizard_Step1PEPExplanationText" xml:space="preserve">
+ <data name="KeySyncWizard_PEPStep1ExplanationText" xml:space="preserve">
<value>Der Schlüsselimportprozess wurde gestartet. Bitte stellen Sie sicher, dass Ihr anderes Gerät, von dem Sie Ihren Schlüssel importieren möchten, eingeschaltet ist.</value>
</data>
- <data name="KeySyncWizard_Step2PEPExplanationText" xml:space="preserve">
+ <data name="KeySyncWizard_PEPStep2ExplanationText" xml:space="preserve">
<value>Bitte vergleichen Sie die folgenden Trustwords mit denjenigen auf Ihrem anderen Gerät und bestätigen Sie sie, wenn sie übereinstimmen.</value>
</data>
<data name="KeySyncWizard_WaitingForResponseText" xml:space="preserve">
<value>Es wird auf eine Antwort vom anderen Gerät gewartet...</value>
</data>
- <data name="KeySyncWizard_Step4PEPSuccessInitiatorExplanationText" xml:space="preserve">
- <value>Der Schlüssel von Ihrem anderen Gerät wird nun standardmäßig verwendet.</value>
+ <data name="KeySyncWizard_PEPSuccessImport" xml:space="preserve">
+ <value>Schlüsselimport erfolgreich!</value>
</data>
- <data name="KeySyncWizard_Step4ErrorExplanationText" xml:space="preserve">
+ <data name="KeySyncWizard_ErrorExplanationText" xml:space="preserve">
<value>Es ist ein Fehler aufgetreten. Ihr Schlüssel konnte nicht importiert werden. Bitte versuchen Sie es erneut.</value>
</data>
- <data name="KeySyncWizard_Step4PEPSuccessNonInitiatorExplanationText" xml:space="preserve">
- <value>Der Schlüssel des anderen Geräts kann nun zum Entschlüsseln von Nachrichten verwendet werden.</value>
+ <data name="KeySyncWizard_PEPSuccessExport" xml:space="preserve">
+ <value>Schlüsselexport erfolgreich!</value>
</data>
<data name="KeySyncWizard_SuccessText" xml:space="preserve">
<value>Schlüsselimport erfolgreich!</value>
@@ -769,7 +763,7 @@
<data name="KeySyncWizard_ErrorText" xml:space="preserve">
<value>Fehler</value>
</data>
- <data name="KeySyncWizard_Step3PEPExplanationText" xml:space="preserve">
+ <data name="KeySyncWizard_PEPStep3ExplanationText" xml:space="preserve">
<value>Schlüssel wird importiert...</value>
</data>
<data name="StoreContextMenu_OpenPGPKeyImportWizard" xml:space="preserve">
@@ -781,9 +775,6 @@
<data name="StoreContextMenu_KeyImportText" xml:space="preserve">
<value>Schlüsselimport</value>
</data>
- <data name="KeySyncWizard_Step1PGPSubtitleText" xml:space="preserve">
- <value>Eine Nachricht mit Ihrem öffentlichen Schlüssel wurde an Sie selbst versendet.</value>
- </data>
<data name="KeySyncWizard_PGPInitialMessageBody" xml:space="preserve">
<value>Um mit dem Schlüsselimport fortzufahren, importieren Sie bitte den angehängten öffentlichen p≡p-Schlüssel und senden Sie eine Antwortnachricht:
@@ -793,4 +784,39 @@
<data name="KeySyncWizard_PGPInitialMessageSubject" xml:space="preserve">
<value>p≡p-Schlüsselimport</value>
</data>
+ <data name="KeySyncWizard_Start" xml:space="preserve">
+ <value>Start</value>
+ </data>
+ <data name="KeySyncWizard_PEPStep1NonInitiatorExplanationText" xml:space="preserve">
+ <value>Wenn Sie einen Schlüsselimport von einem anderen Gerät gestartet haben, klicken Sie bitte auf Start.
+
+Andernfalls klicken Sie bitte auf Abbrechen.</value>
+ </data>
+ <data name="KeySyncWizard_PGPStep5ExplanationText" xml:space="preserve">
+ <value>Bitte vergleichen Sie die PGP-Fingerabdrücke Ihrer beiden Schlüssel mit denjenigen auf Ihrem PGP-Gerät und bestätigen Sie, wenn sie übereinstimmen.</value>
+ </data>
+ <data name="KeySyncWizard_PGPStep6ExplanationText" xml:space="preserve">
+ <value>Erstellen Sie auf Ihrem PGP-Gerät eine neue Antwortnachricht auf die Nachricht, die Sie von p≡p erhalten haben. Hängen Sie nun bitte Ihren privaten PGP-Schlüssel an.</value>
+ </data>
+ <data name="KeySyncWizard_PGPStep7ExplanationText" xml:space="preserve">
+ <value>Verschlüsseln Sie die Antwortnachricht nun wieder mit dem öffentlichen p≡p-Schlüssel und versenden Sie sie.</value>
+ </data>
+ <data name="KeySyncWizard_BackButtonText" xml:space="preserve">
+ <value>Zurück</value>
+ </data>
+ <data name="KeySyncWizard_PEPStep4ExplanationText" xml:space="preserve">
+ <value>Schlüsselimport erfolgreich!</value>
+ </data>
+ <data name="KeySyncWizard_ExportOwnPrivateKey" xml:space="preserve">
+ <value>Meinen privaten Schlüssel auf das andere Gerät exportieren</value>
+ </data>
+ <data name="KeySyncWizard_SetImportedKeyAsDefault" xml:space="preserve">
+ <value>Den importierten Schlüssel standardmäßig verwenden</value>
+ </data>
+ <data name="KeySyncWizard_PEPSuccessOtherKeyUsed" xml:space="preserve">
+ <value>Der Schlüssel von Ihrem anderen Gerät kann nun ebenfalls zum Entschlüsseln verwendet werden.</value>
+ </data>
+ <data name="KeySyncWizard_PEPSuccessOtherKeyUsedAsDefault" xml:space="preserve">
+ <value>Der Schlüssel von Ihrem anderen Gerät wird nun standardmäßig verwendet.</value>
+ </data>
</root>
\ No newline at end of file
--- a/Properties/Resources.resx Thu May 10 15:04:25 2018 +0200
+++ b/Properties/Resources.resx Thu May 17 11:21:56 2018 +0200
@@ -804,22 +804,16 @@
<data name="KeySyncWizard_Finish" xml:space="preserve">
<value>Finish</value>
</data>
- <data name="KeySyncWizard_Step1PGPExplanationText" xml:space="preserve">
- <value>Please import your public p≡p key on your PGP device and reply with a message that:
-
-1. has your public PGP key attached and
-2. is encrypted with the p≡p key you just imported</value>
+ <data name="KeySyncWizard_PGPStep1ExplanationText" xml:space="preserve">
+ <value>A message with your public p≡p key has been sent to yourself. Please open this message on your PGP device and import your public p≡p key into your keychain.</value>
</data>
- <data name="KeySyncWizard_Step2PGPExplanationText" xml:space="preserve">
- <value>Please compare the PGP fingerprints of the below keys with the ones on your PGP device and confirm if they match.</value>
+ <data name="KeySyncWizard_PGPStep2ExplanationText" xml:space="preserve">
+ <value>In your PGP device, create an answer message to the one you received from p≡p and attach your public PGP key.</value>
</data>
- <data name="KeySyncWizard_Step3PGPExplanationText" xml:space="preserve">
- <value>Please send now another reply message that:
-
-1. has your private PGP key attached and
-2. is encrypted with the p≡p key you just imported</value>
+ <data name="KeySyncWizard_PGPStep3ExplanationText" xml:space="preserve">
+ <value>Encrypt the answer message with the public p≡p key you just imported and send it.</value>
</data>
- <data name="KeySyncWizard_Step4SuccessExplanationText" xml:space="preserve">
+ <data name="KeySyncWizard_PGPSuccessExplanationText" xml:space="preserve">
<value>Key successfully imported
Your private PGP key has been successfully imported and will now be used as default p≡p key.</value>
@@ -827,10 +821,10 @@
<data name="KeySyncWizard_WindowTitle" xml:space="preserve">
<value>Key Import</value>
</data>
- <data name="KeySyncWizard_Step1PEPExplanationText" xml:space="preserve">
+ <data name="KeySyncWizard_PEPStep1ExplanationText" xml:space="preserve">
<value>The key import process has been initialized. Please make sure to have the device up and running from which you want to import the key.</value>
</data>
- <data name="KeySyncWizard_Step2PEPExplanationText" xml:space="preserve">
+ <data name="KeySyncWizard_PEPStep2ExplanationText" xml:space="preserve">
<value>Please compare the following Trustwords with the ones on your other device and confirm if they match.</value>
</data>
<data name="KeySyncWizard_WaitingForResponseText" xml:space="preserve">
@@ -839,14 +833,14 @@
<data name="KeySyncWizard_Next" xml:space="preserve">
<value>Next</value>
</data>
- <data name="KeySyncWizard_Step4PEPSuccessInitiatorExplanationText" xml:space="preserve">
- <value>The key from your other device will now be used as your default private key.</value>
+ <data name="KeySyncWizard_PEPSuccessImport" xml:space="preserve">
+ <value>Key successfully imported!</value>
</data>
- <data name="KeySyncWizard_Step4ErrorExplanationText" xml:space="preserve">
+ <data name="KeySyncWizard_ErrorExplanationText" xml:space="preserve">
<value>An error occured. Your key could not be imported correctly. Please try again.</value>
</data>
- <data name="KeySyncWizard_Step4PEPSuccessNonInitiatorExplanationText" xml:space="preserve">
- <value>The key from the other device can now be used to decrypt messages.</value>
+ <data name="KeySyncWizard_PEPSuccessExport" xml:space="preserve">
+ <value>Key successfully exported!</value>
</data>
<data name="KeySyncWizard_SuccessText" xml:space="preserve">
<value>Key import successful!</value>
@@ -854,7 +848,7 @@
<data name="KeySyncWizard_ErrorText" xml:space="preserve">
<value>Error</value>
</data>
- <data name="KeySyncWizard_Step3PEPExplanationText" xml:space="preserve">
+ <data name="KeySyncWizard_PEPStep3ExplanationText" xml:space="preserve">
<value>Importing key...</value>
</data>
<data name="StoreContextMenu_OpenPGPKeyImportWizard" xml:space="preserve">
@@ -869,9 +863,6 @@
<data name="ImageLogoIcon" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\resources\imagelogoicon.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
- <data name="KeySyncWizard_Step1PGPSubtitleText" xml:space="preserve">
- <value>A message with your public key has been sent to yourself.</value>
- </data>
<data name="KeySyncWizard_PGPInitialMessageBody" xml:space="preserve">
<value>To proceed with the Key Import, please import the attached public p≡p key and reply with a message that:
@@ -881,4 +872,39 @@
<data name="KeySyncWizard_PGPInitialMessageSubject" xml:space="preserve">
<value>p≡p Key Import</value>
</data>
+ <data name="KeySyncWizard_Start" xml:space="preserve">
+ <value>Start</value>
+ </data>
+ <data name="KeySyncWizard_PEPStep1NonInitiatorExplanationText" xml:space="preserve">
+ <value>If you initiated a key import for the following account, please click Start.
+
+If this was not you, please cancel.</value>
+ </data>
+ <data name="KeySyncWizard_PGPStep5ExplanationText" xml:space="preserve">
+ <value>Please compare the PGP fingerprints of the below keys with the ones on your PGP device and confirm if they match.</value>
+ </data>
+ <data name="KeySyncWizard_PGPStep6ExplanationText" xml:space="preserve">
+ <value>In your PGP device, create another answer message to the one you received from p≡p. This time, please attach your private PGP key.</value>
+ </data>
+ <data name="KeySyncWizard_PGPStep7ExplanationText" xml:space="preserve">
+ <value>Encrypt the answer message again with the public p≡p key and send it.</value>
+ </data>
+ <data name="KeySyncWizard_BackButtonText" xml:space="preserve">
+ <value>Back</value>
+ </data>
+ <data name="KeySyncWizard_PEPStep4ExplanationText" xml:space="preserve">
+ <value>Key import successful!</value>
+ </data>
+ <data name="KeySyncWizard_ExportOwnPrivateKey" xml:space="preserve">
+ <value>Export my private key to the other device</value>
+ </data>
+ <data name="KeySyncWizard_SetImportedKeyAsDefault" xml:space="preserve">
+ <value>Use the imported key as default key</value>
+ </data>
+ <data name="KeySyncWizard_PEPSuccessOtherKeyUsedAsDefault" xml:space="preserve">
+ <value>The key from your other device will now be used as your default private key.</value>
+ </data>
+ <data name="KeySyncWizard_PEPSuccessOtherKeyUsed" xml:space="preserve">
+ <value>The key from your other device will now also be used to decrypt messages.</value>
+ </data>
</root>
\ No newline at end of file
--- a/UI/HandshakeDialog.xaml.cs Thu May 10 15:04:25 2018 +0200
+++ b/UI/HandshakeDialog.xaml.cs Thu May 17 11:21:56 2018 +0200
@@ -4,7 +4,6 @@
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
-using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
--- a/UI/HandshakeItemsControl.xaml Thu May 10 15:04:25 2018 +0200
+++ b/UI/HandshakeItemsControl.xaml Thu May 17 11:21:56 2018 +0200
@@ -201,7 +201,8 @@
SelectedValuePath="Key"
SelectedValue="{Binding Path=TrustwordsCulture, Mode=TwoWay}"
IsEnabled="{Binding Path=ActiveTab, Converter={StaticResource IsActiveTabToBool}, ConverterParameter=Trustwords}"
- Foreground="{Binding RelativeSource={RelativeSource Self}, Path=IsEnabled, Converter={StaticResource IsEnabledToColor}}" />
+ Foreground="{Binding RelativeSource={RelativeSource Self}, Path=IsEnabled, Converter={StaticResource IsEnabledToColor}}"
+ Visibility="{Binding Path=Mode, Converter={StaticResource IsNotSyncModeToVisibility}}" />
</StackPanel>
<!-- Trustwords -->
--- a/UI/HandshakeItemsControl.xaml.cs Thu May 10 15:04:25 2018 +0200
+++ b/UI/HandshakeItemsControl.xaml.cs Thu May 17 11:21:56 2018 +0200
@@ -127,5 +127,15 @@
handshakeItem.AreTrustwordsExpanded = ((sender as Expander)?.IsExpanded == true);
}
}
+
+ /// <summary>
+ /// Raises the property changed event, if possible, with the given arguments.
+ /// </summary>
+ /// <param name="propertyName">The name of the property that changed.</param>
+ private void RaisePropertyChangedEvent(string propertyName)
+ {
+ this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+ return;
+ }
}
}
--- a/UI/KeySyncWizard.xaml Thu May 10 15:04:25 2018 +0200
+++ b/UI/KeySyncWizard.xaml Thu May 17 11:21:56 2018 +0200
@@ -23,94 +23,92 @@
<ResourceDictionary>
<!-- Converters -->
<BooleanToVisibilityConverter x:Key="BoolToVisibility" />
- <local:InvertBoolConverter x:Key="InvertBool" />
- <local:ValueConverterGroup x:Key="IsWizardStateToVisibility">
- <local:IsWizardStateConverter />
- <BooleanToVisibilityConverter />
- </local:ValueConverterGroup>
- <local:ValueConverterGroup x:Key="IsNotWizardStateToVisibility">
- <local:IsWizardStateConverter />
+ <local:MultiBooleanToVisibilityConverter x:Key="MultiBooleanToVisibility" />
+ <local:ValueConverterGroup x:Key="IsStringNotNullOrEmptyToVisibility">
+ <local:IsStringEmptyConverter />
<local:InvertBoolConverter />
<BooleanToVisibilityConverter />
</local:ValueConverterGroup>
- <local:ValueConverterGroup x:Key="IsNotWizardStateToBool">
- <local:IsWizardStateConverter />
- <local:InvertBoolConverter />
- </local:ValueConverterGroup>
+ <local:IsWizardTypeConverter x:Key="IsWizardType" />
+
+ <!--Dictionary-->
+ <ResourceDictionary.MergedDictionaries>
+ <ResourceDictionary Source="pack://application:,,,/pEp;component/Resources/Dictionary.xaml" />
+ </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
- <!--The window content-->
- <StackPanel Width="470">
-
- <!--Title section-->
- <Grid Background="White"
- Margin="0">
- <Grid.ColumnDefinitions>
- <ColumnDefinition Width="*" />
- <ColumnDefinition Width="Auto" />
- </Grid.ColumnDefinitions>
- <StackPanel Grid.Column="0">
- <TextBlock Margin="20,10,10,10"
- Text="{Binding Path=TitleText}"
- FontWeight="Bold"
- VerticalAlignment="Center"/>
- <TextBlock Margin="20,10,10,10"
- Text="{Binding Path=SubtitleText}"
- TextWrapping="Wrap"
- VerticalAlignment="Center" />
- </StackPanel>
- <Image Grid.Column="1"
- Stretch="Uniform"
- Height="40"
- VerticalAlignment="Center"
- HorizontalAlignment="Right"
- Margin="20,10"
- Source="pack://application:,,,/pEp;component/Resources/ImageLogoMedium.png">
- </Image>
- </Grid>
-
- <Separator Margin="0,0,0,20"
- Background="LightGray" />
+ <StackPanel Margin="10"
+ Width="470">
<!--Information section-->
- <TextBlock Text="{Binding Path=ExplanationText}"
+ <TextBlock Text="{Binding Path=CurrentState.TitleText}"
TextWrapping="Wrap"
- Margin="20,10" />
+ Margin="5,5,5,15" />
+
+ <!--User name section-->
+ <TextBlock Text="{Binding Path=CurrentState.UserText}"
+ Padding="10"
+ MinHeight="80"
+ Background="White"
+ FontWeight="DemiBold"
+ Visibility="{Binding Path=CurrentState.IsUserTextVisible, Converter={StaticResource BoolToVisibility}}" />
<!--Identities section-->
- <local:HandshakeItemsControl Margin="10,0"
- ItemsSource="{Binding Path=Items}"
- Visibility="{Binding Path=State, Converter={StaticResource IsWizardStateToVisibility}, ConverterParameter=Step2}" />
+ <StackPanel Visibility="{Binding Path=CurrentState.AreTrustwordsVisible, Converter={StaticResource BoolToVisibility}}">
+ <local:HandshakeItemsControl ItemsSource="{Binding Path=Items}" />
+ <StackPanel Orientation="Horizontal"
+ Margin="5,10,5,0"
+ Visibility="{Binding Path=IsInitiator, Converter={StaticResource BoolToVisibility}}">
+ <CheckBox VerticalAlignment="Center"
+ IsChecked="{Binding Path=SetImportedKeyAsDefault}" />
+ <Label Content="{x:Static p:Resources.KeySyncWizard_SetImportedKeyAsDefault}"
+ MouseUp="LabelSetImportedKeyAsDefault_MouseUp"/>
+ </StackPanel>
+ <StackPanel Orientation="Horizontal"
+ Margin="5,0,5,5">
+ <StackPanel.Visibility>
+ <MultiBinding Converter="{StaticResource MultiBooleanToVisibility}">
+ <Binding Path="IsInitiator" />
+ <Binding Path="Type" Converter="{StaticResource IsWizardType}" ConverterParameter="pEp" />
+ </MultiBinding>
+ </StackPanel.Visibility>
+ <CheckBox VerticalAlignment="Center"
+ IsChecked="{Binding Path=ExportPrivateKey}" />
+ <Label Content="{x:Static p:Resources.KeySyncWizard_ExportOwnPrivateKey}"
+ MouseUp="LabelExportPrivateKey_MouseUp"/>
+ </StackPanel>
+ </StackPanel>
- <Separator Margin="10,20,10,0"
- Background="LightGray"/>
+ <!--Subtitle section-->
+ <TextBlock Text="{Binding Path=CurrentState.SubtitleText}"
+ TextWrapping="Wrap"
+ Margin="5,15"
+ Visibility="{Binding Path=CurrentState.SubtitleText, Converter={StaticResource IsStringNotNullOrEmptyToVisibility}}" />
<!--Buttons section-->
- <Grid>
- <Grid.ColumnDefinitions>
- <ColumnDefinition Width="*" />
- <ColumnDefinition Width="Auto" />
- </Grid.ColumnDefinitions>
- <StackPanel Grid.Column="1"
- Margin="10"
- Orientation="Horizontal">
- <Button x:Name="OKNextButton"
- Margin="5"
- Padding="5,2"
- MinWidth="70"
- IsEnabled="{Binding Path=State, Converter={StaticResource IsNotWizardStateToBool}, ConverterParameter=Step1|Step3}"
- Click="OKNextButton_Click"
- Content="{Binding Path=NextButtonText}" />
- <Button x:Name="CancelButton"
- Margin="5"
- Padding="5,2"
- MinWidth="70"
- Click="CancelButton_Click"
- Visibility="{Binding Path=State, Converter={StaticResource IsNotWizardStateToVisibility}, ConverterParameter=Step4}"
- Content="{x:Static p:Resources.Options_CancelText}" />
- </StackPanel>
- </Grid>
+ <StackPanel Margin="0,10"
+ Orientation="Horizontal"
+ HorizontalAlignment="Right">
+ <Button x:Name="BackButton"
+ Style="{StaticResource StyleCancelButton}"
+ Margin="0,5,5,5"
+ Click="BackButton_Click"
+ Content="{x:Static p:Resources.KeySyncWizard_BackButtonText}"
+ Visibility="{Binding Path=CurrentState.IsBackButtonVisible, Converter={StaticResource BoolToVisibility}}" />
+ <Button x:Name="AcceptButton"
+ Style="{StaticResource StyleConfirmButton}"
+ Margin="5"
+ Click="AcceptButton_Click"
+ Content="{Binding Path=CurrentState.AcceptButtonText}"
+ Visibility="{Binding Path=CurrentState.IsAcceptButtonVisible, Converter={StaticResource BoolToVisibility}}" />
+ <Button x:Name="CancelButton"
+ Margin="5,5,0,5"
+ Style="{StaticResource StyleWrongButton}"
+ Click="CancelButton_Click"
+ Content="{Binding Path=CurrentState.CancelButtonText}"
+ Visibility="{Binding Path=CurrentState.IsCancelButtonVisible, Converter={StaticResource BoolToVisibility}}" />
+ </StackPanel>
</StackPanel>
</Window>
--- a/UI/KeySyncWizard.xaml.cs Thu May 10 15:04:25 2018 +0200
+++ b/UI/KeySyncWizard.xaml.cs Thu May 17 11:21:56 2018 +0200
@@ -3,7 +3,10 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
+using System.Threading.Tasks;
using System.Windows;
+using System.Windows.Input;
+using System.Windows.Threading;
using Outlook = Microsoft.Office.Interop.Outlook;
namespace pEp.UI
@@ -16,6 +19,24 @@
Interfaces.IReset
{
/// <summary>
+ /// Defines the step this wizard is currently in.
+ /// </summary>
+ public enum Steps
+ {
+ Undefined,
+ Success,
+ Error,
+ Step1,
+ Step2,
+ Step3,
+ Step4,
+ Step5,
+ Step6,
+ Step7,
+ Step8
+ }
+
+ /// <summary>
/// The message types for sync messages.
/// </summary>
public enum MessageTypes
@@ -37,66 +58,33 @@
}
/// <summary>
- /// Defines the state (step) this wizard is currently in.
- /// </summary>
- public enum WizardState
- {
- /// <summary>
- /// Undefined state. Should never occur.
- /// </summary>
- Undefined,
-
- /// <summary>
- /// First state on the side of the device that initiated
- /// the process. Will send a first message and wait for
- /// an answer message from the other device.
- /// </summary>
- Step1,
-
- /// <summary>
- /// Showing the Trustwords dialog, waiting for user input.
- /// </summary>
- Step2,
-
- /// <summary>
- /// Trustwords are accepted, the private key is being sent.
- /// Waiting for key from other device.
- /// </summary>
- Step3,
-
- /// <summary>
- /// Process has finished (successfully or not).
- /// </summary>
- Step4
- }
-
- /// <summary>
/// Event raised when a property is changed on a component.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
- private string _ExplanationText;
+ private WizardState _CurrentState;
+ private bool _ExportPrivateKey;
+ private bool _IsInitiator;
private ObservableCollection<HandshakeItem> _Items;
private PEPIdentity _Myself;
- private string _NextButtonText;
private PEPIdentity _Partner;
- private WizardState _State;
- private string _SubtitleText;
- private bool _Success;
- private string _TitleText;
+ private Steps _Step;
+ private bool _SetImportedKeyAsDefault;
private WizardType _Type;
- public static KeySyncWizard Wizard = null;
+ private bool privateKeyImported = false;
+ private List<MessageTypes> sentMessages = new List<MessageTypes>();
+ private List<PEPMessage> receivedSyncMessages = new List<PEPMessage>();
+ private List<WizardState> states = new List<WizardState>();
+ private object mutexReceivedSyncMessages = new object();
- private bool isInitiator = false;
- private List<MessageTypes> sentMessages = new List<MessageTypes>();
+ public static KeySyncWizard Wizard = null;
/// <summary>
/// Default constructor
/// </summary>
public KeySyncWizard()
- {
- }
+ { }
/// <summary>
/// Constructor to create a new key sync wizard.
@@ -115,57 +103,25 @@
KeySyncWizard.Wizard.Close();
}
+ // Reset all values
+ this.Reset();
+
// Initialize the window
InitializeComponent();
// Set current wizard
KeySyncWizard.Wizard = this;
- // Reset all values
- this.Reset();
-
// Initialize the wizard
- this.InitializeWizard(type, myself, partnerFpr);
-
- // Set if wizard is the one that has started the sync process
- this.isInitiator = isInitiator;
+ this.InitializeWizard(isInitiator, type, myself, partnerFpr);
// Attach event handler for new sync messages
- CryptableMailItem.SyncMessageReceived += KeySyncWizard_SyncMessageReceived;
-
- // Either send initial or answer message
- if (isInitiator)
- {
- // Send initial message
- this.SendSyncMessage(MessageTypes.InitialMessage);
- }
- else
- {
- try
- {
- // Update own identity
- this.Myself = new PEPIdentity(ThisAddIn.PEPEngine.Myself(this.Myself.ToCOMType()));
+ MsgProcessor.SyncMessageReceived += KeySyncWizard_SyncMessageReceived;
- // Create handshake item
- if (this.CreateHandshakeItem())
- {
- // Send answer message with pub key
- this.SendSyncMessage(MessageTypes.PublicKeyMessage);
-
- // Go to next step
- this.GoToNextStep();
- }
- else
- {
- Log.Error("KeySyncWizard: Error creating handshake item.");
- this.GoToLastStep(false);
- }
- }
- catch (Exception ex)
- {
- Log.Error("KeySyncWizard: Error updating Myself. " + ex.ToString());
- this.GoToLastStep(false);
- }
+ // Send initial message if necessary
+ if (this.IsInitiator)
+ {
+ this.SendSyncMessage(MessageTypes.InitialMessage);
}
}
@@ -177,15 +133,42 @@
*************************************************************/
/// <summary>
- /// Gets or sets the explanatory text in the wizard.
+ /// Gets or sets the Items collection.
/// </summary>
- public string ExplanationText
+ public WizardState CurrentState
{
- get { return this._ExplanationText; }
+ get { return this._CurrentState; }
set
{
- this._ExplanationText = value;
- this.RaisePropertyChangedEvent(nameof(this.ExplanationText));
+ this._CurrentState = value;
+ this.RaisePropertyChangedEvent(nameof(this.CurrentState));
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets whether to export the private key.
+ /// </summary>
+ public bool ExportPrivateKey
+ {
+ get { return this._ExportPrivateKey; }
+ set
+ {
+ this._ExportPrivateKey = value;
+ this.RaisePropertyChangedEvent(nameof(this.ExportPrivateKey));
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets whether this wizard is the one that
+ /// initiated the Key Import process.
+ /// </summary>
+ public bool IsInitiator
+ {
+ get { return this._IsInitiator; }
+ set
+ {
+ this._IsInitiator = value;
+ this.RaisePropertyChangedEvent(nameof(this.IsInitiator));
}
}
@@ -216,19 +199,6 @@
}
/// <summary>
- /// Gets or sets the Next/Finish button's text.
- /// </summary>
- public string NextButtonText
- {
- get { return this._NextButtonText; }
- set
- {
- this._NextButtonText = value;
- this.RaisePropertyChangedEvent(nameof(this.NextButtonText));
- }
- }
-
- /// <summary>
/// Gets or sets the sync partner.
/// </summary>
public PEPIdentity Partner
@@ -242,56 +212,35 @@
}
/// <summary>
- /// Gets or sets the wizard state.
+ /// Gets or sets the current wizard step.
/// </summary>
- public WizardState State
+ public Steps Step
{
- get { return this._State; }
+ get { return this._Step; }
set
{
- this._State = value;
- this.RaisePropertyChangedEvent(nameof(this.State));
+ this._Step = value;
+ this.RaisePropertyChangedEvent(nameof(this.Step));
}
}
/// <summary>
- /// Gets or sets the subtitle text in the wizard.
+ /// Gets or sets whether to use the imported key as default key.
/// </summary>
- public string SubtitleText
+ public bool SetImportedKeyAsDefault
{
- get { return this._SubtitleText; }
+ get { return this._SetImportedKeyAsDefault; }
set
{
- this._SubtitleText = value;
- this.RaisePropertyChangedEvent(nameof(this.SubtitleText));
+ this._SetImportedKeyAsDefault = value;
+ this.RaisePropertyChangedEvent(nameof(this.SetImportedKeyAsDefault));
}
}
/// <summary>
/// Gets or sets the success state.
/// </summary>
- public bool Success
- {
- get { return this._Success; }
- set
- {
- this._Success = value;
- this.RaisePropertyChangedEvent(nameof(this.Success));
- }
- }
- /// <summary>
- /// Gets or sets the title text in the wizard.
- /// </summary>
- public string TitleText
- {
- get { return this._TitleText; }
- set
- {
- this._TitleText = value;
- this.RaisePropertyChangedEvent(nameof(this.TitleText));
- }
- }
/// <summary>
/// Gets or sets the wizard type.
@@ -306,6 +255,35 @@
}
}
+ /// <summary>
+ /// Gets the user name to display in the dialog.
+ /// </summary>
+ public string UserName
+ {
+ get
+ {
+ string userName = string.Empty;
+
+ // Try to get user name in format "name (address)"
+ if (string.IsNullOrEmpty(this.Myself?.UserName) == false)
+ {
+ userName = this.Myself.UserName;
+
+ if (string.IsNullOrEmpty(this.Myself?.Address) == false)
+ {
+ userName += " (" + this.Myself.Address + ")";
+ }
+ }
+ // If we have no user name, just display address
+ else if (string.IsNullOrEmpty(this.Myself?.Address) == false)
+ {
+ userName = this.Myself.Address;
+ }
+
+ return userName;
+ }
+ }
+
#endregion
#region Event handlers
@@ -315,39 +293,195 @@
*
*************************************************************/
+ /// <summary>
+ /// Event handler for when the OK/Next button is clicked.
+ /// </summary>
+ private void AcceptButton_Click(object sender, RoutedEventArgs e)
+ {
+ this.CurrentState.AcceptButtonClick();
+ }
+
+ /// <summary>
+ /// Event handler for when the Back button is clicked.
+ /// </summary>
+ private void BackButton_Click(object sender, RoutedEventArgs e)
+ {
+ this.CurrentState.BackButtonClick();
+ }
+
+ /// <summary>
+ /// Event handler for when the Cancel button is clicked.
+ /// </summary>
private void CancelButton_Click(object sender, RoutedEventArgs e)
{
- this.Close();
+ this.CurrentState.CancelButtonClick();
}
- private void OKNextButton_Click(object sender, RoutedEventArgs e)
+ /// <summary>
+ /// Event handler for when a sync message arrives while the wizard is open and in progress.
+ /// </summary>
+ private void KeySyncWizard_SyncMessageReceived(object sender, MsgProcessor.SyncMessageEventArgs e)
{
- // Navigation logic
- switch (this.State)
+ // Ignore outgoing messages
+ if (e.Message?.Direction == pEpMsgDirection.pEpDirIncoming)
{
- case WizardState.Step2:
+ try
+ {
+ // Waiting for message with public key from other device
+ if (((this.Type == WizardType.pEp) && (this.Step == Steps.Step1)) ||
+ ((this.Type == WizardType.PGP) && (this.Step == Steps.Step4)))
{
- // User accepts the fingerprint. Make channel green.
- this.TrustKey();
+ string partnerFpr = null;
+
+ // Make sure the channel is not already trusted (either attack or re-processing)
+ if (e.Message?.Rating >= pEpRating.pEpRatingTrusted)
+ {
+ Log.Warning("KeySyncWizard_SyncMessageReceived: Sync message for already trusted channel received.");
+ return;
+ }
+
+ // In case of pEp sync, use header
+ if (this.Type == WizardType.pEp)
+ {
+ // Public key message received. Show trustwords.
+ partnerFpr = e.Message?.KeyImport;
+
+ Log.Verbose("KeySyncWizard_SyncMessageReceived: pEp import, partner fingerprint is " + partnerFpr);
+
+ // Doublecheck that it's not the own key
+ if (this.Myself?.Fingerprint?.Equals(partnerFpr) == true)
+ {
+ partnerFpr = null;
+ }
+ }
+ else if (this.Type == WizardType.PGP)
+ {
+ // In case of PGP import, use key list
+ string[] keys = e.Message?.KeyList?.Split(',');
+ for (int i = 0; i < keys?.Length; i++)
+ {
+ if (keys[i]?.Equals(this.Myself?.Fingerprint) == false)
+ {
+ partnerFpr = keys[i];
+ Log.Verbose("KeySyncWizard_SyncMessageReceived: PGP import, partner fingerprint is " + partnerFpr ?? "null");
+ break;
+ }
+ }
+ }
+ else
+ {
+ Log.Error("KeySyncWizard_SyncMessageReceived: WizardType unknown.");
+ }
+
+ // If we have a valid fingerprint, show Trustwords
+ if ((this.IsInitiator) &&
+ (string.IsNullOrEmpty(partnerFpr) == false))
+ {
+ // Set the partner's fingerprint
+ this.Partner.Fingerprint = partnerFpr;
+
+ // Marshall to main thread
+ this.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
+ {
+ // Create the handshake item
+ if (this.CreateHandshakeItem())
+ {
+ this.GoToNextStep();
+ }
+ else
+ {
+ Log.Error("KeySyncWizard_SyncMessageReceived: Error creating handshake item.");
+ this.GoToLastStep(false);
+ }
+ }));
+ }
+ else
+ {
+ Log.Error("KeySyncWizard_SyncMessageReceived: Partner fingerprint is null.");
+ }
}
- break;
- /* 'Step 1' and 'Step 3' are not clickable.
- * 'Step 4' finishes the process.
- * 'Undefined' means an error occured.
- */
- case WizardState.Step1:
- case WizardState.Step3:
- case WizardState.Step4:
- case WizardState.Undefined:
- default:
+ // Waiting for private key message
+ else if (((this.Type == WizardType.pEp) && (this.Step == Steps.Step3)) ||
+ ((this.Type == WizardType.PGP) && (this.Step == Steps.Step8)))
{
- this.Close();
+ /* Finish the process under the following conditions:
+ * 1. PGP key import + own private key flag
+ * 2. pEp key import +
+ * a. initiator wizard + own private key flag + partner fpr in key import header
+ * b. not initiator wizard + trusted message + partner fpr in key import header
+ */
+ bool hasDecryptFlagOwnPrivateKey = e.Flags.HasFlag(pEpDecryptFlags.pEpDecryptFlagOwnPrivateKey);
+ if (((this.Type == WizardType.PGP) && (hasDecryptFlagOwnPrivateKey)) ||
+ ((this.IsInitiator) && (e.Message.KeyImport?.Equals(this.Partner?.Fingerprint) == true) && (hasDecryptFlagOwnPrivateKey)) ||
+ ((this.IsInitiator == false) && (e.Message.KeyImport?.Equals(this.Partner?.Fingerprint) == true) && (e.Message.Rating >= pEpRating.pEpRatingTrusted)))
+ {
+ // Set flag
+ this.privateKeyImported = hasDecryptFlagOwnPrivateKey;
+
+ // Marshall to main thread
+ this.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
+ {
+ // Set private key as default if needed
+ bool success = false;
+ if ((this.IsInitiator) &&
+ (this.SetImportedKeyAsDefault))
+ {
+ try
+ {
+ pEpIdentity partner = this.Partner.ToCOMType();
+ ThisAddIn.PEPEngine.SetOwnKey(partner, partner.fpr);
+ success = true;
+ }
+ catch (Exception ex)
+ {
+ success = false;
+ Log.Error("AcceptButtonClick: Error setting own key. " + ex.ToString());
+ }
+ }
+ else
+ {
+ success = true;
+ }
+
+ this.GoToLastStep(success);
+
+ }));
+ }
+ else
+ {
+ Log.Verbose("KeySyncWizard_SyncMessageReceived: Message not processed. Steps: Step 3. Own private key flag is " +
+ e.Flags.HasFlag(pEpDecryptFlags.pEpDecryptFlagOwnPrivateKey).ToString() + ". Rating is " +
+ Enum.GetName(typeof(pEpRating), e.Message?.Rating ?? pEpRating.pEpRatingUndefined) + ". KeyImport is " +
+ e.Message?.KeyImport ?? "null");
+ }
}
- break;
+ }
+ catch (Exception ex)
+ {
+ Log.Error("KeySyncWizard_SyncMessageReceived: Error processing sync message. " + ex.ToString());
+ }
}
}
/// <summary>
+ /// Event handler for when the label next to the Export Private Key checkbox
+ /// is clicked.
+ /// </summary>
+ private void LabelExportPrivateKey_MouseUp(object sender, MouseButtonEventArgs e)
+ {
+ this.ExportPrivateKey = (this.ExportPrivateKey == false);
+ }
+
+ /// <summary>
+ /// Event handler for when the label next to the Set Imported Key As Default checkbox
+ /// is clicked.
+ /// </summary>
+ private void LabelSetImportedKeyAsDefault_MouseUp(object sender, MouseButtonEventArgs e)
+ {
+ this.SetImportedKeyAsDefault = (this.SetImportedKeyAsDefault == false);
+ }
+
+ /// <summary>
/// Raises the property changed event, if possible, with the given arguments.
/// </summary>
/// <param name="propertyName">The name of the property that changed.</param>
@@ -358,127 +492,40 @@
}
/// <summary>
- /// Event handler for when a sync message arrives while the wizard is open and in progress.
+ /// Shows the handshake window
/// </summary>
- private void KeySyncWizard_SyncMessageReceived(object sender, CryptableMailItem.SyncMessageEventArgs e)
+ private bool ShowHandshake()
{
- // Ignore outgoing messages
- if (e.Message?.Direction == pEpMsgDirection.pEpDirIncoming)
- {
- try
- {
- switch (this.State)
- {
- // Step 1: get partner fingerprint and show Trustwords
- case WizardState.Step1:
- {
- string partnerFpr = null;
-
- // Make sure the channel is not already trusted (either attack or re-processing)
- if (e.Message?.Rating >= pEpRating.pEpRatingTrusted)
- {
- Log.Warning("KeySyncWizard_SyncMessageReceived: Sync message for already trusted channel received.");
- return;
- }
-
- // In case of pEp sync, use header
- if (this.Type == WizardType.pEp)
- {
- // Public key message received. Show trustwords.
- partnerFpr = e.Message?.KeyImport;
-
- Log.Verbose("KeySyncWizard_SyncMessageReceived: pEp import, partner fingerprint is " + partnerFpr);
-
- // Doublecheck that it's not the own key
- if (this.Myself?.Fingerprint?.Equals(partnerFpr) == true)
- {
- partnerFpr = null;
- }
- }
- else if (this.Type == WizardType.PGP)
- {
- // In case of PGP import, use key list
- string[] keys = e.Message?.KeyList?.Split(',');
- for (int i = 0; i < keys?.Length; i++)
- {
- if (keys[i]?.Equals(this.Myself?.Fingerprint) == false)
- {
- partnerFpr = keys[i];
- Log.Verbose("KeySyncWizard_SyncMessageReceived: PGP import, partner fingerprint is " + partnerFpr ?? "null");
- break;
- }
- }
- }
- else
- {
- Log.Error("KeySyncWizard_SyncMessageReceived: WizardType unknown.");
- }
+ bool success = false;
- // If we have a valid fingerprint, show Trustwords
- if (string.IsNullOrEmpty(partnerFpr) == false)
- {
- // Set the partner's fingerprint
- this.Partner.Fingerprint = partnerFpr;
+ try
+ {
+ // Update own identity if necessary
+ if (string.IsNullOrEmpty(this.Myself?.Fingerprint))
+ {
+ this.Myself = new PEPIdentity(ThisAddIn.PEPEngine.Myself(this.Myself.ToCOMType()));
+ }
- // Marshall to main thread
- this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(() =>
- {
- // Create the handshake item
- if (this.CreateHandshakeItem())
- {
- this.GoToNextStep();
- }
- else
- {
- Log.Error("KeySyncWizard_SyncMessageReceived: Error creating handshake item.");
- this.GoToLastStep(false);
- }
- }));
- }
- else
- {
- Log.Error("KeySyncWizard_SyncMessageReceived: Partner fingerprint is null.");
- }
- }
- break;
- case WizardState.Step2:
- {
- Log.Verbose("KeySyncWizard_SyncMessageReceived: Nothing done. WizardState is Step 2.");
- }
- break;
- case WizardState.Step3:
- {
- /* Finish the process if a private key has been imported and the message
- * is at least trusted.
- * For pEp key import, check also that we don't import our own key.
- */
- if ((e.Flags.HasFlag(pEpDecryptFlags.pEpDecryptFlagOwnPrivateKey)) &&
- (e.Message.Rating >= pEpRating.pEpRatingTrusted) &&
- ((e.Message.KeyImport?.Equals(this.Partner?.Fingerprint) == true) ||
- (this.Type == WizardType.PGP)))
- {
- this.CompleteWizard();
- }
- else
- {
- Log.Verbose("KeySyncWizard_SyncMessageReceived: Message not processed. WizardState: Step 3. Own private key flag is " +
- e.Flags.HasFlag(pEpDecryptFlags.pEpDecryptFlagOwnPrivateKey).ToString() + ". Rating is " +
- Enum.GetName(typeof(pEpRating), e.Message?.Rating ?? pEpRating.pEpRatingUndefined) + ". KeyImport is " +
- e.Message?.KeyImport ?? "null");
- }
- }
- break;
- case WizardState.Step4:
- case WizardState.Undefined:
- default:
- break;
- }
+ // Create handshake item
+ if (this.CreateHandshakeItem())
+ {
+ // Set success flag
+ success = true;
+
+ // Send answer message with pub key
+ this.SendSyncMessage(MessageTypes.PublicKeyMessage);
}
- catch (Exception ex)
+ else
{
- Log.Error("KeySyncWizard_SyncMessageReceived: Error processing sync message. " + ex.ToString());
+ Log.Error("KeySyncWizard: Error creating handshake item.");
}
}
+ catch (Exception ex)
+ {
+ Log.Error("KeySyncWizard: Error updating Myself. " + ex.ToString());
+ }
+
+ return success;
}
/// <summary>
@@ -487,7 +534,7 @@
private void Window_Closed(object sender, EventArgs e)
{
// Remove event handler
- CryptableMailItem.SyncMessageReceived += KeySyncWizard_SyncMessageReceived;
+ MsgProcessor.SyncMessageReceived += KeySyncWizard_SyncMessageReceived;
// Reset static references
KeySyncWizard.Wizard = new KeySyncWizard();
@@ -503,18 +550,69 @@
*************************************************************/
/// <summary>
+ /// Adds the given PEPMessage to the list of received sync messages.
+ /// </summary>
+ /// <param name="message">The PEPMessage to add to the list.</param>
+ public void AddToReceivedSyncMessages(PEPMessage message)
+ {
+ /* Add message to list if:
+ * 1. a. WizardType is PGP and message is secure
+ * b. WizardType is pEp, the current step is Step 2 and the
+ * message hasn't been sent from myself
+ * 2. Message is not in the list yet
+ */
+ lock (mutexReceivedSyncMessages)
+ {
+ if (((this.Type == WizardType.PGP) &&
+ (message.IsSecure) ||
+ ((this.Type == WizardType.pEp) &&
+ (this.Step == Steps.Step2) &&
+ (this.Myself?.Fingerprint?.Equals(message?.KeyImport) == false))) &&
+ (this.receivedSyncMessages?.Find(a => (a.Id?.Equals(message.Id) == true)) == null))
+ {
+ this.receivedSyncMessages?.Add(message);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Closes the wizard and resets the partner identity in the management.db.
+ /// </summary>
+ private void CancelWizard()
+ {
+ try
+ {
+ pEpIdentity partner = this.Partner.Copy().ToCOMType();
+
+ if (string.IsNullOrEmpty(partner.fpr) == false)
+ {
+ Task.Factory.StartNew(new Action(() =>
+ {
+ ThisAddIn.PEPEngine.KeyResetTrust(partner);
+ }), TaskCreationOptions.LongRunning);
+ }
+ }
+ catch (Exception ex)
+ {
+ Log.Error("CancelWizard: Error resetting identity. " + ex.ToString());
+ }
+
+ this.Close();
+ }
+
+ /// <summary>
/// Completes the process and moves wizard to last step.
/// Sets the imported private key as own key, if needed.
/// </summary>
private void CompleteWizard()
{
// Marshall to main thread
- this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new Action(() =>
+ this.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(() =>
{
bool success = false;
// Private key message received. Set key as default if needed.
- if (this.isInitiator)
+ if (this.IsInitiator)
{
try
{
@@ -550,9 +648,10 @@
HandshakeItem item;
if (HandshakeItem.Create(this.Myself, this.Partner, false, out item) == Globals.ReturnStatus.Success)
{
- item.AreTabControlsVisible = (this.Type == WizardType.PGP);
+ item.AreTabControlsVisible = false;
item.ActiveTab = (this.Type == WizardType.pEp) ? HandshakeItem.Tabs.Trustwords : HandshakeItem.Tabs.Fingerprint;
item.AreHandshakeButtonsVisible = false;
+ item.Mode = HandshakeItem.HandshakeMode.Sync;
this.Items.Add(item);
success = true;
@@ -563,17 +662,658 @@
}
/// <summary>
+ /// Creates a list of wizard states that serve as model for the wizard.
+ /// The pEp Key Import process consists of the following steps:
+ /// Step 1:
+ /// a. Is initiator(user opened wizard): Info message that sync message has been sent.
+ /// Waiting for answer message from other device.
+ /// b. Is not initiator (wizard opened through sync message): Info message that key import has been started.
+ /// Waiting for user decision to continue or abort.
+ /// Step 2:
+ /// - Show trustwords. User interaction: confirm or cancel.
+ /// Step 3:
+ /// - Private keys have been sent. Waiting for answer message from other device.
+ /// Step 4:
+ /// - Only on initiator side: Ask user if they want to set imported key as default. Next or Cancel.
+ /// Success:
+ /// - Key Import successfully finished.
+ /// Error:
+ /// - An error occured during the Key Import process.
+ /// </summary>
+ /// <returns>The list of wizard states.</returns>
+ private List<WizardState> CreatePEPWizardStates()
+ {
+ List<WizardState> states = new List<WizardState>();
+
+ try
+ {
+ // Step 1
+ states.Add(new WizardState
+ {
+ // Step
+ Step = Steps.Step1,
+
+ // Title text
+ TitleText = this.IsInitiator ? Properties.Resources.KeySyncWizard_PEPStep1ExplanationText : Properties.Resources.KeySyncWizard_PEPStep1NonInitiatorExplanationText,
+
+ // Central area
+ AreTrustwordsVisible = false,
+ IsUserTextVisible = true,
+ UserText = this.UserName,
+
+ // Back button
+ IsBackButtonVisible = false,
+
+ // Accept button
+ AcceptButtonText = Properties.Resources.KeySyncWizard_Start,
+ IsAcceptButtonVisible = (this.IsInitiator == false),
+ AcceptButtonClick = new Action(() =>
+ {
+ if (this.ShowHandshake())
+ {
+ this.GoToNextStep();
+ }
+ else
+ {
+ this.GoToLastStep(false);
+ }
+ }),
+
+ // Cancel button
+ CancelButtonText = Properties.Resources.Options_CancelText,
+ IsCancelButtonVisible = true,
+ CancelButtonClick = new Action(() =>
+ {
+ this.CancelWizard();
+ }),
+
+ // Subtitle area
+ SubtitleText = this.IsInitiator ? Properties.Resources.KeySyncWizard_WaitingForResponseText : null
+ });
+
+ // Step 2
+ states.Add(new WizardState
+ {
+ // Step
+ Step = Steps.Step2,
+
+ // Title text
+ TitleText = Properties.Resources.KeySyncWizard_PEPStep2ExplanationText,
+
+ // Central area
+ AreTrustwordsVisible = true,
+ IsUserTextVisible = false,
+
+ // Back button
+ IsBackButtonVisible = false,
+
+ // Accept button
+ AcceptButtonText = Properties.Resources.Handshake_ConfirmTrustwords,
+ IsAcceptButtonVisible = true,
+ AcceptButtonClick = new Action(() =>
+ {
+ this.GoToNextStep();
+ this.TrustKey();
+ }),
+
+ // Cancel button
+ CancelButtonText = Properties.Resources.Handshake_WrongTrustwords,
+ IsCancelButtonVisible = true,
+ CancelButtonClick = new Action(() =>
+ {
+ this.CancelWizard();
+ }),
+
+ // Subtitle area
+ SubtitleText = null
+ });
+
+ // Step 3
+ states.Add(new WizardState
+ {
+ // Step
+ Step = Steps.Step3,
+
+ // Title text
+ TitleText = Properties.Resources.KeySyncWizard_PEPStep3ExplanationText,
+
+ // Central area
+ AreTrustwordsVisible = false,
+ IsUserTextVisible = true,
+ UserText = this.UserName,
+
+ // Back button
+ IsBackButtonVisible = false,
+
+ // Accept button
+ IsAcceptButtonVisible = false,
+
+ // Cancel button
+ CancelButtonText = Properties.Resources.Options_CancelText,
+ IsCancelButtonVisible = true,
+ CancelButtonClick = new Action(() =>
+ {
+ this.CancelWizard();
+ }),
+
+ // Subtitle area
+ SubtitleText = Properties.Resources.KeySyncWizard_WaitingForResponseText
+ });
+
+ // Success
+ states.Add(new WizardState
+ {
+ // Step
+ Step = Steps.Success,
+
+ // Title text
+ TitleText = null,
+
+ // Central area
+ AreTrustwordsVisible = false,
+ IsUserTextVisible = true,
+ UserText = this.UserName,
+
+ // Back button
+ IsBackButtonVisible = false,
+
+ // Accept button
+ AcceptButtonText = Properties.Resources.KeySyncWizard_Finish,
+ IsAcceptButtonVisible = true,
+ AcceptButtonClick = new Action(() =>
+ {
+ this.Close();
+ }),
+
+ // Cancel button
+ IsCancelButtonVisible = false,
+
+ // Subtitle area
+ SubtitleText = null
+ });
+
+ // Error
+ states.Add(new WizardState
+ {
+ // Step
+ Step = Steps.Error,
+
+ // Title text
+ TitleText = Properties.Resources.KeySyncWizard_ErrorExplanationText,
+
+ // Central area
+ AreTrustwordsVisible = false,
+ IsUserTextVisible = true,
+ UserText = this.UserName,
+
+ // Back button
+ IsBackButtonVisible = false,
+
+ // Accept button
+ AcceptButtonText = Properties.Resources.KeySyncWizard_Finish,
+ IsAcceptButtonVisible = true,
+ AcceptButtonClick = new Action(() =>
+ {
+ this.CancelWizard();
+ }),
+
+ // Cancel button
+ IsCancelButtonVisible = false,
+
+ // Subtitle area
+ SubtitleText = null
+ });
+ }
+ catch (Exception ex)
+ {
+ states = null;
+ Log.Error("CreateWizardStates: Error creating wizard states. " + ex.ToString());
+ }
+
+ return states;
+ }
+
+ /// <summary>
+ /// Creates a list of wizard states that serve as model for the wizard.
+ /// The PGP Key Import process consists of the following steps:
+ /// Steps 1-3:
+ /// - Instructions on how to prepare the answer message with pub key.
+ /// Step 4:
+ /// - Waiting for answer message from other device.
+ /// Step 5:
+ /// - Show fingerprints. Confirm or deny them.
+ /// Step 6 - 7:
+ /// - Instructions on how to prepare the answer message with private key.
+ /// Success:
+ /// - Key Import successfully finished.
+ /// Error:
+ /// - An error occured during the Key Import process.
+ /// </summary>
+ /// <returns>The list of wizard states.</returns>
+ private List<WizardState> CreatePGPWizardStates()
+ {
+ List<WizardState> states = new List<WizardState>();
+
+ try
+ {
+ // Step 1
+ states.Add(new WizardState
+ {
+ // Step
+ Step = Steps.Step1,
+
+ // Title text
+ TitleText = Properties.Resources.KeySyncWizard_PGPStep1ExplanationText,
+
+ // Central area
+ AreTrustwordsVisible = false,
+ IsUserTextVisible = true,
+ UserText = this.UserName,
+
+ // Back button
+ IsBackButtonVisible = false,
+
+ // Accept button
+ AcceptButtonText = Properties.Resources.KeySyncWizard_Next,
+ IsAcceptButtonVisible = true,
+ AcceptButtonClick = new Action(() =>
+ {
+ this.GoToNextStep();
+ }),
+
+ // Cancel button
+ CancelButtonText = Properties.Resources.Options_CancelText,
+ IsCancelButtonVisible = true,
+ CancelButtonClick = new Action(() =>
+ {
+ this.CancelWizard();
+ }),
+
+ // Subtitle area
+ SubtitleText = null
+ });
+
+ // Step 2
+ states.Add(new WizardState
+ {
+ // Step
+ Step = Steps.Step2,
+
+ // Title text
+ TitleText = Properties.Resources.KeySyncWizard_PGPStep2ExplanationText,
+
+ // Central area
+ AreTrustwordsVisible = false,
+ IsUserTextVisible = true,
+ UserText = this.UserName,
+
+ // Back button
+ IsBackButtonVisible = true,
+ BackButtonClick = new Action(() =>
+ {
+ this.GoToPreviousStep();
+ }),
+
+ // Accept button
+ AcceptButtonText = Properties.Resources.KeySyncWizard_Next,
+ IsAcceptButtonVisible = true,
+ AcceptButtonClick = new Action(() =>
+ {
+ this.GoToNextStep();
+ }),
+
+ // Cancel button
+ CancelButtonText = Properties.Resources.Options_CancelText,
+ IsCancelButtonVisible = true,
+ CancelButtonClick = new Action(() =>
+ {
+ this.CancelWizard();
+ }),
+
+ // Subtitle area
+ SubtitleText = null
+ });
+
+ // Step 3
+ states.Add(new WizardState
+ {
+ // Step
+ Step = Steps.Step3,
+
+ // Title text
+ TitleText = Properties.Resources.KeySyncWizard_PGPStep3ExplanationText,
+
+ // Central area
+ AreTrustwordsVisible = false,
+ IsUserTextVisible = true,
+ UserText = this.UserName,
+
+ // Back button
+ IsBackButtonVisible = true,
+ BackButtonClick = new Action(() =>
+ {
+ this.GoToPreviousStep();
+ }),
+
+ // Accept button
+ AcceptButtonText = Properties.Resources.KeySyncWizard_Next,
+ IsAcceptButtonVisible = true,
+ AcceptButtonClick = new Action(() =>
+ {
+ this.GoToNextStep();
+ this.ProcessReceivedSyncMessages();
+ }),
+
+ // Cancel button
+ CancelButtonText = Properties.Resources.Options_CancelText,
+ IsCancelButtonVisible = true,
+ CancelButtonClick = new Action(() =>
+ {
+ this.CancelWizard();
+ }),
+
+ // Subtitle area
+ SubtitleText = null
+ });
+
+ // Step 4
+ states.Add(new WizardState
+ {
+ // Step
+ Step = Steps.Step4,
+
+ // Title text
+ TitleText = Properties.Resources.KeySyncWizard_WaitingForResponseText,
+
+ // Central area
+ AreTrustwordsVisible = false,
+ IsUserTextVisible = true,
+ UserText = this.UserName,
+
+ // Back button
+ // Back button
+ IsBackButtonVisible = true,
+ BackButtonClick = new Action(() =>
+ {
+ this.GoToPreviousStep();
+ }),
+
+ // Accept button
+ IsAcceptButtonVisible = false,
+
+ // Cancel button
+ CancelButtonText = Properties.Resources.Options_CancelText,
+ IsCancelButtonVisible = true,
+ CancelButtonClick = new Action(() =>
+ {
+ this.CancelWizard();
+ }),
+
+ // Subtitle area
+ SubtitleText = null
+ });
+
+ // Step 5
+ states.Add(new WizardState
+ {
+ // Step
+ Step = Steps.Step5,
+
+ // Title text
+ TitleText = Properties.Resources.KeySyncWizard_PGPStep5ExplanationText,
+
+ // Central area
+ AreTrustwordsVisible = true,
+ IsUserTextVisible = false,
+
+ // Back button
+ IsBackButtonVisible = false,
+
+ // Accept button
+ AcceptButtonText = Properties.Resources.Handshake_ConfirmFingerprint,
+ IsAcceptButtonVisible = true,
+ AcceptButtonClick = new Action(() =>
+ {
+ this.GoToNextStep();
+ this.TrustKey();
+ }),
+
+ // Cancel button
+ CancelButtonText = Properties.Resources.Handshake_WrongFingerprint,
+ IsCancelButtonVisible = true,
+ CancelButtonClick = new Action(() =>
+ {
+ this.CancelWizard();
+ }),
+
+ // Subtitle area
+ SubtitleText = null
+ });
+
+ // Step 6
+ states.Add(new WizardState
+ {
+ // Step
+ Step = Steps.Step6,
+
+ // Title text
+ TitleText = Properties.Resources.KeySyncWizard_PGPStep6ExplanationText,
+
+ // Central area
+ AreTrustwordsVisible = false,
+ IsUserTextVisible = true,
+ UserText = this.UserName,
+
+ // Back button
+ IsBackButtonVisible = false,
+
+ // Accept button
+ AcceptButtonText = Properties.Resources.KeySyncWizard_Next,
+ IsAcceptButtonVisible = true,
+ AcceptButtonClick = new Action(() =>
+ {
+ this.GoToNextStep();
+ }),
+
+ // Cancel button
+ CancelButtonText = Properties.Resources.Options_CancelText,
+ IsCancelButtonVisible = true,
+ CancelButtonClick = new Action(() =>
+ {
+ this.CancelWizard();
+ }),
+
+ // Subtitle area
+ SubtitleText = null
+ });
+
+ // Step 7
+ states.Add(new WizardState
+ {
+ // Step
+ Step = Steps.Step7,
+
+ // Title text
+ TitleText = Properties.Resources.KeySyncWizard_PGPStep7ExplanationText,
+
+ // Central area
+ AreTrustwordsVisible = false,
+ IsUserTextVisible = true,
+ UserText = this.UserName,
+
+ // Back button
+ IsBackButtonVisible = true,
+ BackButtonClick = new Action(() =>
+ {
+ this.GoToPreviousStep();
+ }),
+
+ // Accept button
+ AcceptButtonText = Properties.Resources.KeySyncWizard_Next,
+ IsAcceptButtonVisible = true,
+ AcceptButtonClick = new Action(() =>
+ {
+ this.GoToNextStep();
+ this.ProcessReceivedSyncMessages();
+ }),
+
+ // Cancel button
+ CancelButtonText = Properties.Resources.Options_CancelText,
+ IsCancelButtonVisible = true,
+ CancelButtonClick = new Action(() =>
+ {
+ this.CancelWizard();
+ }),
+
+ // Subtitle area
+ SubtitleText = null
+ });
+
+ // Step 8
+ states.Add(new WizardState
+ {
+ // Step
+ Step = Steps.Step8,
+
+ // Title text
+ TitleText = Properties.Resources.KeySyncWizard_WaitingForResponseText,
+
+ // Central area
+ AreTrustwordsVisible = false,
+ IsUserTextVisible = true,
+ UserText = this.UserName,
+
+ // Back button
+ IsBackButtonVisible = true,
+ BackButtonClick = new Action(() =>
+ {
+ this.GoToPreviousStep();
+ }),
+
+ // Accept button
+ IsAcceptButtonVisible = false,
+
+ // Cancel button
+ CancelButtonText = Properties.Resources.Options_CancelText,
+ IsCancelButtonVisible = true,
+ CancelButtonClick = new Action(() =>
+ {
+ this.CancelWizard();
+ }),
+
+ // Subtitle area
+ SubtitleText = null
+ });
+
+ // Success
+ states.Add(new WizardState
+ {
+ // Step
+ Step = Steps.Success,
+
+ // Title text
+ TitleText = Properties.Resources.KeySyncWizard_PGPSuccessExplanationText,
+
+ // Central area
+ AreTrustwordsVisible = false,
+ IsUserTextVisible = true,
+ UserText = this.UserName,
+
+ // Back button
+ IsBackButtonVisible = false,
+
+ // Accept button
+ AcceptButtonText = Properties.Resources.KeySyncWizard_Finish,
+ IsAcceptButtonVisible = true,
+ AcceptButtonClick = new Action(() =>
+ {
+ this.Close();
+ }),
+
+ // Cancel button
+ IsCancelButtonVisible = false,
+
+ // Subtitle area
+ SubtitleText = null
+ });
+
+ // Error
+ states.Add(new WizardState
+ {
+ // Step
+ Step = Steps.Error,
+
+ // Title text
+ TitleText = Properties.Resources.KeySyncWizard_ErrorExplanationText,
+
+ // Central area
+ AreTrustwordsVisible = false,
+ IsUserTextVisible = true,
+ UserText = this.UserName,
+
+ // Back button
+ IsBackButtonVisible = false,
+
+ // Accept button
+ AcceptButtonText = Properties.Resources.KeySyncWizard_Finish,
+ IsAcceptButtonVisible = true,
+ AcceptButtonClick = new Action(() =>
+ {
+ this.CancelWizard();
+ }),
+
+ // Cancel button
+ IsCancelButtonVisible = false,
+
+ // Subtitle area
+ SubtitleText = null
+ });
+ }
+ catch (Exception ex)
+ {
+ states = null;
+ Log.Error("CreateWizardStates: Error creating wizard states. " + ex.ToString());
+ }
+
+ return states;
+ }
+
+ /// <summary>
/// Navigates to the last step of the wizard.
/// </summary>
/// <param name="success">Whether or not the wizard has been completed successfully.</param>
private void GoToLastStep(bool success)
{
// Go to last step
- this.State = WizardState.Step4;
- this.Success = success;
+ this.Step = success ? Steps.Success : Steps.Error;
- // Update content
- this.UpdateContent();
+ // Update wording and state
+ var lastState = this.states.Find(a => a.Step == this.Step);
+ if (this.IsInitiator)
+ {
+ if (this.SetImportedKeyAsDefault)
+ {
+ lastState.TitleText = Properties.Resources.KeySyncWizard_PEPSuccessImport + "\n\n" + Properties.Resources.KeySyncWizard_PEPSuccessOtherKeyUsedAsDefault;
+ }
+ else
+ {
+ lastState.TitleText = Properties.Resources.KeySyncWizard_PEPSuccessImport + "\n\n" + Properties.Resources.KeySyncWizard_PEPSuccessOtherKeyUsed;
+ }
+ }
+ else
+ {
+ if (this.privateKeyImported)
+ {
+ lastState.TitleText = Properties.Resources.KeySyncWizard_PEPSuccessExport + "\n\n" + Properties.Resources.KeySyncWizard_PEPSuccessOtherKeyUsed;
+ }
+ else
+ {
+ lastState.TitleText = Properties.Resources.KeySyncWizard_PEPSuccessExport;
+ }
+ }
+
+ // Apply state
+ this.CurrentState = lastState;
Log.Verbose("GoToLastStep: Process finished. Success is " + success.ToString());
}
@@ -584,26 +1324,42 @@
private void GoToNextStep()
{
// Go to next step
- this.State++;
+ this.Step++;
+
+ // Set current state
+ this.CurrentState = states.Find(a => a.Step == this.Step);
+
+ Log.Verbose("GoToNextStep: New state: " + Enum.GetName(typeof(Steps), this.Step));
+ }
- // Update content
- this.UpdateContent();
+ /// <summary>
+ /// Navigates to the previous state of the wizard.
+ /// </summary>
+ private void GoToPreviousStep()
+ {
+ // Go to next step
+ this.Step--;
- Log.Verbose("GoToNextStep: New state: " + Enum.GetName(typeof(WizardState), this.State));
+ // Set current state
+ this.CurrentState = states.Find(a => a.Step == this.Step);
+
+ Log.Verbose("GoToPreviousStep: New state: " + Enum.GetName(typeof(Steps), this.Step));
}
/// <summary>
/// Initializes the wizard.
/// </summary>
- private void InitializeWizard(WizardType type,
+ private void InitializeWizard(bool isInitiator,
+ WizardType type,
PEPIdentity myself,
string partnerFpr)
{
// Set initial state
this.DataContext = this;
this.Myself = myself;
- this.State = WizardState.Step1;
+ this.Step = Steps.Step1;
this.Type = type;
+ this.IsInitiator = isInitiator;
// If own identity is null, get default account
if (this.Myself == null)
@@ -696,8 +1452,39 @@
this.Partner.Fingerprint = partnerFpr;
}
- // Update dialog content
- this.UpdateContent();
+ // Define states
+ this.states = (this.Type == WizardType.pEp) ? this.CreatePEPWizardStates() : this.CreatePGPWizardStates();
+
+ // Set current state
+ this.CurrentState = states?.Find(a => a.Step == Steps.Step1);
+ }
+
+ /// <summary>
+ /// Runs through all received sync messages.
+ /// </summary>
+ private void ProcessReceivedSyncMessages()
+ {
+ lock (mutexReceivedSyncMessages)
+ {
+ if (this.receivedSyncMessages != null)
+ {
+ foreach (var message in this.receivedSyncMessages)
+ {
+ try
+ {
+ Task.Factory.StartNew(new Action(() =>
+ {
+ MsgProcessor msgProcessor = new MsgProcessor();
+ msgProcessor.Decrypt(message);
+ }));
+ }
+ catch (Exception ex)
+ {
+ Log.Error("ProcessReceivedSyncMessages: Error processing sync message. " + ex.ToString());
+ }
+ }
+ }
+ }
}
/// <summary>
@@ -711,93 +1498,117 @@
{
try
{
- // If we have no partner at this point, use a copy of myself
- if (this.Partner == null)
- {
- this.Partner = this.Myself.Copy();
- Log.Verbose("SendSyncMessage: Partner was null. Using copy of myself.");
- }
-
- // Create basic message
- bool processMessage = true;
- PEPMessage message = new PEPMessage
+ // Start sending in background
+ Task.Factory.StartNew(new Action(() =>
{
- From = this.Myself,
- ShortMsg = (messageType == MessageTypes.InitialMessage && this.Type == WizardType.PGP) ? Properties.Resources.KeySyncWizard_PGPInitialMessageSubject : PEPMessage.PEP_HIDDEN_SYNC_MESSAGE_SUBJECT,
- LongMsg = (messageType == MessageTypes.InitialMessage && this.Type == WizardType.PGP) ? Properties.Resources.KeySyncWizard_PGPInitialMessageBody : PEPMessage.PEP_HIDDEN_SYNC_MESSAGE_BODY,
- AutoConsume = (this.Type == WizardType.pEp) ? "yes" : null,
- Direction = pEpMsgDirection.pEpDirOutgoing,
- ForceUnencrypted = (messageType == MessageTypes.InitialMessage ? true : false),
- KeyImport = (this.Type == WizardType.pEp ? this.Myself.Fingerprint : null)
- };
- message.To.Add(this.Partner);
+ // If we have no partner at this point, use a copy of myself
+ if (this.Partner == null)
+ {
+ this.Partner = this.Myself.Copy();
+ this.Partner.Fingerprint = null;
+ Log.Verbose("SendSyncMessage: Partner was null. Using copy of myself.");
+ }
+
+ // Create basic message
+ bool processMessage = true;
+ PEPMessage message = new PEPMessage
+ {
+ From = this.Myself,
+ ShortMsg = (messageType == MessageTypes.InitialMessage && this.Type == WizardType.PGP) ? Properties.Resources.KeySyncWizard_PGPInitialMessageSubject : PEPMessage.PEP_HIDDEN_SYNC_MESSAGE_SUBJECT,
+ LongMsg = (messageType == MessageTypes.InitialMessage && this.Type == WizardType.PGP) ? Properties.Resources.KeySyncWizard_PGPInitialMessageBody : PEPMessage.PEP_HIDDEN_SYNC_MESSAGE_BODY,
+ AutoConsume = (this.Type == WizardType.pEp) ? "yes" : null,
+ Direction = pEpMsgDirection.pEpDirOutgoing,
+ ForceUnencrypted = (messageType == MessageTypes.InitialMessage ? true : false),
+ KeyImport = (this.Type == WizardType.pEp ? this.Myself.Fingerprint : null)
+ };
+ message.To.Add(this.Partner);
+
+ Log.Verbose("SendSyncMessage: Basic message successfully created.");
- Log.Verbose("SendSyncMessage: Basic message successfully created.");
+ // If message type isn't InitialMessage, encrypt it accordingly
+ PEPMessage msg;
+ MsgProcessor msgProcessor = new MsgProcessor();
+ if ((messageType == MessageTypes.PrivateKeyMessage) &&
+ (this.ExportPrivateKey))
+ {
+ // Encrypt and add private key
+ if (msgProcessor.EncryptAndAddPrivateKey(message, this.Partner.Fingerprint, out msg))
+ {
+ Log.Verbose("SendSyncMessage: Private key message successfully created.");
+ message = msg;
+ processMessage = false;
+ }
+ else
+ {
+ Log.Error("SendSyncMessage: Error encrypting private key message.");
+ message = null;
+ }
+ }
+ else if (((messageType == MessageTypes.PrivateKeyMessage) &&
+ (this.ExportPrivateKey == false)) ||
+ (messageType == MessageTypes.PublicKeyMessage))
+ {
+ // Encrypt using partner fpr as extra key
+ if (msgProcessor.Encrypt(message, new string[] { this.Partner.Fingerprint }, out msg))
+ {
+ Log.Verbose("SendSyncMessage: Public key message successfully created.");
+ message = msg;
+ processMessage = false;
+ }
+ else
+ {
+ Log.Error("SendSyncMessage: Error encrypting public key message.");
+ message = null;
+ }
+ }
- // If the message is the private key transport message, add own private key
- PEPMessage msg;
- if (messageType == MessageTypes.PrivateKeyMessage)
- {
- MsgProcessor msgProcessor = new MsgProcessor();
- if (msgProcessor.EncryptAndAddPrivateKey(message, this.Partner.Fingerprint, out msg))
+ // If we have a message, send it
+ if (message != null)
{
- Log.Verbose("SendSyncMessage: Private key message successfully created.");
- message = msg;
- processMessage = false;
+ Log.Verbose("SendSyncMessage: Sending message...");
+
+ // Disable passive mode if needed
+ bool reenablePassiveMode = false;
+ if ((messageType == MessageTypes.InitialMessage) &&
+ (Globals.ThisAddIn.Settings.IsPassiveModeEnabled))
+ {
+ try
+ {
+ ThisAddIn.PEPEngine.PassiveMode(false);
+ reenablePassiveMode = true;
+ Log.Verbose("SendSyncMessage: Passive mode temporarily disabled.");
+ }
+ catch (Exception ex)
+ {
+ Log.Error("SendSyncMessage: Error disabling passive mode. " + ex.ToString());
+ }
+ }
+
+ // Send message
+ Globals.ThisAddIn.CreateAndSendMessage(message, true, true, processMessage, true);
+
+ // Log that message has been sent
+ this.sentMessages?.Add(messageType);
+
+ // Reenable passive mode if needed
+ if (reenablePassiveMode)
+ {
+ try
+ {
+ ThisAddIn.PEPEngine.PassiveMode(Globals.ThisAddIn.Settings.IsPassiveModeEnabled);
+ Log.Verbose("SendSyncMessage: Passive mode reenabled.");
+ }
+ catch (Exception ex)
+ {
+ Log.Error("SendSyncMessage: Error reenabling passive mode. " + ex.ToString());
+ }
+ }
}
else
{
- Log.Error("SendSyncMessage: Error encrypting private key message.");
- message = null;
- }
- }
-
- // If we have a message, send it
- if (message != null)
- {
- Log.Verbose("SendSyncMessage: Sending message...");
-
- // Disable passive mode if needed
- bool reenablePassiveMode = false;
- if ((messageType == MessageTypes.InitialMessage) &&
- (Globals.ThisAddIn.Settings.IsPassiveModeEnabled))
- {
- try
- {
- ThisAddIn.PEPEngine.PassiveMode(false);
- reenablePassiveMode = true;
- Log.Verbose("SendSyncMessage: Passive mode temporarily disabled.");
- }
- catch (Exception ex)
- {
- Log.Error("SendSyncMessage: Error disabling passive mode. " + ex.ToString());
- }
+ Log.Error("SendSyncMessage: Myself identity is null.");
}
-
- // Send message
- Globals.ThisAddIn.CreateAndSendMessage(message, true, true, processMessage, true);
-
- // Log that message has been sent
- this.sentMessages?.Add(messageType);
-
- // Reenable passive mode if needed
- if (reenablePassiveMode)
- {
- try
- {
- ThisAddIn.PEPEngine.PassiveMode(Globals.ThisAddIn.Settings.IsPassiveModeEnabled);
- Log.Verbose("SendSyncMessage: Passive mode reenabled.");
- }
- catch (Exception ex)
- {
- Log.Error("SendSyncMessage: Error reenabling passive mode. " + ex.ToString());
- }
- }
- }
- else
- {
- Log.Error("SendSyncMessage: Myself identity is null.");
- }
+ }), TaskCreationOptions.LongRunning);
}
catch (Exception ex)
{
@@ -807,7 +1618,7 @@
}
/// <summary>
- /// Trusts the communication partner key (makes the channel green)
+ /// Trusts the communication partner key (makes the channel green).
/// </summary>
private void TrustKey()
{
@@ -815,31 +1626,28 @@
{
try
{
- Log.Verbose("TrustKey: Trusting partner key...");
-
- this._Partner = this.Items[0].Partner;
- pEpIdentity partner = this._Partner.ToCOMType();
- ThisAddIn.PEPEngine.TrustPersonalKey(partner);
-
- // If Trustwords are being accepted after having received
- // the private key, finish process.
- if (this.State == WizardState.Step3)
+ // Run in background
+ Task.Factory.StartNew(new Action(() =>
{
- Log.Verbose("TrustKey: Private key already received. Completing wizard.");
- this.CompleteWizard();
- }
- else
+ Log.Verbose("TrustKey: Trusting partner key...");
+
+ // Trust the partner's key
+ this._Partner = this.Items[0].Partner;
+ pEpIdentity partner = this._Partner.ToCOMType();
+ ThisAddIn.PEPEngine.TrustPersonalKey(partner);
+
+ // Process messages that might have been received
+ this.ProcessReceivedSyncMessages();
+
+ }), TaskCreationOptions.LongRunning).ContinueWith(new Action<Task>((result) =>
{
- Log.Verbose("TrustKey: No private key received yet. Going to next step.");
- this.GoToNextStep();
- }
-
- // In pEp sync mode, send private key to partner
- if (this.Type == WizardType.pEp)
- {
- Log.Verbose("TrustKey: Sending private key to partner.");
- this.SendSyncMessage(MessageTypes.PrivateKeyMessage);
- }
+ // In pEp sync mode, send private key message to partner
+ if (this.Type == WizardType.pEp)
+ {
+ Log.Verbose("TrustKey: Sending private key to partner.");
+ this.SendSyncMessage(MessageTypes.PrivateKeyMessage);
+ }
+ }));
}
catch (Exception ex)
{
@@ -855,108 +1663,42 @@
}
/// <summary>
- /// Updates the dialog content according to its current state.
- /// </summary>
- private void UpdateContent()
- {
- // Set title
- if (string.IsNullOrEmpty(this._TitleText))
- {
- this.TitleText = this.TitleText = this.Myself?.Address;
- }
-
- // Set content according to state
- switch (this.State)
- {
- case WizardState.Step1:
- {
- this.NextButtonText = Properties.Resources.KeySyncWizard_Next;
- this.ExplanationText = (this.Type == WizardType.pEp) ? Properties.Resources.KeySyncWizard_Step1PEPExplanationText : Properties.Resources.KeySyncWizard_Step1PGPExplanationText;
- this.SubtitleText = (this.Type == WizardType.pEp) ? Properties.Resources.KeySyncWizard_WaitingForResponseText : Properties.Resources.KeySyncWizard_Step1PGPSubtitleText;
- }
- break;
- case WizardState.Step2:
- {
- this.NextButtonText = (this.Type == WizardType.pEp) ? Properties.Resources.Handshake_ConfirmTrustwords : Properties.Resources.Handshake_ConfirmFingerprint;
- this.ExplanationText = (this.Type == WizardType.pEp) ? Properties.Resources.KeySyncWizard_Step2PEPExplanationText : Properties.Resources.KeySyncWizard_Step2PGPExplanationText;
- this.SubtitleText = (this.Type == WizardType.pEp) ? Properties.Resources.Handshake_ConfirmTrustwords : Properties.Resources.Handshake_ConfirmFingerprint;
- }
- break;
- case WizardState.Step3:
- {
- this.NextButtonText = Properties.Resources.KeySyncWizard_Next;
- this.ExplanationText = (this.Type == WizardType.pEp) ? Properties.Resources.KeySyncWizard_Step3PEPExplanationText : Properties.Resources.KeySyncWizard_Step3PGPExplanationText;
- this.SubtitleText = Properties.Resources.KeySyncWizard_WaitingForResponseText;
- }
- break;
- case WizardState.Step4:
- {
- this.NextButtonText = Properties.Resources.KeySyncWizard_Finish;
-
- if (this.Success)
- {
- this.SubtitleText = Properties.Resources.KeySyncWizard_SuccessText;
-
- switch (this.Type)
- {
- case WizardType.PGP:
- {
- this.ExplanationText = Properties.Resources.KeySyncWizard_Step4SuccessExplanationText;
- }
- break;
- case WizardType.pEp:
- {
- if (this.isInitiator)
- {
- this.ExplanationText = Properties.Resources.KeySyncWizard_Step4PEPSuccessInitiatorExplanationText;
- }
- else
- {
- this.ExplanationText = Properties.Resources.KeySyncWizard_Step4PEPSuccessNonInitiatorExplanationText;
- }
- }
- break;
- case WizardType.Undefined:
- default:
- {
- this.ExplanationText = string.Empty;
- }
- break;
- }
- }
- else
- {
- this.ExplanationText = Properties.Resources.KeySyncWizard_Step4ErrorExplanationText;
- this.SubtitleText = Properties.Resources.KeySyncWizard_ErrorText;
- }
- }
- break;
- case WizardState.Undefined:
- default:
- this.NextButtonText = Properties.Resources.KeySyncWizard_Finish;
- this.ExplanationText = string.Empty;
- this.SubtitleText = string.Empty;
- break;
- }
- }
-
- /// <summary>
/// Resets the object to its defaults.
/// </summary>
public void Reset()
{
- this._ExplanationText = null;
+ this._CurrentState = new WizardState();
+ this._ExportPrivateKey = true;
+ this._IsInitiator = false;
this._Items = new ObservableCollection<HandshakeItem>();
this._Myself = null;
- this._NextButtonText = null;
this._Partner = null;
- this._State = WizardState.Undefined;
- this._SubtitleText = null;
- this._Success = false;
+ this._Step = Steps.Undefined;
+ this._SetImportedKeyAsDefault = true;
this._Type = WizardType.Undefined;
- this._TitleText = null;
}
#endregion
+
+ /// <summary>
+ /// Container to define a wizard state.
+ /// </summary>
+ public class WizardState
+ {
+ public Action AcceptButtonClick { get; set; } = null;
+ public string AcceptButtonText { get; set; } = null;
+ public bool AreTrustwordsVisible { get; set; } = false;
+ public Action BackButtonClick { get; set; } = null;
+ public Action CancelButtonClick { get; set; } = null;
+ public string CancelButtonText { get; set; } = null;
+ public bool IsAcceptButtonVisible { get; set; } = true;
+ public bool IsBackButtonVisible { get; set; } = false;
+ public bool IsCancelButtonVisible { get; set; } = true;
+ public bool IsUserTextVisible { get; set; } = true;
+ public KeySyncWizard.Steps Step { get; set; } = Steps.Undefined;
+ public string SubtitleText { get; set; } = null;
+ public string TitleText { get; set; } = null;
+ public string UserText { get; set; } = null;
+ }
}
}
--- a/UI/ValueConverters.cs Thu May 10 15:04:25 2018 +0200
+++ b/UI/ValueConverters.cs Thu May 17 11:21:56 2018 +0200
@@ -276,61 +276,6 @@
}
/// <summary>
- /// Returns a bool value indicating if the wizard state matches any of the given parameter.
- /// </summary>
- public class IsWizardStateConverter : IValueConverter
- {
- public object Convert(object value,
- Type targetType,
- object parameter,
- CultureInfo culture)
- {
- bool success;
- KeySyncWizard.WizardState param;
-
- if ((value is KeySyncWizard.WizardState) &&
- (parameter is string))
- {
- string[] parameters = (parameter as string).Split('|');
-
- if (parameters?.Length > 0)
- {
- foreach (var p in parameters)
- {
- success = Enum.TryParse(p, out param);
-
- if (success)
- {
- if (((KeySyncWizard.WizardState)value) == param)
- {
- return true;
- }
- }
- else
- {
- throw new ArgumentException();
- }
- }
- }
-
- return false;
- }
- else
- {
- throw new ArgumentException();
- }
- }
-
- public object ConvertBack(object value,
- Type targetType,
- object parameter,
- CultureInfo culture)
- {
- throw new NotImplementedException();
- }
- }
-
- /// <summary>
/// Converter to check if a list is empty.
/// </summary>
public class IsListEmptyConverter : IValueConverter
@@ -530,6 +475,38 @@
}
/// <summary>
+ /// Returns true if the Wizard is in the given state.
+ /// </summary>
+ public class IsWizardTypeConverter : IValueConverter
+ {
+ public object Convert(object value,
+ Type targetType,
+ object parameter,
+ CultureInfo culture)
+ {
+ string val = null;
+ string param = parameter as string;
+
+ try
+ {
+ val = Enum.GetName(typeof(KeySyncWizard.WizardType), value);
+ }
+ catch
+ {
+ val = null;
+ }
+
+ return (param?.Equals(val) == true);
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+
+ /// <summary>
/// Converter to AND several bool values and convert to Visibility.
/// </summary>
public class MultiBooleanToVisibilityConverter : IMultiValueConverter