Add patches for gpgex Kleopatra-kf5 compatibility
authorAndre Heinecke <aheinecke@intevation.de>
Thu, 10 Mar 2016 10:44:33 +0000 (11:44 +0100)
committerAndre Heinecke <aheinecke@intevation.de>
Thu, 10 Mar 2016 10:44:33 +0000 (11:44 +0100)
* Makefile.am (EXTRA_DIST): Add patches
* patches/gpgex-1.0.3/
 0001-Support-gpg4win-registry-keys-and-install-location.patch,
 patches/gpgex-1.0.3/
 0002-Place-assuan-calls-in-a-different-thread.patch: New.

Makefile.am
patches/gpgex-1.0.3/0001-Support-gpg4win-registry-keys-and-install-location.patch [new file with mode: 0755]
patches/gpgex-1.0.3/0002-Place-assuan-calls-in-a-different-thread.patch [new file with mode: 0755]

index 5fdf3e6..3f830b1 100644 (file)
@@ -59,7 +59,9 @@ EXTRA_DIST = autogen.sh README.GIT ONEWS \
         patches/kleopatra/0004-Make-DBus-integration-of-the-smime-conf-optional.patch \
         patches/kleopatra/0005-Hack-generated-conf-files-for-Crosscompiling.patch \
         patches/kcoreaddons/0001-Fix-Kdelibs4-config-migration-for-Windows.patch \
-        patches/pinentry-0.9.7/Qt-Fix-Windows-foreground-window-hacks-for-Qt5.patch
+        patches/pinentry-0.9.7/Qt-Fix-Windows-foreground-window-hacks-for-Qt5.patch \
+        patches/gpgex-1.0.3/0001-Support-gpg4win-registry-keys-and-install-location.patch \
+        patches/gpgex-1.0.3/0002-Place-assuan-calls-in-a-different-thread.patch
 
 copy-news:
        cp NEWS doc/website/NEWS.last
