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