1 /* -*- mode: c++; c-basic-offset:4 -*-
2 commands/command.cpp
3
4 This file is part of Kleopatra, the KDE keymanager
5 SPDX-FileCopyrightText: 2007 Klarälvdalens Datakonsult AB
6
7 SPDX-License-Identifier: GPL-2.0-or-later
8 */
9
10 #include <config-kleopatra.h>
11
12 #include "command.h"
13 #include "command_p.h"
14
15 #include "signencryptfilescommand.h"
16 #include "importcertificatefromfilecommand.h"
17 #include "decryptverifyfilescommand.h"
18 #include "detailscommand.h"
19 #include "lookupcertificatescommand.h"
20 #include "checksumverifyfilescommand.h"
21
22 #include <Libkleo/KeyCache>
23 #include <Libkleo/Classify>
24
25
26 #include <view/tabwidget.h>
27
28 #include "kleopatra_debug.h"
29 #include <KWindowSystem>
30
31 #include <QAbstractItemView>
32 #include <QFileInfo>
33
34 using namespace Kleo;
35 using namespace Kleo::Commands;
36 using namespace GpgME;
37
Private(Command * qq)38 Command::Private::Private(Command *qq)
39 : q(qq),
40 autoDelete(true),
41 warnWhenRunningAtShutdown(true)
42 {
43 }
44
Private(Command * qq,KeyListController * controller)45 Command::Private::Private(Command *qq, KeyListController *controller)
46 : q(qq),
47 autoDelete(true),
48 warnWhenRunningAtShutdown(true),
49 controller_(controller)
50 {
51 }
52
Private(Command * qq,QWidget * parent)53 Command::Private::Private(Command *qq, QWidget *parent)
54 : q(qq),
55 autoDelete(true),
56 warnWhenRunningAtShutdown(true),
57 parentWidget_(parent)
58 {
59 }
60
~Private()61 Command::Private::~Private()
62 {
63 qCDebug(KLEOPATRA_LOG);
64 }
65
Command(KeyListController * p)66 Command::Command(KeyListController *p)
67 : QObject(p), d(new Private(this, p))
68 {
69 if (p) {
70 p->registerCommand(this);
71 }
72 }
73
Command(QAbstractItemView * v,KeyListController * p)74 Command::Command(QAbstractItemView *v, KeyListController *p)
75 : QObject(p), d(new Private(this, p))
76 {
77 if (p) {
78 p->registerCommand(this);
79 }
80 if (v) {
81 setView(v);
82 }
83 }
84
Command(Private * pp)85 Command::Command(Private *pp)
86 : QObject(pp->controller_), d(pp)
87 {
88 if (pp->controller_) {
89 pp->controller_->registerCommand(this);
90 }
91 }
92
Command(QAbstractItemView * v,Private * pp)93 Command::Command(QAbstractItemView *v, Private *pp)
94 : QObject(pp->controller_), d(pp)
95 {
96 if (pp->controller_) {
97 pp->controller_->registerCommand(this);
98 }
99 if (v) {
100 setView(v);
101 }
102 }
103
Command(const GpgME::Key & key)104 Command::Command(const GpgME::Key &key)
105 : QObject(nullptr), d(new Private(this))
106 {
107 d->keys_ = std::vector<Key>(1, key);
108 }
109
Command(const std::vector<GpgME::Key> & keys)110 Command::Command(const std::vector<GpgME::Key> &keys)
111 : QObject(nullptr), d(new Private(this))
112 {
113 d->keys_ = keys;
114 }
115
Command(const Key & key,Private * pp)116 Command::Command(const Key &key, Private *pp)
117 : QObject(nullptr), d(pp)
118 {
119 d->keys_ = std::vector<Key>(1, key);
120 }
121
Command(const std::vector<GpgME::Key> & keys,Private * pp)122 Command::Command(const std::vector<GpgME::Key> &keys, Private *pp)
123 : QObject(nullptr), d(pp)
124 {
125 d->keys_ = keys;
126 }
127
~Command()128 Command::~Command()
129 {
130 qCDebug(KLEOPATRA_LOG);
131 }
132
setAutoDelete(bool on)133 void Command::setAutoDelete(bool on)
134 {
135 d->autoDelete = on;
136 }
137
autoDelete() const138 bool Command::autoDelete() const
139 {
140 return d->autoDelete;
141 }
142
setWarnWhenRunningAtShutdown(bool on)143 void Command::setWarnWhenRunningAtShutdown(bool on)
144 {
145 d->warnWhenRunningAtShutdown = on;
146 }
147
warnWhenRunningAtShutdown() const148 bool Command::warnWhenRunningAtShutdown() const
149 {
150 return d->warnWhenRunningAtShutdown;
151 }
152
setParentWidget(QWidget * widget)153 void Command::setParentWidget(QWidget *widget)
154 {
155 d->parentWidget_ = widget;
156 }
157
setParentWId(WId wid)158 void Command::setParentWId(WId wid)
159 {
160 d->parentWId = wid;
161 }
162
setView(QAbstractItemView * view)163 void Command::setView(QAbstractItemView *view)
164 {
165 if (view == d->view_) {
166 return;
167 }
168 d->view_ = view;
169 if (!view || !d->indexes_.empty()) {
170 return;
171 }
172 const QItemSelectionModel *const sm = view->selectionModel();
173 if (!sm) {
174 qCWarning(KLEOPATRA_LOG) << "view " << (void *)view << " has no selectionModel!";
175 return;
176 }
177 const QList<QModelIndex> selected = sm->selectedRows();
178 if (!selected.empty()) {
179 std::copy(selected.begin(), selected.end(), std::back_inserter(d->indexes_));
180 return;
181 }
182 }
183
setIndex(const QModelIndex & idx)184 void Command::setIndex(const QModelIndex &idx)
185 {
186 d->indexes_.clear();
187 d->indexes_.push_back(idx);
188 }
189
setIndexes(const QList<QModelIndex> & idx)190 void Command::setIndexes(const QList<QModelIndex> &idx)
191 {
192 d->indexes_.clear();
193 std::copy(idx.begin(), idx.end(), std::back_inserter(d->indexes_));
194 }
195
setKey(const Key & key)196 void Command::setKey(const Key &key)
197 {
198 d->keys_.clear();
199 if (!key.isNull()) {
200 d->keys_.push_back(key);
201 }
202 }
203
setKeys(const std::vector<Key> & keys)204 void Command::setKeys(const std::vector<Key> &keys)
205 {
206 d->keys_ = keys;
207 }
208
start()209 void Command::start()
210 {
211 doStart();
212 }
213
cancel()214 void Command::cancel()
215 {
216 qCDebug(KLEOPATRA_LOG) << metaObject()->className();
217 doCancel();
218 Q_EMIT canceled();
219 }
220
addTemporaryView(const QString & title,AbstractKeyListSortFilterProxyModel * proxy,const QString & tabToolTip)221 void Command::addTemporaryView(const QString &title, AbstractKeyListSortFilterProxyModel *proxy, const QString &tabToolTip)
222 {
223 if (TabWidget *const tw = d->controller_ ? d->controller_->tabWidget() : nullptr)
224 if (QAbstractItemView *const v = tw->addTemporaryView(title, proxy, tabToolTip)) {
225 setView(v);
226 }
227 }
228
applyWindowID(QWidget * w) const229 void Command::applyWindowID(QWidget *w) const
230 {
231 if (w) {
232 if (d->parentWId) {
233 if (QWidget *pw = QWidget::find(d->parentWId)) {
234 // remember the current focus widget; re-parenting resets it
235 QWidget *focusWidget = w->focusWidget();
236 w->setParent(pw, w->windowFlags());
237 if (focusWidget) {
238 focusWidget->setFocus();
239 }
240 } else {
241 w->setAttribute(Qt::WA_NativeWindow, true);
242 KWindowSystem::setMainWindow(w->windowHandle(), d->parentWId);
243 }
244 } else {
245 // remember the current focus widget; re-parenting resets it
246 QWidget *focusWidget = w->focusWidget();
247 w->setParent(d->parentWidgetOrView(), w->windowFlags());
248 if (focusWidget) {
249 focusWidget->setFocus();
250 }
251 }
252 }
253 }
254
255 // static
commandsForFiles(const QStringList & files)256 QVector <Command *> Command::commandsForFiles(const QStringList &files)
257 {
258 QStringList importFiles, decryptFiles, encryptFiles, checksumFiles;
259 QVector <Command *> cmds;
260 for (const QString &fileName : files) {
261 const unsigned int classification = classify(fileName);
262
263 if (classification & Class::AnyCertStoreType) {
264 importFiles << fileName;
265 } else if (classification & Class::AnyMessageType) {
266 // For any message we decrypt / verify. This includes
267 // the class CipherText
268 decryptFiles << fileName;
269 } else if (isChecksumFile(fileName)) {
270 checksumFiles << fileName;
271 } else {
272 QFileInfo fi(fileName);
273 if (fi.isReadable()) {
274 encryptFiles << fileName;
275 }
276 }
277 }
278 if (!importFiles.isEmpty()) {
279 cmds << new ImportCertificateFromFileCommand(importFiles, nullptr);
280 }
281 if (!decryptFiles.isEmpty()) {
282 cmds << new DecryptVerifyFilesCommand(decryptFiles, nullptr);
283 }
284 if (!encryptFiles.isEmpty()) {
285 cmds << new SignEncryptFilesCommand(encryptFiles, nullptr);
286 }
287 if (!checksumFiles.isEmpty()) {
288 cmds << new ChecksumVerifyFilesCommand(checksumFiles, nullptr);
289 }
290 return cmds;
291 }
292
293 // static
commandForQuery(const QString & query)294 Command *Command::commandForQuery(const QString &query)
295 {
296 const auto cache = Kleo::KeyCache::instance();
297 GpgME::Key key = cache->findByKeyIDOrFingerprint(query.toLocal8Bit().data());
298
299 if (key.isNull() && query.size() > 16) {
300 // Try to find by subkeyid
301 std::vector<std::string> id;
302 id.push_back(query.right(16).toStdString());
303 auto keys = cache->findSubkeysByKeyID(id);
304 if (keys.size()) {
305 key = keys[0].parent();
306 }
307 }
308 if (key.isNull()) {
309 return new LookupCertificatesCommand(query, nullptr);
310 } else {
311 return new DetailsCommand(key, nullptr);
312 }
313 }
314