UI/FormRegionPrivacyStatus.cs
author Dean
Thu, 27 Oct 2016 12:36:01 +0200
changeset 1390 223d68887143
parent 1385 86376048af74
child 1402 4322d0b8e8ed
permissions -rw-r--r--
OUT-139: Support changing whether pEp is enabled/disabled from the SendUsingAccount in drafts.
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@1138
    31
                Outlook.MailItem omi;
Dean@1138
    32
Dean@1138
    33
                try
Dean@1138
    34
                {
Dean@1138
    35
                    omi = (Outlook.MailItem)e.OutlookItem;
Dean@1138
    36
                }
Dean@1138
    37
                catch
Dean@1138
    38
                {
Dean@1138
    39
                    // Never load if it's not a MailItem
Dean@1138
    40
                    e.Cancel = true;
Dean@1138
    41
                    return;
Dean@1138
    42
                }
Dean@1138
    43
Dean@985
    44
                //WindowFormRegionCollection formRegions;
Dean@327
    45
Dean@327
    46
                /* There is a Microsoft bug at least in Outlook 2013 and Windows 8.1
Dean@327
    47
                 * This bug causes multiple PrivacyStatus form regions to appear stacked on top of each other.
Dean@327
    48
                 * To trigger this bug, on an unencrypted server, click reply to compose an in-line response.
Dean@327
    49
                 * Then click to another tab such as People or Tasks. Then click back on the mail tab to view 
Dean@327
    50
                 * the original email again. Two form regions will be visible: 
Dean@327
    51
                 * (1) for the status during the in-line reply and 
Dean@327
    52
                 * (2) for the status of only the received message.
Dean@327
    53
                 * 
Dean@327
    54
                 * To fix this bug, any existing form regions are found and closed when initializing a new privacy status
Dean@327
    55
                 * form region.
Dean@327
    56
                 */
Dean@985
    57
                /*
Dean@327
    58
                try
Dean@327
    59
                {
Dean@987
    60
                    formRegions = Globals.FormRegions[Globals.ThisAddIn.Application.ActiveWindow()];
Dean@327
    61
                    if (formRegions.FormRegionPrivacyStatus != null)
Dean@327
    62
                    {
Dean@985
    63
                        // Note: there seems to be no way to actually close the form region.
Dean@985
    64
                        // Therefore, this is as close as possible to actually closing it.
Dean@985
    65
                        // The actual form regions will be cleaned up as soon as another email is selected.
Dean@327
    66
                        formRegions.FormRegionPrivacyStatus.OutlookFormRegion.Visible = false;
Dean@327
    67
                    }
Dean@327
    68
                }
Dean@327
    69
                catch { }
Dean@985
    70
                */
Dean@1169
    71
Dean@327
    72
                return;
vb@133
    73
            }
vb@133
    74
        }
vb@133
    75
vb@133
    76
        #endregion
vb@133
    77
Dean@159
    78
        /* Notes:
Dean@179
    79
         * 
Dean@159
    80
         * Use this.OutlookItem to get a reference to the current Outlook item.
Dean@159
    81
         * Use this.OutlookFormRegion to get a reference to the form region.
Dean@179
    82
         * 
Dean@179
    83
         * UI State Managment:
Dean@179
    84
         * 
Dean@179
    85
         * The UI state is almost entirely set from the associated mail item data.
Dean@179
    86
         * However, a separate state class is maintained to represent the UI as some separation is needed.
Dean@179
    87
         * This logical separation MUST be maintained throughout the code.
Dean@179
    88
         * Specific cases are noted where possible.
Dean@179
    89
         * 
Dean@356
    90
         * The separate privacy status manager form state is also managed here.
Dean@159
    91
         */
Dean@159
    92
Dean@1384
    93
        /// <summary>
Dean@1384
    94
        /// Event for when the form region is expanded or collapsed.
Dean@1384
    95
        /// </summary>
Dean@1384
    96
        public event EventHandler Expanded;
Dean@1384
    97
Dean@1390
    98
        private CryptableMailItem       cryptableMailItem      = null;
Dean@1390
    99
        private bool                    displayMirrorRequested = false;
Dean@1390
   100
        private bool                    isEnabled              = true;
Dean@1384
   101
        private bool?                   isExpandedPrevious     = null;
Dean@1390
   102
        private bool                    isManagerFormEnabled   = true;
Dean@1390
   103
        private bool                    isStarted              = false;
Dean@758
   104
        private FormManagePrivacyStatus managerForm            = null;
Dean@758
   105
        private bool                    refreshOngoing         = false;
Dean@259
   106
Dean@159
   107
        /**************************************************************
Dean@159
   108
         * 
Dean@1375
   109
         * Property Accessors
Dean@1375
   110
         * 
Dean@1375
   111
         *************************************************************/
Dean@1375
   112
Dean@1375
   113
        /// <summary>
Dean@1377
   114
        /// Gets or sets the displayed state.
Dean@1375
   115
        /// </summary>
Dean@1377
   116
        public FormControlPrivacyStatus.State DisplayState
Dean@1375
   117
        {
Dean@1377
   118
            get { return (this.FormControlPrivacyStatusChild.DisplayState); }
Dean@1377
   119
            set { this.FormControlPrivacyStatusChild.DisplayState = value; }
Dean@1375
   120
        }
Dean@1375
   121
Dean@1375
   122
        /**************************************************************
Dean@1375
   123
         * 
Dean@159
   124
         * Methods
Dean@159
   125
         * 
Dean@159
   126
         *************************************************************/
Dean@159
   127
Dean@171
   128
        /// <summary>
Dean@438
   129
        /// Determines if this form region is running in an inspector window.
Dean@438
   130
        /// If not true, it is assumed to be within an explorer window.
Dean@438
   131
        /// </summary>
Dean@438
   132
        /// <returns>True if an inspector window, false if within an explorer.</returns>
Dean@438
   133
        private bool IsWithinInspector()
Dean@438
   134
        {
Dean@438
   135
            bool isWithinInspector = false;
Dean@895
   136
            Outlook.Inspector insp = null;
Dean@438
   137
Dean@438
   138
            try
Dean@438
   139
            {
Dean@895
   140
                /* There are two potential methods to determine if the item is within an inspector.
Dean@895
   141
                 * (1) Use this.OutlookFormRegion.Parent which will contain either the Explorer or an Inspector
Dean@895
   142
                 *     A cast could be tried to an Explorer of this parent and if it fails, it's assumed to be an inspector
Dean@895
   143
                 * (2) Use this.OutlookFormRegion.Inspector which will contain the Inspector if it exists.
Dean@895
   144
                 *     This will fail or return null if this form region is not running within it's own Inspector window.
Dean@895
   145
                 */
Dean@895
   146
                insp = this.OutlookFormRegion.Inspector;
Dean@895
   147
Dean@895
   148
                if (insp != null)
Dean@895
   149
                {
Dean@895
   150
                    isWithinInspector = true;
Dean@895
   151
                }
Dean@438
   152
            }
Dean@438
   153
            catch
Dean@438
   154
            {
Dean@895
   155
                isWithinInspector = false;
Dean@438
   156
            }
Dean@438
   157
            finally
Dean@438
   158
            {
Dean@895
   159
                if (insp != null)
Dean@438
   160
                {
Dean@895
   161
                    Marshal.ReleaseComObject(insp);
Dean@895
   162
                    insp = null;
Dean@438
   163
                }
Dean@438
   164
            }
Dean@438
   165
Dean@438
   166
            return (isWithinInspector);
Dean@438
   167
        }
Dean@438
   168
Dean@438
   169
        /// <summary>
Dean@672
   170
        /// Completes the handshake process when the identity of a partner was previously marked as mistrusted.
Dean@281
   171
        /// </summary>
Dean@646
   172
        /// <param name="myself">The personal identity to complete the handshake with.</param>
Dean@646
   173
        /// <param name="partner">The identity of the partner to complete the handshake with.</param>
Dean@672
   174
        private void DoHandshakeForMistrustedKey(PEPIdentity myself,
Dean@672
   175
                                                 PEPIdentity partner)
Dean@281
   176
        {
Dean@281
   177
            DialogResult result;
Dean@281
   178
Dean@1074
   179
            result = System.Windows.Forms.MessageBox.Show(this.ParentForm,
Dean@1074
   180
                                                          pEp.Properties.Resources.Message_WarningMistrustedKey,
Dean@1074
   181
                                                          pEp.Properties.Resources.Message_TitleConfirmOperation,
Thomas@1184
   182
                                                          MessageBoxButtons.YesNo,
Thomas@1184
   183
                                                          MessageBoxIcon.Warning);
Dean@281
   184
Dean@423
   185
            if (result == DialogResult.Yes)
Dean@281
   186
            {
Dean@646
   187
                this.DoHandshake(myself, partner);
Dean@281
   188
            }
Dean@281
   189
Dean@281
   190
            return;
Dean@281
   191
        }
Dean@281
   192
Dean@281
   193
        /// <summary>
Dean@281
   194
        /// Completes the handshake process where the identity of a partner is confirmed.
Dean@179
   195
        /// </summary>
Dean@646
   196
        /// <param name="myself">The personal identity to complete the handshake with.</param>
Dean@646
   197
        /// <param name="partner">The identity of the partner to complete the handshake with.</param>
Dean@646
   198
        private void DoHandshake(PEPIdentity myself,
Dean@646
   199
                                 PEPIdentity partner)
