[git] GpgOL - branch, async-enc, updated. gpgol-2.0.6-56-g3e851be

by Andre Heinecke cvs at cvs.gnupg.org
Thu Mar 1 13:47:19 CET 2018


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GnuPG extension for MS Outlook".

The branch, async-enc has been updated
       via  3e851bed56cba229a1a6de656c6639ffbc288081 (commit)
       via  16cf48705599010e380bc7c72ba8b2d945006471 (commit)
       via  d6246cd90e33d530cfecf654cecc097d73bef038 (commit)
       via  6ec4348a7e575921db013b6cc9d1f0d07ae0ddb8 (commit)
       via  eb1ed3493ebe49cbbb61fb4deb311f44f553b176 (commit)
       via  456cdf6165ef012769058507b5ef3edde729ca47 (commit)
       via  14d0e2d9d1e0f058ee391363aeee67614d9a7734 (commit)
       via  7700f5da2744cc7aa718aaaeedc66618b4088bff (commit)
       via  dc2f7424d081c1de0b639b3ab52aaa8092077c27 (commit)
       via  13ec7979aaff33e2d3112bc397ab0a291ffade2f (commit)
      from  325b90573a184b65bf1d66e5f6f0eebeb9f0d6ea (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 3e851bed56cba229a1a6de656c6639ffbc288081
Author: Andre Heinecke <aheinecke at intevation.de>
Date:   Thu Mar 1 13:46:50 2018 +0100

    Minor wait cleanup in overlay
    
    * src/overlay.cpp (Overlay::~Overlay): Wait afteer writing
    the quit.

diff --git a/src/overlay.cpp b/src/overlay.cpp
index f1467b9..8e088d6 100644
--- a/src/overlay.cpp
+++ b/src/overlay.cpp
@@ -81,8 +81,8 @@ Overlay::~Overlay()
 {
   log_debug ("%s:%s: Stopping overlay.",
              SRCNAME, __func__);
-  m_overlayCtx->wait ();
   m_overlayStdin.write ("quit\n", 5);
   m_overlayStdin.write (nullptr, 0);
+  m_overlayCtx->wait ();
   EnableWindow (m_wid, TRUE);
 }

commit 16cf48705599010e380bc7c72ba8b2d945006471
Author: Andre Heinecke <aheinecke at intevation.de>
Date:   Thu Mar 1 13:46:13 2018 +0100

    Localize keyresolver
    
    * src/cryptcontroller.cpp (CryptController::resolve_keys):
    Add --lang argument.

diff --git a/src/cryptcontroller.cpp b/src/cryptcontroller.cpp
index e2e4570..8557cc4 100644
--- a/src/cryptcontroller.cpp
+++ b/src/cryptcontroller.cpp
@@ -375,24 +375,23 @@ CryptController::resolve_keys ()
       release_cArray (recipients);
     }
 
-  // Convert our collected vector to c strings
-  // It's a bit overhead but should be quick for such small
-  // data.
-  char **cargs = vector_to_cArray (args);
+  args.push_back (std::string ("--lang"));
+  args.push_back (std::string (gettext_localename ()));
 
   // Args are prepared. Spawn the resolver.
   auto ctx = GpgME::Context::createForEngine (GpgME::SpawnEngine);
-
   if (!ctx)
     {
       // can't happen
-      release_cArray (cargs);
       TRACEPOINT;
       return -1;
     }
 
-  GpgME::Data mystdin (GpgME::Data::null), mystdout, mystderr;
 
+  // Convert our collected vector to c strings
+  // It's a bit overhead but should be quick for such small
+  // data.
+  char **cargs = vector_to_cArray (args);
 #ifdef DEBUG_RESOLVER
   log_debug ("Spawning args:");
   for (size_t i = 0; cargs && cargs[i]; i++)
@@ -401,6 +400,7 @@ CryptController::resolve_keys ()
     }
 #endif
 
