UI/FormRegionPrivacyStatus.cs
author Dean
Tue, 09 Aug 2016 07:13:16 -0700
changeset 1117 467740b195fe
parent 1115 f152a1ffe405
child 1130 12df85031401
permissions -rw-r--r--
Correct an issue updating the manage privacy status form color rating.
Dean@1069
     1
using pEp.UI;
Dean@1069
     2
using pEpCOMServerAdapterLib;
Dean@159
     3
using System;
vb@133
     4
using System.Collections.Generic;
Dean@445
     5
using System.ComponentModel;
Dean@859
     6
using System.Diagnostics;
Dean@159
     7
using System.Runtime.InteropServices;
Dean@1074
     8
using System.Windows;
vb@133
     9
using System.Windows.Forms;
Dean@1069
    10
using System.Windows.Media.Imaging;
vb@133
    11
using Outlook = Microsoft.Office.Interop.Outlook;
vb@133
    12
vb@133
    13
namespace pEp
vb@133
    14
{
Dean@159
    15
    /// <summary>
Dean@312
    16
    /// Partial class for the privacy status form region that is displayed below every outlook message.
Dean@159
    17
    /// </summary>
Dean@910
    18
    internal partial class FormRegionPrivacyStatus
vb@133
    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@312
    23
        [Microsoft.Office.Tools.Outlook.FormRegionName("pEp.FormRegionPrivacyStatus")]
Dean@312
    24
        public partial class FormRegionPrivacyStatusFactory
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@312
    29
            private void FormRegionPrivacyStatus_FormRegionInitializing(object sender, Microsoft.Office.Tools.Outlook.FormRegionInitializingEventArgs e)
vb@133
    30
            {
Dean@985
    31
                //WindowFormRegionCollection formRegions;
Dean@327
    32
Dean@327
    33
                /* There is a Microsoft bug at least in Outlook 2013 and Windows 8.1
Dean@327
    34
                 * This bug causes multiple PrivacyStatus form regions to appear stacked on top of each other.
Dean@327
    35
                 * To trigger this bug, on an unencrypted server, click reply to compose an in-line response.
Dean@327
    36
                 * Then click to another tab such as People or Tasks. Then click back on the mail tab to view 
Dean@327
    37
                 * the original email again. Two form regions will be visible: 
Dean@327
    38
                 * (1) for the status during the in-line reply and 
Dean@327
    39
                 * (2) for the status of only the received message.
Dean@327
    40
                 * 
Dean@327
    41
                 * To fix this bug, any existing form regions are found and closed when initializing a new privacy status
Dean@327
    42
                 * form region.
Dean@327
    43
                 */
Dean@985
    44
                /*
Dean@327
    45
                try
Dean@327
    46
                {
Dean@987
    47
                    formRegions = Globals.FormRegions[Globals.ThisAddIn.Application.ActiveWindow()];
Dean@327
    48
                    if (formRegions.FormRegionPrivacyStatus != null)
Dean@327
    49
                    {
Dean@985
    50
                        // Note: there seems to be no way to actually close the form region.
Dean@985
    51
                        // Therefore, this is as close as possible to actually closing it.
Dean@985
    52
                        // The actual form regions will be cleaned up as soon as another email is selected.
Dean@327
    53
                        formRegions.FormRegionPrivacyStatus.OutlookFormRegion.Visible = false;
Dean@327
    54
                    }
Dean@327
    55
                }
Dean@327
    56
                catch { }
Dean@985
    57
                */
Dean@327
    58
                return;
vb@133
    59
            }
vb@133
    60
        }
vb@133
    61
vb@133
    62
        #endregion
vb@133
    63
Dean@159
    64
        /* Notes:
Dean@179
    65
         * 
Dean@159
    66
         * Use this.OutlookItem to get a reference to the current Outlook item.
Dean@159
    67
         * Use this.OutlookFormRegion to get a reference to the form region.
Dean@179
    68
         * 
Dean@179
    69
         * UI State Managment:
Dean@179
    70
         * 
Dean@179
    71
         * The UI state is almost entirely set from the associated mail item data.
Dean@179
    72
         * However, a separate state class is maintained to represent the UI as some separation is needed.
Dean@179
    73
         * This logical separation MUST be maintained throughout the code.
Dean@179
    74
         * Specific cases are noted where possible.
Dean@179
    75
         * 
Dean@356
    76
         * The separate privacy status manager form state is also managed here.
Dean@259
    77
         * 
Dean@159
    78
         */
Dean@159
    79
Dean@758
    80
        private CryptableMailItem       associatedMailItem     = null;
Dean@758
    81
        private bool                    initialized            = false;
Dean@758
    82
        private FormManagePrivacyStatus managerForm            = null;
Dean@758
    83
        private bool                    refreshOngoing         = false;
Dean@758
    84
        private bool                    displayMirrorRequested = false;
Dean@259
    85
Dean@159
    86
        /**************************************************************
Dean@159
    87
         * 
Dean@159
    88
         * Methods
Dean@159
    89
         * 
Dean@159
    90
         *************************************************************/
Dean@159
    91
Dean@171
    92
        /// <summary>
Dean@438
    93
        /// Determines if this form region is running in an inspector window.
Dean@438
    94
        /// If not true, it is assumed to be within an explorer window.
Dean@438
    95
        /// </summary>
Dean@438
    96
        /// <returns>True if an inspector window, false if within an explorer.</returns>
Dean@438
    97
        private bool IsWithinInspector()
Dean@438
    98
        {
Dean@438
    99
            bool isWithinInspector = false;
Dean@895
   100
            Outlook.Inspector insp = null;
Dean@438
   101
Dean@438
   102
            try
Dean@438
   103
            {
Dean@895
   104
                /* There are two potential methods to determine if the item is within an inspector.
Dean@895
   105
                 * (1) Use this.OutlookFormRegion.Parent which will contain either the Explorer or an Inspector
Dean@895
   106
                 *     A cast could be tried to an Explorer of this parent and if it fails, it's assumed to be an inspector
Dean@895
   107
                 * (2) Use this.OutlookFormRegion.Inspector which will contain the Inspector if it exists.
Dean@895
   108
                 *     This will fail or return null if this form region is not running within it's own Inspector window.
Dean@895
   109
                 */
Dean@895
   110
                insp = this.OutlookFormRegion.Inspector;
Dean@895
   111
Dean@895
   112
                if (insp != null)
Dean@895
   113
                {
Dean@895
   114
                    isWithinInspector = true;
Dean@895
   115
                }
Dean@438
   116
            }
Dean@438
   117
            catch
Dean@438
   118
            {
Dean@895
   119
                isWithinInspector = false;
Dean@438
   120
            }
Dean@438
   121
            finally
Dean@438
   122
            {
Dean@895
   123
                if (insp != null)
Dean@438
   124
                {
Dean@895
   125
                    Marshal.ReleaseComObject(insp);
Dean@895
   126
                    insp = null;
Dean@438
   127
                }
Dean@438
   128
            }
Dean@438
   129
Dean@438
   130
            return (isWithinInspector);
Dean@438
   131
        }
Dean@438
   132
Dean@438
   133
        /// <summary>
Dean@170
   134
        /// Sets the cryptable mail item associated with this encryption status panel.
Dean@170
   135
        /// The associated mail item can then be accessed through its local variable.
Dean@170
   136
        /// </summary>
Dean@170
   137
        private void SetAssociatedMailItem()