vb@133
   200
        {
Dean@179
   201
            DialogResult result;
Dean@155
   202
            FormHandshake handshakeDialog;
markus@201
   203
Dean@1249
   204
            Log.Verbose("DoHandshake: Handshake started.");
vb@139
   205
Dean@155
   206
            // Create and show handshake dialog
Dean@1075
   207
            handshakeDialog = new FormHandshake();
Dean@1082
   208
            handshakeDialog.StartPosition = FormStartPosition.CenterParent;
Dean@1377
   209
            handshakeDialog.DisplayState = new FormControlHandshake.State(myself, partner,
Dean@1377
   210
                                                                          Globals.ThisAddIn.Settings.TrustwordsCulture);
Dean@1086
   211
Dean@179
   212
            result = handshakeDialog.ShowDialog(this);
Dean@646
   213
            this.ProcessDoHandshakeResult(result, partner);
Dean@356
   214
Dean@356
   215
            return;
Dean@356
   216
        }
Dean@356
   217
Dean@356
   218
        /// <summary>
Dean@356
   219
        /// Processes the result of the do handshake dialog after a user makes a selection.
Dean@356
   220
        /// </summary>
Dean@356
   221
        /// <param name="result">The result of the handshake dialog selection.</param>
Dean@356
   222
        /// <param name="partner">The identity of the partner to handshake with.</param>
Dean@356
   223
        private void ProcessDoHandshakeResult(DialogResult result,
Dean@384
   224
                                              PEPIdentity partner)
Dean@356
   225
        {
markus@1337
   226
            pEpRating partnerIdentityRating;
markus@1337
   227
            pEpColor partnerIdentityColor;
markus@1337
   228
            pEpIdentity identityPartner = ThisAddIn.PEPEngine.UpdateIdentity(partner.ToCOMType());
vb@133
   229
vb@133
   230
            switch (result)
vb@133
   231
            {
vb@133
   232
                case DialogResult.Yes:
Dean@279
   233
                    {
Dean@1310
   234
                        // Get the rating/color to determine if key was previously mistrusted -- warning to user must be displayed earlier
Dean@1295
   235
                        try
Dean@281
   236
                        {
markus@1337
   237
                            partnerIdentityRating = ThisAddIn.PEPEngine.IdentityRating(identityPartner);
Dean@1310
   238
                        }
Dean@1310
   239
                        catch (COMException ex)
Dean@1310
   240
                        {
markus@1337
   241
                            partnerIdentityRating = pEpRating.pEpRatingUndefined;
Dean@1310
   242
                            Log.Warning("ProcessDoHandshakeResult: Failed to get identity rating, " + ex.ToString());
Dean@1310
   243
                        }
Dean@1341
   244
                        partnerIdentityColor = partnerIdentityRating.ToColor();
Dean@1310
   245
Dean@1310
   246
                        // Process result
Dean@1310
   247
                        try
Dean@1310
   248
                        {
markus@1337
   249
                            if (partnerIdentityColor == pEpColor.pEpColorRed)
Dean@1295
   250
                            {
markus@1337
   251
                                ThisAddIn.PEPEngine.KeyResetTrust(ref identityPartner);
Dean@1295
   252
                            }
Dean@1295
   253
markus@1337
   254
                            identityPartner = ThisAddIn.PEPEngine.TrustPersonalKey(ref identityPartner);
Dean@281
   255
                        }
Dean@1295
   256
                        catch (Exception ex)
Dean@1295
   257
                        {
Dean@1295
   258
                            Log.Error("ProcessDoHandshakeResult: Error occured while trying to set trust: " + ex.ToString());
Dean@1295
   259
                        }
Dean@279
   260
Dean@1130
   261
                        this.ImmediateRatingAndUIUpdate();
Dean@1117
   262
                        this.UpdateManagePrivacyStatusForm();
Dean@279
   263
Dean@279
   264
                        break;
Dean@279
   265
                    }
vb@133
   266
                case DialogResult.No:
Dean@279
   267
                    {
Dean@1295
   268
                        try
Dean@1295
   269
                        {
markus@1337
   270
                            ThisAddIn.PEPEngine.KeyMistrusted(ref identityPartner);
Dean@1295
   271
                        }
Dean@1295
   272
                        catch (Exception ex)
Dean@1295
   273
                        {
Dean@1295
   274
                            Log.Error("ProcessDoHandshakeResult: Error occured while trying to mistrust key: " + ex.ToString());
Dean@1295
   275
                        }
Dean@279
   276
Dean@1130
   277
                        this.ImmediateRatingAndUIUpdate();
Dean@1117
   278
                        this.UpdateManagePrivacyStatusForm();
Dean@279
   279
Dean@279
   280
                        break;
Dean@279
   281
                    }
vb@133
   282
            }
Dean@279
   283
Dean@1249
   284
            Log.Verbose("ProcessDoHandshakeResult: Handshake complete.");
Dean@740
   285
Dean@279
   286
            return;
vb@133
   287
        }
vb@133
   288
Dean@179
   289
        /// <summary>
Dean@179
   290
        /// Reverses any past handshake confirmation by unconfirming the given identity partner.
Dean@179
   291
        /// </summary>
Dean@384
   292
        /// <param name="partner">The identity of the partner to unconfirm.</param>
Dean@384
   293
        private void UndoHandshake(PEPIdentity partner)
vb@133
   294
        {
markus@1337
   295
            pEpIdentity identityPartner = ThisAddIn.PEPEngine.UpdateIdentity(partner.ToCOMType());
markus@1337
   296
            ThisAddIn.PEPEngine.KeyResetTrust(ref identityPartner);
Dean@279
   297
Dean@1130
   298
            this.ImmediateRatingAndUIUpdate();
Dean@1117
   299
            this.UpdateManagePrivacyStatusForm();
Dean@279
   300
Dean@279
   301
            return;
vb@133
   302
        }
vb@133
   303
Dean@161
   304
        /// <summary>
Dean@279
   305
        /// Builds a new manager form state using this encryption state/mail item current state.
Dean@279
   306
        /// </summary>
Dean@279
   307
        /// <returns>A new manager form state.</returns>
Dean@1069
   308
        private FormControlManagePrivacyStatus.State GetManagerState()