+  GpgME::Data mystdin (GpgME::Data::null), mystdout, mystderr;
   GpgME::Error err = ctx->spawn (cargs[0], const_cast <const char**> (cargs),
                                  mystdin, mystdout, mystderr,
                                  (GpgME::Context::SpawnFlags) (

commit d6246cd90e33d530cfecf654cecc097d73bef038
Author: Andre Heinecke <aheinecke at intevation.de>
Date:   Thu Mar 1 13:39:06 2018 +0100

    Add keycache for located keys
    
    * src/keycache.cpp, src/keycache.h: New.
    * src/Makefile.am: Add new files.
    * src/mail.cpp (in_de_vs_mode): Move to cpphelp.
    Rename global maps to s_ prefix to be more clear.
    (Mail::locate_keys): Use keycache.
    (do_locate): Removed.
    (Mail::locate_all_crypto_recipents): New.
    * src/cpphelp.cpp: Add in_de_vs_mode.
    * src/ribbon-callbacks.cpp (mark_mime_action): Trigger
    locate on crypto toggle.
    
    --
    Every serious MUA needs a Keycache ;-)
    
    This is needed to store the keys returned by
    gpg --locate-keys if we want to use them later to automatically
    send to the keys located this way.

diff --git a/src/Makefile.am b/src/Makefile.am
index 7ef1edd..125265d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -88,7 +88,8 @@ gpgol_SOURCES = \
 	cryptcontroller.cpp cryptcontroller.h \
 	cpphelp.cpp cpphelp.h \
 	wks-helper.cpp wks-helper.h \
-	overlay.cpp overlay.h
+	overlay.cpp overlay.h \
+	keycache.cpp keycache.h
 
 
 #treeview_SOURCES = treeview.c
diff --git a/src/cpphelp.cpp b/src/cpphelp.cpp
index 20b91d3..85c8db3 100644
--- a/src/cpphelp.cpp
+++ b/src/cpphelp.cpp
@@ -26,6 +26,10 @@
 
 #include "common.h"
 
+#include <gpgme++/context.h>
+#include <gpgme++/error.h>
+#include <gpgme++/configuration.h>
+
 void
 release_cArray (char **carray)
 {
@@ -55,3 +59,55 @@ vector_to_cArray(const std::vector<std::string> &vec)
   ret[vec.size()] = NULL;
   return ret;
 }
+
+bool
+in_de_vs_mode()
+{
+/* We cache the values only once. A change requires restart.
+     This is because checking this is very expensive as gpgconf
+     spawns each process to query the settings. */
+  static bool checked;
+  static bool vs_mode;
+
+  if (checked)
+    {
+      return vs_mode;
+    }
+  GpgME::Error err;
+  const auto components = GpgME::Configuration::Component::load (err);
+  log_debug ("%s:%s: Checking for de-vs mode.",
+             SRCNAME, __func__);
+  if (err)
+    {
+      log_error ("%s:%s: Failed to get gpgconf components: %s",
+                 SRCNAME, __func__, err.asString ());
+      checked = true;
+      vs_mode = false;
+      return vs_mode;
+    }
+  for (const auto &component: components)
+    {
+      if (component.name () && !strcmp (component.name (), "gpg"))
+        {
+          for (const auto &option: component.options ())
+            {
+              if (option.name () && !strcmp (option.name (), "compliance") &&
+                  option.currentValue ().stringValue () &&
+                  !stricmp (option.currentValue ().stringValue (), "de-vs"))
+                {
+                  log_debug ("%s:%s: Detected de-vs mode",
+                             SRCNAME, __func__);
+                  checked = true;
+                  vs_mode = true;
+                  return vs_mode;
+                }
+            }
+          checked = true;
+          vs_mode = false;
+          return vs_mode;
+        }
+    }
+  checked = true;
+  vs_mode = false;
+  return false;
+}
diff --git a/src/cpphelp.h b/src/cpphelp.h
index 0b60170..bbf68e0 100644
--- a/src/cpphelp.h
+++ b/src/cpphelp.h
@@ -36,4 +36,7 @@ void rtrim(std::string &s);
 /* Convert a string vector to a null terminated char array */
 char **vector_to_cArray (const std::vector<std::string> &vec);
 
+/* Check if we are in de_vs mode. */
+bool in_de_vs_mode ();
+
 #endif // CPPHELP_H
diff --git a/src/keycache.cpp b/src/keycache.cpp
new file mode 100644
index 0000000..3907772
--- /dev/null
+++ b/src/keycache.cpp
@@ -0,0 +1,366 @@
+/* @file keycache.cpp
+ * @brief Internal keycache
+ *
+ * Copyright (C) 2018 Intevation GmbH
+ *
+ * This file is part of GpgOL.
+ *
+ * GpgOL is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GpgOL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "keycache.h"
+
+#include "common.h"
+#include "cpphelp.h"
+
+#include <gpg-error.h>
+#include <gpgme++/context.h>
+#include <gpgme++/key.h>
+
+#include <windows.h>
+
+#include <map>
+
+GPGRT_LOCK_DEFINE (keycache_lock);
+static KeyCache* singleton = nullptr;
+
+class KeyCache::Private
+{
+public:
+  Private()
+  {
+
+  }
+
+  void setPgpKey(const char *mbox, const GpgME::Key &key)
+  {
+    const std::string sMbox(mbox);
+
+    gpgrt_lock_lock (&keycache_lock);
+    auto it = m_pgp_key_map.find (sMbox);
+
+    if ( it == m_pgp_key_map.end ())
+      {
+        m_pgp_key_map.insert (std::pair<std::string, GpgME::Key> (sMbox, GpgME::Key()));
+      }
+    else
+      {
+        it->second = key;
+      }
+    gpgrt_lock_unlock (&keycache_lock);
+  }
+
+  void setSmimeKey(const char *mbox, const GpgME::Key &key)
+  {
+    const std::string sMbox(mbox);
+
+    gpgrt_lock_lock (&keycache_lock);
+    auto it = m_smime_key_map.find (sMbox);
+
+    if ( it == m_smime_key_map.end ())
+      {
+        m_smime_key_map.insert (std::pair<std::string, GpgME::Key> (sMbox, GpgME::Key()));
+      }
+    else
+      {
+        it->second = key;
+      }
+    gpgrt_lock_unlock (&keycache_lock);
+  }
+
+  GpgME::Key getKey (const char *addr, GpgME::Protocol proto)
+  {
+    if (!addr)
+      {
+        return GpgME::Key();
+      }
+    auto mbox = GpgME::UserID::addrSpecFromString (addr);
+
+    if (proto == GpgME::OpenPGP)
+      {
+        gpgrt_lock_lock (&keycache_lock);
+        const auto it = m_pgp_key_map.find (mbox);
+
+        if (it == m_pgp_key_map.end ())
+          {
+            gpgrt_lock_unlock (&keycache_lock);
+            return GpgME::Key();
+          }
+        const auto ret = it->second;
+        gpgrt_lock_unlock (&keycache_lock);
+
+        return ret;
+      }
+    gpgrt_lock_lock (&keycache_lock);
+    const auto it = m_smime_key_map.find (mbox);
+
+    if (it == m_smime_key_map.end ())
+      {
+        gpgrt_lock_unlock (&keycache_lock);
+        return GpgME::Key();
+      }
+    const auto ret = it->second;
+    gpgrt_lock_unlock (&keycache_lock);
+
+    return ret;
+  }
+
+  GpgME::Key getSigningKey (const char *addr, GpgME::Protocol proto)
+  {
+    const auto key = getKey (addr, proto);
+    if (key.isNull())
+      {
+        return key;
+      }
+    if (!key.canReallySign())
+      {
+        log_mime_parser ("%s:%s: Discarding key for %s because it can't sign",
+                   SRCNAME, __func__, addr);
+        return GpgME::Key();
+      }
+    if (!key.hasSecret())
+      {
+        log_mime_parser ("%s:%s: Discarding key for %s because it has no secret",
+                   SRCNAME, __func__, addr);
+        return GpgME::Key();
+      }
+    if (in_de_vs_mode () && !key.isDeVs())
+      {
+        log_mime_parser ("%s:%s: signing key for %s is not deVS",
+                   SRCNAME, __func__, addr);
+        return GpgME::Key();
+      }
+    return key;
+  }
+
+  std::vector<GpgME::Key> getEncryptionKeys (const char **recipients,
+                                             GpgME::Protocol proto)
+  {
+    std::vector<GpgME::Key> ret;
+    if (!recipients)
+      {
+        TRACEPOINT;
+        return ret;
+      }
+    for (int i = 0; recipients[i]; i++)
+      {
+        const auto key = getKey (recipients[i], proto);
+        if (key.isNull())
+          {
+            log_mime_parser ("%s:%s: No key for %s. no internal encryption",
+                       SRCNAME, __func__, recipients[i]);
+            return std::vector<GpgME::Key>();
+          }
+
+        if (!key.canEncrypt() || key.isRevoked() ||
+            key.isExpired() || key.isDisabled() || key.isInvalid())
+          {
+            log_mime_parser ("%s:%s: Invalid key for %s. no internal encryption",
+                       SRCNAME, __func__, recipients[i]);
+            return std::vector<GpgME::Key>();
+          }
+
+        if (in_de_vs_mode () && key.isDeVs ())
+          {
+            log_mime_parser ("%s:%s: key for %s is not deVS",
+                       SRCNAME, __func__, recipients[i]);
+            return std::vector<GpgME::Key>();
+          }
+
+        bool validEnough = false;
+        /* Here we do the check if the key is valid for this recipient */
+        const auto addrSpec = GpgME::UserID::addrSpecFromString (recipients[i]);
+        for (const auto &uid: key.userIDs ())
+          {
+            if (addrSpec != uid.addrSpec())
+              {
+                // Ignore unmatching addr specs
+                continue;
+              }
+            if (uid.validity() >= GpgME::UserID::Marginal)
+              {
+                validEnough = true;
+                break;
+              }
+          }
+        if (!validEnough)
+          {
+            log_mime_parser ("%s:%s: UID for %s does not have at least marginal trust",
+                             SRCNAME, __func__, recipients[i]);
+            return std::vector<GpgME::Key>();
+          }
+        // Accepting key
+        ret.push_back (key);
+      }
+    return ret;
+  }
+
+  std::map<std::string, GpgME::Key> m_pgp_key_map;
+  std::map<std::string, GpgME::Key> m_smime_key_map;
+};
+
+KeyCache::KeyCache():
+  d(new Private)
+{
+}
+
+KeyCache *
+KeyCache::instance ()
+{
+  if (!singleton)
+    {
+      singleton = new KeyCache();
+    }
+  return singleton;
+}
+
+GpgME::Key
+KeyCache::getSigningKey (const char *addr, GpgME::Protocol proto) const
+{
+  return d->getSigningKey (addr, proto);
+}
+
+std::vector<GpgME::Key>
+KeyCache::getEncryptionKeys (const char **recipients, GpgME::Protocol proto) const
+{
+  return d->getEncryptionKeys (recipients, proto);
+}
+
+static DWORD WINAPI
+do_locate (LPVOID arg)
+{
+  char *addr = (char*) arg;
+
+  log_mime_parser ("%s:%s searching key for addr: \"%s\"",
+                   SRCNAME, __func__, addr);
+
+  const auto k = GpgME::Key::locate (addr);
+
+  if (!k.isNull ())
+    {
+      log_mime_parser ("%s:%s found key for addr: \"%s\":%s",
+                       SRCNAME, __func__, addr, k.primaryFingerprint());
+      KeyCache::instance ()->setPgpKey (addr, k);
+    }
+
+  if (opt.enable_smime)
+    {
+      auto ctx = GpgME::Context::createForProtocol (GpgME::OpenPGP);
+      if (!ctx)
+        {
+          TRACEPOINT;
+          xfree (addr);
+          return 0;
+        }
+      // We need to validate here to fetch CRL's
+      ctx->setKeyListMode (GpgME::KeyListMode::Local |
+                           GpgME::KeyListMode::Validate);
+      GpgME::Error e = ctx->startKeyListing (addr);
+      if (e)
+        {
+          TRACEPOINT;
+          xfree (addr);
+          return 0;
+        }
+
+      std::vector<GpgME::Key> keys;
+      GpgME::Error err;
+      do {
+          keys.push_back(ctx->nextKey(err));
+      } while (!err);
+      keys.pop_back();
+      delete ctx;
+
+      GpgME::Key candidate;
+      for (const auto &key: keys)
+        {
+          if (key.isRevoked() || key.isExpired() ||
+              key.isDisabled() || key.isInvalid())
+            {
+              log_mime_parser ("%s:%s: Skipping invalid S/MIME key",
+                               SRCNAME, __func__);
+              continue;
+            }
+          if (candidate.isNull() || !candidate.numUserIDs())
+            {
+              if (key.numUserIDs() &&
+                  candidate.userID(0).validity() <= key.userID(0).validity())
+                {
+                  candidate = key;
+                }
+            }
+        }
+      if (!candidate.isNull())
+        {
+          log_mime_parser ("%s:%s found SMIME key for addr: \"%s\":%s",
+                           SRCNAME, __func__, addr, candidate.primaryFingerprint());
+          KeyCache::instance()->setSmimeKey (addr, candidate);
+        }
+    }
+  xfree (addr);
+
+  log_debug ("%s:%s locator thread done",
+             SRCNAME, __func__);
+  return 0;
+}
+
+void KeyCache::startLocate (char **recipients) const
+{
+  log_debug ("%s:%s start locate",
+             SRCNAME, __func__);
+  if (!recipients)
+    {
+      TRACEPOINT;
+      return;
+    }
+  gpgrt_lock_lock (&keycache_lock);
+  log_debug ("%s:%s locked",
+             SRCNAME, __func__);
+
+  for (int i = 0; recipients[i]; i++)
+    {
+      log_debug ("%s:%s looking tat %s",
+                 SRCNAME, __func__, recipients[i]);
+      std::string recp = GpgME::UserID::addrSpecFromString (recipients[i]);
+      if (recp.empty ())
+        {
+          continue;
+        }
+      if (d->m_pgp_key_map.find (recp) == d->m_pgp_key_map.end ())
+        {
+          // It's enough to look at the PGP Key map. We marked
+          // searched keys there.
+          d->m_pgp_key_map.insert (std::pair<std::string, GpgME::Key> (recp, GpgME::Key()));
+          log_debug ("%s:%s Creating a locator thread",
+                     SRCNAME, __func__);
+          HANDLE thread = CreateThread (NULL, 0, do_locate,
+                                        (LPVOID) strdup (recp.c_str ()), 0,
+                                        NULL);
+          CloseHandle (thread);
+        }
+    }
+  gpgrt_lock_unlock (&keycache_lock);
+}
+
+void
+KeyCache::setSmimeKey(const char *mbox, const GpgME::Key &key)
+{
+  d->setSmimeKey(mbox, key);
+}
+
+void
+KeyCache::setPgpKey(const char *mbox, const GpgME::Key &key)
+{
+  d->setPgpKey(mbox, key);
+}
diff --git a/src/keycache.h b/src/keycache.h
new file mode 100644
index 0000000..7f68fe2
--- /dev/null
+++ b/src/keycache.h
@@ -0,0 +1,74 @@
+#ifndef KEYCACHE_H
+#define KEYCACHE_H
+
+/* @file keycache.h
+ * @brief Internal keycache
+ *
+ * Copyright (C) 2018 Intevation GmbH
+ *
+ * This file is part of GpgOL.
+ *
+ * GpgOL is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GpgOL is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <memory>
+#include <vector>
+
+#include <gpgme++/global.h>
+
+namespace GpgME
+{
+  class Key;
+};
+
+class KeyCache
+{
+protected:
+    /** Internal ctor */
+    explicit KeyCache ();
+
+public:
+    /** Get the KeyCache */
+    static KeyCache* instance ();
+
+    /* Try to find a key for signing in the internal
+       cache. If no proper key is found a Null key is
+       returned.*/
+    GpgME::Key getSigningKey (const char *addr, GpgME::Protocol proto) const;
+
+    /* Get the keys for recipents. The keys
+       are taken from the internal cache. If
+       one recipient can't be resolved an empty
+       list is returned. */
+    std::vector<GpgME::Key> getEncryptionKeys (const char **recipients,
+                                               GpgME::Protocol proto) const;
+
+    /* Start a key location in a background thread filling
+       the key cache. cArray is a null terminated array
+       of address strings. */
+    void startLocate (char **cArray) const;
+
+
+    // Internal for thread
+    void setSmimeKey(const char *mbox, const GpgME::Key &key);
+    void setPgpKey(const char *mbox, const GpgME::Key &key);
+
+private:
+    class Private;
+    std::shared_ptr<Private> d;
+};
+
+#endif
diff --git a/src/mail.cpp b/src/mail.cpp
index 818dc69..7405328 100644
--- a/src/mail.cpp
+++ b/src/mail.cpp
@@ -38,6 +38,8 @@
 #include "windowmessages.h"
 #include "mlang-charset.h"
 #include "wks-helper.h"
