kleopatraapplication.cpp 18.9 KB
Newer Older
1 2 3 4
/*
    kleopatraapplication.cpp

    This file is part of Kleopatra, the KDE keymanager
5 6 7 8 9 10
    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
11 12 13 14 15 16
*/

#include <config-kleopatra.h>

#include "kleopatraapplication.h"

17
#include "mainwindow.h"
18
#include "kleopatra_options.h"
Marc Mutz's avatar
Marc Mutz committed
19 20
#include "systrayicon.h"
#include <smartcard/readerstatus.h>
21
#include <conf/configuredialog.h>
22

23
#include <Libkleo/GnuPG>
24 25 26
#include <utils/kdpipeiodevice.h>
#include <utils/log.h>

27
#include <gpgme++/key.h>
28 29 30

#include <Libkleo/FileSystemWatcher>
#include <Libkleo/KeyCache>
31
#include <Libkleo/Classify>
32 33 34 35 36

#ifdef HAVE_USABLE_ASSUAN
# include <uiserver/uiserver.h>
#endif

37 38 39 40
#include "commands/signencryptfilescommand.h"
#include "commands/decryptverifyfilescommand.h"
#include "commands/lookupcertificatescommand.h"
#include "commands/checksumcreatefilescommand.h"
41
#include "commands/checksumverifyfilescommand.h"
42
#include "commands/detailscommand.h"
43
#include "commands/newcertificatecommand.h"
44

45 46
#include "dialogs/updatenotification.h"

47
#include <KIconLoader>
Laurent Montel's avatar
Laurent Montel committed
48
#include <KLocalizedString>
Laurent Montel's avatar
Laurent Montel committed
49
#include "kleopatra_debug.h"
50
#include <KMessageBox>
51
#include <KWindowSystem>
52

53
#include <QFile>
Marc Mutz's avatar
Marc Mutz committed
54
#include <QDir>
55
#include <QPointer>
56 57

#include <memory>
58
#include <KSharedConfig>
59 60

using namespace Kleo;
61
using namespace Kleo::Commands;
62

Laurent Montel's avatar
Laurent Montel committed
63 64
static void add_resources()
{
Laurent Montel's avatar
Laurent Montel committed
65 66
    KIconLoader::global()->addAppDir(QStringLiteral("libkleopatra"));
    KIconLoader::global()->addAppDir(QStringLiteral("kwatchgnupg"));
67 68
}

Laurent Montel's avatar
Laurent Montel committed
69 70
static QList<QByteArray> default_logging_options()
{
71
    QList<QByteArray> result;
Laurent Montel's avatar
Laurent Montel committed
72
    result.push_back("io");
73 74 75
    return result;
}

