diff --git a/Makefile.am b/Makefile.am
index b689bf1c..e69a61d3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,110 +1,120 @@
# Makefile.am - Installer for GnuPG 4 Windows Makefile.
# Copyright (C) 2005, 2008, 2012 g10 Code GmbH
#
# This file is part of GPG4Win.
#
# GPG4Win is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# GPG4Win 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see .
ACLOCAL_AMFLAGS = -I m4
AUTOMAKE_OPTIONS = dist-bzip2 no-dist-gzip
DISTCHECK_CONFIGURE_FLAGS = --host=i686-w64-mingw32
if BUILD_GPG4WIN
po = po
else
po =
endif
if BUILD_GPG4WIN
doc = doc
else
doc =
endif
SUBDIRS = ${po} packages ${doc} src
# find patches -type f | sort | sed 's/$/ \\/' | sed 's/^/ /'
+# find patches-appimage -type f | sort | sed 's/$/ \\/' | sed 's/^/ /'
EXTRA_DIST = autogen.sh README.GIT ONEWS \
doc/license-page doc/GPLv3 \
build-aux/git-log-footer build-aux/git-log-fix \
patches/boost/boost-1-fixes.patch \
patches/breeze-icons/0001-Make-binary-icons-cross-compilable.patch \
patches/extra-cmake-modules/0001-Use-BIN_INSTALL_DIR-data-for-DATAROOTDIR-on-Windows.patch \
patches/glib-2.41.5/01-socket.patch \
patches/glib-2.41.5/02-formatsec.patch \
patches/gpgol/0001-Handle-protected-headers-also-on-multipart-parts.patch \
patches/kconfigwidgets/0001-Make-QDbus-optional.patch \
patches/kiconthemes/0001-Make-DBus-optional.patch \
patches/kleopatra/lower-cmake-requirement.patch \
patches/kxmlgui/0001-make-qdbus-optional.patch \
patches/kxmlgui/0004-Cruedly-disable-KSendbugmail.patch \
patches/libkleo/lower-cmake-requirement.patch \
patches/libkleo/z-01-use-pre-5.80-ecm_qt_declare_logging_category.patch \
patches/qtbase/0001-Fix-build-without-std-thread.patch \
patches/qtbase/0001-Gpg4win-qstandardpaths-patch.patch \
patches/qtbase/0002-Gpg4win-theme-names-and-relpaths.patch \
patches/qtbase/0003-Fix-build-with-GCC-11-include-limits.patch \
patches/qttools/disable-most-tools.patch \
- patches/w32pth-2.0.5/workaround-broken-libtool.patch
+ patches/w32pth-2.0.5/workaround-broken-libtool.patch \
+ patches-appimage/gnupg-2.3.2/0001-agent-Fix-segv-in-GET_PASSPHRASE-regression.patch \
+ patches-appimage/gnupg-2.3.2/0002-build-Fix-ksba.h-not-found-problem.patch \
+ patches-appimage/gnupg-2.3.2/0003-common-New-function-substitute_envvars.patch \
+ patches-appimage/gnupg-2.3.2/0004-common-Support-a-gpgconf.ctl-file-under-Unix.patch \
+ patches-appimage/gnupg-2.3.2/0005-build-Fix-several-include-file-not-found-problems.patch \
+ patches-appimage/kconfigwidgets/0001-build-without-KF5Auth.patch \
+ patches-appimage/libkleo-21.08.1/0001-Add-support-for-non-standard-boost-include-directori.patch \
+ patches-appimage/libkleo-21.08.1/z-01-use-pre-5.80-ecm_qt_declare_logging_category.patch \
+ patches-appimage/qtwayland-5.15.0/00-disable-wayland-server.patch
copy-news:
cp NEWS doc/website/NEWS.last
copy-release: gpg4win-$(VERSION).tar.bz2 installers/gpg4win-$(VERSION).exe \
installers/gpg4win-light-$(VERSION).exe \
installers/gpg4win-vanilla-$(VERSION).exe
@echo Copying $(VERSION) to $(RELEASEHOST) >&2
@set -e;\
if ssh "$$(echo $(RELEASEHOST)|cut -d: -f -1)" \
test -f "$$(echo $(RELEASEHOST)/gpg4win-$(VERSION).exe|cut -d: -f2-)";\
then echo "This release has already been copied to the server" >&2 ;\
else scp gpg4win-$(VERSION).tar.bz2 \
installers/gpg4win-$(VERSION).exe \
installers/gpg4win-light-$(VERSION).exe \
installers/gpg4win-vanilla-$(VERSION).exe \
installers/gpg4win-src-$(VERSION).exe $(RELEASEHOST)/ ;\
for f in en de ; do \
scp src/README.$$f.txt \
$(RELEASEHOST)/README-$(VERSION).$$f.txt; \
done;\
fi
dist-hook: gen-ChangeLog
gen_start_date = 2012-03-26T00:00:00
.PHONY: gen-ChangeLog
gen-ChangeLog:
set -e; \
if test -d $(top_srcdir)/.git; then \
(cd $(top_srcdir) && \
$(GITLOG_TO_CHANGELOG) --append-dot --tear-off \
--amend=build-aux/git-log-fix \
--since=$(gen_start_date) ) > $(distdir)/cl-t; \
cat $(top_srcdir)/build-aux/git-log-footer >> $(distdir)/cl-t;\
rm -f $(distdir)/ChangeLog; \
mv $(distdir)/cl-t $(distdir)/ChangeLog; \
fi
download: packages/packages.current
(cd packages; ./download.sh)
msi:
$(MAKE) $(AM_MAKEFLAGS) -C src msi
msi-signed:
$(MAKE) $(AM_MAKEFLAGS) -C src msi-signed
msi-upload:
$(MAKE) $(AM_MAKEFLAGS) -C src msi-upload
diff --git a/patches-appimage/gnupg-2.3.2/0001-agent-Fix-segv-in-GET_PASSPHRASE-regression.patch b/patches-appimage/gnupg-2.3.2/0001-agent-Fix-segv-in-GET_PASSPHRASE-regression.patch
new file mode 100644
index 00000000..8fdda43a
--- /dev/null
+++ b/patches-appimage/gnupg-2.3.2/0001-agent-Fix-segv-in-GET_PASSPHRASE-regression.patch
@@ -0,0 +1,34 @@
+#! /bin/sh
+patch -p1 -l -f $* < $0
+exit $?
+
+From af3b1901549baa8fbe8140d9fa75a4a2b7a77a7e Mon Sep 17 00:00:00 2001
+From: Werner Koch
+Date: Tue, 7 Sep 2021 08:57:44 +0200
+Subject: [PATCH GnuPG] agent: Fix segv in GET_PASSPHRASE (regression)
+
+* agent/command.c (cmd_get_passphrase): Do not deref PI. PI is always
+NULL.
+--
+
+Fixes-commit: b89b1f35c29ceaebe39b31444936aa66c9297f2c
+GnuPG-bug-id: 5577
+---
+ agent/command.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/agent/command.c b/agent/command.c
+index 5e2dbc809..3e074443a 100644
+--- a/agent/command.c
++++ b/agent/command.c
+@@ -1955,7 +1955,7 @@ cmd_get_passphrase (assuan_context_t ctx, char *line)
+ opt_qualbar, cacheid, CACHE_MODE_USER, NULL);
+ xfree (entry_errtext);
+ entry_errtext = NULL;
+- is_generated = !!(pi->status & PINENTRY_STATUS_PASSWORD_GENERATED);
++ is_generated = 0;
+
+ if (!rc)
+ {
+--
+2.33.0
diff --git a/patches-appimage/gnupg-2.3.2/0002-build-Fix-ksba.h-not-found-problem.patch b/patches-appimage/gnupg-2.3.2/0002-build-Fix-ksba.h-not-found-problem.patch
new file mode 100755
index 00000000..0d0f5c3e
--- /dev/null
+++ b/patches-appimage/gnupg-2.3.2/0002-build-Fix-ksba.h-not-found-problem.patch
@@ -0,0 +1,17 @@
+#! /bin/sh
+patch -p1 -l -f $* < $0
+exit $?
+
+diff --git a/sm/Makefile.in b/sm/Makefile.in
+index b2f042de8..c676adac9 100644
+--- a/sm/Makefile.in
++++ b/sm/Makefile.in
+@@ -557,7 +557,7 @@ t_common_ldadd = $(libcommon) $(LIBGCRYPT_LIBS) $(KSBA_LIBS) \
+ $(GPG_ERROR_LIBS) $(LIBINTL) $(LIBICONV)
+
+ t_minip12_CFLAGS = -DWITHOUT_NPTH=1 \
+- $(LIBGCRYPT_CFLAGS) $(GPG_ERROR_CFLAGS)
++ $(LIBGCRYPT_CFLAGS) $(KSBA_CFLAGS) $(GPG_ERROR_CFLAGS)
+
+ t_minip12_SOURCES = $(t_common_src) t-minip12.c minip12.c
+ t_minip12_LDADD = $(t_common_ldadd) $(NETLIBS)
diff --git a/patches-appimage/gnupg-2.3.2/0003-common-New-function-substitute_envvars.patch b/patches-appimage/gnupg-2.3.2/0003-common-New-function-substitute_envvars.patch
new file mode 100755
index 00000000..15651079
--- /dev/null
+++ b/patches-appimage/gnupg-2.3.2/0003-common-New-function-substitute_envvars.patch
@@ -0,0 +1,274 @@
+#! /bin/sh
+patch -p1 -l -f $* < $0
+exit $?
+
+From 9c272dc245456d5403e3bd50553b4fdccb370e27 Mon Sep 17 00:00:00 2001
+From: Werner Koch
+Date: Fri, 17 Sep 2021 17:33:21 +0200
+Subject: [PATCH GnuPG 1/2] common: New function substitute_envvars.
+
+* common/stringhelp.c (substitute_envvars): New. Based on code in
+gpg-connect-agent.
+* common/t-stringhelp.c: Include sysutils.h.
+(test_substitute_envvars): New.
+--
+
+GnuPG-bug-id: 5599
+---
+ common/stringhelp.c | 104 ++++++++++++++++++++++++++++++++++++++++++
+ common/stringhelp.h | 3 ++
+ common/t-stringhelp.c | 99 ++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 206 insertions(+)
+
+diff --git a/common/stringhelp.c b/common/stringhelp.c
+index 4dc179738..c9e10800d 100644
+--- a/common/stringhelp.c
++++ b/common/stringhelp.c
+@@ -1692,3 +1692,107 @@ format_text (const char *text_in, int target_cols, int max_cols)
+
+ return text;
+ }
++
++
++/* Substitute environment variables in STRING and return a new string.
++ * On error the function returns NULL. */
++char *
++substitute_envvars (const char *string)
++{
++ char *line, *p, *pend;
++ const char *value;
++ size_t valuelen, n;
++ char *result = NULL;
++
++ result = line = xtrystrdup (string);
++ if (!result)
++ return NULL; /* Ooops */
++
++ while (*line)
++ {
++ p = strchr (line, '$');
++ if (!p)
++ goto leave; /* No or no more variables. */
++
++ if (p[1] == '$') /* Escaped dollar sign. */
++ {
++ memmove (p, p+1, strlen (p+1)+1);
++ line = p + 1;
++ continue;
++ }
++
++ if (p[1] == '{')
++ {
++ int count = 0;
++
++ for (pend=p+2; *pend; pend++)
++ {
++ if (*pend == '{')
++ count++;
++ else if (*pend == '}')
++ {
++ if (--count < 0)
++ break;
++ }
++ }
++ if (!*pend)
++ goto leave; /* Unclosed - don't substitute. */
++ }
++ else
++ {
++ for (pend = p+1; *pend && (alnump (pend) || *pend == '_'); pend++)
++ ;
++ }
++
++ if (p[1] == '{' && *pend == '}')
++ {
++ int save = *pend;
++ *pend = 0;
++ value = getenv (p+2);
++ *pend++ = save;
++ }
++ else
++ {
++ int save = *pend;
++ *pend = 0;
++ value = getenv (p+1);
++ *pend = save;
++ }
++
++ if (!value)
++ value = "";
++ valuelen = strlen (value);
++ if (valuelen <= pend - p)
++ {
++ memcpy (p, value, valuelen);
++ p += valuelen;
++ n = pend - p;
++ if (n)
++ memmove (p, p+n, strlen (p+n)+1);
++ line = p;
++ }
++ else
++ {
++ char *src = result;
++ char *dst;
++
++ dst = xtrymalloc (strlen (src) + valuelen + 1);
++ if (!dst)
++ {
++ xfree (result);
++ return NULL;
++ }
++ n = p - src;
++ memcpy (dst, src, n);
++ memcpy (dst + n, value, valuelen);
++ n += valuelen;
++ strcpy (dst + n, pend);
++ line = dst + n;
++ xfree (result);
++ result = dst;
++ }
++ }
++
++ leave:
++ return result;
++}
+diff --git a/common/stringhelp.h b/common/stringhelp.h
+index 598f698c8..cd874af2e 100644
+--- a/common/stringhelp.h
++++ b/common/stringhelp.h
+@@ -166,6 +166,9 @@ int compare_version_strings (const char *my_version, const char *req_version);
+ /* Format a string so that it fits within about TARGET_COLS columns. */
+ char *format_text (const char *text, int target_cols, int max_cols);
+
++/* Substitute environmen variabales in STRING. */
++char *substitute_envvars (const char *string);
++
+
+ /*-- mapstrings.c --*/
+ const char *map_static_macro_string (const char *string);
+diff --git a/common/t-stringhelp.c b/common/t-stringhelp.c
+index 5eca5a092..8d0c1c576 100644
+--- a/common/t-stringhelp.c
++++ b/common/t-stringhelp.c
+@@ -43,6 +43,7 @@
+ #include
+
+ #include "t-support.h"
++#include "sysutils.h"
+ #include "stringhelp.h"
+
+
+@@ -1194,6 +1195,103 @@ test_compare_version_strings (void)
+ }
+
+
++static void
++test_substitute_envvars (void)
++{
++ struct {
++ const char *name;
++ const char *value;
++ } envvars[] = {
++ { "HOME", "/home/joe" },
++ { "AVAR", "avar" },
++ { "AVAR1", "avarx" },
++ { "AVAR2", "avarxy" },
++ { "AVAR3", "avarxyz" },
++ { "AVAR0", "ava" },
++ { "MY_VAR", "my_vars_value" },
++ { "STRANGE{X}VAR", "strange{x}vars-value" },
++ { "ZERO", "" }
++ };
++ struct {
++ const char *string;
++ const char *result;
++ } tests[] = {
++ { "foo bar",
++ "foo bar"
++ },
++ { "foo $HOME",
++ "foo /home/joe"
++ },
++ { "foo $HOME ",
++ "foo /home/joe "
++ },
++ { "foo $HOME$$",
++ "foo /home/joe$"
++ },
++ { "foo ${HOME}/.ssh",
++ "foo /home/joe/.ssh"
++ },
++ { "foo $HOME/.ssh",
++ "foo /home/joe/.ssh"
++ },
++ { "foo $HOME_/.ssh",
++ "foo /.ssh"
++ },
++ { "foo $HOME/.ssh/$MY_VAR:1",
++ "foo /home/joe/.ssh/my_vars_value:1"
++ },
++ { "foo $HOME${MY_VAR}:1",
++ "foo /home/joemy_vars_value:1"
++ },
++ { "${STRANGE{X}VAR}-bla",
++ "strange{x}vars-value-bla"
++ },
++ { "${STRANGE{X}{VAR}-bla", /* missing "}" */
++ "${STRANGE{X}{VAR}-bla"
++ },
++ { "zero->$ZERO<-",
++ "zero-><-"
++ },
++ { "->$AVAR.$AVAR1.$AVAR2.$AVAR3.$AVAR0<-",
++ "->avar.avarx.avarxy.avarxyz.ava<-"
++ },
++ { "",
++ ""
++ }
++ };
++ int idx;
++ char *res;
++
++ for (idx=0; idx < DIM(envvars); idx++)
++ if (gnupg_setenv (envvars[idx].name, envvars[idx].value, 1))
++ {
++ fprintf (stderr,"error setting envvar '%s' to '%s': %s\n",
++ envvars[idx].name, envvars[idx].value,
++ strerror (errno));
++ exit (2);
++ }
++
++ for (idx=0; idx < DIM(tests); idx++)
++ {
++ res = substitute_envvars (tests[idx].string);
++ if (!res)
++ {
++ fprintf (stderr,"error substituting '%s' (test %d): %s\n",
++ tests[idx].string, idx, strerror (errno));
++ exit (2);
++ }
++ if (strcmp (res, tests[idx].result))
++ {
++ fprintf (stderr, "substituted '%s'\n", tests[idx].string);
++ fprintf (stderr, " wanted '%s'\n", tests[idx].result);
++ fprintf (stderr, " got '%s'\n", res);
++ fail (idx);
++ }
++ xfree (res);
++ }
++}
++
++
+ int
+ main (int argc, char **argv)
+ {
+@@ -1213,6 +1311,7 @@ main (int argc, char **argv)
+ test_split_fields_colon ();
+ test_compare_version_strings ();
+ test_format_text ();
++ test_substitute_envvars ();
+
+ xfree (home_buffer);
+ return !!errcount;
+--
+2.33.0
diff --git a/patches-appimage/gnupg-2.3.2/0004-common-Support-a-gpgconf.ctl-file-under-Unix.patch b/patches-appimage/gnupg-2.3.2/0004-common-Support-a-gpgconf.ctl-file-under-Unix.patch
new file mode 100755
index 00000000..d696c716
--- /dev/null
+++ b/patches-appimage/gnupg-2.3.2/0004-common-Support-a-gpgconf.ctl-file-under-Unix.patch
@@ -0,0 +1,415 @@
+#! /bin/sh
+patch -p1 -l -f $* < $0
+exit $?
+
+From d4768bb982adb5c8410303334ee8d82ba0d71f3b Mon Sep 17 00:00:00 2001
+From: Werner Koch
+Date: Fri, 17 Sep 2021 17:39:07 +0200
+Subject: [PATCH GnuPG 2/2] common: Support a gpgconf.ctl file under Unix.
+
+* common/homedir.c (unix_rootdir): New.
+(gnupg_bindir): Use it.
+(gnupg_libexecdir): Use it.
+(gnupg_libdir): Use it.
+(gnupg_datadir): Use it.
+(gnupg_localedir): Use it.
+--
+
+This feature is useful for building and using an AppImage version of
+gnupg and probably also for some other use cases.
+
+GnuPG-bug-id: 5999
+
+Here is a sample gpgconf.ctl file
+--8<---------------cut here---------------start------------->8---
+# gpgconf.ctl
+#
+# This file is used to change the directories where the gpg components
+# are installed. It does not change the configuration directories.
+# The file is expected in the same directory as gpgconf. The physical
+# installation directories are evaluated and no symlinks. Blank lines
+# and lines starting with pound signed are ignored. No errors are
+# printed for unknown keywords or commands. The only defined key for
+# now is "rootdir" which must be followed by one optional space, an
+# equal sign, and the value for the root directory. Environment
+# variables are substituted in standard shell manner, the final value
+# must start with a slash, trailing slashed are stripped.
+
+rootdir = $APPDIR/gnupg
+--8<---------------cut here---------------end--------------->8---
+---
+ common/homedir.c | 269 ++++++++++++++++++++++++++++++++++++++++++++---
+ 1 file changed, 252 insertions(+), 17 deletions(-)
+
+diff --git a/common/homedir.c b/common/homedir.c
+index 7969a2c2e..b1c06bcf0 100644
+--- a/common/homedir.c
++++ b/common/homedir.c
+@@ -388,8 +388,10 @@ check_portable_app (const char *dir)
+ }
+ xfree (fname);
+ }
++#endif /*HAVE_W32_SYSTEM*/
+
+
++#ifdef HAVE_W32_SYSTEM
+ /* Determine the root directory of the gnupg installation on Windows. */
+ static const char *
+ w32_rootdir (void)
+@@ -441,7 +443,180 @@ w32_rootdir (void)
+ /* Fallback to the hardwired value. */
+ return GNUPG_LIBEXECDIR;
+ }
++#endif /*HAVE_W32_SYSTEM*/
++
+
++#ifndef HAVE_W32_SYSTEM /* Unix */
++/* Determine the root directory of the gnupg installation on Unix.
++ * The standard case is that this function returns NULL so that the
++ * root directory as configured at build time is used. However, it
++ * may return a static string with a different root directory, similar
++ * to what we do on Windows. That second mode is triggered by the
++ * existence of a file gpgconf.ctl installed side-by-side to gpgconf.
++ * This file is parsed for keywords describing the actually to be used
++ * root directory. There is no solid standard on Unix to locate the
++ * binary used to create the process, thus we support this currently
++ * only on Linux where we can look this info up using the proc file
++ * system. */
++static const char *
++unix_rootdir (void)
++{
++ static int checked;
++ static char *dir;
++
++ if (!checked)
++ {
++ char *p;
++ char *buffer;
++ size_t bufsize = 256-1;
++ int nread;
++ gpg_error_t err;
++ char *line;
++ size_t linelen;
++ ssize_t length;
++ estream_t fp;
++ char *rootdir;
++
++ for (;;)
++ {
++ buffer = xmalloc (bufsize+1);
++ nread = readlink ("/proc/self/exe", buffer, bufsize);
++ if (nread < 0)
++ {
++ err = gpg_error_from_syserror ();
++ log_info ("error reading symlink '/proc/self/exe': %s\n",
++ gpg_strerror (err));
++ buffer[0] = 0;
++ break;
++ }
++ else if (nread < bufsize)
++ {
++ buffer[nread] = 0;
++ break; /* Got it. */
++ }
++ else if (bufsize >= 4095)
++ {
++ buffer[0] = 0;
++ log_info ("error reading symlink '/proc/self/exe': %s\n",
++ "value too large");
++ break;
++ }
++ xfree (buffer);
++ bufsize += 256;
++ }
++ if (!*buffer)
++ {
++ xfree (buffer);
++ checked = 1;
++ return NULL; /* Error - assume no gpgconf.ctl. */
++ }
++
++ p = strrchr (buffer, '/');
++ if (!p)
++ {
++ xfree (buffer);
++ checked = 1;
++ return NULL; /* Erroneous /proc - assume no gpgconf.ctl. */
++ }
++ *p = 0; /* BUFFER has the directory. */
++ if ((p = strrchr (buffer, '/')))
++ {
++ /* Strip one part and expect the file below a bin dir. */
++ *p = 0;
++ p = xstrconcat (buffer, "/bin/gpgconf.ctl", NULL);
++ xfree (buffer);
++ buffer = p;
++ }
++ else /* !p */
++ {
++ /* Installed in the root which is not a good idea. Assume
++ * no gpgconf.ctl. */
++ xfree (buffer);
++ checked = 1;
++ return NULL;
++ }
++
++ if (gnupg_access (buffer, F_OK))
++ {
++ /* No gpgconf.ctl file. */
++ xfree (buffer);
++ checked = 1;
++ return NULL;
++ }
++ /* log_info ("detected '%s'\n", buffer); */
++ fp = es_fopen (buffer, "r");
++ if (!fp)
++ {
++ err = gpg_error_from_syserror ();
++ log_info ("error opening '%s': %s\n", buffer, gpg_strerror (err));
++ xfree (buffer);
++ checked = 1;
++ return NULL;
++ }
++
++ line = NULL;
++ linelen = 0;
++ rootdir = NULL;
++ while ((length = es_read_line (fp, &line, &linelen, NULL)) > 0)
++ {
++ /* Strip NL and CR, if present. */
++ while (length > 0
++ && (line[length - 1] == '\n' || line[length - 1] == '\r'))
++ line[--length] = 0;
++ trim_spaces (line);
++ if (!strncmp (line, "rootdir=", 8))
++ p = line + 8;
++ else if (!strncmp (line, "rootdir =", 9)) /* (What a kludge) */
++ p = line + 9;
++ else
++ continue;
++ trim_spaces (p);
++ rootdir = substitute_envvars (p);
++ if (!rootdir)
++ {
++ err = gpg_error_from_syserror ();
++ log_info ("error getting rootdir from gpgconf.ctl: %s\n",
++ gpg_strerror (err));
++ }
++ break;
++ }
++ if (length < 0 || es_ferror (fp))
++ {
++ err = gpg_error_from_syserror ();
++ log_info ("error reading '%s': %s\n", buffer, gpg_strerror (err));
++ es_fclose (fp);
++ xfree (buffer);
++ xfree (line);
++ checked = 1;
++ return NULL;
++ }
++ es_fclose (fp);
++ xfree (buffer);
++ xfree (line);
++
++ if (!rootdir || !*rootdir || *rootdir != '/')
++ {
++ log_info ("invalid rootdir '%s' specified in gpgconf.ctl\n", rootdir);
++ xfree (rootdir);
++ dir = NULL;
++ }
++ else
++ {
++ while (*rootdir && rootdir[strlen (rootdir)-1] == '/')
++ rootdir[strlen (rootdir)-1] = 0;
++ dir = rootdir;
++ gpgrt_annotate_leaked_object (dir);
++ /* log_info ("want rootdir '%s'\n", dir); */
++ }
++ checked = 1;
++ }
++
++ return dir;
++}
++#endif /* Unix */
++
++
++#ifdef HAVE_W32_SYSTEM
+ static const char *
+ w32_commondir (void)
+ {
+@@ -954,20 +1129,13 @@ gnupg_sysconfdir (void)
+ const char *
+ gnupg_bindir (void)
+ {
+-#if defined (HAVE_W32CE_SYSTEM)
+ static char *name;
+-
+- if (!name)
+- name = xstrconcat (w32_rootdir (), DIRSEP_S "bin", NULL);
+- return name;
+-#elif defined(HAVE_W32_SYSTEM)
+ const char *rdir;
+
++#if defined(HAVE_W32_SYSTEM)
+ rdir = w32_rootdir ();
+ if (w32_bin_is_bin)
+ {
+- static char *name;
+-
+ if (!name)
+ {
+ name = xstrconcat (rdir, DIRSEP_S "bin", NULL);
+@@ -978,7 +1146,18 @@ gnupg_bindir (void)
+ else
+ return rdir;
+ #else /*!HAVE_W32_SYSTEM*/
+- return GNUPG_BINDIR;
++ rdir = unix_rootdir ();
++ if (rdir)
++ {
++ if (!name)
++ {
++ name = xstrconcat (rdir, DIRSEP_S "bin", NULL);
++ gpgrt_annotate_leaked_object (name);
++ }
++ return name;
++ }
++ else
++ return GNUPG_BINDIR;
+ #endif /*!HAVE_W32_SYSTEM*/
+ }
+
+@@ -991,16 +1170,30 @@ gnupg_libexecdir (void)
+ #ifdef HAVE_W32_SYSTEM
+ return gnupg_bindir ();
+ #else /*!HAVE_W32_SYSTEM*/
+- return GNUPG_LIBEXECDIR;
++ static char *name;
++ const char *rdir;
++
++ rdir = unix_rootdir ();
++ if (rdir)
++ {
++ if (!name)
++ {
++ name = xstrconcat (rdir, DIRSEP_S "libexec", NULL);
++ gpgrt_annotate_leaked_object (name);
++ }
++ return name;
++ }
++ else
++ return GNUPG_LIBEXECDIR;
+ #endif /*!HAVE_W32_SYSTEM*/
+ }
+
+ const char *
+ gnupg_libdir (void)
+ {
+-#ifdef HAVE_W32_SYSTEM
+ static char *name;
+
++#ifdef HAVE_W32_SYSTEM
+ if (!name)
+ {
+ name = xstrconcat (w32_rootdir (), DIRSEP_S "lib" DIRSEP_S "gnupg", NULL);
+@@ -1008,16 +1201,29 @@ gnupg_libdir (void)
+ }
+ return name;
+ #else /*!HAVE_W32_SYSTEM*/
+- return GNUPG_LIBDIR;
++ const char *rdir;
++
++ rdir = unix_rootdir ();
++ if (rdir)
++ {
++ if (!name)
++ {
++ name = xstrconcat (rdir, DIRSEP_S "lib", DIRSEP_S, "gnupg", NULL);
++ gpgrt_annotate_leaked_object (name);
++ }
++ return name;
++ }
++ else
++ return GNUPG_LIBDIR;
+ #endif /*!HAVE_W32_SYSTEM*/
+ }
+
+ const char *
+ gnupg_datadir (void)
+ {
+-#ifdef HAVE_W32_SYSTEM
+ static char *name;
+
++#ifdef HAVE_W32_SYSTEM
+ if (!name)
+ {
+ name = xstrconcat (w32_rootdir (), DIRSEP_S "share" DIRSEP_S "gnupg",
+@@ -1026,7 +1232,20 @@ gnupg_datadir (void)
+ }
+ return name;
+ #else /*!HAVE_W32_SYSTEM*/
+- return GNUPG_DATADIR;
++ const char *rdir;
++
++ rdir = unix_rootdir ();
++ if (rdir)
++ {
++ if (!name)
++ {
++ name = xstrconcat (rdir, DIRSEP_S "share" DIRSEP_S "gnupg", NULL);
++ gpgrt_annotate_leaked_object (name);
++ }
++ return name;
++ }
++ else
++ return GNUPG_DATADIR;
+ #endif /*!HAVE_W32_SYSTEM*/
+ }
+
+@@ -1034,9 +1253,9 @@ gnupg_datadir (void)
+ const char *
+ gnupg_localedir (void)
+ {
+-#ifdef HAVE_W32_SYSTEM
+ static char *name;
+
++#ifdef HAVE_W32_SYSTEM
+ if (!name)
+ {
+ name = xstrconcat (w32_rootdir (), DIRSEP_S "share" DIRSEP_S "locale",
+@@ -1045,7 +1264,20 @@ gnupg_localedir (void)
+ }
+ return name;
+ #else /*!HAVE_W32_SYSTEM*/
+- return LOCALEDIR;
++ const char *rdir;
++
++ rdir = unix_rootdir ();
++ if (rdir)
++ {
++ if (!name)
++ {
++ name = xstrconcat (rdir, DIRSEP_S "share" DIRSEP_S "locale", NULL);
++ gpgrt_annotate_leaked_object (name);
++ }
++ return name;
++ }
++ else
++ return LOCALEDIR;
+ #endif /*!HAVE_W32_SYSTEM*/
+ }
+
+@@ -1171,7 +1403,10 @@ static int gnupg_module_name_called;
+ * be called before any invocation of 'gnupg_module_name', and must
+ * not be called twice. It can be used by test suites to make sure
+ * the components from the build directory are used instead of
+- * potentially outdated installed ones. */
++ * potentially outdated installed ones.
++ * Fixme: It might be better to make use of the newer gpgconf.ctl feature
++ * for regression testing.
++ */
+ void
+ gnupg_set_builddir (const char *newdir)
+ {
+--
+2.33.0
diff --git a/patches-appimage/gnupg-2.3.2/0005-build-Fix-several-include-file-not-found-problems.patch b/patches-appimage/gnupg-2.3.2/0005-build-Fix-several-include-file-not-found-problems.patch
new file mode 100755
index 00000000..cac1650c
--- /dev/null
+++ b/patches-appimage/gnupg-2.3.2/0005-build-Fix-several-include-file-not-found-problems.patch
@@ -0,0 +1,73 @@
+#! /bin/sh
+patch -p1 -l -f $* < $0
+exit $?
+
+diff --git a/dirmngr/Makefile.in b/dirmngr/Makefile.in
+index f56e59a3e..d154e5228 100644
+--- a/dirmngr/Makefile.in
++++ b/dirmngr/Makefile.in
+@@ -790,7 +790,7 @@ t_ldap_parse_uri_SOURCES = \
+
+ t_ldap_parse_uri_CFLAGS = -DWITHOUT_NPTH=1 $(USE_C99_CFLAGS) \
+ $(LIBGCRYPT_CFLAGS) \
+- $(LIBASSUAN_CFLAGS) $(GPG_ERROR_CFLAGS)
++ $(LIBASSUAN_CFLAGS) $(GPG_ERROR_CFLAGS) $(KSBA_CFLAGS)
+
+ t_ldap_parse_uri_LDADD = $(ldaplibs) $(t_common_ldadd) $(DNSLIBS)
+ t_ldap_misc_SOURCES = t-ldap-misc.c ldap-misc.c ldap-misc.h $(ldap_url)
+diff --git a/kbx/Makefile.in b/kbx/Makefile.in
+index dd727e1e0..f5fe341bc 100644
+--- a/kbx/Makefile.in
++++ b/kbx/Makefile.in
+@@ -577,8 +577,8 @@ client_sources = \
+
+ libkeybox_a_SOURCES = $(common_sources) $(client_sources)
+ libkeybox509_a_SOURCES = $(common_sources) $(client_sources)
+-libkeybox_a_CFLAGS = $(AM_CFLAGS) $(LIBASSUAN_CFLAGS)
+-libkeybox509_a_CFLAGS = $(AM_CFLAGS) $(LIBASSUAN_CFLAGS) -DKEYBOX_WITH_X509=1
++libkeybox_a_CFLAGS = $(AM_CFLAGS) $(LIBASSUAN_CFLAGS) $(NPTH_CFLAGS)
++libkeybox509_a_CFLAGS = $(AM_CFLAGS) $(LIBASSUAN_CFLAGS) $(NPTH_CFLAGS) -DKEYBOX_WITH_X509=1
+
+ # We need W32SOCKLIBS because the init subsystem code in libcommon
+ # requires it - although we don't actually need it. It is easier
+diff --git a/tools/Makefile.in b/tools/Makefile.in
+index 4c29f84ed..9e9e13eda 100644
+--- a/tools/Makefile.in
++++ b/tools/Makefile.in
+@@ -744,7 +744,7 @@ gpgtar_SOURCES = \
+ gpgtar-extract.c \
+ gpgtar-list.c
+
+-gpgtar_CFLAGS = $(GPG_ERROR_CFLAGS)
++gpgtar_CFLAGS = $(LIBGCRYPT_CFLAGS) $(GPG_ERROR_CFLAGS)
+ gpgtar_LDADD = $(libcommon) $(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS) \
+ $(LIBINTL) $(NETLIBS) $(LIBICONV) $(W32SOCKLIBS) \
+ $(gpgtar_rc_objs)
+@@ -759,7 +759,7 @@ gpg_wks_server_SOURCES = \
+ mime-maker.c mime-maker.h \
+ send-mail.c send-mail.h
+
+-gpg_wks_server_CFLAGS = $(GPG_ERROR_CFLAGS) $(INCICONV)
++gpg_wks_server_CFLAGS = $(LIBGCRYPT_CFLAGS) $(GPG_ERROR_CFLAGS) $(INCICONV)
+ gpg_wks_server_LDADD = $(libcommon) $(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS) \
+ $(LIBINTL) $(LIBICONV)
+
+@@ -774,7 +774,8 @@ gpg_wks_client_SOURCES = \
+ send-mail.c send-mail.h \
+ call-dirmngr.c call-dirmngr.h
+
+-gpg_wks_client_CFLAGS = $(LIBASSUAN_CFLAGS) $(GPG_ERROR_CFLAGS) $(INCICONV)
++gpg_wks_client_CFLAGS = $(LIBASSUAN_CFLAGS) $(LIBGCRYPT_CFLAGS) \
++ $(GPG_ERROR_CFLAGS) $(INCICONV)
+ gpg_wks_client_LDADD = $(libcommon) \
+ $(LIBASSUAN_LIBS) $(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS) \
+ $(LIBINTL) $(LIBICONV) $(NETLIBS) \
+@@ -783,7 +784,7 @@ gpg_wks_client_LDADD = $(libcommon) \
+ gpg_pair_tool_SOURCES = \
+ gpg-pair-tool.c
+
+-gpg_pair_tool_CFLAGS = $(GPG_ERROR_CFLAGS) $(INCICONV)
++gpg_pair_tool_CFLAGS = $(LIBGCRYPT_CFLAGS) $(GPG_ERROR_CFLAGS) $(INCICONV)
+ gpg_pair_tool_LDADD = $(libcommon) \
+ $(LIBGCRYPT_LIBS) $(GPG_ERROR_LIBS) \
+ $(LIBINTL) $(LIBICONV) $(W32SOCKLIBS)
diff --git a/patches-appimage/kconfigwidgets/0001-build-without-KF5Auth.patch b/patches-appimage/kconfigwidgets/0001-build-without-KF5Auth.patch
new file mode 100755
index 00000000..6e07cce2
--- /dev/null
+++ b/patches-appimage/kconfigwidgets/0001-build-without-KF5Auth.patch
@@ -0,0 +1,17 @@
+#! /bin/sh
+patch -p1 -l -f $* < $0
+exit $?
+
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index bed53d1..87f976c 100644
+--- CMakeLists.txt.orig 2018-02-28 08:33:32.052419561 +0100
++++ CMakeLists.txt 2018-02-28 08:35:44.523986191 +0100
+@@ -39,7 +39,7 @@
+ PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KF5ConfigWidgetsConfigVersion.cmake"
+ SOVERSION 5)
+
+-if (NOT ANDROID)
++if (FALSE)
+ find_package(KF5Auth ${KF5_DEP_VERSION} REQUIRED)
+ endif()
+ find_package(KF5CoreAddons ${KF5_DEP_VERSION} REQUIRED)
diff --git a/patches-appimage/libkleo-21.08.1/0001-Add-support-for-non-standard-boost-include-directori.patch b/patches-appimage/libkleo-21.08.1/0001-Add-support-for-non-standard-boost-include-directori.patch
new file mode 100755
index 00000000..607b16aa
--- /dev/null
+++ b/patches-appimage/libkleo-21.08.1/0001-Add-support-for-non-standard-boost-include-directori.patch
@@ -0,0 +1,31 @@
+#! /bin/sh
+patch -p1 -l -f $* < $0
+exit $?
+
+From 991d6b9f1868080a9ed93ed55cf6dc794ee6a9d1 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ingo=20Kl=C3=B6cker?=
+Date: Thu, 23 Sep 2021 12:08:06 +0200
+Subject: [PATCH] Add support for non-standard boost include directories
+
+GnuPG-bug-id: 5592
+---
+ src/CMakeLists.txt | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
+index 48e6cfa..ba85f6c 100644
+--- a/src/CMakeLists.txt
++++ b/src/CMakeLists.txt
+@@ -1,6 +1,9 @@
+
+ # target_include_directories does not handle empty include paths
+-include_directories(${GPGME_INCLUDES})
++include_directories(
++ ${Boost_INCLUDE_DIRS}
++ ${GPGME_INCLUDES}
++)
+
+ add_definitions(-DTRANSLATION_DOMAIN=\"libkleopatra\")
+
+--
+2.33.0
diff --git a/patches-appimage/libkleo-21.08.1/z-01-use-pre-5.80-ecm_qt_declare_logging_category.patch b/patches-appimage/libkleo-21.08.1/z-01-use-pre-5.80-ecm_qt_declare_logging_category.patch
new file mode 100755
index 00000000..f5a0e98b
--- /dev/null
+++ b/patches-appimage/libkleo-21.08.1/z-01-use-pre-5.80-ecm_qt_declare_logging_category.patch
@@ -0,0 +1,41 @@
+#! /bin/sh
+patch -p1 -l -f $* < $0
+exit $?
+
+diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
+index 806b1bb..496843d 100644
+--- a/src/CMakeLists.txt
++++ b/src/CMakeLists.txt
+@@ -51,11 +51,13 @@ target_sources(KF5Libkleo PRIVATE
+ utils/cryptoconfig.cpp
+ utils/test.cpp
+ )
+-ecm_qt_declare_logging_category(KF5Libkleo HEADER libkleo_debug.h IDENTIFIER LIBKLEO_LOG CATEGORY_NAME org.kde.pim.libkleo
++ecm_qt_declare_logging_category(libkleo_core_SRCS HEADER libkleo_debug.h IDENTIFIER LIBKLEO_LOG CATEGORY_NAME org.kde.pim.libkleo
+ DESCRIPTION "libkleo (kleo_core)"
+ EXPORT LIBKLEO
+ )
+-
++target_sources(KF5Libkleo PRIVATE
++ ${libkleo_core_SRCS}
++)
+
+ target_sources(KF5Libkleo PRIVATE
+ ui/dnattributeorderconfigwidget.cpp
+@@ -70,12 +72,14 @@ target_sources(KF5Libkleo PRIVATE
+ ui/editdirectoryservicedialog.cpp
+ )
+
+-ecm_qt_declare_logging_category(KF5Libkleo HEADER kleo_ui_debug.h IDENTIFIER KLEO_UI_LOG CATEGORY_NAME org.kde.pim.kleo_ui
++ecm_qt_declare_logging_category(libkleo_ui_SRCS HEADER kleo_ui_debug.h IDENTIFIER KLEO_UI_LOG CATEGORY_NAME org.kde.pim.kleo_ui
+ DESCRIPTION "libkleo (kleo_ui)"
+ OLD_CATEGORY_NAMES log_kleo_ui
+ EXPORT LIBKLEO
+ )
+-
++target_sources(KF5Libkleo PRIVATE
++ ${libkleo_ui_SRCS}
++)
+
+ target_sources(KF5Libkleo PRIVATE # make this a separate lib.
+ ui/keylistview.cpp
diff --git a/patches-appimage/qtwayland-5.15.0/00-disable-wayland-server.patch b/patches-appimage/qtwayland-5.15.0/00-disable-wayland-server.patch
new file mode 100755
index 00000000..f89f6bf6
--- /dev/null
+++ b/patches-appimage/qtwayland-5.15.0/00-disable-wayland-server.patch
@@ -0,0 +1,49 @@
+#! /bin/sh
+patch -p1 -l -f $* < $0
+exit $?
+
+--- a/configure.json
++++ b/configure.json
+@@ -1,6 +1,5 @@
+ {
+ "subconfigs": [
+- "src/client",
+- "src/compositor"
++ "src/client"
+ ]
+ }
+--- a/src/src.pro
++++ b/src/src.pro
+@@ -1,9 +1,8 @@
+ TEMPLATE=subdirs
+ include($$OUT_PWD/client/qtwaylandclient-config.pri)
+-include($$OUT_PWD/compositor/qtwaylandcompositor-config.pri)
+-QT_FOR_CONFIG += waylandclient-private waylandcompositor-private
++QT_FOR_CONFIG += waylandclient-private
+
+-qtConfig(wayland-client)|qtConfig(wayland-server) {
++qtConfig(wayland-client) {
+ sub_qtwaylandscanner.subdir = qtwaylandscanner
+ sub_qtwaylandscanner.target = sub-qtwaylandscanner
+ SUBDIRS += sub_qtwaylandscanner
+@@ -18,20 +17,11 @@
+ sub_plugins.subdir = plugins
+ sub_plugins.depends += sub-qtwaylandscanner
+ qtConfig(wayland-client):sub_plugins.depends += sub-client
+- qtConfig(wayland-server):sub_plugins.depends += sub-compositor
+ sub_plugins.target = sub-plugins
+ SUBDIRS += sub_plugins
+
+- qtConfig(wayland-server) {
+- sub_compositor.subdir = compositor
+- sub_compositor.depends = sub-qtwaylandscanner
+- sub_compositor.target = sub-compositor
+- SUBDIRS += sub_compositor
+- }
+-
+ sub_imports.subdir = imports
+ qtConfig(wayland-client):sub_imports.depends += sub-client
+- qtConfig(wayland-server):sub_imports.depends += sub-compositor
+ sub_imports.target = sub-imports
+ SUBDIRS += sub_imports
+ }