Dean@279
   309
        {
Dean@737
   310
            int currIndex = 0;
Dean@527
   311
            bool isMyself;
Dean@364
   312
            string trustwordsShort;
Dean@364
   313
            string trustwordsFull;
Dean@1069
   314
            BitmapImage imageForceUnencOn;
Dean@1069
   315
            BitmapImage imageGreen;
Dean@1069
   316
            BitmapImage imageNoColor;
Dean@1069
   317
            BitmapImage imageRed;
Dean@1069
   318
            BitmapImage imageYellow;
Dean@384
   319
            List<PEPIdentity> identities;
Dean@1106
   320
            PEPIdentity identity;
Dean@384
   321
            PEPIdentity myIdentity;
Dean@259
   322
            SelectionItem item;
Dean@1069
   323
            FormControlManagePrivacyStatus.State managerState = new FormControlManagePrivacyStatus.State();
Dean@1069
   324
Dean@1390
   325
            if (this.cryptableMailItem != null)
Dean@769
   326
            {
Dean@1298
   327
                // Load all images from resources
Dean@1298
   328
                imageForceUnencOn = new BitmapImage(new Uri("pack://application:,,,/pEp;component/Resources/ImageForceUnencOn.png", UriKind.RelativeOrAbsolute));
Dean@1298
   329
                imageGreen = new BitmapImage(new Uri("pack://application:,,,/pEp;component/Resources/ImagePrivacyStatusGreen.png", UriKind.RelativeOrAbsolute));
Dean@1298
   330
                imageNoColor = new BitmapImage(new Uri("pack://application:,,,/pEp;component/Resources/ImagePrivacyStatusNoColor.png", UriKind.RelativeOrAbsolute));
Dean@1298
   331
                imageRed = new BitmapImage(new Uri("pack://application:,,,/pEp;component/Resources/ImagePrivacyStatusRed.png", UriKind.RelativeOrAbsolute));
Dean@1298
   332
                imageYellow = new BitmapImage(new Uri("pack://application:,,,/pEp;component/Resources/ImagePrivacyStatusYellow.png", UriKind.RelativeOrAbsolute));
Dean@1298
   333
Dean@1390
   334
                // Resolve all recipients -- this ensures the identities list is correctly populated
Dean@1390
   335
                this.ResolveAllRecipients();
Dean@332
   336
Dean@1298
   337
                managerState.Rating = this.FormControlPrivacyStatusChild.DisplayState.Rating;
Dean@1390
   338
                managerState.IsIncoming = this.cryptableMailItem.IsIncoming;
Dean@259
   339
Dean@1298
   340
                // Get identities
Dean@1390
   341
                identities = this.cryptableMailItem.Recipients;
Dean@1390
   342
                myIdentity = this.cryptableMailItem.Myself;
Dean@1106
   343
Dean@1298
   344
                // Include the from identity for incoming messages at the beginning
Dean@1390
   345
                identity = this.cryptableMailItem.From;
Dean@1390
   346
                if ((this.cryptableMailItem.IsIncoming) &&
Dean@1298
   347
                    (identity != null))
Dean@1298
   348
                {
Dean@1298
   349
                    identities.Insert(0, identity);
Dean@1298
   350
                }
Dean@259
   351
Dean@1298
   352
                // Remove own identity in the MailItem from the list
Dean@1298
   353
                if (myIdentity != null)
Dean@638
   354
                {
Dean@1298
   355
                    for (int i = (identities.Count - 1); i >= 0; i--)
Dean@1106
   356
                    {
Dean@1298
   357
                        if ((identities[i] != null) &&
Dean@1298
   358
                            (identities[i].EqualsByAddress(myIdentity)))
Dean@1298
   359
                        {
Dean@1298
   360
                            identities.RemoveAt(i);
Dean@1298
   361
                        }
Dean@1106
   362
                    }
Dean@638
   363
                }
Dean@366
   364
Dean@1298
   365
                // Add identities
Dean@1298
   366
                identities = PEPIdentity.ToFlatList(identities);
Dean@1298
   367
                managerState.Identities.Clear();
Dean@1298
   368
                foreach (PEPIdentity ident in identities)
Dean@1298
   369
                {
Dean@1298
   370
                    // Needed so index can be used within anonymous methods without getting into the 'outer variable trap' of currIndex
Dean@1298
   371
                    int index = currIndex;
Dean@737
   372
Dean@1298
   373
                    if (ident.IsAddressValid)
Dean@1298
   374
                    {
Dean@1298
   375
                        // Update the partner identity to get a fingerprint, preserve IsForceUnencrypted
markus@1337
   376
                        pEpIdentity partnerIdentity_s = ThisAddIn.PEPEngine.UpdateIdentity(ident.ToCOMType());
Dean@1298
   377
                        PEPIdentity partnerIdentity = new PEPIdentity(partnerIdentity_s);
Dean@1298
   378
                        partnerIdentity.IsForceUnencrypted = ident.IsForceUnencrypted;
Dean@774
   379
Dean@1298
   380
                        try
Dean@1298
   381
                        {
Dean@1362
   382
                            partnerIdentity.Rating = ThisAddIn.PEPEngine.IdentityRating(partnerIdentity_s);
Dean@1298
   383
                        }
Dean@1298
   384
                        catch (COMException ex)
Dean@1298
   385
                        {
Dean@1362
   386
                            partnerIdentity.Rating = pEpRating.pEpRatingUndefined;
Dean@1298
   387
                            Log.Warning("GetManagerState: Failed to get identity rating, " + ex.ToString());
Dean@1298
   388
                        }
Dean@1018
   389
Dean@1298
   390
                        isMyself = PEPIdentity.GetIsOwnIdentity(partnerIdentity.Address);
Dean@724
   391
Dean@1298
   392
                        // Calculate trustwords
Dean@1298
   393
                        Globals.ThisAddIn.CalcTrustwords(myIdentity,
Dean@1298
   394
                                                         partnerIdentity,
Dean@1298
   395
                                                         out trustwordsShort,
Dean@1298
   396
                                                         out trustwordsFull,
Dean@1298
   397
                                                         Globals.ThisAddIn.Settings.TrustwordsCulture?.TwoLetterISOLanguageName);
Dean@880
   398
Dean@1298
   399
                        item = new SelectionItem();
Dean@1348
   400
                        item.TextLine1 = partnerIdentity.UserName;
Dean@1298
   401
                        item.TextLine2 = partnerIdentity.Address;
Dean@1298
   402
                        item.Tag = (string.IsNullOrWhiteSpace(partnerIdentity.Fingerprint) ? null : trustwordsShort);
Dean@259
   403
Dean@1298
   404
                        // Don't show both the user name and address if they are the same
Dean@1298
   405
                        if ((item.TextLine1 != null) &&
Dean@1298
   406
                            (item.TextLine2 != null) &&
Dean@1298
   407
                            (item.TextLine1 == item.TextLine2))
Dean@1298
   408
                        {
Dean@1298
   409
                            item.IsTwoTextLinesVisible = false;
Dean@1298
   410
                        }
Dean@332
   411
Dean@1298
   412
                        // Set image
Dean@1298
   413
                        if ((partnerIdentity.IsForceUnencryptedBool) &&
Dean@1298
   414
                            (managerState.IsIncoming == false))
Dean@641
   415
                        {
Dean@1298
   416
                            item.ItemImage = imageForceUnencOn;
Dean@641
   417
                        }
Dean@1298
   418
                        else
Dean@1298
   419
                        {
Dean@1362
   420
                            switch (partnerIdentity.Rating.ToColor())
Dean@1298
   421
                            {
markus@1337
   422
                                case pEpColor.pEpColorGreen:
Dean@1298
   423
                                    item.ItemImage = imageGreen;
Dean@1298
   424
                                    break;
markus@1337
   425
                                case pEpColor.pEpColorYellow:
Dean@1298
   426
                                    item.ItemImage = imageYellow;
Dean@1298
   427
                                    break;
markus@1337
   428
                                case pEpColor.pEpColorRed:
Dean@1298
   429
                                    item.ItemImage = imageRed;
Dean@1298
   430
                                    break;
markus@1337
   431
                                case pEpColor.pEpColorNoColor:
Dean@1298
   432
                                    item.ItemImage = imageNoColor;
Dean@1298
   433
                                    break;
Dean@1298
   434
                                default:
Dean@1298
   435
                                    item.ItemImage = null;
Dean@1298
   436
                                    break;
Dean@1298
   437
                            }
Dean@1298
   438
                        }
Dean@259
   439
Dean@1298
   440
                        // Set button
Dean@1298
   441
                        if ((isMyself) ||
Dean@1298
   442
                            ((partnerIdentity.IsForceUnencryptedBool) &&
Dean@1298
   443
                             (managerState.IsIncoming == false)))
Dean@485
   444
                        {
Dean@1298
   445
                            item.IsButtonVisible = false;
Dean@641
   446
                            item.IsExpandable = false;
Dean@485
   447
                        }
Dean@485
   448
                        else
Dean@485
   449
                        {
Dean@1362
   450
                            switch (partnerIdentity.Rating.ToColor())
Dean@1298
   451
                            {
Dean@1362
   452
                                case pEpColor.pEpColorGreen:
Dean@1362
   453
                                    {
Dean@1362
   454
                                        // Undo handshake
Dean@1362
   455
                                        item.TextButton = pEp.Properties.Resources.PrivacyStatus_StopTrusting;
Dean@1362
   456
                                        item.IsButtonVisible = true;
Dean@1362
   457
                                        item.ButtonOnClick = (x, y) => { this.UndoHandshake(partnerIdentity.Copy()); };
Dean@1298
   458
Dean@1362
   459
                                        item.IsExpandable = false;
Dean@1298
   460
Dean@1362
   461
                                        break;
Dean@1362
   462
                                    }
Dean@1362
   463
                                case pEpColor.pEpColorYellow:
Dean@1362
   464
                                    {
Dean@1362
   465
                                        // Do handshake
Dean@1362
   466
                                        item.TextButton = pEp.Properties.Resources.PrivacyStatus_Handshake;
Dean@1362
   467
                                        item.IsButtonVisible = true;
Dean@1362
   468
                                        item.ButtonOnClick = (x, y) => { this.DoHandshake(myIdentity.Copy(), partnerIdentity.Copy()); };
Dean@1298
   469
Dean@1362
   470
                                        item.IsExpandable = true;
Dean@1362
   471
                                        item.ExpandedText = pEp.Properties.Resources.Handshake_ConfirmTrustwordsText + "\n\n" +
Dean@1362
   472
                                                            trustwordsShort;
Dean@1298
   473
Dean@1362
   474
                                        item.ExpandedButton1Text = pEp.Properties.Resources.Handshake_ConfirmText;
Dean@1362
   475
                                        item.ExpandedButton1OnClick = (x, y) => { this.ProcessDoHandshakeResult(DialogResult.Yes, partnerIdentity.Copy()); };
Dean@1362
   476
                                        item.ExpandedButton1Style = (Style)Globals.ResourceDict["StyleConfirmButton"];
Dean@1362
   477
Dean@1362
   478
                                        item.ExpandedButton2Text = pEp.Properties.Resources.Handshake_CancelText;
Dean@1362
   479
                                        item.ExpandedButton2OnClick = (x, y) =>
Dean@1362
   480
                                        {
Dean@1362
   481
                                            SelectionItem selItem;
Dean@1362
   482
                                            FormControlManagePrivacyStatus.State activeState;
Dean@1362
   483
Dean@1362
   484
                                            if (this.managerForm != null)
Dean@1362
   485
                                            {
Dean@1377
   486
                                                activeState = this.managerForm.DisplayState;
Dean@1362
   487
Dean@1362
   488
                                                if ((index >= 0) &&
Dean@1362
   489
                                                    (index < activeState.Identities.Count))
Dean@1362
   490
                                                {
Dean@1362
   491
                                                    selItem = activeState.Identities[index];
Dean@1362
   492
                                                    selItem.TextButton = pEp.Properties.Resources.PrivacyStatus_Handshake;
Dean@1362
   493
                                                    selItem.IsExpanded = false;
Dean@1362
   494
                                                    selItem.IsExpandable = false;
Dean@1362
   495
                                                }
Dean@1362
   496
                                            }
Dean@1362
   497
                                        };
Dean@1362
   498
                                        item.ExpandedButton2Style = (Style)Globals.ResourceDict["StyleCancelButton"];
Dean@1362
   499
Dean@1362
   500
                                        item.ExpandedButton3Text = pEp.Properties.Resources.Handshake_WrongText;
Dean@1362
   501
                                        item.ExpandedButton3OnClick = (x, y) => { this.ProcessDoHandshakeResult(DialogResult.No, partnerIdentity.Copy()); };
Dean@1362
   502
                                        item.ExpandedButton3Style = (Style)Globals.ResourceDict["StyleWrongButton"];
Dean@1362
   503
Dean@1362
   504
                                        break;
Dean@1362
   505
                                    }
Dean@1362
   506
                                case pEpColor.pEpColorRed:
Dean@1298
   507
                                    {
Dean@1362
   508
                                        // Redo handshake with confirmation
Dean@1362
   509
                                        item.TextButton = pEp.Properties.Resources.PrivacyStatus_Handshake;
Dean@1362
   510
                                        item.IsButtonVisible = true;
Dean@1362
   511
                                        item.ButtonOnClick = (x, y) => { this.DoHandshakeForMistrustedKey(myIdentity.Copy(), partnerIdentity.Copy()); };
Dean@1298
   512
Dean@1362
   513
                                        item.IsExpandable = false;
Dean@1298
   514
Dean@1362
   515
                                        break;
Dean@1362
   516
                                    }
Dean@1362
   517
                                default:
Dean@1362
   518
                                    {
Dean@1362
   519
                                        item.IsButtonVisible = false;
Dean@1362
   520
                                        item.IsExpandable = false;
Dean@1362
   521
                                        break;
Dean@1362
   522
                                    }
Dean@1298
   523
                            }
Dean@485
   524
                        }
Dean@366
   525
                    }
Dean@1298
   526
                    else // Invalid identity
Dean@1298
   527
                    {
Dean@1298
   528
                        item = new SelectionItem();
Dean@1348
   529
                        item.TextLine1 = ident.UserName;
Dean@1298
   530
                        item.TextLine2 = ident.Address;
Dean@1298
   531
                        item.ItemImage = null;
Dean@1298
   532
                        item.IsTwoTextLinesVisible = true;
Dean@1298
   533
                        item.IsButtonVisible = false;
Dean@1298
   534
                    }
Dean@1298
   535
Dean@1298
   536
                    managerState.Identities.Add(item);
Dean@1298
   537
                    currIndex++;
Dean@259
   538
                }
Dean@259
   539
Dean@1298
   540
                // Attempt to select and expand the first identity requiring a handshake
Dean@1298
   541
                for (int i = 0; i < managerState.Identities.Count; i++)
Dean@375
   542
                {
Dean@1298
   543
                    // Determine if it's a handshake identity by checking if it's expandable
Dean@1298
   544
                    if (managerState.Identities[i].IsExpandable)
Dean@1298
   545
                    {
Dean@1298
   546
                        managerState.Identities[i].TextButton = Properties.Resources.PrivacyStatus_HandshakeAdvanced;
Dean@1298
   547
                        managerState.Identities[i].IsExpanded = true;
Dean@1298
   548
                        managerState.SelectedIdentityIndex = i;
Dean@1298
   549
                        break;
Dean@1298
   550
                    }
Dean@375
   551
                }
Dean@375
   552
            }
Dean@375
   553
Dean@279
   554
            return (managerState);
Dean@279
   555
        }