Laurent Montel's avatar
Laurent Montel committed
76 77
class KleopatraApplication::Private
{
78
    friend class ::KleopatraApplication;
Laurent Montel's avatar
Laurent Montel committed
79
    KleopatraApplication *const q;
80
public:
Laurent Montel's avatar
Laurent Montel committed
81 82
    explicit Private(KleopatraApplication *qq)
        : q(qq),
83
          ignoreNewInstance(true),
84
          firstNewInstance(true),
85
          sysTray(nullptr)
86 87 88
    {
    }
    ~Private() {
Laurent Montel's avatar
Laurent Montel committed
89
#ifndef QT_NO_SYSTEMTRAYICON
90
        delete sysTray;
Laurent Montel's avatar
Laurent Montel committed
91
#endif
92 93
    }
    void init()
Marc Mutz's avatar
Marc Mutz committed
94
    {
Laurent Montel's avatar
Laurent Montel committed
95
        KDAB_SET_OBJECT_NAME(readerStatus);
96
#ifndef QT_NO_SYSTEMTRAYICON
97
        sysTray = new SysTrayIcon();
98
        sysTray->setFirstCardWithNullPin(readerStatus.firstCardWithNullPin());
99
        sysTray->setAnyCardCanLearnKeys(readerStatus.anyCardCanLearnKeys());
Marc Mutz's avatar
Marc Mutz committed
100

101 102
        connect(&readerStatus, &SmartCard::ReaderStatus::firstCardWithNullPinChanged,
                sysTray, &SysTrayIcon::setFirstCardWithNullPin);
Laurent Montel's avatar
Laurent Montel committed
103
        connect(&readerStatus, &SmartCard::ReaderStatus::anyCardCanLearnKeysChanged,
104
                sysTray, &SysTrayIcon::setAnyCardCanLearnKeys);
105
#endif
Marc Mutz's avatar
Marc Mutz committed
106
    }
107

108
private:
Laurent Montel's avatar
Laurent Montel committed
109 110 111 112 113
    void connectConfigureDialog()
    {
        if (configureDialog && q->mainWindow()) {
            connect(configureDialog, SIGNAL(configCommitted()), q->mainWindow(), SLOT(slotConfigCommitted()));
        }
114
    }
Laurent Montel's avatar
Laurent Montel committed
115 116 117 118 119
    void disconnectConfigureDialog()
    {
        if (configureDialog && q->mainWindow()) {
            disconnect(configureDialog, SIGNAL(configCommitted()), q->mainWindow(), SLOT(slotConfigCommitted()));
        }
120 121
    }

122 123
public:
    bool ignoreNewInstance;
124
    bool firstNewInstance;
125
    QPointer<ConfigureDialog> configureDialog;
126
    QPointer<MainWindow> mainWindow;
Marc Mutz's avatar
Marc Mutz committed
127
    SmartCard::ReaderStatus readerStatus;
128
#ifndef QT_NO_SYSTEMTRAYICON
129
    SysTrayIcon *sysTray;
130
#endif
131
    std::shared_ptr<KeyCache> keyCache;
132
    std::shared_ptr<Log> log;
133
    std::shared_ptr<FileSystemWatcher> watcher;
134 135

public:
Laurent Montel's avatar
Laurent Montel committed
136 137
    void setupKeyCache()
    {
138
        keyCache = KeyCache::mutableInstance();
Laurent Montel's avatar
Laurent Montel committed
139
        watcher.reset(new FileSystemWatcher);
Marc Mutz's avatar
Marc Mutz committed
140

141
        watcher->whitelistFiles(gnupgFileWhitelist());
Laurent Montel's avatar
Laurent Montel committed
142 143 144
        watcher->addPath(gnupgHomeDirectory());
        watcher->setDelay(1000);
        keyCache->addFileSystemWatcher(watcher);
145
        keyCache->setGroupsConfig(QStringLiteral("kleopatragroupsrc"));
146 147
    }

Laurent Montel's avatar
Laurent Montel committed
148 149
    void setupLogging()
    {
150 151
        log = Log::mutableInstance();

Laurent Montel's avatar
Laurent Montel committed
152
        const QByteArray envOptions = qgetenv("KLEOPATRA_LOGOPTIONS");
153
        const bool logAll = envOptions.trimmed() == "all";
Laurent Montel's avatar
Laurent Montel committed
154
        const QList<QByteArray> options = envOptions.isEmpty() ? default_logging_options() : envOptions.split(',');
Marc Mutz's avatar
Marc Mutz committed
155

Laurent Montel's avatar
Laurent Montel committed
156 157
        const QByteArray dirNative = qgetenv("KLEOPATRA_LOGDIR");
        if (dirNative.isEmpty()) {
158
            return;
Laurent Montel's avatar
Laurent Montel committed
159 160
        }
        const QString dir = QFile::decodeName(dirNative);
161
        const QString logFileName = QDir(dir).absoluteFilePath(QStringLiteral("kleopatra.log.%1").arg(QCoreApplication::applicationPid()));
Laurent Montel's avatar
Laurent Montel committed
162
        std::unique_ptr<QFile> logFile(new QFile(logFileName));
Laurent Montel's avatar
Laurent Montel committed
163
        if (!logFile->open(QIODevice::WriteOnly | QIODevice::Append)) {
Laurent Montel's avatar
Laurent Montel committed
164
            qCDebug(KLEOPATRA_LOG) << "Could not open file for logging: " << logFileName << "\nLogging disabled";
165 166
            return;
        }
Marc Mutz's avatar
Marc Mutz committed
167

Laurent Montel's avatar
Laurent Montel committed
168 169 170 171
        log->setOutputDirectory(dir);
        if (logAll || options.contains("io")) {
            log->setIOLoggingEnabled(true);
        }
172
        qInstallMessageHandler(Log::messageHandler);
Marc Mutz's avatar
Marc Mutz committed
173

174
#ifdef HAVE_USABLE_ASSUAN
Laurent Montel's avatar
Laurent Montel committed
175 176 177 178
        if (logAll || options.contains("pipeio")) {
            KDPipeIODevice::setDebugLevel(KDPipeIODevice::Debug);
        }
        UiServer::setLogStream(log->logFile());
179 180 181 182 183
#endif

    }
};

