[git] GpgOL - branch, async-enc, updated. gpgol-2.0.6-37-g573661d

by Andre Heinecke cvs at cvs.gnupg.org
Fri Feb 16 13:07:02 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  573661d09c07b67680be17418e13fcfa960c4a2d (commit)
       via  6436349496e052cddbebef7394fb88db60bb4846 (commit)
       via  7c611426da261b67dd422ada7ae5b85bd8265649 (commit)
       via  e59a0ab7032ad219d1ed727831034ee51d12649f (commit)
       via  acf089c3376a1e097ebc6d4cc1dde8ac124df8a8 (commit)
       via  cc08ea5d290c279fcd69a7f6b712e20f9f8f5900 (commit)
       via  e25a51950583d0ae051b38f0aed17522fb8f77b5 (commit)
      from  ab69aab5ea815d377236f02f207ebb0aaaf6406a (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 573661d09c07b67680be17418e13fcfa960c4a2d
Author: Andre Heinecke <aheinecke at intevation.de>
Date:   Fri Feb 16 13:05:09 2018 +0100

    Add notification handling to WKS Helper
    
    * src/windowmessages.cpp,
    src/windowmessages.h (WKS_NOTIFY): New.
    * src/wks-helper.cpp, src/wks-helper.h: Add more code.
    
    --
    After an encrypt / sign we send a notification some time
    later that a MessageBox for WKS Publishing can be opened
    back in the UI thread.

diff --git a/src/windowmessages.cpp b/src/windowmessages.cpp
index bfed366..9bb0f5c 100644
--- a/src/windowmessages.cpp
+++ b/src/windowmessages.cpp
@@ -25,6 +25,7 @@
 #include "oomhelp.h"
 #include "mail.h"
 #include "gpgoladdin.h"
+#include "wks-helper.h"
 
 #include <stdio.h>
 
@@ -113,6 +114,15 @@ gpgol_window_proc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
                 }
               // Finaly this should pass.
               invoke_oom_method (mail->item (), "Send", NULL);
+              // Allow the WKS helper to queue a notification.
+              WKSHelper::instance()->allow_notify ();
+              break;
+            }
+          case (WKS_NOTIFY):
+            {
+              WKSHelper::instance ()->notify ((const char *) ctx->data);
+              xfree (ctx->data);
+              break;
             }
           default:
             log_debug ("%s:%s: Unknown msg %x",
diff --git a/src/windowmessages.h b/src/windowmessages.h
index fba7088..69762af 100644
--- a/src/windowmessages.h
+++ b/src/windowmessages.h
@@ -48,6 +48,7 @@ typedef enum _gpgol_wmsg_type
                       to mail */
   CLOSE, /* Close the message in the next event loop. */
   CRYPTO_DONE, /* Sign / Encrypt done. */
+  WKS_NOTIFY, /* Show a WKS Notification. */
 } gpgol_wmsg_type;
 
 typedef struct
diff --git a/src/wks-helper.cpp b/src/wks-helper.cpp
index efe3bce..49e6dbe 100644
--- a/src/wks-helper.cpp
+++ b/src/wks-helper.cpp
@@ -21,6 +21,9 @@
 
 #include "common.h"
 #include "cpphelp.h"
+#include "oomhelp.h"
+#include "windowmessages.h"
+#include "overlay.h"
 
 #include <map>
 
@@ -33,6 +36,9 @@
 
 #define CHECK_MIN_INTERVAL (60 * 60 * 24 * 7)
 
+#undef _
+#define _(a) utf8_gettext (a)
+
 static std::map <std::string, WKSHelper::WKSState> s_states;
 static std::map <std::string, time_t> s_last_checked;
 
@@ -162,27 +168,17 @@ do_check (LPVOID arg)
   rtrim (data);
 
   bool success = data == "[GNUPG:] SUCCESS";
-  const auto state = success ? WKSHelper::Supported : WKSHelper::NotSupported;
-
-  gpgrt_lock_lock (&wks_lock);
-
-  auto it = s_states.find(mbox);
-
-  // TODO figure out if it was published.
+  // TODO Figure out NeedsPublish state.
+  const auto state = success ? WKSHelper::NeedsPublish : WKSHelper::NotSupported;
   if (success)
     {
       log_debug ("%s:%s: WKS client: '%s' is supported",
                  SRCNAME, __func__, mbox.c_str ());
     }
-  if (it != s_states.end())
-    {
-      it->second = state;
-    }
-  else
-    {
-      s_states.insert (std::make_pair (mbox, state));
-    }
 
+  WKSHelper::instance()->update_state (mbox, state);
+
+  gpgrt_lock_lock (&wks_lock);
   auto tit = s_last_checked.find(mbox);
   auto now = time (0);
   if (tit != s_last_checked.end())
@@ -193,11 +189,13 @@ do_check (LPVOID arg)
     {
       s_last_checked.insert (std::make_pair (mbox, now));
     }
-
   gpgrt_lock_unlock (&wks_lock);
+
+  WKSHelper::instance()->save ();
   return 0;
 }
 