Dean@279
   556
Dean@279
   557
        /// <summary>
Dean@279
   558
        /// Builds the latest state of the encryption status manager then shows the UI.
Dean@279
   559
        /// </summary>
Dean@279
   560
        private void BuildAndShowManager()
Dean@279
   561
        {
Dean@279
   562
            DialogResult result;
Dean@313
   563
            FormManagePrivacyStatus form;
Dean@279
   564
Dean@483
   565
            try
Dean@483
   566
            {
Dean@483
   567
                // Show the form
Dean@483
   568
                form = new FormManagePrivacyStatus();
Dean@1082
   569
                form.StartPosition = FormStartPosition.CenterParent;
Dean@1021
   570
                form.FormClosed += ManagerForm_FormClosed;
Dean@1377
   571
                form.DisplayState = this.GetManagerState();
Dean@259
   572
Dean@483
   573
                this.managerForm = form;
Dean@1073
   574
                result = form.ShowDialog(this.ParentForm);
Dean@483
   575
            }
Dean@483
   576
            catch (Exception ex)
Dean@483
   577
            {
Dean@860
   578
                Globals.StopAndSendCrashReport(ex);
Dean@483
   579
            }
Dean@259
   580
Dean@259
   581
            return;
Dean@259
   582
        }
Dean@259
   583
Dean@259
   584
        /// <summary>
Dean@1130
   585
        /// Schedules for the pEp rating and UI (including displayed mirror) to be updated.
Dean@1001
   586
        /// This can be called many times with no issue as the update is only run every n milliseconds.
Dean@179
   587
        /// </summary>
Dean@1130
   588
        public void RequestRatingAndUIUpdate()
Dean@1001
   589
        {
Dean@1390
   590
            if (this.isEnabled)
Dean@1390
   591
            {
Dean@1390
   592
                this.TimerRefresh.Enabled = true;
Dean@1390
   593
            }
Dean@1001
   594
            return;
Dean@1001
   595
        }
Dean@1001
   596
Dean@1001
   597
        /// <summary>
Dean@1130
   598
        /// Immediately starts the update of UI rating based on the associated mail item.
Dean@1001
   599
        /// This will start decryption as necessary and also will update the displayed mirror.
Dean@1001
   600
        /// This method by-passes the refresh timer completely.
Dean@1001
   601
        /// WARNING: This method assumes the message is fully downloaded already.
Dean@1001
   602
        /// </summary>
Dean@1130
   603
        private void ImmediateRatingAndUIUpdate()
Dean@159
   604
        {
Dean@1390
   605
            if ((this.isEnabled) &&
Dean@1390
   606
                (this.cryptableMailItem != null))
Dean@159
   607
            {
Dean@1301
   608
                Log.Verbose("ImmediateRatingAndUIUpdate: Starting processing.");
Dean@740
   609
Dean@1301
   610
                // Start the rating calculation/decryption process
Dean@1390
   611
                this.cryptableMailItem.StartProcessing();
Dean@159
   612
            }
Dean@159
   613
Dean@179
   614
            return;
Dean@159
   615
        }
Dean@159
   616
Dean@709
   617
        /// <summary>
Dean@1117
   618
        /// Immediately update the manage privacy status form display state.
Dean@1117
   619
        /// This by default will completely rebuild the display state.
Dean@1117
   620
        /// </summary>
Dean@1130
   621
        /// <param name="onlyRating">True to update only the rating, false to rebuild the entire display state.</param>
Dean@1130
   622
        private void UpdateManagePrivacyStatusForm(bool onlyRating = false)
Dean@1117
   623
        {
Dean@1117
   624
            if (this.managerForm != null)
Dean@1117
   625
            {
Dean@1130
   626
                if (onlyRating)
Dean@1117
   627
                {
Dean@1130
   628
                    // Only update the message rating
Dean@1377
   629
                    this.managerForm.DisplayState.Rating = this.FormControlPrivacyStatusChild.DisplayState.Rating;
Dean@1117
   630
                }
Dean@1117
   631
                else
Dean@1117
   632
                {
Dean@1117
   633
                    // Rebuild the entire display state which will update any identity changes
Dean@1377
   634
                    this.managerForm.DisplayState = this.GetManagerState();
Dean@1117
   635
                }
Dean@1117
   636
            }
Dean@1117
   637
Dean@1117
   638
            return;
Dean@1117
   639
        }
Dean@1117
   640
Dean@1117
   641
        /// <summary>
Dean@709
   642
        /// Clears the associated unencrypted preview and displays the given note (if any).
Dean@709
   643
        /// </summary>
Dean@709
   644
        /// <param name="note">The note to diplsay.</param>
Dean@709
   645
        private void ClearPreview(string note = null)
Dean@709
   646
        {
Dean@987
   647
            WindowFormRegionCollection formRegions = Globals.FormRegions[Globals.ThisAddIn.Application.ActiveWindow()];
Dean@709
   648
Dean@709
   649
            if ((formRegions != null) &&
Dean@709
   650
                (formRegions.FormRegionPreviewUnencrypted != null) &&
Dean@709
   651
                (formRegions.FormRegionPreviewUnencrypted.Visible))
Dean@709
   652
            {
Dean@709
   653
                formRegions.FormRegionPreviewUnencrypted.ClearMessage();
Dean@709
   654
                formRegions.FormRegionPreviewUnencrypted.SetNote(note);
Dean@709
   655
            }
Dean@709
   656
Dean@709
   657
            return;
Dean@709
   658
        }
Dean@709
   659
Dean@1390
   660
        /// <summary>
Dean@1390
   661
        /// Sets whether processing of the mail item is enabled.
Dean@1390
   662
        /// This should commonly be set from the .GetIsPEPEnabled() value.
Dean@1390
   663
        /// </summary>
Dean@1390
   664
        private void SetIsEnabled(bool enabled)