184 185
KleopatraApplication::KleopatraApplication(int &argc, char *argv[])
    : QApplication(argc, argv), d(new Private(this))
186
{
187 188 189 190 191
}

void KleopatraApplication::init()
{
    d->init();
192
    add_resources();
193 194
    d->setupKeyCache();
    d->setupLogging();
195
#ifndef QT_NO_SYSTEMTRAYICON
196
    d->sysTray->show();
197
#endif
Laurent Montel's avatar
Laurent Montel committed
198
    setQuitOnLastWindowClosed(false);
199
    KWindowSystem::allowExternalProcessWindowActivation();
200 201
}

Laurent Montel's avatar
Laurent Montel committed
202 203
KleopatraApplication::~KleopatraApplication()
{
Andrey Legayev's avatar
Andrey Legayev committed
204 205 206 207
    // main window doesn't receive "close" signal and cannot
    // save settings before app exit
    delete d->mainWindow;

208
    // work around kdelibs bug https://bugs.kde.org/show_bug.cgi?id=162514
209
    KSharedConfig::openConfig()->sync();
210 211
}

212
namespace
Laurent Montel's avatar
Laurent Montel committed
213
{
214
typedef void (KleopatraApplication::*Func)(const QStringList &, GpgME::Protocol);
215 216
}

Laurent Montel's avatar
Laurent Montel committed
217 218
void KleopatraApplication::slotActivateRequested(const QStringList &arguments,
        const QString &workingDirectory)
Laurent Montel's avatar
Laurent Montel committed
219
{
220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
    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()) {
Laurent Montel's avatar
Laurent Montel committed
238
        KMessageBox::sorry(nullptr, err.toHtmlEscaped(), i18n("Failed to execute command"));
Laurent Montel's avatar
Laurent Montel committed
239
        Q_EMIT setExitValue(1);
240
        return;
241
    }
242
    Q_EMIT setExitValue(0);
243 244
}

Laurent Montel's avatar
Laurent Montel committed
245 246
QString KleopatraApplication::newInstance(const QCommandLineParser &parser,
        const QString &workingDirectory)
Laurent Montel's avatar
Laurent Montel committed
247 248
{
    if (d->ignoreNewInstance) {
249 250
        qCDebug(KLEOPATRA_LOG) << "New instance ignored because of ignoreNewInstance";
        return QString();
Laurent Montel's avatar
Laurent Montel committed
251
    }
252

253 254
    QStringList files;
    const QDir cwd = QDir(workingDirectory);
Andre Heinecke's avatar
Andre Heinecke committed
255 256 257 258
    bool queryMode = parser.isSet(QStringLiteral("query")) || parser.isSet(QStringLiteral("search"));

    // Query and Search treat positional arguments differently, see below.
    if (!queryMode) {
Laurent Montel's avatar
Laurent Montel committed
259 260
        const auto positionalArguments = parser.positionalArguments();
        for (const QString &file : positionalArguments) {
Andre Heinecke's avatar
Andre Heinecke committed
261 262 263 264 265 266 267
            // 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);
            }
268 269
        }
    }
270

271
    GpgME::Protocol protocol = GpgME::UnknownProtocol;
272

273
    if (parser.isSet(QStringLiteral("openpgp"))) {
Laurent Montel's avatar
Laurent Montel committed
274
        qCDebug(KLEOPATRA_LOG) << "found OpenPGP";
275
        protocol = GpgME::OpenPGP;
Laurent Montel's avatar
Laurent Montel committed
276
    }
277