+#include "keycache.h"
+#include "cpphelp.h"
 
 #include <gpgme++/configuration.h>
 #include <gpgme++/tofuinfo.h>
@@ -59,64 +61,12 @@
 
 using namespace GpgME;
 
-static std::map<LPDISPATCH, Mail*> g_mail_map;
-static std::map<std::string, Mail*> g_uid_map;
+static std::map<LPDISPATCH, Mail*> s_mail_map;
+static std::map<std::string, Mail*> s_uid_map;
 static std::set<std::string> uids_searched;
 
 static Mail *s_last_mail;
 
-static bool
-in_de_vs_mode()
-{
-  /* We cache the values only once. A change requires restart.
-     This is because checking this is very expensive as gpgconf
-     spawns each process to query the settings. */
-  static bool checked;
-  static bool vs_mode;
-
-  if (checked)
-    {
-      return vs_mode;
-    }
-  Error err;
-  const auto components = Configuration::Component::load (err);
-  log_debug ("%s:%s: Checking for de-vs mode.",
-             SRCNAME, __func__);
-  if (err)
-    {
-      log_error ("%s:%s: Failed to get gpgconf components: %s",
-                 SRCNAME, __func__, err.asString ());
-      checked = true;
-      vs_mode = false;
-      return vs_mode;
-    }
-  for (const auto &component: components)
-    {
-      if (component.name () && !strcmp (component.name (), "gpg"))
-        {
-          for (const auto &option: component.options ())
-            {
-              if (option.name () && !strcmp (option.name (), "compliance") &&
-                  option.currentValue ().stringValue () &&
-                  !stricmp (option.currentValue ().stringValue (), "de-vs"))
-                {
-                  log_debug ("%s:%s: Detected de-vs mode",
-                             SRCNAME, __func__);
-                  checked = true;
-                  vs_mode = true;
-                  return vs_mode;
-                }
-            }
-          checked = true;
-          vs_mode = false;
-          return vs_mode;
-        }
-    }
-  checked = true;
-  vs_mode = false;
-  return false;
-}
-
 #define COPYBUFSIZE (8 * 1024)
 
 Mail::Mail (LPDISPATCH mailitem) :