Dean@1390
   665
        {
Dean@1390
   666
            bool setByCache = false;
Dean@1390
   667
            PEPIdentity currIdent;
Dean@1390
   668
            Globals.ReturnStatus sts;
Dean@1390
   669
            Outlook.MailItem omi = null;
Dean@1390
   670
            Outlook.Recipient currUser = null;
Dean@1390
   671
            Outlook.Account currAccount = null;
Dean@1390
   672
            Outlook.Account sendingAccount = null;
Dean@1390
   673
            Outlook.NameSpace ns = null;
Dean@1390
   674
Dean@1390
   675
            this.OutlookFormRegion.Visible = enabled;
Dean@1390
   676
            this.isEnabled = enabled;
Dean@1390
   677
Dean@1390
   678
            if (enabled)
Dean@1390
   679
            {
Dean@1390
   680
                // Do not allow initialization more than once
Dean@1390
   681
                if (this.isStarted == false)
Dean@1390
   682
                {
Dean@1390
   683
                    /* It's possible for new draft MailItems to be created outside the context of an account.
Dean@1390
   684
                     * In this situation the SendUsingAccount will always be null which of course breaks several pEp operations.
Dean@1390
   685
                     * The operations themselves cannot make the assumption about what account information to use.
Dean@1390
   686
                     * Therefore, the situation is detected here and for draft mail items a null SendUsingAccount will be 
Dean@1390
   687
                     * set with the session's default account.
Dean@1390
   688
                     */
Dean@1390
   689
                    try
Dean@1390
   690
                    {
Dean@1390
   691
                        ns = Globals.ThisAddIn.Application.Session;
Dean@1390
   692
Dean@1390
   693
                        if ((this.OutlookItem is Outlook.MailItem) &&
Dean@1390
   694
                            ((Outlook.MailItem)this.OutlookItem).GetIsDraft())
Dean@1390
   695
                        {
Dean@1390
   696
                            omi = this.OutlookItem as Outlook.MailItem;
Dean@1390
   697
                            sendingAccount = omi.SendUsingAccount;
Dean@1390
   698
                            currUser = ns.CurrentUser;
Dean@1390
   699
Dean@1390
   700
                            if (sendingAccount == null)
Dean@1390
   701
                            {
Dean@1390
   702
                                sts = PEPIdentity.Create(currUser, out currIdent);
Dean@1390
   703
Dean@1390
   704
                                if (sts == Globals.ReturnStatus.Success)
Dean@1390
   705
                                {
Dean@1390
   706
                                    currAccount = PEPIdentity.GetOwnAccount(currIdent.Address);
Dean@1390
   707
                                    omi.SendUsingAccount = currAccount;
Dean@1390
   708
                                }
Dean@1390
   709
                            }
Dean@1390
   710
                        }
Dean@1390
   711
                    }
Dean@1390
   712
                    catch { }
Dean@1390
   713
                    finally
Dean@1390
   714
                    {
Dean@1390
   715
                        if (omi != null)
Dean@1390
   716
                        {
Dean@1390
   717
                            Marshal.ReleaseComObject(omi);
Dean@1390
   718
                            omi = null;
Dean@1390
   719
                        }
Dean@1390
   720
Dean@1390
   721
                        if (currUser != null)
Dean@1390
   722
                        {
Dean@1390
   723
                            Marshal.ReleaseComObject(currUser);
Dean@1390
   724
                            currUser = null;
Dean@1390
   725
                        }
Dean@1390
   726
Dean@1390
   727
                        if (currAccount != null)
Dean@1390
   728
                        {
Dean@1390
   729
                            Marshal.ReleaseComObject(currAccount);
Dean@1390
   730
                            currAccount = null;
Dean@1390
   731
                        }
Dean@1390
   732
Dean@1390
   733
                        if (sendingAccount != null)
Dean@1390
   734
                        {
Dean@1390
   735
                            Marshal.ReleaseComObject(sendingAccount);
Dean@1390
   736
                            sendingAccount = null;
Dean@1390
   737
                        }
Dean@1390
   738
Dean@1390
   739
                        if (ns != null)
Dean@1390
   740
                        {
Dean@1390
   741
                            Marshal.ReleaseComObject(ns);
Dean@1390
   742
                            ns = null;
Dean@1390
   743
                        }
Dean@1390
   744
                    }
Dean@1390
   745
Dean@1390
   746
                    // Set reader upgrade link visibility
Dean@1390
   747
                    if ((Globals.RELEASE_MODE == Globals.ReleaseMode.Reader) &&
Dean@1390
   748
                        (this.cryptableMailItem != null) &&
Dean@1390
   749
                        (this.cryptableMailItem.IsDraft))
Dean@1390
   750
                    {
Dean@1390
   751
                        this.FormControlPrivacyStatusChild.DisplayState.UpgradeLinkIsVisible = true;
Dean@1390
   752
                    }
Dean@1390
   753
                    else
Dean@1390
   754
                    {
Dean@1390
   755
                        this.FormControlPrivacyStatusChild.DisplayState.UpgradeLinkIsVisible = false;
Dean@1390
   756
                    }
Dean@1390
   757
Dean@1390
   758
                    /* For a MailItem being forwarded or replied to it's import to check against the encrypted conversation cache.
Dean@1390
   759
                     * This is normally done within CryptableMailItem_EncryptedConversationCacheUpdated; however,
Dean@1390
   760
                     * for trusted servers that use an in-line reponse, the EncryptedConversationCacheUpdated event occurs
Dean@1390
   761
                     * BEFORE the new mail item is created. This means it never sees the event.
Dean@1390
   762
                     * To get around this issue, when the form region is first shown, also check if the mail item
Dean@1390
   763
                     * exists in the encrypted conversation cache and should be marked as formerly encrypted.
Dean@1390
   764
                     * If this check passes, never event connect the CryptableMailItem_EncryptedConversationCacheUpdated event.
Dean@1390
   765
                     */
Dean@1390
   766
                    if (this.cryptableMailItem != null)
Dean@1390
   767
                    {
Dean@1390
   768
                        setByCache = this.cryptableMailItem.SetIsOriginallyEncryptedByCache();
Dean@1390
   769
                    }
Dean@1390
   770
Dean@1390
   771
                    // Connect events
Dean@1390
   772
                    if (setByCache == false) { CryptableMailItem.EncryptedConversationCacheUpdated += CryptableMailItem_EncryptedConversationCacheUpdated; }
Dean@1390
   773
                    this.FormControlPrivacyStatusChild.PrivacyViewClick += FormControlPrivacyStatusChild_PrivacyViewClick;
Dean@1390
   774
                    this.Expanded += FormRegionPrivacyStatus_Expanded;
Dean@1390
   775
Dean@1390
   776
                    this.TimerRefresh.Tick += TimerRefresh_Tick;
Dean@1390
   777
                    this.isStarted = true;
Dean@1390
   778
                }
Dean@1390
   779
            }
Dean@1390
   780
            else
Dean@1390
   781
            {
Dean@1390
   782
                // Disconnect events
Dean@1390
   783
                CryptableMailItem.EncryptedConversationCacheUpdated -= CryptableMailItem_EncryptedConversationCacheUpdated;
Dean@1390
   784
                this.FormControlPrivacyStatusChild.PrivacyViewClick -= FormControlPrivacyStatusChild_PrivacyViewClick;
Dean@1390
   785
                this.Expanded -= FormRegionPrivacyStatus_Expanded;
Dean@1390
   786
Dean@1390
   787
                // Stop and disconnect the refresh timer
Dean@1390
   788
                this.TimerRefresh.Stop();
Dean@1390
   789
                this.TimerRefresh.Enabled = false;
Dean@1390
   790
                this.TimerRefresh.Tick -= TimerRefresh_Tick;
Dean@1390
   791
Dean@1390
   792
                this.isStarted = false;
Dean@1390
   793
            }
Dean@1390
   794
Dean@1390
   795
            return;
Dean@1390
   796
        }
Dean@1390
   797
Dean@1390
   798
        /// <summary>
Dean@1390
   799
        /// Resolves all recipients of the Outlook mail item.
Dean@1390
   800
        /// </summary>
Dean@1390
   801
        private void ResolveAllRecipients()
Dean@1390
   802
        {
Dean@1390
   803
            if ((this.isEnabled) &&
Dean@1390
   804
                (this.cryptableMailItem != null))
Dean@1390
   805
            {
Dean@1390
   806
                /*
Dean@1390
   807
                 * Note: The PropertyChanged changed event must be disconnected before trying to resolve.
Dean@1390
   808
                 * This is because the resolve process can modify the contents of the mail item which triggers an event.
Dean@1390
   809
                 * The PropertyChanged event would then trigger a UI refresh cycle. However, because the GetManagerState itself 
Dean@1390
   810
                 * is called within the UI refresh, an infinite loop could occur trying to resolve a recipient that
Dean@1390
   811
                 * cannot be resolved(no address).
Dean@1390
   812
                 */
Dean@1390
   813
                this.cryptableMailItem.PropertyChanged -= MailItem_PropertyChanged;
Dean@1390
   814
                this.cryptableMailItem.ResolveAllRecipients();
Dean@1390
   815
                this.cryptableMailItem.PropertyChanged += MailItem_PropertyChanged;
Dean@1390
   816
            }
Dean@1390
   817
Dean@1390
   818
            return;
Dean@1390
   819
        }
Dean@1390
   820
Dean@159
   821
        /**************************************************************
Dean@159
   822
         * 
Dean@159
   823
         * Event Handling
Dean@159
   824
         * 
Dean@159
   825
         *************************************************************/
Dean@159
   826
Dean@159
   827
        /// <summary>
Dean@680
   828
        /// Event handler that is called when the form region is displayed.
Dean@1211
   829
        /// This is called each time the form region looses then regains visibility 
Dean@680
   830
        /// (for example an other email is selected then back to this one).
Dean@159
   831
        /// </summary>
Dean@312
   832
        private void FormRegionPrivacyStatus_FormRegionShowing(object sender, System.EventArgs e)