+
 void
 WKSHelper::start_check (const std::string &mbox, bool forced) const
 {
@@ -234,3 +232,158 @@ WKSHelper::save () const
 {
   // TODO
 }
+
+static DWORD WINAPI
+do_notify (LPVOID arg)
+{
+  /** Wait till a message was sent */
+  //Sleep (5000);
+  do_in_ui_thread (WKS_NOTIFY, arg);
+
+  return 0;
+}
+
+void
+WKSHelper::allow_notify () const
+{
+  gpgrt_lock_lock (&wks_lock);
+  for (auto &pair: s_states)
+    {
+      if (pair.second == NeedsPublish)
+        {
+          CloseHandle (CreateThread (NULL, 0, do_notify,
+                                     strdup (pair.first.c_str ()), 0,
+                                     NULL));
+          break;
+        }
+    }
+  gpgrt_lock_unlock (&wks_lock);
+}
+
+void
+WKSHelper::notify (const char *cBox) const
+{
+  std::string mbox = cBox;
+
+  const auto state = get_state (mbox);
+
+  if (state == NeedsPublish)
+    {
+      wchar_t * w_title = utf8_to_wchar (_("GpgOL: Key directory available!"));
+      wchar_t * w_desc = utf8_to_wchar (_("Your mail provider supports a key directory.\n\n"
+                                          "Register your key in that directory to make\n"
+                                          "it easier for others to send you encrypted mail.\n\n\n"
+                                          "Register Key?"));
+      if (MessageBoxW (get_active_hwnd (),
+                       w_desc, w_title, MB_ICONINFORMATION | MB_YESNO) == IDYES)
+        {
+          start_publish (mbox);
+        }
+      else
+        {
+           update_state (mbox, PublishDenied);
+        }
+
+      xfree (w_desc);
+      xfree (w_title);
+      return;
+    }
+  else
+    {
+      log_debug ("%s:%s: Unhandled notify state: %i for '%s'",
+                 SRCNAME, __func__, state, cBox);
+      return;
+    }
+}
+
+void
+WKSHelper::start_publish (const std::string &mbox) const
+{
+  Overlay (get_active_hwnd (),
+           std::string (_("Creating registration request...")));
+
+  log_debug ("%s:%s: Start publish for '%s'",
+             SRCNAME, __func__, mbox.c_str ());
+
+  const auto key = GpgME::Key::locate (mbox.c_str ());
+
+  if (key.isNull ())
+    {
+      MessageBox (get_active_hwnd (),
+                  "WKS publish failed to find key for mail address.",
+                  _("GpgOL"),
+                  MB_ICONINFORMATION|MB_OK);
+      return;
+    }
+
+  const auto wksPath = get_wks_client_path ();
+
+  if (wksPath.empty())
+    {
+      TRACEPOINT;
+      return;
+    }
+
+  std::vector<std::string> args;
+
+  args.push_back (wksPath);
+  args.push_back (std::string ("--create"));
+  args.push_back (std::string (key.primaryFingerprint ()));
+  args.push_back (mbox);
+
+  // Spawn the process
+  auto ctx = GpgME::Context::createForEngine (GpgME::SpawnEngine);
+  if (!ctx)
+    {
+      TRACEPOINT;
+      return;
+    }
+
+  GpgME::Data mystdin, mystdout, mystderr;
+
+  char **cargs = vector_to_cArray (args);
+
+  GpgME::Error err = ctx->spawn (cargs[0], const_cast <const char **> (cargs),
+                                 mystdin, mystdout, mystderr,
+                                 GpgME::Context::SpawnNone);
+  release_cArray (cargs);
+
+  if (err)
+    {
+      log_debug ("%s:%s: WKS client spawn code: %i asString: %s",
+                 SRCNAME, __func__, err.code(), err.asString());
+      return;
+    }
+  auto data = mystdout.toString ();
+
+  if (data.empty ())
+    {
+      MessageBox (get_active_hwnd (),
+                  "WKS client failed to create publishing request.",
+                  _("GpgOL"),
+                  MB_ICONINFORMATION|MB_OK);
+      return;
+    }
+
+  log_debug ("%s:%s: WKS client: returned '%s'",
+             SRCNAME, __func__, data.c_str ());
+  return;
+}
+
+
+void
+WKSHelper::update_state (const std::string &mbox, WKSState state) const
+{
+  gpgrt_lock_lock (&wks_lock);
+  auto it = s_states.find(mbox);
+
+  if (it != s_states.end())
+    {
+      it->second = state;
+    }
+  else
+    {
+      s_states.insert (std::make_pair (mbox, state));
+    }
+  gpgrt_lock_unlock (&wks_lock);
+}
diff --git a/src/wks-helper.h b/src/wks-helper.h
index 29af516..2f55a3f 100644
--- a/src/wks-helper.h
+++ b/src/wks-helper.h
@@ -41,6 +41,7 @@ public:
         NeedsPublish, /* <-- There was no key published for this address */
         NeedsUpdate, /* <-- Not yet implemeted. */
         RequestSent, /* <-- A publishing request has been sent. */
+        PublishDenied, /* <-- A user denied publishing. */
       };
 
     ~WKSHelper ();
@@ -72,9 +73,23 @@ public:
     */
     void start_check (const std::string &mbox, bool force = false) const;
 