@@ -161,7 +111,7 @@ Mail::Mail (LPDISPATCH mailitem) :
       gpgol_release(mailitem);
       return;
     }
-  g_mail_map.insert (std::pair<LPDISPATCH, Mail *> (mailitem, this));
+  s_mail_map.insert (std::pair<LPDISPATCH, Mail *> (mailitem, this));
   s_last_mail = this;
 }
 
@@ -180,18 +130,18 @@ Mail::~Mail()
   detach_MailItemEvents_sink (m_event_sink);
   gpgol_release(m_event_sink);
 
-  it = g_mail_map.find(m_mailitem);
-  if (it != g_mail_map.end())
+  it = s_mail_map.find(m_mailitem);
+  if (it != s_mail_map.end())
     {
-      g_mail_map.erase (it);
+      s_mail_map.erase (it);
     }
 
   if (!m_uuid.empty())
     {
-      auto it2 = g_uid_map.find(m_uuid);
-      if (it2 != g_uid_map.end())
+      auto it2 = s_uid_map.find(m_uuid);
+      if (it2 != s_uid_map.end())
         {
-          g_uid_map.erase (it2);
+          s_uid_map.erase (it2);
         }
     }
 
@@ -222,8 +172,8 @@ Mail::get_mail_for_item (LPDISPATCH mailitem)
       return NULL;
     }
   std::map<LPDISPATCH, Mail *>::iterator it;
