command.cpp 6.9 KB
Newer Older
Marc Mutz's avatar
Marc Mutz committed
1 2 3 4
/* -*- mode: c++; c-basic-offset:4 -*-
    commands/command.cpp

    This file is part of Kleopatra, the KDE keymanager
5 6 7
    SPDX-FileCopyrightText: 2007 Klarälvdalens Datakonsult AB

    SPDX-License-Identifier: GPL-2.0-or-later
Marc Mutz's avatar
Marc Mutz committed
8 9
*/

10 11
#include <config-kleopatra.h>

12 13 14
#include "command.h"
#include "command_p.h"

15 16 17 18 19
#include "signencryptfilescommand.h"
#include "importcertificatefromfilecommand.h"
#include "decryptverifyfilescommand.h"
#include "detailscommand.h"
#include "lookupcertificatescommand.h"
20
#include "checksumverifyfilescommand.h"
21

22
#include <Libkleo/KeyCache>
23
#include <Libkleo/Classify>
24

25

26 27
#include <view/tabwidget.h>

Laurent Montel's avatar
Laurent Montel committed
28
#include "kleopatra_debug.h"
Thomas McGuire's avatar
Thomas McGuire committed
29
#include <KWindowSystem>
Marc Mutz's avatar
Marc Mutz committed
30

31
#include <QAbstractItemView>
32
#include <QFileInfo>
33 34

using namespace Kleo;
35
using namespace Kleo::Commands;
36
using namespace GpgME;
37

38 39 40 41 42 43 44
Command::Private::Private(Command *qq)
    : q(qq),
      autoDelete(true),
      warnWhenRunningAtShutdown(true)
{
}

Laurent Montel's avatar
Laurent Montel committed
45 46 47 48 49
Command::Private::Private(Command *qq, KeyListController *controller)
    : q(qq),
      autoDelete(true),
      warnWhenRunningAtShutdown(true),
      controller_(controller)
50
{
51
}
52

53 54 55 56 57 58
Command::Private::Private(Command *qq, QWidget *parent)
    : q(qq),
      autoDelete(true),
      warnWhenRunningAtShutdown(true),
      parentWidget_(parent)
{
59 60
}

Laurent Montel's avatar
Laurent Montel committed
61 62
Command::Private::~Private()
{
Laurent Montel's avatar
Laurent Montel committed
63
    qCDebug(KLEOPATRA_LOG);
Laurent Montel's avatar
Laurent Montel committed
64
}
65

Laurent Montel's avatar
Laurent Montel committed
66 67
Command::Command(KeyListController *p)
    : QObject(p), d(new Private(this, p))
68
{
Laurent Montel's avatar
Laurent Montel committed
69 70 71
    if (p) {
        p->registerCommand(this);
    }
72 73
}

Laurent Montel's avatar
Laurent Montel committed
74 75
Command::Command(QAbstractItemView *v, KeyListController *p)
    : QObject(p), d(new Private(this, p))
76
{
Laurent Montel's avatar
Laurent Montel committed
77 78 79 80 81 82
    if (p) {
        p->registerCommand(this);
    }
    if (v) {
        setView(v);
    }
83 84
}

Laurent Montel's avatar
Laurent Montel committed
85 86
Command::Command(Private *pp)
    : QObject(pp->controller_), d(pp)
87
{
Laurent Montel's avatar
Laurent Montel committed
88 89 90
    if (pp->controller_) {
        pp->controller_->registerCommand(this);
    }
91 92
}

Laurent Montel's avatar
Laurent Montel committed
93 94
Command::Command(QAbstractItemView *v, Private *pp)
    : QObject(pp->controller_), d(pp)
95
{
Laurent Montel's avatar
Laurent Montel committed
96 97 98 99 100 101
    if (pp->controller_) {
        pp->controller_->registerCommand(this);
    }
    if (v) {
        setView(v);
    }
102 103
}

Yuri Chornoivan's avatar
Yuri Chornoivan committed
104
Command::Command(const GpgME::Key &key)
105
    : QObject(nullptr), d(new Private(this))
106
{
Laurent Montel's avatar
Laurent Montel committed
107
    d->keys_ = std::vector<Key>(1, key);
108 109
}

Yuri Chornoivan's avatar
Yuri Chornoivan committed
110
Command::Command(const std::vector<GpgME::Key> &keys)
111
    : QObject(nullptr), d(new Private(this))
112 113 114 115
{
    d->keys_ = keys;
}

