selectcertificatecommand.cpp 5.23 KB
Newer Older
1
2
3
4
/* -*- mode: c++; c-basic-offset:4 -*-
    uiserver/selectcertificatecommand.cpp

    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
11
12
13
14
15
*/

#include <config-kleopatra.h>

#include "selectcertificatecommand.h"

#include <dialogs/certificateselectiondialog.h>

Laurent Montel's avatar
Laurent Montel committed
16
#include <Libkleo/Stl_Util>
17
#include <Libkleo/KleoException>
18
#include <Libkleo/KeyCache>
19
20
21
22
23

#include <gpgme++/key.h>

#include <gpg-error.h>

Laurent Montel's avatar
Laurent Montel committed
24
#include "kleopatra_debug.h"
Laurent Montel's avatar
Laurent Montel committed
25
#include <KLocalizedString>
26
27
28
29
30
31
32
33
34

#include <QByteArray>
#include <QPointer>

#include <string>
#include <algorithm>

using namespace Kleo;
using namespace Kleo::Dialogs;
35
using namespace GpgME;
36

Laurent Montel's avatar
Laurent Montel committed
37
38
class SelectCertificateCommand::Private
{
39
    friend class ::Kleo::SelectCertificateCommand;
Laurent Montel's avatar
Laurent Montel committed
40
    SelectCertificateCommand *const q;
41
public:
Laurent Montel's avatar
Laurent Montel committed
42
43
    Private(SelectCertificateCommand *qq) :
        q(qq),
44
45
46
47
48
49
50
51
        dialog()
    {

    }

private:
    void slotDialogAccepted();
    void slotDialogRejected();
Laurent Montel's avatar
Laurent Montel committed
52
    void slotSelectedCertificates(int, const QByteArray &);
53
54

private:
Laurent Montel's avatar
Laurent Montel committed
55
56
57
    void ensureDialogCreated()
    {
        if (dialog) {
58
            return;
Laurent Montel's avatar
Laurent Montel committed
59
        }
60
        dialog = new CertificateSelectionDialog;
Laurent Montel's avatar
Laurent Montel committed
61
62
        q->applyWindowID(dialog);
        dialog->setAttribute(Qt::WA_DeleteOnClose);
63
        //dialog->setWindowTitle( i18nc( "@title", "Certificate Selection" ) );
Laurent Montel's avatar
Laurent Montel committed
64
65
        connect(dialog, SIGNAL(accepted()), q, SLOT(slotDialogAccepted()));
        connect(dialog, SIGNAL(rejected()), q, SLOT(slotDialogRejected()));
66
    }
Laurent Montel's avatar
Laurent Montel committed
67
68
    void ensureDialogShown()
    {
69
        ensureDialogCreated();
Laurent Montel's avatar
Laurent Montel committed
70
        if (dialog->isVisible()) {
71
            dialog->raise();
Laurent Montel's avatar
Laurent Montel committed
72
        } else {
73
            dialog->show();
Laurent Montel's avatar
Laurent Montel committed
74
        }
75
76
77
78
79
80
81
    }

private:
    QPointer<CertificateSelectionDialog> dialog;
};

SelectCertificateCommand::SelectCertificateCommand()
Laurent Montel's avatar
Laurent Montel committed
82
    : QObject(), AssuanCommandMixin<SelectCertificateCommand>(), d(new Private(this)) {}
83
84
85
86

SelectCertificateCommand::~SelectCertificateCommand() {}

static const struct {
Laurent Montel's avatar
Laurent Montel committed
87
    const char *name;
88
89
90
91
92
93
94
95
96
97
    CertificateSelectionDialog::Option option;
} option_table[] = {
    { "multi",        CertificateSelectionDialog::MultiSelection },
    { "sign-only",    CertificateSelectionDialog::SignOnly       },
    { "encrypt-only", CertificateSelectionDialog::EncryptOnly    },
    { "openpgp-only", CertificateSelectionDialog::OpenPGPFormat  },
    { "x509-only",    CertificateSelectionDialog::CMSFormat      },
    { "secret-only",  CertificateSelectionDialog::SecretKeys     },
};