+    /** Starts gpg-wks-client --create */
+    void start_publish (const std::string &mbox) const;
+
+    /** Allow queueing a notification. */
+    void allow_notify () const;
+
+    /** Send a notification and start publishing accordingly */
+    void notify (const char *mbox) const;
+
+    /** Store the current static maps. */
+    void save () const;
+
+    /** Update or insert a state in the static maps. */
+    void update_state (const std::string &mbox, WKSState state) const;
+
 private:
     time_t get_check_time (const std::string &mbox) const;
 
-    void save() const;
-    void load() const;;
+    void load() const;
 };

commit 6436349496e052cddbebef7394fb88db60bb4846
Author: Andre Heinecke <aheinecke at intevation.de>
Date:   Fri Feb 16 13:03:06 2018 +0100

    Fix detection of unencrypted mails in send
    
    * src/mailitem-events.cpp (EVENT_SINK_INVOKE): Check
    state before passing send.
    
    --
    This has not lead to bugs because no needs_crypto mails
    went to update_crypt_mapi but it's the wrong branch anyhow
    and the mails should pass through our hacks in send.

diff --git a/src/mailitem-events.cpp b/src/mailitem-events.cpp
index dc667be..2360789 100644
--- a/src/mailitem-events.cpp
+++ b/src/mailitem-events.cpp
@@ -335,7 +335,7 @@ EVENT_SINK_INVOKE(MailItemEvents)
            */
           log_oom_extra ("%s:%s: Send : %p",
                          SRCNAME, __func__, m_mail);
-          if (!m_mail->needs_crypto ())
+          if (!m_mail->needs_crypto () && m_mail->crypt_state () == Mail::NoCryptMail)
             {
              log_debug ("%s:%s: No crypto neccessary. Passing send for %p obj %p",
                         SRCNAME, __func__, m_mail, m_object);

commit 7c611426da261b67dd422ada7ae5b85bd8265649
Author: Andre Heinecke <aheinecke at intevation.de>
Date:   Fri Feb 16 13:01:49 2018 +0100

    Add EnableWindow functionality to Overlay
    
    * src/overlay.cpp (Overlay::~Overlay): Enable window.
    (Overlay::Overlay): Disable window.
    * src/overlay.h (m_wid): New member.

diff --git a/src/overlay.cpp b/src/overlay.cpp
index a53bc14..f1467b9 100644
--- a/src/overlay.cpp
+++ b/src/overlay.cpp
@@ -27,8 +27,10 @@
 
 #include <gpgme++/context.h>
 
-Overlay::Overlay (HWND wid, const std::string &text)
+Overlay::Overlay (HWND wid, const std::string &text): m_wid (wid)
 {
+  // Disable the window early to avoid it beeing closed.
+  EnableWindow (m_wid, FALSE);
   std::vector<std::string> args;
 
   // Collect the arguments
@@ -36,6 +38,7 @@ Overlay::Overlay (HWND wid, const std::string &text)
   if (!gpg4win_dir)
     {
       TRACEPOINT;
+      EnableWindow (m_wid, TRUE);
       return;
     }
   const auto overlayer = std::string (gpg4win_dir) + "\\bin\\overlayer.exe";
@@ -56,6 +59,7 @@ Overlay::Overlay (HWND wid, const std::string &text)
       // can't happen
       release_cArray (cargs);
       TRACEPOINT;
+      EnableWindow (m_wid, TRUE);
       return;
     }
 
@@ -68,7 +72,6 @@ Overlay::Overlay (HWND wid, const std::string &text)
                                                 GpgME::Context::SpawnAllowSetFg |
                                                 GpgME::Context::SpawnShowWindow));
   release_cArray (cargs);
-  TRACEPOINT;
 
   log_debug ("%s:%s: Created overlay window over %p",
              SRCNAME, __func__, wid);
@@ -78,5 +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);
+  EnableWindow (m_wid, TRUE);
 }
diff --git a/src/overlay.h b/src/overlay.h
index 9f8ed62..3e9c634 100644
--- a/src/overlay.h
+++ b/src/overlay.h
@@ -41,6 +41,7 @@ public:
 private:
   std::unique_ptr<GpgME::Context> m_overlayCtx;
   GpgME::Data m_overlayStdin;
+  HWND m_wid;
 };
 
 #endif // OVERLAY_H

commit e59a0ab7032ad219d1ed727831034ee51d12649f
Author: Andre Heinecke <aheinecke at intevation.de>
Date:   Fri Feb 16 10:53:54 2018 +0100

    Put overlayer calls in a simple RAII class
    
    * src/Makefile.am: Add overlay.
    * src/cryptocontroller.cpp (start_crypto_overlay): Move code
    into seperate class.
    (stop_crypto_overlay): Removed. Unique ptr takes care of that.
    * src/cryptocontroller.h: Update accordingly.
    * src/overlay.cpp, src/overlay.h: New.

diff --git a/src/Makefile.am b/src/Makefile.am
index 026f031..7ef1edd 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -87,7 +87,8 @@ gpgol_SOURCES = \
 	explorer-events.cpp explorers-events.cpp \
 	cryptcontroller.cpp cryptcontroller.h \
 	cpphelp.cpp cpphelp.h \
-	wks-helper.cpp wks-helper.h
+	wks-helper.cpp wks-helper.h \
+	overlay.cpp overlay.h
 
 
 #treeview_SOURCES = treeview.c
