Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F34381684
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
43 KB
Subscribers
None
View Options
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
Details
Attached
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
Attached To
rKLEOPATRA Kleopatra
Event Timeline
Log In to Comment