Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package qgpgme for openSUSE:Factory checked 
in at 2026-08-02 23:13:48
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/qgpgme (Old)
 and      /work/SRC/openSUSE:Factory/.qgpgme.new.16738 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "qgpgme"

Sun Aug  2 23:13:48 2026 rev:4 rq:1369101 version:2.2.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/qgpgme/qgpgme.changes    2026-06-01 
17:58:54.253628121 +0200
+++ /work/SRC/openSUSE:Factory/.qgpgme.new.16738/qgpgme.changes 2026-08-02 
23:14:24.888255300 +0200
@@ -1,0 +2,7 @@
+Fri Jul 31 08:59:02 UTC 2026 - Andreas Stieger <[email protected]>
+
+- Update to 2.2.0:
+  * Add job for querying Active Directory
+  * Don't start dirmngr for WKD lookup if it is disabled for gpg
+
+-------------------------------------------------------------------

Old:
----
  qgpgme-2.1.0.tar.xz
  qgpgme-2.1.0.tar.xz.sig

New:
----
  qgpgme-2.2.0.tar.xz
  qgpgme-2.2.0.tar.xz.sig

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ qgpgme.spec ++++++
--- /var/tmp/diff_new_pack.LdYxrE/_old  2026-08-02 23:14:25.508276582 +0200
+++ /var/tmp/diff_new_pack.LdYxrE/_new  2026-08-02 23:14:25.512276720 +0200
@@ -17,13 +17,14 @@
 
 
 %define sover 15
-%if 0%{?suse_version} >= 1600
+%bcond_without qt5
+%if 0%{?suse_version} > 1600
 %bcond_without qt6
 %else
 %bcond_with qt6
 %endif
 Name:           qgpgme
-Version:        2.1.0
+Version:        2.2.0
 Release:        0
 Summary:        Qt API bindings/wrapper for GPGME
 License:        GPL-2.0-or-later
@@ -36,13 +37,15 @@
 BuildRequires:  c++_compiler
 BuildRequires:  cmake
 BuildRequires:  pkgconfig
-BuildRequires:  cmake(Gpgmepp) >= 2.0.0
-BuildRequires:  cmake(Qt5Core) >= 5.15.0
+BuildRequires:  cmake(Gpgmepp) >= 2.1.0
 BuildRequires:  pkgconfig(gpg-error) >= 1.47
-BuildRequires:  pkgconfig(gpgme) >= 2.0.0
+BuildRequires:  pkgconfig(gpgme) >= 2.1.0
+%if %{with qt5}
+BuildRequires:  cmake(Qt5Core) >= 5.15.0
+%endif
 %if %{with qt6}
 BuildRequires:  cmake(Qt6Core) >= 6.5.0
-BuildRequires:  cmake(Qt6CoreTools) >= 6.9.1
+BuildRequires:  cmake(Qt6CoreTools) >= 6.11.1
 BuildRequires:  cmake(Qt6Test)
 %endif
 %if 0%{?suse_version} < 1600
@@ -52,6 +55,7 @@
 %description
 QGpgme provides a very high level Qt API around GpgMEpp.
 
+%if %{with qt5}
 %package -n libqgpgme%{sover}
 Summary:        Qt5 API bindings/wrapper for GPGME
 
@@ -59,6 +63,7 @@
 QGpgme provides a very high level Qt API around GpgMEpp.
 
 This package contains the shared library built for Qt5.
+%endif
 
 %if %{with qt6}
 %package -n libqgpgmeqt6-%{sover}
@@ -70,21 +75,23 @@
 This package contains the shared library built for Qt6.
 %endif
 
+%if %{with qt5}
 %package -n libqgpgme-devel
 Summary:        Development files for %{name} (Qt5)
 Requires:       libqgpgme%{sover} = %{version}
-Requires:       cmake(Gpgmepp) >= 2.0.0
+Requires:       cmake(Gpgmepp) >= 2.1.0
 
 %description -n libqgpgme-devel
 QGpgme provides a very high level Qt API around GpgMEpp.
 
 This package contains the files needed to build using %{name} and Qt5.
+%endif
 
 %if %{with qt6}
 %package -n libqgpgmeqt6-devel
 Summary:        Development files for %{name} (Qt6)
 Requires:       libqgpgmeqt6-%{sover} = %{version}
-Requires:       cmake(Gpgmepp) >= 2.0.0
+Requires:       cmake(Gpgmepp) >= 2.1.0
 
 %description -n libqgpgmeqt6-devel
 QGpgme provides a very high level Qt API around GpgMEpp.
@@ -100,9 +107,15 @@
 export CXX=g++-12
 %endif
 %cmake \
+%if %{with qt5}
        -DBUILD_WITH_QT5:BOOL=ON \
+%else
+       -DBUILD_WITH_QT5:BOOL=OFF \
+%endif
 %if %{with qt6}
        -DBUILD_WITH_QT6:BOOL=ON \
+%else
+       -DBUILD_WITH_QT6:BOOL=OFF \
 %endif
        -DBUILD_TESTING:BOOL=ON \
        %{nil}
@@ -114,14 +127,18 @@
 %check
 %ctest
 
+%if %{with qt5}
 %ldconfig_scriptlets -n libqgpgme%{sover}
+%endif
 %if %{with qt6}
 %ldconfig_scriptlets -n libqgpgmeqt6-%{sover}
 %endif
 
+%if %{with qt5}
 %files -n libqgpgme%{sover}
 %license COPYING
 %{_libdir}/libqgpgme.so.%{sover}{,.*}
+%endif
 
 %if %{with qt6}
 %files -n libqgpgmeqt6-%{sover}
@@ -129,12 +146,14 @@
 %{_libdir}/libqgpgmeqt6.so.%{sover}{,.*}
 %endif
 
+%if %{with qt5}
 %files -n libqgpgme-devel
 %license COPYING
 %doc ChangeLog NEWS README VERSION
 %{_libdir}/libqgpgme.so
 %{_includedir}/qgpgme-qt5
 %{_libdir}/cmake/QGpgme
+%endif
 
 %if %{with qt6}
 %files -n libqgpgmeqt6-devel

++++++ qgpgme-2.1.0.tar.xz -> qgpgme-2.2.0.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qgpgme-2.1.0/CMakeLists.txt 
new/qgpgme-2.2.0/CMakeLists.txt
--- old/qgpgme-2.1.0/CMakeLists.txt     2026-05-18 14:24:04.000000000 +0200
+++ new/qgpgme-2.2.0/CMakeLists.txt     2026-07-20 15:07:38.000000000 +0200
@@ -21,7 +21,7 @@
 
 cmake_minimum_required(VERSION 3.16 FATAL_ERROR)
 
-set(FULL_VERSION "2.1.0")
+set(FULL_VERSION "2.2.0")
 
 string(REGEX MATCH "^[0-9]+.[0-9]+.[0-9]+" cmake_compat_version 
${FULL_VERSION})
 project(qgpgme VERSION ${cmake_compat_version})
@@ -35,14 +35,14 @@
 #   (Interfaces added/removed/changed: CURRENT++, REVISION=0)
 #   (Interfaces added:                 AGE++)
 #   (Interfaces removed:               AGE=0)
-set(LIBQGPGME_LT_CURRENT "23")
-set(LIBQGPGME_LT_AGE "8")
+set(LIBQGPGME_LT_CURRENT "24")
+set(LIBQGPGME_LT_AGE "9")
 set(LIBQGPGME_LT_REVISION "0")
 math(EXPR LIBQGPGME_SOVERSION "${LIBQGPGME_LT_CURRENT} - ${LIBQGPGME_LT_AGE}")
 
 set(GPG_ERROR_REQUIRED_VERSION "1.47")