diff --git a/src/cryptcontroller.cpp b/src/cryptcontroller.cpp
index c45102a..a510978 100644
--- a/src/cryptcontroller.cpp
+++ b/src/cryptcontroller.cpp
@@ -27,6 +27,7 @@
 #include "mapihelp.h"
 #include "mimemaker.h"
 #include "wks-helper.h"
+#include "overlay.h"
 
 #include <gpgme++/context.h>
 #include <gpgme++/signingresult.h>
@@ -79,7 +80,6 @@ CryptController::CryptController (Mail *mail, bool encrypt, bool sign,
 
 CryptController::~CryptController()
 {
-  stop_crypto_overlay();
   log_debug ("%s:%s:%p",
              SRCNAME, __func__, m_mail);
 }
@@ -916,76 +916,19 @@ CryptController::parse_micalg (const GpgME::SigningResult &result)
 }
 
 void
-CryptController::stop_crypto_overlay ()
-{
-  if (m_overlayCtx)
-    {
-      log_debug ("%s:%s: Stopping crypto overlay.",
-                 SRCNAME, __func__);
-      m_overlayStdin.write ("quit\n", 5);
-      m_overlayCtx = nullptr;
-    }
-}
-
-void
 CryptController::start_crypto_overlay ()
 {
-  std::vector<std::string> args;
+  auto wid = m_mail->get_window ();
 
-  // Collect the arguments
-  char *gpg4win_dir = get_gpg4win_dir ();
-  if (!gpg4win_dir)
-    {
-      TRACEPOINT;
-      return;
-    }
-  const auto overlayer = std::string (gpg4win_dir) + "\\bin\\overlayer.exe";
-  xfree (gpg4win_dir);
-  args.push_back (overlayer);
-
-  auto wnd = m_mail->get_window ();
-  if (wnd)
-    {
-      // Pass the handle of the active window for raise / overlay.
-      args.push_back (std::string ("--hwnd"));
-      args.push_back (std::to_string ((int) wnd));
-    }
+  std::string text;
 
-  args.push_back (std::string ("--overlayText"));
   if (m_encrypt)
     {
-      args.push_back (std::string (_("Encrypting...")));
+      text = _("Encrypting...");
     }
   else if (m_sign)
     {
-      args.push_back (std::string (_("Signing...")));
+      text =_("Signing...");
     }
-  char **cargs = vector_to_cArray (args);
-
-  m_overlayCtx = GpgME::Context::createForEngine (GpgME::SpawnEngine);
-
-  if (!m_overlayCtx)
-    {
-      // can't happen
-      release_cArray (cargs);
-      TRACEPOINT;
-      return;
-    }
-
-  GpgME::Data mystderr(GpgME::Data::null);
-  GpgME::Data mystdout(GpgME::Data::null);
-
-  GpgME::Error err = m_overlayCtx->spawnAsync (cargs[0], const_cast <const char**> (cargs),
-                                      m_overlayStdin, mystdout, mystderr,
-                                      (GpgME::Context::SpawnFlags) (
-                                       GpgME::Context::SpawnAllowSetFg |
-                                       GpgME::Context::SpawnShowWindow));
-#ifdef DEBUG_RESOLVER
-  log_debug ("Overlayer args:");
-  for (size_t i = 0; cargs && cargs[i]; i++)
-    {
-      log_debug ("%i: '%s'", i, cargs[i]);
-    }
-#endif
-  release_cArray (cargs);
+  m_overlay = std::unique_ptr<Overlay> (new Overlay (wid, text));
 }
diff --git a/src/cryptcontroller.h b/src/cryptcontroller.h
index 4178a2c..ebcd4e0 100644
--- a/src/cryptcontroller.h
+++ b/src/cryptcontroller.h
@@ -28,6 +28,7 @@
 #include <gpgme++/data.h>
 
 class Mail;
+class Overlay;
 
 namespace GpgME
 {
@@ -72,18 +73,16 @@ private:
   void parse_micalg (const GpgME::SigningResult &sResult);
 
   void start_crypto_overlay ();
-  void stop_crypto_overlay ();
 
 private:
   Mail *m_mail;
   GpgME::Data m_input, m_bodyInput, m_signedData, m_output;
-  GpgME::Data m_overlayStdin;
   std::string m_micalg;
   bool m_encrypt, m_sign, m_inline, m_crypto_success;
   GpgME::Protocol m_proto;
   GpgME::Key m_signer_key;
   std::vector<GpgME::Key> m_recipients;
-  std::unique_ptr<GpgME::Context> m_overlayCtx;
+  std::unique_ptr<Overlay> m_overlay;
 };
 
 #endif
