Adjust design, reorder, add deletion of internal messages OUT-308
authorThomas
Wed, 25 Oct 2017 14:21:44 +0200
branchOUT-308
changeset 1885a284dbe6cf79
parent 1884 af5911e1cae5
child 1887 7f7402d294da
Adjust design, reorder, add deletion of internal messages
DecryptionStack.cs
Extensions/MailItemExtensions.cs
FPPMessage.cs
Globals.cs
Properties/Resources.resx
UI/HandshakeDialog.xaml
UI/HandshakeDialog.xaml.cs
UI/ValueConverters.cs
     1.1 --- a/DecryptionStack.cs	Wed Oct 25 09:08:11 2017 +0200
     1.2 +++ b/DecryptionStack.cs	Wed Oct 25 14:21:44 2017 +0200
     1.3 @@ -270,6 +270,7 @@
     1.4                      if (omi.GetIsForceFullyProtected())
     1.5                      {
     1.6                          Log.Verbose("DecryptionStack.DecryptionTimer_Tick: Force Protection Protocol Message found. Processing...");
     1.7 +                        omi.UnRead = false;
     1.8                          var fppMessage = new FPPMessage(omi);
     1.9                          fppMessage.ProcessIncoming();
    1.10                      }
    1.11 @@ -285,6 +286,8 @@
    1.12                          cmi.StartProcessing(true);
    1.13                          Log.Verbose("DecryptionStack.DecryptionTimer_Tick: started decryption of item with entryId " + omi?.EntryID);
    1.14                      }
    1.15 +
    1.16 +                    omi = null;
    1.17                  }
    1.18                  else
    1.19                  {
     2.1 --- a/Extensions/MailItemExtensions.cs	Wed Oct 25 09:08:11 2017 +0200
     2.2 +++ b/Extensions/MailItemExtensions.cs	Wed Oct 25 14:21:44 2017 +0200
     2.3 @@ -119,142 +119,6 @@
     2.4           *************************************************************/
     2.5  
     2.6          /// <summary>
     2.7 -        /// Converts the given mail item into a forcefully encrypted mail item. This is done
     2.8 -        /// by saving the original message to disk and encrypt it symmetrically. Then, the original
     2.9 -        /// is cleared of all content information and attachments and the encrypted message is
    2.10 -        /// added as attachment to the mail item.
    2.11 -        /// </summary>
    2.12 -        /// <param name="omi">The Outlook mail item to process with.</param>
    2.13 -        /// <returns>True if the Outlook mail item was converted successfully, otherwise false.</returns>
    2.14 -        public static Globals.ReturnStatus ConvertToForcefullyProtected(this Outlook.MailItem omi)
    2.15 -        {
    2.16 -            Globals.ReturnStatus status = Globals.ReturnStatus.Failure;
    2.17 -            Outlook.Attachments attachments = null;
    2.18 -            string key = null;
    2.19 -
    2.20 -            try
    2.21 -            {
    2.22 -                ///////////////////////////
    2.23 -                // Step 1: Save message to disk and encrypt symmetrically
    2.24 -                ///////////////////////////
    2.25 -
    2.26 -                // Save message as EML file on disk
    2.27 -                string messagePath = omi.SaveAsEml();
    2.28 -
    2.29 -                if (string.IsNullOrEmpty(messagePath))
    2.30 -                {
    2.31 -                    throw new Exception("Error saving message in EML format");
    2.32 -                }
    2.33 -
    2.34 -                // Create encrypted message path and encryption key
    2.35 -                string encryptedMessagePath = Path.ChangeExtension(messagePath, "pEp");
    2.36 -                key = Guid.NewGuid().ToString();
    2.37 -
    2.38 -                // Encrypt saved message
    2.39 -                if (FPPMessage.EncryptFile(messagePath, encryptedMessagePath, key) != Globals.ReturnStatus.Success)
    2.40 -                {
    2.41 -                    throw new Exception("Error encrypting message.");
    2.42 -                }
    2.43 -
    2.44 -                ///////////////////////////
    2.45 -                // Step 2: Store key and message uuid to database
    2.46 -                ///////////////////////////
    2.47 -
    2.48 -                // Read GUID from MAPI property
    2.49 -                string id = omi.GetForceProtectionId();
    2.50 -
    2.51 -                // Save value to database
    2.52 -                if (string.IsNullOrEmpty(id))
    2.53 -                {
    2.54 -                    throw new Exception("Error getting message GUID.");
    2.55 -                }
    2.56 -                else if (FPPMessage.StoreMsgIdAndKeyInDb(id, key) != Globals.ReturnStatus.Success)
    2.57 -                {
    2.58 -                    throw new Exception("Error saving key and message uuid to db.");
    2.59 -                }
    2.60 -
    2.61 -                ///////////////////////////
    2.62 -                // Step 3: Clear the content of the original message
    2.63 -                ///////////////////////////
    2.64 -
    2.65 -                omi.Subject = "p≡p";
    2.66 -                omi.BodyFormat = Outlook.OlBodyFormat.olFormatPlain;
    2.67 -                omi.Body = null;
    2.68 -                omi.HTMLBody = null;
    2.69 -
    2.70 -                /* Note that setting the RTFBody to null or an empty byte array throws an exception.
    2.71 -                 * Therefore, it is sent to a single zero byte to be constant.
    2.72 -                 * The RTFBody is ignored when sending the actual message.
    2.73 -                 */
    2.74 -                omi.RTFBody = new byte[] { 0x00 };
    2.75 -
    2.76 -                // Remove any previous attachments
    2.77 -                attachments = omi.Attachments;
    2.78 -                while (attachments.Count > 0)
    2.79 -                {
    2.80 -                    /* OUT-193: We cannot use attachments.Remove() here, as it
    2.81 -                     * seems to be buggy in Outlook 2013. Let's hope that
    2.82 -                     * using Attachment.Delete() has no bad side effects on
    2.83 -                     * other Outlook versions.
    2.84 -                     * OUT-292: The Delete() method can fail under rare circumstances.
    2.85 -                     * In this case, just log the error and break. 
    2.86 -                     * NOTE: We can NOT use a for loop here, as this leads to unforeseeable 
    2.87 -                     * issues with actual attachments (supposedly due to race conditions on 
    2.88 -                     * multithreaded decryption operations).
    2.89 -                     */
    2.90 -                    try
    2.91 -                    {
    2.92 -                        attachments[attachments.Count].Delete();
    2.93 -                    }
    2.94 -                    catch (Exception ex)
    2.95 -                    {
    2.96 -                        throw new Exception("Error deleting attachment. " + ex.ToString());
    2.97 -                    }
    2.98 -                }
    2.99 -
   2.100 -                ///////////////////////////
   2.101 -                // Step 4: Attach the encrypted original as attachment
   2.102 -                ///////////////////////////
   2.103 -
   2.104 -                // Add mail
   2.105 -                try
   2.106 -                {
   2.107 -                    attachments.Add(encryptedMessagePath, Outlook.OlAttachmentType.olByValue);
   2.108 -                }
   2.109 -                catch (Exception ex)
   2.110 -                {
   2.111 -                    throw new Exception("Error adding encrypted original as attachment. " + ex.ToString());
   2.112 -                }
   2.113 -
   2.114 -                // Add message text
   2.115 -                omi.Body = "This is a forcefully encrypted message. Please download pEp to decrypt it.";
   2.116 -
   2.117 -                // Remove plain and encrypted mails from disk
   2.118 -                try
   2.119 -                {
   2.120 -                    File.Delete(messagePath);
   2.121 -                    File.Delete(encryptedMessagePath);
   2.122 -                }
   2.123 -                catch (Exception ex)
   2.124 -                {
   2.125 -                    Log.Error("MailItemExtensions.ConvertToForcefullyProtected: Error deleting original mail from disk. " + ex.ToString());
   2.126 -                }
   2.127 -
   2.128 -                status = Globals.ReturnStatus.Success;
   2.129 -            }
   2.130 -            catch (Exception ex)
   2.131 -            {
   2.132 -                Log.Error("MailItemExtensions.ConvertToForcefullyProtected: Error protecting mail item. " + ex.ToString());
   2.133 -            }
   2.134 -            finally
   2.135 -            {
   2.136 -                attachments = null;
   2.137 -            }
   2.138 -
   2.139 -            return status;
   2.140 -        }
   2.141 -
   2.142 -        /// <summary>
   2.143          /// Determines whether to enable the form region for this mail item.
   2.144          /// </summary>
   2.145          /// <param name="omi">The Outlook mail item to process with.</param>
     3.1 --- a/FPPMessage.cs	Wed Oct 25 09:08:11 2017 +0200
     3.2 +++ b/FPPMessage.cs	Wed Oct 25 14:21:44 2017 +0200
     3.3 @@ -24,8 +24,15 @@
     3.4          public const string PEP_FPP_DB_MESSAGE_ID_COLUMN_NAME       = "MessageID";
     3.5          public const string PEP_FPP_DB_KEY_COLUMN_NAME              = "Key";
     3.6  
     3.7 -        public const string PEP_FPP_MESSAGE_BODY                    = "This message is part of p≡p's concept to synchronize. \n\nYou can safely ignore it. It will be deleted automatically.";
     3.8 -        public const string PEP_FPP_MESSAGE_SUBJECT                 = "p≡p synchronization message - please ignore";
     3.9 +        public const string PEP_FPP_HIDDEN_MESSAGE_BODY             = "This message is part of p≡p's concept to synchronize. \n\nYou can safely ignore it. It will be deleted automatically.";
    3.10 +        public const string PEP_FPP_HIDDEN_MESSAGE_SUBJECT          = "p≡p synchronization message - please ignore";
    3.11 +        public const string PEP_FPP_MESSAGE_BODY_PLAIN              = "This message is protected by p≡p. \n\nTo read this message, you can either download the free p≡p Reader here: " + 
    3.12 +                                                                      Globals.PEP_WEBSITE_READER_LINK + " \n\nTo read and send protected messages yourself, you can get your copy of p≡p here: " + 
    3.13 +                                                                      Globals.PEP_WEBSITE_UPGRADE_LINK;
    3.14 +        public const string PEP_FPP_MESSAGE_BODY_HTML               = "This message is protected by <span style=\"color:#03AA4B\">p≡p</span>. < /br>< /br>To read this message, you can either download the free " +
    3.15 +                                                                      "<a style=\"color:#03AA4B; text-decoration: none\" href=\"" + Globals.PEP_WEBSITE_READER_LINK + "\">p≡p Reader</a> or, " +
    3.16 +                                                                      "to read and send protected messages yourself, you can get your copy of <a style=\"color:#03AA4B; text-decoration: none\" href=\"" + 
    3.17 +                                                                      Globals.PEP_WEBSITE_UPGRADE_LINK + "\">p≡p here</a>.";
    3.18          public const string PEP_FPP_ATTACHMENT_FILE_NAME            = "ignore_this_attachment.pEp";
    3.19          public const string PEP_FPP_ATTACHMENT_MIME_TYPE            = "application/pEp.forceProtected";
    3.20  
    3.21 @@ -195,6 +202,13 @@
    3.22                      Log.Error("FPPMessage.ProcessIncoming: Task result is null.");
    3.23                  }
    3.24              }, TaskScheduler.FromCurrentSynchronizationContext());
    3.25 +
    3.26 +            // Enable also the automatic cleaning of internal messages
    3.27 +            try
    3.28 +            {
    3.29 +                Globals.ThisAddIn.EnableInboxCleaning();
    3.30 +            }
    3.31 +            catch { }
    3.32          }
    3.33  
    3.34          /// <summary>
    3.35 @@ -325,8 +339,8 @@
    3.36                  // Set base properties
    3.37                  nextMsg.AutoConsume = "yes";
    3.38                  nextMsg.ForceProtectionId = this.CurrentMessage.ForceProtectionId;
    3.39 -                nextMsg.ShortMsg = FPPMessage.PEP_FPP_MESSAGE_SUBJECT;
    3.40 -                nextMsg.LongMsg = FPPMessage.PEP_FPP_MESSAGE_BODY;
    3.41 +                nextMsg.ShortMsg = FPPMessage.PEP_FPP_HIDDEN_MESSAGE_SUBJECT;
    3.42 +                nextMsg.LongMsg = FPPMessage.PEP_FPP_HIDDEN_MESSAGE_BODY;
    3.43                  nextMsg.From = this.ReceivedBy;
    3.44                  nextMsg.To.Add(this.CurrentMessage.From);
    3.45                  Log.Verbose("CreateAndSendNextFPPMessage: Basic properties set.");
    3.46 @@ -563,6 +577,22 @@
    3.47                  // Partner identity is the sender of the current message
    3.48                  partnerIdentity = new PEPIdentity(ThisAddIn.PEPEngine.UpdateIdentity(currentMsg.From.ToCOMType()));
    3.49  
    3.50 +                // Close handshake dialog if it was still open
    3.51 +                if (handshakeDialog != null)
    3.52 +                {
    3.53 +                    try
    3.54 +                    {
    3.55 +                        handshakeDialog.DialogResult = null;
    3.56 +                        handshakeDialog.Close();
    3.57 +                    }
    3.58 +                    catch (Exception ex)
    3.59 +                    {
    3.60 +                        Log.Error("FPPMessage.ShowHandshake: Error closing handshake dialog. " + ex.ToString());
    3.61 +                    }
    3.62 +
    3.63 +                    handshakeDialog = null;
    3.64 +                }
    3.65 +
    3.66                  // Show handshake dialog
    3.67                  handshakeDialog = new HandshakeDialog(ownIdentity,
    3.68                                                        partnerIdentity,
    3.69 @@ -753,7 +783,7 @@
    3.70              // Convert message if necessary
    3.71              if (convertMessage)
    3.72              {
    3.73 -                status = omi.ConvertToForcefullyProtected();
    3.74 +                status = FPPMessage.ConvertToForcefullyProtected(omi);
    3.75              }
    3.76              else
    3.77              {
    3.78 @@ -762,6 +792,144 @@
    3.79  
    3.80              return status;
    3.81          }
    3.82 +
    3.83 +
    3.84 +        /// <summary>
    3.85 +        /// Converts the given mail item into a forcefully encrypted mail item. This is done
    3.86 +        /// by saving the original message to disk and encrypt it symmetrically. Then, the original
    3.87 +        /// is cleared of all content information and attachments and the encrypted message is
    3.88 +        /// added as attachment to the mail item.
    3.89 +        /// </summary>
    3.90 +        /// <param name="omi">The Outlook mail item to process with.</param>
    3.91 +        /// <returns>True if the Outlook mail item was converted successfully, otherwise false.</returns>
    3.92 +        public static Globals.ReturnStatus ConvertToForcefullyProtected(Outlook.MailItem omi)
    3.93 +        {
    3.94 +            Globals.ReturnStatus status = Globals.ReturnStatus.Failure;
    3.95 +            Outlook.Attachments attachments = null;
    3.96 +            string key = null;
    3.97 +
    3.98 +            try
    3.99 +            {
   3.100 +                ///////////////////////////
   3.101 +                // Step 1: Save message to disk and encrypt symmetrically
   3.102 +                ///////////////////////////
   3.103 +
   3.104 +                // Save message as EML file on disk
   3.105 +                string messagePath = omi.SaveAsEml();
   3.106 +
   3.107 +                if (string.IsNullOrEmpty(messagePath))
   3.108 +                {
   3.109 +                    throw new Exception("Error saving message in EML format");
   3.110 +                }
   3.111 +
   3.112 +                // Create encrypted message path and encryption key
   3.113 +                string encryptedMessagePath = Path.ChangeExtension(messagePath, "pEp");
   3.114 +                key = Guid.NewGuid().ToString();
   3.115 +
   3.116 +                // Encrypt saved message
   3.117 +                if (FPPMessage.EncryptFile(messagePath, encryptedMessagePath, key) != Globals.ReturnStatus.Success)
   3.118 +                {
   3.119 +                    throw new Exception("Error encrypting message.");
   3.120 +                }
   3.121 +
   3.122 +                ///////////////////////////
   3.123 +                // Step 2: Store key and message uuid to database
   3.124 +                ///////////////////////////
   3.125 +
   3.126 +                // Read GUID from MAPI property
   3.127 +                string id = omi.GetForceProtectionId();
   3.128 +
   3.129 +                // Save value to database
   3.130 +                if (string.IsNullOrEmpty(id))
   3.131 +                {
   3.132 +                    throw new Exception("Error getting message GUID.");
   3.133 +                }
   3.134 +                else if (FPPMessage.StoreMsgIdAndKeyInDb(id, key) != Globals.ReturnStatus.Success)
   3.135 +                {
   3.136 +                    throw new Exception("Error saving key and message uuid to db.");
   3.137 +                }
   3.138 +
   3.139 +                ///////////////////////////
   3.140 +                // Step 3: Clear the content of the original message
   3.141 +                ///////////////////////////
   3.142 +
   3.143 +                omi.Subject = "p≡p";
   3.144 +                omi.BodyFormat = Outlook.OlBodyFormat.olFormatPlain;
   3.145 +                omi.Body = null;
   3.146 +                omi.HTMLBody = null;
   3.147 +
   3.148 +                /* Note that setting the RTFBody to null or an empty byte array throws an exception.
   3.149 +                 * Therefore, it is sent to a single zero byte to be constant.
   3.150 +                 * The RTFBody is ignored when sending the actual message.
   3.151 +                 */
   3.152 +                omi.RTFBody = new byte[] { 0x00 };
   3.153 +
   3.154 +                // Remove any previous attachments
   3.155 +                attachments = omi.Attachments;
   3.156 +                while (attachments.Count > 0)
   3.157 +                {
   3.158 +                    /* OUT-193: We cannot use attachments.Remove() here, as it
   3.159 +                     * seems to be buggy in Outlook 2013. Let's hope that
   3.160 +                     * using Attachment.Delete() has no bad side effects on
   3.161 +                     * other Outlook versions.
   3.162 +                     * OUT-292: The Delete() method can fail under rare circumstances.
   3.163 +                     * In this case, just log the error and break. 
   3.164 +                     * NOTE: We can NOT use a for loop here, as this leads to unforeseeable 
   3.165 +                     * issues with actual attachments (supposedly due to race conditions on 
   3.166 +                     * multithreaded decryption operations).
   3.167 +                     */
   3.168 +                    try
   3.169 +                    {
   3.170 +                        attachments[attachments.Count].Delete();
   3.171 +                    }
   3.172 +                    catch (Exception ex)
   3.173 +                    {
   3.174 +                        throw new Exception("Error deleting attachment. " + ex.ToString());
   3.175 +                    }
   3.176 +                }
   3.177 +
   3.178 +                ///////////////////////////
   3.179 +                // Step 4: Attach the encrypted original as attachment
   3.180 +                ///////////////////////////
   3.181 +
   3.182 +                // Add mail
   3.183 +                try
   3.184 +                {
   3.185 +                    attachments.Add(encryptedMessagePath, Outlook.OlAttachmentType.olByValue);
   3.186 +                }
   3.187 +                catch (Exception ex)
   3.188 +                {
   3.189 +                    throw new Exception("Error adding encrypted original as attachment. " + ex.ToString());
   3.190 +                }
   3.191 +
   3.192 +                // Add message text
   3.193 +                omi.Body = FPPMessage.PEP_FPP_MESSAGE_BODY_PLAIN;
   3.194 +                omi.HTMLBody = FPPMessage.PEP_FPP_MESSAGE_BODY_HTML;
   3.195 +
   3.196 +                // Remove plain and encrypted mails from disk
   3.197 +                try
   3.198 +                {
   3.199 +                    File.Delete(messagePath);
   3.200 +                    File.Delete(encryptedMessagePath);
   3.201 +                }
   3.202 +                catch (Exception ex)
   3.203 +                {
   3.204 +                    Log.Error("MailItemExtensions.ConvertToForcefullyProtected: Error deleting original mail from disk. " + ex.ToString());
   3.205 +                }
   3.206 +
   3.207 +                status = Globals.ReturnStatus.Success;
   3.208 +            }
   3.209 +            catch (Exception ex)
   3.210 +            {
   3.211 +                Log.Error("MailItemExtensions.ConvertToForcefullyProtected: Error protecting mail item. " + ex.ToString());
   3.212 +            }
   3.213 +            finally
   3.214 +            {
   3.215 +                attachments = null;
   3.216 +            }
   3.217 +
   3.218 +            return status;
   3.219 +        }
   3.220          #endregion
   3.221  
   3.222          #region Database operations
     4.1 --- a/Globals.cs	Wed Oct 25 09:08:11 2017 +0200
     4.2 +++ b/Globals.cs	Wed Oct 25 14:21:44 2017 +0200
     4.3 @@ -34,6 +34,7 @@
     4.4          public const string PEP_NAME_INSTALL           = "pEp for Outlook";               // Name for Windows installer, must sync with installation code (shared with reader)
     4.5          public const string PEP_WEBSITE_LINK           = "https://prettyeasyprivacy.com";
     4.6          public const string PEP_WEBSITE_UPGRADE_LINK   = "https://pep.digitalcourage.de/shop/p8801p-for-outlook.html";
     4.7 +        public const string PEP_WEBSITE_READER_LINK    = "https://pep.digitalcourage.de/shop/p8801p-for-outlook.html";
     4.8  
     4.9  #if READER_RELEASE_MODE
    4.10          public const ReleaseMode RELEASE_MODE = ReleaseMode.Reader;
     5.1 --- a/Properties/Resources.resx	Wed Oct 25 09:08:11 2017 +0200
     5.2 +++ b/Properties/Resources.resx	Wed Oct 25 14:21:44 2017 +0200
     5.3 @@ -778,9 +778,9 @@
     5.4      <value>Reject</value>
     5.5    </data>
     5.6    <data name="Handshake_ForceProtectionSendKeyExplanationText" xml:space="preserve">
     5.7 -    <value>A partner requests your confirmation to decrypt a forcefully encrypted message that you sent to this address. Please confirm by verifying the following Trustwords.</value>
     5.8 +    <value>Your communication partner will be completely Secure &amp; Trusted by comparing the Trustwords below with your communication partner, by making a phone call.</value>
     5.9    </data>
    5.10    <data name="Handshake_ForceProtectionImportKeyExplanationText" xml:space="preserve">
    5.11 -    <value>You have received a Secure message which you can read by confirming the Trustwords below with your communication partner.</value>
    5.12 +    <value>You have received a Secure message which you can read by confirming the Trustwords below with your communication partner, by making a phone call.</value>
    5.13    </data>
    5.14  </root>
    5.15 \ No newline at end of file
     6.1 --- a/UI/HandshakeDialog.xaml	Wed Oct 25 09:08:11 2017 +0200
     6.2 +++ b/UI/HandshakeDialog.xaml	Wed Oct 25 14:21:44 2017 +0200
     6.3 @@ -50,6 +50,11 @@
     6.4                  <local:InvertBoolConverter />
     6.5                  <BooleanToVisibilityConverter />
     6.6              </local:ValueConverterGroup>
     6.7 +            <local:ValueConverterGroup x:Key="IsNotSyncModeToVisibility">
     6.8 +                <local:IsSyncModeToBoolConverter />
     6.9 +                <local:InvertBoolConverter />
    6.10 +                <BooleanToVisibilityConverter />
    6.11 +            </local:ValueConverterGroup>
    6.12  
    6.13              <!-- Dictionary -->
    6.14              <ResourceDictionary.MergedDictionaries>
    6.15 @@ -108,7 +113,7 @@
    6.16                                Margin="5"
    6.17                                MinHeight="38"
    6.18                                MouseLeftButtonUp="IdentityGrid_MouseLeftButtonUp"
    6.19 -                              Visibility="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=Mode, Converter={StaticResource IsStandardModeToVisibility}, ConverterParameter=Standard}">
    6.20 +                              Visibility="{Binding Path=Mode, Converter={StaticResource IsNotSyncModeToVisibility}}">
    6.21                              <Grid.ColumnDefinitions>
    6.22                                  <ColumnDefinition Width="Auto" />
    6.23                                  <ColumnDefinition Width="*" />
    6.24 @@ -256,19 +261,20 @@
    6.25                              <!-- Buttons -->
    6.26                              <StackPanel Grid.Row="5"
    6.27                                          Orientation="Horizontal"
    6.28 -                                        HorizontalAlignment="Left"
    6.29 +                                        HorizontalAlignment="Right"
    6.30                                          Margin="0,5,0,0">
    6.31 +                                <Button Style="{StaticResource StyleWrongButton}"
    6.32 +                                        HorizontalAlignment="Center"
    6.33 +                                        Margin="0,5,5,5"
    6.34 +                                        Content="{Binding Path=ExpandedButton2Text, FallbackValue=Wrong}"
    6.35 +                                        Click="ButtonWrong_Click" />
    6.36                                  <Button Style="{StaticResource StyleConfirmButton}"
    6.37 -                                        HorizontalAlignment="Left"
    6.38 -                                        Margin="0,5,5,5"
    6.39 +                                        HorizontalAlignment="Center"
    6.40 +                                        Margin="5,5,0,5"
    6.41                                          Content="{Binding Path=ExpandedButton1Text, FallbackValue=Confirm}"
    6.42                                          Click="ButtonConfirm_Click"
    6.43 -                                        IsDefault="True" />
    6.44 -                                <Button Style="{StaticResource StyleWrongButton}"
    6.45 -                                        HorizontalAlignment="Left"
    6.46 -                                        Margin="5,5,0,5"
    6.47 -                                        Content="{Binding Path=ExpandedButton2Text, FallbackValue=Wrong}"
    6.48 -                                        Click="ButtonWrong_Click" />
    6.49 +                                        IsDefault="True"
    6.50 +                                        Loaded="ConfirmButton_Loaded"/>
    6.51                              </StackPanel>
    6.52                          </StackPanel>
    6.53                      </StackPanel>
     7.1 --- a/UI/HandshakeDialog.xaml.cs	Wed Oct 25 09:08:11 2017 +0200
     7.2 +++ b/UI/HandshakeDialog.xaml.cs	Wed Oct 25 14:21:44 2017 +0200
     7.3 @@ -479,6 +479,20 @@
     7.4              }
     7.5          }
     7.6  
     7.7 +        /// <summary>
     7.8 +        /// Event handler for when the Confirm button has been loaded.
     7.9 +        /// </summary>
    7.10 +        private void ConfirmButton_Loaded(object sender, RoutedEventArgs e)
    7.11 +        {
    7.12 +            // If not in standard mode, preselect this button
    7.13 +            if (this.Mode != HandshakeMode.Standard)
    7.14 +            {
    7.15 +                Button button = sender as Button;
    7.16 +
    7.17 +                button?.Focus();
    7.18 +            }
    7.19 +        }
    7.20 +
    7.21          /**************************************************************
    7.22           * 
    7.23           * Methods
    7.24 @@ -847,7 +861,7 @@
    7.25                  }
    7.26              }
    7.27              // Force Protection Protocol dialog
    7.28 -            else if ((this._Mode == HandshakeMode.ForceProtectionImportKey) ||
    7.29 +            else if ((this._Mode == HandshakeMode.ForceProtectionSendKey) ||
    7.30                       (this._Mode == HandshakeMode.ForceProtectionImportKey))
    7.31              {
    7.32                  // Create one item and add it to collection
    7.33 @@ -857,7 +871,6 @@
    7.34                  {
    7.35                      item.Myself = this._Myself;
    7.36                      item.Partner = this._SyncPartner;
    7.37 -                    item.ItemName = this.SyncPartner.UserName;
    7.38                      item.IsClickable = false;
    7.39                      item.IsExpanded = true;
    7.40                      item.IsSeparatorVisible = false;
    7.41 @@ -884,8 +897,37 @@
    7.42                              break;
    7.43                      }
    7.44  
    7.45 +                    // Update the partner identity
    7.46 +                    pEpIdentity syncPartner = this.SyncPartner.ToCOMType();
    7.47 +                    PEPIdentity partnerIdentity = new PEPIdentity(ThisAddIn.PEPEngine.UpdateIdentity(syncPartner));
    7.48 +
    7.49 +                    try
    7.50 +                    {
    7.51 +                        partnerIdentity.Rating = ThisAddIn.PEPEngine.IdentityRating(syncPartner);
    7.52 +                    }
    7.53 +                    catch (COMException ex)
    7.54 +                    {
    7.55 +                        Log.Error("HandshakeDialog.BuildDialog: Error getting partner identity rating. " + ex.ToString());
    7.56 +                        partnerIdentity.Rating = pEpRating.pEpRatingUndefined;
    7.57 +                    }
    7.58 +
    7.59 +                    // Set partner user name
    7.60 +                    if (string.IsNullOrEmpty(this.SyncPartner.UserName) == false)
    7.61 +                    {
    7.62 +                        item.ItemName = this.SyncPartner.UserName;
    7.63 +
    7.64 +                        if (string.IsNullOrEmpty(this.SyncPartner.Address) == false)
    7.65 +                        {
    7.66 +                            item.ItemName += " (" + this.SyncPartner.Address + ")";
    7.67 +                        }
    7.68 +                    }
    7.69 +                    else
    7.70 +                    {
    7.71 +                        item.ItemName = this.SyncPartner.Address;
    7.72 +                    }
    7.73 +
    7.74                      // Set rating image
    7.75 -                    switch (this.SyncPartner.Rating.ToColor())
    7.76 +                    switch (partnerIdentity.Rating.ToColor())
    7.77                      {
    7.78                          case pEpColor.pEpColorGreen:
    7.79                              item.ItemImage = new BitmapImage(new Uri("pack://application:,,,/pEp;component/Resources/ImagePrivacyStatusGreen.png", UriKind.RelativeOrAbsolute));
     8.1 --- a/UI/ValueConverters.cs	Wed Oct 25 09:08:11 2017 +0200
     8.2 +++ b/UI/ValueConverters.cs	Wed Oct 25 14:21:44 2017 +0200
     8.3 @@ -435,6 +435,45 @@
     8.4      }
     8.5  
     8.6      /// <summary>
     8.7 +    /// Returns true if given parameter is one of the sync modes. Otherwise false
     8.8 +    /// </summary>
     8.9 +    public class IsSyncModeToBoolConverter : IValueConverter
    8.10 +    {
    8.11 +        public object Convert(object value,
    8.12 +                              Type targetType,
    8.13 +                              object parameter,
    8.14 +                              CultureInfo culture)
    8.15 +        {
    8.16 +            bool result = false;
    8.17 +            string val = null;
    8.18 +
    8.19 +            try
    8.20 +            {
    8.21 +                val = Enum.GetName(typeof(HandshakeDialog.HandshakeMode), value);
    8.22 +            }
    8.23 +            catch
    8.24 +            {
    8.25 +                val = null;
    8.26 +            }
    8.27 +
    8.28 +            if ((val != null) &&
    8.29 +                (val.Equals(Enum.GetName(typeof(HandshakeDialog.HandshakeMode), HandshakeDialog.HandshakeMode.SyncTypeA)) ||
    8.30 +                 val.Equals(Enum.GetName(typeof(HandshakeDialog.HandshakeMode), HandshakeDialog.HandshakeMode.SyncTypeB)) ||
    8.31 +                 val.Equals(Enum.GetName(typeof(HandshakeDialog.HandshakeMode), HandshakeDialog.HandshakeMode.SyncTypeC))))
    8.32 +            {
    8.33 +                result = true;
    8.34 +            }
    8.35 +
    8.36 +            return result;
    8.37 +        }
    8.38 +
    8.39 +        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    8.40 +        {
    8.41 +            throw new NotImplementedException();
    8.42 +        }
    8.43 +    }
    8.44 +
    8.45 +    /// <summary>
    8.46      /// Converter to AND several bool values and convert to Visibility.
    8.47      /// </summary>
    8.48      public class MultiBooleanToVisibilityConverter : IMultiValueConverter