278 279 280
    if (parser.isSet(QStringLiteral("cms"))) {
        qCDebug(KLEOPATRA_LOG) << "found CMS";
        if (protocol == GpgME::OpenPGP) {
Laurent Montel's avatar
Laurent Montel committed
281
            return i18n("Ambiguous protocol: --openpgp and --cms");
282 283
        }
        protocol = GpgME::CMS;
284 285
    }

286 287 288 289 290
    // 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.
291
        // casting it from an integer is ok though as the values are guaranteed to
292 293 294 295 296 297 298
        // be compatible in the documentation.
        parentId = reinterpret_cast<WId>(parser.value(QStringLiteral("parent-windowid")).toUInt());
#else
        parentId = parser.value(QStringLiteral("parent-windowid")).toUInt();
#endif
    }

299 300
    // Handle openpgp4fpr URI scheme
    QString needle;
Andre Heinecke's avatar
Andre Heinecke committed
301 302
    if (queryMode) {
        needle = parser.positionalArguments().join(QLatin1Char(' '));
303
    }
Laurent Montel's avatar
Laurent Montel committed
304
    if (needle.startsWith(QLatin1String("openpgp4fpr:"))) {
305 306 307
        needle.remove(0, 12);
    }

308 309 310 311 312 313 314 315 316
    // 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");
        }
Laurent Montel's avatar
Laurent Montel committed
317
        LookupCertificatesCommand *const cmd = new LookupCertificatesCommand(needle, nullptr);
318 319 320 321 322
        cmd->setParentWId(parentId);
        cmd->start();
        return QString();
    }

323
    // Check for --query command
324
    if (parser.isSet(QStringLiteral("query"))) {
325
        if (needle.isEmpty()) {
326
            return i18n("No fingerprint argument specified for --query");
327
        }
328
        auto cmd = Command::commandForQuery(needle);
329 330
        cmd->setParentWId(parentId);
        cmd->start();
331
        return QString();
332 333
    }

334
    // Check for --gen-key command
Laurent Montel's avatar
Laurent Montel committed
335
    if (parser.isSet(QStringLiteral("gen-key"))) {
Laurent Montel's avatar
Laurent Montel committed
336
        auto cmd = new NewCertificateCommand(nullptr);
337 338 339 340 341 342
        cmd->setParentWId(parentId);
        cmd->setProtocol(protocol);
        cmd->start();
        return QString();
    }

343
    // Check for --config command
Laurent Montel's avatar
Laurent Montel committed
344
    if (parser.isSet(QStringLiteral("config"))) {
345 346 347 348
        openConfigDialogWithForeignParent(parentId);
        return QString();
    }

349 350 351 352 353 354 355 356
    static const QMap<QString, Func> 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 },
357 358
        { QStringLiteral("decrypt-verify"), &KleopatraApplication::decryptVerifyFiles },
        { QStringLiteral("checksum"), &KleopatraApplication::checksumFiles },
359 360
    };

361 362 363 364 365 366
    QString found;
    Q_FOREACH (const QString &opt, funcMap.keys()) {
        if (parser.isSet(opt) && found.isEmpty()) {
            found = opt;
        } else if (parser.isSet(opt)) {
            return i18n("Ambiguous commands \"%1\" and \"%2\"", found, opt);
367
        }
368 369
    }

370
    QStringList errors;
371
    if (!found.isEmpty()) {
Laurent Montel's avatar
Laurent Montel committed
372
        if (files.empty()) {
Yuri Chornoivan's avatar
Yuri Chornoivan committed
373
            return i18n("No files specified for \"%1\" command", found);
374
        }
375 376
        qCDebug(KLEOPATRA_LOG) << "found" << found;
        (this->*funcMap.value(found))(files, protocol);
377
    } else {
Laurent Montel's avatar
Laurent Montel committed
378
        if (files.empty()) {
379
            if (!(d->firstNewInstance && isSessionRestored())) {
Laurent Montel's avatar
Laurent Montel committed
380
                qCDebug(KLEOPATRA_LOG) << "openOrRaiseMainWindow";
Lindsay Mathieson's avatar
Lindsay Mathieson committed
381 382
                openOrRaiseMainWindow();
            }
383
        } else {
Laurent Montel's avatar
Laurent Montel committed
384
            for (const QString& fileName : qAsConst(files)) {
385 386
                QFileInfo fi(fileName);
                if (!fi.isReadable()) {
387
                    errors << i18n("Cannot read \"%1\"", fileName);
388 389
                }
            }
390
            Q_FOREACH (Command *cmd, Command::commandsForFiles(files)) {
391 392 393 394 395 396 397 398 399 400 401 402
                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);
                }
403 404
                cmd->start();
            }