Dean@170
   138
        {
Dean@170
   139
            bool errorOccurred = false;
Dean@170
   140
            Outlook.MailItem omi = null;
Dean@170
   141
Dean@170
   142
            // Null check
Dean@170
   143
            if (!errorOccurred)
Dean@170
   144
            {
Dean@170
   145
                try
Dean@170
   146
                {
Dean@170
   147
                    if (this.OutlookItem == null)
Dean@170
   148
                    {
Dean@170
   149
                        errorOccurred = true;
Dean@170
   150
                    }
Dean@170
   151
                }
Dean@170
   152
                catch (COMException)
Dean@170
   153
                {
Dean@170
   154
                    errorOccurred = true;
Dean@170
   155
                }
Dean@170
   156
            }
Dean@170
   157
Dean@170
   158
            // Attempt to get and cast the outlook mail item
Dean@170
   159
            if (!errorOccurred)
Dean@170
   160
            {
Dean@170
   161
                try
Dean@170
   162
                {
Dean@170
   163
                    omi = (Outlook.MailItem)this.OutlookItem;
Dean@170
   164
                }
Dean@170
   165
                catch
Dean@170
   166
                {
Dean@170
   167
                    errorOccurred = true;
Dean@170
   168
                }
Dean@170
   169
            }
Dean@170
   170
Dean@170
   171
            // Finally set the associated mail item
Dean@170
   172
            if ((errorOccurred) ||
Dean@170
   173
                (omi == null))
Dean@170
   174
            {
Dean@170
   175
                this.associatedMailItem = null;
Dean@170
   176
            }
Dean@170
   177
            else
Dean@170
   178
            {
Dean@170
   179
                // Check if the associated mail item has already been set
Dean@170
   180
                if (this.associatedMailItem != null)
Dean@170
   181
                {
Dean@170
   182
                    // Only re-set the mail item if the EntryID has changed
Dean@170
   183
                    if (this.associatedMailItem.EntryID != omi.EntryID)
Dean@170
   184
                    {
Dean@170
   185
                        this.associatedMailItem = new CryptableMailItem(omi);
Dean@170
   186
                    }
Dean@170
   187
                }
Dean@170
   188
                else
Dean@170
   189
                {
Dean@170
   190
                    this.associatedMailItem = new CryptableMailItem(omi);
Dean@170
   191
                }
Dean@170
   192
            }
Dean@170
   193
Dean@170
   194
            return;
Dean@170
   195
        }
Dean@170
   196
Dean@179
   197
        /// <summary>
Dean@672
   198
        /// Completes the handshake process when the identity of a partner was previously marked as mistrusted.
Dean@281
   199
        /// </summary>
Dean@646
   200
        /// <param name="myself">The personal identity to complete the handshake with.</param>
Dean@646
   201
        /// <param name="partner">The identity of the partner to complete the handshake with.</param>
Dean@672
   202
        private void DoHandshakeForMistrustedKey(PEPIdentity myself,
Dean@672
   203
                                                 PEPIdentity partner)
Dean@281
   204
        {
Dean@281
   205
            DialogResult result;
Dean@281
   206
Dean@1074
   207
            result = System.Windows.Forms.MessageBox.Show(this.ParentForm,
Dean@1074
   208
                                                          pEp.Properties.Resources.Message_WarningMistrustedKey,
Dean@1074
   209
                                                          pEp.Properties.Resources.Message_TitleConfirmOperation,
Dean@1074
   210
                                                          MessageBoxButtons.YesNo);
Dean@281
   211
Dean@423
   212
            if (result == DialogResult.Yes)
Dean@281
   213
            {
Dean@646
   214
                this.DoHandshake(myself, partner);
Dean@281
   215
            }
Dean@281
   216
Dean@281
   217
            return;
Dean@281
   218
        }
Dean@281
   219
Dean@281
   220
        /// <summary>
Dean@281
   221
        /// Completes the handshake process where the identity of a partner is confirmed.
Dean@179
   222
        /// </summary>
Dean@646
   223
        /// <param name="myself">The personal identity to complete the handshake with.</param>
Dean@646
   224
        /// <param name="partner">The identity of the partner to complete the handshake with.</param>
Dean@646
   225
        private void DoHandshake(PEPIdentity myself,
Dean@646
   226
                                 PEPIdentity partner)
vb@133
   227
        {
Dean@179
   228
            DialogResult result;
Dean@155
   229
            FormHandshake handshakeDialog;
markus@201
   230
Dean@860
   231
            Globals.LogVerbose("DoHandshake: Handshake started.");
vb@139
   232
Dean@155
   233
            // Create and show handshake dialog
Dean@1075
   234
            handshakeDialog = new FormHandshake();
Dean@1082
   235
            handshakeDialog.StartPosition = FormStartPosition.CenterParent;
Dean@1075
   236
            handshakeDialog.FormControl.DisplayState = new FormControlHandshake.State(myself, partner);
Dean@1086
   237
Dean@179
   238
            result = handshakeDialog.ShowDialog(this);
Dean@646
   239
            this.ProcessDoHandshakeResult(result, partner);
Dean@356
   240
Dean@356
   241
            return;
Dean@356
   242
        }
Dean@356
   243
Dean@356
   244
        /// <summary>
Dean@356
   245
        /// Processes the result of the do handshake dialog after a user makes a selection.
Dean@356
   246
        /// </summary>
Dean@356
   247
        /// <param name="result">The result of the handshake dialog selection.</param>
Dean@356
   248
        /// <param name="partner">The identity of the partner to handshake with.</param>
Dean@356
   249
        private void ProcessDoHandshakeResult(DialogResult result,
Dean@384
   250
                                              PEPIdentity partner)
Dean@356
   251
        {
Dean@1115
   252
            pEp_identity_s identityPartner = ThisAddIn.PEPEngine.update_identity(partner.ToCOMType());
vb@133
   253
vb@133
   254
            switch (result)
vb@133
   255
            {
vb@133
   256
                case DialogResult.Yes:
Dean@279
   257
                    {
Dean@672
   258
                        // Check if key was previously mistrusted -- warning to user must be displayed earlier
Dean@672
   259
                        if (identityPartner.comm_type == _pEp_comm_type.pEp_ct_mistrusted)
Dean@281
   260
                        {
Dean@1115
   261
                            ThisAddIn.PEPEngine.key_reset_trust(ref identityPartner);
Dean@281
   262
                        }
Dean@281
   263
Dean@1115
   264
                        identityPartner = ThisAddIn.PEPEngine.trust_personal_key(ref identityPartner);
Dean@279
   265
Dean@1001
   266
                        this.ImmediateColorRatingAndUIUpdate();
Dean@1117
   267
                        this.UpdateManagePrivacyStatusForm();
Dean@279
   268
Dean@279
   269
                        break;
Dean@279
   270
                    }
vb@133
   271
                case DialogResult.No:
Dean@279
   272
                    {
Dean@1115
   273
                        ThisAddIn.PEPEngine.key_compromized(ref identityPartner);
Dean@279
   274
Dean@1001
   275
                        this.ImmediateColorRatingAndUIUpdate();
Dean@1117
   276
                        this.UpdateManagePrivacyStatusForm();
Dean@279
   277
Dean@279
   278
                        break;
Dean@279
   279
                    }
vb@133
   280
            }
Dean@279
   281
Dean@860
   282
            Globals.LogVerbose("ProcessDoHandshakeResult: Handshake complete.");
Dean@740
   283
Dean@279
   284
            return;
vb@133
   285
        }
vb@133
   286
Dean@179
   287
        /// <summary>
Dean@179
   288
        /// Reverses any past handshake confirmation by unconfirming the given identity partner.
Dean@179
   289
        /// </summary>
Dean@384
   290
        /// <param name="partner">The identity of the partner to unconfirm.</param>
Dean@384
   291
        private void UndoHandshake(PEPIdentity partner)
vb@133
   292
        {
Dean@1115
   293
            pEp_identity_s identityPartner = ThisAddIn.PEPEngine.update_identity(partner.ToCOMType());
Dean@1115
   294
            ThisAddIn.PEPEngine.key_reset_trust(ref identityPartner);
Dean@279
   295
Dean@1001
   296
            this.ImmediateColorRatingAndUIUpdate();
Dean@1117
   297
            this.UpdateManagePrivacyStatusForm();
Dean@279
   298
Dean@279
   299
            return;
vb@133
   300
        }
vb@133
   301
Dean@161
   302
        /// <summary>
Dean@279
   303
        /// Builds a new manager form state using this encryption state/mail item current state.