Dean@159
   833
        {
Dean@1390
   834
            // Set mail item
Dean@1390
   835
            if (this.OutlookItem is Outlook.MailItem)
Dean@1390
   836
            {
Dean@1390
   837
                this.cryptableMailItem = new CryptableMailItem((Outlook.MailItem)this.OutlookItem);
Dean@1390
   838
            }
Dean@1390
   839
            else
Dean@1390
   840
            {
Dean@1390
   841
                this.cryptableMailItem = null;
Dean@1390
   842
            }
Dean@1169
   843
Dean@1390
   844
            // Connect cryptable mail item events
Dean@1390
   845
            if (this.cryptableMailItem != null)
Dean@680
   846
            {
Dean@1197
   847
                try
Dean@1197
   848
                {
Dean@1390
   849
                    this.cryptableMailItem.PropertyChanged += MailItem_PropertyChanged;
Dean@1390
   850
                    this.cryptableMailItem.ProcessingCompleted += MailItem_ProcessingCompleted;
Dean@1390
   851
                    this.cryptableMailItem.GetMirrorCompleted += MailItem_GetMirrorCompleted;
Dean@1390
   852
                    this.cryptableMailItem.Send += MailItem_Send;
Dean@1390
   853
Dean@1390
   854
                    if (this.cryptableMailItem.IsSecurelyStored)
Dean@1197
   855
                    {
Dean@1390
   856
                        this.cryptableMailItem.Open += MailItem_Open;
Dean@1197
   857
                    }
Dean@1197
   858
                }
Dean@1197
   859
                catch { }
Dean@179
   860
            }
Dean@159
   861
Dean@1390
   862
            // Update pEp enabled status
Dean@1390
   863
            this.SetIsEnabled(((Outlook.MailItem)this.OutlookItem).GetIsPEPEnabled());
Dean@1390
   864
            if (this.isEnabled)
Dean@1390
   865
            {
Dean@1390
   866
                // Call the timer tick method manually to refresh data with no delay
Dean@1390
   867
                this.TimerRefresh_Tick(null, new EventArgs());
Dean@1390
   868
            }
Dean@179
   869
Dean@179
   870
            return;
Dean@159
   871
        }
Dean@159
   872
Dean@159
   873
        /// <summary>
Dean@159
   874
        /// Event handler for when the form region is closed.
Dean@159
   875
        /// </summary>
Dean@312
   876
        private void FormRegionPrivacyStatus_FormRegionClosed(object sender, System.EventArgs e)
Dean@159
   877
        {
Dean@1390
   878
            // Disconnect cryptable mail item
Dean@1390
   879
            if (this.cryptableMailItem != null)
Dean@179
   880
            {
Dean@179
   881
                try
Dean@179
   882
                {
Dean@1390
   883
                    this.cryptableMailItem.PropertyChanged -= MailItem_PropertyChanged;
Dean@1390
   884
                    this.cryptableMailItem.ProcessingCompleted -= MailItem_ProcessingCompleted;
Dean@1390
   885
                    this.cryptableMailItem.GetMirrorCompleted -= MailItem_GetMirrorCompleted;
Dean@1390
   886
                    this.cryptableMailItem.Open -= MailItem_Open;
Dean@1390
   887
                    this.cryptableMailItem.Send -= MailItem_Send;
Dean@179
   888
                }
Dean@179
   889
                catch { }
Dean@1390
   890
Dean@1390
   891
                this.cryptableMailItem.Dispose();
Dean@1390
   892
                this.cryptableMailItem = null;
Dean@179
   893
            }
Dean@179
   894
Dean@1390
   895
            // Disconnect other
Dean@1390
   896
            this.SetIsEnabled(false);
Dean@682
   897
Dean@179
   898
            return;
Dean@179
   899
        }
Dean@179
   900
Dean@179
   901
        /// <summary>
Dean@1384
   902
        /// Event handler for when the form region is expanded or collapsed.
Dean@1384
   903
        /// </summary>
Dean@1384
   904
        private void FormRegionPrivacyStatus_Expanded(object sender, EventArgs e)
Dean@1384
   905
        {
Dean@1385
   906
            /* This Outlook form region has a bug where clicking the '+' button to expand will also
Dean@1385
   907
             * raise a click event on the privacy status button. Basically, Outlook would fire the click event 
Dean@1385
   908
             * (FormControlPrivacyStatusChild_PrivacyViewClick) immediately after the region is expanded even though at 
Dean@1385
   909
             * the time it was clicked it was collapsed and the click already captured by the expander '+' button.
Dean@1385
   910
             * This code here works around that issue by disabling the manager form when the form region is collapsed.
Dean@1385
   911
             * Since the click event occurs BEFORE the expanded event, this will disable opening the manage privacy status
Dean@1385
   912
             * form in this situation.
Dean@1385
   913
             */
Dean@1390
   914
            this.isManagerFormEnabled = this.OutlookFormRegion.IsExpanded;
Dean@1384
   915
Dean@1384
   916
            return;
Dean@1384
   917
        }
Dean@1384
   918
Dean@1384
   919
        /// <summary>
Dean@1384
   920
        /// Event handler called after the monitor timer has elapsed.
Dean@1384
   921
        /// This should be used only for quick polling of changes in Outlook or the UI state.
Dean@1384
   922
        /// </summary>
Dean@1384
   923
        private void TimerMonitor_Tick(object sender, EventArgs e)
Dean@1384
   924
        {
Dean@1384
   925
            bool isExpandedCurrent;
Dean@1384
   926
Dean@1384
   927
            // Check for IsExpanded changes
Dean@1384
   928
            isExpandedCurrent = this.OutlookFormRegion.IsExpanded;
Dean@1384
   929
            if ((this.isExpandedPrevious == null) ||
Dean@1384
   930
                ((bool)this.isExpandedPrevious != isExpandedCurrent))
Dean@1384
   931
            {
Dean@1384
   932
                this.Expanded?.Invoke(this, new EventArgs());
Dean@1384
   933
            }
Dean@1384
   934
            this.isExpandedPrevious = isExpandedCurrent;
Dean@1384
   935
Dean@1384
   936
            return;
Dean@1384
   937
        }
Dean@1384
   938
Dean@1384
   939
        /// <summary>
Dean@179
   940
        /// Event handler called after the refresh timer has elapsed.
Dean@179
   941
        /// </summary>
Dean@179
   942
        private void TimerRefresh_Tick(object sender, EventArgs e)
Dean@179
   943
        {
Dean@199
   944
            bool tryAgain = false;
Dean@684
   945
            bool markForDownload = false;
Dean@179
   946
            this.TimerRefresh.Enabled = false; // Only once
Dean@684
   947
            Outlook.OlDownloadState dlState;
markus@201
   948
Dean@709
   949
            /* The Refresh/UI_Update process is a little more complicated here than other forms.
Dean@709
   950
             * There are the following components:
Dean@709
   951
             *   1. TimerRefresh_Tick
Dean@709
   952
             *        This is the main timer tick event handler called any time
Dean@1130
   953
             *        a refresh was requested (RequestRatingAndUIUpdate) and hasn't been run yet. 
Dean@1001
   954
             *        A refresh is requested either at initialization or when a property changes
Dean@709
   955
             *        (such as MailItem_PropertyChanged). It is on a timer as many 
Dean@709
   956
             *        property change events could occur rapidy, but only one refresh should
Dean@709
   957
             *        occur for performance reasons.
Dean@709
   958
             * 
Dean@1130
   959
             *   2. ImmediateRatingAndUIUpdate
Dean@1307
   960
             *        This will re-calculate the mail item's rating.
Dean@1307
   961
             *        This internally just calls CryptableMailItem.StartProcessing.
Dean@709
   962
             * 
Dean@1130
   963
             *   3. MailItem_ProcessingCompleted
Dean@1307
   964
             *        When processing of the mail item is complete, this even handler will be called.
Dean@1130
   965
             *        This will update the UI with the latest rating then call StartGetMirror.
Dean@709
   966
             *        The CopyStateToUI method is used which means any open privacy status form will also
Dean@709
   967
             *        be updated.
Dean@709
   968
             * 
Dean@709
   969
             *   4. MailItem_GetMirrorComplete
Dean@709
   970
             *        This is the final step in updating the UI, after a mirror is located, it's contents
Dean@1307
   971
             *        will be shown in the unencrypted preview.
Dean@709
   972
             * 
Dean@709
   973
             * The general calling sequence is as shown above 1->4 with each component calling the next.
Dean@709
   974
             * However, for methods that update the mail item directly, commonly only 2->4 is needed.
Dean@709
   975
             */
Dean@709
   976
Dean@179
   977
            // Ensure the tick method is not called more than once
Dean@1390
   978
            if ((this.isEnabled) &&
Dean@1390
   979
                (refreshOngoing == false))
Dean@179
   980
            {
Dean@179
   981
                this.refreshOngoing = true;
Dean@179
   982
Dean@1390
   983
                if (this.cryptableMailItem != null)
Dean@179
   984
                {
Dean@684
   985
                    // Attempt to get the download state
Dean@684
   986
                    try
Dean@684
   987
                    {
Dean@1390
   988
                        dlState = this.cryptableMailItem.DownloadState;
Dean@684
   989
                    }
Dean@684
   990
                    catch (Exception ex)
Dean@684
   991
                    {
Dean@1249
   992
                        Log.Warning("TimerRefresh_Tick: Get DownloadState failed, " + ex.ToString());
Dean@684
   993
Dean@684
   994
                        // Assume everything is downloaded, but try to download again as well
Dean@684
   995
                        dlState = Outlook.OlDownloadState.olFullItem;
Dean@684
   996
                        markForDownload = true;
Dean@684
   997
                    }
Dean@684
   998
Dean@684
   999
                    if (dlState == Outlook.OlDownloadState.olFullItem)
Dean@179
  1000
                    {
Dean@1130
  1001
                        this.ImmediateRatingAndUIUpdate();
Dean@179
  1002
                    }
Dean@179
  1003
                    else
Dean@179
  1004
                    {
Dean@684
  1005
                        markForDownload = true;
Dean@684
  1006
                    }
Dean@684
  1007
Dean@684
  1008
                    if (markForDownload)
Dean@684
  1009
                    {
Dean@684
  1010
                        // Try to mark the message for full download
Dean@684
  1011
                        try
Dean@684
  1012
                        {
Dean@1390
  1013
                            this.cryptableMailItem.MarkForDownload = Outlook.OlRemoteStatus.olMarkedForDownload;
Dean@684
  1014
                            tryAgain = true;
Dean@684
  1015
                        }
Dean@684
  1016
                        catch (Exception ex)
Dean@684
  1017
                        {
Dean@1249
  1018
                            Log.Warning("TimerRefresh_Tick: MarkForDownload failed, " + ex.ToString());
Dean@684
  1019
                        }
Dean@179
  1020
                    }
Dean@179
  1021
                }
Dean@179
  1022
Dean@199
  1023
                // Set the timer to refresh again later automatically
Dean@199
  1024
                if (tryAgain)
Dean@199
  1025
                {
Dean@199
  1026
                    this.TimerRefresh.Interval = 100;
Dean@199
  1027
                    this.TimerRefresh.Enabled = true;
Dean@199
  1028
                }
Dean@199
  1029
Dean@179
  1030
                this.refreshOngoing = false;
Dean@179
  1031
            }
Dean@175
  1032
Dean@159
  1033
            return;
Dean@159
  1034
        }