-set(GPGME_REQUIRED_VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.0")
-set(GPGMEPP_REQUIRED_VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.0")
+set(GPGME_REQUIRED_VERSION "2.1.0")
+set(GPGMEPP_REQUIRED_VERSION "2.1.0")
 set(QT5_REQUIRED_VERSION "5.15.0")
 set(QT6_REQUIRED_VERSION "6.5.0")
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qgpgme-2.1.0/ChangeLog new/qgpgme-2.2.0/ChangeLog
--- old/qgpgme-2.1.0/ChangeLog  2026-05-18 14:24:04.000000000 +0200
+++ new/qgpgme-2.2.0/ChangeLog  2026-07-20 15:07:38.000000000 +0200
@@ -1,3 +1,45 @@
+2026-07-20  Ingo Klöcker  <[email protected]>
+
+       Release 2.2.0.
+       + commit 447c4a7665c9b3467b489d8b3e73513fb1eff4a4
+
+
+2026-06-24  Ingo Klöcker  <[email protected]>
+
+       Don't start dirmngr for WKD lookup if it is disabled for gpg.
+       + commit d764c5c57973fb452726024d1ef8634e1856e5a0
+       * src/qgpgmewkdlookupjob.cpp (startDirmngr): Check disable-dirmngr
+       option of gpg.
+
+       Don't start dirmngr for AD query if it is disabled for gpg and gpgsm.
+       + commit 82ad47a35d0f4e47a7a9f958a519b0230d21524e
+       * src/qgpgmeadqueryjob.cpp (startDirmngr): Check disable-dirmngr
+       option of gpg and gpgsm.
+
+2026-06-17  Ingo Klöcker  <[email protected]>
+
+       Add job for querying Active Directory.
+       + commit 905e3851170d362261f1f6b6c04767aa23332baa
+       * src/CMakeLists.txt: Add new files.
+       * src/adqueryjob.cpp, src/adqueryjob.h, src/adqueryjob_p.h,
+       src/adqueryresult.cpp, src/adqueryresult.h, src/qgpgmeadqueryjob.cpp,
+       src/qgpgmeadqueryjob.h: New.
+       * src/protocol.h (class Protocol): Add pure virtual member function
+       adQueryJob
+       * src/protocol_p.h (Protocol::adQueryJob): ... and implement it.
+       * src/qt6compat_p.h (operator<<): Add QDebug stream operator for
+       std::string for Qt 5 and older Qt 6.
+
+       * tests/CMakeLists.txt: Add new test runner run-adqueryjob.
+       * tests/run-adqueryjob.cpp: New.
+
+       Add helper for splitting a std::string_view.
+       + commit 47af4f6a344ea8ee1fb69ef447979894b58fb0f6
+       * src/util.h (_qgpgme::split): New.
+
+       * tests/CMakeLists.txt: Add new test.
+       * tests/t-util.cpp: New.
+
 2026-05-18  Werner Koch  <[email protected]>
 
        Release 2.1.0.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qgpgme-2.1.0/NEWS new/qgpgme-2.2.0/NEWS
--- old/qgpgme-2.1.0/NEWS       2026-05-18 14:24:04.000000000 +0200
+++ new/qgpgme-2.2.0/NEWS       2026-07-20 15:07:38.000000000 +0200
@@ -1,3 +1,21 @@
+Noteworthy changes in version 2.2.0 (2026-07-20)  [C24/A9/R0]
+------------------------------------------------
+
+ * Add job for querying Active Directory. [T6094]
+
+ * Don't start dirmngr for WKD lookup if it is disabled for gpg. [T8304]
+
+ * Interface changes relative to the 2.1.0 release:
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ADQueryJob                    NEW.
+ ADQueryOption                 NEW.
+ ADQueryOptions                NEW.
+ ADQueryResult                 NEW.
+ Protocol::adQueryJob          NEW.
+
+ Release-info: https://dev.gnupg.org/T8360
+
+
 Noteworthy changes in version 2.1.0 (2026-05-18)  [C23/A8/R0]
 ------------------------------------------------
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qgpgme-2.1.0/VERSION new/qgpgme-2.2.0/VERSION
--- old/qgpgme-2.1.0/VERSION    2026-05-18 14:24:04.000000000 +0200
+++ new/qgpgme-2.2.0/VERSION    2026-07-20 15:07:38.000000000 +0200
@@ -1,2 +1,2 @@
-2.1.0
-02184c928f555efc6b18b6ec08379e15ddd68894
+2.2.0
+447c4a7665c9b3467b489d8b3e73513fb1eff4a4
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qgpgme-2.1.0/src/CMakeLists.txt 
new/qgpgme-2.2.0/src/CMakeLists.txt
--- old/qgpgme-2.1.0/src/CMakeLists.txt 2026-05-18 14:24:04.000000000 +0200
+++ new/qgpgme-2.2.0/src/CMakeLists.txt 2026-07-20 15:07:38.000000000 +0200
@@ -36,6 +36,8 @@
     abstractimportjob.cpp
     addexistingsubkeyjob.cpp
     adduseridjob.cpp
+    adqueryjob.cpp
+    adqueryresult.cpp
     changeexpiryjob.cpp
     changeownertrustjob.cpp
     changepasswdjob.cpp
@@ -66,6 +68,7 @@
     qgpgme_debug.cpp
     qgpgmeaddexistingsubkeyjob.cpp
     qgpgmeadduseridjob.cpp
+    qgpgmeadqueryjob.cpp
     qgpgmebackend.cpp
     qgpgmechangeexpiryjob.cpp
     qgpgmechangeownertrustjob.cpp
@@ -140,6 +143,7 @@
     protocol_p.h
     qgpgmeaddexistingsubkeyjob.h
     qgpgmeadduseridjob.h
+    qgpgmeadqueryjob.h
     qgpgmebackend.h
     qgpgmechangeexpiryjob.h
     qgpgmechangeownertrustjob.h
@@ -197,6 +201,8 @@
     AbstractImportJob
     AddExistingSubkeyJob
     AddUserIDJob
+    ADQueryJob
+    ADQueryResult
     ChangeExpiryJob
     ChangeOwnerTrustJob
     ChangePasswdJob
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qgpgme-2.1.0/src/adqueryjob.cpp 
new/qgpgme-2.2.0/src/adqueryjob.cpp
--- old/qgpgme-2.1.0/src/adqueryjob.cpp 1970-01-01 01:00:00.000000000 +0100
+++ new/qgpgme-2.2.0/src/adqueryjob.cpp 2026-07-20 15:07:38.000000000 +0200
@@ -0,0 +1,70 @@
+/*
+    adqueryjob.cpp
+
+    This file is part of qgpgme, the Qt API binding for gpgme
+    Copyright (c) 2026 g10 Code GmbH
+    Software engineering by Ingo Klöcker <[email protected]>
+
+    QGpgME 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.
+
+    QGpgME 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, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  
USA
+
+    In addition, as a special exception, the copyright holders give
+    permission to link the code of this program with any edition of
+    the Qt library by Trolltech AS, Norway (or with modified versions
+    of Qt that use the same license as Qt), and distribute linked
+    combinations including the two.  You must obey the GNU General
+    Public License in all respects for all of the code used other than
+    Qt.  If you modify this file, you may extend this exception to
+    your version of the file, but you are not obligated to do so.  If
+    you do not wish to do so, delete this exception statement from
+    your version.
+*/
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include "adqueryjob.h"
+
+#include "adqueryjob_p.h"
+#include "adqueryresult.h"
+
+using namespace QGpgME;
+
+ADQueryJob::ADQueryJob(std::unique_ptr<ADQueryJobPrivate> dd, QObject *parent)
+    : Job{std::move(dd), parent}
+{
+}
+
+ADQueryJob::~ADQueryJob() = default;
+
+GpgME::Error ADQueryJob::start(const QString &filter, const QStringList 
&attributes, ADQueryOptions options)
+{
+    Q_D(ADQueryJob);
+    d->m_filter = filter;
+    d->m_attributes = attributes;
+    d->m_options = options;
+    return d->startIt();
+}
+
+ADQueryResult ADQueryJob::exec(const QString &filter, const QStringList 
&attributes, ADQueryOptions options)
+{
+    Q_D(ADQueryJob);
+    d->m_filter = filter;
+    d->m_attributes = attributes;
+    d->m_options = options;
+    return d->execIt();
+}
+
+#include "moc_adqueryjob.cpp"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qgpgme-2.1.0/src/adqueryjob.h 
new/qgpgme-2.2.0/src/adqueryjob.h
--- old/qgpgme-2.1.0/src/adqueryjob.h   1970-01-01 01:00:00.000000000 +0100
+++ new/qgpgme-2.2.0/src/adqueryjob.h   2026-07-20 15:07:38.000000000 +0200
@@ -0,0 +1,90 @@
+/*
+    adqueryjob.h
+
+    This file is part of qgpgme, the Qt API binding for gpgme
+    Copyright (c) 2026 g10 Code GmbH
+    Software engineering by Ingo Klöcker <[email protected]>
+
+    QGpgME 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.
+
+    QGpgME 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, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  
USA
+
+    In addition, as a special exception, the copyright holders give
+    permission to link the code of this program with any edition of
+    the Qt library by Trolltech AS, Norway (or with modified versions
+    of Qt that use the same license as Qt), and distribute linked
+    combinations including the two.  You must obey the GNU General
+    Public License in all respects for all of the code used other than
+    Qt.  If you modify this file, you may extend this exception to
+    your version of the file, but you are not obligated to do so.  If
+    you do not wish to do so, delete this exception statement from
+    your version.
+*/
+
+#ifndef __QGPGME_ADQUERYJOB_H__
+#define __QGPGME_ADQUERYJOB_H__
+
+#include "job.h"
+
+#include "qgpgme_export.h"
+
+class QString;
+
+namespace GpgME
+{
+class Error;
+}
+
+namespace QGpgME
+{
+
+enum class ADQueryOption {
+    Default = 0x00,
+    RootDSE = 0x01,
+    SubstituteVariables = 0x02,
+};
+Q_DECLARE_FLAGS(ADQueryOptions, ADQueryOption);
+
+class ADQueryResult;
+
+class ADQueryJobPrivate;
+
+class QGPGME_EXPORT ADQueryJob : public Job
+{
+    Q_OBJECT
+protected:
+    ADQueryJob(std::unique_ptr<ADQueryJobPrivate>, QObject *parent);
+
+public:
+    ~ADQueryJob() override;
+
+    /**
+     * Starts an AD query with filter \a filter asking for the attributes \a 
attributes.
+     */
+    GpgME::Error start(const QString &filter, const QStringList &attributes, 
ADQueryOptions options = ADQueryOption::Default);
+
+    /**
+     * Runs an AD query with filter \a filter asking for the attributes \a 
attributes.
+     */
+    ADQueryResult exec(const QString &filter, const QStringList &attributes, 
ADQueryOptions options = ADQueryOption::Default);
+
+Q_SIGNALS:
+    void result(const ADQueryResult &result, const QString &auditLogAsHtml = 
{}, const GpgME::Error &auditLogError = {});
+
+private:
+    Q_DECLARE_PRIVATE(ADQueryJob)
+};
+
+}
+
+#endif // __QGPGME_ADQUERYJOB_H__
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qgpgme-2.1.0/src/adqueryjob_p.h 
new/qgpgme-2.2.0/src/adqueryjob_p.h
--- old/qgpgme-2.1.0/src/adqueryjob_p.h 1970-01-01 01:00:00.000000000 +0100
+++ new/qgpgme-2.2.0/src/adqueryjob_p.h 2026-07-20 15:07:38.000000000 +0200
@@ -0,0 +1,58 @@
+/*
+    adqueryjob_p.h
+
+    This file is part of qgpgme, the Qt API binding for gpgme
+    Copyright (c) 2026 g10 Code GmbH
+    Software engineering by Ingo Klöcker <[email protected]>
+
+    QGpgME 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.
+
+    QGpgME 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, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  
USA
+
+    In addition, as a special exception, the copyright holders give
+    permission to link the code of this program with any edition of
+    the Qt library by Trolltech AS, Norway (or with modified versions
+    of Qt that use the same license as Qt), and distribute linked
+    combinations including the two.  You must obey the GNU General
+    Public License in all respects for all of the code used other than
+    Qt.  If you modify this file, you may extend this exception to
+    your version of the file, but you are not obligated to do so.  If
+    you do not wish to do so, delete this exception statement from
+    your version.
+*/
+
+#ifndef __QGPGME_ADQUERYEJOB_P_H__
+#define __QGPGME_ADQUERYEJOB_P_H__
+
+#include "adqueryjob.h"
+
+#include "job_p.h"
+
+namespace QGpgME
+{
+
+class ADQueryResult;
+
+class ADQueryJobPrivate : public JobPrivate
+{
+public:
+    QString m_filter;
+    QStringList m_attributes;
+    ADQueryOptions m_options = ADQueryOption::Default;
+
+    virtual ADQueryResult execIt() = 0;
+};
+
+}
+
+#endif // __QGPGME_ADQUERYEJOB_P_H__
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qgpgme-2.1.0/src/adqueryresult.cpp 
new/qgpgme-2.2.0/src/adqueryresult.cpp
--- old/qgpgme-2.1.0/src/adqueryresult.cpp      1970-01-01 01:00:00.000000000 
+0100
+++ new/qgpgme-2.2.0/src/adqueryresult.cpp      2026-07-20 15:07:38.000000000 
+0200
@@ -0,0 +1,133 @@
+/*
+    adqueryresult.cpp - wraps the result of a ADQueryJob
+
+    This file is part of qgpgme, the Qt API binding for gpgme
+    Copyright (c) 2026 g10 Code GmbH
+    Software engineering by Ingo Klöcker <[email protected]>
+
+    QGpgME 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.
+
+    QGpgME 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, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  
USA
+
+    In addition, as a special exception, the copyright holders give
+    permission to link the code of this program with any edition of
+    the Qt library by Trolltech AS, Norway (or with modified versions
+    of Qt that use the same license as Qt), and distribute linked
+    combinations including the two.  You must obey the GNU General
+    Public License in all respects for all of the code used other than
+    Qt.  If you modify this file, you may extend this exception to
+    your version of the file, but you are not obligated to do so.  If
+    you do not wish to do so, delete this exception statement from
+    your version.
+*/
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include "adqueryresult.h"
+
+#include <iterator>
+#include <ostream>
+
+using namespace QGpgME;
+using namespace GpgME;
+
+class ADQueryResult::Private
+{
+public:
+    QList<Attribute> attributes;
+    QString source;
+};
+
+ADQueryResult::ADQueryResult() = default;
+
+ADQueryResult::~ADQueryResult() = default;
+
+ADQueryResult::ADQueryResult(const Error &error)
+    : Result{error}
+    , d{new Private{{}, {}}}
+{
+}
+
+ADQueryResult::ADQueryResult(const QList<Attribute> &attributes, const QString 
&source, const GpgME::Error &error)
+    : Result{error}
+    , d{new Private{attributes, source}}
+{
+}
+
+ADQueryResult::ADQueryResult(const ADQueryResult &other)
+    : Result{other}
+{
+    if (other.d) {
+        d.reset(new Private{*other.d});
+    }
+}
+
+ADQueryResult &ADQueryResult::operator=(const ADQueryResult &other)
+{
+    auto tmp = other;
+    swap(tmp);
+    return *this;
+}
+
+ADQueryResult::ADQueryResult(ADQueryResult &&other) = default;
+
+ADQueryResult &ADQueryResult::operator=(ADQueryResult &&other) = default;
+
+void ADQueryResult::swap(ADQueryResult &other) noexcept
+{
+    Result::swap(other);
+    std::swap(this->d, other.d);
+}
+
+bool ADQueryResult::isNull() const
+{
+    return !d && !bool(error());
+}
+
+QList<ADQueryResult::Attribute> ADQueryResult::attributes() const
+{
+    return d ? d->attributes : QList<ADQueryResult::Attribute>{};
+}
+
+QString ADQueryResult::source() const
+{
+    return d ? d->source : QString{};
+}
+
+void QGpgME::swap(ADQueryResult &a, ADQueryResult &b)
+{
+    a.swap(b);
+}
+
+std::ostream &QGpgME::operator<<(std::ostream &os, const ADQueryResult &result)
+{
+    os << "QGpgME::ADQueryResult(";
+    if (!result.isNull()) {
+        os << "\n source: " << result.source().toStdString()
+           << "\n attributes:\n";
+        const auto attributes = result.attributes();
+        std::copy(attributes.begin(), attributes.end(),
+                  std::ostream_iterator<ADQueryResult::Attribute>(os, "\n"));
+    }
+    return os << ')';
+}
+
+std::ostream &QGpgME::operator<<(std::ostream &os, const 
ADQueryResult::Attribute &attribute)
+{
+    return os << "QGpgME::ADQueryResult::Attribute("
+              << "\n name:  " << attribute.name.toStdString()
+              << "\n value: " << attribute.value.toStdString()
+              << "\n)";
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qgpgme-2.1.0/src/adqueryresult.h 
new/qgpgme-2.2.0/src/adqueryresult.h
--- old/qgpgme-2.1.0/src/adqueryresult.h        1970-01-01 01:00:00.000000000 
+0100
+++ new/qgpgme-2.2.0/src/adqueryresult.h        2026-07-20 15:07:38.000000000 
+0200
@@ -0,0 +1,99 @@
+/*
+    adqueryresult.h - wraps the result of a ADQueryJob
+
+    This file is part of qgpgme, the Qt API binding for gpgme
+    Copyright (c) 2026 g10 Code GmbH
+    Software engineering by Ingo Klöcker <[email protected]>
+
+    QGpgME 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.
+
+    QGpgME 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, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  
USA
+
+    In addition, as a special exception, the copyright holders give
+    permission to link the code of this program with any edition of
+    the Qt library by Trolltech AS, Norway (or with modified versions
+    of Qt that use the same license as Qt), and distribute linked
+    combinations including the two.  You must obey the GNU General
+    Public License in all respects for all of the code used other than
+    Qt.  If you modify this file, you may extend this exception to
+    your version of the file, but you are not obligated to do so.  If
+    you do not wish to do so, delete this exception statement from
+    your version.
+*/
+
+#ifndef __QGPGME_ADQUERYRESULT_H__
+#define __QGPGME_ADQUERYRESULT_H__
+
+#include "qgpgme_export.h"
+
+#include <QList>
+#include <QString>
+
+#include <gpgme++/result.h>
+
+#include <memory>
+
+namespace GpgME
+{
+class Error;
+}
+
+namespace QGpgME
+{
+
+class QGPGME_EXPORT ADQueryResult : public GpgME::Result
+{
+public:
+    struct Attribute {
+        QString name;
+        QString value;
+
+        Attribute(QString _name, QString _value)
+            : name(std::move(_name))
+            , value(std::move(_value))
+        {
+        }
+    };
+
+    ADQueryResult();
+    ~ADQueryResult();
+
+    explicit ADQueryResult(const GpgME::Error &err);
+    explicit ADQueryResult(const QList<Attribute> &attributes, const QString 
&source, const GpgME::Error &err);
+
+    ADQueryResult(const ADQueryResult &other);
+    ADQueryResult &operator=(const ADQueryResult &other);
+
+    ADQueryResult(ADQueryResult &&other);
+    ADQueryResult &operator=(ADQueryResult &&other);
+
+    void swap(ADQueryResult &other) noexcept;
+
+    bool isNull() const;
+
+    QList<Attribute> attributes() const;
+    QString source() const;
+
+private:
+    class Private;
+    std::unique_ptr<Private> d;
+};
+
+QGPGME_EXPORT void swap(ADQueryResult &a, ADQueryResult &b);
+
+QGPGME_EXPORT std::ostream &operator<<(std::ostream &os, const ADQueryResult 
&result);
+QGPGME_EXPORT std::ostream &operator<<(std::ostream &os, const 
ADQueryResult::Attribute &result);
+
+}
+
+#endif // __QGPGME_ADQUERYRESULT_H__
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qgpgme-2.1.0/src/protocol.h 
new/qgpgme-2.2.0/src/protocol.h
--- old/qgpgme-2.1.0/src/protocol.h     2026-05-18 14:24:04.000000000 +0200
+++ new/qgpgme-2.2.0/src/protocol.h     2026-07-20 15:07:38.000000000 +0200
@@ -41,6 +41,7 @@
 
 namespace QGpgME {
 class AddExistingSubkeyJob;
+class ADQueryJob;
 class CryptoConfig;
 class KeyListJob;
 class ListAllKeysJob;
@@ -201,6 +202,8 @@
     virtual DecryptVerifyArchiveJob *decryptVerifyArchiveJob() const = 0;
 
     virtual WKDRefreshJob *wkdRefreshJob() const = 0;
+
+    virtual ADQueryJob *adQueryJob() const = 0;
 };
 
 /** Obtain a reference to the OpenPGP Protocol.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qgpgme-2.1.0/src/protocol_p.h 
new/qgpgme-2.2.0/src/protocol_p.h
--- old/qgpgme-2.1.0/src/protocol_p.h   2026-05-18 14:24:04.000000000 +0200
+++ new/qgpgme-2.2.0/src/protocol_p.h   2026-07-20 15:07:38.000000000 +0200
@@ -37,6 +37,7 @@
 #define __QGPGME_PROTOCOL_P_H__
 #include "qgpgmenewcryptoconfig.h"
 
+#include "qgpgmeadqueryjob.h"
 #include "qgpgmekeygenerationjob.h"
 #include "qgpgmekeylistjob.h"
 #include "qgpgmelistallkeysjob.h"
@@ -566,6 +567,14 @@
         }
         return nullptr;
     }
+
+    QGpgME::ADQueryJob *adQueryJob() const override
+    {
+        if (auto context = 
GpgME::Context::createForEngine(GpgME::AssuanEngine)) {
+            return new QGpgME::QGpgMEADQueryJob{context.release()};
+        }
+        return nullptr;
+    }
 };
 
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qgpgme-2.1.0/src/qgpgmeadqueryjob.cpp 
new/qgpgme-2.2.0/src/qgpgmeadqueryjob.cpp
--- old/qgpgme-2.1.0/src/qgpgmeadqueryjob.cpp   1970-01-01 01:00:00.000000000 
+0100
+++ new/qgpgme-2.2.0/src/qgpgmeadqueryjob.cpp   2026-07-20 15:07:38.000000000 
+0200
@@ -0,0 +1,256 @@
+/*
+    qgpgmeadqueryjob.cpp
+
+    This file is part of qgpgme, the Qt API binding for gpgme
+    Copyright (c) 2026 g10 Code GmbH
+    Software engineering by Ingo Klöcker <[email protected]>
+
+    QGpgME 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.
+
+    QGpgME 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, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  
USA
+
+    In addition, as a special exception, the copyright holders give
+    permission to link the code of this program with any edition of
+    the Qt library by Trolltech AS, Norway (or with modified versions
+    of Qt that use the same license as Qt), and distribute linked
+    combinations including the two.  You must obey the GNU General
+    Public License in all respects for all of the code used other than
+    Qt.  If you modify this file, you may extend this exception to
+    your version of the file, but you are not obligated to do so.  If
+    you do not wish to do so, delete this exception statement from
+    your version.
+*/
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include "qgpgmeadqueryjob.h"
+
+#include "adqueryjob_p.h"
+#include "cryptoconfig.h"
+#include "debug.h"
+#include "protocol.h"
+#include "qgpgme_debug.h"
+#include "qt6compat_p.h"
+#include "util.h"
+
+#include <gpgme++/context.h>
+#include <gpgme++/data.h>
+#include <gpgme++/defaultassuantransaction.h>
+
+#include <gpg-error.h>
+
+using namespace QGpgME;
+using namespace GpgME;
+using namespace Qt::Literals;
+
+namespace QGpgME
+{
+
+class QGpgMEADQueryJobPrivate : public ADQueryJobPrivate
+{
+public:
+    Q_DECLARE_PUBLIC(QGpgMEADQueryJob)
+
+    QGpgMEADQueryJobPrivate() = default;
+
+    ~QGpgMEADQueryJobPrivate() override = default;
+
+private:
+    QGpgMEADQueryJob::result_type runADQuery(Context *ctx, const QString 
&filter, const QStringList &attributes, ADQueryOptions options);
+
+    GpgME::Error startIt() override;
+
+    void startNow() override
+    {
+        Q_Q(QGpgMEADQueryJob);
+        q->run();
+    }
+
+    ADQueryResult execIt() override;
+};
+
+}
+
+QGpgMEADQueryJob::QGpgMEADQueryJob(Context *context)
+    : mixin_type{context}
+{
+    lateInitialization();
+}
+
+QGpgMEADQueryJob::~QGpgMEADQueryJob() = default;
+
+static GpgME::Error startDirmngr(Context *assuanCtx)
+{
+    // don't start dirmngr if it is disabled for gpg _and_ gpgsm
+    if (QGpgME::cryptoConfig()->entry("gpg", "disable-dirmngr")->boolValue()
+        && QGpgME::cryptoConfig()->entry("gpgsm", 
"disable-dirmngr")->boolValue()) {
+        return Error::fromCode(GPG_ERR_NO_DIRMNGR);
+    }
+
+    Error err;
+    auto spawnCtx = 
std::unique_ptr<Context>{Context::createForEngine(SpawnEngine, &err)};
+    if (err) {
+        qCDebug(QGPGME_LOG) << "Error: Failed to get context for spawn engine 
(" << err << ")";
+    }
+    const auto gpgconfProgram = GpgME::dirInfo("gpgconf-name");
+    // replace backslashes with forward slashes in homedir to work around bug 
T6833
+    std::string homedir{GpgME::dirInfo("homedir")};
+    std::replace(homedir.begin(), homedir.end(), '\\', '/');
+    const char *argv[] = {
+        gpgconfProgram,
+        "--homedir",
+        homedir.c_str(),
+        "--launch",
+        "dirmngr",
+        NULL
+    };
+    auto ignoreIO = Data{Data::null};
+    if (!err) {
+        qCDebug(QGPGME_LOG) << "Starting dirmngr ...";
+        err = spawnCtx->spawn(gpgconfProgram, argv,
+                              ignoreIO, ignoreIO, ignoreIO,
+                              Context::SpawnDetached);
+    }
+
+    if (!err) {
+        // wait for socket to become available
+        int cnt = 0;
+        do {
+            ++cnt;
+            qCDebug(QGPGME_LOG) << "Waiting for dirmngr to start ...";
+            QThread::msleep(250 * cnt);
+            err = assuanCtx->assuanTransact("GETINFO version");
+        } while (err.code() == GPG_ERR_ASS_CONNECT_FAILED && cnt < 5);
+    }
+
+    return err;
+}
+
+static GpgME::Error setUpDirmngrAssuanConnection(Context *ctx)
+{
+    Error err;
+
+    const std::string dirmngrSocket = GpgME::dirInfo("dirmngr-socket");
+    err = ctx->setEngineFileName(dirmngrSocket.c_str());
+
+    if (!err) {
+        err = ctx->setEngineHomeDirectory("");
+    }
+
+    if (!err) {
+        // try to connect to dirmngr
+        err = ctx->assuanTransact("GETINFO version");
+        if (err.code() == GPG_ERR_ASS_CONNECT_FAILED) {
+            err = startDirmngr(ctx);
+        }
+    }
+
+    return err;
+}
+
+static QString _QStringFromStdStringView(std::string_view s)
+{
+    return s.empty() ? QString{} : QString::fromUtf8(s.data(), s.size());
+}
+
+static QList<QGpgME::ADQueryResult::Attribute> parse_query_result(const 
std::string &resultData)
+{
+    QList<QGpgME::ADQueryResult::Attribute> result;
+
+    const auto lines = _qgpgme::split(resultData, '\n');
+    for (auto line : lines) {
+        if (line.empty()) {
+            continue;
+        }
+        if (line.front() == ' ') {
+            // line starts with space -> continuation of last value
+            if (!result.empty()) {
+                result.back().value += 
_QStringFromStdStringView(line.substr(1));
+            }
+        } else {
+            const auto nameEnd = line.find(':');
+            if ((nameEnd == line.npos) || (line[nameEnd + 1] != ' ')) {
+                qCDebug(QGPGME_LOG) << "Unexpected line in AD_QUERY result:" 
<< std::string{line};
+                continue;
+            }
+            const std::string_view name = line.substr(0, nameEnd);
+            const std::string_view value = line.substr(nameEnd + 2);
+            result.push_back({_QStringFromStdStringView(name), 
_QStringFromStdStringView(value)});
+        }
+    }
+
+    return result;
+}
+
+static QGpgMEADQueryJob::result_type run_ad_query(Context *ctx, const QString 
&filter, const QStringList &attributes, ADQueryOptions options)
+{
+    ADQueryResult result;
+
+    Error err = setUpDirmngrAssuanConnection(ctx);
+
+    if (!err) {
+        QStringList arguments;
+        if (options & ADQueryOption::RootDSE) {
+            arguments.push_back(u"--rootdse"_s);
+        }
+        if (options & ADQueryOption::SubstituteVariables) {
+            arguments.push_back(u"--subst"_s);
+        }
+        if (!attributes.empty()) {
+            arguments.push_back("--attr="_L1 + attributes.join(u','));
+        }
+        arguments.push_back(u"--"_s);
+        arguments.push_back(filter);
+        const std::string cmd = std::string{"AD_QUERY "} += arguments.join(u' 
').toStdString();
+        err = ctx->assuanTransact(cmd.c_str());
+        if (err) {
+            qCDebug(QGPGME_LOG) << "AD_QUERY failed with" << err;
+        }
+    }
+
+    if (!err) {
+        const auto transaction = 
std::unique_ptr<DefaultAssuanTransaction>(dynamic_cast<DefaultAssuanTransaction*>(ctx->takeLastAssuanTransaction().release()));
+        const std::string source = transaction->firstStatusLine("SOURCE");
+        const std::string rawData = transaction->data();
+        if (rawData.empty()) {
+            qCDebug(QGPGME_LOG) << "No data returned for" << filter;
+            result = ADQueryResult{};
+        } else {
+            qCDebug(QGPGME_LOG) << "Got a result for" << filter << "at" << 
source.c_str();
+            result = ADQueryResult{parse_query_result(rawData), 
QString::fromStdString(source), {}};
+        }
+    }
+
+    return std::make_tuple(err ? ADQueryResult{err} : result, QString{}, 
Error{});
+}
+
+GpgME::Error QGpgMEADQueryJobPrivate::startIt()
+{
+    Q_Q(QGpgMEADQueryJob);
+    q->run([=](Context *ctx) {
+        return run_ad_query(ctx, m_filter, m_attributes, m_options);
+    });
+
+    return {};
+}
+
+ADQueryResult QGpgMEADQueryJobPrivate::execIt()
+{
+    Q_Q(QGpgMEADQueryJob);
+    const QGpgMEADQueryJob::result_type r = run_ad_query(q->context(), 
m_filter, m_attributes, m_options);
+    return std::get<0>(r);
+}
+
+#include "moc_qgpgmeadqueryjob.cpp"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qgpgme-2.1.0/src/qgpgmeadqueryjob.h 
new/qgpgme-2.2.0/src/qgpgmeadqueryjob.h
--- old/qgpgme-2.1.0/src/qgpgmeadqueryjob.h     1970-01-01 01:00:00.000000000 
+0100
+++ new/qgpgme-2.2.0/src/qgpgmeadqueryjob.h     2026-07-20 15:07:38.000000000 
+0200
@@ -0,0 +1,69 @@
+/*
+    qgpgmeadqueryjob.h
+
+    This file is part of qgpgme, the Qt API binding for gpgme
+    Copyright (c) 2026 g10 Code GmbH
+    Software engineering by Ingo Klöcker <[email protected]>
+
+    QGpgME 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.
+
+    QGpgME 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, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  
USA
+
+    In addition, as a special exception, the copyright holders give
+    permission to link the code of this program with any edition of
+    the Qt library by Trolltech AS, Norway (or with modified versions
+    of Qt that use the same license as Qt), and distribute linked
+    combinations including the two.  You must obey the GNU General
+    Public License in all respects for all of the code used other than
+    Qt.  If you modify this file, you may extend this exception to
+    your version of the file, but you are not obligated to do so.  If
+    you do not wish to do so, delete this exception statement from
+    your version.
+*/
+
+#ifndef __QGPGME_QGPGMEADQUERYJOB_H__
+#define __QGPGME_QGPGMEADQUERYJOB_H__
+
+#include "adqueryjob.h"
+
+#include "adqueryresult.h"
+#include "threadedjobmixin.h"
+
+namespace QGpgME
+{
+
+class QGpgMEADQueryJobPrivate;
+
+class QGpgMEADQueryJob
+#ifdef Q_MOC_RUN
+    : public ADQueryJob
+#else
+    : public _detail::ThreadedJobMixin<ADQueryJob, QGpgMEADQueryJobPrivate, 
std::tuple<ADQueryResult, QString, GpgME::Error> >
+#endif
+{
+    Q_OBJECT
+#ifdef Q_MOC_RUN
+public Q_SLOTS:
+    void slotFinished();
+#endif
+public:
+    explicit QGpgMEADQueryJob(GpgME::Context *context);
+    ~QGpgMEADQueryJob() override;
+
+private:
+    Q_DECLARE_PRIVATE(QGpgMEADQueryJob)
+};
+
+}
+
+#endif // __QGPGME_QGPGMEADQUERYJOB_H__
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qgpgme-2.1.0/src/qgpgmewkdlookupjob.cpp 
new/qgpgme-2.2.0/src/qgpgmewkdlookupjob.cpp
--- old/qgpgme-2.1.0/src/qgpgmewkdlookupjob.cpp 2026-05-18 14:24:04.000000000 
+0200
+++ new/qgpgme-2.2.0/src/qgpgmewkdlookupjob.cpp 2026-07-20 15:07:38.000000000 
+0200
@@ -37,7 +37,9 @@
 
 #include "qgpgmewkdlookupjob.h"
 
+#include "cryptoconfig.h"
 #include "debug.h"
+#include "protocol.h"
 #include "qgpgme_debug.h"
 
 #include <gpgme++/context.h>
@@ -59,8 +61,12 @@
 
 static GpgME::Error startDirmngr(Context *assuanCtx)
 {
-    Error err;
+    // don't start dirmngr if it is disabled for gpg
+    if (QGpgME::cryptoConfig()->entry("gpg", "disable-dirmngr")->boolValue()) {
+        return Error::fromCode(GPG_ERR_NO_DIRMNGR);
+    }
 
+    Error err;
     auto spawnCtx = 
std::unique_ptr<Context>{Context::createForEngine(SpawnEngine, &err)};
     if (err) {
         qCDebug(QGPGME_LOG) << "Error: Failed to get context for spawn engine 
(" << err << ")";
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qgpgme-2.1.0/src/qt6compat_p.h 
new/qgpgme-2.2.0/src/qt6compat_p.h
--- old/qgpgme-2.1.0/src/qt6compat_p.h  2026-05-18 14:24:04.000000000 +0200
+++ new/qgpgme-2.2.0/src/qt6compat_p.h  2026-07-20 15:07:38.000000000 +0200
@@ -35,10 +35,11 @@
 
 #include <QtGlobal>
 
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
-
+#include <QDebug>
 #include <QString>
 
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+
 namespace Qt
 {
 inline namespace Literals
@@ -58,3 +59,10 @@
 } // Qt
 
 #endif
+
+#if QT_VERSION < QT_VERSION_CHECK(6, 5, 0)
+inline QDebug operator<<(QDebug s, const std::string &string)
+{
+    return s << QString::fromStdString(string);
+}
+#endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qgpgme-2.1.0/src/util.h new/qgpgme-2.2.0/src/util.h
--- old/qgpgme-2.1.0/src/util.h 2026-05-18 14:24:04.000000000 +0200
+++ new/qgpgme-2.2.0/src/util.h 2026-07-20 15:07:38.000000000 +0200
@@ -40,6 +40,7 @@
 
 #include <gpgme.h>
 
+#include <memory>
 #include <string>
 #include <vector>
 
@@ -62,6 +63,27 @@
 #endif
 }
 
+namespace _qgpgme
+{
+
+static inline std::vector<std::string_view> split(const std::string_view s, 
char delimiter)
+{
+    std::vector<std::string_view> result;
+    std::string_view::size_type start = 0;
+    std::string_view::size_type end;
+    do {
+        end = s.find(delimiter, start);
+        if (end == s.npos) {
+            end = s.size();
+        }
+        result.emplace_back(std::addressof(s[start]), end - start);
+        start = end + 1;
+    } while (end != s.size());
+    return result;
+}
+
+}
+
 std::vector<std::string> toStrings(const QStringList &l);
 
 QStringList toFingerprints(const std::vector<GpgME::Key> &keys);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qgpgme-2.1.0/tests/CMakeLists.txt 
new/qgpgme-2.2.0/tests/CMakeLists.txt
--- old/qgpgme-2.1.0/tests/CMakeLists.txt       2026-05-18 14:24:04.000000000 
+0200
+++ new/qgpgme-2.2.0/tests/CMakeLists.txt       2026-07-20 15:07:38.000000000 
+0200
@@ -62,6 +62,7 @@
 _g10_add_test(t-setprimaryuserid.cpp)
 _g10_add_test(t-tofuinfo.cpp)
 _g10_add_test(t-trustsignatures.cpp)
+_g10_add_test(t-util.cpp)
 _g10_add_test(t-various.cpp)
 _g10_add_test(t-verify.cpp)
 _g10_add_test(t-wkdlookup.cpp)
@@ -78,6 +79,7 @@
     target_link_libraries(${_name} ${qgpgme_library} Gpgmepp)
 endmacro()
 
+_g10_add_testprogram(run-adqueryjob.cpp)
 _g10_add_testprogram(run-decryptverifyarchivejob.cpp)
 _g10_add_testprogram(run-decryptverifyjob.cpp)
 _g10_add_testprogram(run-encryptarchivejob.cpp)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qgpgme-2.1.0/tests/run-adqueryjob.cpp 
new/qgpgme-2.2.0/tests/run-adqueryjob.cpp
--- old/qgpgme-2.1.0/tests/run-adqueryjob.cpp   1970-01-01 01:00:00.000000000 
+0100
+++ new/qgpgme-2.2.0/tests/run-adqueryjob.cpp   2026-07-20 15:07:38.000000000 
+0200
@@ -0,0 +1,132 @@
+/*
+    run-adqueryjob.cpp
+
+    This file is part of QGpgME's test suite.
+    Copyright (c) 2026 g10 Code GmbH
+    Software engineering by Ingo Klöcker <[email protected]>
+
+    QGpgME 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.
+
+    QGpgME 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, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  
USA
+
+    In addition, as a special exception, the copyright holders give
+    permission to link the code of this program with any edition of
+    the Qt library by Trolltech AS, Norway (or with modified versions
+    of Qt that use the same license as Qt), and distribute linked
+    combinations including the two.  You must obey the GNU General
+    Public License in all respects for all of the code used other than
+    Qt.  If you modify this file, you may extend this exception to
+    your version of the file, but you are not obligated to do so.  If
+    you do not wish to do so, delete this exception statement from
+    your version.
+*/
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include <adqueryjob.h>
+#include <adqueryresult.h>
+#include <debug.h>
+#include <protocol.h>
+
+#include <QCommandLineParser>
+#include <QCoreApplication>
+
+#include <gpgme++/context.h>
+
+#include <iostream>
+
+using namespace GpgME;
+
+std::ostream &operator<<(std::ostream &os, const QString &s)
+{
+    return os << s.toLocal8Bit().constData();
+}
+
+struct CommandLineOptions {
+    bool asynchronous = false;
+    QString attributes;
+    QString email;
+};
+
+CommandLineOptions parseCommandLine(const QStringList &arguments)
+{
+    CommandLineOptions options;
+
+    QCommandLineParser parser;
+    parser.setApplicationDescription("Test program for ADQueryJob");
+    parser.addHelpOption();
+    parser.addOptions({
+        {"async", "Run the job asynchronously"},
+    });
+    parser.addPositionalArgument("attributes", "Comma separated list of 
attributes to ask for");
+    parser.addPositionalArgument("email", "User to ask for");
+
+    parser.process(arguments);
+
+    const auto args = parser.positionalArguments();
+    if (args.size() != 2) {
+        parser.showHelp(1);
+    }
+
+    options.asynchronous = parser.isSet("async");
+    options.attributes = args[0];
+    options.email = args[1];
+
+    return options;
+}
+
+static void printResult(const QGpgME::ADQueryResult &result)
+{
+    if (result.error()) {
+        std::cout << "Error: " << result.error().asStdString() << std::endl;
+    } else {
+        std::cout << "Result: " << result << std::endl;
+    }
+}
+
+int main(int argc, char **argv)
+{
+    GpgME::initializeLibrary();
+
+    QCoreApplication app{argc, argv};
+    app.setApplicationName("run-adqueryjob");
+
+    const auto options = parseCommandLine(app.arguments());
+
+    Error err;
+    std::cout << "Querying AD for attributes " << options.attributes << " of 
user with email " << options.email << std::endl;
+
+    auto job = 
std::unique_ptr<QGpgME::ADQueryJob>(QGpgME::openpgp()->adQueryJob());
+    if (!job) {
+        std::cerr << "Error: Could not create job to query AD" << std::endl;
+        return 1;
+    }
+    const QString filter = 
QStringLiteral("(&(objectcategory=person)(objectclass=user) 
(|(userPrincipalName=%1) (mail=%1)))").arg(options.email);
+    if (options.asynchronous) {
+        QObject::connect(job.get(), &QGpgME::ADQueryJob::result, &app, 
[](const QGpgME::ADQueryResult &result, const QString &, const GpgME::Error &) {
+            printResult(result);
+            qApp->quit();
+        });
+        err = job->start(filter, options.attributes.split(u','), 
QGpgME::ADQueryOption::SubstituteVariables);
+        if (err) {
+            std::cerr << "Error: " << err << std::endl;
+            return 1;
+        }
+        job.release(); // NOLINT(bugprone-unused-return-value); job will 
delete itself when it's done
+        return app.exec();
+    } else {
+        printResult(job->exec(filter, options.attributes.split(u','), 
QGpgME::ADQueryOption::SubstituteVariables));
+    }
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/qgpgme-2.1.0/tests/t-util.cpp 
new/qgpgme-2.2.0/tests/t-util.cpp
--- old/qgpgme-2.1.0/tests/t-util.cpp   1970-01-01 01:00:00.000000000 +0100
+++ new/qgpgme-2.2.0/tests/t-util.cpp   2026-07-20 15:07:38.000000000 +0200
@@ -0,0 +1,91 @@
+/*
+    t-util.cpp
+
+    This file is part of qgpgme, the Qt API binding for gpgme
+    Copyright (c) 2026 g10 Code GmbH
+    Software engineering by Ingo Klöcker <[email protected]>
+
+    QGpgME 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.
+
+    QGpgME 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, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  
USA
+
+    In addition, as a special exception, the copyright holders give
+    permission to link the code of this program with any edition of
+    the Qt library by Trolltech AS, Norway (or with modified versions
+    of Qt that use the same license as Qt), and distribute linked
+    combinations including the two.  You must obey the GNU General
+    Public License in all respects for all of the code used other than
+    Qt.  If you modify this file, you may extend this exception to
+    your version of the file, but you are not obligated to do so.  If
+    you do not wish to do so, delete this exception statement from
+    your version.
+*/
+
+#include "util.h"
+
+#include <qt6compat_p.h>
+
+#include <QString>
+#include <QTest>
+
+using namespace std::literals;
+
+class TestUtil : public QObject
+{
+    Q_OBJECT
+public:
+    using QObject::QObject;
+
+private Q_SLOTS:
+    void test_split()
+    {
+        using VecSV = std::vector<std::string_view>;
+        {
+            const auto result = _qgpgme::split(""sv, ',');
+            QCOMPARE(result, VecSV{""sv});
+        }
+        {
+            const auto result = _qgpgme::split("abc"sv, ',');
+            QCOMPARE(result, VecSV{"abc"sv});
+        }
+        {
+            const auto result = _qgpgme::split("abc,def"sv, ',');
+            const auto expected = VecSV{"abc"sv, "def"sv};
+            QCOMPARE(result, expected);
+        }
+        {
+            const auto result = _qgpgme::split(",abc"sv, ',');
+            const auto expected = VecSV{""sv, "abc"sv};
+            QCOMPARE(result, expected);
+        }
+        {
+            const auto result = _qgpgme::split("abc,"sv, ',');
+            const auto expected = VecSV{"abc"sv, ""sv};
+            QCOMPARE(result, expected);
+        }
+        {
+            const auto result = _qgpgme::split("abc,,def"sv, ',');
+            const auto expected = VecSV{"abc"sv, ""sv, "def"sv};
+            QCOMPARE(result, expected);
+        }
+        {
+            const auto result = _qgpgme::split(","sv, ',');
+            const auto expected = VecSV{""sv, ""sv};
+            QCOMPARE(result, expected);
+        }
+    }
+};
+
+QTEST_GUILESS_MAIN(TestUtil)
+
+#include "t-util.moc"

++++++ qgpgme.keyring ++++++
--- /var/tmp/diff_new_pack.LdYxrE/_old  2026-08-02 23:14:25.804286742 +0200
+++ /var/tmp/diff_new_pack.LdYxrE/_new  2026-08-02 23:14:25.808286880 +0200
@@ -66,30 +66,39 @@
 KdYretbGQwo+vXLXfWk9QKHXwF2IdkUSnL/IyFje/thujBW2UJZMTO3vD830px2G
 k4h1BBATCAAdFiEEAvON/3Mf+XywOaHaVJ5pXpBboggFAmgeDcYACgkQVJ5pXpBb
 ogis0wD9H38UP4TH3Y19d7mnkSifeHkldKc4iUP/Ok3w/+Di5qkA/iA7xLTtiuhW
-jhnuwb68kTxh8Beg023EiqsJb9qWnY8umFMEYWlKoxMJKyQDAwIIAQEHAgMEXpcP
-02ZRAOCLJg1uGzUMwnXiYjDzXbBjUdXH/hBZhaIG6eGu9IXFVvOyMPv9a/6/duYw
-+sv4zYMvIWJJ7A2ZxLQkR251UEcuY29tIChSZWxlYXNlIFNpZ25pbmcgS2V5IDIw
-MjEpiJoEExMIAEIWIQQC843/cx/5fLA5odpUnmlekFuiCAUCYWlKowIbAwUJD3HX
-igULCQgHAgMiAgEGFQoJCAsCBBYCAwECHgcCF4AACgkQVJ5pXpBboghOSgD9FhqN
-pOXV4QFT8Z2bXajeOsjnk3nFkrZdOpLHblyVXKMA/RfAxb86Dn40PWuLdsCoANVa
-UENSzDPzBjGxvQLiRgGSiHUEEBYKAB0WIQRtqm5kp20oQFcbSQJSiJe4JkA62gUC
-YWlO8QAKCRBSiJe4JkA62slAAQCHtjLKSMDL9CzXILeOLyIF8hWc9e9uWsjHdJFH
-IPBELwEAq1lsS4pO0+WCQtSAyV5Nxkn+8SEkT4a99D2jmBYKoQWIdQQQFgoAHRYh
-BMHTS2khnkruwLocIeP9/yGORbcrBQJhaU9aAAoJEOP9/yGORbcrHh4BAOnpoZI3
-99TjEuXxFK9BRWNUD5oJOsxBHeFHCrDyWIXbAQDc7cQLHPp7X4Ogi1igkEEsovB6
-IiewZn/6HldiuldOAJhzBGmcEd0TCSskAwMCCAEBCwMDBFT19o0ILvhUHY7++XKs
-7VXucAoXgkq5WEvqBsIzGGSrWlC6fc+L6bDS6YSSw2yRMWmeY7fukPLaDY/BtAFe
-6LYHos4tyUkjHcUliMyEPvnIUapDL+ZS8I+ihkt4wlfWPrQkR251UEcuY29tIChS
-ZWxlYXNlIFNpZ25pbmcgS2V5IDIwMjYpiNUEExMJAF0WIQQUkyad5h8SSqaaMW46
-3zTr27IApAUCaZwU6xsUgAAAAAAEAA5tYW51MiwyLjUrMS4xMSwyLDICGwMFCQ8M
-a4AFCwkIBwICIgIGFQoJCAsCBBYCAwECHgcCF4AACgkQOt8069uyAKS3FAF/d81D
-kMhp98EHpDa/ZLbvIZuTDvz/wngLOzHvMLy+zAm1UQKU4nRT9YCjiz7/hS55AX4w
-h36hfXlNvTpP8tXjY+MNo7oMuHx+a23KgB77KTxKCMoF/ZAetYFhVwcubFRk5KOI
-dQQQEwgAHRYhBALzjf9zH/l8sDmh2lSeaV6QW6IIBQJpnBZZAAoJEFSeaV6QW6II
-+a4BAJsGiYwA0Vwt0p2pxeSh/IGJTSHfFWYkEMf3pt5HGBGBAP9Hxc04lXgkr5yS
-AMOkqdhB2Y/VsrU5IltHfPNRWrBUsYh1BBAWCgAdFiEEbapuZKdtKEBXG0kCUoiX
-uCZAOtoFAmmcFpkACgkQUoiXuCZAOtq2fQEA4HuVHLXfTB9WNLA07Tuc8jziaGjG
-d3g9PrWIQiUMfsEA/2MPh5wwTaX+8YsBc+DwBGtNshzReN+OBDpnyk/ILEoM
-=rCfC
+jhnuwb68kTxh8Beg023EiqsJb9qWnY8umDMEal3qBxYJKwYBBAHaRw8BAQdAE3rp
+rW3s+unBl4VP1mXNXLn0Z/sOxGNy4p9nNgJP2mm0KEluZ28gS2zDtmNrZXIgKFJl
+bGVhc2UgU2lnbmluZyBLZXkgMjAyNimItQQTFgoAXRYhBNAq5JFzva1W5PiCI3B+
+VtPe9BFcBQJqXfiJGxSAAAAAAAQADm1hbnUyLDIuNSsxLjEyLDIsMgIbAwUJErWS
+lwULCQgHAgIiAgYVCgkICwIEFgIDAQIeBwIXgAAKCRBwflbT3vQRXPNvAP0X73ms
+UO574LuDcSSGhguVAWMxBxXxcM8q7nY35lXPsQEA11kEuQTBXbN9vy10/iOE9WJM
+4OWKiQrp6FcpQwFV/w+IdQQQFgoAHRYhBLgc4RKyao6ovnuV0uN1M5v0xRhABQJq
+XiSmAAoJEON1M5v0xRhAaCkBAKZQkMYbXqflBnb9gtYEuIkY2Tw2bU/3jmuSKG8g
+eR3xAQCZ90UeWzGV4GdV8ovW9aSWy8HWFaSQfkX9kC9BR5CGCphTBGFpSqMTCSsk
+AwMCCAEBBwIDBF6XD9NmUQDgiyYNbhs1DMJ14mIw812wY1HVx/4QWYWiBunhrvSF
+xVbzsjD7/Wv+v3bmMPrL+M2DLyFiSewNmcS0JEdudVBHLmNvbSAoUmVsZWFzZSBT
+aWduaW5nIEtleSAyMDIxKYiaBBMTCABCFiEEAvON/3Mf+XywOaHaVJ5pXpBboggF
+AmFpSqMCGwMFCQ9x14oFCwkIBwIDIgIBBhUKCQgLAgQWAgMBAh4HAheAAAoJEFSe
+aV6QW6IITkoA/RYajaTl1eEBU/Gdm12o3jrI55N5xZK2XTqSx25clVyjAP0XwMW/
+Og5+ND1ri3bAqADVWlBDUswz8wYxsb0C4kYBkoh1BBAWCgAdFiEEbapuZKdtKEBX
+G0kCUoiXuCZAOtoFAmFpTvEACgkQUoiXuCZAOtrJQAEAh7YyykjAy/Qs1yC3ji8i
+BfIVnPXvblrIx3SRRyDwRC8BAKtZbEuKTtPlgkLUgMleTcZJ/vEhJE+GvfQ9o5gW
+CqEFiHUEEBYKAB0WIQTB00tpIZ5K7sC6HCHj/f8hjkW3KwUCYWlPWgAKCRDj/f8h
+jkW3Kx4eAQDp6aGSN/fU4xLl8RSvQUVjVA+aCTrMQR3hRwqw8liF2wEA3O3ECxz6
+e1+DoItYoJBBLKLweiInsGZ/+h5XYrpXTgCYcwRpnBHdEwkrJAMDAggBAQsDAwRU
+9faNCC74VB2O/vlyrO1V7nAKF4JKuVhL6gbCMxhkq1pQun3Pi+mw0umEksNskTFp
+nmO37pDy2g2PwbQBXui2B6LOLclJIx3FJYjMhD75yFGqQy/mUvCPooZLeMJX1j60
+JEdudVBHLmNvbSAoUmVsZWFzZSBTaWduaW5nIEtleSAyMDI2KYjVBBMTCQBdFiEE
+FJMmneYfEkqmmjFuOt8069uyAKQFAmmcFOsbFIAAAAAABAAObWFudTIsMi41KzEu
+MTEsMiwyAhsDBQkPDGuABQsJCAcCAiICBhUKCQgLAgQWAgMBAh4HAheAAAoJEDrf
+NOvbsgCktxQBf3fNQ5DIaffBB6Q2v2S27yGbkw78/8J4Czsx7zC8vswJtVEClOJ0
+U/WAo4s+/4UueQF+MId+oX15Tb06T/LV42PjDaO6DLh8fmttyoAe+yk8SgjKBf2Q
+HrWBYVcHLmxUZOSjiHUEEBMIAB0WIQQC843/cx/5fLA5odpUnmlekFuiCAUCaZwW
+WQAKCRBUnmlekFuiCPmuAQCbBomMANFcLdKdqcXkofyBiU0h3xVmJBDH96beRxgR
+gQD/R8XNOJV4JK+ckgDDpKnYQdmP1bK1OSJbR3zzUVqwVLGIdQQQFgoAHRYhBG2q
+bmSnbShAVxtJAlKIl7gmQDraBQJpnBaZAAoJEFKIl7gmQDratn0BAOB7lRy130wf
+VjSwNO07nPI84mhoxnd4PT61iEIlDH7BAP9jD4ecME2l/vGLAXPg8ARrTbIc0Xjf
+jgQ6Z8pPyCxKDA==
+=/vKN
 -----END PGP PUBLIC KEY BLOCK-----
 

Reply via email to