diff --git a/src/overlay.cpp b/src/overlay.cpp
new file mode 100644
index 0000000..a53bc14
--- /dev/null
+++ b/src/overlay.cpp
@@ -0,0 +1,82 @@
+/*
+ * 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 "overlay.h"
+
+#include "common.h"
+#include "cpphelp.h"
+
+#include <vector>
+
+#include <gpgme++/context.h>
+
+Overlay::Overlay (HWND wid, const std::string &text)
+{
+  std::vector<std::string> args;
+
+  // Collect the arguments
+  char *gpg4win_dir = get_gpg4win_dir ();
+  if (!gpg4win_dir)
+    {
+      TRACEPOINT;
+      return;
+    }
+  const auto overlayer = std::string (gpg4win_dir) + "\\bin\\overlayer.exe";
+  xfree (gpg4win_dir);
+  args.push_back (overlayer);
+
+  args.push_back (std::string ("--hwnd"));
+  args.push_back (std::to_string ((int) wid));
+
+  args.push_back (std::string ("--overlayText"));
+  args.push_back (text);
+  char **cargs = vector_to_cArray (args);
+
+  m_overlayCtx = GpgME::Context::createForEngine (GpgME::SpawnEngine);
+
+  if (!m_overlayCtx)
+    {
+      // can't happen
+      release_cArray (cargs);
+      TRACEPOINT;
+      return;
+    }
+
+  GpgME::Data mystderr(GpgME::Data::null);
+  GpgME::Data mystdout(GpgME::Data::null);
+
+  GpgME::Error err = m_overlayCtx->spawnAsync (cargs[0], const_cast <const char**> (cargs),
+                                               m_overlayStdin, mystdout, mystderr,
+                                               (GpgME::Context::SpawnFlags) (
+                                                GpgME::Context::SpawnAllowSetFg |
+                                                GpgME::Context::SpawnShowWindow));
+  release_cArray (cargs);
+  TRACEPOINT;
+
+  log_debug ("%s:%s: Created overlay window over %p",
+             SRCNAME, __func__, wid);
+}
+
+Overlay::~Overlay()
+{
+  log_debug ("%s:%s: Stopping overlay.",
+             SRCNAME, __func__);
+  m_overlayStdin.write ("quit\n", 5);
+}
diff --git a/src/overlay.h b/src/overlay.h
new file mode 100644
index 0000000..9f8ed62
--- /dev/null
+++ b/src/overlay.h
@@ -0,0 +1,46 @@
+#ifndef OVERLAY_H
+#define OVERLAY_H
+/* @file overlay.h
+ * @brief Overlay something through WinAPI.
+ *
+ * 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 <windows.h>
+
+#include <string>
+
+#include <gpgme++/data.h>
+
+namespace GpgME
+{
+  class Context;
+} // namespace GpgME
+
+class Overlay
+{
+public:
+  /* Create an overlay over a foreign window */
+  Overlay(HWND handle, const std::string &text);
+  ~Overlay();
+
+private:
+  std::unique_ptr<GpgME::Context> m_overlayCtx;
+  GpgME::Data m_overlayStdin;
+};
+
+#endif // OVERLAY_H

commit acf089c3376a1e097ebc6d4cc1dde8ac124df8a8
Author: Andre Heinecke <aheinecke at intevation.de>
Date:   Fri Feb 16 09:40:23 2018 +0100

    Implement WKS Supported check
    
    * src/Makefile.am: Add wks-helper
    * src/wks-helper.cpp: New.
    * src/wks-helper.h: New.
    * src/cryptcontroller.cpp (CryptController::do_crypto): Trigger
    WKS Check when doing crypto.

diff --git a/src/Makefile.am b/src/Makefile.am
index d605c20..026f031 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -86,7 +86,8 @@ gpgol_SOURCES = \
 	mimedataprovider.cpp mimedataprovider.h \
 	explorer-events.cpp explorers-events.cpp \
 	cryptcontroller.cpp cryptcontroller.h \
-	cpphelp.cpp cpphelp.h
+	cpphelp.cpp cpphelp.h \
+	wks-helper.cpp wks-helper.h
 
 
 #treeview_SOURCES = treeview.c
diff --git a/src/cryptcontroller.cpp b/src/cryptcontroller.cpp
index eee123d..c45102a 100644
--- a/src/cryptcontroller.cpp
+++ b/src/cryptcontroller.cpp
@@ -26,6 +26,7 @@
 #include "mail.h"
 #include "mapihelp.h"
 #include "mimemaker.h"
+#include "wks-helper.h"
 
 #include <gpgme++/context.h>
 #include <gpgme++/signingresult.h>
@@ -443,6 +444,9 @@ CryptController::do_crypto ()
   log_debug ("%s:%s",
              SRCNAME, __func__);
 
