Page MenuHome GnuPG

No OneTemporary

diff --git a/ConfigureChecks.cmake b/ConfigureChecks.cmake
index 514fbdf79..b1625e375 100644
--- a/ConfigureChecks.cmake
+++ b/ConfigureChecks.cmake
@@ -1,72 +1,10 @@
# assuan configure checks
include(CheckFunctionExists)
if ( ASSUAN2_FOUND )
else ( ASSUAN2_FOUND )
# TODO Clean this up with assuan 2 as hard dependency.
message(FATAL_ERROR "At least version 2 of libassuan is required for Kleopatra.")
endif ( ASSUAN2_FOUND )
-set( USABLE_ASSUAN_FOUND false )
-
-
- set( CMAKE_REQUIRED_INCLUDES ${ASSUAN2_INCLUDES} )
-
- set( CMAKE_REQUIRED_LIBRARIES ${ASSUAN2_LIBRARIES} )
- set( USABLE_ASSUAN_FOUND true )
-
- # TODO: this workaround will be removed as soon as we find better solution
- if(MINGW)
- set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${KDEWIN32_INCLUDE_DIR}/mingw)
- elseif(MSVC)
- set(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${KDEWIN32_INCLUDE_DIR}/msvc)
- endif(MINGW)
-
-if ( USABLE_ASSUAN_FOUND )
- # check if assuan.h can be compiled standalone (it couldn't, on
- # Windows, until recently, because of a HAVE_W32_SYSTEM #ifdef in
- # there)
- check_cxx_source_compiles( "
- #include <assuan.h>
- int main() {
- return 1;
- }
- "
- USABLE_ASSUAN_FOUND )
-endif( USABLE_ASSUAN_FOUND )
-
-if ( USABLE_ASSUAN_FOUND )
-
- # check whether assuan and gpgme may be linked to simultaneously
- check_function_exists( "assuan_get_pointer" USABLE_ASSUAN_FOUND )
-
-endif( USABLE_ASSUAN_FOUND )
-
-if ( USABLE_ASSUAN_FOUND )
-
- # check if gpg-error already has GPG_ERR_SOURCE_KLEO
- check_cxx_source_compiles("
- #include <gpg-error.h>
- static gpg_err_source_t src = GPG_ERR_SOURCE_KLEO;
- int main() { return 0; }
- "
- HAVE_GPG_ERR_SOURCE_KLEO )
-
-endif ( USABLE_ASSUAN_FOUND )
-
-if ( USABLE_ASSUAN_FOUND )
message( STATUS "Usable assuan found for Kleopatra" )
-else ( USABLE_ASSUAN_FOUND )
- message( STATUS "NO usable assuan found for Kleopatra" )
-endif ( USABLE_ASSUAN_FOUND )
-
-if (USABLE_ASSUAN_FOUND)
- set (HAVE_USABLE_ASSUAN 1)
- set (HAVE_KLEOPATRACLIENT_LIBRARY 1)
-else()
- set (HAVE_USABLE_ASSUAN 0)
- set (HAVE_KLEOPATRACLIENT_LIBRARY 0)
-endif()
-
-set(CMAKE_REQUIRED_INCLUDES)
-set(CMAKE_REQUIRED_LIBRARIES)
diff --git a/config-kleopatra.h.cmake b/config-kleopatra.h.cmake
index e2439bc32..aa2d3dd27 100644
--- a/config-kleopatra.h.cmake
+++ b/config-kleopatra.h.cmake
@@ -1,47 +1,41 @@
-/* Define to 1 if you have a recent enough libassuan */
-#cmakedefine HAVE_USABLE_ASSUAN 1
-
-/* Define to 1 if you build libkleopatraclient */
-#cmakedefine HAVE_KLEOPATRACLIENT_LIBRARY 1
-
/* DBus available */
#cmakedefine01 HAVE_QDBUS
/* Defined if QGpgME supports changing the expiration date of the primary key and the subkeys simultaneously */
#cmakedefine QGPGME_SUPPORTS_CHANGING_EXPIRATION_OF_COMPLETE_KEY 1
/* Defined if QGpgME supports retrieving the default value of a config entry */
#cmakedefine QGPGME_CRYPTOCONFIGENTRY_HAS_DEFAULT_VALUE 1
/* Defined if QGpgME supports WKD lookup */
#cmakedefine QGPGME_SUPPORTS_WKDLOOKUP 1
/* Defined if QGpgME supports specifying an import filter when importing keys */
#cmakedefine QGPGME_SUPPORTS_IMPORT_WITH_FILTER 1
/* Defined if QGpgME supports setting key origin when importing keys */
#cmakedefine QGPGME_SUPPORTS_IMPORT_WITH_KEY_ORIGIN 1
/* Defined if QGpgME supports the export of secret keys */
#cmakedefine QGPGME_SUPPORTS_SECRET_KEY_EXPORT 1
/* Defined if QGpgME supports the export of secret subkeys */
#cmakedefine QGPGME_SUPPORTS_SECRET_SUBKEY_EXPORT 1
/* Defined if QGpgME supports receiving keys by their key ids */
#cmakedefine QGPGME_SUPPORTS_RECEIVING_KEYS_BY_KEY_ID 1
/* Defined if QGpgME supports revoking own OpenPGP keys */
#cmakedefine QGPGME_SUPPORTS_KEY_REVOCATION 1
/* Defined if QGpgME supports refreshing keys */
#cmakedefine QGPGME_SUPPORTS_KEY_REFRESH 1
/* Defined if QGpgME supports setting the file name of encrypted data */
#cmakedefine QGPGME_SUPPORTS_SET_FILENAME 1
/* Defined if QGpgME supports setting the primary user id of a key */
#cmakedefine QGPGME_SUPPORTS_SET_PRIMARY_UID 1
/* Defined if GpgME++ supports setting the curve when generating ECC card keys */
#cmakedefine GPGMEPP_SUPPORTS_SET_CURVE 1
diff --git a/src/commands/selftestcommand.cpp b/src/commands/selftestcommand.cpp
index e0d6a0a58..71747427b 100644
--- a/src/commands/selftestcommand.cpp
+++ b/src/commands/selftestcommand.cpp
@@ -1,268 +1,264 @@
/* -*- mode: c++; c-basic-offset:4 -*-
commands/selftestcommand.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <config-kleopatra.h>
#include "selftestcommand.h"
#include "command_p.h"
#include <dialogs/selftestdialog.h>
#include "kleopatra_debug.h"
#ifdef Q_OS_WIN
# include <selftest/registrycheck.h>
#endif
#include <selftest/enginecheck.h>
#include <selftest/gpgconfcheck.h>
-#ifdef HAVE_KLEOPATRACLIENT_LIBRARY
-# include <selftest/uiservercheck.h>
-#endif
+#include <selftest/uiservercheck.h>
#include <selftest/gpgagentcheck.h>
#include <selftest/libkleopatrarccheck.h>
#include <selftest/compliancecheck.h>
#include <Libkleo/Stl_Util>
#include <KConfigGroup>
#include <KSharedConfig>
#include <vector>
#include <QGpgME/CryptoConfig>
#include <QGpgME/Protocol>
using namespace Kleo;
using namespace Kleo::Commands;
using namespace Kleo::Dialogs;
static const char *const components[] = {
nullptr, // gpgconf
"gpg",
"gpg-agent",
"scdaemon",
"gpgsm",
"dirmngr",
};
static const unsigned int numComponents = sizeof components / sizeof * components;
class SelfTestCommand::Private : Command::Private
{
friend class ::Kleo::Commands::SelfTestCommand;
SelfTestCommand *q_func() const
{
return static_cast<SelfTestCommand *>(q);
}
public:
explicit Private(SelfTestCommand *qq, KeyListController *c);
~Private() override;
private:
void init();
void ensureDialogCreated()
{
if (dialog) {
return;
}
dialog = new SelfTestDialog;
applyWindowID(dialog);
dialog->setAttribute(Qt::WA_DeleteOnClose);
connect(dialog, &SelfTestDialog::updateRequested, q_func(), [this]() { slotUpdateRequested(); });
connect(dialog, &QDialog::accepted, q_func(), [this]() { slotDialogAccepted(); });
connect(dialog, &QDialog::rejected, q_func(), [this]() { slotDialogRejected(); });
dialog->setRunAtStartUp(runAtStartUp());
dialog->setAutomaticMode(automatic);
}
void ensureDialogShown()
{
ensureDialogCreated();
if (dialog->isVisible()) {
dialog->raise();
} else {
dialog->show();
}
}
bool runAtStartUp() const
{
const KConfigGroup config(KSharedConfig::openConfig(), "Self-Test");
return config.readEntry("run-at-startup", true);
}
void setRunAtStartUp(bool on)
{
KConfigGroup config(KSharedConfig::openConfig(), "Self-Test");
config.writeEntry("run-at-startup", on);
}
void runTests()
{
std::vector< std::shared_ptr<Kleo::SelfTest> > tests;
#if defined(Q_OS_WIN)
qCDebug(KLEOPATRA_LOG) << "Checking Windows Registry...";
tests.push_back(makeGpgProgramRegistryCheckSelfTest());
-#if defined(HAVE_KLEOPATRACLIENT_LIBRARY)
qCDebug(KLEOPATRA_LOG) << "Checking Ui Server connectivity...";
tests.push_back(makeUiServerConnectivitySelfTest());
-#endif
#endif
qCDebug(KLEOPATRA_LOG) << "Checking gpg installation...";
tests.push_back(makeGpgEngineCheckSelfTest());
qCDebug(KLEOPATRA_LOG) << "Checking gpgsm installation...";
tests.push_back(makeGpgSmEngineCheckSelfTest());
qCDebug(KLEOPATRA_LOG) << "Checking gpgconf installation...";
tests.push_back(makeGpgConfEngineCheckSelfTest());
for (unsigned int i = 0; i < numComponents; ++i) {
qCDebug(KLEOPATRA_LOG) << "Checking configuration of:" << components[i];
tests.push_back(makeGpgConfCheckConfigurationSelfTest(components[i]));
}
#ifndef Q_OS_WIN
tests.push_back(makeGpgAgentConnectivitySelfTest());
#endif
tests.push_back(makeDeVSComplianceCheckSelfTest());
tests.push_back(makeLibKleopatraRcSelfTest());
if (!dialog && std::none_of(tests.cbegin(), tests.cend(),
[](const std::shared_ptr<SelfTest> &test) {
return test->failed();
})) {
finished();
return;
}
ensureDialogCreated();
dialog->setTests(tests);
ensureDialogShown();
}
private:
void slotDialogAccepted()
{
setRunAtStartUp(dialog->runAtStartUp());
finished();
}
void slotDialogRejected()
{
if (automatic) {
canceled = true;
Command::Private::canceled();
} else {
slotDialogAccepted();
}
}
void slotUpdateRequested()
{
const auto conf = QGpgME::cryptoConfig();
if (conf) {
conf->clear();
}
runTests();
}
private:
QPointer<SelfTestDialog> dialog;
bool canceled;
bool automatic;
};
SelfTestCommand::Private *SelfTestCommand::d_func()
{
return static_cast<Private *>(d.get());
}
const SelfTestCommand::Private *SelfTestCommand::d_func() const
{
return static_cast<const Private *>(d.get());
}
#define d d_func()
#define q q_func()
SelfTestCommand::Private::Private(SelfTestCommand *qq, KeyListController *c)
: Command::Private(qq, c),
dialog(),
canceled(false),
automatic(false)
{
}
SelfTestCommand::Private::~Private()
{
}
SelfTestCommand::SelfTestCommand(KeyListController *c)
: Command(new Private(this, c))
{
d->init();
}
SelfTestCommand::SelfTestCommand(QAbstractItemView *v, KeyListController *c)
: Command(v, new Private(this, c))
{
d->init();
}
void SelfTestCommand::Private::init()
{
}
SelfTestCommand::~SelfTestCommand() {}
void SelfTestCommand::setAutomaticMode(bool on)
{
d->automatic = on;
if (d->dialog) {
d->dialog->setAutomaticMode(on);
}
}
bool SelfTestCommand::isCanceled() const
{
return d->canceled;
}
void SelfTestCommand::doStart()
{
if (d->automatic) {
if (!d->runAtStartUp()) {
d->finished();
return;
}
} else {
d->ensureDialogCreated();
}
d->runTests();
}
void SelfTestCommand::doCancel()
{
d->canceled = true;
if (d->dialog) {
d->dialog->close();
}
d->dialog = nullptr;
}
#undef d
#undef q
#include "moc_selftestcommand.cpp"
diff --git a/src/kleo-assuan.h b/src/kleo-assuan.h
index 700eb9046..9d9838ba0 100644
--- a/src/kleo-assuan.h
+++ b/src/kleo-assuan.h
@@ -1,42 +1,13 @@
/* -*- mode: c++; c-basic-offset:4 -*-
kleo-assuan.h
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
-#ifdef HAVE_USABLE_ASSUAN
-# include <assuan.h>
-#else
-/*
- * copied from assuan.h:
- */
-
-/* assuan.h - Definitions for the Assuan IPC library
- * SPDX-FileCopyrightText: 2001, 2002, 2003, 2005, 2007 Free Software Foundation Inc.
- *
- * This file is part of Assuan.
- *
- * SPDX-License-Identifier: LGPL-2.1-or-later
- */
-
-#ifdef _WIN32
-typedef void *assuan_fd_t;
-#define ASSUAN_INVALID_FD ((void*)(-1))
-#define ASSUAN_INT2FD(s) ((void *)(s))
-#define ASSUAN_FD2INT(h) ((unsigned int)(h))
-#else
-using assuan_fd_t = int;
-#define ASSUAN_INVALID_FD (-1)
-#define ASSUAN_INT2FD(s) ((s))
-#define ASSUAN_FD2INT(h) ((h))
-#endif
-/*
- * end copied from assuan.h
- */
-#endif
+#include <assuan.h>
diff --git a/src/kleopatra_options.h b/src/kleopatra_options.h
index 488f5bb62..65beae9eb 100644
--- a/src/kleopatra_options.h
+++ b/src/kleopatra_options.h
@@ -1,59 +1,57 @@
/*
kleopatra_options.h
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2015 Bundesamt für Sicherheit in der Informationstechnik
SPDX-FileContributor: Intevation GmbH
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include <config-kleopatra.h>
#include <QCommandLineParser>
#include <KLocalizedString>
static void kleopatra_options(QCommandLineParser *parser)
{
parser->addOptions({
QCommandLineOption({QStringLiteral("openpgp"), QStringLiteral("p")}, i18n("Use OpenPGP for the following operation")),
QCommandLineOption({QStringLiteral("cms"), QStringLiteral("c")}, i18n("Use CMS (X.509, S/MIME) for the following operation")),
-#ifdef HAVE_USABLE_ASSUAN
QCommandLineOption(QStringLiteral("uiserver-socket"), i18n("Location of the socket the ui server is listening on"), QStringLiteral("argument")),
QCommandLineOption(QStringLiteral("daemon"), i18n("Run UI server only, hide main window")),
-#endif
QCommandLineOption({QStringLiteral("import-certificate"), QStringLiteral("i")}, i18n("Import certificate file(s)")),
QCommandLineOption({QStringLiteral("encrypt"), QStringLiteral("e")}, i18n("Encrypt file(s)")),
QCommandLineOption({QStringLiteral("sign"), QStringLiteral("s")}, i18n("Sign file(s)")),
QCommandLineOption({QStringLiteral("sign-encrypt"), QStringLiteral("E")}, i18n("Sign and/or encrypt file(s)")),
QCommandLineOption(QStringLiteral("encrypt-sign"), i18n("Same as --sign-encrypt, do not use")),
QCommandLineOption({QStringLiteral("decrypt"), QStringLiteral("d")}, i18n("Decrypt file(s)")),
QCommandLineOption({QStringLiteral("verify"), QStringLiteral("V")}, i18n("Verify file/signature")),
QCommandLineOption({QStringLiteral("decrypt-verify"), QStringLiteral("D")}, i18n("Decrypt and/or verify file(s)")),
QCommandLineOption(QStringLiteral("search"), i18n("Search for a certificate on a keyserver")),
QCommandLineOption(QStringLiteral("checksum"), i18n("Create or check a checksum file")),
QCommandLineOption({QStringLiteral("query"), QStringLiteral("q")},
i18nc("If a certificate is already known it shows the certificate details dialog. "
"Otherwise it brings up the certificate search dialog.",
"Show details of a local certificate or search for it on a keyserver by fingerprint")),
QCommandLineOption(QStringLiteral("gen-key"), i18n("Create a new key pair or certificate signing request")),
QCommandLineOption(QStringLiteral("parent-windowid"), i18n("Parent Window Id for dialogs"), QStringLiteral("windowId")),
QCommandLineOption(QStringLiteral("config"), i18n("Open the config dialog")),
});
/* Security note: To avoid code execution by shared library injection
* through e.g. -platformpluginpath any external input should be seperated
* by a double dash -- this is why query / search uses positional arguments.
*
* For example on Windows there is an URLhandler for openpgp4fpr:
* be opened with Kleopatra's query function. And while a browser should
* urlescape such a query there might be tricks to inject a quote character
* and as such inject command line options for Kleopatra in an URL. */
parser->addPositionalArgument(QStringLiteral("files"),
i18n("File(s) to process"),
QStringLiteral("-- [files..]"));
parser->addPositionalArgument(QStringLiteral("query"),
i18n("String or Fingerprint for query and search"),
QStringLiteral("-- [query..]"));
}
diff --git a/src/kleopatraapplication.cpp b/src/kleopatraapplication.cpp
index 8f911d4b5..c922e2be1 100644
--- a/src/kleopatraapplication.cpp
+++ b/src/kleopatraapplication.cpp
@@ -1,833 +1,829 @@
/*
kleopatraapplication.cpp
This file is part of Kleopatra, the KDE keymanager
SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB
SPDX-FileCopyrightText: 2016 Bundesamt für Sicherheit in der Informationstechnik
SPDX-FileContributor: Intevation GmbH
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <config-kleopatra.h>
#include "kleopatraapplication.h"
#include "mainwindow.h"
#include "kleopatra_options.h"
#include "systrayicon.h"
#include "settings.h"
#include "smimevalidationpreferences.h"
#include <smartcard/readerstatus.h>
#include <conf/configuredialog.h>
#include <Libkleo/GnuPG>
#include <utils/kdpipeiodevice.h>
#include <utils/log.h>
#include <gpgme++/key.h>
#include <Libkleo/Dn>
#include <Libkleo/FileSystemWatcher>
#include <Libkleo/KeyCache>
#include <Libkleo/KeyFilterManager>
#include <Libkleo/KeyGroupConfig>
#include <Libkleo/Classify>
#include <Libkleo/SystemInfo>
-#ifdef HAVE_USABLE_ASSUAN
-# include <uiserver/uiserver.h>
-#endif
+#include <uiserver/uiserver.h>
#include "commands/signencryptfilescommand.h"
#include "commands/decryptverifyfilescommand.h"
#include "commands/lookupcertificatescommand.h"
#include "commands/checksumcreatefilescommand.h"
#include "commands/checksumverifyfilescommand.h"
#include "commands/detailscommand.h"
#include "commands/newcertificatesigningrequestcommand.h"
#include "commands/newopenpgpcertificatecommand.h"
#include "dialogs/updatenotification.h"
#include <KIconLoader>
#include <KLocalizedString>
#include "kleopatra_debug.h"
#include <KMessageBox>
#include <KWindowSystem>
#include <QDesktopServices>
#include <QFile>
#include <QDir>
#include <QFocusFrame>
#if QT_CONFIG(graphicseffect)
#include <QGraphicsEffect>
#endif
#include <QPointer>
#include <QStyleOption>
#include <QStylePainter>
#include <memory>
#include <KSharedConfig>
#ifdef Q_OS_WIN
#include <QtPlatformHeaders/QWindowsWindowFunctions>
#endif
using namespace Kleo;
using namespace Kleo::Commands;
static void add_resources()
{
KIconLoader::global()->addAppDir(QStringLiteral("libkleopatra"));
KIconLoader::global()->addAppDir(QStringLiteral("kwatchgnupg"));
}
static QList<QByteArray> default_logging_options()
{
QList<QByteArray> result;
result.push_back("io");
return result;
}
namespace
{
class FocusFrame : public QFocusFrame
{
Q_OBJECT
public:
using QFocusFrame::QFocusFrame;
protected:
void paintEvent(QPaintEvent *event) override;
};
static QRect effectiveWidgetRect(const QWidget *w)
{
// based on QWidgetPrivate::effectiveRectFor
#if QT_CONFIG(graphicseffect)
if (auto graphicsEffect = w->graphicsEffect(); graphicsEffect && graphicsEffect->isEnabled())
return graphicsEffect->boundingRectFor(w->rect()).toAlignedRect();
#endif // QT_CONFIG(graphicseffect)
return w->rect();
}
static QRect clipRect(const QWidget *w)
{
// based on QWidgetPrivate::clipRect
if (!w->isVisible()) {
return QRect();
}
QRect r = effectiveWidgetRect(w);
int ox = 0;
int oy = 0;
while (w && w->isVisible() && !w->isWindow() && w->parentWidget()) {
ox -= w->x();
oy -= w->y();
w = w->parentWidget();
r &= QRect(ox, oy, w->width(), w->height());
}
return r;
}
void FocusFrame::paintEvent(QPaintEvent *)
{
if (!widget()) {
return;
}
QStylePainter p(this);
QStyleOptionFocusRect option;
initStyleOption(&option);
const int vmargin = style()->pixelMetric(QStyle::PM_FocusFrameVMargin, &option);
const int hmargin = style()->pixelMetric(QStyle::PM_FocusFrameHMargin, &option);
const QRect rect = clipRect(widget()).adjusted(0, 0, hmargin*2, vmargin*2);
p.setClipRect(rect);
p.drawPrimitive(QStyle::PE_FrameFocusRect, option);
}
}
class KleopatraApplication::Private
{
friend class ::KleopatraApplication;
KleopatraApplication *const q;
public:
explicit Private(KleopatraApplication *qq)
: q(qq)
, ignoreNewInstance(true)
, firstNewInstance(true)
, sysTray(nullptr)
, groupConfig{std::make_shared<KeyGroupConfig>(QStringLiteral("kleopatragroupsrc"))}
{
}
~Private() {
#ifndef QT_NO_SYSTEMTRAYICON
delete sysTray;
#endif
}
void setUpSysTrayIcon()
{
KDAB_SET_OBJECT_NAME(readerStatus);
#ifndef QT_NO_SYSTEMTRAYICON
sysTray = new SysTrayIcon();
sysTray->setFirstCardWithNullPin(readerStatus.firstCardWithNullPin());
sysTray->setAnyCardCanLearnKeys(readerStatus.anyCardCanLearnKeys());
connect(&readerStatus, &SmartCard::ReaderStatus::firstCardWithNullPinChanged,
sysTray, &SysTrayIcon::setFirstCardWithNullPin);
connect(&readerStatus, &SmartCard::ReaderStatus::anyCardCanLearnKeysChanged,
sysTray, &SysTrayIcon::setAnyCardCanLearnKeys);
#endif
}
private:
void connectConfigureDialog()
{
if (configureDialog) {
if (q->mainWindow()) {
connect(configureDialog, SIGNAL(configCommitted()),
q->mainWindow(), SLOT(slotConfigCommitted()));
}
connect(configureDialog, &ConfigureDialog::configCommitted,
q, &KleopatraApplication::configurationChanged);
}
}
void disconnectConfigureDialog()
{
if (configureDialog) {
if (q->mainWindow()) {
disconnect(configureDialog, SIGNAL(configCommitted()),
q->mainWindow(), SLOT(slotConfigCommitted()));
}
disconnect(configureDialog, &ConfigureDialog::configCommitted,
q, &KleopatraApplication::configurationChanged);
}
}
public:
bool ignoreNewInstance;
bool firstNewInstance;
QPointer<FocusFrame> focusFrame;
QPointer<ConfigureDialog> configureDialog;
QPointer<MainWindow> mainWindow;
SmartCard::ReaderStatus readerStatus;
#ifndef QT_NO_SYSTEMTRAYICON
SysTrayIcon *sysTray;
#endif
std::shared_ptr<KeyGroupConfig> groupConfig;
std::shared_ptr<KeyCache> keyCache;
std::shared_ptr<Log> log;
std::shared_ptr<FileSystemWatcher> watcher;
public:
void setupKeyCache()
{
keyCache = KeyCache::mutableInstance();
keyCache->setRefreshInterval(SMimeValidationPreferences{}.refreshInterval());
watcher.reset(new FileSystemWatcher);
watcher->whitelistFiles(gnupgFileWhitelist());
watcher->addPaths(gnupgFolderWhitelist());
watcher->setDelay(1000);
keyCache->addFileSystemWatcher(watcher);
keyCache->setGroupConfig(groupConfig);
keyCache->setGroupsEnabled(Settings().groupsEnabled());
}
void setUpFilterManager()
{
if (!Settings{}.cmsEnabled()) {
KeyFilterManager::instance()->alwaysFilterByProtocol(GpgME::OpenPGP);
}
}
void setupLogging()
{
log = Log::mutableInstance();
const QByteArray envOptions = qgetenv("KLEOPATRA_LOGOPTIONS");
const bool logAll = envOptions.trimmed() == "all";
const QList<QByteArray> options = envOptions.isEmpty() ? default_logging_options() : envOptions.split(',');
const QByteArray dirNative = qgetenv("KLEOPATRA_LOGDIR");
if (dirNative.isEmpty()) {
return;
}
const QString dir = QFile::decodeName(dirNative);
const QString logFileName = QDir(dir).absoluteFilePath(QStringLiteral("kleopatra.log.%1").arg(QCoreApplication::applicationPid()));
std::unique_ptr<QFile> logFile(new QFile(logFileName));
if (!logFile->open(QIODevice::WriteOnly | QIODevice::Append)) {
qCDebug(KLEOPATRA_LOG) << "Could not open file for logging: " << logFileName << "\nLogging disabled";
return;
}
log->setOutputDirectory(dir);
if (logAll || options.contains("io")) {
log->setIOLoggingEnabled(true);
}
qInstallMessageHandler(Log::messageHandler);
-#ifdef HAVE_USABLE_ASSUAN
if (logAll || options.contains("pipeio")) {
KDPipeIODevice::setDebugLevel(KDPipeIODevice::Debug);
}
UiServer::setLogStream(log->logFile());
-#endif
}
void updateFocusFrame(QWidget *focusWidget)
{
if (focusWidget && focusWidget->inherits("QLabel") && focusWidget->window()->testAttribute(Qt::WA_KeyboardFocusChange)) {
if (!focusFrame) {
focusFrame = new FocusFrame{focusWidget};
}
focusFrame->setWidget(focusWidget);
} else if (focusFrame) {
focusFrame->setWidget(nullptr);
}
}
};
KleopatraApplication::KleopatraApplication(int &argc, char *argv[])
: QApplication(argc, argv), d(new Private(this))
{
// disable parent<->child navigation in tree views with left/right arrow keys
// because this interferes with column by column navigation that is required
// for accessibility
setStyleSheet(QStringLiteral("QTreeView { arrow-keys-navigate-into-children: 0; }"));
connect(this, &QApplication::focusChanged,
this, [this](QWidget *, QWidget *now) {
d->updateFocusFrame(now);
});
}
void KleopatraApplication::init()
{
#ifdef Q_OS_WIN
QWindowsWindowFunctions::setWindowActivationBehavior(
QWindowsWindowFunctions::AlwaysActivateWindow);
#endif
const auto blockedUrlSchemes = Settings{}.blockedUrlSchemes();
for (const auto &scheme : blockedUrlSchemes) {
QDesktopServices::setUrlHandler(scheme, this, "blockUrl");
}
add_resources();
DN::setAttributeOrder(Settings{}.attributeOrder());
/* Start the gpg-agent early, this is done explicitly
* because on an empty keyring our keylistings wont start
* the agent. In that case any assuan-connect calls to
* the agent will fail. The requested start via the
* connection is additionally done in case the gpg-agent
* is killed while Kleopatra is running. */
startGpgAgent();
connect(&d->readerStatus, &SmartCard::ReaderStatus::startOfGpgAgentRequested,
this, &KleopatraApplication::startGpgAgent);
d->setupKeyCache();
d->setUpSysTrayIcon();
d->setUpFilterManager();
d->setupLogging();
#ifdef Q_OS_WIN
// Under Linux the Theme is set outside. On Windows we have to do
// it ourself.
if (SystemInfo::isDarkModeActive()) {
QIcon::setThemeName("breeze-dark");
}
#endif
#ifndef QT_NO_SYSTEMTRAYICON
d->sysTray->show();
#endif
setQuitOnLastWindowClosed(false);
KWindowSystem::allowExternalProcessWindowActivation();
}
KleopatraApplication::~KleopatraApplication()
{
// main window doesn't receive "close" signal and cannot
// save settings before app exit
delete d->mainWindow;
// work around kdelibs bug https://bugs.kde.org/show_bug.cgi?id=162514
KSharedConfig::openConfig()->sync();
}
namespace
{
using Func = void (KleopatraApplication::*)(const QStringList &, GpgME::Protocol);
}
void KleopatraApplication::slotActivateRequested(const QStringList &arguments,
const QString &workingDirectory)
{
QCommandLineParser parser;
kleopatra_options(&parser);
QString err;
if (!arguments.isEmpty() && !parser.parse(arguments)) {
err = parser.errorText();
} else if (arguments.isEmpty()) {
// KDBusServices omits the application name if no other
// arguments are provided. In that case the parser prints
// a warning.
parser.parse(QStringList() << QCoreApplication::applicationFilePath());
}
if (err.isEmpty()) {
err = newInstance(parser, workingDirectory);
}
if (!err.isEmpty()) {
KMessageBox::error(nullptr, err.toHtmlEscaped(), i18n("Failed to execute command"));
Q_EMIT setExitValue(1);
return;
}
Q_EMIT setExitValue(0);
}
QString KleopatraApplication::newInstance(const QCommandLineParser &parser,
const QString &workingDirectory)
{
if (d->ignoreNewInstance) {
qCDebug(KLEOPATRA_LOG) << "New instance ignored because of ignoreNewInstance";
return QString();
}
QStringList files;
const QDir cwd = QDir(workingDirectory);
bool queryMode = parser.isSet(QStringLiteral("query")) || parser.isSet(QStringLiteral("search"));
// Query and Search treat positional arguments differently, see below.
if (!queryMode) {
const auto positionalArguments = parser.positionalArguments();
for (const QString &file : positionalArguments) {
// We do not check that file exists here. Better handle
// these errors in the UI.
if (QFileInfo(file).isAbsolute()) {
files << file;
} else {
files << cwd.absoluteFilePath(file);
}
}
}
GpgME::Protocol protocol = GpgME::UnknownProtocol;
if (parser.isSet(QStringLiteral("openpgp"))) {
qCDebug(KLEOPATRA_LOG) << "found OpenPGP";
protocol = GpgME::OpenPGP;
}
if (parser.isSet(QStringLiteral("cms"))) {
qCDebug(KLEOPATRA_LOG) << "found CMS";
if (protocol == GpgME::OpenPGP) {
return i18n("Ambiguous protocol: --openpgp and --cms");
}
protocol = GpgME::CMS;
}
// Check for Parent Window id
WId parentId = 0;
if (parser.isSet(QStringLiteral("parent-windowid"))) {
#ifdef Q_OS_WIN
// WId is not a portable type as it is a pointer type on Windows.
// casting it from an integer is ok though as the values are guaranteed to
// be compatible in the documentation.
parentId = reinterpret_cast<WId>(parser.value(QStringLiteral("parent-windowid")).toUInt());
#else
parentId = parser.value(QStringLiteral("parent-windowid")).toUInt();
#endif
}
// Handle openpgp4fpr URI scheme
QString needle;
if (queryMode) {
needle = parser.positionalArguments().join(QLatin1Char(' '));
}
if (needle.startsWith(QLatin1String("openpgp4fpr:"))) {
needle.remove(0, 12);
}
// Check for --search command.
if (parser.isSet(QStringLiteral("search"))) {
// This is an extra command instead of a combination with the
// similar query to avoid changing the older query commands behavior
// and query's "show details if a certificate exist or search on a
// keyserver" logic is hard to explain and use consistently.
if (needle.isEmpty()) {
return i18n("No search string specified for --search");
}
auto const cmd = new LookupCertificatesCommand(needle, nullptr);
cmd->setParentWId(parentId);
cmd->start();
return QString();
}
// Check for --query command
if (parser.isSet(QStringLiteral("query"))) {
if (needle.isEmpty()) {
return i18n("No fingerprint argument specified for --query");
}
auto cmd = Command::commandForQuery(needle);
cmd->setParentWId(parentId);
cmd->start();
return QString();
}
// Check for --gen-key command
if (parser.isSet(QStringLiteral("gen-key"))) {
if (protocol == GpgME::CMS) {
const Kleo::Settings settings{};
if (settings.cmsEnabled() && settings.cmsCertificateCreationAllowed()) {
auto cmd = new NewCertificateSigningRequestCommand;
cmd->setParentWId(parentId);
cmd->start();
} else {
return i18n("You are not allowed to create S/MIME certificate signing requests.");
}
} else {
auto cmd = new NewOpenPGPCertificateCommand;
cmd->setParentWId(parentId);
cmd->start();
}
return QString();
}
// Check for --config command
if (parser.isSet(QStringLiteral("config"))) {
openConfigDialogWithForeignParent(parentId);
return QString();
}
struct FuncInfo {
QString optionName;
Func func;
};
static const std::vector<FuncInfo> funcMap {
{ QStringLiteral("import-certificate"), &KleopatraApplication::importCertificatesFromFile },
{ QStringLiteral("encrypt"), &KleopatraApplication::encryptFiles },
{ QStringLiteral("sign"), &KleopatraApplication::signFiles },
{ QStringLiteral("encrypt-sign"), &KleopatraApplication::signEncryptFiles },
{ QStringLiteral("sign-encrypt"), &KleopatraApplication::signEncryptFiles },
{ QStringLiteral("decrypt"), &KleopatraApplication::decryptFiles },
{ QStringLiteral("verify"), &KleopatraApplication::verifyFiles },
{ QStringLiteral("decrypt-verify"), &KleopatraApplication::decryptVerifyFiles },
{ QStringLiteral("checksum"), &KleopatraApplication::checksumFiles },
};
QString found;
Func foundFunc = nullptr;
for (const auto &[opt, fn] : funcMap) {
if (parser.isSet(opt) && found.isEmpty()) {
found = opt;
foundFunc = fn;
} else if (parser.isSet(opt)) {
return i18n(R"(Ambiguous commands "%1" and "%2")", found, opt);
}
}
QStringList errors;
if (!found.isEmpty()) {
if (files.empty()) {
return i18n("No files specified for \"%1\" command", found);
}
qCDebug(KLEOPATRA_LOG) << "found" << found;
(this->*foundFunc)(files, protocol);
} else {
if (files.empty()) {
if (!(d->firstNewInstance && isSessionRestored())) {
qCDebug(KLEOPATRA_LOG) << "openOrRaiseMainWindow";
openOrRaiseMainWindow();
}
} else {
for (const QString& fileName : std::as_const(files)) {
QFileInfo fi(fileName);
if (!fi.isReadable()) {
errors << i18n("Cannot read \"%1\"", fileName);
}
}
const QVector<Command *> allCmds = Command::commandsForFiles(files);
for (Command *cmd : allCmds) {
if (parentId) {
cmd->setParentWId(parentId);
} else {
MainWindow *mw = mainWindow();
if (!mw) {
mw = new MainWindow;
mw->setAttribute(Qt::WA_DeleteOnClose);
setMainWindow(mw);
d->connectConfigureDialog();
}
cmd->setParentWidget(mw);
}
cmd->start();
}
}
}
d->firstNewInstance = false;
#ifdef Q_OS_WIN
// On Windows we might be started from the
// explorer in any working directory. E.g.
// a double click on a file. To avoid preventing
// the folder from deletion we set the
// working directory to the users homedir.
QDir::setCurrent(QDir::homePath());
#endif
return errors.join(QLatin1Char('\n'));
}
#ifndef QT_NO_SYSTEMTRAYICON
const SysTrayIcon *KleopatraApplication::sysTrayIcon() const
{
return d->sysTray;
}
SysTrayIcon *KleopatraApplication::sysTrayIcon()
{
return d->sysTray;
}
#endif
const MainWindow *KleopatraApplication::mainWindow() const
{
return d->mainWindow;
}
MainWindow *KleopatraApplication::mainWindow()
{
return d->mainWindow;
}
void KleopatraApplication::setMainWindow(MainWindow *mainWindow)
{
if (mainWindow == d->mainWindow) {
return;
}
d->disconnectConfigureDialog();
d->mainWindow = mainWindow;
#ifndef QT_NO_SYSTEMTRAYICON
d->sysTray->setMainWindow(mainWindow);
#endif
d->connectConfigureDialog();
}
static void open_or_raise(QWidget *w)
{
#ifdef Q_OS_WIN
if (w->isMinimized()) {
qCDebug(KLEOPATRA_LOG) << __func__ << "unminimizing and raising window";
KWindowSystem::unminimizeWindow(w->winId());
w->raise();
} else if (w->isVisible()) {
qCDebug(KLEOPATRA_LOG) << __func__ << "raising window";
w->raise();
#else
if (w->isVisible()) {
qCDebug(KLEOPATRA_LOG) << __func__ << "activating window";
KWindowSystem::updateStartupId(w->windowHandle());
KWindowSystem::activateWindow(w->windowHandle());
#endif
} else {
qCDebug(KLEOPATRA_LOG) << __func__ << "showing window";
w->show();
}
}
void KleopatraApplication::toggleMainWindowVisibility()
{
if (mainWindow()) {
mainWindow()->setVisible(!mainWindow()->isVisible());
} else {
openOrRaiseMainWindow();
}
}
void KleopatraApplication::restoreMainWindow()
{
qCDebug(KLEOPATRA_LOG) << "restoring main window";
// Sanity checks
if (!isSessionRestored()) {
qCDebug(KLEOPATRA_LOG) << "Not in session restore";
return;
}
if (mainWindow()) {
qCDebug(KLEOPATRA_LOG) << "Already have main window";
return;
}
auto mw = new MainWindow;
if (KMainWindow::canBeRestored(1)) {
// restore to hidden state, Mainwindow::readProperties() will
// restore saved visibility.
mw->restore(1, false);
}
mw->setAttribute(Qt::WA_DeleteOnClose);
setMainWindow(mw);
d->connectConfigureDialog();
}
void KleopatraApplication::openOrRaiseMainWindow()
{
MainWindow *mw = mainWindow();
if (!mw) {
mw = new MainWindow;
mw->setAttribute(Qt::WA_DeleteOnClose);
setMainWindow(mw);
d->connectConfigureDialog();
}
open_or_raise(mw);
UpdateNotification::checkUpdate(mw);
}
void KleopatraApplication::openConfigDialogWithForeignParent(WId parentWId)
{
if (!d->configureDialog) {
d->configureDialog = new ConfigureDialog;
d->configureDialog->setAttribute(Qt::WA_DeleteOnClose);
d->connectConfigureDialog();
}
// This is similar to what the commands do.
if (parentWId) {
if (QWidget *pw = QWidget::find(parentWId)) {
d->configureDialog->setParent(pw, d->configureDialog->windowFlags());
} else {
d->configureDialog->setAttribute(Qt::WA_NativeWindow, true);
KWindowSystem::setMainWindow(d->configureDialog->windowHandle(), parentWId);
}
}
open_or_raise(d->configureDialog);
// If we have a parent we want to raise over it.
if (parentWId) {
d->configureDialog->raise();
}
}
void KleopatraApplication::openOrRaiseConfigDialog()
{
openConfigDialogWithForeignParent(0);
}
#ifndef QT_NO_SYSTEMTRAYICON
void KleopatraApplication::startMonitoringSmartCard()
{
d->readerStatus.startMonitoring();
}
#endif // QT_NO_SYSTEMTRAYICON
void KleopatraApplication::importCertificatesFromFile(const QStringList &files, GpgME::Protocol /*proto*/)
{
openOrRaiseMainWindow();
if (!files.empty()) {
mainWindow()->importCertificatesFromFile(files);
}
}
void KleopatraApplication::encryptFiles(const QStringList &files, GpgME::Protocol proto)
{
auto const cmd = new SignEncryptFilesCommand(files, nullptr);
cmd->setEncryptionPolicy(Force);
cmd->setSigningPolicy(Allow);
if (proto != GpgME::UnknownProtocol) {
cmd->setProtocol(proto);
}
cmd->start();
}
void KleopatraApplication::signFiles(const QStringList &files, GpgME::Protocol proto)
{
auto const cmd = new SignEncryptFilesCommand(files, nullptr);
cmd->setSigningPolicy(Force);
cmd->setEncryptionPolicy(Deny);
if (proto != GpgME::UnknownProtocol) {
cmd->setProtocol(proto);
}
cmd->start();
}
void KleopatraApplication::signEncryptFiles(const QStringList &files, GpgME::Protocol proto)
{
auto const cmd = new SignEncryptFilesCommand(files, nullptr);
if (proto != GpgME::UnknownProtocol) {
cmd->setProtocol(proto);
}
cmd->start();
}
void KleopatraApplication::decryptFiles(const QStringList &files, GpgME::Protocol /*proto*/)
{
auto const cmd = new DecryptVerifyFilesCommand(files, nullptr);
cmd->setOperation(Decrypt);
cmd->start();
}
void KleopatraApplication::verifyFiles(const QStringList &files, GpgME::Protocol /*proto*/)
{
auto const cmd = new DecryptVerifyFilesCommand(files, nullptr);
cmd->setOperation(Verify);
cmd->start();
}
void KleopatraApplication::decryptVerifyFiles(const QStringList &files, GpgME::Protocol /*proto*/)
{
auto const cmd = new DecryptVerifyFilesCommand(files, nullptr);
cmd->start();
}
void KleopatraApplication::checksumFiles(const QStringList &files, GpgME::Protocol /*proto*/)
{
QStringList verifyFiles, createFiles;
for (const QString &file : files) {
if (isChecksumFile(file)) {
verifyFiles << file;
} else {
createFiles << file;
}
}
if (!verifyFiles.isEmpty()) {
auto const cmd = new ChecksumVerifyFilesCommand(verifyFiles, nullptr);
cmd->start();
}
if (!createFiles.isEmpty()) {
auto const cmd = new ChecksumCreateFilesCommand(createFiles, nullptr);
cmd->start();
}
}
void KleopatraApplication::setIgnoreNewInstance(bool ignore)
{
d->ignoreNewInstance = ignore;
}
bool KleopatraApplication::ignoreNewInstance() const
{
return d->ignoreNewInstance;
}
void KleopatraApplication::blockUrl(const QUrl &url)
{
qCDebug(KLEOPATRA_LOG) << "Blocking URL" << url;
KMessageBox::error(mainWindow(),i18n ("Opening an external link is administratively prohibited."),
i18n ("Prohibited"));
}
void KleopatraApplication::startGpgAgent()
{
Kleo::launchGpgAgent();
}
#include "kleopatraapplication.moc"
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 182921fa2..cbb7d3aaf 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -1,79 +1,76 @@
# SPDX-FileCopyrightText: none
# SPDX-License-Identifier: BSD-3-Clause
add_subdirectory(gnupg_home)
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR})
include_directories(
${CMAKE_SOURCE_DIR}/src/
${CMAKE_BINARY_DIR}/src/
${GPGME_INCLUDES}
)
########### next target ###############
set(test_verify_SRCS test_verify.cpp)
add_definitions(-DKLEO_TEST_GNUPGHOME="${CMAKE_CURRENT_BINARY_DIR}/gnupg_home")
add_definitions(-DKLEO_TEST_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}")
add_executable(test_verify ${test_verify_SRCS})
add_test(NAME test_verify COMMAND test_verify)
ecm_mark_as_test(test_verify)
target_link_libraries(test_verify
KF5::Libkleo
Qt::Test
KF5::CoreAddons
KF5::I18n
Qt::Widgets
)
if (QT_MAJOR_VERSION STREQUAL "6")
target_link_libraries(test_verify QGpgmeQt6)
else()
target_link_libraries(test_verify QGpgme)
endif()
########### next target ###############
-if(USABLE_ASSUAN_FOUND)
-
# this doesn't yet work on Windows
add_definitions(-DGPG_ERR_SOURCE_DEFAULT=GPG_ERR_SOURCE_USER_2)
set(test_uiserver_SRCS test_uiserver.cpp ${CMAKE_SOURCE_DIR}/src/utils/wsastarter.cpp)
#FIXME: omitting TEST makes test_uiserver print output again on a Win32 console;
# find a better fix for this issue
if(WIN32)
add_executable(test_uiserver ${test_uiserver_SRCS})
else()
add_executable(test_uiserver ${test_uiserver_SRCS})
endif()
target_link_libraries(test_uiserver KF5::I18n)
target_link_libraries(test_uiserver
KF5::Libkleo
${ASSUAN2_LIBRARIES}
)
if(WIN32)
target_link_libraries(test_uiserver
${ASSUAN_VANILLA_LIBRARIES}
ws2_32
)
else()
target_link_libraries(test_uiserver
${ASSUAN_PTHREAD_LIBRARIES}
)
endif()
if (QT_MAJOR_VERSION STREQUAL "6")
target_link_libraries(test_uiserver QGpgmeQt6)
else()
target_link_libraries(test_uiserver QGpgme)
endif()
-endif()

File Metadata

Mime Type
text/x-diff
Expires
Sat, Jan 3, 11:44 PM (22 h, 28 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
2f/af/63a85a33f38436f9f96e772710ff

Event Timeline