405 406
        }
    }
407
    d->firstNewInstance = false;
408

409 410 411 412 413 414 415 416 417
#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

Laurent Montel's avatar
Laurent Montel committed
418
    return errors.join(QLatin1Char('\n'));
419 420
}

421
#ifndef QT_NO_SYSTEMTRAYICON
Laurent Montel's avatar
Laurent Montel committed
422 423
const SysTrayIcon *KleopatraApplication::sysTrayIcon() const
{
424
    return d->sysTray;
425 426
}

Laurent Montel's avatar
Laurent Montel committed
427 428
SysTrayIcon *KleopatraApplication::sysTrayIcon()
{
429
    return d->sysTray;
430
}
431
#endif
432

Laurent Montel's avatar
Laurent Montel committed
433 434
const MainWindow *KleopatraApplication::mainWindow() const
{
435
    return d->mainWindow;
436 437
}

Laurent Montel's avatar
Laurent Montel committed
438 439
MainWindow *KleopatraApplication::mainWindow()
{
440
    return d->mainWindow;
441 442
}

Laurent Montel's avatar
Laurent Montel committed
443 444 445
void KleopatraApplication::setMainWindow(MainWindow *mainWindow)
{
    if (mainWindow == d->mainWindow) {
446
        return;
Laurent Montel's avatar
Laurent Montel committed
447
    }
448 449 450 451 452

    d->disconnectConfigureDialog();

    d->mainWindow = mainWindow;
#ifndef QT_NO_SYSTEMTRAYICON
453
    d->sysTray->setMainWindow(mainWindow);
454 455
#endif

456 457 458
    d->connectConfigureDialog();
}

Laurent Montel's avatar
Laurent Montel committed
459 460 461 462
static void open_or_raise(QWidget *w)
{
    if (w->isMinimized()) {
        KWindowSystem::unminimizeWindow(w->winId());
463
        w->raise();
Laurent Montel's avatar
Laurent Montel committed
464
    } else if (w->isVisible()) {
465 466 467 468 469
        w->raise();
    } else {
        w->show();
    }
}
470

Lindsay Mathieson's avatar
Lindsay Mathieson committed
471 472
void KleopatraApplication::toggleMainWindowVisibility()
{
Laurent Montel's avatar
Laurent Montel committed
473 474
    if (mainWindow()) {
        mainWindow()->setVisible(!mainWindow()->isVisible());
Lindsay Mathieson's avatar
Lindsay Mathieson committed
475 476 477 478 479
    } else {
        openOrRaiseMainWindow();
    }
}

Laurent Montel's avatar
Laurent Montel committed
480 481
void KleopatraApplication::restoreMainWindow()
{
Laurent Montel's avatar
Laurent Montel committed
482
    qCDebug(KLEOPATRA_LOG) << "restoring main window";
Lindsay Mathieson's avatar
Lindsay Mathieson committed
483 484

    // Sanity checks
Laurent Montel's avatar
Laurent Montel committed
485
    if (!isSessionRestored()) {
Laurent Montel's avatar
Laurent Montel committed
486
        qCDebug(KLEOPATRA_LOG) << "Not in session restore";
Lindsay Mathieson's avatar
Lindsay Mathieson committed
487 488 489
        return;
    }

Laurent Montel's avatar
Laurent Montel committed
490
    if (mainWindow()) {
Laurent Montel's avatar
Laurent Montel committed
491
        qCDebug(KLEOPATRA_LOG) << "Already have main window";
Lindsay Mathieson's avatar
Lindsay Mathieson committed
492 493 494
        return;
    }

Laurent Montel's avatar
Laurent Montel committed
495 496
    MainWindow *mw = new MainWindow;
    if (KMainWindow::canBeRestored(1)) {
Lindsay Mathieson's avatar
Lindsay Mathieson committed
497 498
        // restore to hidden state, Mainwindow::readProperties() will
        // restore saved visibility.
Laurent Montel's avatar
Laurent Montel committed
499
        mw->restore(1, false);
Lindsay Mathieson's avatar
Lindsay Mathieson committed
500 501
    }

Laurent Montel's avatar
Laurent Montel committed
502 503
    mw->setAttribute(Qt::WA_DeleteOnClose);
    setMainWindow(mw);
Lindsay Mathieson's avatar
Lindsay Mathieson committed
504 505 506 507
    d->connectConfigureDialog();

}