+  /* Start a WKS check if necessary. */
+  WKSHelper::instance()->start_check (m_mail->get_cached_sender ());
+
   if (resolve_keys ())
     {
       log_debug ("%s:%s: Failure to resolve keys.",
diff --git a/src/wks-helper.cpp b/src/wks-helper.cpp
new file mode 100644
index 0000000..efe3bce
--- /dev/null
+++ b/src/wks-helper.cpp
@@ -0,0 +1,236 @@
+/* wks-helper.cpp - Web Key Services for GpgOL
+ * 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 "wks-helper.h"
+
+#include "common.h"
+#include "cpphelp.h"
+
+#include <map>
+
+#include <unistd.h>
+
+#include <gpg-error.h>
+#include <gpgme++/key.h>
+#include <gpgme++/data.h>
+#include <gpgme++/context.h>
+
+#define CHECK_MIN_INTERVAL (60 * 60 * 24 * 7)
+
+static std::map <std::string, WKSHelper::WKSState> s_states;
+static std::map <std::string, time_t> s_last_checked;
+
+static WKSHelper* singleton = NULL;
+
+GPGRT_LOCK_DEFINE (wks_lock);
+
+WKSHelper::WKSHelper()
+{
+  load ();
+}
+
+WKSHelper::~WKSHelper ()
+{
+  // Ensure that we are not destroyed while
+  // worker is running.
+  gpgrt_lock_lock (&wks_lock);
+  gpgrt_lock_unlock (&wks_lock);
+}
+
+const WKSHelper*
+WKSHelper::instance ()
+{
+  if (!singleton)
+    {
+      singleton = new WKSHelper ();
+    }
+  return singleton;
+}
+
+WKSHelper::WKSState
+WKSHelper::get_state (const std::string &mbox) const
+{
+  gpgrt_lock_lock (&wks_lock);
+  const auto it = s_states.find(mbox);
+  const auto dataEnd = s_states.end();
+  gpgrt_lock_unlock (&wks_lock);
+  if (it == dataEnd)
+    {
+      return NotChecked;
+    }
+  return it->second;
+}
+
+time_t
+WKSHelper::get_check_time (const std::string &mbox) const
+{
+  gpgrt_lock_lock (&wks_lock);
+  const auto it = s_last_checked.find(mbox);
+  const auto dataEnd = s_last_checked.end();
+  gpgrt_lock_unlock (&wks_lock);
+  if (it == dataEnd)
+    {
+      return 0;
+    }
+  return it->second;
+}
+
+static std::string
+get_wks_client_path ()
+{
+  char *gpg4win_dir = get_gpg4win_dir ();
+  if (!gpg4win_dir)
+    {
+      TRACEPOINT;
+      return std::string ();
+    }
+  const auto ret = std::string (gpg4win_dir) +
+                  "\\..\\GnuPG\\bin\\gpg-wks-client.exe";
+  xfree (gpg4win_dir);
+
+  if (!access (ret.c_str (), F_OK))
+    {
+      return ret;
+    }
+  log_debug ("%s:%s: Failed to find wks-client in '%s'",
+             SRCNAME, __func__, ret.c_str ());
+  return std::string ();
+}
+
+static DWORD WINAPI
+do_check (LPVOID arg)
+{
+  const auto wksPath = get_wks_client_path ();
+
+  if (wksPath.empty())
+    {
+      return 0;
+    }
+
+  std::vector<std::string> args;
+  const auto mbox = std::string ((char *) arg);
+  xfree (arg);
+
+  args.push_back (wksPath);
+  args.push_back (std::string ("--status-fd"));
+  args.push_back (std::string ("1"));
+  args.push_back (std::string ("--supported"));
+  args.push_back (mbox);
+
+  // Spawn the process
+  auto ctx = GpgME::Context::createForEngine (GpgME::SpawnEngine);
+
+  if (!ctx)
+    {
+      TRACEPOINT;
+      return 0;
+    }
+
+  GpgME::Data mystdin, mystdout, mystderr;
+
+  char **cargs = vector_to_cArray (args);
+
+  GpgME::Error err = ctx->spawn (cargs[0], const_cast <const char **> (cargs),
+                                 mystdin, mystdout, mystderr,
+                                 GpgME::Context::SpawnNone);
+  release_cArray (cargs);
+
+  if (err)
+    {
+      log_debug ("%s:%s: WKS client spawn code: %i asString: %s",
+                 SRCNAME, __func__, err.code(), err.asString());
+      return 0;
+    }
+
+  auto data = mystdout.toString ();
+  rtrim (data);
+
+  bool success = data == "[GNUPG:] SUCCESS";
+  const auto state = success ? WKSHelper::Supported : WKSHelper::NotSupported;
+
+  gpgrt_lock_lock (&wks_lock);
+
+  auto it = s_states.find(mbox);
+
+  // TODO figure out if it was published.
+  if (success)
+    {
+      log_debug ("%s:%s: WKS client: '%s' is supported",
+                 SRCNAME, __func__, mbox.c_str ());
+    }
+  if (it != s_states.end())
+    {
+      it->second = state;
+    }
+  else
+    {
+      s_states.insert (std::make_pair (mbox, state));
+    }
+
+  auto tit = s_last_checked.find(mbox);
+  auto now = time (0);
+  if (tit != s_last_checked.end())
+    {
+      tit->second = now;
+    }
+  else
+    {
+      s_last_checked.insert (std::make_pair (mbox, now));
+    }
+
+  gpgrt_lock_unlock (&wks_lock);
+  return 0;
+}
+
+void
+WKSHelper::start_check (const std::string &mbox, bool forced) const
+{
+  auto lastTime = get_check_time (mbox);
+  auto now = time (0);
+  if (!forced && lastTime && difftime (lastTime, now) < CHECK_MIN_INTERVAL)
+    {
+      /* Data is new enough */
+      return;
+    }
+
+  if (mbox.empty())
+    {
+      log_debug ("%s:%s: start check called without mbox",
+                 SRCNAME, __func__);
+    }
+
+  log_debug ("%s:%s: WKSHelper starting check",
+             SRCNAME, __func__);
+  /* Start the actual work that can be done in a background thread. */
+  CloseHandle (CreateThread (NULL, 0, do_check, strdup (mbox.c_str ()), 0,
+                             NULL));
+  return;
+}
+
+void
+WKSHelper::load () const
+{
+  // TODO
+}
+
+void
+WKSHelper::save () const
+{
+  // TODO
+}
diff --git a/src/wks-helper.h b/src/wks-helper.h
new file mode 100644
index 0000000..29af516
--- /dev/null
+++ b/src/wks-helper.h
@@ -0,0 +1,80 @@
+/* @file wks-helper.cpp
+ * @brief Helper to work with a web-key-service
+ *
+ * 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 <string>
+
+/** @brief Helper for web key services.
+ *
+ * Everything is public to make it easy to access data
+ * members from another windows thread. Don't mess with them.
+ */
+class WKSHelper
+{
+protected:
+    /** Loads the list of checked keys */
+    explicit WKSHelper ();
+public:
+    enum WKSState
+      {
+        NotChecked, /*<-- Supported state was not checked */
+        NotSupported, /* <-- WKS is not supported for this address */
+        Supported, /* <-- WKS is supported for this address */
+        NeedsPublish, /* <-- There was no key published for this address */
+        NeedsUpdate, /* <-- Not yet implemeted. */
+        RequestSent, /* <-- A publishing request has been sent. */
+      };
+
+    ~WKSHelper ();
+
+    /** Get the WKSHelper
+
+        On the initial request:
+        Ensure that the OOM is available.
+        Will load all account addresses from OOM and then return.
+
+        Starts a background thread to load info from a file
+        and run checks if necessary.
+
+        When the thread is finished initialized will be true.
+    */
+    static const WKSHelper* instance ();
+
+    /** If the key for the address @address should be published */
+    WKSState get_state (const std::string &mbox) const;
+
+    /** Start a supported check for a given mbox.
+
+        If force is true the check will be run. Otherwise
+        the state will only be updated if the last check
+        was more then 7 days ago.
+
+        Returns immediately as the check is run in a background
+        thread.
+    */
+    void start_check (const std::string &mbox, bool force = false) const;
+
+private:
+    time_t get_check_time (const std::string &mbox) const;
+
+    void save() const;
+    void load() const;;
+};