Dean@279
   304
        /// </summary>
Dean@279
   305
        /// <returns>A new manager form state.</returns>
Dean@1069
   306
        private FormControlManagePrivacyStatus.State GetManagerState()
Dean@279
   307
        {
Dean@737
   308
            int currIndex = 0;
Dean@527
   309
            bool isMyself;
Dean@364
   310
            string trustwordsShort;
Dean@364
   311
            string trustwordsFull;
Dean@1069
   312
            BitmapImage imageForceUnencOn;
Dean@1069
   313
            BitmapImage imageGreen;
Dean@1069
   314
            BitmapImage imageNoColor;
Dean@1069
   315
            BitmapImage imageRed;
Dean@1069
   316
            BitmapImage imageYellow;
Dean@384
   317
            List<PEPIdentity> identities;
Dean@1106
   318
            PEPIdentity identity;
Dean@384
   319
            PEPIdentity myIdentity;
Dean@259
   320
            _pEp_color identityPartnerColor;
Dean@259
   321
            SelectionItem item;
Dean@1069
   322
            FormControlManagePrivacyStatus.State managerState = new FormControlManagePrivacyStatus.State();
Dean@1069
   323
Dean@1069
   324
            // Load all images from resources
Dean@1069
   325
            imageForceUnencOn = new BitmapImage(new Uri("pack://application:,,,/pEp;component/Resources/ImageForceUnencOn.png", UriKind.RelativeOrAbsolute));
Dean@1069
   326
            imageGreen = new BitmapImage(new Uri("pack://application:,,,/pEp;component/Resources/ImagePrivacyStatusGreen.png", UriKind.RelativeOrAbsolute));
Dean@1069
   327
            imageNoColor = new BitmapImage(new Uri("pack://application:,,,/pEp;component/Resources/ImagePrivacyStatusNoColor.png", UriKind.RelativeOrAbsolute));
Dean@1069
   328
            imageRed = new BitmapImage(new Uri("pack://application:,,,/pEp;component/Resources/ImagePrivacyStatusRed.png", UriKind.RelativeOrAbsolute));
Dean@1069
   329
            imageYellow = new BitmapImage(new Uri("pack://application:,,,/pEp;component/Resources/ImagePrivacyStatusYellow.png", UriKind.RelativeOrAbsolute));
Dean@259
   330
Dean@769
   331
            /* Resolve all recipients -- this ensures the identities list is correctly populated
Dean@769
   332
             *
Dean@769
   333
             * Note: The PropertyChanged changed event must be disconnected before trying to resolve.
Dean@769
   334
             * This is because the resolve process can modify the contents of the mail item which triggers an event.
Dean@769
   335
             * The PropertyChanged event would then trigger a UI refresh cycle. However, because the GetManagerState itself 
Dean@769
   336
             * is called within the UI refresh, an infinite loop could occur trying to resolve a recipient that 
Dean@769
   337
             * cannot be resolved (no address).
Dean@769
   338
             */
Dean@769
   339
            if (this.associatedMailItem != null)
Dean@769
   340
            {
Dean@769
   341
                this.associatedMailItem.PropertyChanged -= MailItem_PropertyChanged;
Dean@769
   342
                this.associatedMailItem.ResolveAllRecipients();
Dean@769
   343
                this.associatedMailItem.PropertyChanged += MailItem_PropertyChanged;
Dean@769
   344
            }
Dean@332
   345
Dean@1086
   346
            managerState.ColorRating = this.FormControlPrivacyStatusChild.DisplayState.ColorRating;
Dean@279
   347
            managerState.IsIncoming = this.associatedMailItem.IsIncoming;
Dean@259
   348
Dean@1106
   349
            // Get identities
Dean@1106
   350
            identities = this.associatedMailItem.Recipients;
Dean@1106
   351
            myIdentity = this.associatedMailItem.Myself;
Dean@1106
   352
Dean@1106
   353
            // Include the from identity for incoming messages at the beginning
Dean@1106
   354
            identity = this.associatedMailItem.From;
Dean@1106
   355
            if ((this.associatedMailItem.IsIncoming) &&
Dean@1106
   356
                (identity != null))
Dean@259
   357
            {
Dean@1106
   358
                identities.Insert(0, identity);
Dean@1106
   359
            }
Dean@259
   360
Dean@1106
   361
            // Remove own identity in the MailItem from the list
Dean@1106
   362
            if (myIdentity != null)
Dean@1106
   363
            {
Dean@1106
   364
                for (int i = (identities.Count - 1); i >= 0; i--)
Dean@638
   365
                {
Dean@1106
   366
                    if ((identities[i] != null) &&
Dean@1106
   367
                        (identities[i].EqualsByAddress(myIdentity)))
Dean@1106
   368
                    {
Dean@1106
   369
                        identities.RemoveAt(i);
Dean@1106
   370
                    }
Dean@638
   371
                }
Dean@259
   372
            }
Dean@366
   373
Dean@279
   374
            // Add identities
Dean@394
   375
            identities = PEPIdentity.ToFlatList(identities);
Dean@279
   376
            managerState.Identities.Clear();
Dean@384
   377
            foreach (PEPIdentity ident in identities)
Dean@259
   378
            {
Dean@737
   379
                // Needed so index can be used within anonymous methods without getting into the 'outer variable trap' of currIndex
Dean@737
   380
                int index = currIndex;
Dean@737
   381
Dean@865
   382
                if (ident.IsAddressValid)
Dean@485
   383
                {
Dean@774
   384
                    // Update the partner identity to get a fingerprint, preserve IsForceUnencrypted
Dean@1115
   385
                    pEp_identity_s partnerIdentity_s = ThisAddIn.PEPEngine.update_identity(ident.ToCOMType());
Dean@485
   386
                    PEPIdentity partnerIdentity = new PEPIdentity(partnerIdentity_s);
Dean@774
   387
                    partnerIdentity.IsForceUnencrypted = ident.IsForceUnencrypted;
Dean@774
   388
Dean@1018
   389
                    try
Dean@1018
   390
                    {
Dean@1115
   391
                        identityPartnerColor = ThisAddIn.PEPEngine.identity_color(partnerIdentity_s);
Dean@1018
   392
                    }
Dean@1018
   393
                    catch (COMException ex)
Dean@1018
   394
                    {
Dean@1018
   395
                        identityPartnerColor = _pEp_color.pEp_rating_undefined;
Dean@1018
   396
                        Globals.Log("GetManagerState: Failed to get identity color, " + ex.ToString());
Dean@1018
   397
                    }
Dean@1018
   398
Dean@910
   399
                    isMyself = PEPIdentity.GetIsOwnIdentity(partnerIdentity.Address);
Dean@724
   400
Dean@880
   401
                    // Calculate trustwords
Dean@880
   402
                    Globals.ThisAddIn.CalcTrustwords(myIdentity,
Dean@880
   403
                                                     partnerIdentity,
Dean@880
   404
                                                     out trustwordsShort,
Dean@880
   405
                                                     out trustwordsFull,
Dean@1090
   406
                                                     PEPSettings.CULTURE_CODE_DEFAULT);
Dean@880
   407
Dean@485
   408
                    item = new SelectionItem();
Dean@485
   409
                    item.TextLine1 = partnerIdentity.Username;
Dean@485
   410
                    item.TextLine2 = partnerIdentity.Address;
Dean@894
   411
                    item.Tag = (string.IsNullOrWhiteSpace(partnerIdentity.Fingerprint) ? null : trustwordsShort);
Dean@259
   412
Dean@485
   413
                    // Don't show both the user name and address if they are the same
Dean@485
   414
                    if ((item.TextLine1 != null) &&
Dean@485
   415
                        (item.TextLine2 != null) &&
Dean@485
   416
                        (item.TextLine1 == item.TextLine2))
Dean@485
   417
                    {
Dean@485
   418
                        item.IsTwoTextLinesVisible = false;
Dean@485
   419
                    }
Dean@332
   420
Dean@485
   421
                    // Set image
Dean@774
   422
                    if ((partnerIdentity.IsForceUnencryptedBool) &&
Dean@653
   423
                        (managerState.IsIncoming == false))
Dean@485
   424
                    {
Dean@1069
   425
                        item.ItemImage = imageForceUnencOn;
Dean@641
   426
                    }
Dean@641
   427
                    else
Dean@641
   428
                    {
Dean@641
   429
                        switch (PrivacyState.ConvertRatingToPrivacyColor(identityPartnerColor))
Dean@641
   430
                        {
Dean@641
   431
                            case PrivacyState.PrivacyColor.Green:
Dean@1069
   432
                                item.ItemImage = imageGreen;
Dean@641
   433
                                break;
Dean@641
   434
                            case PrivacyState.PrivacyColor.Yellow:
Dean@1069
   435
                                item.ItemImage = imageYellow;
Dean@641
   436
                                break;
Dean@641
   437
                            case PrivacyState.PrivacyColor.Red:
Dean@1069
   438
                                item.ItemImage = imageRed;
Dean@641
   439
                                break;
Dean@641
   440
                            case PrivacyState.PrivacyColor.NoColor:
Dean@1069
   441
                                item.ItemImage = imageNoColor;
Dean@641
   442
                                break;
Dean@641
   443
                            default:
Dean@641
   444
                                item.ItemImage = null;
Dean@641
   445
                                break;
Dean@641
   446
                        }
Dean@485
   447
                    }
Dean@259
   448
Dean@485
   449
                    // Set button
Dean@653
   450
                    if ((isMyself) ||
Dean@774
   451
                        ((partnerIdentity.IsForceUnencryptedBool) &&
Dean@653
   452
                         (managerState.IsIncoming == false)))
Dean@653
   453
                    {
Dean@653
   454
                        item.IsButtonVisible = false;
Dean@653
   455
                        item.IsExpandable = false;
Dean@653
   456
                    }
Dean@653
   457
                    else
Dean@366
   458
                    {
Dean@485
   459
                        if (partnerIdentity.CommunicationType >= _pEp_comm_type.pEp_ct_confirmed_encryption)
Dean@485
   460
                        {
Dean@485
   461
                            // Undo handshake
Dean@485
   462
                            item.TextButton = pEp.Properties.Resources.PrivacyStatus_StopTrusting;
Dean@485
   463
                            item.IsButtonVisible = true;
Dean@646
   464
                            item.ButtonOnClick = (x, y) => { this.UndoHandshake(partnerIdentity.Copy()); };
Dean@356
   465
Dean@485
   466
                            item.IsExpandable = false;
Dean@485
   467
                        }
Dean@485
   468
                        else if (partnerIdentity.CommunicationType >= _pEp_comm_type.pEp_ct_unconfirmed_encryption &&
Dean@485
   469
                                 partnerIdentity.CommunicationType < _pEp_comm_type.pEp_ct_confirmed_encryption)
Dean@485
   470
                        {
Dean@485
   471
                            // Do handshake
Dean@737
   472
                            item.TextButton = pEp.Properties.Resources.PrivacyStatus_Handshake;
Dean@485
   473
                            item.IsButtonVisible = true;
Dean@646
   474
                            item.ButtonOnClick = (x, y) => { this.DoHandshake(myIdentity.Copy(), partnerIdentity.Copy()); };
Dean@356
   475
Dean@485
   476
                            item.IsExpandable = true;
Dean@1069
   477
                            item.ExpandedText = Properties.Resources.PrivacyStatus_TrustwordDesc + "\n\n" +
Dean@485
   478
                                                trustwordsShort;
Dean@447
   479
Dean@1075
   480
                            item.ExpandedButton1Text = pEp.Properties.Resources.Handshake_ConfirmText;
Dean@646
   481
                            item.ExpandedButton1OnClick = (x, y) => { this.ProcessDoHandshakeResult(DialogResult.Yes, partnerIdentity.Copy()); };
Dean@1074
   482
                            item.ExpandedButton1Style = (Style)Globals.ResourceDict["StyleConfirmButton"];
Dean@447
   483
Dean@1075
   484
                            item.ExpandedButton2Text = pEp.Properties.Resources.Handshake_CancelText;
Dean@737
   485
                            item.ExpandedButton2OnClick = (x, y) =>
Dean@737
   486
                                {
Dean@1069
   487
                                    SelectionItem selItem;
Dean@1069
   488
                                    FormControlManagePrivacyStatus.State activeState;
Dean@737
   489
Dean@737
   490
                                    if (this.managerForm != null)
Dean@737
   491
                                    {
Dean@1072
   492
                                        activeState = this.managerForm.FormControl.DisplayState;
Dean@758
   493
Dean@737
   494
                                        if ((index >= 0) &&
Dean@1069
   495
                                            (index < activeState.Identities.Count))
Dean@737
   496
                                        {
Dean@1069
   497
                                            selItem = activeState.Identities[index];
Dean@1069
   498
                                            selItem.TextButton = pEp.Properties.Resources.PrivacyStatus_Handshake;
Dean@1069
   499
                                            selItem.IsExpanded = false;
Dean@1069
   500
                                            selItem.IsExpandable = false;
Dean@737
   501
                                        }
Dean@737
   502
                                    }
Dean@737
   503
                                };
Dean@1074
   504
                            item.ExpandedButton2Style = (Style)Globals.ResourceDict["StyleCancelButton"];
Dean@737
   505
Dean@1075
   506
                            item.ExpandedButton3Text = pEp.Properties.Resources.Handshake_WrongText;
Dean@737
   507
                            item.ExpandedButton3OnClick = (x, y) => { this.ProcessDoHandshakeResult(DialogResult.No, partnerIdentity.Copy()); };
Dean@1074
   508
                            item.ExpandedButton3Style = (Style)Globals.ResourceDict["StyleWrongButton"];
Dean@485
   509
                        }
Dean@672
   510
                        else if (partnerIdentity.CommunicationType == _pEp_comm_type.pEp_ct_mistrusted)
Dean@485
   511
                        {
Dean@485
   512
                            // Redo handshake with confirmation
Dean@485
   513
                            item.TextButton = pEp.Properties.Resources.PrivacyStatus_Handshake;
Dean@485
   514
                            item.IsButtonVisible = true;
Dean@672
   515
                            item.ButtonOnClick = (x, y) => { this.DoHandshakeForMistrustedKey(myIdentity.Copy(), partnerIdentity.Copy()); };
Dean@641
   516
Dean@641
   517
                            item.IsExpandable = false;
Dean@485
   518
                        }
Dean@485
   519
                        else
Dean@485
   520
                        {
Dean@485
   521
                            item.IsButtonVisible = false;
Dean@641
   522
                            item.IsExpandable = false;
Dean@485
   523
                        }
Dean@366
   524
                    }
Dean@281
   525
                }
Dean@485
   526
                else // Invalid identity
Dean@259
   527
                {
Dean@485
   528
                    item = new SelectionItem();
Dean@485
   529
                    item.TextLine1 = ident.Username;
Dean@485
   530
                    item.TextLine2 = ident.Address;
Dean@485
   531
                    item.ItemImage = null;
Dean@485
   532
                    item.IsTwoTextLinesVisible = true;
Dean@259
   533
                    item.IsButtonVisible = false;
Dean@259
   534
                }
Dean@259
   535
Dean@279
   536
                managerState.Identities.Add(item);
Dean@737
   537
                currIndex++;
Dean@259
   538
            }
Dean@259
   539
Dean@737
   540
            // Attempt to select and expand the first identity requiring a handshake
Dean@375
   541
            for (int i = 0; i < managerState.Identities.Count; i++)
Dean@375
   542
            {
Dean@737
   543
                // Determine if it's a handshake identity by checking if it's expandable
Dean@375
   544
                if (managerState.Identities[i].IsExpandable)
Dean@375
   545
                {
Dean@737
   546
                    managerState.Identities[i].TextButton = Properties.Resources.PrivacyStatus_HandshakeAdvanced;
Dean@737
   547
                    managerState.Identities[i].IsExpanded = true;
Dean@375
   548
                    managerState.SelectedIdentityIndex = i;
Dean@375
   549
                    break;
Dean@375
   550
                }
Dean@375
   551
            }
Dean@375
   552
Dean@279
   553
            return (managerState);
Dean@279
   554
        }