Laurent Montel's avatar
Laurent Montel committed
508 509 510 511
void KleopatraApplication::openOrRaiseMainWindow()
{
    MainWindow *mw = mainWindow();
    if (!mw) {
512
        mw = new MainWindow;
Laurent Montel's avatar
Laurent Montel committed
513 514
        mw->setAttribute(Qt::WA_DeleteOnClose);
        setMainWindow(mw);
515 516
        d->connectConfigureDialog();
    }
Laurent Montel's avatar
Laurent Montel committed
517
    open_or_raise(mw);
518
    UpdateNotification::checkUpdate(mw);
519 520
}

521
void KleopatraApplication::openConfigDialogWithForeignParent(WId parentWId)
Laurent Montel's avatar
Laurent Montel committed
522 523
{
    if (!d->configureDialog) {
524
        d->configureDialog = new ConfigureDialog;
Laurent Montel's avatar
Laurent Montel committed
525
        d->configureDialog->setAttribute(Qt::WA_DeleteOnClose);
526 527
        d->connectConfigureDialog();
    }
528 529 530 531 532 533

    // This is similar to what the commands do.
    if (parentWId) {
        if (QWidget *pw = QWidget::find(parentWId)) {
            d->configureDialog->setParent(pw, d->configureDialog->windowFlags());
        } else {
534
            d->configureDialog->setAttribute(Qt::WA_NativeWindow, true);
535
            KWindowSystem::setMainWindow(d->configureDialog->windowHandle(), parentWId);
536 537 538
        }
    }

Laurent Montel's avatar
Laurent Montel committed
539
    open_or_raise(d->configureDialog);
540 541 542 543 544 545 546 547 548 549

    // If we have a parent we want to raise over it.
    if (parentWId) {
        d->configureDialog->raise();
    }
}

void KleopatraApplication::openOrRaiseConfigDialog()
{
    openConfigDialogWithForeignParent(0);
Marc Mutz's avatar
Marc Mutz committed
550 551
}

552
#ifndef QT_NO_SYSTEMTRAYICON
Laurent Montel's avatar
Laurent Montel committed
553 554
void KleopatraApplication::startMonitoringSmartCard()
{
Thomas McGuire's avatar
Thomas McGuire committed
555 556
    d->readerStatus.startMonitoring();
}
557
#endif // QT_NO_SYSTEMTRAYICON
Thomas McGuire's avatar
Thomas McGuire committed
558

Laurent Montel's avatar
Laurent Montel committed
559 560
void KleopatraApplication::importCertificatesFromFile(const QStringList &files, GpgME::Protocol /*proto*/)
{
561
    openOrRaiseMainWindow();
Laurent Montel's avatar
Laurent Montel committed
562
    if (!files.empty()) {
563
        mainWindow()->importCertificatesFromFile(files);
Laurent Montel's avatar
Laurent Montel committed
564
    }
565 566
}

Laurent Montel's avatar
Laurent Montel committed
567 568
void KleopatraApplication::encryptFiles(const QStringList &files, GpgME::Protocol proto)
{
Laurent Montel's avatar
Laurent Montel committed
569
    SignEncryptFilesCommand *const cmd = new SignEncryptFilesCommand(files, nullptr);
Laurent Montel's avatar
Laurent Montel committed
570 571 572 573 574
    cmd->setEncryptionPolicy(Force);
    cmd->setSigningPolicy(Allow);
    if (proto != GpgME::UnknownProtocol) {
        cmd->setProtocol(proto);
    }
Marc Mutz's avatar
Marc Mutz committed
575
    cmd->start();
576 577
}

