Page MenuHome GnuPG

keyrequester.cpp
No OneTemporary

keyrequester.cpp

/* -*- c++ -*-
keyrequester.cpp
This file is part of libkleopatra, the KDE keymanagement library
SPDX-FileCopyrightText: 2004 Klarälvdalens Datakonsult AB
Based on kpgpui.cpp
SPDX-FileCopyrightText: 2001, 2002 the KPGP authors
See file libkdenetwork/AUTHORS.kpgp for details
This file is part of KPGP, the KDE PGP/GnuPG support library.
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <config-libkleo.h>
#include "keyrequester.h"
#include "keyselectiondialog.h"
#include <libkleo/algorithm.h>
#include <libkleo/compliance.h>
#include <libkleo/dn.h>
#include <libkleo/formatting.h>
#include <libkleo/keyhelpers.h>
#include <KLocalizedString>
#include <KMessageBox>
#include <QGpgME/KeyListJob>
#include <QApplication>
#include <QDialog>
#include <QHBoxLayout>
#include <QPushButton>
#include <QString>
#include <gpgme++/key.h>
#include <gpgme++/keylistresult.h>
using namespace QGpgME;
using namespace Kleo;
Kleo::KeyRequester::KeyRequester(unsigned int allowedKeys, bool multipleKeys, QWidget *parent)
: QWidget(parent)
, mOpenPGPBackend(nullptr)
, mSMIMEBackend(nullptr)
, mMulti(multipleKeys)
, mKeyUsage(allowedKeys)
, mJobs(0)
, d(nullptr)
{
init();
}
Kleo::KeyRequester::KeyRequester(QWidget *parent)
: QWidget(parent)
, mOpenPGPBackend(nullptr)
, mSMIMEBackend(nullptr)
, mMulti(false)
, mKeyUsage(0)
, mJobs(0)
, d(nullptr)
{
init();
}
void Kleo::KeyRequester::init()
{
auto hlay = new QHBoxLayout(this);
hlay->setContentsMargins(0, 0, 0, 0);
if (DeVSCompliance::isCompliant()) {
mComplianceIcon = new QLabel{this};
mComplianceIcon->setPixmap(QIcon::fromTheme(QStringLiteral("emblem-question")).pixmap(22));
}
// the label where the key id is to be displayed:
mLabel = new QLabel(this);
mLabel->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
// the button to unset any key:
mEraseButton = new QPushButton(this);
mEraseButton->setAutoDefault(false);
mEraseButton->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum));
mEraseButton->setIcon(
QIcon::fromTheme(QApplication::isRightToLeft() ? QStringLiteral("edit-clear-locationbar-ltr") : QStringLiteral("edit-clear-locationbar-rtl")));
mEraseButton->setToolTip(i18n("Clear"));
// the button to call the KeySelectionDialog:
mDialogButton = new QPushButton(i18n("Change..."), this);
mDialogButton->setAutoDefault(false);
if (mComplianceIcon) {
hlay->addWidget(mComplianceIcon);
}
hlay->addWidget(mLabel, 1);
hlay->addWidget(mEraseButton);
hlay->addWidget(mDialogButton);
connect(mEraseButton, &QPushButton::clicked, this, &SigningKeyRequester::slotEraseButtonClicked);
connect(mDialogButton, &QPushButton::clicked, this, &SigningKeyRequester::slotDialogButtonClicked);
setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed));
setAllowedKeys(mKeyUsage);
}
Kleo::KeyRequester::~KeyRequester()
{
}
const std::vector<GpgME::Key> &Kleo::KeyRequester::keys() const
{
return mKeys;
}
const GpgME::Key &Kleo::KeyRequester::key() const
{
static const GpgME::Key null = GpgME::Key::null;
if (mKeys.empty()) {
return null;
} else {
return mKeys.front();
}
}
void Kleo::KeyRequester::setKeys(const std::vector<GpgME::Key> &keys)
{
mKeys.clear();
for (auto it = keys.begin(); it != keys.end(); ++it) {
if (!it->isNull()) {
mKeys.push_back(*it);
}
}
updateKeys();
}
void Kleo::KeyRequester::setKey(const GpgME::Key &key)
{
mKeys.clear();
if (!key.isNull()) {
mKeys.push_back(key);
}
updateKeys();
}
QString Kleo::KeyRequester::fingerprint() const
{
if (mKeys.empty()) {
return QString();
} else {
return QLatin1String(mKeys.front().primaryFingerprint());
}
}
QStringList Kleo::KeyRequester::fingerprints() const
{
QStringList result;
for (auto it = mKeys.begin(); it != mKeys.end(); ++it) {
if (!it->isNull()) {
if (const char *fpr = it->primaryFingerprint()) {
result.push_back(QLatin1String(fpr));
}
}
}
return result;
}
void Kleo::KeyRequester::setFingerprint(const QString &fingerprint)
{
startKeyListJob(QStringList(fingerprint));
}
void Kleo::KeyRequester::setFingerprints(const QStringList &fingerprints)
{
startKeyListJob(fingerprints);
}
void Kleo::KeyRequester::updateKeys()
{
if (mKeys.empty()) {
if (mComplianceIcon) {
mComplianceIcon->setPixmap(QIcon::fromTheme(QStringLiteral("emblem-unavailable")).pixmap(22));
mComplianceIcon->setToolTip(QString{});
}
mLabel->clear();
return;
}
if (mKeys.size() > 1) {
setMultipleKeysEnabled(true);
}
QStringList labelTexts;
QString toolTipText;
for (std::vector<GpgME::Key>::const_iterator it = mKeys.begin(); it != mKeys.end(); ++it) {
if (it->isNull()) {
continue;
}
const QString fpr = QLatin1String(it->primaryFingerprint());
labelTexts.push_back(fpr.right(8));
toolTipText += fpr.right(8) + QLatin1String(": ");
if (const char *uid = it->userID(0).id()) {
if (it->protocol() == GpgME::OpenPGP) {
toolTipText += QString::fromUtf8(uid);
} else {
toolTipText += Kleo::DN(uid).prettyDN();
}
} else {
toolTipText += xi18n("<placeholder>unknown</placeholder>");
}
toolTipText += QLatin1Char('\n');
}
if (mComplianceIcon) {
if (Kleo::all_of(mKeys, &Kleo::DeVSCompliance::keyIsCompliant)) {
mComplianceIcon->setPixmap(QIcon::fromTheme(QStringLiteral("emblem-success")).pixmap(22));
mComplianceIcon->setToolTip(DeVSCompliance::name(true));
} else {
mComplianceIcon->setPixmap(QIcon::fromTheme(QStringLiteral("emblem-warning")).pixmap(22));
mComplianceIcon->setToolTip(DeVSCompliance::name(false));
}
}
mLabel->setText(labelTexts.join(QLatin1String(", ")));
mLabel->setToolTip(toolTipText);
}
#ifndef __KLEO_UI_SHOW_KEY_LIST_ERROR_H__
#define __KLEO_UI_SHOW_KEY_LIST_ERROR_H__
static void showKeyListError(QWidget *parent, const GpgME::Error &err)
{
Q_ASSERT(err);
const QString msg = i18n(
"<qt><p>An error occurred while fetching "
"the keys from the backend:</p>"
"<p><b>%1</b></p></qt>",
Formatting::errorAsString(err));
KMessageBox::error(parent, msg, i18n("Key Listing Failed"));
}
#endif // __KLEO_UI_SHOW_KEY_LIST_ERROR_H__
void Kleo::KeyRequester::startKeyListJob(const QStringList &fingerprints)
{
if (!mSMIMEBackend && !mOpenPGPBackend) {
return;
}
mTmpKeys.clear();
mJobs = 0;
unsigned int count = 0;
for (QStringList::const_iterator it = fingerprints.begin(); it != fingerprints.end(); ++it) {
if (!(*it).trimmed().isEmpty()) {
++count;
}
}
if (!count) {
// don't fall into the trap that an empty pattern means
// "return all keys" :)
setKey(GpgME::Key::null);
return;
}
if (mOpenPGPBackend) {
KeyListJob *job = mOpenPGPBackend->keyListJob(false); // local, no sigs
if (!job) {
KMessageBox::error(this,
i18n("The OpenPGP backend does not support listing keys. "
"Check your installation."),
i18n("Key Listing Failed"));
} else {
connect(job, &KeyListJob::result, this, &SigningKeyRequester::slotKeyListResult);
connect(job, &KeyListJob::nextKey, this, &SigningKeyRequester::slotNextKey);
const GpgME::Error err =
job->start(fingerprints, mKeyUsage & Kleo::KeySelectionDialog::SecretKeys && !(mKeyUsage & Kleo::KeySelectionDialog::PublicKeys));
if (err) {
showKeyListError(this, err);
} else {
++mJobs;
}
}
}
if (mSMIMEBackend) {
KeyListJob *job = mSMIMEBackend->keyListJob(false); // local, no sigs
if (!job) {
KMessageBox::error(this,
i18n("The S/MIME backend does not support listing keys. "
"Check your installation."),
i18n("Key Listing Failed"));
} else {
connect(job, &KeyListJob::result, this, &SigningKeyRequester::slotKeyListResult);
connect(job, &KeyListJob::nextKey, this, &SigningKeyRequester::slotNextKey);
const GpgME::Error err =
job->start(fingerprints, mKeyUsage & Kleo::KeySelectionDialog::SecretKeys && !(mKeyUsage & Kleo::KeySelectionDialog::PublicKeys));
if (err) {
showKeyListError(this, err);
} else {
++mJobs;
}
}
}
if (mJobs > 0) {
mEraseButton->setEnabled(false);
mDialogButton->setEnabled(false);
}
}
void Kleo::KeyRequester::slotNextKey(const GpgME::Key &key)
{
if (!key.isNull()) {
mTmpKeys.push_back(key);
}
}
void Kleo::KeyRequester::slotKeyListResult(const GpgME::KeyListResult &res)
{
if (res.error()) {
showKeyListError(this, res.error());
}
if (--mJobs <= 0) {
mEraseButton->setEnabled(true);
mDialogButton->setEnabled(true);
setKeys(mTmpKeys);
mTmpKeys.clear();
}
}
void Kleo::KeyRequester::slotDialogButtonClicked()
{
KeySelectionDialog *dlg = mKeys.empty() ? new KeySelectionDialog(mDialogCaption, mDialogMessage, mInitialQuery, mKeyUsage, mMulti, false, this)
: new KeySelectionDialog(mDialogCaption, mDialogCaption, mKeys, mKeyUsage, mMulti, false, this);
if (dlg->exec() == QDialog::Accepted) {
if (mMulti) {
setKeys(dlg->selectedKeys());
} else {
setKey(dlg->selectedKey());
}
Q_EMIT changed();
}
delete dlg;
}
void Kleo::KeyRequester::slotEraseButtonClicked()
{
if (!mKeys.empty()) {
Q_EMIT changed();
}
mKeys.clear();
updateKeys();
}
void Kleo::KeyRequester::setDialogCaption(const QString &caption)
{
mDialogCaption = caption;
}
void Kleo::KeyRequester::setDialogMessage(const QString &msg)
{
mDialogMessage = msg;
}
bool Kleo::KeyRequester::isMultipleKeysEnabled() const
{
return mMulti;
}
void Kleo::KeyRequester::setMultipleKeysEnabled(bool multi)
{
if (multi == mMulti) {
return;
}
if (!multi && !mKeys.empty()) {
mKeys.erase(mKeys.begin() + 1, mKeys.end());
}
mMulti = multi;
updateKeys();
}
unsigned int Kleo::KeyRequester::allowedKeys() const
{
return mKeyUsage;
}
void Kleo::KeyRequester::setAllowedKeys(unsigned int keyUsage)
{
mKeyUsage = keyUsage;
mOpenPGPBackend = nullptr;
mSMIMEBackend = nullptr;
if (mKeyUsage & KeySelectionDialog::OpenPGPKeys) {
mOpenPGPBackend = openpgp();
}
if (mKeyUsage & KeySelectionDialog::SMIMEKeys) {
mSMIMEBackend = smime();
}
if (mOpenPGPBackend && !mSMIMEBackend) {
mDialogCaption = i18n("OpenPGP Key Selection");
mDialogMessage = i18n("Please select an OpenPGP key to use.");
} else if (!mOpenPGPBackend && mSMIMEBackend) {
mDialogCaption = i18n("S/MIME Key Selection");
mDialogMessage = i18n("Please select an S/MIME key to use.");
} else {
mDialogCaption = i18n("Key Selection");
mDialogMessage = i18n("Please select an (OpenPGP or S/MIME) key to use.");
}
}
QPushButton *Kleo::KeyRequester::dialogButton()
{
return mDialogButton;
}
QPushButton *Kleo::KeyRequester::eraseButton()
{
return mEraseButton;
}
static inline unsigned int foo(bool openpgp, bool smime, bool trusted, bool valid)
{
unsigned int result = 0;
if (openpgp) {
result |= Kleo::KeySelectionDialog::OpenPGPKeys;
}
if (smime) {
result |= Kleo::KeySelectionDialog::SMIMEKeys;
}
if (trusted) {
result |= Kleo::KeySelectionDialog::TrustedKeys;
}
if (valid) {
result |= Kleo::KeySelectionDialog::ValidKeys;
}
return result;
}
static inline unsigned int encryptionKeyUsage(bool openpgp, bool smime, bool trusted, bool valid)
{
return foo(openpgp, smime, trusted, valid) | Kleo::KeySelectionDialog::EncryptionKeys | Kleo::KeySelectionDialog::PublicKeys;
}
static inline unsigned int signingKeyUsage(bool openpgp, bool smime, bool trusted, bool valid)
{
return foo(openpgp, smime, trusted, valid) | Kleo::KeySelectionDialog::SigningKeys | Kleo::KeySelectionDialog::SecretKeys;
}
Kleo::EncryptionKeyRequester::EncryptionKeyRequester(bool multi, unsigned int proto, QWidget *parent, bool onlyTrusted, bool onlyValid)
: KeyRequester(encryptionKeyUsage(proto & OpenPGP, proto & SMIME, onlyTrusted, onlyValid), multi, parent)
, d(nullptr)
{
}
Kleo::EncryptionKeyRequester::EncryptionKeyRequester(QWidget *parent)
: KeyRequester(0, false, parent)
, d(nullptr)
{
}
Kleo::EncryptionKeyRequester::~EncryptionKeyRequester()
{
}
void Kleo::EncryptionKeyRequester::setAllowedKeys(unsigned int proto, bool onlyTrusted, bool onlyValid)
{
KeyRequester::setAllowedKeys(encryptionKeyUsage(proto & OpenPGP, proto & SMIME, onlyTrusted, onlyValid));
}
Kleo::SigningKeyRequester::SigningKeyRequester(bool multi, unsigned int proto, QWidget *parent, bool onlyTrusted, bool onlyValid)
: KeyRequester(signingKeyUsage(proto & OpenPGP, proto & SMIME, onlyTrusted, onlyValid), multi, parent)
, d(nullptr)
{
}
Kleo::SigningKeyRequester::SigningKeyRequester(QWidget *parent)
: KeyRequester(0, false, parent)
, d(nullptr)
{
}
Kleo::SigningKeyRequester::~SigningKeyRequester()
{
}
void Kleo::SigningKeyRequester::setAllowedKeys(unsigned int proto, bool onlyTrusted, bool onlyValid)
{
KeyRequester::setAllowedKeys(signingKeyUsage(proto & OpenPGP, proto & SMIME, onlyTrusted, onlyValid));
}
void Kleo::KeyRequester::virtual_hook(int, void *)
{
}
void Kleo::EncryptionKeyRequester::virtual_hook(int id, void *data)
{
KeyRequester::virtual_hook(id, data);
}
void Kleo::SigningKeyRequester::virtual_hook(int id, void *data)
{
KeyRequester::virtual_hook(id, data);
}

File Metadata

Mime Type
text/x-c
Expires
Fri, Mar 13, 8:34 AM (11 h, 19 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
8c/2b/44f17351572c7e4227e9eb570ec2

Event Timeline