UI/FormRegionPrivacyStatus.cs
author Dean Looyengoed
Thu, 17 Mar 2016 19:44:57 +0100
changeset 682 f6025a3d4062
parent 680 c3c99a2d9403
child 683 21bad2819cf8
permissions -rw-r--r--
Shutdown the refresh timer on form region close AND item Send event.
Shutting down the timer on send is necessary at the mail item properties can't be
accessed during sending (Such as downloadState) because the mail item is being moved.
This avoids some crashes.
Dean@159
     1
´╗┐using pEpCOMServerAdapterLib;
Dean@159
     2
using System;
vb@133
     3
using System.Collections.Generic;
Dean@445
     4
using System.ComponentModel;
Dean@438
     5
using System.Drawing;
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@312
    14
    /// Partial class for the privacy status form region that is displayed below every outlook message.
Dean@159
    15
    /// </summary>
Dean@312
    16
    partial class FormRegionPrivacyStatus
vb@133
    17
    {
vb@133
    18
        #region Form Region Factory
vb@133
    19
vb@133
    20
        [Microsoft.Office.Tools.Outlook.FormRegionMessageClass(Microsoft.Office.Tools.Outlook.FormRegionMessageClassAttribute.Note)]
Dean@312
    21
        [Microsoft.Office.Tools.Outlook.FormRegionName("pEp.FormRegionPrivacyStatus")]
Dean@312
    22
        public partial class FormRegionPrivacyStatusFactory
vb@133
    23
        {
vb@133
    24
            // Occurs before the form region is initialized.
vb@133
    25
            // To prevent the form region from appearing, set e.Cancel to true.
vb@133
    26
            // Use e.OutlookItem to get a reference to the current Outlook item.
Dean@312
    27
            private void FormRegionPrivacyStatus_FormRegionInitializing(object sender, Microsoft.Office.Tools.Outlook.FormRegionInitializingEventArgs e)
vb@133
    28
            {
Dean@327
    29
                WindowFormRegionCollection formRegions;
Dean@327
    30
Dean@327
    31
                /* There is a Microsoft bug at least in Outlook 2013 and Windows 8.1
Dean@327
    32
                 * This bug causes multiple PrivacyStatus form regions to appear stacked on top of each other.
Dean@327
    33
                 * To trigger this bug, on an unencrypted server, click reply to compose an in-line response.
Dean@327
    34
                 * Then click to another tab such as People or Tasks. Then click back on the mail tab to view 
Dean@327
    35
                 * the original email again. Two form regions will be visible: 
Dean@327
    36
                 * (1) for the status during the in-line reply and 
Dean@327
    37
                 * (2) for the status of only the received message.
Dean@327
    38
                 * 
Dean@327
    39
                 * To fix this bug, any existing form regions are found and closed when initializing a new privacy status
Dean@327
    40
                 * form region.
Dean@327
    41
                 */
Dean@327
    42
Dean@327
    43
                try
Dean@327
    44
                {
Dean@327
    45
                    formRegions = Globals.FormRegions[Globals.ThisAddIn.Application.ActiveExplorer()];
Dean@327
    46
                    if (formRegions.FormRegionPrivacyStatus != null)
Dean@327
    47
                    {
Dean@327
    48
                        /* Note: there seems to be no way to actually close the form region.
Dean@327
    49
                         * Therefore, this is as close as possible to actually closing it.
Dean@327
    50
                         * The actual form regions will be cleaned up as soon as another email is selected.
Dean@327
    51
                         */
Dean@327
    52
                        formRegions.FormRegionPrivacyStatus.OutlookFormRegion.Visible = false;
Dean@327
    53
                    }
Dean@327
    54
                }
Dean@327
    55
                catch { }
Dean@327
    56
Dean@327
    57
                return;
vb@133
    58
            }
vb@133
    59
        }
vb@133
    60
vb@133
    61
        #endregion
vb@133
    62
Dean@159
    63
        /* Notes:
Dean@179
    64
         * 
Dean@159
    65
         * Use this.OutlookItem to get a reference to the current Outlook item.
Dean@159
    66
         * Use this.OutlookFormRegion to get a reference to the form region.
Dean@179
    67
         * 
Dean@179
    68
         * UI State Managment:
Dean@179
    69
         * 
Dean@179
    70
         * The UI state is almost entirely set from the associated mail item data.
Dean@179
    71
         * However, a separate state class is maintained to represent the UI as some separation is needed.
Dean@179
    72
         * This logical separation MUST be maintained throughout the code.
Dean@179
    73
         * Specific cases are noted where possible.
Dean@179
    74
         * 
Dean@356
    75
         * The separate privacy status manager form state is also managed here.
Dean@259
    76
         * 
Dean@159
    77
         */
Dean@159
    78
Dean@680
    79
        private CryptableMailItem       associatedMailItem = null;
Dean@680
    80
        private bool                    eventsAreConnected = false;
Dean@680
    81
        private bool                    initialized        = false;
Dean@680
    82
        private FormManagePrivacyStatus managerForm        = null;
Dean@680
    83
        private bool                    refreshOngoing     = false;
Dean@259
    84
Dean@250
    85
        // Data or controls not stored in the UI
Dean@179
    86
        private _pEp_color stateUIColorRating; // WARNING: Do NOT use this directly
vb@133
    87
Dean@159
    88
        /**************************************************************
Dean@159
    89
         * 
Dean@159
    90
         * Methods
Dean@159
    91
         * 
Dean@159
    92
         *************************************************************/
Dean@159
    93
Dean@171
    94
        /// <summary>
Dean@438
    95
        /// Determines if this form region is running in an inspector window.
Dean@438
    96
        /// If not true, it is assumed to be within an explorer window.
Dean@438
    97
        /// </summary>
Dean@438
    98
        /// <returns>True if an inspector window, false if within an explorer.</returns>
Dean@438
    99
        private bool IsWithinInspector()
Dean@438
   100
        {
Dean@438
   101
            bool isWithinInspector = false;
Dean@438
   102
            Outlook.Explorer temp = null;
Dean@438
   103
Dean@438
   104
            try
Dean@438
   105
            {
Dean@438
   106
                // Just try to cast to an explorer class
Dean@438
   107
                temp = (Outlook.Explorer)this.OutlookFormRegion.Parent;
Dean@438
   108
                isWithinInspector = false;
Dean@438
   109
            }
Dean@438
   110
            catch
Dean@438
   111
            {
Dean@438
   112
                isWithinInspector = true;
Dean@438
   113
            }
Dean@438
   114
            finally
Dean@438
   115
            {
Dean@438
   116
                if (temp != null)
Dean@438
   117
                {
Dean@438
   118
                    Marshal.ReleaseComObject(temp);
Dean@438
   119
                    temp = null;
Dean@438
   120
                }
Dean@438
   121
            }
Dean@438
   122
Dean@438
   123
            return (isWithinInspector);
Dean@438
   124
        }
Dean@438
   125
Dean@438
   126
        /// <summary>
Dean@170
   127
        /// Sets the cryptable mail item associated with this encryption status panel.
Dean@170
   128
        /// The associated mail item can then be accessed through its local variable.
Dean@170
   129
        /// </summary>
Dean@170
   130
        private void SetAssociatedMailItem()
Dean@170
   131
        {
Dean@170
   132
            bool errorOccurred = false;
Dean@170
   133
            Outlook.MailItem omi = null;
Dean@170
   134
Dean@170
   135
            // Null check
Dean@170
   136
            if (!errorOccurred)
Dean@170
   137
            {
Dean@170
   138
                try
Dean@170
   139
                {
Dean@170
   140
                    if (this.OutlookItem == null)
Dean@170
   141
                    {
Dean@170
   142
                        errorOccurred = true;
Dean@170
   143
                    }
Dean@170
   144
                }
Dean@170
   145
                catch (COMException)
Dean@170
   146
                {
Dean@170
   147
                    errorOccurred = true;
Dean@170
   148
                }
Dean@170
   149
            }
Dean@170
   150
Dean@170
   151
            // Attempt to get and cast the outlook mail item
Dean@170
   152
            if (!errorOccurred)
Dean@170
   153
            {
Dean@170
   154
                try
Dean@170
   155
                {
Dean@170
   156
                    omi = (Outlook.MailItem)this.OutlookItem;
Dean@170
   157
                }
Dean@170
   158
                catch
Dean@170
   159
                {
Dean@170
   160
                    errorOccurred = true;
Dean@170
   161
                }
Dean@170
   162
            }
Dean@170
   163
Dean@170
   164
            // Finally set the associated mail item
Dean@170
   165
            if ((errorOccurred) ||
Dean@170
   166
                (omi == null))
Dean@170
   167
            {
Dean@170
   168
                this.associatedMailItem = null;
Dean@170
   169
            }
Dean@170
   170
            else
Dean@170
   171
            {
Dean@170
   172
                // Check if the associated mail item has already been set
Dean@170
   173
                if (this.associatedMailItem != null)
Dean@170
   174
                {
Dean@170
   175
                    // Only re-set the mail item if the EntryID has changed
Dean@170
   176
                    if (this.associatedMailItem.EntryID != omi.EntryID)
Dean@170
   177
                    {
Dean@170
   178
                        this.associatedMailItem = new CryptableMailItem(omi);
Dean@170
   179
                    }
Dean@170
   180
                }
Dean@170
   181
                else
Dean@170
   182
                {
Dean@170
   183
                    this.associatedMailItem = new CryptableMailItem(omi);
Dean@170
   184
                }
Dean@170
   185
            }
Dean@170
   186
Dean@170
   187
            return;
Dean@170
   188
        }
Dean@170
   189
Dean@179
   190
        /// <summary>
Dean@672
   191
        /// Completes the handshake process when the identity of a partner was previously marked as mistrusted.
Dean@281
   192
        /// </summary>
Dean@646
   193
        /// <param name="myself">The personal identity to complete the handshake with.</param>
Dean@646
   194
        /// <param name="partner">The identity of the partner to complete the handshake with.</param>
Dean@672
   195
        private void DoHandshakeForMistrustedKey(PEPIdentity myself,
Dean@672
   196
                                                 PEPIdentity partner)
Dean@281
   197
        {
Dean@281
   198
            DialogResult result;
Dean@281
   199
Dean@281
   200
            result = MessageBox.Show(this.ParentForm,
Dean@672
   201
                                     pEp.Properties.Resources.Message_WarningMistrustedKey,
Dean@378
   202
                                     pEp.Properties.Resources.Message_TitleConfirmOperation,
Dean@423
   203
                                     MessageBoxButtons.YesNo);
Dean@281
   204
Dean@423
   205
            if (result == DialogResult.Yes)
Dean@281
   206
            {
Dean@646
   207
                this.DoHandshake(myself, partner);
Dean@281
   208
            }
Dean@281
   209
Dean@281
   210
            return;
Dean@281
   211
        }
Dean@281
   212
Dean@281
   213
        /// <summary>
Dean@281
   214
        /// Completes the handshake process where the identity of a partner is confirmed.
Dean@179
   215
        /// </summary>
Dean@646
   216
        /// <param name="myself">The personal identity to complete the handshake with.</param>
Dean@646
   217
        /// <param name="partner">The identity of the partner to complete the handshake with.</param>
Dean@646
   218
        private void DoHandshake(PEPIdentity myself,
Dean@646
   219
                                 PEPIdentity partner)
vb@133
   220
        {
Dean@155
   221
            string ownFpr;
Dean@155
   222
            string partnerFpr;
Dean@363
   223
            string trustwordsShort;
Dean@363
   224
            string trustwordsFull;
Dean@155
   225
            string[] lines;
Dean@179
   226
            DialogResult result;
Dean@155
   227
            FormHandshake handshakeDialog;
Dean@155
   228
            FormHandshake.State state = new FormHandshake.State();
markus@201
   229
Dean@660
   230
            Global.AddToLog("DoHandshake: handshake started.");
vb@139
   231
Dean@363
   232
            // Process identities
Dean@646
   233
            if (partner.Username == "")
Dean@363
   234
            {
Dean@646
   235
                partner.Username = partner.Address;
vb@133
   236
            }
Dean@646
   237
            partner.UserID = Globals.ThisAddIn.GetUserID(partner.Address);
Dean@363
   238
Dean@363
   239
            // Calculate and add trustwords
Dean@646
   240
            this.CalcTrustwords(myself, partner, out trustwordsShort, out trustwordsFull);
Dean@646
   241
            state.Myself = myself.Copy();
Dean@646
   242
            state.Partner = partner.Copy();
Dean@363
   243
            state.TrustwordsShort = trustwordsShort;
Dean@363
   244
            state.TrustwordsFull = trustwordsFull;
Dean@363
   245
Dean@363
   246
            // Calculate and add fingerprint
Dean@646
   247
            ownFpr = this.ToQuadruple(myself.Fingerprint);
Dean@646
   248
            partnerFpr = this.ToQuadruple(partner.Fingerprint);
vb@133
   249
Dean@646
   250
            if (myself.Fingerprint.CompareTo(partner.Fingerprint) > 0)
vb@133
   251
            {
Dean@155
   252
                lines = new string[3];
Dean@378
   253
                lines[0] = pEp.Properties.Resources.PrivacyStatus_TrustwordsPartnerShortPartner + partnerFpr;
Dean@378
   254
                lines[2] = pEp.Properties.Resources.PrivacyStatus_TrustwordsPartnerShortMyself + ownFpr;
Dean@155
   255
                state.Fingerprint = lines;
vb@133
   256
            }
vb@133
   257
            else
vb@133
   258
            {
Dean@155
   259
                lines = new string[3];
Dean@378
   260
                lines[0] = pEp.Properties.Resources.PrivacyStatus_TrustwordsOwnShortMyself + ownFpr;
Dean@378
   261
                lines[2] = pEp.Properties.Resources.PrivacyStatus_TrustwordsOwnShortPartner + partnerFpr;
Dean@155
   262
                state.Fingerprint = lines;
vb@133
   263
            }
vb@133
   264
Dean@155
   265
            // Create and show handshake dialog
Dean@155
   266
            handshakeDialog = new FormHandshake(state);
Dean@179
   267
            handshakeDialog.StartPosition = FormStartPosition.CenterScreen;
Dean@179
   268
            result = handshakeDialog.ShowDialog(this);
Dean@155
   269
Dean@646
   270
            this.ProcessDoHandshakeResult(result, partner);
Dean@356
   271
Dean@356
   272
            return;
Dean@356
   273
        }
Dean@356
   274
Dean@356
   275
        /// <summary>
Dean@356
   276
        /// Processes the result of the do handshake dialog after a user makes a selection.
Dean@356
   277
        /// </summary>
Dean@356
   278
        /// <param name="result">The result of the handshake dialog selection.</param>
Dean@356
   279
        /// <param name="partner">The identity of the partner to handshake with.</param>
Dean@356
   280
        private void ProcessDoHandshakeResult(DialogResult result,
Dean@384
   281
                                              PEPIdentity partner)
Dean@356
   282
        {
Dean@384
   283
            pEp_identity_s identityPartner = ThisAddIn.pEp.update_identity(partner.ToCOMType());
vb@133
   284
vb@133
   285
            switch (result)
vb@133
   286
            {
vb@133
   287
                case DialogResult.Yes:
Dean@279
   288
                    {
Dean@672
   289
                        // Check if key was previously mistrusted -- warning to user must be displayed earlier
Dean@672
   290
                        if (identityPartner.comm_type == _pEp_comm_type.pEp_ct_mistrusted)
Dean@281
   291
                        {
Dean@281
   292
                            ThisAddIn.pEp.key_reset_trust(ref identityPartner);
Dean@281
   293
                        }
Dean@281
   294
Dean@279
   295
                        identityPartner = ThisAddIn.pEp.trust_personal_key(ref identityPartner);
Dean@279
   296
Dean@279
   297
                        this.UpdateUIFromMailItem();
Dean@279
   298
Dean@279
   299
                        // Update the manager form state
Dean@279
   300
                        if (this.managerForm != null)
Dean@279
   301
                        {
Dean@279
   302
                            this.managerForm.CopyStateToUI(this.GetManagerState());
Dean@279
   303
                        }
Dean@279
   304
Dean@279
   305
                        break;
Dean@279
   306
                    }
vb@133
   307
                case DialogResult.No:
Dean@279
   308
                    {
Dean@279
   309
                        ThisAddIn.pEp.key_compromized(ref identityPartner);
Dean@279
   310
Dean@279
   311
                        this.UpdateUIFromMailItem();
Dean@279
   312
Dean@279
   313
                        // Update the manager form state
Dean@279
   314
                        if (this.managerForm != null)
Dean@279
   315
                        {
Dean@279
   316
                            this.managerForm.CopyStateToUI(this.GetManagerState());
Dean@279
   317
                        }
Dean@279
   318
Dean@279
   319
                        break;
Dean@279
   320
                    }
vb@133
   321
            }
Dean@279
   322
Dean@279
   323
            return;
vb@133
   324
        }
vb@133
   325
Dean@179
   326
        /// <summary>
Dean@179
   327
        /// Reverses any past handshake confirmation by unconfirming the given identity partner.
Dean@179
   328
        /// </summary>
Dean@384
   329
        /// <param name="partner">The identity of the partner to unconfirm.</param>
Dean@384
   330
        private void UndoHandshake(PEPIdentity partner)
vb@133
   331
        {
Dean@384
   332
            pEp_identity_s identityPartner = ThisAddIn.pEp.update_identity(partner.ToCOMType());
Dean@280
   333
            ThisAddIn.pEp.key_reset_trust(ref identityPartner);
Dean@279
   334
Dean@179
   335
            this.UpdateUIFromMailItem();
Dean@279
   336
Dean@279
   337
            // Update the manager form state
Dean@279
   338
            if (this.managerForm != null)
Dean@279
   339
            {
Dean@279
   340
                this.managerForm.CopyStateToUI(this.GetManagerState());
Dean@279
   341
            }
Dean@279
   342
Dean@279
   343
            return;
vb@133
   344
        }
vb@133
   345
Dean@161
   346
        /// <summary>
Dean@363
   347
        /// Calculates both the short and full trustwords between the given personal identity and the identity partner.
Dean@363
   348
        /// </summary>
Dean@646
   349
        /// <param name="myself">The personal identity.</param>
Dean@646
   350
        /// <param name="partner">The identity of the partner.</param>
Dean@363
   351
        /// <param name="trustwordsShort">The short version of trustwords.</param>
Dean@363
   352
        /// <param name="trustwordsFull">The full/long version of trustwords.</param>
Dean@646
   353
        private void CalcTrustwords(PEPIdentity myself,
Dean@646
   354
                                    PEPIdentity partner,
Dean@363
   355
                                    out string trustwordsShort,
Dean@363
   356
                                    out string trustwordsFull)
Dean@363
   357
        {
Dean@363
   358
            string myShort;
Dean@363
   359
            string myLong;
Dean@363
   360
            string partnerShort;
Dean@363
   361
            string partnerLong;
Dean@363
   362
Dean@674
   363
            myShort = ThisAddIn.pEp.trustwords(myself.Fingerprint, max_words: 5);
Dean@674
   364
            myLong = ThisAddIn.pEp.trustwords(myself.Fingerprint);
Dean@674
   365
            partnerShort = ThisAddIn.pEp.trustwords(partner.Fingerprint, max_words: 5);
Dean@674
   366
            partnerLong = ThisAddIn.pEp.trustwords(partner.Fingerprint);
Dean@363
   367
Dean@646
   368
            if (myself.Fingerprint.CompareTo(partner.Fingerprint) > 0)
Dean@363
   369
            {
Dean@363
   370
                trustwordsShort = partnerShort + myShort;
Dean@363
   371
                trustwordsFull = partnerLong + myLong;
Dean@363
   372
            }
Dean@363
   373
            else
Dean@363
   374
            {
Dean@673
   375
                trustwordsShort = myShort + partnerShort;
Dean@673
   376
                trustwordsFull = myLong + partnerLong;
Dean@363
   377
            }
Dean@363
   378
Dean@363
   379
            return;
Dean@363
   380
        }
Dean@363
   381
Dean@363
   382
        /// <summary>
Dean@161
   383
        /// Formats the given text string as separated 4-character groups.
Dean@161
   384
        /// Example: 49422235FC99585B891C --> 4942 2235 FC99 585B 891C
Dean@161
   385
        /// </summary>
Dean@161
   386
        /// <param name="text">The text to format in 4-character groups.</param>
Dean@161
   387
        /// <returns>The re-formatted string.</returns>
Dean@161
   388
        private string ToQuadruple(string text)
Dean@159
   389
        {
Dean@159
   390
            List<string> result = new List<string>();
Dean@159
   391
Dean@161
   392
            if (text != null)
Dean@159
   393
            {
Dean@161
   394
                for (int i = 0; i < text.Length; i += 4)
Dean@159
   395
                {
Dean@161
   396
                    try
Dean@161
   397
                    {
Dean@161
   398
                        result.Add(text.Substring(i, 4));
Dean@161
   399
                    }
Dean@161
   400
                    catch (ArgumentOutOfRangeException)
Dean@161
   401
                    {
Dean@161
   402
                        result.Add(text.Substring(i));
Dean@161
   403
                        break;
Dean@161
   404
                    }
Dean@159
   405
                }
Dean@159
   406
            }
Dean@159
   407
Dean@159
   408
            return String.Join(" ", result);
Dean@159
   409
        }
markus@201
   410
Dean@196
   411
        /// <summary>
Dean@196
   412
        /// Makes the unencrypted preview form.
Dean@196
   413
        /// This gets the active form region then fills it's content.
Dean@196
   414
        /// </summary>
Dean@198
   415
        /// <returns>True if successful, otherwise false.</returns>
Dean@198
   416
        private bool MakePreview()
Dean@159
   417
        {
Dean@620
   418
            bool success = false;
Dean@198
   419
            bool isSuccessful;
Dean@198
   420
            byte[] rtfBody;
Dean@159
   421
            WindowFormRegionCollection formRegions;
Dean@620
   422
            PEPMessage mirror;
Dean@198
   423
            formRegions = Globals.FormRegions[Globals.ThisAddIn.Application.ActiveExplorer()];
Dean@159
   424
Dean@198
   425
            if ((formRegions != null) &&
Dean@198
   426
                (formRegions.FormRegionPreviewUnencrypted != null) &&
Dean@620
   427
                (formRegions.FormRegionPreviewUnencrypted.Visible))
Dean@198
   428
            {
Dean@620
   429
                formRegions.FormRegionPreviewUnencrypted.ClearMessage();
Dean@620
   430
                mirror = this.associatedMailItem.MirrorGet();
Dean@682
   431
Dean@620
   432
                if (mirror != null)
Dean@198
   433
                {
Dean@620
   434
                    // Attempt to the the RTF body
Dean@620
   435
                    isSuccessful = this.associatedMailItem.MirrorTryGetRTFBody(out rtfBody);
Dean@620
   436
                    if (isSuccessful == false)
Dean@620
   437
                    {
Dean@620
   438
                        return (false);
Dean@620
   439
                    }
Dean@620
   440
Dean@620
   441
                    formRegions.FormRegionPreviewUnencrypted.SetMessage(mirror);
Dean@620
   442
                    formRegions.FormRegionPreviewUnencrypted.SetRTFBody(System.Text.Encoding.ASCII.GetString(rtfBody, 0, rtfBody.Length));
Dean@620
   443
                    success = true;
Dean@198
   444
                }
Dean@198
   445
            }
Dean@198
   446
Dean@198
   447
            return (success);
Dean@159
   448
        }
markus@201
   449
Dean@179
   450
        /// <summary>
Dean@279
   451
        /// Builds a new manager form state using this encryption state/mail item current state.
Dean@279
   452
        /// </summary>
Dean@279
   453
        /// <returns>A new manager form state.</returns>
Dean@313
   454
        private FormManagePrivacyStatus.State GetManagerState()
Dean@279
   455
        {
Dean@527
   456
            bool isMyself;
Dean@664
   457
            bool forceUnencrypted;
Dean@364
   458
            string trustwordsShort;
Dean@364
   459
            string trustwordsFull;
Dean@384
   460
            List<PEPIdentity> identities;
Dean@384
   461
            PEPIdentity myIdentity;
Dean@384
   462
            PEPIdentity incomingIdent;
Dean@527
   463
            PEPIdentity[] myIdentities;
Dean@259
   464
            _pEp_color identityPartnerColor;
Dean@259
   465
            SelectionItem item;
Dean@312
   466
            PrivacyState state = this.CopyUIToState();
Dean@313
   467
            FormManagePrivacyStatus.State managerState = new FormManagePrivacyStatus.State();
Dean@259
   468
Dean@332
   469
            // Resolve all recipients -- this ensures the identities list is correctly populated
Dean@332
   470
            this.associatedMailItem.ResolveAllRecipients();
Dean@332
   471
Dean@279
   472
            managerState.VisualState = state.Copy();
Dean@279
   473
            managerState.IsIncoming = this.associatedMailItem.IsIncoming;
Dean@259
   474
Dean@653
   475
            if (managerState.IsIncoming)
Dean@259
   476
            {
Dean@384
   477
                identities = new List<PEPIdentity>();
Dean@259
   478
Dean@259
   479
                // Add only one identity
Dean@638
   480
                if (this.associatedMailItem.From != null)
Dean@638
   481
                {
Dean@638
   482
                    incomingIdent = new PEPIdentity();
Dean@638
   483
                    incomingIdent.Address = this.associatedMailItem.From.Address;
Dean@638
   484
                    incomingIdent.Username = this.associatedMailItem.From.Username;
Dean@638
   485
                    incomingIdent.UserID = Globals.ThisAddIn.GetUserID(incomingIdent.Address);
Dean@259
   486
Dean@638
   487
                    identities.Add(incomingIdent);
Dean@638
   488
                }
Dean@259
   489
            }
Dean@259
   490
            else
Dean@259
   491
            {
Dean@395
   492
                identities = this.associatedMailItem.Recipients;
Dean@259
   493
            }
Dean@259
   494
Dean@366
   495
            // Get my identity
Dean@633
   496
            myIdentity = this.associatedMailItem.Myself;
Dean@527
   497
            myIdentities = PEPIdentity.GetMyIdentities();
Dean@366
   498
Dean@279
   499
            // Add identities
Dean@394
   500
            identities = PEPIdentity.ToFlatList(identities);
Dean@279
   501
            managerState.Identities.Clear();
Dean@384
   502
            foreach (PEPIdentity ident in identities)
Dean@259
   503
            {
Dean@648
   504
                if (ident.IsValid)
Dean@485
   505
                {
Dean@485
   506
                    pEp_identity_s partnerIdentity_s = ThisAddIn.pEp.update_identity(ident.ToCOMType());
Dean@485
   507
                    PEPIdentity partnerIdentity = new PEPIdentity(partnerIdentity_s);
Dean@485
   508
                    identityPartnerColor = ThisAddIn.pEp.identity_color(partnerIdentity_s);
Dean@664
   509
                    forceUnencrypted = Globals.ThisAddIn.ContactIsForceUnencrypted(partnerIdentity.Address);
Dean@259
   510
Dean@527
   511
                    // Check if identity is myself
Dean@527
   512
                    isMyself = false;
Dean@527
   513
                    foreach (PEPIdentity me in myIdentities)
Dean@527
   514
                    {
Dean@527
   515
                        if (partnerIdentity.EqualsByAddress(me))
Dean@527
   516
                        {
Dean@527
   517
                            isMyself = true;
Dean@527
   518
                            break;
Dean@527
   519
                        }
Dean@527
   520
                    }
Dean@527
   521
Dean@485
   522
                    item = new SelectionItem();
Dean@485
   523
                    item.TextLine1 = partnerIdentity.Username;
Dean@485
   524
                    item.TextLine2 = partnerIdentity.Address;
Dean@259
   525
Dean@485
   526
                    // Don't show both the user name and address if they are the same
Dean@485
   527
                    if ((item.TextLine1 != null) &&
Dean@485
   528
                        (item.TextLine2 != null) &&
Dean@485
   529
                        (item.TextLine1 == item.TextLine2))
Dean@485
   530
                    {
Dean@485
   531
                        item.IsTwoTextLinesVisible = false;
Dean@485
   532
                    }
Dean@332
   533
Dean@527
   534
                    // Calculate trustwords
Dean@527
   535
                    this.CalcTrustwords(myIdentity,
Dean@527
   536
                                        partnerIdentity,
Dean@527
   537
                                        out trustwordsShort,
Dean@527
   538
                                        out trustwordsFull);
Dean@527
   539
Dean@485
   540
                    // Set image
Dean@664
   541
                    if ((forceUnencrypted) &&
Dean@653
   542
                        (managerState.IsIncoming == false))
Dean@485
   543
                    {
Dean@641
   544
                        // Show the force unencrypted image indicating this is set by the user not the engine
Dean@642
   545
                        item.ItemImage = pEp.Properties.Resources.ImageForceUnencOn;
Dean@641
   546
                    }
Dean@641
   547
                    else
Dean@641
   548
                    {
Dean@641
   549
                        switch (PrivacyState.ConvertRatingToPrivacyColor(identityPartnerColor))
Dean@641
   550
                        {
Dean@641
   551
                            case PrivacyState.PrivacyColor.Green:
Dean@641
   552
                                item.ItemImage = pEp.Properties.Resources.ImagePrivacyStatusGreen;
Dean@641
   553
                                break;
Dean@641
   554
                            case PrivacyState.PrivacyColor.Yellow:
Dean@641
   555
                                item.ItemImage = pEp.Properties.Resources.ImagePrivacyStatusYellow;
Dean@641
   556
                                break;
Dean@641
   557
                            case PrivacyState.PrivacyColor.Red:
Dean@641
   558
                                item.ItemImage = pEp.Properties.Resources.ImagePrivacyStatusRed;
Dean@641
   559
                                break;
Dean@641
   560
                            case PrivacyState.PrivacyColor.NoColor:
Dean@641
   561
                                item.ItemImage = pEp.Properties.Resources.ImagePrivacyStatusNoColor;
Dean@641
   562
                                break;
Dean@641
   563
                            default:
Dean@641
   564
                                item.ItemImage = null;
Dean@641
   565
                                break;
Dean@641
   566
                        }
Dean@485
   567
                    }
Dean@259
   568
Dean@485
   569
                    // Set button
Dean@653
   570
                    if ((isMyself) ||
Dean@664
   571
                        ((forceUnencrypted) &&
Dean@653
   572
                         (managerState.IsIncoming == false)))
Dean@653
   573
                    {
Dean@653
   574
                        item.IsButtonVisible = false;
Dean@653
   575
                        item.IsExpandable = false;
Dean@653
   576
                    }
Dean@653
   577
                    else
Dean@366
   578
                    {
Dean@485
   579
                        if (partnerIdentity.CommunicationType >= _pEp_comm_type.pEp_ct_confirmed_encryption)
Dean@485
   580
                        {
Dean@485
   581
                            // Undo handshake
Dean@485
   582
                            item.TextButton = pEp.Properties.Resources.PrivacyStatus_StopTrusting;
Dean@485
   583
                            item.IsButtonVisible = true;
Dean@646
   584
                            item.ButtonOnClick = (x, y) => { this.UndoHandshake(partnerIdentity.Copy()); };
Dean@356
   585
Dean@485
   586
                            item.IsExpandable = false;
Dean@485
   587
                        }
Dean@485
   588
                        else if (partnerIdentity.CommunicationType >= _pEp_comm_type.pEp_ct_unconfirmed_encryption &&
Dean@485
   589
                                 partnerIdentity.CommunicationType < _pEp_comm_type.pEp_ct_confirmed_encryption)
Dean@485
   590
                        {
Dean@485
   591
                            // Do handshake
Dean@485
   592
                            item.TextButton = pEp.Properties.Resources.PrivacyStatus_HandshakeAdvanced;
Dean@485
   593
                            item.IsButtonVisible = true;
Dean@646
   594
                            item.ButtonOnClick = (x, y) => { this.DoHandshake(myIdentity.Copy(), partnerIdentity.Copy()); };
Dean@356
   595
Dean@485
   596
                            item.IsExpandable = true;
Dean@485
   597
                            item.ExpandedText = Properties.Resources.PrivacyStatus_TrustwordDesc + "\n\n" +
Dean@485
   598
                                                trustwordsShort;
Dean@447
   599
Dean@485
   600
                            item.ExpandedButton1Text = Properties.Resources.PrivacyStatus_SelectTrust;
Dean@646
   601
                            item.ExpandedButton1OnClick = (x, y) => { this.ProcessDoHandshakeResult(DialogResult.Yes, partnerIdentity.Copy()); };
Dean@485
   602
                            item.ExpandedButton1BackColor = PrivacyState.COLOR_GREEN;
Dean@485
   603
                            item.ExpandedButton1ForeColor = Color.White;
Dean@447
   604
Dean@485
   605
                            item.ExpandedButton2Text = Properties.Resources.PrivacyStatus_SelectMistrust;
Dean@646
   606
                            item.ExpandedButton2OnClick = (x, y) => { this.ProcessDoHandshakeResult(DialogResult.No, partnerIdentity.Copy()); };
Dean@485
   607
                            item.ExpandedButton2BackColor = PrivacyState.COLOR_RED;
Dean@485
   608
                            item.ExpandedButton2ForeColor = Color.White;
Dean@485
   609
                        }
Dean@672
   610
                        else if (partnerIdentity.CommunicationType == _pEp_comm_type.pEp_ct_mistrusted)
Dean@485
   611
                        {
Dean@485
   612
                            // Redo handshake with confirmation
Dean@485
   613
                            item.TextButton = pEp.Properties.Resources.PrivacyStatus_Handshake;
Dean@485
   614
                            item.IsButtonVisible = true;
Dean@672
   615
                            item.ButtonOnClick = (x, y) => { this.DoHandshakeForMistrustedKey(myIdentity.Copy(), partnerIdentity.Copy()); };
Dean@641
   616
Dean@641
   617
                            item.IsExpandable = false;
Dean@485
   618
                        }
Dean@485
   619
                        else
Dean@485
   620
                        {
Dean@485
   621
                            item.IsButtonVisible = false;
Dean@641
   622
                            item.IsExpandable = false;
Dean@485
   623
                        }
Dean@366
   624
                    }
Dean@281
   625
                }
Dean@485
   626
                else // Invalid identity
Dean@259
   627
                {
Dean@485
   628
                    item = new SelectionItem();
Dean@485
   629
                    item.TextLine1 = ident.Username;
Dean@485
   630
                    item.TextLine2 = ident.Address;
Dean@485
   631
                    item.ItemImage = null;
Dean@485
   632
                    item.IsTwoTextLinesVisible = true;
Dean@259
   633
                    item.IsButtonVisible = false;
Dean@259
   634
                }
Dean@259
   635
Dean@279
   636
                managerState.Identities.Add(item);
Dean@259
   637
            }
Dean@259
   638
Dean@375
   639
            // Attempt to select the first identity requiring a handshake
Dean@375
   640
            for (int i = 0; i < managerState.Identities.Count; i++)
Dean@375
   641
            {
Dean@375
   642
                // Determine if it's a handshake identity by simply seeing if it's expandable
Dean@375
   643
                if (managerState.Identities[i].IsExpandable)
Dean@375
   644
                {
Dean@375
   645
                    managerState.SelectedIdentityIndex = i;
Dean@375
   646
                    break;
Dean@375
   647
                }
Dean@375
   648
            }
Dean@375
   649
Dean@279
   650
            return (managerState);
Dean@279
   651
        }
Dean@279
   652
Dean@279
   653
        /// <summary>
Dean@279
   654
        /// Builds the latest state of the encryption status manager then shows the UI.
Dean@279
   655
        /// </summary>
Dean@279
   656
        private void BuildAndShowManager()
Dean@279
   657
        {
Dean@279
   658
            DialogResult result;
Dean@313
   659
            FormManagePrivacyStatus form;
Dean@313
   660
            FormManagePrivacyStatus.State stateOut;
Dean@279
   661
Dean@483
   662
            try
Dean@483
   663
            {
Dean@483
   664
                // Show the form
Dean@483
   665
                form = new FormManagePrivacyStatus();
Dean@483
   666
                form.StartPosition = FormStartPosition.CenterScreen;
Dean@259
   667
Dean@483
   668
                this.managerForm = form;
Dean@483
   669
                result = form.ShowDialog(this.ParentForm, this.GetManagerState(), out stateOut); // Must show as dialog to block code
Dean@483
   670
            }
Dean@483
   671
            catch (Exception ex)
Dean@483
   672
            {
Dean@660
   673
                Global.StopAndSendCrashReport(ex);
Dean@483
   674
            }
Dean@259
   675
Dean@259
   676
            return;
Dean@259
   677
        }
Dean@259
   678
Dean@259
   679
        /// <summary>
Dean@179
   680
        /// Updates the status of the UI state based on the associated mail item.
Dean@179
   681
        /// Any previous state changes in the UI are preserved.
Dean@179
   682
        /// </summary>
Dean@622
   683
        public void UpdateUIFromMailItem()
Dean@159
   684
        {
Dean@312
   685
            PrivacyState state;
Dean@664
   686
            bool? forceUnencryptedProperty;
Dean@159
   687
Dean@173
   688
            if (this.associatedMailItem != null)
Dean@159
   689
            {
Dean@664
   690
                forceUnencryptedProperty = this.associatedMailItem.ForceUnencrypted;
Dean@342
   691
Dean@664
   692
                if ((forceUnencryptedProperty != null) &&
Dean@664
   693
                    ((bool)forceUnencryptedProperty == true))
Dean@159
   694
                {
Dean@342
   695
                    // Force unencrypted
Dean@312
   696
                    state = new PrivacyState(_pEp_color.pEp_rating_unencrypted);
Dean@680
   697
                    this.CopyStateToUI(state);
Dean@159
   698
                }
Dean@159
   699
                else
Dean@159
   700
                {
Dean@680
   701
                    // Start the color rating calculation/decryption process
Dean@680
   702
                    this.associatedMailItem.StartDecryption();
Dean@159
   703
                }
Dean@159
   704
            }
Dean@159
   705
Dean@179
   706
            return;
Dean@159
   707
        }
Dean@159
   708
Dean@172
   709
        #region StateMethods
Dean@172
   710
Dean@172
   711
        /// <summary>
Dean@172
   712
        /// Connects or disconnects all control events from the UI.
Dean@172
   713
        /// </summary>
Dean@172
   714
        /// <param name="connect">True to connect events, false to disconnect.</param>
Dean@172
   715
        private void ConnectEvents(bool connect)
Dean@172
   716
        {
Dean@172
   717
            // Connect events only if not already connected
markus@201
   718
            if ((connect == true) &&
Dean@172
   719
                (this.eventsAreConnected == false))
Dean@172
   720
            {
Dean@312
   721
                this.ButtonPrivacyStatus.Click += this.ButtonPrivacyStatus_Click;
Dean@312
   722
                this.ButtonPrivacyStatus.MouseUp += this.ButtonPrivacyStatus_MouseUp;
Dean@179
   723
Dean@172
   724
                this.eventsAreConnected = true;
Dean@172
   725
            }
Dean@172
   726
            // Always attempt to disconnect
Dean@172
   727
            else if (connect == false)
Dean@172
   728
            {
Dean@312
   729
                this.ButtonPrivacyStatus.Click -= this.ButtonPrivacyStatus_Click;
Dean@312
   730
                this.ButtonPrivacyStatus.MouseUp -= this.ButtonPrivacyStatus_MouseUp;
Dean@179
   731
Dean@172
   732
                this.eventsAreConnected = false;
Dean@172
   733
            }
Dean@172
   734
Dean@172
   735
            return;
Dean@172
   736
        }
Dean@172
   737
Dean@172
   738
        /// <summary>
Dean@172
   739
        /// Refreshes the UI by reloading the state.
Dean@172
   740
        /// </summary>
Dean@172
   741
        private void RefreshUI()
Dean@172
   742
        {
Dean@172
   743
            this.CopyStateToUI(this.CopyUIToState());
Dean@172
   744
            return;
Dean@172
   745
        }
Dean@172
   746
Dean@172
   747
        /// <summary>
Dean@172
   748
        /// Copies the given state to the UI.
Dean@172
   749
        /// Events are turned off until the process is complete.
Dean@172
   750
        /// </summary>
Dean@172
   751
        /// <param name="state">The state to set to the UI.</param>
Dean@312
   752
        private void CopyStateToUI(PrivacyState state)
Dean@172
   753
        {
Dean@172
   754
            this.ConnectEvents(false);
markus@201
   755
Dean@172
   756
            ///////////////////////////////////////////////////////////
Dean@172
   757
            // Set UI data
Dean@172
   758
            ///////////////////////////////////////////////////////////
Dean@172
   759
Dean@179
   760
            // Save UI state maintained outside of controls
Dean@312
   761
            this.stateUIColorRating = state.PrivacyStatus;
Dean@179
   762
Dean@312
   763
            this.ButtonPrivacyStatus.BackColor = state.BackgroundColor;
Dean@312
   764
            this.ButtonPrivacyStatus.ForeColor = state.ForegroundColor;
Dean@312
   765
            this.ButtonPrivacyStatus.Text = state.ShortText;
Dean@172
   766
Dean@670
   767
            // Update the manager form state
Dean@670
   768
            if (this.managerForm != null)
Dean@670
   769
            {
Dean@670
   770
                this.managerForm.CopyStateToUI(this.GetManagerState());
Dean@670
   771
            }
Dean@670
   772
Dean@172
   773
            this.ConnectEvents(true);
Dean@172
   774
Dean@172
   775
            return;
Dean@172
   776
        }
Dean@172
   777
Dean@172
   778
        /// <summary>
Dean@172
   779
        /// Copies the UI to a new state.
Dean@172
   780
        /// </summary>
Dean@172
   781
        /// <returns>The state of the UI.</returns>
Dean@312
   782
        private PrivacyState CopyUIToState()
Dean@172
   783
        {
Dean@312
   784
            return (new PrivacyState(this.stateUIColorRating));
Dean@172
   785
        }
Dean@172
   786
Dean@172
   787
        #endregion
Dean@172
   788
Dean@159
   789
        /**************************************************************
Dean@159
   790
         * 
Dean@159
   791
         * Event Handling
Dean@159
   792
         * 
Dean@159
   793
         *************************************************************/
Dean@159
   794
Dean@159
   795
        /// <summary>
Dean@680
   796
        /// Event handler that is called when the form region is displayed.
Dean@680
   797
        /// This is called each time the form region looses then regains visiblity 
Dean@680
   798
        /// (for example an other email is selected then back to this one).
Dean@159
   799
        /// </summary>
Dean@312
   800
        private void FormRegionPrivacyStatus_FormRegionShowing(object sender, System.EventArgs e)
Dean@159
   801
        {
Dean@680
   802
            // Do not allow initialization more than once
Dean@680
   803
            if (initialized == false)
Dean@680
   804
            {
Dean@680
   805
                this.SetAssociatedMailItem();
Dean@173
   806
Dean@680
   807
                // Set background color for Office 2013
Dean@159
   808
                try
Dean@159
   809
                {
Dean@680
   810
                    if (Globals.ThisAddIn.Application.Version.Substring(0, 2) == "15")
Dean@159
   811
                    {
Dean@680
   812
                        if (this.IsWithinInspector())
Dean@680
   813
                        {
Dean@680
   814
                            this.BackColor = SystemColors.ButtonFace;
Dean@680
   815
                        }
Dean@680
   816
                        else
Dean@680
   817
                        {
Dean@680
   818
                            this.BackColor = SystemColors.Window;
Dean@680
   819
                        }
Dean@159
   820
                    }
Dean@159
   821
                }
Dean@159
   822
                catch { }
Dean@680
   823
Dean@680
   824
                // Connect cryptable mail item events
Dean@680
   825
                if (this.associatedMailItem != null)
Dean@680
   826
                {
Dean@680
   827
                    try
Dean@680
   828
                    {
Dean@680
   829
                        this.associatedMailItem.PropertyChanged += MailItem_PropertyChanged;
Dean@680
   830
                        this.associatedMailItem.DecryptionComplete += MailItem_DecryptionComplete;
Dean@682
   831
                        this.associatedMailItem.Send += MailItem_Send;
Dean@680
   832
Dean@680
   833
                        if (this.associatedMailItem.IsInEncryptedStore &&
Dean@680
   834
                            this.associatedMailItem.IsPGPEncrypted)
Dean@680
   835
                        {
Dean@680
   836
                            this.associatedMailItem.Open += MailItem_Open;
Dean@680
   837
                        }
Dean@680
   838
                    }
Dean@680
   839
                    catch { }
Dean@680
   840
                }
Dean@680
   841
Dean@680
   842
                // Set the default UI state
Dean@680
   843
                this.CopyStateToUI(new PrivacyState());
Dean@680
   844
Dean@680
   845
                this.initialized = true;
Dean@179
   846
            }
Dean@159
   847
Dean@199
   848
            // Call the timer tick method manually to refresh data
Dean@199
   849
            this.TimerRefresh_Tick(null, new EventArgs());
Dean@179
   850
Dean@179
   851
            return;
Dean@159
   852
        }
Dean@159
   853
Dean@159
   854
        /// <summary>
Dean@159
   855
        /// Event handler for when the form region is closed.
Dean@159
   856
        /// </summary>
Dean@312
   857
        private void FormRegionPrivacyStatus_FormRegionClosed(object sender, System.EventArgs e)
Dean@159
   858
        {
Dean@199
   859
            // Disconnect cryptable mail item events
Dean@190
   860
            if (this.associatedMailItem != null)
Dean@179
   861
            {
Dean@179
   862
                try
Dean@179
   863
                {
Dean@445
   864
                    this.associatedMailItem.PropertyChanged -= MailItem_PropertyChanged;
Dean@680
   865
                    this.associatedMailItem.DecryptionComplete -= MailItem_DecryptionComplete;
markus@201
   866
                    this.associatedMailItem.Open -= MailItem_Open;
Dean@682
   867
                    this.associatedMailItem.Send -= MailItem_Send;
Dean@179
   868
                }
Dean@179
   869
                catch { }
Dean@179
   870
            }
Dean@179
   871
Dean@682
   872
            // Stop and disconnect the refresh timer
Dean@682
   873
            this.TimerRefresh.Stop();
Dean@682
   874
            this.TimerRefresh.Enabled = false;
Dean@682
   875
            this.TimerRefresh.Tick -= TimerRefresh_Tick;
Dean@682
   876
Dean@179
   877
            return;
Dean@179
   878
        }
Dean@179
   879
Dean@179
   880
        /// <summary>
Dean@179
   881
        /// Event handler called after the refresh timer has elapsed.
Dean@179
   882
        /// </summary>
Dean@179
   883
        private void TimerRefresh_Tick(object sender, EventArgs e)
Dean@179
   884
        {
Dean@199
   885
            bool tryAgain = false;
Dean@199
   886
            bool isSuccessful;
Dean@179
   887
            this.TimerRefresh.Enabled = false; // Only once
markus@201
   888
Dean@179
   889
            // Ensure the tick method is not called more than once
Dean@179
   890
            if (refreshOngoing == false)
Dean@179
   891
            {
Dean@179
   892
                this.refreshOngoing = true;
Dean@179
   893
Dean@179
   894
                if (this.associatedMailItem != null)
Dean@179
   895
                {
Dean@179
   896
                    if (this.associatedMailItem.DownloadState == Outlook.OlDownloadState.olFullItem)
Dean@179
   897
                    {
Dean@179
   898
                        this.UpdateUIFromMailItem();
Dean@199
   899
Dean@199
   900
                        /* Create the unencrypted preview if the mail item is encrypted and
Dean@199
   901
                         * it is in an encrypted (untrusted) store
Dean@199
   902
                         * 
Dean@312
   903
                         * This is done here because FormRegionPrivacyStatus has the cryptable mail item and
Dean@199
   904
                         * it also is initialized after FormRegionPreviewUnencrypted.
Dean@199
   905
                         */
Dean@199
   906
                        if (this.associatedMailItem.IsInEncryptedStore &&
Dean@199
   907
                            this.associatedMailItem.IsPGPEncrypted)
Dean@199
   908
                        {
Dean@199
   909
                            isSuccessful = this.MakePreview();
Dean@199
   910
Dean@534
   911
                            // Disable try again as it never seems to recover in real-world testing
Dean@534
   912
                            /*if (isSuccessful == false)
Dean@199
   913
                            {
Dean@199
   914
                                tryAgain = true;
Dean@534
   915
                            }*/
Dean@199
   916
                        }
Dean@179
   917
                    }
Dean@179
   918
                    else
Dean@179
   919
                    {
Dean@179
   920
                        this.associatedMailItem.MarkForDownload = Outlook.OlRemoteStatus.olMarkedForDownload;
Dean@199
   921
                        tryAgain = true;
Dean@179
   922
                    }
Dean@179
   923
                }
Dean@179
   924
Dean@199
   925
                // Set the timer to refresh again later automatically
Dean@199
   926
                if (tryAgain)
Dean@199
   927
                {
Dean@199
   928
                    this.TimerRefresh.Interval = 100;
Dean@199
   929
                    this.TimerRefresh.Enabled = true;
Dean@199
   930
                }
Dean@199
   931
Dean@179
   932
                this.refreshOngoing = false;
Dean@179
   933
            }
Dean@175
   934
Dean@159
   935
            return;
Dean@159
   936
        }
Dean@159
   937
Dean@169
   938
        /// <summary>
Dean@680
   939
        /// Event handler for when the decryption process is completed in the associated mail item.
Dean@680
   940
        /// </summary>
Dean@680
   941
        private void MailItem_DecryptionComplete(CryptableMailItem sender, CryptableMailItem.DecryptionEventArgs e)
Dean@680
   942
        {
Dean@680
   943
            try
Dean@680
   944
            {
Dean@680
   945
                // Marshal code back to UI thread as necessary
Dean@680
   946
                this.Invoke(new Action(() =>
Dean@680
   947
                    {
Dean@680
   948
                        this.CopyStateToUI(new PrivacyState(e.ColorRating));
Dean@680
   949
                    }));
Dean@680
   950
            }
Dean@680
   951
            catch (Exception ex)
Dean@680
   952
            {
Dean@680
   953
                Global.AddToLog("MailItem_DecryptionComplete: Error setting UI state, " + ex.ToString());
Dean@680
   954
            }
Dean@680
   955
Dean@680
   956
            return;
Dean@680
   957
        }
Dean@680
   958
Dean@680
   959
        /// <summary>
Dean@169
   960
        /// Event handler for when a mail item is being opened in an inspector.
Dean@180
   961
        /// See: https://msdn.microsoft.com/en-us/library/office/ff865989.aspx
Dean@169
   962
        /// </summary>
Dean@169
   963
        /// <param name="cancel">Whether to cancel the event: Value is False when the event occurs. 
Dean@169
   964
        /// If the event procedure sets this argument to True, the open operation is not completed 
Dean@169
   965
        /// and the inspector is not displayed.</param>
Dean@169
   966
        private void MailItem_Open(ref bool cancel)
Dean@159
   967
        {
Dean@173
   968
            if (this.associatedMailItem != null && this.associatedMailItem.MirrorDisplay())
Dean@169
   969
            {
Dean@169
   970
                cancel = true;
Dean@169
   971
            }
Dean@169
   972
Dean@169
   973
            return;
Dean@159
   974
        }
Dean@159
   975
Dean@169
   976
        /// <summary>
Dean@682
   977
        /// Event handler for when a mail item is sent.
Dean@682
   978
        /// See: https://msdn.microsoft.com/en-us/library/office/ff865379.aspx
Dean@682
   979
        /// </summary>
Dean@682
   980
        /// <param name="cancel">Whether to cancel the event: Value is False when the event occurs. 
Dean@682
   981
        /// If the event procedure sets this argument to True, the send operation is not completed 
Dean@682
   982
        /// and the inspector is left open.</param>
Dean@682
   983
        private void MailItem_Send(ref bool cancel)
Dean@682
   984
        {
Dean@682
   985
            // Stop and disconnect the refresh timer
Dean@682
   986
            // This is necessary so an ongoing refresh doesn't try to access a mail item as it's being moved
Dean@682
   987
            this.TimerRefresh.Stop();
Dean@682
   988
            this.TimerRefresh.Enabled = false;
Dean@682
   989
            this.TimerRefresh.Tick -= TimerRefresh_Tick;
Dean@682
   990
Dean@682
   991
            return;
Dean@682
   992
        }
Dean@682
   993
Dean@682
   994
        /// <summary>
Dean@169
   995
        /// Event handler for when a mail item property is changed.
Dean@169
   996
        /// See: https://msdn.microsoft.com/en-us/library/office/ff866739.aspx
Dean@169
   997
        /// </summary>
Dean@169
   998
        /// <param name="propertyName">The name of the property that was changed.</param>
Dean@445
   999
        private void MailItem_PropertyChanged(object sender, PropertyChangedEventArgs e)
Dean@159
  1000
        {
Dean@445
  1001
            switch (e.PropertyName.ToUpper())
Dean@159
  1002
            {
Dean@179
  1003
                case "TO":
Dean@179
  1004
                    // Start the refresh timer
Dean@179
  1005
                    this.TimerRefresh.Enabled = true;
Dean@159
  1006
                    break;
Dean@159
  1007
                // Outlook bug: there are always both events, so one is enough
Dean@159
  1008
                //case "CC":
Dean@179
  1009
                //    // Start the refresh timer
Dean@179
  1010
                //    this.TimerRefresh.Enabled = true;
Dean@159
  1011
                //    break;
Dean@159
  1012
            }
Dean@169
  1013
Dean@169
  1014
            return;
Dean@159
  1015
        }
Dean@159
  1016
Dean@179
  1017
        /// <summary>
Dean@312
  1018
        /// Event handler for when the privacy status button is clicked.
Dean@179
  1019
        /// </summary>
Dean@312
  1020
        private void ButtonPrivacyStatus_Click(object sender, EventArgs e)
vb@133
  1021
        {
Dean@310
  1022
            this.BuildAndShowManager();
Dean@179
  1023
            return;
vb@133
  1024
        }
vb@133
  1025
Dean@179
  1026
        /// <summary>
Dean@312
  1027
        /// Event handler for when a mouse button is released over the privacy status button.
Dean@179
  1028
        /// </summary>
Dean@312
  1029
        private void ButtonPrivacyStatus_MouseUp(object sender, MouseEventArgs e)
vb@133
  1030
        {
Dean@179
  1031
            return;
vb@133
  1032
        }
vb@133
  1033
    }
vb@133
  1034
}