Laurent Montel's avatar
Laurent Montel committed
116
Command::Command(const Key &key, Private *pp)
Laurent Montel's avatar
Laurent Montel committed
117
    : QObject(nullptr), d(pp)
118
{
Laurent Montel's avatar
Laurent Montel committed
119
    d->keys_ = std::vector<Key>(1, key);
120 121
}

Yuri Chornoivan's avatar
Yuri Chornoivan committed
122
Command::Command(const std::vector<GpgME::Key> &keys, Private *pp)
Laurent Montel's avatar
Laurent Montel committed
123
    : QObject(nullptr), d(pp)
124 125 126 127
{
    d->keys_ = keys;
}

Laurent Montel's avatar
Laurent Montel committed
128 129
Command::~Command()
{
Laurent Montel's avatar
Laurent Montel committed
130
    qCDebug(KLEOPATRA_LOG);
Laurent Montel's avatar
Laurent Montel committed
131
}
132

Laurent Montel's avatar
Laurent Montel committed
133 134
void Command::setAutoDelete(bool on)
{
135 136
    d->autoDelete = on;
}
137

Laurent Montel's avatar
Laurent Montel committed
138 139
bool Command::autoDelete() const
{
140 141
    return d->autoDelete;
}
142

Laurent Montel's avatar
Laurent Montel committed
143 144
void Command::setWarnWhenRunningAtShutdown(bool on)
{
145 146 147
    d->warnWhenRunningAtShutdown = on;
}

Laurent Montel's avatar
Laurent Montel committed
148 149
bool Command::warnWhenRunningAtShutdown() const
{
150 151 152
    return d->warnWhenRunningAtShutdown;
}

Laurent Montel's avatar
Laurent Montel committed
153 154
void Command::setParentWidget(QWidget *widget)
{
155 156 157
    d->parentWidget_ = widget;
}

Laurent Montel's avatar
Laurent Montel committed
158 159
void Command::setParentWId(WId wid)
{
160 161 162
    d->parentWId = wid;
}

Laurent Montel's avatar
Laurent Montel committed
163 164 165
void Command::setView(QAbstractItemView *view)
{
    if (view == d->view_) {
166
        return;
Laurent Montel's avatar
Laurent Montel committed
167
    }
168
    d->view_ = view;
Laurent Montel's avatar
Laurent Montel committed
169
    if (!view || !d->indexes_.empty()) {
170
        return;
Laurent Montel's avatar
Laurent Montel committed
171 172 173
    }
    const QItemSelectionModel *const sm = view->selectionModel();
    if (!sm) {
Laurent Montel's avatar
Laurent Montel committed
174
        qCWarning(KLEOPATRA_LOG) << "view " << (void *)view << " has no selectionModel!";
175 176 177
        return;
    }
    const QList<QModelIndex> selected = sm->selectedRows();
Laurent Montel's avatar
Laurent Montel committed
178 179
    if (!selected.empty()) {
        std::copy(selected.begin(), selected.end(), std::back_inserter(d->indexes_));
180 181
        return;
    }
182 183
}

Laurent Montel's avatar
Laurent Montel committed
184 185
void Command::setIndex(const QModelIndex &idx)
{
186
    d->indexes_.clear();
Laurent Montel's avatar
Laurent Montel committed
187
    d->indexes_.push_back(idx);
188 189
}

Laurent Montel's avatar
Laurent Montel committed
190 191
void Command::setIndexes(const QList<QModelIndex> &idx)
{
192
    d->indexes_.clear();
Laurent Montel's avatar
Laurent Montel committed
193
    std::copy(idx.begin(), idx.end(), std::back_inserter(d->indexes_));
194 195
}

Laurent Montel's avatar
Laurent Montel committed
196 197
void Command::setKey(const Key &key)
{
198
    d->keys_.clear();
Laurent Montel's avatar
Laurent Montel committed
199 200 201
    if (!key.isNull()) {
        d->keys_.push_back(key);
    }
202 203
}

Laurent Montel's avatar
Laurent Montel committed
204 205
void Command::setKeys(const std::vector<Key> &keys)
{
206 207 208
    d->keys_ = keys;
}

Laurent Montel's avatar
Laurent Montel committed
209 210
void Command::start()
{
211 212 213
    doStart();
}

Laurent Montel's avatar
Laurent Montel committed
214 215
void Command::cancel()
{
216
    qCDebug(KLEOPATRA_LOG) << metaObject()->className();
217
    doCancel();
Laurent Montel's avatar
Laurent Montel committed
218
    Q_EMIT canceled();
219 220
}