Laurent Montel's avatar
Laurent Montel committed
98
99
int SelectCertificateCommand::doStart()
{
100
101
102
    d->ensureDialogCreated();

    CertificateSelectionDialog::Options opts;
103
    for (unsigned int i = 0; i < sizeof option_table / sizeof * option_table; ++i) {
Laurent Montel's avatar
Laurent Montel committed
104
105
106
        if (hasOption(option_table[i].name)) {
            opts |= option_table[i].option;
        }
107
    }
108
    if ((opts & CertificateSelectionDialog::AnyCertificate) == 0) {
109
110
111
        // neither sign-only nor encrypt-only => any usage
        opts |= CertificateSelectionDialog::AnyCertificate;
    }
112
    if ((opts & CertificateSelectionDialog::AnyFormat) == 0) {
113
114
115
        // neither openpgp-only nor x509-only => any protocol
        opts |= CertificateSelectionDialog::AnyFormat;
    }
Laurent Montel's avatar
Laurent Montel committed
116
    d->dialog->setOptions(opts);
117

Laurent Montel's avatar
Laurent Montel committed
118
119
    if (const int err = inquire("SELECTED_CERTIFICATES",
                                this, SLOT(slotSelectedCertificates(int,QByteArray)))) {
120
        return err;
Laurent Montel's avatar
Laurent Montel committed
121
    }
122

123
124
125
126
127
    d->ensureDialogShown();

    return 0;
}

Laurent Montel's avatar
Laurent Montel committed
128
129
void SelectCertificateCommand::Private::slotSelectedCertificates(int err, const QByteArray &data)
{
Laurent Montel's avatar
Laurent Montel committed
130
    qCDebug(KLEOPATRA_LOG) << err << ", " << data.constData();
Laurent Montel's avatar
Laurent Montel committed
131
    if (err) {
132
        return;
Laurent Montel's avatar
Laurent Montel committed
133
    }
134
135
136
137
    const auto split = data.split('\n');
    std::vector<std::string> fprs;
    fprs.reserve(split.size());
    std::transform(split.cbegin(), split.cend(), std::back_inserter(fprs), std::mem_fn(&QByteArray::constData));
Laurent Montel's avatar
Laurent Montel committed
138
    const std::vector<Key> keys = KeyCache::instance()->findByKeyIDOrFingerprint(fprs);
Laurent Montel's avatar
Laurent Montel committed
139
    for (const Key &key : keys) {
Laurent Montel's avatar
Laurent Montel committed
140
        qCDebug(KLEOPATRA_LOG) << "found key " << key.userID(0).id();
Laurent Montel's avatar
Laurent Montel committed
141
142
143
144
    }
    if (dialog) {
        dialog->selectCertificates(keys);
    } else {
Laurent Montel's avatar
Laurent Montel committed
145
        qCWarning(KLEOPATRA_LOG) << "dialog == NULL in slotSelectedCertificates";
Laurent Montel's avatar
Laurent Montel committed
146
    }
147
148
}

Laurent Montel's avatar
Laurent Montel committed
149
150
151
void SelectCertificateCommand::doCanceled()
{
    if (d->dialog) {
152
        d->dialog->close();
Laurent Montel's avatar
Laurent Montel committed
153
    }
154
155
}

Laurent Montel's avatar
Laurent Montel committed
156
157
void SelectCertificateCommand::Private::slotDialogAccepted()
{
158
159
    try {
        QByteArray data;
Laurent Montel's avatar
Laurent Montel committed
160
        Q_FOREACH (const Key &key, dialog->selectedCertificates()) {
161
            data += key.primaryFingerprint();
162
            data += '\n';
163
        }
Laurent Montel's avatar
Laurent Montel committed
164
        q->sendData(data);
165
        q->done();
Laurent Montel's avatar
Laurent Montel committed
166
167
168
169
170
171
172
173
174
    } catch (const Exception &e) {
        q->done(e.error(), e.message());
    } catch (const std::exception &e) {
        q->done(makeError(GPG_ERR_UNEXPECTED),
                i18n("Caught unexpected exception in SelectCertificateCommand::Private::slotDialogAccepted: %1",
                     QString::fromLocal8Bit(e.what())));
    } catch (...) {
        q->done(makeError(GPG_ERR_UNEXPECTED),
                i18n("Caught unknown exception in SelectCertificateCommand::Private::slotDialogAccepted"));
175
176
177
    }
}

Laurent Montel's avatar
Laurent Montel committed
178
179
void SelectCertificateCommand::Private::slotDialogRejected()
{
Laurent Montel's avatar
Laurent Montel committed
180
    dialog = nullptr;
Laurent Montel's avatar
Laurent Montel committed
181
    q->done(makeError(GPG_ERR_CANCELED));
182
183
184
}

#include "moc_selectcertificatecommand.cpp"