UI/FormRegionEncryptionStatus.cs
author Dean Looyengoed
Fri, 15 Jan 2016 21:35:25 +0100
changeset 281 4040d2e488b6
parent 280 dd7ed070e7d0
child 286 e2d89ff44ef0
permissions -rw-r--r--
Add handshake procedure for keys that were previously marked as compromised.
Dean@159
     1
´╗┐using pEpCOMServerAdapterLib;
Dean@159
     2
using System;
vb@133
     3
using System.Collections.Generic;
Dean@159
     4
using System.Diagnostics;
vb@133
     5
using System.Linq;
Dean@159
     6
using System.Runtime.InteropServices;
vb@133
     7
using System.Windows.Forms;
Dean@159
     8
using Color = System.Drawing.Color;
vb@133
     9
using Outlook = Microsoft.Office.Interop.Outlook;
vb@133
    10
vb@133
    11
namespace pEp
vb@133
    12
{
Dean@159
    13
    /// <summary>
Dean@159
    14
    /// Partial class for the encryption status panel that is displayed below every outlook message.
Dean@159
    15
    /// </summary>
Dean@196
    16
    partial class FormRegionEncryptionStatus
vb@133
    17
    {
Dean@244
    18
        private const int SELECTION_LIST_OPEN_THRESHOLD = 1; // Selection list will open if greater or equal to this value
Dean@244
    19
vb@133
    20
        #region Form Region Factory
vb@133
    21
vb@133
    22
        [Microsoft.Office.Tools.Outlook.FormRegionMessageClass(Microsoft.Office.Tools.Outlook.FormRegionMessageClassAttribute.Note)]
Dean@196
    23
        [Microsoft.Office.Tools.Outlook.FormRegionName("pEp.FormRegionEncryptionStatus")]
Dean@196
    24
        public partial class FormRegionEncryptionStatusFactory
vb@133
    25
        {
vb@133
    26
            // Occurs before the form region is initialized.
vb@133
    27
            // To prevent the form region from appearing, set e.Cancel to true.
vb@133
    28
            // Use e.OutlookItem to get a reference to the current Outlook item.
Dean@196
    29
            private void FormRegionEncryptionStatus_FormRegionInitializing(object sender, Microsoft.Office.Tools.Outlook.FormRegionInitializingEventArgs e)
vb@133
    30
            {
vb@133
    31
            }
vb@133
    32
        }
vb@133
    33
vb@133
    34
        #endregion
vb@133
    35
Dean@159
    36
        /* Notes:
Dean@179
    37
         * 
Dean@159
    38
         * Use this.OutlookItem to get a reference to the current Outlook item.
Dean@159
    39
         * Use this.OutlookFormRegion to get a reference to the form region.
Dean@179
    40
         * 
Dean@179
    41
         * UI State Managment:
Dean@179
    42
         * 
Dean@179
    43
         * The UI state is almost entirely set from the associated mail item data.
Dean@179
    44
         * However, a separate state class is maintained to represent the UI as some separation is needed.
Dean@179
    45
         * This logical separation MUST be maintained throughout the code.
Dean@179
    46
         * Specific cases are noted where possible.
Dean@179
    47
         * 
Dean@259
    48
         * The separate encryption status manager form state is also managed here.
Dean@259
    49
         * 
Dean@159
    50
         */
Dean@159
    51
Dean@170
    52
        private CryptableMailItem associatedMailItem = null;
Dean@179
    53
        private bool              refreshOngoing     = false;
Dean@179
    54
        private bool              eventsAreConnected = false;
Dean@170
    55
Dean@259
    56
        private FormManageEncryptionStatus managerForm = null;
Dean@259
    57
Dean@250
    58
        // Data or controls not stored in the UI
Dean@179
    59
        private _pEp_color stateUIColorRating; // WARNING: Do NOT use this directly
vb@133
    60
Dean@159
    61
        /**************************************************************
Dean@159
    62
         * 
Dean@159
    63
         * Methods
Dean@159
    64
         * 
Dean@159
    65
         *************************************************************/
Dean@159
    66
Dean@171
    67
        /// <summary>
Dean@170
    68
        /// Sets the cryptable mail item associated with this encryption status panel.
Dean@170
    69
        /// The associated mail item can then be accessed through its local variable.
Dean@170
    70
        /// </summary>
Dean@170
    71
        private void SetAssociatedMailItem()
Dean@170
    72
        {
Dean@170
    73
            bool errorOccurred = false;
Dean@170
    74
            Outlook.MailItem omi = null;
Dean@170
    75
Dean@170
    76
            // Null check
Dean@170
    77
            if (!errorOccurred)
Dean@170
    78
            {
Dean@170
    79
                try
Dean@170
    80
                {
Dean@170
    81
                    if (this.OutlookItem == null)
Dean@170
    82
                    {
Dean@170
    83
                        errorOccurred = true;
Dean@170
    84
                    }
Dean@170
    85
                }
Dean@170
    86
                catch (COMException)
Dean@170
    87
                {
Dean@170
    88
                    errorOccurred = true;
Dean@170
    89
                }
Dean@170
    90
            }
Dean@170
    91
Dean@170
    92
            // Attempt to get and cast the outlook mail item
Dean@170
    93
            if (!errorOccurred)
Dean@170
    94
            {
Dean@170
    95
                try
Dean@170
    96
                {
Dean@170
    97
                    omi = (Outlook.MailItem)this.OutlookItem;
Dean@170
    98
                }
Dean@170
    99
                catch
Dean@170
   100
                {
Dean@170
   101
                    errorOccurred = true;
Dean@170
   102
                }
Dean@170
   103
            }
Dean@170
   104
Dean@170
   105
            // Finally set the associated mail item
Dean@170
   106
            if ((errorOccurred) ||
Dean@170
   107
                (omi == null))
Dean@170
   108
            {
Dean@170
   109
                this.associatedMailItem = null;
Dean@170
   110
            }
Dean@170
   111
            else
Dean@170
   112
            {
Dean@170
   113
                // Check if the associated mail item has already been set
Dean@170
   114
                if (this.associatedMailItem != null)
Dean@170
   115
                {
Dean@170
   116
                    // Only re-set the mail item if the EntryID has changed
Dean@170
   117
                    if (this.associatedMailItem.EntryID != omi.EntryID)
Dean@170
   118
                    {
Dean@170
   119
                        this.associatedMailItem = new CryptableMailItem(omi);
Dean@170
   120
                    }
Dean@170
   121
                }
Dean@170
   122
                else
Dean@170
   123
                {
Dean@170
   124
                    this.associatedMailItem = new CryptableMailItem(omi);
Dean@170
   125
                }
Dean@170
   126
            }
Dean@170
   127
Dean@170
   128
            return;
Dean@170
   129
        }
Dean@170
   130
Dean@179
   131
        /// <summary>
Dean@281
   132
        /// Completes the handshake process when the identity of a partner was previously marked as compromized.
Dean@281
   133
        /// </summary>
Dean@281
   134
        /// <param name="identityPartner">The identity of the partner to complete the handshake with.</param>
Dean@281
   135
        private void DoHandshakeForCompromisedKey(pEp_identity_s identityPartner)
Dean@281
   136
        {
Dean@281
   137
            DialogResult result;
Dean@281
   138
Dean@281
   139
            result = MessageBox.Show(this.ParentForm,
Dean@281
   140
                                     pEp.Properties.Resources.WarningCompromisedKey,
Dean@281
   141
                                     pEp.Properties.Resources.ConfirmOperationTitle,
Dean@281
   142
                                     MessageBoxButtons.OKCancel);
Dean@281
   143
Dean@281
   144
            if (result == DialogResult.OK)
Dean@281
   145
            {
Dean@281
   146
                this.DoHandshake(identityPartner);
Dean@281
   147
            }
Dean@281
   148
Dean@281
   149
            return;
Dean@281
   150
        }
Dean@281
   151
Dean@281
   152
        /// <summary>
Dean@281
   153
        /// Completes the handshake process where the identity of a partner is confirmed.
Dean@179
   154
        /// </summary>
Dean@179
   155
        /// <param name="identityPartner">The identity of the partner to complete the handshake with.</param>
Dean@179
   156
        private void DoHandshake(pEp_identity_s identityPartner)
vb@133
   157
        {
Dean@155
   158
            string ownShort;
Dean@155
   159
            string ownLong;
Dean@155
   160
            string ownFpr;
Dean@155
   161
            string partnerShort;
Dean@155
   162
            string partnerLong;
Dean@155
   163
            string partnerFpr;
Dean@155
   164
            string[] lines;
Dean@179
   165
            DialogResult result;
Dean@155
   166
            pEp_identity_s me;
Dean@155
   167
            FormHandshake handshakeDialog;
Dean@155
   168
            FormHandshake.State state = new FormHandshake.State();
markus@201
   169
Dean@190
   170
            Globals.ThisAddIn.LogVerbose("doHandshake");
Dean@190
   171
            Globals.ThisAddIn.LogVerbose(identityPartner.address);
vb@139
   172
vb@132
   173
            if (identityPartner.username == "")
vb@133
   174
                identityPartner.username = identityPartner.address;
Dean@190
   175
            Globals.ThisAddIn.LogVerbose(identityPartner.username);
vb@133
   176
dean@144
   177
            identityPartner.user_id = CryptableMailItem.GetUserIDFromAddress(identityPartner.address, identityPartner.username);
Dean@190
   178
            Globals.ThisAddIn.LogVerbose(identityPartner.user_id);
vb@133
   179
Dean@173
   180
            if (this.associatedMailItem.IsIncoming)
vb@133
   181
            {
Dean@173
   182
                string entryID = this.associatedMailItem.ReceivedByEntryID;
vb@133
   183
                string address = "";
vb@133
   184
markus@201
   185
                foreach (Outlook.Account a in Globals.ThisAddIn.Application.Session.Accounts)
markus@201
   186
                {
markus@201
   187
                    if (a.CurrentUser.EntryID == entryID)
markus@201
   188
                    {
vb@133
   189
                        address = a.SmtpAddress;
vb@133
   190
                        break;
vb@133
   191
                    }
vb@133
   192
                }
vb@133
   193
vb@133
   194
                if (address == "")
Dean@190
   195
                    address = Globals.ThisAddIn.Application.Session.Accounts[1].SmtpAddress;
vb@133
   196
Dean@190
   197
                me = Globals.ThisAddIn.mySelf(address);
vb@133
   198
            }
vb@133
   199
            else // outgoing
vb@133
   200
            {
Dean@190
   201
                Globals.ThisAddIn.LogVerbose("mailItem.from_address: " + this.associatedMailItem.FromAddress);
Dean@190
   202
                me = Globals.ThisAddIn.mySelf(this.associatedMailItem.FromAddress);
vb@133
   203
            }
vb@133
   204
Dean@190
   205
            Globals.ThisAddIn.LogVerbose(me.fpr);
vb@139
   206
Dean@155
   207
            ownShort = ThisAddIn.pEp.trustwords(me.fpr, max_words: 5).ToLower();
markus@201
   208
            ownLong = ThisAddIn.pEp.trustwords(me.fpr).ToLower();
markus@201
   209
            ownFpr = this.ToQuadruple(me.fpr);
vb@133
   210
Dean@190
   211
            Globals.ThisAddIn.LogVerbose(identityPartner.fpr);
vb@139
   212
Dean@155
   213
            partnerShort = ThisAddIn.pEp.trustwords(identityPartner.fpr, max_words: 5).ToLower();
markus@201
   214
            partnerLong = ThisAddIn.pEp.trustwords(identityPartner.fpr).ToLower();
markus@201
   215
            partnerFpr = this.ToQuadruple(identityPartner.fpr);
vb@133
   216
Dean@155
   217
            if (ownFpr.CompareTo(partnerFpr) > 0)
vb@133
   218
            {
Dean@155
   219
                state.TrustwordsShort = partnerShort + ownShort;
markus@201
   220
                state.TrustwordsFull = partnerLong + ownLong;
Dean@155
   221
Dean@155
   222
                lines = new string[3];
Dean@155
   223
                lines[0] = pEp.Properties.Resources.TrustwordsPartnershortPartner + partnerFpr;
Dean@155
   224
                lines[2] = pEp.Properties.Resources.TrustwordsPartnershortMyself + ownFpr;
Dean@155
   225
                state.Fingerprint = lines;
vb@133
   226
            }
vb@133
   227
            else
vb@133
   228
            {
Dean@155
   229
                state.TrustwordsShort = ownShort + " " + partnerShort;
markus@201
   230
                state.TrustwordsFull = ownLong + " " + partnerLong;
Dean@155
   231
Dean@155
   232
                lines = new string[3];
Dean@155
   233
                lines[0] = pEp.Properties.Resources.TrustwordsOwnshortMyself + ownFpr;
Dean@155
   234
                lines[2] = pEp.Properties.Resources.TrustwordsOwnshortPartner + partnerFpr;
Dean@155
   235
                state.Fingerprint = lines;
vb@133
   236
            }
vb@133
   237
Dean@190
   238
            Globals.ThisAddIn.LogVerbose("try to show dialog");
vb@139
   239
Dean@155
   240
            // Create and show handshake dialog
Dean@155
   241
            handshakeDialog = new FormHandshake(state);
Dean@179
   242
            handshakeDialog.StartPosition = FormStartPosition.CenterScreen;
Dean@179
   243
            result = handshakeDialog.ShowDialog(this);
Dean@155
   244
Dean@190
   245
            Globals.ThisAddIn.LogVerbose("handshakeDialog.ShowDialog(this) => " + result.ToString());
vb@133
   246
vb@133
   247
            switch (result)
vb@133
   248
            {
vb@133
   249
                case DialogResult.Yes:
Dean@279
   250
                    {
Dean@279
   251
                        identityPartner = ThisAddIn.pEp.update_identity(identityPartner);
Dean@281
   252
Dean@281
   253
                        // Check if key was previously compromized -- warning for this must be displayed earlier
Dean@281
   254
                        if (identityPartner.comm_type == _pEp_comm_type.pEp_ct_compromized)
Dean@281
   255
                        {
Dean@281
   256
                            ThisAddIn.pEp.key_reset_trust(ref identityPartner);
Dean@281
   257
                            identityPartner = ThisAddIn.pEp.update_identity(ref identityPartner);
Dean@281
   258
                        }
Dean@281
   259
Dean@281
   260
                        // Trust the key
Dean@279
   261
                        identityPartner = ThisAddIn.pEp.trust_personal_key(ref identityPartner);
Dean@279
   262
                        identityPartner = ThisAddIn.pEp.update_identity(identityPartner);
Dean@279
   263
Dean@279
   264
                        // Save any manager form data
Dean@279
   265
                        if (this.managerForm != null)
Dean@279
   266
                        {
Dean@279
   267
                            this.SetManagerState(this.managerForm.CopyUIToState());
Dean@279
   268
                        }
Dean@279
   269
Dean@279
   270
                        this.UpdateUIFromMailItem();
Dean@279
   271
Dean@279
   272
                        // Update the manager form state
Dean@279
   273
                        if (this.managerForm != null)
Dean@279
   274
                        {
Dean@279
   275
                            this.managerForm.CopyStateToUI(this.GetManagerState());
Dean@279
   276
                        }
Dean@279
   277
Dean@279
   278
                        break;
Dean@279
   279
                    }
vb@133
   280
                case DialogResult.No:
Dean@279
   281
                    {
Dean@279
   282
                        identityPartner = ThisAddIn.pEp.update_identity(identityPartner);
Dean@279
   283
                        ThisAddIn.pEp.key_compromized(ref identityPartner);
Dean@279
   284
                        identityPartner.comm_type = _pEp_comm_type.pEp_ct_compromized;
Dean@279
   285
                        identityPartner = ThisAddIn.pEp.update_identity(identityPartner);
Dean@279
   286
Dean@279
   287
                        // Save any manager form data
Dean@279
   288
                        if (this.managerForm != null)
Dean@279
   289
                        {
Dean@279
   290
                            this.SetManagerState(this.managerForm.CopyUIToState());
Dean@279
   291
                        }
Dean@279
   292
Dean@279
   293
                        this.UpdateUIFromMailItem();
Dean@279
   294
Dean@279
   295
                        // Update the manager form state
Dean@279
   296
                        if (this.managerForm != null)
Dean@279
   297
                        {
Dean@279
   298
                            this.managerForm.CopyStateToUI(this.GetManagerState());
Dean@279
   299
                        }
Dean@279
   300
Dean@279
   301
                        break;
Dean@279
   302
                    }
vb@133
   303
            }
Dean@279
   304
Dean@279
   305
            return;
vb@133
   306
        }
vb@133
   307
Dean@179
   308
        /// <summary>
Dean@179
   309
        /// Reverses any past handshake confirmation by unconfirming the given identity partner.
Dean@179
   310
        /// </summary>
Dean@179
   311
        /// <param name="identityPartner">The identity of the partner to unconfirm.</param>
Dean@179
   312
        private void UndoHandshake(pEp_identity_s identityPartner)
vb@133
   313
        {
Dean@279
   314
            identityPartner = ThisAddIn.pEp.update_identity(identityPartner);
Dean@280
   315
            ThisAddIn.pEp.key_reset_trust(ref identityPartner);
Dean@279
   316
            identityPartner = ThisAddIn.pEp.update_identity(identityPartner);
Dean@279
   317
Dean@279
   318
            // Save any manager form data
Dean@279
   319
            if (this.managerForm != null)
Dean@279
   320
            {
Dean@279
   321
                this.SetManagerState(this.managerForm.CopyUIToState());
Dean@279
   322
            }
markus@201
   323
Dean@179
   324
            this.UpdateUIFromMailItem();
Dean@279
   325
Dean@279
   326
            // Update the manager form state
Dean@279
   327
            if (this.managerForm != null)
Dean@279
   328
            {
Dean@279
   329
                this.managerForm.CopyStateToUI(this.GetManagerState());
Dean@279
   330
            }
Dean@279
   331
Dean@279
   332
            return;
vb@133
   333
        }
vb@133
   334
Dean@161
   335
        /// <summary>
Dean@161
   336
        /// Formats the given text string as separated 4-character groups.
Dean@161
   337
        /// Example: 49422235FC99585B891C --> 4942 2235 FC99 585B 891C
Dean@161
   338
        /// </summary>
Dean@161
   339
        /// <param name="text">The text to format in 4-character groups.</param>
Dean@161
   340
        /// <returns>The re-formatted string.</returns>
Dean@161
   341
        private string ToQuadruple(string text)
Dean@159
   342
        {
Dean@159
   343
            List<string> result = new List<string>();
Dean@159
   344
Dean@161
   345
            if (text != null)
Dean@159
   346
            {
Dean@161
   347
                for (int i = 0; i < text.Length; i += 4)
Dean@159
   348
                {
Dean@161
   349
                    try
Dean@161
   350
                    {
Dean@161
   351
                        result.Add(text.Substring(i, 4));
Dean@161
   352
                    }
Dean@161
   353
                    catch (ArgumentOutOfRangeException)
Dean@161
   354
                    {
Dean@161
   355
                        result.Add(text.Substring(i));
Dean@161
   356
                        break;
Dean@161
   357
                    }
Dean@159
   358
                }
Dean@159
   359
            }
Dean@159
   360
Dean@159
   361
            return String.Join(" ", result);
Dean@159
   362
        }
markus@201
   363
Dean@196
   364
        /// <summary>
Dean@196
   365
        /// Makes the unencrypted preview form.
Dean@196
   366
        /// This gets the active form region then fills it's content.
Dean@196
   367
        /// </summary>
Dean@198
   368
        /// <returns>True if successful, otherwise false.</returns>
Dean@198
   369
        private bool MakePreview()
Dean@159
   370
        {
Dean@198
   371
            bool success = true;
Dean@198
   372
            bool isSuccessful;
Dean@198
   373
            byte[] rtfBody;
Dean@198
   374
            string subject;
Dean@159
   375
            WindowFormRegionCollection formRegions;
markus@201
   376
Dean@198
   377
            formRegions = Globals.FormRegions[Globals.ThisAddIn.Application.ActiveExplorer()];
Dean@159
   378
Dean@198
   379
            if ((formRegions != null) &&
Dean@198
   380
                (formRegions.FormRegionPreviewUnencrypted != null) &&
Dean@198
   381
                (formRegions.FormRegionPreviewUnencrypted.Visible))
Dean@198
   382
            {
Dean@198
   383
                // Attempt to the the RTF body
Dean@198
   384
                isSuccessful = this.associatedMailItem.MirrorTryGetRTFBody(out rtfBody);
Dean@198
   385
                if (isSuccessful == false)
Dean@198
   386
                {
Dean@198
   387
                    return (false);
Dean@198
   388
                }
Dean@159
   389
Dean@198
   390
                // Attempt to get the subject
Dean@198
   391
                isSuccessful = this.associatedMailItem.MirrorTryGetSubject(out subject);
Dean@198
   392
                if (isSuccessful == false)
Dean@159
   393
                {
Dean@198
   394
                    return (false);
Dean@159
   395
                }
Dean@196
   396
Dean@198
   397
                // Add data to the form
markus@201
   398
                formRegions.FormRegionPreviewUnencrypted.RichTextBoxPreview.Rtf = System.Text.Encoding.ASCII.GetString(rtfBody, 0, rtfBody.Length);
markus@201
   399
                formRegions.FormRegionPreviewUnencrypted.TextBoxSubject.Text = subject;
markus@201
   400
                formRegions.FormRegionPreviewUnencrypted.TextBoxFrom.Text = this.associatedMailItem.FromUsername + " <" + this.associatedMailItem.FromAddress + ">";
Dean@198
   401
            }
Dean@198
   402
            else
Dean@198
   403
            {
Dean@198
   404
                success = false;
Dean@198
   405
            }
Dean@198
   406
Dean@198
   407
            return (success);
Dean@159
   408
        }
markus@201
   409
Dean@179
   410
        /// <summary>
Dean@279
   411
        /// Copies any necessary data from the given manager form state back into this encryption status/mail item current state.
Dean@259
   412
        /// </summary>
Dean@279
   413
        /// <param name="state">The state to copy data from.</param>
Dean@279
   414
        private void SetManagerState(FormManageEncryptionStatus.State state)
Dean@259
   415
        {
Dean@279
   416
            if (state != null)
Dean@279
   417
            {
Dean@279
   418
                // Save send unencrypted
Dean@279
   419
                if (state.IsIncoming == false)
Dean@279
   420
                {
Dean@279
   421
                    switch (state.SendUnencrypted)
Dean@279
   422
                    {
Dean@279
   423
                        case CheckState.Checked:
Dean@279
   424
                            {
Dean@279
   425
                                // Set the mail item to checked
Dean@279
   426
                                this.associatedMailItem.SendUnencrypted = CheckState.Checked;
Dean@279
   427
                                break;
Dean@279
   428
                            }
Dean@279
   429
                        case CheckState.Unchecked:
Dean@279
   430
                            {
Dean@279
   431
                                // Set the mail item to unchecked ONLY if it was previously checked
Dean@279
   432
                                // This is necessary because the UI will default to unchecked if interminate
Dean@279
   433
                                if (this.associatedMailItem.SendUnencrypted == CheckState.Checked)
Dean@279
   434
                                {
Dean@279
   435
                                    this.associatedMailItem.SendUnencrypted = CheckState.Unchecked;
Dean@279
   436
                                }
Dean@279
   437
                                break;
Dean@279
   438
                            }
Dean@279
   439
                        case CheckState.Indeterminate:
Dean@279
   440
                            {
Dean@279
   441
                                // Set the mail item to indeterminate
Dean@279
   442
                                this.associatedMailItem.SendUnencrypted = CheckState.Indeterminate;
Dean@279
   443
                                break;
Dean@279
   444
                            }
Dean@279
   445
                    }
Dean@279
   446
Dean@279
   447
                    this.UpdateUIFromMailItem();
Dean@279
   448
                }
Dean@279
   449
            }
Dean@279
   450
Dean@279
   451
            return;
Dean@279
   452
        }
Dean@279
   453
Dean@279
   454
        /// <summary>
Dean@279
   455
        /// Builds a new manager form state using this encryption state/mail item current state.
Dean@279
   456
        /// </summary>
Dean@279
   457
        /// <returns>A new manager form state.</returns>
Dean@279
   458
        private FormManageEncryptionStatus.State GetManagerState()
Dean@279
   459
        {
Dean@259
   460
            pEp_identity_s[] identities;
Dean@259
   461
            pEp_identity_s incomingIdent;
Dean@259
   462
            pEp_identity_s identityPartner;
Dean@259
   463
            _pEp_color identityPartnerColor;
Dean@259
   464
            SelectionItem item;
Dean@279
   465
            EncryptionState state = this.CopyUIToState();
Dean@279
   466
            FormManageEncryptionStatus.State managerState = new FormManageEncryptionStatus.State();
Dean@259
   467
Dean@279
   468
            managerState.VisualState = state.Copy();
Dean@279
   469
            managerState.SendUnencrypted = this.associatedMailItem.SendUnencrypted;
Dean@279
   470
            managerState.IsIncoming = this.associatedMailItem.IsIncoming;
Dean@279
   471
            managerState.EncryptionStatusReason = this.BuildEncryptionStatusReason(state.EncryptionStatus);
Dean@259
   472
Dean@259
   473
            if (this.associatedMailItem.IsIncoming)
Dean@259
   474
            {
Dean@259
   475
                identities = new pEp_identity_s[1];
Dean@259
   476
Dean@259
   477
                // Add only one identity
Dean@259
   478
                incomingIdent = new pEp_identity_s();
Dean@259
   479
                incomingIdent.address = this.associatedMailItem.FromAddress;
Dean@259
   480
                incomingIdent.username = this.associatedMailItem.FromUsername;
Dean@259
   481
                incomingIdent.user_id = CryptableMailItem.GetUserIDFromAddress(incomingIdent.address, incomingIdent.username);
Dean@259
   482
Dean@259
   483
                identities[0] = incomingIdent;
Dean@259
   484
            }
Dean@259
   485
            else
Dean@259
   486
            {
Dean@259
   487
                identities = this.associatedMailItem.Addresses;
Dean@259
   488
            }
Dean@259
   489
Dean@279
   490
            // Add identities
Dean@279
   491
            managerState.Identities.Clear();
Dean@259
   492
            foreach (pEp_identity_s ident in identities)
Dean@259
   493
            {
Dean@259
   494
                identityPartner = ThisAddIn.pEp.update_identity(ident);
Dean@259
   495
                identityPartnerColor = ThisAddIn.pEp.identity_color(identityPartner);
Dean@259
   496
Dean@259
   497
                item = new SelectionItem();
Dean@259
   498
                item.TextLine1 = identityPartner.username;
Dean@259
   499
                item.TextLine2 = identityPartner.address;
Dean@259
   500
Dean@259
   501
                // Set image
Dean@259
   502
                switch (identityPartnerColor)
Dean@259
   503
                {
Dean@259
   504
                    case _pEp_color.pEp_rating_trusted:
Dean@259
   505
                    case _pEp_color.pEp_rating_trusted_and_anonymized:
Dean@259
   506
                        item.ItemImage = pEp.Properties.Resources.green;
Dean@259
   507
                        break;
Dean@259
   508
                    case _pEp_color.pEp_rating_reliable:
Dean@259
   509
                        item.ItemImage = pEp.Properties.Resources.yellow;
Dean@259
   510
                        break;
Dean@259
   511
                    case _pEp_color.pEp_rating_under_attack:
Dean@259
   512
                        item.ItemImage = pEp.Properties.Resources.red;
Dean@259
   513
                        break;
Dean@259
   514
                    default:
Dean@259
   515
                        item.ItemImage = null;
Dean@259
   516
                        break;
Dean@259
   517
                }
Dean@259
   518
Dean@259
   519
                // Set button
Dean@259
   520
                if (identityPartner.comm_type >= _pEp_comm_type.pEp_ct_confirmed_encryption)
Dean@259
   521
                {
Dean@259
   522
                    // Undo handshake
Dean@277
   523
                    item.TextButton = pEp.Properties.Resources.StopTrusting;
Dean@259
   524
                    item.IsButtonVisible = true;
Dean@259
   525
                    item.OnClick = (x, y) => { this.UndoHandshake(ident); };
Dean@259
   526
                }
Dean@259
   527
                else if (identityPartner.comm_type >= _pEp_comm_type.pEp_ct_unconfirmed_encryption &&
Dean@259
   528
                         identityPartner.comm_type < _pEp_comm_type.pEp_ct_confirmed_encryption)
Dean@259
   529
                {
Dean@259
   530
                    // Do handshake
Dean@277
   531
                    item.TextButton = pEp.Properties.Resources.Handshake;
Dean@259
   532
                    item.IsButtonVisible = true;
Dean@259
   533
                    item.OnClick = (x, y) => { this.DoHandshake(identityPartner); };
Dean@259
   534
                }
Dean@281
   535
                else if (identityPartner.comm_type == _pEp_comm_type.pEp_ct_compromized)
Dean@281
   536
                {
Dean@281
   537
                    // Redo handshake with confirmation
Dean@281
   538
                    item.TextButton = pEp.Properties.Resources.Handshake;
Dean@281
   539
                    item.IsButtonVisible = true;
Dean@281
   540
                    item.OnClick = (x, y) => { this.DoHandshakeForCompromisedKey(identityPartner); };
Dean@281
   541
                }
Dean@259
   542
                else
Dean@259
   543
                {
Dean@259
   544
                    // No button, just view
Dean@259
   545
                    item.IsButtonVisible = false;
Dean@259
   546
                }
Dean@259
   547
Dean@279
   548
                managerState.Identities.Add(item);
Dean@259
   549
            }
Dean@259
   550
Dean@279
   551
            return (managerState);
Dean@279
   552
        }
Dean@279
   553
Dean@279
   554
        /// <summary>
Dean@279
   555
        /// Builds the latest state of the encryption status manager then shows the UI.
Dean@279
   556
        /// </summary>
Dean@279
   557
        private void BuildAndShowManager()
Dean@279
   558
        {
Dean@279
   559
            DialogResult result;
Dean@279
   560
            FormManageEncryptionStatus form;
Dean@279
   561
            FormManageEncryptionStatus.State stateOut;
Dean@279
   562
Dean@259
   563
            // Show the form
Dean@259
   564
            form = new FormManageEncryptionStatus();
Dean@259
   565
            form.StartPosition = FormStartPosition.CenterScreen;
Dean@259
   566
Dean@259
   567
            this.managerForm = form;
Dean@279
   568
            result = form.ShowDialog(this.ParentForm, this.GetManagerState(), out stateOut); // Must show as dialog to block code
Dean@259
   569
Dean@259
   570
            if (result == DialogResult.OK)
Dean@259
   571
            {
Dean@279
   572
                this.SetManagerState(stateOut);
Dean@259
   573
            }
Dean@259
   574
Dean@259
   575
            return;
Dean@259
   576
        }
Dean@259
   577
Dean@259
   578
        /// <summary>
Dean@259
   579
        /// Builds the reason string for the given color rating of the associated mail item.
Dean@259
   580
        /// </summary>
Dean@259
   581
        /// <param name="colorRating">The encryption status color rating to get the reason for.</param>
Dean@259
   582
        /// <returns>The encryption status reason string or null.</returns>
Dean@259
   583
        private string BuildEncryptionStatusReason(_pEp_color colorRating)
Dean@259
   584
        {
Dean@259
   585
            string reason = null;
Dean@259
   586
            string keyinfo;
Dean@259
   587
            string[] keys;
Dean@259
   588
Dean@259
   589
            switch (colorRating)
Dean@259
   590
            {
Dean@259
   591
                case (_pEp_color.pEp_rating_green):
Dean@259
   592
                    {
Dean@266
   593
                        // Add all keys the message is encrypted with
Dean@266
   594
                        try
Dean@266
   595
                        {
Dean@266
   596
                            keys = this.associatedMailItem.Keylist;
Dean@259
   597
Dean@266
   598
                            if (keys.Length > 0)
Dean@266
   599
                            {
Dean@266
   600
                                if (keys.Length > 1)
Dean@266
   601
                                {
Dean@266
   602
                                    reason = String.Format(pEp.Properties.Resources.EncryptionStatusClickMessageMultiple + " {0}.",
Dean@266
   603
                                                           String.Join(", ", keys));
Dean@266
   604
                                }
Dean@266
   605
                                else
Dean@266
   606
                                {
Dean@266
   607
                                    reason = String.Format(pEp.Properties.Resources.EncryptionStatusClickMessageSingle + " {0}.",
Dean@266
   608
                                                           keys[0]);
Dean@266
   609
                                }
Dean@266
   610
                            }
Dean@266
   611
                        }
Dean@266
   612
                        catch (Exception) { }
Dean@266
   613
                        break;
Dean@266
   614
                    }
Dean@266
   615
                case (_pEp_color.pEp_rating_yellow):
Dean@266
   616
                    {
Dean@266
   617
                        // Reason is empty -- a handshake dialog will be shown
Dean@266
   618
                        break;
Dean@266
   619
                    }
Dean@266
   620
                case (_pEp_color.pEp_rating_unencrypted):
Dean@266
   621
                    {
Dean@266
   622
                        if (this.associatedMailItem.IsIncoming)
Dean@259
   623
                        {
Dean@266
   624
                            reason = pEp.Properties.Resources.RatingUnencryptedMessageboxReasonBody;
Dean@266
   625
                        }
Dean@266
   626
                        else
Dean@266
   627
                        {
Dean@266
   628
                            if (this.associatedMailItem.SendUnencrypted == CheckState.Checked)
Dean@259
   629
                            {
Dean@277
   630
                                reason = pEp.Properties.Resources.RatingUnencryptedMessageboxReasonBody2;
Dean@259
   631
                            }
Dean@259
   632
                            else
Dean@259
   633
                            {
Dean@266
   634
                                // Add all identity comm types
Dean@266
   635
                                try
Dean@266
   636
                                {
Dean@266
   637
                                    reason = "";
Dean@266
   638
                                    foreach (pEp_identity_s identity in this.associatedMailItem.Addresses)
Dean@266
   639
                                    {
Dean@266
   640
                                        if (identity.comm_type < _pEp_comm_type.pEp_ct_security_by_obscurity)
Dean@266
   641
                                        {
Dean@266
   642
                                            if (reason != "")
Dean@266
   643
                                            {
Dean@266
   644
                                                reason += "\n";
Dean@266
   645
                                            }
Dean@266
   646
Dean@266
   647
                                            // TODO: reason string in English language only and trivial
Dean@266
   648
                                            string ct = identity.comm_type.ToString();
Dean@266
   649
                                            ct = new string(ct.Skip(7).ToArray());
Dean@266
   650
                                            ct = ct.Replace("_", " ");
Dean@266
   651
                                            reason += identity.username + " <" + identity.address + ">: " + ct;
Dean@266
   652
                                        }
Dean@266
   653
                                    }
Dean@266
   654
                                }
Dean@266
   655
                                catch (COMException) { }
Dean@259
   656
                            }
Dean@259
   657
                        }
Dean@266
   658
                        break;
Dean@259
   659
                    }
Dean@259
   660
                case (_pEp_color.pEp_rating_cannot_decrypt):
Dean@259
   661
                case (_pEp_color.pEp_rating_have_no_key):
Dean@259
   662
                    {
Dean@266
   663
                        try
Dean@266
   664
                        {
Dean@266
   665
                            keys = this.associatedMailItem.Keylist;
Dean@259
   666
Dean@266
   667
                            if (keys.Length > 1)
Dean@259
   668
                            {
Dean@266
   669
                                if (keys.Length == 2)
Dean@266
   670
                                {
Dean@266
   671
                                    reason = pEp.Properties.Resources.RatingHavenokeyMessageboxReasonBodyNokey;
Dean@266
   672
                                }
Dean@266
   673
                                else
Dean@266
   674
                                {
Dean@266
   675
                                    reason = string.Format(pEp.Properties.Resources.RatingHavenokeyMessageboxReasonBodySomekey,
Dean@266
   676
                                                           keys.Length - 1);
Dean@266
   677
                                }
Dean@266
   678
Dean@266
   679
                                // Add each key
Dean@266
   680
                                keyinfo = "";
Dean@266
   681
                                foreach (string key in keys)
Dean@266
   682
                                {
Dean@266
   683
                                    if (key.Length >= 8)
Dean@266
   684
                                        keyinfo += "\n" + key;
Dean@266
   685
                                }
Dean@266
   686
Dean@266
   687
                                reason += keyinfo;
Dean@266
   688
                            }
Dean@266
   689
                            else if (keys.Length == 1)
Dean@266
   690
                            {
Dean@266
   691
                                reason = pEp.Properties.Resources.RatingHavenokeyMessageboxReasonError + keys[0];
Dean@259
   692
                            }
Dean@259
   693
                            else
Dean@259
   694
                            {
Dean@266
   695
                                reason = pEp.Properties.Resources.RatingHavenokeyMessageboxReasonUnknownformat;
Dean@259
   696
                            }
Dean@266
   697
                        }
Dean@266
   698
                        catch (COMException) { }
Dean@259
   699
Dean@266
   700
                        break;
Dean@259
   701
                    }
Dean@259
   702
                default:
Dean@266
   703
                    {
Dean@266
   704
                        // No reason
Dean@266
   705
                        break;
Dean@266
   706
                    }
Dean@259
   707
            }
Dean@259
   708
Dean@259
   709
            return (reason);
Dean@259
   710
        }
Dean@259
   711
Dean@259
   712
        /// <summary>
Dean@179
   713
        /// Updates the status of the UI state based on the associated mail item.
Dean@179
   714
        /// Any previous state changes in the UI are preserved.
Dean@179
   715
        /// </summary>
Dean@179
   716
        private void UpdateUIFromMailItem()
Dean@159
   717
        {
Dean@266
   718
            EncryptionState state;
Dean@159
   719
Dean@173
   720
            if (this.associatedMailItem != null)
Dean@159
   721
            {
Dean@179
   722
                if (this.associatedMailItem.SendUnencrypted == CheckState.Checked)
Dean@159
   723
                {
Dean@179
   724
                    // Always set to unencrypted
Dean@266
   725
                    state = new EncryptionState(_pEp_color.pEp_rating_unencrypted);
Dean@159
   726
                }
Dean@159
   727
                else
Dean@159
   728
                {
Dean@266
   729
                    state = new EncryptionState(this.associatedMailItem.ColorRating);
Dean@159
   730
                }
Dean@179
   731
Dean@179
   732
                this.CopyStateToUI(state);
Dean@159
   733
            }
Dean@159
   734
Dean@179
   735
            return;
Dean@159
   736
        }
Dean@159
   737
Dean@172
   738
        #region StateMethods
Dean@172
   739
Dean@172
   740
        /// <summary>
Dean@172
   741
        /// Connects or disconnects all control events from the UI.
Dean@172
   742
        /// </summary>
Dean@172
   743
        /// <param name="connect">True to connect events, false to disconnect.</param>
Dean@172
   744
        private void ConnectEvents(bool connect)
Dean@172
   745
        {
Dean@172
   746
            // Connect events only if not already connected
markus@201
   747
            if ((connect == true) &&
Dean@172
   748
                (this.eventsAreConnected == false))
Dean@172
   749
            {
markus@201
   750
                this.ButtonEncryptionStatus.Click += this.ButtonEncryptionStatus_Click;
markus@201
   751
                this.ButtonEncryptionStatus.MouseUp += this.ButtonEncryptionStatus_MouseUp;
Dean@179
   752
                this.LinkLabelExplanation.LinkClicked += this.LinkLabelExplanation_LinkClicked;
Dean@179
   753
markus@201
   754
                this.PictureBoxOptions.Click += this.PictureBoxOptions_Click;
Dean@179
   755
                this.PictureBoxOptions.MouseHover += this.PictureBoxOptions_MouseHover;
Dean@179
   756
Dean@172
   757
                this.eventsAreConnected = true;
Dean@172
   758
            }
Dean@172
   759
            // Always attempt to disconnect
Dean@172
   760
            else if (connect == false)
Dean@172
   761
            {
markus@201
   762
                this.ButtonEncryptionStatus.Click -= this.ButtonEncryptionStatus_Click;
markus@201
   763
                this.ButtonEncryptionStatus.MouseUp -= this.ButtonEncryptionStatus_MouseUp;
Dean@179
   764
                this.LinkLabelExplanation.LinkClicked -= this.LinkLabelExplanation_LinkClicked;
Dean@179
   765
markus@201
   766
                this.PictureBoxOptions.Click -= this.PictureBoxOptions_Click;
Dean@179
   767
                this.PictureBoxOptions.MouseHover -= this.PictureBoxOptions_MouseHover;
Dean@179
   768
Dean@172
   769
                this.eventsAreConnected = false;
Dean@172
   770
            }
Dean@172
   771
Dean@172
   772
            return;
Dean@172
   773
        }
Dean@172
   774
Dean@172
   775
        /// <summary>
Dean@172
   776
        /// Refreshes the UI by reloading the state.
Dean@172
   777
        /// </summary>
Dean@172
   778
        private void RefreshUI()
Dean@172
   779
        {
Dean@172
   780
            this.CopyStateToUI(this.CopyUIToState());
Dean@172
   781
            return;
Dean@172
   782
        }
Dean@172
   783
Dean@172
   784
        /// <summary>
Dean@172
   785
        /// Copies the given state to the UI.
Dean@172
   786
        /// Events are turned off until the process is complete.
Dean@172
   787
        /// </summary>
Dean@172
   788
        /// <param name="state">The state to set to the UI.</param>
Dean@266
   789
        private void CopyStateToUI(EncryptionState state)
Dean@172
   790
        {
Dean@172
   791
            this.ConnectEvents(false);
markus@201
   792
Dean@172
   793
            ///////////////////////////////////////////////////////////
Dean@172
   794
            // Set UI data
Dean@172
   795
            ///////////////////////////////////////////////////////////
Dean@172
   796
Dean@179
   797
            // Save UI state maintained outside of controls
Dean@259
   798
            this.stateUIColorRating = state.EncryptionStatus;
Dean@179
   799
Dean@259
   800
            this.ButtonEncryptionStatus.BackColor = state.BackgroundColor;
Dean@259
   801
            this.ButtonEncryptionStatus.ForeColor = state.ForegroundColor;
Dean@259
   802
            this.ButtonEncryptionStatus.Text = state.ShortText;
Dean@259
   803
            this.LinkLabelExplanation.Text = state.LongText;
Dean@172
   804
Dean@172
   805
            this.ConnectEvents(true);
Dean@172
   806
Dean@172
   807
            return;
Dean@172
   808
        }
Dean@172
   809
Dean@172
   810
        /// <summary>
Dean@172
   811
        /// Copies the UI to a new state.
Dean@172
   812
        /// </summary>
Dean@172
   813
        /// <returns>The state of the UI.</returns>
Dean@266
   814
        private EncryptionState CopyUIToState()
Dean@172
   815
        {
Dean@266
   816
            return (new EncryptionState(this.stateUIColorRating));
Dean@172
   817
        }
Dean@172
   818
Dean@172
   819
        #endregion
Dean@172
   820
Dean@159
   821
        /**************************************************************
Dean@159
   822
         * 
Dean@159
   823
         * Event Handling
Dean@159
   824
         * 
Dean@159
   825
         *************************************************************/
Dean@159
   826
Dean@159
   827
        /// <summary>
Dean@159
   828
        /// Event handler that is called before the form region is displayed.
Dean@159
   829
        /// </summary>
Dean@196
   830
        private void FormRegionEncryptionStatus_FormRegionShowing(object sender, System.EventArgs e)
Dean@159
   831
        {
Dean@173
   832
            this.SetAssociatedMailItem();
Dean@173
   833
Dean@199
   834
            // Connect cryptable mail item events
Dean@189
   835
            if (this.associatedMailItem != null)
Dean@159
   836
            {
Dean@159
   837
                try
Dean@159
   838
                {
Dean@189
   839
                    this.associatedMailItem.PropertyChange += MailItem_PropertyChange;
Dean@179
   840
Dean@189
   841
                    if (this.associatedMailItem.IsInEncryptedStore &&
Dean@198
   842
                        this.associatedMailItem.IsPGPEncrypted)
Dean@159
   843
                    {
Dean@189
   844
                        this.associatedMailItem.Open += MailItem_Open;
Dean@159
   845
                    }
Dean@159
   846
                }
Dean@159
   847
                catch { }
Dean@179
   848
            }
Dean@159
   849
Dean@179
   850
            // Set the default UI state
Dean@266
   851
            this.CopyStateToUI(new EncryptionState());
Dean@179
   852
Dean@199
   853
            // Call the timer tick method manually to refresh data
Dean@199
   854
            this.TimerRefresh_Tick(null, new EventArgs());
Dean@179
   855
Dean@179
   856
            return;
Dean@159
   857
        }
Dean@159
   858
Dean@159
   859
        /// <summary>
Dean@159
   860
        /// Event handler for when the form region is closed.
Dean@159
   861
        /// </summary>
Dean@196
   862
        private void FormRegionEncryptionStatus_FormRegionClosed(object sender, System.EventArgs e)
Dean@159
   863
        {
Dean@199
   864
            // Disconnect cryptable mail item events
Dean@190
   865
            if (this.associatedMailItem != null)
Dean@179
   866
            {
Dean@179
   867
                try
Dean@179
   868
                {
Dean@190
   869
                    this.associatedMailItem.PropertyChange -= MailItem_PropertyChange;
markus@201
   870
                    this.associatedMailItem.Open -= MailItem_Open;
Dean@179
   871
                }
Dean@179
   872
                catch { }
Dean@179
   873
            }
Dean@179
   874
Dean@179
   875
            return;
Dean@179
   876
        }
Dean@179
   877
Dean@179
   878
        /// <summary>
Dean@179
   879
        /// Event handler called after the refresh timer has elapsed.
Dean@179
   880
        /// </summary>
Dean@179
   881
        private void TimerRefresh_Tick(object sender, EventArgs e)
Dean@179
   882
        {
Dean@199
   883
            bool tryAgain = false;
Dean@199
   884
            bool isSuccessful;
Dean@179
   885
            this.TimerRefresh.Enabled = false; // Only once
markus@201
   886
Dean@179
   887
            // Ensure the tick method is not called more than once
Dean@179
   888
            if (refreshOngoing == false)
Dean@179
   889
            {
Dean@179
   890
                this.refreshOngoing = true;
Dean@179
   891
Dean@179
   892
                if (this.associatedMailItem != null)
Dean@179
   893
                {
Dean@179
   894
                    if (this.associatedMailItem.DownloadState == Outlook.OlDownloadState.olFullItem)
Dean@179
   895
                    {
Dean@179
   896
                        this.UpdateUIFromMailItem();
Dean@199
   897
Dean@199
   898
                        /* Create the unencrypted preview if the mail item is encrypted and
Dean@199
   899
                         * it is in an encrypted (untrusted) store
Dean@199
   900
                         * 
Dean@199
   901
                         * This is done here because FormRegionEncryptionStatus has the cryptable mail item and
Dean@199
   902
                         * it also is initialized after FormRegionPreviewUnencrypted.
Dean@199
   903
                         */
Dean@199
   904
                        if (this.associatedMailItem.IsInEncryptedStore &&
Dean@199
   905
                            this.associatedMailItem.IsPGPEncrypted)
Dean@199
   906
                        {
Dean@199
   907
                            isSuccessful = this.MakePreview();
Dean@199
   908
Dean@199
   909
                            if (isSuccessful == false)
Dean@199
   910
                            {
Dean@199
   911
                                tryAgain = true;
Dean@199
   912
                            }
Dean@199
   913
                        }
Dean@179
   914
                    }
Dean@179
   915
                    else
Dean@179
   916
                    {
Dean@179
   917
                        this.associatedMailItem.MarkForDownload = Outlook.OlRemoteStatus.olMarkedForDownload;
Dean@199
   918
                        tryAgain = true;
Dean@179
   919
                    }
Dean@179
   920
                }
Dean@179
   921
Dean@199
   922
                // Set the timer to refresh again later automatically
Dean@199
   923
                if (tryAgain)
Dean@199
   924
                {
Dean@199
   925
                    this.TimerRefresh.Interval = 100;
Dean@199
   926
                    this.TimerRefresh.Enabled = true;
Dean@199
   927
                }
Dean@199
   928
Dean@179
   929
                this.refreshOngoing = false;
Dean@179
   930
            }
Dean@175
   931
Dean@159
   932
            return;
Dean@159
   933
        }
Dean@159
   934
Dean@169
   935
        /// <summary>
Dean@169
   936
        /// Event handler for when a mail item is being opened in an inspector.
Dean@180
   937
        /// See: https://msdn.microsoft.com/en-us/library/office/ff865989.aspx
Dean@169
   938
        /// </summary>
Dean@169
   939
        /// <param name="cancel">Whether to cancel the event: Value is False when the event occurs. 
Dean@169
   940
        /// If the event procedure sets this argument to True, the open operation is not completed 
Dean@169
   941
        /// and the inspector is not displayed.</param>
Dean@169
   942
        private void MailItem_Open(ref bool cancel)
Dean@159
   943
        {
Dean@173
   944
            if (this.associatedMailItem != null && this.associatedMailItem.MirrorDisplay())
Dean@169
   945
            {
Dean@169
   946
                cancel = true;
Dean@169
   947
            }
Dean@169
   948
Dean@169
   949
            return;
Dean@159
   950
        }
Dean@159
   951
Dean@169
   952
        /// <summary>
Dean@169
   953
        /// Event handler for when a mail item property is changed.
Dean@169
   954
        /// See: https://msdn.microsoft.com/en-us/library/office/ff866739.aspx
Dean@169
   955
        /// </summary>
Dean@169
   956
        /// <param name="propertyName">The name of the property that was changed.</param>
Dean@169
   957
        private void MailItem_PropertyChange(string propertyName)
Dean@159
   958
        {
Dean@179
   959
            switch (propertyName.ToUpper())
Dean@159
   960
            {
Dean@179
   961
                case "TO":
Dean@179
   962
                    // Start the refresh timer
Dean@179
   963
                    this.TimerRefresh.Enabled = true;
Dean@159
   964
                    break;
Dean@159
   965
                // Outlook bug: there are always both events, so one is enough
Dean@159
   966
                //case "CC":
Dean@179
   967
                //    // Start the refresh timer
Dean@179
   968
                //    this.TimerRefresh.Enabled = true;
Dean@159
   969
                //    break;
Dean@159
   970
            }
Dean@169
   971
Dean@169
   972
            return;
Dean@159
   973
        }
Dean@159
   974
Dean@179
   975
        /// <summary>
Dean@179
   976
        /// Event handler for when the encryption status button is clicked.
Dean@179
   977
        /// </summary>
Dean@178
   978
        private void ButtonEncryptionStatus_Click(object sender, EventArgs e)
vb@133
   979
        {
Dean@179
   980
            string reason;
Dean@266
   981
            EncryptionState state = this.CopyUIToState();
Dean@250
   982
            pEp_identity_s identityPartner;
Dean@250
   983
            List<pEp_identity_s> partnersToCheck;
markus@201
   984
Dean@259
   985
            switch (state.EncryptionStatus)
vb@133
   986
            {
vb@133
   987
                case _pEp_color.pEp_rating_yellow:
vb@133
   988
                    {
Dean@266
   989
                        try
vb@133
   990
                        {
Dean@266
   991
                            // Incoming
Dean@266
   992
                            if (this.associatedMailItem.IsIncoming)
Dean@266
   993
                            {
Dean@266
   994
                                identityPartner = new pEp_identity_s();
Dean@266
   995
                                identityPartner.address = this.associatedMailItem.FromAddress;
Dean@266
   996
                                identityPartner.username = this.associatedMailItem.FromUsername;
Dean@266
   997
                                identityPartner.user_id = CryptableMailItem.GetUserIDFromAddress(identityPartner.address, identityPartner.username);
vb@139
   998
vb@133
   999
                                try
vb@133
  1000
                                {
Dean@266
  1001
                                    identityPartner = ThisAddIn.pEp.update_identity(identityPartner);
Dean@266
  1002
                                }
Dean@266
  1003
                                catch
Dean@266
  1004
                                {
Dean@266
  1005
                                    state = new EncryptionState(_pEp_color.pEp_rating_undefined);
Dean@266
  1006
                                    this.CopyStateToUI(state);
Dean@266
  1007
                                    return;
Dean@266
  1008
                                }
Dean@259
  1009
Dean@266
  1010
                                this.DoHandshake(identityPartner);
Dean@266
  1011
                            }
Dean@266
  1012
                            // Outgoing
Dean@266
  1013
                            else
Dean@266
  1014
                            {
Dean@266
  1015
                                // Build list of handshake partners
Dean@266
  1016
                                partnersToCheck = new List<pEp_identity_s>();
Dean@266
  1017
                                foreach (pEp_identity_s identity in this.associatedMailItem.Addresses)
Dean@266
  1018
                                {
Dean@266
  1019
                                    try
vb@133
  1020
                                    {
Dean@266
  1021
                                        identityPartner = ThisAddIn.pEp.update_identity(identity);
Dean@266
  1022
Dean@266
  1023
                                        if (identityPartner.comm_type >= _pEp_comm_type.pEp_ct_unconfirmed_encryption &&
Dean@266
  1024
                                            identityPartner.comm_type < _pEp_comm_type.pEp_ct_confirmed_encryption)
Dean@266
  1025
                                        {
Dean@266
  1026
                                            partnersToCheck.Add(identityPartner);
Dean@266
  1027
                                        }
vb@133
  1028
                                    }
Dean@266
  1029
                                    catch { }
vb@133
  1030
                                }
vb@133
  1031
Dean@266
  1032
                                if (partnersToCheck.Count == 0)
Dean@266
  1033
                                {
Dean@266
  1034
                                    state = new EncryptionState(_pEp_color.pEp_rating_undefined);
Dean@266
  1035
                                    this.CopyStateToUI(state);
Dean@266
  1036
                                    return;
Dean@266
  1037
                                }
Dean@266
  1038
                                else if (partnersToCheck.Count == 1)
Dean@266
  1039
                                {
Dean@266
  1040
                                    this.DoHandshake(partnersToCheck[0]);
Dean@266
  1041
                                }
Dean@266
  1042
                                else if (partnersToCheck.Count > 1)
Dean@266
  1043
                                {
Dean@266
  1044
                                    this.BuildAndShowManager();
Dean@266
  1045
                                }
vb@133
  1046
                            }
vb@133
  1047
                        }
Dean@266
  1048
                        catch (COMException) { }
Dean@266
  1049
                        catch (Exception) { }
Dean@266
  1050
                        break;
vb@133
  1051
                    }
Dean@259
  1052
                default:
Dean@266
  1053
                    {
Dean@266
  1054
                        reason = this.BuildEncryptionStatusReason(state.EncryptionStatus);
Dean@259
  1055
Dean@266
  1056
                        if ((reason != null) &&
Dean@266
  1057
                            (reason != ""))
Dean@266
  1058
                        {
Dean@266
  1059
                            MessageBox.Show(reason, "",
Dean@266
  1060
                                            MessageBoxButtons.OK,
Dean@266
  1061
                                            MessageBoxIcon.Information);
Dean@266
  1062
                        }
Dean@266
  1063
                        break;
vb@133
  1064
                    }
vb@133
  1065
            }
Dean@179
  1066
Dean@179
  1067
            return;
vb@133
  1068
        }
vb@133
  1069
Dean@179
  1070
        /// <summary>
Dean@179
  1071
        /// Event handler for when a mouse button is released over the encryption status button.
Dean@179
  1072
        /// </summary>
Dean@179
  1073
        private void ButtonEncryptionStatus_MouseUp(object sender, MouseEventArgs e)
vb@133
  1074
        {
Dean@179
  1075
            if ((sender != null) &&
Dean@179
  1076
                (e.Button == System.Windows.Forms.MouseButtons.Right))
markus@201
  1077
            {
Dean@259
  1078
                this.BuildAndShowManager();
vb@133
  1079
            }
Dean@179
  1080
Dean@179
  1081
            return;
vb@133
  1082
        }
vb@133
  1083
Dean@179
  1084
        /// <summary>
Dean@179
  1085
        /// Event handler for when the explanation link label is clicked.
Dean@179
  1086
        /// </summary>
Dean@179
  1087
        private void LinkLabelExplanation_LinkClicked(object sender, System.Windows.Forms.LinkLabelLinkClickedEventArgs e)
Dean@179
  1088
        {
Dean@259
  1089
            this.BuildAndShowManager();
Dean@179
  1090
            return;
vb@133
  1091
        }
Dean@151
  1092
Dean@151
  1093
        /// <summary>
Dean@151
  1094
        /// Event handler for when the options picture box is clicked.
Dean@151
  1095
        /// This will open the options form for user editing.
Dean@151
  1096
        /// </summary>
Dean@151
  1097
        private void PictureBoxOptions_Click(object sender, EventArgs e)
Dean@151
  1098
        {
Dean@159
  1099
            DialogResult result;
Dean@203
  1100
            FormOptions frm;
Dean@203
  1101
            FormOptions.State stateIn;
Dean@203
  1102
            FormOptions.State stateOut;
Dean@203
  1103
Dean@203
  1104
            // Build form and state
Dean@203
  1105
            frm = new FormOptions();
Dean@154
  1106
            frm.StartPosition = FormStartPosition.CenterScreen;
Dean@203
  1107
            stateIn = Globals.ThisAddIn.GetOptionsState();
Dean@203
  1108
Dean@203
  1109
            result = frm.ShowDialog(this.ParentForm, stateIn, out stateOut); // Must show as dialog to block code
Dean@203
  1110
Dean@203
  1111
            if (result == DialogResult.OK)
Dean@203
  1112
            {
Dean@203
  1113
                Globals.ThisAddIn.SetOptionsState(stateOut);
Dean@203
  1114
            }
Dean@151
  1115
Dean@151
  1116
            return;
Dean@151
  1117
        }
Dean@151
  1118
Dean@151
  1119
        /// <summary>
Dean@151
  1120
        /// Event handler for when the mouse hovers over the options picture box.
Dean@151
  1121
        /// This is a work-around to show a tool tip.
Dean@151
  1122
        /// </summary>
Dean@151
  1123
        private void PictureBoxOptions_MouseHover(object sender, EventArgs e)
Dean@151
  1124
        {
Dean@151
  1125
            ToolTip toolTip = new ToolTip();
Dean@277
  1126
            toolTip.SetToolTip(this.PictureBoxOptions, pEp.Properties.Resources.ToolTipOptions);
Dean@151
  1127
            return;
Dean@151
  1128
        }
vb@133
  1129
    }
vb@133
  1130
}