Laurent Montel's avatar
Laurent Montel committed
221 222
void Command::addTemporaryView(const QString &title, AbstractKeyListSortFilterProxyModel *proxy, const QString &tabToolTip)
{
Laurent Montel's avatar
Laurent Montel committed
223
    if (TabWidget *const tw = d->controller_ ? d->controller_->tabWidget() : nullptr)
Laurent Montel's avatar
Laurent Montel committed
224 225 226
        if (QAbstractItemView *const v = tw->addTemporaryView(title, proxy, tabToolTip)) {
            setView(v);
        }
227 228
}

Laurent Montel's avatar
Laurent Montel committed
229 230
void Command::applyWindowID(QWidget *w) const
{
Sergio Martins's avatar
Sergio Martins committed
231 232
    if (w) {
        if (d->parentWId) {
Laurent Montel's avatar
Laurent Montel committed
233 234 235
            if (QWidget *pw = QWidget::find(d->parentWId)) {
                w->setParent(pw, w->windowFlags());
            } else {
236 237
                w->setAttribute(Qt::WA_NativeWindow, true);
                KWindowSystem::setMainWindow(w->windowHandle(), d->parentWId);
Laurent Montel's avatar
Laurent Montel committed
238
            }
Sergio Martins's avatar
Sergio Martins committed
239
        } else {
Laurent Montel's avatar
Laurent Montel committed
240 241
            w->setParent(d->parentWidgetOrView(), w->windowFlags());
        }
Sergio Martins's avatar
Sergio Martins committed
242
    }
Thomas McGuire's avatar
Thomas McGuire committed
243
}
244 245

// static
246
QVector <Command *> Command::commandsForFiles(const QStringList &files)
247
{
248
    QStringList importFiles, decryptFiles, encryptFiles, checksumFiles;
249
    QVector <Command *> cmds;
250
    for (const QString &fileName : files) {
Andre Heinecke's avatar
Andre Heinecke committed
251
        const unsigned int classification = classify(fileName);
252 253 254 255 256 257 258

        if (classification & Class::AnyCertStoreType) {
            importFiles << fileName;
        } else if (classification & Class::AnyMessageType) {
            // For any message we decrypt / verify. This includes
            // the class CipherText
            decryptFiles << fileName;
259 260
        } else if (isChecksumFile(fileName)) {
            checksumFiles << fileName;
261 262 263 264 265
        } else {
            QFileInfo fi(fileName);
            if (fi.isReadable()) {
                encryptFiles << fileName;
            }
266 267
        }
    }
268
    if (!importFiles.isEmpty()) {
Laurent Montel's avatar
Laurent Montel committed
269
        cmds << new ImportCertificateFromFileCommand(importFiles, nullptr);
270 271
    }
    if (!decryptFiles.isEmpty()) {
Laurent Montel's avatar
Laurent Montel committed
272
        cmds << new DecryptVerifyFilesCommand(decryptFiles, nullptr);
273 274
    }
    if (!encryptFiles.isEmpty()) {
Laurent Montel's avatar
Laurent Montel committed
275
        cmds << new SignEncryptFilesCommand(encryptFiles, nullptr);
276
    }
277
    if (!checksumFiles.isEmpty()) {
Laurent Montel's avatar
Laurent Montel committed
278
        cmds << new ChecksumVerifyFilesCommand(checksumFiles, nullptr);
279
    }
280
    return cmds;
281 282 283 284 285
}

// static
Command *Command::commandForQuery(const QString &query)
{
Andre Heinecke's avatar
Andre Heinecke committed
286 287 288 289 290 291 292 293 294 295 296 297
    const auto cache = Kleo::KeyCache::instance();
    GpgME::Key key = cache->findByKeyIDOrFingerprint(query.toLocal8Bit().data());

    if (key.isNull() && query.size() > 16) {
        // Try to find by subkeyid
        std::vector<std::string> id;
        id.push_back(query.right(16).toStdString());
        auto keys = cache->findSubkeysByKeyID(id);
        if (keys.size()) {
            key = keys[0].parent();
        }
    }
298
    if (key.isNull()) {
Laurent Montel's avatar
Laurent Montel committed
299
        return new LookupCertificatesCommand(query, nullptr);
300
    } else {
Laurent Montel's avatar
Laurent Montel committed
301
        return new DetailsCommand(key, nullptr);
302 303
    }
}