commit cc08ea5d290c279fcd69a7f6b712e20f9f8f5900
Author: Andre Heinecke <aheinecke at intevation.de>
Date:   Fri Feb 16 09:39:53 2018 +0100

    Fix minor memleak
    
    * src/cryptcontroller.cpp (CryptController::do_crypto): Free
    gpg4win_dir.

diff --git a/src/cryptcontroller.cpp b/src/cryptcontroller.cpp
index 2f74294..eee123d 100644
--- a/src/cryptcontroller.cpp
+++ b/src/cryptcontroller.cpp
@@ -936,6 +936,7 @@ CryptController::start_crypto_overlay ()
       return;
     }
   const auto overlayer = std::string (gpg4win_dir) + "\\bin\\overlayer.exe";
+  xfree (gpg4win_dir);
   args.push_back (overlayer);
 
   auto wnd = m_mail->get_window ();

commit e25a51950583d0ae051b38f0aed17522fb8f77b5
Author: Andre Heinecke <aheinecke at intevation.de>
Date:   Fri Feb 16 08:09:03 2018 +0100

    Factor out common cpp helper to cpphelp
    
    * src/cryptcontroller.cpp (release_carray, vector_to_charArray)
    (rtrim): Move into cpphelp.
    * src/cpphelp.cpp, src/cpphelp.h: New.
    * src/Makefile.am: Add it.

diff --git a/src/Makefile.am b/src/Makefile.am
index 90091cb..d605c20 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -85,7 +85,8 @@ gpgol_SOURCES = \
 	parsecontroller.cpp parsecontroller.h \
 	mimedataprovider.cpp mimedataprovider.h \
 	explorer-events.cpp explorers-events.cpp \
-	cryptcontroller.cpp cryptcontroller.h
+	cryptcontroller.cpp cryptcontroller.h \
+	cpphelp.cpp cpphelp.h
 
 
 #treeview_SOURCES = treeview.c
diff --git a/src/cpphelp.cpp b/src/cpphelp.cpp
new file mode 100644
index 0000000..20b91d3
--- /dev/null
+++ b/src/cpphelp.cpp
@@ -0,0 +1,57 @@
+/* @file cpphelp.h
+ * @brief Common cpp helper stuff
+ *
+ * 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 <algorithm>
+#include "cpphelp.h"
+
+#include "common.h"
+
+void
+release_cArray (char **carray)
+{
+  if (carray)
+    {
+      for (int idx = 0; carray[idx]; idx++)
+        xfree (carray[idx]);
+      xfree (carray);
+    }
+}
+
+void
+rtrim(std::string &s) {
+    s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) {
+        return !std::isspace(ch);
+    }).base(), s.end());
+}
+
+char **
+vector_to_cArray(const std::vector<std::string> &vec)
+{
+  char ** ret = (char**) xmalloc (sizeof (char*) * (vec.size() + 1));
+  for (size_t i = 0; i < vec.size(); i++)
+    {
+      ret[i] = strdup (vec[i].c_str());
+    }
+  ret[vec.size()] = NULL;
+  return ret;
+}
diff --git a/src/cpphelp.h b/src/cpphelp.h
new file mode 100644
index 0000000..0b60170
--- /dev/null
+++ b/src/cpphelp.h
@@ -0,0 +1,39 @@
+#ifndef CPPHELP_H
+#define CPPHELP_H
+/* @file cpphelp.h
+ * @brief Common cpp helper stuff
+ *
+ * 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 <string>
+#include <vector>
+
+/* Stuff that should be in common but is c++ so it does not fit in there. */
+
+
+/* Release a null terminated char* array */
+void release_cArray (char **carray);
+
+/* Trim whitespace from a string. */
+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);
+
+#endif // CPPHELP_H
diff --git a/src/cryptcontroller.cpp b/src/cryptcontroller.cpp
index 2920544..2f74294 100644
--- a/src/cryptcontroller.cpp
+++ b/src/cryptcontroller.cpp
@@ -21,6 +21,7 @@
 #include "config.h"
 
 #include "common.h"