-  it = g_mail_map.find(mailitem);
-  if (it == g_mail_map.end())
+  it = s_mail_map.find(mailitem);
+  if (it == s_mail_map.end())
     {
       return NULL;
     }
@@ -237,8 +187,8 @@ Mail::get_mail_for_uuid (const char *uuid)
     {
       return NULL;
     }
-  auto it = g_uid_map.find(std::string(uuid));
-  if (it == g_uid_map.end())
+  auto it = s_uid_map.find(std::string(uuid));
+  if (it == s_uid_map.end())
     {
       return NULL;
     }
@@ -248,8 +198,8 @@ Mail::get_mail_for_uuid (const char *uuid)
 bool
 Mail::is_valid_ptr (const Mail *mail)
 {
-  auto it = g_mail_map.begin();
-  while (it != g_mail_map.end())
+  auto it = s_mail_map.begin();
+  while (it != s_mail_map.end())
     {
       if (it->second == mail)
         return true;
@@ -1415,7 +1365,7 @@ Mail::close_all_mails ()
   int err = 0;
   std::map<LPDISPATCH, Mail *>::iterator it;
   TRACEPOINT;
-  std::map<LPDISPATCH, Mail *> mail_map_copy = g_mail_map;
+  std::map<LPDISPATCH, Mail *> mail_map_copy = s_mail_map;
   for (it = mail_map_copy.begin(); it != mail_map_copy.end(); ++it)
     {
       /* XXX For non racy code the is_valid_ptr check should not
@@ -1449,7 +1399,7 @@ Mail::revert_all_mails ()
 {
   int err = 0;
   std::map<LPDISPATCH, Mail *>::iterator it;
-  for (it = g_mail_map.begin(); it != g_mail_map.end(); ++it)
+  for (it = s_mail_map.begin(); it != s_mail_map.end(); ++it)
     {
       if (it->second->revert ())
         {
@@ -1474,7 +1424,7 @@ Mail::wipe_all_mails ()
 {
   int err = 0;
   std::map<LPDISPATCH, Mail *>::iterator it;
-  for (it = g_mail_map.begin(); it != g_mail_map.end(); ++it)
+  for (it = s_mail_map.begin(); it != s_mail_map.end(); ++it)
     {
       if (it->second->wipe ())
         {
@@ -1953,7 +1903,7 @@ Mail::set_uuid()
                      SRCNAME, __func__, m_mailitem, uuid);
           delete other;
         }
-      g_uid_map.insert (std::pair<std::string, Mail *> (m_uuid, this));
+      s_uid_map.insert (std::pair<std::string, Mail *> (m_uuid, this));
       log_debug ("%s:%s: uuid for %p is now %s",
                  SRCNAME, __func__, this,
                  m_uuid.c_str());
@@ -2450,71 +2400,12 @@ Mail::get_sig_fpr() const
   return m_sig.fingerprint();
 }
 
-
-static DWORD WINAPI
-do_locate (LPVOID arg)
-{
-  char *recipient = (char*) arg;
-  log_debug ("%s:%s searching key for recipient: \"%s\"",
-             SRCNAME, __func__, recipient);
-  Context *ctx = Context::createForProtocol (OpenPGP);
-
-  if (!ctx)
-    {
-      TRACEPOINT;
-      return 0;
-    }
-
-  ctx->setKeyListMode (GpgME::Extern | GpgME::Local);
-  ctx->startKeyListing (recipient, false);
-
-  std::vector<Key> keys;
-  Error err;
-  do {
-      keys.push_back (ctx->nextKey(err));
-    } while (!err);
-  keys.pop_back ();
-  ctx->endKeyListing ();
-  delete ctx;
-
-  if (keys.size ())
-    {
-      log_debug ("%s:%s found key for recipient: \"%s\"",
-                 SRCNAME, __func__, recipient);
-    }
-  xfree (recipient);
-  // do_in_ui_thread (UNKNOWN, NULL);
-  return 0;
-}
-
-GPGRT_LOCK_DEFINE(uids_searched_lock);
-
 /** Try to locate the keys for all recipients */
 void Mail::locate_keys()
 {
-  gpgrt_lock_lock (&uids_searched_lock);
   char ** recipients = get_recipients ();
-
-  if (!recipients)
-    {
-      TRACEPOINT;
-      return;
-    }
-  for (int i = 0; recipients[i]; i++)
-    {
-      std::string recp = recipients[i];
-      if (uids_searched.find (recp) == uids_searched.end ())
-        {
-          uids_searched.insert (recp);
-          HANDLE thread = CreateThread (NULL, 0, do_locate,
-                                        (LPVOID) strdup(recipients[i]), 0,
-                                        NULL);
-          CloseHandle (thread);
-        }
-      xfree (recipients[i]);
-    }
-  xfree (recipients);
-  gpgrt_lock_unlock (&uids_searched_lock);
+  KeyCache::instance()->startLocate (recipients);
+  release_cArray (recipients);
 }
 
 bool
@@ -2756,3 +2647,22 @@ Mail::get_last_mail ()
     }
   return s_last_mail;
 }
+
+// static
+void
+Mail::locate_all_crypto_recipients()
+{
+  if (!opt.autoresolve)
+    {
+      return;
+    }
+
+  std::map<LPDISPATCH, Mail *>::iterator it;
+  for (it = s_mail_map.begin(); it != s_mail_map.end(); ++it)
+    {
+      if (it->second->needs_crypto ())
+        {
+          it->second->locate_keys ();
+        }
+    }
+}
diff --git a/src/mail.h b/src/mail.h
index 53c0e23..f8cdbab 100644
--- a/src/mail.h
+++ b/src/mail.h
@@ -133,6 +133,18 @@ public:
     */
   static int close_all_mails ();
 
+  /** @brief locate recipients for all crypto mails
+    *
+    * To avoid lookups of recipients for non crypto mails we only
+    * locate keys when a crypto action is already selected.
+    *
+    * As the user can do this after recipients were added but
+    * we don't know for which mail the crypt button was triggered.
+    * we march over all mails and if they are crypto mails we check
+    * that the recipents were located.
+    */
+  static void locate_all_crypto_recipients ();
+
   /** @brief Reference to the mailitem. Do not Release! */
   LPDISPATCH item () { return m_mailitem; }
 
diff --git a/src/ribbon-callbacks.cpp b/src/ribbon-callbacks.cpp
index e579026..4f7d0a9 100644
--- a/src/ribbon-callbacks.cpp
+++ b/src/ribbon-callbacks.cpp
@@ -1357,6 +1357,11 @@ mark_mime_action (LPDISPATCH ctrl, int flags, bool is_explorer)
       we invalidate a lot *sigh* */
   gpgoladdin_invalidate_ui ();
 
+  if (newflags & 1)
+    {
+      Mail::locate_all_crypto_recipients ();
+    }
+
 done:
   gpgol_release (context);
   gpgol_release (mailitem);

commit 6ec4348a7e575921db013b6cc9d1f0d07ae0ddb8
Author: Andre Heinecke <aheinecke at intevation.de>
Date:   Thu Mar 1 13:37:38 2018 +0100

    Fix surprising toggle behavior
    
    * src/ribbon-callbacks.cpp (mark_mime_action): If a sub action
    was active click on secure activates both sign and encrypt.

diff --git a/src/ribbon-callbacks.cpp b/src/ribbon-callbacks.cpp
index 92c3e36..e579026 100644
--- a/src/ribbon-callbacks.cpp
+++ b/src/ribbon-callbacks.cpp
@@ -1333,7 +1333,16 @@ mark_mime_action (LPDISPATCH ctrl, int flags, bool is_explorer)
 
   oldflags = get_gpgol_draft_info_flags (message);
 
-  newflags = oldflags xor flags;
+  if (flags == 3 && oldflags != 3)
+    {
+      // If only one sub button is active activate
+      // both now.
+      newflags = 3;
+    }
+  else
+    {
+      newflags = oldflags xor flags;
+    }
 
   if (set_gpgol_draft_info_flags (message, newflags))
     {

commit eb1ed3493ebe49cbbb61fb4deb311f44f553b176
Merge: 325b905 456cdf6
Author: Andre Heinecke <aheinecke at intevation.de>
Date:   Tue Feb 27 07:50:01 2018 +0100

    Merge branch 'master' into async-enc

diff --cc src/mapihelp.cpp
index 4647ee1,0c1bff3..7e33823
--- a/src/mapihelp.cpp
+++ b/src/mapihelp.cpp
@@@ -1140,10 -1182,22 +1182,26 @@@ change_message_class_ipm_note_smime_mul
          {
            newvalue = xstrdup ("IPM.Note.GpgOL.MultipartSigned");
          }
 +      else if (!strcmp (ct, "wks.confirmation.mail"))
 +        {
 +          newvalue = xstrdup ("IPM.Note.GpgOL.WKSConfirmation");
 +        }
+       else if (ct && !strcmp (ct, "application/ms-tnef"))
+         {
+           /* So no PGP Inline. Lets look at the attachment. */
+           char *attach_mime = get_first_attach_mime_tag (message);
+           if (!attach_mime)
+             {
+               xfree (ct);
+               xfree (proto);
+               return nullptr;
+             }
+           if (!strcmp (attach_mime, "multipart/signed"))
+             {
+               newvalue = xstrdup ("IPM.Note.GpgOL.MultipartSigned");
+               xfree (attach_mime);
+             }
+         }
        xfree (proto);
        xfree (ct);
      }

-----------------------------------------------------------------------

Summary of changes:
 src/Makefile.am          |   3 +-
 src/cpphelp.cpp          |  56 ++++++++
 src/cpphelp.h            |   3 +
 src/cryptcontroller.cpp  |  14 +-
 src/keycache.cpp         | 366 +++++++++++++++++++++++++++++++++++++++++++++++
 src/keycache.h           |  74 ++++++++++
 src/mail.cpp             | 196 ++++++++-----------------
 src/mail.h               |  12 ++
 src/mapihelp.cpp         |  66 ++++++++-
 src/oomhelp.h            |   5 +
 src/overlay.cpp          |   2 +-
 src/parsecontroller.cpp  |  12 +-
 src/ribbon-callbacks.cpp |  69 +++++----
 13 files changed, 706 insertions(+), 172 deletions(-)
 create mode 100644 src/keycache.cpp
 create mode 100644 src/keycache.h


hooks/post-receive
-- 
GnuPG extension for MS Outlook
http://git.gnupg.org




More information about the Gnupg-commits mailing list