Dean@279
   555
Dean@279
   556
        /// <summary>
Dean@279
   557
        /// Builds the latest state of the encryption status manager then shows the UI.
Dean@279
   558
        /// </summary>
Dean@279
   559
        private void BuildAndShowManager()
Dean@279
   560
        {
Dean@279
   561
            DialogResult result;
Dean@313
   562
            FormManagePrivacyStatus form;
Dean@279
   563
Dean@483
   564
            try
Dean@483
   565
            {
Dean@483
   566
                // Show the form
Dean@483
   567
                form = new FormManagePrivacyStatus();
Dean@1082
   568
                form.StartPosition = FormStartPosition.CenterParent;
Dean@1021
   569
                form.FormClosed += ManagerForm_FormClosed;
Dean@1073
   570
                form.FormControl.DisplayState = this.GetManagerState();
Dean@259
   571
Dean@483
   572
                this.managerForm = form;
Dean@1073
   573
                result = form.ShowDialog(this.ParentForm);
Dean@483
   574
            }
Dean@483
   575
            catch (Exception ex)
Dean@483
   576
            {
Dean@860
   577
                Globals.StopAndSendCrashReport(ex);
Dean@483
   578
            }
Dean@259
   579
Dean@259
   580
            return;
Dean@259
   581
        }