+#include "cpphelp.h"
 #include "cryptcontroller.h"
 #include "mail.h"
 #include "mapihelp.h"
@@ -161,38 +162,6 @@ CryptController::collect_data ()
   return 0;
 }
 
-static void
-release_carray (char **recipients)
-{
-  int idx;
-
-  if (recipients)
-    {
-      for (idx=0; recipients[idx]; idx++)
-        xfree (recipients[idx]);
-      xfree (recipients);
-    }
-}
-
-static inline void
-rtrim(std::string &s) {
-    s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) {
-        return !std::isspace(ch);
-    }).base(), s.end());
-}
-
-char **
-vector_to_charArray(const std::vector<std::string> &vec)
-{
-  char ** ret = (char**) xmalloc (sizeof (char*) * (vec.size() + 1));
-  for (size_t i = 0; i < vec.size(); i++)
-    {
-      ret[i] = strdup (vec[i].c_str());
-    }
-  ret[vec.size()] = NULL;
-  return ret;
-}
-
 int
 CryptController::lookup_fingerprints (const std::string &sigFpr,
                                       const std::vector<std::string> recpFprs)
@@ -232,7 +201,7 @@ CryptController::lookup_fingerprints (const std::string &sigFpr,
   }
 
   // Convert recipient fingerprints
-  char **cRecps = vector_to_charArray (recpFprs);
+  char **cRecps = vector_to_cArray (recpFprs);
 
   err = ctx->startKeyListing (const_cast<const char **> (cRecps));
 
@@ -248,7 +217,7 @@ CryptController::lookup_fingerprints (const std::string &sigFpr,
 
   m_recipients.pop_back();
 
-  release_carray (cRecps);
+  release_cArray (cRecps);
 
   return 0;
 }
@@ -402,13 +371,13 @@ CryptController::resolve_keys ()
           args.push_back (GpgME::UserID::addrSpecFromString (recipients[i]));
         }
 
-      release_carray (recipients);
+      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_charArray (args);
+  char **cargs = vector_to_cArray (args);
 
   // Args are prepared. Spawn the resolver.
   auto ctx = GpgME::Context::createForEngine (GpgME::SpawnEngine);
@@ -416,7 +385,7 @@ CryptController::resolve_keys ()
   if (!ctx)
     {
       // can't happen
-      release_carray (cargs);
+      release_cArray (cargs);
       TRACEPOINT;
       return -1;
     }
@@ -448,7 +417,7 @@ CryptController::resolve_keys ()
   log_debug ("Resolver stderr:\n'%s'", mystderr.toString ().c_str ());
 #endif
 
-  release_carray (cargs);
+  release_cArray (cargs);
 
   if (err)
     {
@@ -986,14 +955,14 @@ CryptController::start_crypto_overlay ()
     {
       args.push_back (std::string (_("Signing...")));
     }
-  char **cargs = vector_to_charArray (args);
+  char **cargs = vector_to_cArray (args);
 
   m_overlayCtx = GpgME::Context::createForEngine (GpgME::SpawnEngine);
 
   if (!m_overlayCtx)
     {
       // can't happen
-      release_carray (cargs);
+      release_cArray (cargs);
       TRACEPOINT;
       return;
     }
@@ -1013,5 +982,5 @@ CryptController::start_crypto_overlay ()
       log_debug ("%i: '%s'", i, cargs[i]);
     }
 #endif
-  release_carray (cargs);
+  release_cArray (cargs);
 }

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

Summary of changes:
 src/Makefile.am                    |   5 +-
 src/cpphelp.cpp                    |  57 ++++++
 src/{addin-options.h => cpphelp.h} |  29 ++-
 src/cryptcontroller.cpp            | 117 ++---------
 src/cryptcontroller.h              |   5 +-
 src/mailitem-events.cpp            |   2 +-
 src/overlay.cpp                    |  88 +++++++++
 src/{addin-options.h => overlay.h} |  37 +++-
 src/windowmessages.cpp             |  10 +
 src/windowmessages.h               |   1 +
 src/wks-helper.cpp                 | 389 +++++++++++++++++++++++++++++++++++++
 src/wks-helper.h                   |  95 +++++++++
 12 files changed, 714 insertions(+), 121 deletions(-)
 create mode 100644 src/cpphelp.cpp
 copy src/{addin-options.h => cpphelp.h} (56%)
 create mode 100644 src/overlay.cpp
 copy src/{addin-options.h => overlay.h} (57%)
 create mode 100644 src/wks-helper.cpp
 create mode 100644 src/wks-helper.h


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




More information about the Gnupg-commits mailing list