diff --git a/patches/gpgex-1.0.3/0001-Support-gpg4win-registry-keys-and-install-location.patch b/patches/gpgex-1.0.3/0001-Support-gpg4win-registry-keys-and-install-location.patch
new file mode 100755 (executable)
index 0000000..aefa31e
--- /dev/null
@@ -0,0 +1,206 @@
+#! /bin/sh
+patch -p1 -l -f $* < $0
+exit $?
+
+From 7dde1455bd1871a8f402d8c71c09d11b2b53f0ac Mon Sep 17 00:00:00 2001
+From: Andre Heinecke <aheinecke@intevation.de>
+Date: Thu, 10 Mar 2016 11:34:51 +0100
+Subject: [PATCH 1/2] Support gpg4win registry keys and install location
+
+* src/client.cc (default_uiserver_cmdline): Rewrite based on GpgOL.
+* src/main.cc (get_debug_file): Use new keys.
+* src/registry.h (REGKEY): Replace by GPG4WIN_REGKEY_2/3 add x64 key.
+
+--
+This tries harder to find kleopatra or GPA and looks in both the old
+GNU GnuPG registry key as in the new Gpg4win registry key. Also
+it looks both under /bin and not in /bin subfolder.
+---
+ src/client.cc  | 100 +++++++++++++++++++++++++++++++++++----------------------
+ src/main.cc    |  12 +++++--
+ src/registry.h |  13 ++++++--
+ 3 files changed, 83 insertions(+), 42 deletions(-)
+
+diff --git a/src/client.cc b/src/client.cc
+index 6aaa0f6..58be03b 100644
+--- a/src/client.cc
++++ b/src/client.cc
+@@ -108,67 +108,91 @@ default_uiserver_cmdline (void)
+     }
+ #else /*!ENABLE_GPA_ONLY*/
+     {
+-      const char *dir;
++      const char *dir, *tmp;
+       char *uiserver, *p;
+-      int extra_arglen = 0;
++      int extra_arglen = 9;
++      const char * server_names[] = {"bin\\kleopatra.exe",
++                                     "kleopatra.exe",
++                                     "bin\\launch-gpa.exe",
++                                     "launch-gpa.exe",
++                                     "bin\\gpa.exe",
++                                     "gpa.exe",
++                                     NULL};
+
+       dir = gpgex_server::root_dir;
+       if (!dir)
+         return NULL;
+
+-      uiserver = read_w32_registry_string (NULL, REGKEY, "UI Server");
++      uiserver = read_w32_registry_string (NULL, GPG4WIN_REGKEY_2,
++                                           "UI Server");
++      if (!uiserver)
++        {
++          uiserver = read_w32_registry_string (NULL, GPG4WIN_REGKEY_3,
++                                               "UI Server");
++        }
+       if (!uiserver)
+         {
+           uiserver = strdup ("kleopatra.exe");
+           if (!uiserver)
+             return NULL;
+-          extra_arglen = 9; /* Space required for " --daemon".  */
+         }
+-
+-      name = (char*)malloc (strlen (dir) + strlen (uiserver) + extra_arglen +2);
+-      if (!name)
++      if (uiserver)
+         {
++          name = (char*) malloc (strlen (dir) + strlen (uiserver) +
++                                 extra_arglen + 2);
++          if (!name)
++            return NULL;
++          strcpy (stpcpy (stpcpy (name, dir), "\\"), uiserver);
++          for (p = name; *p; p++)
++            if (*p == '/')
++              *p = '\\';
+           free (uiserver);
+-          return NULL;
+         }
+-      strcpy (stpcpy (stpcpy (name, dir), "\\"), uiserver);
+-      for (p = name; *p; p++)
+-        if (*p == '/')
+-          *p = '\\';
+-      free (uiserver);
+-      gpgex_server::ui_server = "Kleopatra";
+-      if (extra_arglen && access (name, F_OK))
++      if (name && !access (name, F_OK))
++        {
++          /* Set through registry or default kleo */
++          if (strstr (name, "kleopatra.exe"))
++            {
++              gpgex_server::ui_server = "Kleopatra";
++              strcat (name, " --daemon");
++            }
++          else
++            {
++              gpgex_server::ui_server = "GPA";
++            }
++          return name;
++        }
++      /* Fallbacks */
++      for (tmp = *server_names; *tmp; tmp++)
+         {
+-          /* Kleopatra is not installed: Try GPA instead but if it is
+-             also not available return the Kleopatra filename.  */
+-          const char gpaserver[] = "launch-gpa.exe";
+-          char *name2;
+-
+-          name2 = (char*)malloc (strlen (dir) + strlen (gpaserver)
+-                                 + extra_arglen+2);
+-          if (name2)
++          if (name)
++            {
++              free (name);
++            }
++          name = (char*) malloc (strlen (dir) + strlen (tmp) + extra_arglen + 2);
++          if (!name)
++            return NULL;
++          strcpy (stpcpy (stpcpy (name, dir), "\\"), tmp);
++          for (p = name; *p; p++)
++            if (*p == '/')
++              *p = '\\';
++          if (!access (name, F_OK))
+             {
+-              strcpy (stpcpy (stpcpy (name2, dir), "\\"), gpaserver);
+-              for (p = name2; *p; p++)
+-                if (*p == '/')
+-                  *p = '\\';
+-              if (access (name2, F_OK ))
+-                free (name2);
++              /* Found a viable candidate */
++              /* Set through registry and is accessible */
++              if (strstr (name, "kleopatra.exe"))
++                {
++                  gpgex_server::ui_server = "Kleopatra";
++                  strcat (name, " --daemon");
++                }
+               else
+                 {
+-                  free (name);
+-                  name = name2;
+                   gpgex_server::ui_server = "GPA";
+                 }
++              return name;
+             }
+         }
+-
+-      /* Append the --daemon arg unless the server name has been taken
+-         from the Registry.  */
+-      if (name && extra_arglen)
+-        strcat (name, " --daemon");
+-      else
+-        gpgex_server::ui_server = NULL;
++      gpgex_server::ui_server = NULL;
+     }
+ #endif /*!ENABLE_GPA_ONLY*/
+
+diff --git a/src/main.cc b/src/main.cc
+index dcade3b..8cc0ed9 100644
+--- a/src/main.cc
++++ b/src/main.cc
+@@ -167,8 +167,16 @@ FILE *debug_file;
+ static char *
+ get_debug_file (void)
+ {
+-  return read_w32_registry_string ("HKEY_LOCAL_MACHINE", REGKEY,
+-                                 "GpgEX Debug File");
++  char *name = read_w32_registry_string (NULL,
++                                         GPG4WIN_REGKEY_3,
++                                         "GpgEX Debug File");
++  if (!name)
++    {
++      name = read_w32_registry_string (NULL,
++                                       GPG4WIN_REGKEY_2,
++                                       "GpgEX Debug File");
++    }
++  return name;
+ }
+
+
+diff --git a/src/registry.h b/src/registry.h
+index 51113ab..d0e38ef 100644
+--- a/src/registry.h
++++ b/src/registry.h
+@@ -43,8 +43,17 @@ char *read_w32_registry_string (const char *root, const char *dir,
+ /* Retrieve the default home directory.  */
+ const char *default_homedir (void);
+
+-/* Registry key for this software.  */
+-#define REGKEY "Software\\GNU\\GnuPG"
++/* The Registry key used by Gpg4win.  */
++#ifdef WIN64
++# define GPG4WIN_REGKEY_2  "Software\\Wow6432Node\\GNU\\GnuPG"
++#else
++# define GPG4WIN_REGKEY_2  "Software\\GNU\\GnuPG"
++#endif
++#ifdef WIN64
++# define GPG4WIN_REGKEY_3  "Software\\Wow6432Node\\Gpg4win"
++#else
++# define GPG4WIN_REGKEY_3  "Software\\Gpg4win"
++#endif
+
+ #ifdef __cplusplus
+ #if 0
+--
+2.1.4
diff --git a/patches/gpgex-1.0.3/0002-Place-assuan-calls-in-a-different-thread.patch b/patches/gpgex-1.0.3/0002-Place-assuan-calls-in-a-different-thread.patch
new file mode 100755 (executable)
index 0000000..0718e94
--- /dev/null
@@ -0,0 +1,147 @@
+#! /bin/sh
+patch -p1 -l -f $* < $0
+exit $?
+
+From 423092437aade400521b7bb8d3d28085a93f4228 Mon Sep 17 00:00:00 2001
+From: Andre Heinecke <aheinecke@intevation.de>
+Date: Thu, 10 Mar 2016 11:38:11 +0100
+Subject: [PATCH 2/2] Place assuan calls in a different thread
+
+* src/client.cc (client_t::call_assuan): Use call_assuan_async. Void.
+ (call_assuan_async): New. To be used in CreateThread.
+
+--
+Using a different thread makes sense here as starting the uiserver
+can take a while and the return value was ignored anyway.
+
+This also fixes interaction with Kleopatra from Qt5 as the
+wId handling code Kleopatra uses to make the explorer the
+parent Window utilizes SendMessage calls which resulted in
+a deadlock.
+---
+ src/client.cc | 64 +++++++++++++++++++++++++++++++++++++++++++----------------
+ src/client.h  |  2 +-
+ 2 files changed, 48 insertions(+), 18 deletions(-)
+
+diff --git a/src/client.cc b/src/client.cc
+index 58be03b..ebf82a8 100644
+--- a/src/client.cc
++++ b/src/client.cc
+@@ -410,20 +410,29 @@ uiserver_connect (assuan_context_t *ctx, HWND hwnd)
+   return TRACE_GPGERR (rc);
+ }
+
++typedef struct async_arg
++{
++  const char *cmd;
++  vector<string> filenames;
++  HWND wid;
++} async_arg_t;
+
+-bool
+-client_t::call_assuan (const char *cmd, vector<string> &filenames)
++static DWORD WINAPI
++call_assuan_async (LPVOID arg)
+ {
++  async_arg_t *async_args = (async_arg_t *)arg;
+   int rc = 0;
+   int connect_failed = 0;
++  const char *cmd = async_args->cmd;
++  const vector<string> filenames = async_args->filenames;
+
+   assuan_context_t ctx = NULL;
+   string msg;
+
+-  TRACE_BEG2 (DEBUG_ASSUAN, "client_t::call_assuan", this,
+-            "%s on %u files", cmd, filenames.size ());
++  TRACE_BEG2 (DEBUG_ASSUAN, "client_t::call_assuan_async", 0,
++              "%s on %u files", cmd, filenames.size ());
+
+-  rc = uiserver_connect (&ctx, this->window);
++  rc = uiserver_connect (&ctx, async_args->wid);
+   if (rc)
+     {
+       connect_failed = 1;
+@@ -434,23 +443,23 @@ client_t::call_assuan (const char *cmd, vector<string> &filenames)
+     {
+       /* Set the input files.  We don't specify the output files.  */
+       for (unsigned int i = 0; i < filenames.size (); i++)
+-      {
+-        msg = "FILE " + escape (filenames[i]);
++        {
++          msg = "FILE " + escape (filenames[i]);
+
+-        (void) TRACE_LOG1 ("sending cmd: %s", msg.c_str ());
++          (void) TRACE_LOG1 ("sending cmd: %s", msg.c_str ());
+
+-        rc = assuan_transact (ctx, msg.c_str (),
+-                              NULL, NULL, NULL, NULL, NULL, NULL);
+-        if (rc)
+-          goto leave;
+-      }
++          rc = assuan_transact (ctx, msg.c_str (),
++                                NULL, NULL, NULL, NULL, NULL, NULL);
++          if (rc)
++            goto leave;
++        }
+
+       /* Set the --nohup option, so that the operation continues and
+-       completes in the background.  */
++         completes in the background.  */
+       msg = ((string) cmd) + " --nohup";
+       (void) TRACE_LOG1 ("sending cmd: %s", msg.c_str ());
+       rc = assuan_transact (ctx, msg.c_str (),
+-                          NULL, NULL, NULL, NULL, NULL, NULL);
++                            NULL, NULL, NULL, NULL, NULL, NULL);
+     }
+   catch (std::bad_alloc)
+     {
+@@ -484,10 +493,31 @@ client_t::call_assuan (const char *cmd, vector<string> &filenames)
+                   gpgex_server::ui_server? gpgex_server::ui_server:"",
+                   gpgex_server::ui_server? ")":"",
+                   gpg_strerror (rc));
+-      MessageBox (this->window, buf, "GpgEX", MB_ICONINFORMATION);
++      MessageBox (async_args->wid, buf, "GpgEX", MB_ICONINFORMATION);
+     }
++  delete async_args;
++  return 0;
++}
+
+-  return rc ? false : true;
++void
++client_t::call_assuan (const char *cmd, vector<string> &filenames)
++{
++  TRACE_BEG (DEBUG_ASSUAN, "client_t::call_assuan", cmd);
++  async_arg_t * args = new async_arg_t;
++  args->cmd = cmd;
++  args->filenames = filenames;
++  args->wid = this->window;
++
++  /* We move the call in a different thread as the Windows explorer
++     is blocked until our call finishes. We don't want that.
++     Additionally Kleopatra / Qt5 SendsMessages to the parent
++     window provided in wid. Qt does this with blocking calls
++     so Kleopatra blocks until the explorer processes more
++     Window Messages and we block the explorer. This is
++     a deadlock. */
++  CreateThread (NULL, 0, call_assuan_async, (LPVOID) args, 0,
++                NULL);
++  return;
+ }
+
\f
+diff --git a/src/client.h b/src/client.h
+index 81fdfd6..8d08cd9 100644
+--- a/src/client.h
++++ b/src/client.h
+@@ -34,7 +34,7 @@ class client_t
+  private:
+   HWND window;
+
+-  bool call_assuan (const char *cmd, vector<string> &filenames);
++  void call_assuan (const char *cmd, vector<string> &filenames);
+
+  public:
+   client_t (HWND window_handle)
+--
+2.1.4