Dean@259
   582
Dean@259
   583
        /// <summary>
Dean@1001
   584
        /// Schedules for the color rating and UI (including displayed mirror) to be updated.
Dean@1001
   585
        /// This can be called many times with no issue as the update is only run every n milliseconds.
Dean@179
   586
        /// </summary>
Dean@1001
   587
        public void RequestColorRatingAndUIUpdate()
Dean@1001
   588
        {
Dean@1001
   589
            this.TimerRefresh.Enabled = true;
Dean@1001
   590
            return;
Dean@1001
   591
        }
Dean@1001
   592
Dean@1001
   593
        /// <summary>
Dean@1001
   594
        /// Immediately starts the update of UI color rating based on the associated mail item.
Dean@1001
   595
        /// This will start decryption as necessary and also will update the displayed mirror.
Dean@1001
   596
        /// This method by-passes the refresh timer completely.
Dean@1001
   597
        /// WARNING: This method assumes the message is fully downloaded already.
Dean@1001
   598
        /// </summary>
Dean@1001
   599
        private void ImmediateColorRatingAndUIUpdate()
Dean@159
   600
        {
Dean@860
   601
            Globals.LogVerbose("UpdateUIFromMailItem: Started.");
Dean@740
   602
Dean@173
   603
            if (this.associatedMailItem != null)
Dean@159
   604
            {
Dean@1094
   605
                if (this.associatedMailItem.ForceUnencrypted == true)
Dean@159
   606
                {
Dean@342
   607
                    // Force unencrypted
Dean@1086
   608
                    this.FormControlPrivacyStatusChild.DisplayState.ColorRating = _pEp_color.pEp_rating_unencrypted;
Dean@740
   609
Dean@860
   610
                    Globals.LogVerbose("UpdateUIFromMailItem: Force unencrypted detected.");
Dean@159
   611
                }
Dean@159
   612
                else
Dean@159
   613
                {
Dean@860
   614
                    Globals.LogVerbose("UpdateUIFromMailItem: Starting decryption.");
Dean@740
   615
Dean@680
   616
                    // Start the color rating calculation/decryption process
Dean@1096
   617
                    this.associatedMailItem.StartProcessing();
Dean@159
   618
                }
Dean@159
   619
            }
Dean@159
   620
Dean@179
   621
            return;
Dean@159
   622
        }
Dean@159
   623
Dean@709
   624
        /// <summary>
Dean@1117
   625
        /// Immediately update the manage privacy status form display state.
Dean@1117
   626
        /// This by default will completely rebuild the display state.
Dean@1117
   627
        /// </summary>
Dean@1117
   628
        /// <param name="onlyColorRating">True to update only the color rating, false to rebuild the entire display state.</param>
Dean@1117
   629
        private void UpdateManagePrivacyStatusForm(bool onlyColorRating = false)
Dean@1117
   630
        {
Dean@1117
   631
            if (this.managerForm != null)
Dean@1117
   632
            {
Dean@1117
   633
                if (onlyColorRating)
Dean@1117
   634
                {
Dean@1117
   635
                    // Only update the message color rating
Dean@1117
   636
                    this.managerForm.FormControl.DisplayState.ColorRating = this.FormControlPrivacyStatusChild.DisplayState.ColorRating;
Dean@1117
   637
                }
Dean@1117
   638
                else
Dean@1117
   639
                {
Dean@1117
   640
                    // Rebuild the entire display state which will update any identity changes
Dean@1117
   641
                    this.managerForm.FormControl.DisplayState = this.GetManagerState();
Dean@1117
   642
                }
Dean@1117
   643
            }
Dean@1117
   644
Dean@1117
   645
            return;
Dean@1117
   646
        }
Dean@1117
   647
Dean@1117
   648
        /// <summary>
Dean@709
   649
        /// Clears the associated unencrypted preview and displays the given note (if any).
Dean@709
   650
        /// </summary>
Dean@709
   651
        /// <param name="note">The note to diplsay.</param>
Dean@709
   652
        private void ClearPreview(string note = null)
Dean@709
   653
        {
Dean@987
   654
            WindowFormRegionCollection formRegions = Globals.FormRegions[Globals.ThisAddIn.Application.ActiveWindow()];
Dean@709
   655
Dean@709
   656
            if ((formRegions != null) &&
Dean@709
   657
                (formRegions.FormRegionPreviewUnencrypted != null) &&
Dean@709
   658
                (formRegions.FormRegionPreviewUnencrypted.Visible))
Dean@709
   659
            {
Dean@709
   660
                formRegions.FormRegionPreviewUnencrypted.ClearMessage();
Dean@709
   661
                formRegions.FormRegionPreviewUnencrypted.SetNote(note);
Dean@709
   662
            }
Dean@709
   663
Dean@709
   664
            return;
Dean@709
   665
        }
Dean@709
   666
Dean@159
   667
        /**************************************************************
Dean@159
   668
         * 
Dean@159
   669
         * Event Handling
Dean@159
   670
         * 
Dean@159
   671
         *************************************************************/
Dean@159
   672
Dean@159
   673
        /// <summary>
Dean@680
   674
        /// Event handler that is called when the form region is displayed.
Dean@680
   675
        /// This is called each time the form region looses then regains visiblity 
Dean@680
   676
        /// (for example an other email is selected then back to this one).
Dean@159
   677
        /// </summary>
Dean@312
   678
        private void FormRegionPrivacyStatus_FormRegionShowing(object sender, System.EventArgs e)