Dean@159
  1035
Dean@169
  1036
        /// <summary>
Dean@1096
  1037
        /// Event handler for when the processing is completed in the associated mail item.
Dean@709
  1038
        /// This will then update the form region UI and the privacy status window as needed.
Dean@680
  1039
        /// </summary>
Dean@1096
  1040
        private void MailItem_ProcessingCompleted(object sender, CryptableMailItem.ProcessingCompletedEventArgs e)
Dean@680
  1041
        {
Dean@1249
  1042
            Log.Verbose("MailItem_ProcessingComplete: Decryption completed.");
Dean@740
  1043
Dean@680
  1044
            try
Dean@680
  1045
            {
Dean@680
  1046
                // Marshal code back to UI thread as necessary
Dean@680
  1047
                this.Invoke(new Action(() =>
Dean@680
  1048
                    {
Dean@1390
  1049
                        if (this.isEnabled)
Dean@1390
  1050
                        {
Dean@1390
  1051
                            this.FormControlPrivacyStatusChild.DisplayState.Rating = e.Rating;
Dean@1390
  1052
                            RibbonCustomizations.Invalidate();
Dean@1390
  1053
                            this.UpdateManagePrivacyStatusForm(true); // Only update the rating
Dean@709
  1054
Dean@1390
  1055
                            /* Create the unencrypted preview if the mail item is encrypted and
Dean@1390
  1056
                             * it is in an encrypted (untrusted) store
Dean@1390
  1057
                             * 
Dean@1390
  1058
                             * This is done here because FormRegionPrivacyStatus has the cryptable mail item and
Dean@1390
  1059
                             * it also is initialized after FormRegionPreviewUnencrypted.
Dean@1390
  1060
                             */
Dean@1390
  1061
                            try
Dean@747
  1062
                            {
Dean@1390
  1063
                                if (this.cryptableMailItem.IsSecurelyStored)
Dean@1390
  1064
                                {
Dean@1390
  1065
                                    Log.Verbose("MailItem_ProcessingComplete: Starting mirror location.");
Dean@1390
  1066
                                    this.cryptableMailItem.StartGetMirror();
Dean@1390
  1067
                                }
Dean@1390
  1068
                                else
Dean@1390
  1069
                                {
Dean@1390
  1070
                                    this.ClearPreview();
Dean@1390
  1071
                                }
Dean@747
  1072
                            }
Dean@1390
  1073
                            catch (Exception ex)
Dean@747
  1074
                            {
Dean@1390
  1075
                                // Error is possible in some situations where the mail item was deleted or moved while decryption was ongoing.
Dean@1390
  1076
                                // While rare, just log the issue and stop the process
Dean@1390
  1077
                                Log.Warning("MailItem_ProcessingComplete: Failed to start mirror location, " + ex.ToString());
Dean@747
  1078
                            }
Dean@709
  1079
                        }
Dean@680
  1080
                    }));
Dean@680
  1081
            }
Dean@680
  1082
            catch (Exception ex)
Dean@680
  1083
            {
Dean@1249
  1084
                Log.Error("MailItem_ProcessingComplete: Error setting UI state, " + ex.ToString());
Dean@680
  1085
            }
Dean@680
  1086
Dean@680
  1087
            return;
Dean@680
  1088
        }
Dean@680
  1089
Dean@680
  1090
        /// <summary>
Dean@709
  1091
        /// Event handler for when the get mirror locating process is complete for the associated mail item.
Dean@709
  1092
        /// This will then update the unencrypted preview in the UI.
Dean@709
  1093
        /// </summary>
Dean@1096
  1094
        private void MailItem_GetMirrorCompleted(object sender, CryptableMailItem.GetMirrorCompletedEventArgs e)
Dean@709
  1095
        {
Dean@709
  1096
            try
Dean@709
  1097
            {
Dean@709
  1098
                // Marshal code back to UI thread as necessary
Dean@709
  1099
                this.Invoke(new Action(() =>
Dean@709
  1100
                    {
Dean@1390
  1101
                        if (this.isEnabled)
Dean@1390
  1102
                        {
Dean@1390
  1103
                            WindowFormRegionCollection formRegions = Globals.FormRegions[Globals.ThisAddIn.Application.ActiveWindow()];
Dean@709
  1104
Dean@1390
  1105
                            if ((e.Mirror == null) &&
Dean@1390
  1106
                                (this.cryptableMailItem.LastProcessedStatus == Globals.ReturnStatus.Failure))
Dean@910
  1107
                            {
Dean@1390
  1108
                                this.ClearPreview(Properties.Resources.Message_OpenError);
Dean@1390
  1109
                                Log.Verbose("MailItem_GetMirrorComplete: Cannot display mirror, failure during decryption.");
Dean@910
  1110
                            }
Dean@1390
  1111
                            else if ((e.Mirror == null) &&
Dean@1390
  1112
                                     (this.cryptableMailItem.LastProcessedStatus == Globals.ReturnStatus.FailureNoConnection))
Dean@1390
  1113
                            {
Dean@1390
  1114
                                this.ClearPreview(Properties.Resources.Message_DecryptionNoConnection);
Dean@1390
  1115
                                Log.Verbose("MailItem_GetMirrorComplete: Cannot display mirror, connection failure during decryption.");
Dean@1390
  1116
                            }
Dean@1390
  1117
                            else
Dean@1390
  1118
                            {
Dean@1390
  1119
                                if ((formRegions != null) &&
Dean@1390
  1120
                                    (formRegions.FormRegionPreviewUnencrypted != null) &&
Dean@1390
  1121
                                    (formRegions.FormRegionPreviewUnencrypted.Visible))
Dean@1390
  1122
                                {
Dean@1390
  1123
                                    formRegions.FormRegionPreviewUnencrypted.SetMessage(e.Mirror);
Dean@1390
  1124
                                    Log.Verbose("MailItem_GetMirrorComplete: Mirror found and displayed.");
Dean@1390
  1125
                                }
Dean@1390
  1126
                            }
Dean@758
  1127
Dean@1390
  1128
                            // Display the mirror if necessary
Dean@1390
  1129
                            if ((this.cryptableMailItem != null) &&
Dean@1390
  1130
                                (this.displayMirrorRequested))
Dean@1390
  1131
                            {
Dean@1390
  1132
                                this.cryptableMailItem.DisplayMirror();
Dean@1390
  1133
                                this.displayMirrorRequested = false;
Dean@1390
  1134
                            }
Dean@758
  1135
                        }
Dean@709
  1136
                    }));
Dean@709
  1137
            }
Dean@709
  1138
            catch (Exception ex)
Dean@709
  1139
            {
Dean@1249
  1140
                Log.Error("MailItem_GetMirrorComplete: Error displaying preview, " + ex.ToString());
Dean@709
  1141
            }
Dean@709
  1142
Dean@709
  1143
            return;
Dean@709
  1144
        }
Dean@709
  1145
Dean@709
  1146
        /// <summary>
Dean@807
  1147
        /// Event handler for the static mail item encrypted conversation cache updated.
Dean@807
  1148
        /// This event is fired after the conversation cache has been updated with parent information following a
Dean@807
  1149
        /// forward or reply mail item event (on a different, likely parent, mail item).
Dean@807
  1150
        /// </summary>
Dean@807
  1151
        private void CryptableMailItem_EncryptedConversationCacheUpdated(object sender, EventArgs e)
Dean@807
  1152
        {
Dean@1390
  1153
            if (this.isEnabled)
Dean@1390
  1154
            {
Dean@1390
  1155
                // Process the mail item now that the cache is updated
Dean@1390
  1156
                this.cryptableMailItem.SetIsOriginallyEncryptedByCache();
Dean@807
  1157
Dean@1390
  1158
                // Remove the event handler -- this can only be processed once because it's timing dependent
Dean@1390
  1159
                CryptableMailItem.EncryptedConversationCacheUpdated -= CryptableMailItem_EncryptedConversationCacheUpdated;
Dean@1390
  1160
            }
Dean@807
  1161
Dean@807
  1162
            return;
Dean@807
  1163
        }
Dean@807
  1164
Dean@807
  1165
        /// <summary>
Dean@169
  1166
        /// Event handler for when a mail item is being opened in an inspector.
Dean@180
  1167
        /// See: https://msdn.microsoft.com/en-us/library/office/ff865989.aspx
Dean@169
  1168
        /// </summary>
Dean@169
  1169
        /// <param name="cancel">Whether to cancel the event: Value is False when the event occurs. 
Dean@169
  1170
        /// If the event procedure sets this argument to True, the open operation is not completed 
Dean@169
  1171
        /// and the inspector is not displayed.</param>