Laurent Montel's avatar
Laurent Montel committed
578 579
void KleopatraApplication::signFiles(const QStringList &files, GpgME::Protocol proto)
{
Laurent Montel's avatar
Laurent Montel committed
580
    SignEncryptFilesCommand *const cmd = new SignEncryptFilesCommand(files, nullptr);
Laurent Montel's avatar
Laurent Montel committed
581 582 583 584 585
    cmd->setSigningPolicy(Force);
    cmd->setEncryptionPolicy(Deny);
    if (proto != GpgME::UnknownProtocol) {
        cmd->setProtocol(proto);
    }
Marc Mutz's avatar
Marc Mutz committed
586
    cmd->start();
587 588
}

Laurent Montel's avatar
Laurent Montel committed
589 590
void KleopatraApplication::signEncryptFiles(const QStringList &files, GpgME::Protocol proto)
{
Laurent Montel's avatar
Laurent Montel committed
591
    SignEncryptFilesCommand *const cmd = new SignEncryptFilesCommand(files, nullptr);
Laurent Montel's avatar
Laurent Montel committed
592 593 594
    if (proto != GpgME::UnknownProtocol) {
        cmd->setProtocol(proto);
    }
595
    cmd->start();
596 597
}

Laurent Montel's avatar
Laurent Montel committed
598 599
void KleopatraApplication::decryptFiles(const QStringList &files, GpgME::Protocol /*proto*/)
{
Laurent Montel's avatar
Laurent Montel committed
600
    DecryptVerifyFilesCommand *const cmd = new DecryptVerifyFilesCommand(files, nullptr);
Laurent Montel's avatar
Laurent Montel committed
601
    cmd->setOperation(Decrypt);
Marc Mutz's avatar
Marc Mutz committed
602
    cmd->start();
603 604
}

Laurent Montel's avatar
Laurent Montel committed
605 606
void KleopatraApplication::verifyFiles(const QStringList &files, GpgME::Protocol /*proto*/)
{
Laurent Montel's avatar
Laurent Montel committed
607
    DecryptVerifyFilesCommand *const cmd = new DecryptVerifyFilesCommand(files, nullptr);
Laurent Montel's avatar
Laurent Montel committed
608
    cmd->setOperation(Verify);
Marc Mutz's avatar
Marc Mutz committed
609
    cmd->start();
610 611
}

Laurent Montel's avatar
Laurent Montel committed
612 613
void KleopatraApplication::decryptVerifyFiles(const QStringList &files, GpgME::Protocol /*proto*/)
{
Laurent Montel's avatar
Laurent Montel committed
614
    DecryptVerifyFilesCommand *const cmd = new DecryptVerifyFilesCommand(files, nullptr);
615
    cmd->start();
616 617
}

618 619
void KleopatraApplication::checksumFiles(const QStringList &files, GpgME::Protocol /*proto*/)
{
620 621
    QStringList verifyFiles, createFiles;

Laurent Montel's avatar
Laurent Montel committed
622
    for (const QString &file : files) {
623 624 625 626 627 628 629 630
        if (isChecksumFile(file)) {
            verifyFiles << file;
        } else {
            createFiles << file;
        }
    }

    if (!verifyFiles.isEmpty()) {
Laurent Montel's avatar
Laurent Montel committed
631
        auto *const cmd = new ChecksumVerifyFilesCommand(verifyFiles, nullptr);
632 633 634
        cmd->start();
    }
    if (!createFiles.isEmpty()) {
Laurent Montel's avatar
Laurent Montel committed
635
        auto *const cmd = new ChecksumCreateFilesCommand(createFiles, nullptr);
636 637
        cmd->start();
    }
638 639
}

Laurent Montel's avatar
Laurent Montel committed
640 641
void KleopatraApplication::setIgnoreNewInstance(bool ignore)
{
642 643 644
    d->ignoreNewInstance = ignore;
}

Laurent Montel's avatar
Laurent Montel committed
645 646
bool KleopatraApplication::ignoreNewInstance() const
{
647 648
    return d->ignoreNewInstance;
}