Dean@159
   679
        {
Dean@680
   680
            // Do not allow initialization more than once
Dean@680
   681
            if (initialized == false)
Dean@680
   682
            {
Dean@680
   683
                this.SetAssociatedMailItem();
Dean@173
   684
Dean@680
   685
                // Set background color for Office 2013
Dean@159
   686
                try
Dean@159
   687
                {
Dean@680
   688
                    if (Globals.ThisAddIn.Application.Version.Substring(0, 2) == "15")
Dean@159
   689
                    {
Dean@680
   690
                        if (this.IsWithinInspector())
Dean@680
   691
                        {
Dean@1074
   692
                            this.BackColor = System.Drawing.SystemColors.ButtonFace;
Dean@680
   693
                        }
Dean@680
   694
                        else
Dean@680
   695
                        {
Dean@1074
   696
                            this.BackColor = System.Drawing.SystemColors.Window;
Dean@680
   697
                        }
Dean@159
   698
                    }
Dean@159
   699
                }
Dean@159
   700
                catch { }
Dean@680
   701
Dean@680
   702
                // Connect cryptable mail item events
Dean@680
   703
                if (this.associatedMailItem != null)
Dean@680
   704
                {
Dean@680
   705
                    try
Dean@680
   706
                    {
Dean@680
   707
                        this.associatedMailItem.PropertyChanged += MailItem_PropertyChanged;
Dean@1096
   708
                        this.associatedMailItem.ProcessingCompleted += MailItem_ProcessingCompleted;
Dean@1096
   709
                        this.associatedMailItem.GetMirrorCompleted += MailItem_GetMirrorCompleted;
Dean@682
   710
                        this.associatedMailItem.Send += MailItem_Send;
Dean@680
   711
Dean@1096
   712
                        if (this.associatedMailItem.IsStoredEncrypted)
Dean@680
   713
                        {
Dean@680
   714
                            this.associatedMailItem.Open += MailItem_Open;
Dean@680
   715
                        }
Dean@680
   716
                    }
Dean@680
   717
                    catch { }
Dean@680
   718
                }
Dean@680
   719
Dean@1086
   720
                // Connect events
Dean@807
   721
                CryptableMailItem.EncryptedConversationCacheUpdated += CryptableMailItem_EncryptedConversationCacheUpdated;
Dean@1086
   722
                this.FormControlPrivacyStatusChild.PrivacyViewClick += FormControlPrivacyStatusChild_PrivacyViewClick;
Dean@807
   723
Dean@683
   724
                this.TimerRefresh.Tick += TimerRefresh_Tick;
Dean@680
   725
                this.initialized = true;
Dean@179
   726
            }
Dean@159
   727
Dean@683
   728
            // Call the timer tick method manually to refresh data with no delay
Dean@199
   729
            this.TimerRefresh_Tick(null, new EventArgs());
Dean@179
   730
Dean@179
   731
            return;
Dean@159
   732
        }
Dean@159
   733
Dean@159
   734
        /// <summary>
Dean@159
   735
        /// Event handler for when the form region is closed.
Dean@159
   736
        /// </summary>
Dean@312
   737
        private void FormRegionPrivacyStatus_FormRegionClosed(object sender, System.EventArgs e)
Dean@159
   738
        {
Dean@199
   739
            // Disconnect cryptable mail item events
Dean@190
   740
            if (this.associatedMailItem != null)
Dean@179
   741
            {
Dean@179
   742
                try
Dean@179
   743
                {
Dean@445
   744
                    this.associatedMailItem.PropertyChanged -= MailItem_PropertyChanged;
Dean@1096
   745
                    this.associatedMailItem.ProcessingCompleted -= MailItem_ProcessingCompleted;
Dean@1096
   746
                    this.associatedMailItem.GetMirrorCompleted -= MailItem_GetMirrorCompleted;
markus@201
   747
                    this.associatedMailItem.Open -= MailItem_Open;
Dean@682
   748
                    this.associatedMailItem.Send -= MailItem_Send;
Dean@179
   749
                }
Dean@179
   750
                catch { }
Dean@179
   751
            }
Dean@179
   752
Dean@1086
   753
            // Disconnect events
Dean@807
   754
            CryptableMailItem.EncryptedConversationCacheUpdated -= CryptableMailItem_EncryptedConversationCacheUpdated;
Dean@1086
   755
            this.FormControlPrivacyStatusChild.PrivacyViewClick -= FormControlPrivacyStatusChild_PrivacyViewClick;
Dean@807
   756
Dean@682
   757
            // Stop and disconnect the refresh timer
Dean@682
   758
            this.TimerRefresh.Stop();
Dean@682
   759
            this.TimerRefresh.Enabled = false;
Dean@682
   760
            this.TimerRefresh.Tick -= TimerRefresh_Tick;
Dean@682
   761
Dean@179
   762
            return;
Dean@179
   763
        }
Dean@179
   764
Dean@179
   765
        /// <summary>
Dean@179
   766
        /// Event handler called after the refresh timer has elapsed.
Dean@179
   767
        /// </summary>
Dean@179
   768
        private void TimerRefresh_Tick(object sender, EventArgs e)
Dean@179
   769
        {
Dean@199
   770
            bool tryAgain = false;
Dean@684
   771
            bool markForDownload = false;
Dean@179
   772
            this.TimerRefresh.Enabled = false; // Only once
Dean@684
   773
            Outlook.OlDownloadState dlState;
markus@201
   774
Dean@709
   775
            /* The Refresh/UI_Update process is a little more complicated here than other forms.
Dean@709
   776
             * There are the following components:
Dean@709
   777
             *   1. TimerRefresh_Tick
Dean@709
   778
             *        This is the main timer tick event handler called any time
Dean@1001
   779
             *        a refresh was requested (RequestColorRatingAndUIUpdate) and hasn't been run yet. 
Dean@1001
   780
             *        A refresh is requested either at initialization or when a property changes
Dean@709
   781
             *        (such as MailItem_PropertyChanged). It is on a timer as many 
Dean@709
   782
             *        property change events could occur rapidy, but only one refresh should
Dean@709
   783
             *        occur for performance reasons.
Dean@709
   784
             * 
Dean@1001
   785
             *   2. ImmediateColorRatingAndUIUpdate
Dean@709
   786
             *        This will re-calculate the mail item's color rating and then update the UI.
Dean@709
   787
             *        However, if a mail item is not forcefully unencrypted, it will just call StartDecryption.
Dean@709
   788
             * 
Dean@709
   789
             *   3. MailItem_DecryptionComplete
Dean@709
   790
             *        When decryption of the mail item is complete, this even handler will be called.
Dean@709
   791
             *        This will update the UI with the latest color rating then call StartGetMirror.
Dean@709
   792
             *        The CopyStateToUI method is used which means any open privacy status form will also
Dean@709
   793
             *        be updated.
Dean@709
   794
             * 
Dean@709
   795
             *   4. MailItem_GetMirrorComplete
Dean@709
   796
             *        This is the final step in updating the UI, after a mirror is located, it's contents
Dean@709
   797
             *        will be shown to the unencrypted preview.
Dean@709
   798
             * 
Dean@709
   799
             * The general calling sequence is as shown above 1->4 with each component calling the next.
Dean@709
   800
             * However, for methods that update the mail item directly, commonly only 2->4 is needed.
Dean@709
   801
             */
Dean@709
   802
Dean@179
   803
            // Ensure the tick method is not called more than once
Dean@179
   804
            if (refreshOngoing == false)
Dean@179
   805
            {
Dean@179
   806
                this.refreshOngoing = true;
Dean@179
   807
Dean@179
   808
                if (this.associatedMailItem != null)
Dean@179
   809
                {
Dean@684
   810
                    // Attempt to get the download state
Dean@684
   811
                    try
Dean@684
   812
                    {
Dean@684
   813
                        dlState = this.associatedMailItem.DownloadState;
Dean@684
   814
                    }
Dean@684
   815
                    catch (Exception ex)
Dean@684
   816
                    {
Dean@860
   817
                        Globals.Log("TimerRefresh_Tick: Get DownloadState failed, " + ex.ToString());
Dean@684
   818
Dean@684
   819
                        // Assume everything is downloaded, but try to download again as well
Dean@684
   820
                        dlState = Outlook.OlDownloadState.olFullItem;
Dean@684
   821
                        markForDownload = true;
Dean@684
   822
                    }
Dean@684
   823
Dean@684
   824
                    if (dlState == Outlook.OlDownloadState.olFullItem)
Dean@179
   825
                    {
Dean@1001
   826
                        this.ImmediateColorRatingAndUIUpdate();
Dean@179
   827
                    }
Dean@179
   828
                    else
Dean@179
   829
                    {
Dean@684
   830
                        markForDownload = true;
Dean@684
   831
                    }
Dean@684
   832
Dean@684
   833
                    if (markForDownload)
Dean@684
   834
                    {
Dean@684
   835
                        // Try to mark the message for full download
Dean@684
   836
                        try
Dean@684
   837
                        {
Dean@684
   838
                            this.associatedMailItem.MarkForDownload = Outlook.OlRemoteStatus.olMarkedForDownload;
Dean@684
   839
                            tryAgain = true;
Dean@684
   840
                        }
Dean@684
   841
                        catch (Exception ex)
Dean@684
   842
                        {
Dean@860
   843
                            Globals.Log("TimerRefresh_Tick: MarkForDownload failed, " + ex.ToString());
Dean@684
   844
                        }
Dean@179
   845
                    }
Dean@179
   846
                }
Dean@179
   847
Dean@199
   848
                // Set the timer to refresh again later automatically
Dean@199
   849
                if (tryAgain)
Dean@199
   850
                {
Dean@199
   851
                    this.TimerRefresh.Interval = 100;
Dean@199
   852
                    this.TimerRefresh.Enabled = true;
Dean@199
   853
                }
Dean@199
   854
Dean@179
   855
                this.refreshOngoing = false;
Dean@179
   856
            }
Dean@175
   857
Dean@159
   858
            return;
Dean@159
   859
        }