Dean@169
  1172
        private void MailItem_Open(ref bool cancel)
Dean@159
  1173
        {
Dean@758
  1174
            bool result;
Dean@758
  1175
Dean@1390
  1176
            if ((this.isEnabled) &&
Dean@1390
  1177
                (this.cryptableMailItem != null) &&
Dean@1390
  1178
                (this.cryptableMailItem.IsSecurelyStored))
Dean@169
  1179
            {
Dean@758
  1180
                // Try to open the mirror
Dean@1390
  1181
                result = this.cryptableMailItem.DisplayMirror();
Dean@758
  1182
Dean@758
  1183
                if (result == false)
Dean@758
  1184
                {
Dean@758
  1185
                    // Set flag to open after decryption/mirror location
Dean@758
  1186
                    this.displayMirrorRequested = true;
Dean@758
  1187
                }
Dean@758
  1188
Dean@758
  1189
                // Always cancel opening the original
Dean@169
  1190
                cancel = true;
Dean@169
  1191
            }
Dean@169
  1192
Dean@169
  1193
            return;
Dean@159
  1194
        }
Dean@159
  1195
Dean@169
  1196
        /// <summary>
Dean@682
  1197
        /// Event handler for when a mail item is sent.
Dean@682
  1198
        /// See: https://msdn.microsoft.com/en-us/library/office/ff865379.aspx
Dean@682
  1199
        /// </summary>
Dean@682
  1200
        /// <param name="cancel">Whether to cancel the event: Value is False when the event occurs. 
Dean@682
  1201
        /// If the event procedure sets this argument to True, the send operation is not completed 
Dean@682
  1202
        /// and the inspector is left open.</param>
Dean@682
  1203
        private void MailItem_Send(ref bool cancel)
Dean@682
  1204
        {
Dean@807
  1205
            DialogResult result;
Dean@807
  1206
Dean@1390
  1207
            if (this.isEnabled)
Dean@807
  1208
            {
Dean@1390
  1209
                if ((Globals.ThisAddIn.Settings.IsSecurityLossWarningEnabled) &&
Dean@1390
  1210
                    (this.cryptableMailItem.IsOriginallyEncrypted) &&
Dean@1390
  1211
                    (this.FormControlPrivacyStatusChild.DisplayState.Rating < pEpRating.pEpRatingUnreliable))
Dean@1390
  1212
                {
Thomas@1318
  1213
Thomas@1318
  1214
#if READER_RELEASE_MODE
Dean@1390
  1215
                    FormReaderSplash warningMessage = new FormReaderSplash(true);
Dean@1390
  1216
                    result = warningMessage.ShowDialog();
Thomas@1318
  1217
Dean@1390
  1218
                    if (result != DialogResult.OK)
Dean@1390
  1219
                    {
Dean@1390
  1220
                        // Cancel sending
Dean@1390
  1221
                        cancel = true;
Dean@1390
  1222
                    }
Dean@1390
  1223
#else
Dean@1390
  1224
                    result = System.Windows.Forms.MessageBox.Show(this.ParentForm,
Dean@1390
  1225
                                                                  pEp.Properties.Resources.Message_WarningSecurityLoss,
Dean@1390
  1226
                                                                  pEp.Properties.Resources.Message_TitleConfirmOperation,
Dean@1390
  1227
                                                                  MessageBoxButtons.YesNo,
Dean@1390
  1228
                                                                  MessageBoxIcon.Warning);
Dean@1390
  1229
Dean@1390
  1230
                    if (result == DialogResult.No)
Dean@1390
  1231
                    {
Dean@1390
  1232
                        // Cancel sending
Dean@1390
  1233
                        cancel = true;
Dean@1390
  1234
                    }
Dean@1390
  1235
#endif
Dean@1390
  1236
                }
Dean@1390
  1237
Dean@1390
  1238
                // Stop and disconnect the refresh timer
Dean@1390
  1239
                // This is necessary so an ongoing refresh doesn't try to access a mail item as it's being moved
Dean@1390
  1240
                if (cancel == false)
Thomas@1318
  1241
                {
Dean@1390
  1242
                    this.TimerRefresh.Stop();
Dean@1390
  1243
                    this.TimerRefresh.Enabled = false;
Dean@1390
  1244
                    this.TimerRefresh.Tick -= TimerRefresh_Tick;
Thomas@1318
  1245
                }
Dean@807
  1246
            }
Dean@682
  1247
Dean@682
  1248
            return;
Dean@682
  1249
        }
Dean@682
  1250
Dean@682
  1251
        /// <summary>
Dean@169
  1252
        /// Event handler for when a mail item property is changed.
Dean@169
  1253
        /// See: https://msdn.microsoft.com/en-us/library/office/ff866739.aspx
Dean@169
  1254
        /// </summary>
Dean@169
  1255
        /// <param name="propertyName">The name of the property that was changed.</param>
Dean@445
  1256
        private void MailItem_PropertyChanged(object sender, PropertyChangedEventArgs e)
Dean@159
  1257
        {
Dean@1349
  1258
            switch (e.PropertyName.ToUpperInvariant())
Dean@159
  1259
            {
Dean@1390
  1260
                case "BCC":
Dean@1390
  1261
                    {
Dean@1390
  1262
                        // Outlook always fires Bcc, Cc and To together so only "TO" is used
Dean@1390
  1263
                        break;
Dean@1390
  1264
                    }
Dean@1390
  1265
                case "CC":
Dean@1390
  1266
                    {
Dean@1390
  1267
                        // Outlook always fires Bcc, Cc and To together so only "TO" is used
Dean@1390
  1268
                        break;
Dean@1390
  1269
                    }
Dean@1390
  1270
                case "SENTONBEHALFOFNAME":
Dean@1390
  1271
                    {
Dean@1390
  1272
                        // Always fired with "SENDUSINGACCOUNT" so is ignored
Dean@1390
  1273
                        break;
Dean@1390
  1274
                    }
Dean@1390
  1275
                case "SENDUSINGACCOUNT":
Dean@1390
  1276
                    {
Dean@1390
  1277
                        // Update pEp enabled status
Dean@1390
  1278
                        this.SetIsEnabled(((Outlook.MailItem)this.OutlookItem).GetIsPEPEnabled());
Dean@1390
  1279
Dean@1390
  1280
                        // Refresh the UI
Dean@1390
  1281
                        this.ResolveAllRecipients();
Dean@1390
  1282
                        this.RequestRatingAndUIUpdate();
Dean@1390
  1283
                        RibbonCustomizations.Invalidate();
Dean@1390
  1284
Dean@1390
  1285
                        break;
Dean@1390
  1286
                    }
Dean@179
  1287
                case "TO":
Dean@1390
  1288
                    {
Dean@1390
  1289
                        if (this.isEnabled)
Dean@1390
  1290
                        {
Dean@1390
  1291
                            this.RequestRatingAndUIUpdate();
Dean@1390
  1292
                        }
Dean@1390
  1293
                        break;
Dean@1390
  1294
                    }
Dean@159
  1295
            }
Dean@169
  1296
Dean@169
  1297
            return;
Dean@159
  1298
        }
Dean@159
  1299
Dean@179
  1300
        /// <summary>
Dean@1021
  1301
        /// Event handler for when the manager form is closed.
Dean@1021
  1302
        /// </summary>
Dean@1021
  1303
        private void ManagerForm_FormClosed(object sender, FormClosedEventArgs e)
Dean@1021
  1304
        {
Dean@1021
  1305
            // Remove the reference held in the FormRegionPrivacyStatus so it stops getting updated
Dean@1021
  1306
            if (this.managerForm != null)
Dean@1021
  1307
            {
Dean@1021
  1308
                this.managerForm.FormClosed -= ManagerForm_FormClosed;
Dean@1021
  1309
                this.managerForm = null;
Dean@1021
  1310
            }
Dean@1021
  1311
Dean@1021
  1312
            return;
Dean@1021
  1313
        }
Dean@1021
  1314
Dean@1021
  1315
        /// <summary>
Dean@859
  1316
        /// Event handler for when the pEp website hyperlink is clicked.
Dean@859
  1317
        /// </summary>
Dean@859
  1318
        private void LinkLabelUpgrade_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
Dean@859
  1319
        {
Dean@966
  1320
            try
Dean@966
  1321
            {
Dean@1007
  1322
                Process.Start(Globals.PEP_WEBSITE_UPGRADE_LINK);
Dean@966
  1323
            }
Dean@966
  1324
            catch (Exception ex)
Dean@966
  1325
            {
Dean@1249
  1326
                Log.Error("LinkLabelUpgrade_LinkClicked: Unable to open website link, " + ex.ToString());
Dean@966
  1327
            }
Dean@966
  1328
Dean@859
  1329
            return;
Dean@859
  1330
        }
Dean@1047
  1331
Dean@1047
  1332
        /// <summary>
Dean@1086
  1333
        /// Event handler for when the privacy view button is clicked within the form control.
Dean@1047
  1334
        /// </summary>
Dean@1086
  1335
        private void FormControlPrivacyStatusChild_PrivacyViewClick(object sender, System.Windows.RoutedEventArgs e)
Dean@1047
  1336
        {
Dean@1390
  1337
            if (this.isManagerFormEnabled)
Dean@1384
  1338
            {
Dean@1384
  1339
                this.RequestRatingAndUIUpdate();
Dean@1384
  1340
                this.BuildAndShowManager();
Dean@1384
  1341
            }
Dean@1384
  1342
Dean@1047
  1343
            return;
Dean@1047
  1344
        }
vb@133
  1345
    }
vb@133
  1346
}