Dean@159
   860
Dean@169
   861
        /// <summary>
Dean@1096
   862
        /// Event handler for when the processing is completed in the associated mail item.
Dean@709
   863
        /// This will then update the form region UI and the privacy status window as needed.
Dean@680
   864
        /// </summary>
Dean@1096
   865
        private void MailItem_ProcessingCompleted(object sender, CryptableMailItem.ProcessingCompletedEventArgs e)
Dean@680
   866
        {
Dean@1096
   867
            Globals.LogVerbose("MailItem_ProcessingComplete: Decryption completed.");
Dean@740
   868
Dean@680
   869
            try
Dean@680
   870
            {
Dean@680
   871
                // Marshal code back to UI thread as necessary
Dean@680
   872
                this.Invoke(new Action(() =>
Dean@680
   873
                    {
Dean@1086
   874
                        this.FormControlPrivacyStatusChild.DisplayState.ColorRating = e.ColorRating;
Dean@1117
   875
                        this.UpdateManagePrivacyStatusForm(true); // Only update the color rating
Dean@709
   876
Dean@709
   877
                        /* Create the unencrypted preview if the mail item is encrypted and
Dean@709
   878
                         * it is in an encrypted (untrusted) store
Dean@709
   879
                         * 
Dean@709
   880
                         * This is done here because FormRegionPrivacyStatus has the cryptable mail item and
Dean@709
   881
                         * it also is initialized after FormRegionPreviewUnencrypted.
Dean@709
   882
                         */
Dean@747
   883
                        try
Dean@709
   884
                        {
Dean@1096
   885
                            if (this.associatedMailItem.IsStoredEncrypted)
Dean@747
   886
                            {
Dean@1096
   887
                                Globals.LogVerbose("MailItem_ProcessingComplete: Starting mirror location.");
Dean@747
   888
                                this.associatedMailItem.StartGetMirror();
Dean@747
   889
                            }
Dean@747
   890
                            else
Dean@747
   891
                            {
Dean@747
   892
                                this.ClearPreview();
Dean@747
   893
                            }
Dean@709
   894
                        }
Dean@747
   895
                        catch (Exception ex)
Dean@719
   896
                        {
Dean@747
   897
                            // Error is possible in some situations where the mail item was deleted or moved while decryption was ongoing.
Dean@747
   898
                            // While rare, just log the issue and stop the process
Dean@1096
   899
                            Globals.Log("MailItem_ProcessingComplete: Failed to start mirror location, " + ex.ToString());
Dean@719
   900
                        }
Dean@680
   901
                    }));
Dean@680
   902
            }
Dean@680
   903
            catch (Exception ex)
Dean@680
   904
            {
Dean@1096
   905
                Globals.Log("MailItem_ProcessingComplete: Error setting UI state, " + ex.ToString());
Dean@680
   906
            }
Dean@680
   907
Dean@680
   908
            return;
Dean@680
   909
        }
Dean@680
   910
Dean@680
   911
        /// <summary>
Dean@709
   912
        /// Event handler for when the get mirror locating process is complete for the associated mail item.
Dean@709
   913
        /// This will then update the unencrypted preview in the UI.
Dean@709
   914
        /// </summary>
Dean@1096
   915
        private void MailItem_GetMirrorCompleted(object sender, CryptableMailItem.GetMirrorCompletedEventArgs e)
Dean@709
   916
        {
Dean@709
   917
            try
Dean@709
   918
            {
Dean@709
   919
                // Marshal code back to UI thread as necessary
Dean@709
   920
                this.Invoke(new Action(() =>
Dean@709
   921
                    {
Dean@987
   922
                        WindowFormRegionCollection formRegions = Globals.FormRegions[Globals.ThisAddIn.Application.ActiveWindow()];
Dean@709
   923
Dean@910
   924
                        if ((e.Mirror == null) &&
Dean@1096
   925
                            (this.associatedMailItem.LastProcessingStatus == Globals.ReturnStatus.Failure))
Dean@1014
   926
                        {
Dean@1014
   927
                            this.ClearPreview(Properties.Resources.Message_OpenError);
Dean@1014
   928
                            Globals.LogVerbose("MailItem_GetMirrorComplete: Cannot display mirror, failure during decryption.");
Dean@1014
   929
                        }
Dean@1014
   930
                        else if ((e.Mirror == null) &&
Dean@1096
   931
                                 (this.associatedMailItem.LastProcessingStatus == Globals.ReturnStatus.FailureNoConnection))
Dean@709
   932
                        {
Dean@910
   933
                            this.ClearPreview(Properties.Resources.Message_DecryptionNoConnection);
Dean@910
   934
                            Globals.LogVerbose("MailItem_GetMirrorComplete: Cannot display mirror, connection failure during decryption.");
Dean@910
   935
                        }
Dean@910
   936
                        else
Dean@910
   937
                        {
Dean@910
   938
                            if ((formRegions != null) &&
Dean@910
   939
                                (formRegions.FormRegionPreviewUnencrypted != null) &&
Dean@910
   940
                                (formRegions.FormRegionPreviewUnencrypted.Visible))
Dean@910
   941
                            {
Dean@910
   942
                                formRegions.FormRegionPreviewUnencrypted.SetMessage(e.Mirror);
Dean@910
   943
                                Globals.LogVerbose("MailItem_GetMirrorComplete: Mirror found and displayed.");
Dean@910
   944
                            }
Dean@709
   945
                        }
Dean@758
   946
Dean@758
   947
                        // Display the mirror if necessary
Dean@758
   948
                        if ((this.associatedMailItem != null) &&
Dean@758
   949
                            (this.displayMirrorRequested))
Dean@758
   950
                        {
Dean@758
   951
                            this.associatedMailItem.DisplayMirror();
Dean@758
   952
                            this.displayMirrorRequested = false;
Dean@758
   953
                        }
Dean@709
   954
                    }));
Dean@709
   955
            }
Dean@709
   956
            catch (Exception ex)
Dean@709
   957
            {
Dean@860
   958
                Globals.Log("MailItem_GetMirrorComplete: Error displaying preview, " + ex.ToString());
Dean@709
   959
            }
Dean@709
   960
Dean@709
   961
            return;
Dean@709
   962
        }
Dean@709
   963
Dean@709
   964
        /// <summary>
Dean@807
   965
        /// Event handler for the static mail item encrypted conversation cache updated.
Dean@807
   966
        /// This event is fired after the conversation cache has been updated with parent information following a
Dean@807
   967
        /// forward or reply mail item event (on a different, likely parent, mail item).
Dean@807
   968
        /// </summary>
Dean@807
   969
        private void CryptableMailItem_EncryptedConversationCacheUpdated(object sender, EventArgs e)
Dean@807
   970
        {
Dean@807
   971
            // Process the mail item now that the cache is updated
Dean@807
   972
            this.associatedMailItem.SetIsOriginallyEncryptedByCache();
Dean@807
   973
Dean@807
   974
            // Remove the event handler -- this can only be processed once because it's timing dependent
Dean@807
   975
            CryptableMailItem.EncryptedConversationCacheUpdated -= CryptableMailItem_EncryptedConversationCacheUpdated;
Dean@807
   976
Dean@807
   977
            return;
Dean@807
   978
        }
Dean@807
   979
Dean@807
   980
        /// <summary>
Dean@169
   981
        /// Event handler for when a mail item is being opened in an inspector.
Dean@180
   982
        /// See: https://msdn.microsoft.com/en-us/library/office/ff865989.aspx
Dean@169
   983
        /// </summary>
Dean@169
   984
        /// <param name="cancel">Whether to cancel the event: Value is False when the event occurs. 
Dean@169
   985
        /// If the event procedure sets this argument to True, the open operation is not completed 
Dean@169
   986
        /// and the inspector is not displayed.</param>
Dean@169
   987
        private void MailItem_Open(ref bool cancel)
Dean@159
   988
        {
Dean@758
   989
            bool result;
Dean@758
   990
Dean@758
   991
            if (this.associatedMailItem != null &&
Dean@1096
   992
                this.associatedMailItem.IsStoredEncrypted)
Dean@169
   993
            {
Dean@758
   994
                // Try to open the mirror
Dean@758
   995
                result = this.associatedMailItem.DisplayMirror();
Dean@758
   996
Dean@758
   997
                if (result == false)
Dean@758
   998
                {
Dean@758
   999
                    // Set flag to open after decryption/mirror location
Dean@758
  1000
                    this.displayMirrorRequested = true;
Dean@758
  1001
                }
Dean@758
  1002
Dean@758
  1003
                // Always cancel opening the original
Dean@169
  1004
                cancel = true;
Dean@169
  1005
            }
Dean@169
  1006
Dean@169
  1007
            return;
Dean@159
  1008
        }
Dean@159
  1009
Dean@169
  1010
        /// <summary>
Dean@682
  1011
        /// Event handler for when a mail item is sent.
Dean@682
  1012
        /// See: https://msdn.microsoft.com/en-us/library/office/ff865379.aspx
Dean@682
  1013
        /// </summary>
Dean@682
  1014
        /// <param name="cancel">Whether to cancel the event: Value is False when the event occurs. 
Dean@682
  1015
        /// If the event procedure sets this argument to True, the send operation is not completed 
Dean@682
  1016
        /// and the inspector is left open.</param>
Dean@682
  1017
        private void MailItem_Send(ref bool cancel)
Dean@682
  1018
        {
Dean@807
  1019
            DialogResult result;
Dean@807
  1020
Dean@807
  1021
            if ((this.associatedMailItem.IsOriginallyEncrypted) &&
Dean@1086
  1022
                (this.FormControlPrivacyStatusChild.DisplayState.ColorRating < _pEp_color.pEp_rating_unreliable))
Dean@807
  1023
            {
Dean@1074
  1024
                result = System.Windows.Forms.MessageBox.Show(this.ParentForm,
Dean@1074
  1025
                                                              pEp.Properties.Resources.Message_WarningPreviouslyEncrypted,
Dean@1074
  1026
                                                              pEp.Properties.Resources.Message_TitleConfirmOperation,
Dean@1074
  1027
                                                              MessageBoxButtons.YesNo);
Dean@807
  1028
Dean@807
  1029
                if (result == DialogResult.No)
Dean@807
  1030
                {
Dean@807
  1031
                    // Cancel sending
Dean@807
  1032
                    cancel = true;
Dean@807
  1033
                }
Dean@807
  1034
            }
Dean@807
  1035
Dean@682
  1036
            // Stop and disconnect the refresh timer
Dean@682
  1037
            // This is necessary so an ongoing refresh doesn't try to access a mail item as it's being moved
Dean@807
  1038
            if (cancel == false)
Dean@807
  1039
            {
Dean@807
  1040
                this.TimerRefresh.Stop();
Dean@807
  1041
                this.TimerRefresh.Enabled = false;
Dean@807
  1042
                this.TimerRefresh.Tick -= TimerRefresh_Tick;
Dean@807
  1043
            }
Dean@682
  1044
Dean@682
  1045
            return;
Dean@682
  1046
        }
Dean@682
  1047
Dean@682
  1048
        /// <summary>
Dean@169
  1049
        /// Event handler for when a mail item property is changed.
Dean@169
  1050
        /// See: https://msdn.microsoft.com/en-us/library/office/ff866739.aspx
Dean@169
  1051
        /// </summary>
Dean@169
  1052
        /// <param name="propertyName">The name of the property that was changed.</param>
Dean@445
  1053
        private void MailItem_PropertyChanged(object sender, PropertyChangedEventArgs e)
Dean@159
  1054
        {
Dean@445
  1055
            switch (e.PropertyName.ToUpper())
Dean@159
  1056
            {
Dean@179
  1057
                case "TO":
Dean@1001
  1058
                    this.RequestColorRatingAndUIUpdate();
Dean@159
  1059
                    break;
Dean@1106
  1060
                    // Outlook bug: there are always both events, so one is enough
Dean@1106
  1061
                    //case "CC":
Dean@1106
  1062
                    //    this.RequestColorRatingAndUIUpdate();
Dean@1106
  1063
                    //    break;
Dean@159
  1064
            }
Dean@169
  1065
Dean@169
  1066
            return;
Dean@159
  1067
        }
Dean@159
  1068
Dean@179
  1069
        /// <summary>
Dean@1021
  1070
        /// Event handler for when the manager form is closed.
Dean@1021
  1071
        /// </summary>
Dean@1021
  1072
        private void ManagerForm_FormClosed(object sender, FormClosedEventArgs e)
Dean@1021
  1073
        {
Dean@1021
  1074
            // Remove the reference held in the FormRegionPrivacyStatus so it stops getting updated
Dean@1021
  1075
            if (this.managerForm != null)
Dean@1021
  1076
            {
Dean@1021
  1077
                this.managerForm.FormClosed -= ManagerForm_FormClosed;
Dean@1021
  1078
                this.managerForm = null;
Dean@1021
  1079
            }
Dean@1021
  1080
Dean@1021
  1081
            return;
Dean@1021
  1082
        }
Dean@1021
  1083
Dean@1021
  1084
        /// <summary>
Dean@859
  1085
        /// Event handler for when the pEp website hyperlink is clicked.
Dean@859
  1086
        /// </summary>
Dean@859
  1087
        private void LinkLabelUpgrade_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
Dean@859
  1088
        {
Dean@966
  1089
            try
Dean@966
  1090
            {
Dean@1007
  1091
                Process.Start(Globals.PEP_WEBSITE_UPGRADE_LINK);
Dean@966
  1092
            }
Dean@966
  1093
            catch (Exception ex)
Dean@966
  1094
            {
Dean@1007
  1095
                Globals.Log("LinkLabelUpgrade_LinkClicked: Unable to open website link, " + ex.ToString());
Dean@966
  1096
            }
Dean@966
  1097
Dean@859
  1098
            return;
Dean@859
  1099
        }
Dean@1047
  1100
Dean@1047
  1101
        /// <summary>
Dean@1086
  1102
        /// Event handler for when the privacy view button is clicked within the form control.
Dean@1047
  1103
        /// </summary>
Dean@1086
  1104
        private void FormControlPrivacyStatusChild_PrivacyViewClick(object sender, System.Windows.RoutedEventArgs e)
Dean@1047
  1105
        {
Dean@1047
  1106
            this.RequestColorRatingAndUIUpdate();
Dean@1047
  1107
            this.BuildAndShowManager();
Dean@1047
  1108
            return;
Dean@1047
  1109
        }
vb@133
  1110
    }
vb@133
  1111
}