Automatically add recipients from decryptresult

In notepad this makes the workflow of "decrypt and answer"
easy as the sender of a message usually encrypted the message
also to himself. So by default for an Answer you don't
have to do any key selection.
parent 3f34d34c
......@@ -174,6 +174,7 @@ set(_kleopatra_SRCS
crypto/gui/signemailwizard.cpp
crypto/gui/signencryptwidget.cpp
crypto/gui/signencryptwizard.cpp
crypto/gui/unknownrecipientwidget.cpp
crypto/gui/verifychecksumsdialog.cpp
......
......@@ -897,6 +897,11 @@ GpgME::VerificationResult DecryptVerifyResult::verificationResult() const
return d->m_verificationResult;
}
GpgME::DecryptionResult DecryptVerifyResult::decryptionResult() const
{
return d->m_decryptionResult;
}
class AbstractDecryptVerifyTask::Private
{
public:
......
......@@ -246,6 +246,7 @@ public:
QPointer<Task> parentTask() const override;
GpgME::VerificationResult verificationResult() const;
GpgME::DecryptionResult decryptionResult() const;
private:
static QString keyToString(const GpgME::Key &key);
......
......@@ -35,6 +35,7 @@
#include "kleopatra_debug.h"
#include "certificatelineedit.h"
#include "unknownrecipientwidget.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
......@@ -236,9 +237,60 @@ void SignEncryptWidget::addRecipient(const Key &key)
if (!key.isNull()) {
certSel->setKey(key);
mAddedKeys << key;
}
}
void SignEncryptWidget::clearAddedRecipients()
{
for (auto w: mUnknownWidgets) {
mRecpLayout->removeWidget(w);
delete w;
}
for (auto &key: mAddedKeys) {
removeRecipient(key);
}
}
void SignEncryptWidget::addUnknownRecipient(const char *keyID)
{
auto unknownWidget = new UnknownRecipientWidget(keyID);
mUnknownWidgets << unknownWidget;
if (!mRecpLayout->itemAtPosition(mRecpRowCount - 1, 1)) {
// First widget. Should align with the row above that
// contians the encrypt for others checkbox.
mRecpLayout->addWidget(unknownWidget, mRecpRowCount - 1, 1);
} else {
mRecpLayout->addWidget(unknownWidget, mRecpRowCount++, 1);
}
connect(KeyCache::instance().get(), &Kleo::KeyCache::keysMayHaveChanged,
this, [this] () {
// Check if any unknown recipient can now be found.
for (auto w: mUnknownWidgets) {
auto key = KeyCache::instance()->findByKeyIDOrFingerprint(w->keyID().toLatin1().constData());
if (key.isNull()) {
std::vector<std::string> subids;
subids.push_back(std::string(w->keyID().toLatin1().constData()));
for (const auto &subkey: KeyCache::instance()->findSubkeysByKeyID(subids)) {
key = subkey.parent();
}
}
if (key.isNull()) {
continue;
}
// Key is now available replace by line edit.
qCDebug(KLEOPATRA_LOG) << "Removing widget for keyid: " << w->keyID();
mRecpLayout->removeWidget(w);
mUnknownWidgets.removeAll(w);
delete w;
addRecipient(key);
}
});
}
void SignEncryptWidget::recipientsChanged()
{
bool oneEmpty = false;
......@@ -369,6 +421,23 @@ void SignEncryptWidget::recpRemovalRequested(CertificateLineEdit *w)
}
}
void SignEncryptWidget::removeRecipient(const GpgME::Key &key)
{
for (CertificateLineEdit *edit: mRecpWidgets) {
const auto editKey = edit->key();
if (key.isNull() && editKey.isNull()) {
recpRemovalRequested(edit);
return;
}
if (editKey.primaryFingerprint() &&
key.primaryFingerprint() &&
!strcmp(editKey.primaryFingerprint(), key.primaryFingerprint())) {
recpRemovalRequested(edit);
return;
}
}
}
bool SignEncryptWidget::encryptSymmetric() const
{
return mSymmetric->isChecked();
......
......@@ -44,6 +44,7 @@ namespace Kleo
class CertificateLineEdit;
class KeySelectionCombo;
class AbstractKeyListModel;
class UnknownRecipientWidget;
class SignEncryptWidget: public QWidget
{
......@@ -88,12 +89,23 @@ public:
* S/MIME and OpenPGP */
void setProtocol(GpgME::Protocol protocol);
/** Add a recipient with the key key */
void addRecipient(const GpgME::Key &key);
/** Add a placehoder for an unknown key */
void addUnknownRecipient(const char *keyId);
/** Remove all Recipients added by keyId or by key. */
void clearAddedRecipients();
/** Remove a Recipient key */
void removeRecipient(const GpgME::Key &key);
protected Q_SLOTS:
void updateOp();
void recipientsChanged();
void recpRemovalRequested(CertificateLineEdit *w);
void addRecipient();
void addRecipient(const GpgME::Key &key);
protected:
void loadKeys();
......@@ -111,6 +123,8 @@ private:
KeySelectionCombo *mSigSelect,
*mSelfSelect;
QVector<CertificateLineEdit *> mRecpWidgets;
QVector<UnknownRecipientWidget *> mUnknownWidgets;
QVector<GpgME::Key> mAddedKeys;
QGridLayout *mRecpLayout;
QString mOp;
AbstractKeyListModel *mModel;
......
/* crypto/gui/unknownrecipientwidget.cpp
This file is part of Kleopatra, the KDE keymanager
Copyright (c) 2018 by Intevation GmbH
Kleopatra is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
Kleopatra is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
In addition, as a special exception, the copyright holders give
permission to link the code of this program with any edition of
the Qt library by Trolltech AS, Norway (or with modified versions
of Qt that use the same license as Qt), and distribute linked
combinations including the two. You must obey the GNU General
Public License in all respects for all of the code used other than
Qt. If you modify this file, you may extend this exception to
your version of the file, but you are not obligated to do so. If
you do not wish to do so, delete this exception statement from
your version.
*/
#include "unknownrecipientwidget.h"
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QFont>
#include "commands/lookupcertificatescommand.h"
#include <KLocalizedString>
using namespace Kleo;
UnknownRecipientWidget::UnknownRecipientWidget(const char *keyid,
QWidget *parent):
QWidget(parent)
{
auto hLay = new QHBoxLayout(this);
auto caption = new QLabel(i18nc("Caption for an unknwon key/certificate where only ID is known.",
"Unknown Recipient:"));
mKeyID = QString::fromLatin1(keyid);
auto keyIdLabel = new QLabel(mKeyID);
keyIdLabel->setFont(QFont("Monospace"));
auto lookUpBtn = new QPushButton(i18n("Search"));
lookUpBtn->setIcon(QIcon::fromTheme("edit-find"));
lookUpBtn->setToolTip(i18n("Search on keyserver"));
connect (lookUpBtn, &QPushButton::clicked, this, [this, lookUpBtn] () {
lookUpBtn->setEnabled(false);
auto cmd = new Kleo::Commands::LookupCertificatesCommand(mKeyID, nullptr);
connect(cmd, &Kleo::Commands::LookupCertificatesCommand::finished,
this, [lookUpBtn]() {
lookUpBtn->setEnabled(true);
});
cmd->setParentWidget(this->parentWidget());
cmd->start();
});
hLay->addWidget(caption);
hLay->addWidget(keyIdLabel);
hLay->addWidget(lookUpBtn);
hLay->addStretch(1);
setToolTip(i18n("The data was encrypted to this key / certificate."));
}
QString UnknownRecipientWidget::keyID() const {
return mKeyID;
}
/* crypto/gui/unknownrecipientwidget.h
This file is part of Kleopatra, the KDE keymanager
Copyright (c) 2018 by Intevation GmbH
Kleopatra is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
Kleopatra is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
In addition, as a special exception, the copyright holders give
permission to link the code of this program with any edition of
the Qt library by Trolltech AS, Norway (or with modified versions
of Qt that use the same license as Qt), and distribute linked
combinations including the two. You must obey the GNU General
Public License in all respects for all of the code used other than
Qt. If you modify this file, you may extend this exception to
your version of the file, but you are not obligated to do so. If
you do not wish to do so, delete this exception statement from
your version.
*/
#ifndef CRYPTO_GUI_UNKNOWNRECIPIENTWIDGET_H
#define CRYPTO_GUI_UNKNOWNRECIPIENTWIDGET_H
#include <QWidget>
#include <QString>
namespace Kleo
{
class UnknownRecipientWidget: public QWidget
{
Q_OBJECT
public:
explicit UnknownRecipientWidget(const char *keyid, QWidget *parent = nullptr);
QString keyID() const;
private:
QString mKeyID;
};
} // namespace Kleo:
#endif
......@@ -35,6 +35,7 @@
#include <Libkleo/Exception>
#include <Libkleo/Classify>
#include <Libkleo/KeyCache>
#include "crypto/gui/signencryptwidget.h"
#include "crypto/gui/resultitemwidget.h"
......@@ -45,6 +46,8 @@
#include "utils/input.h"
#include "utils/output.h"
#include <gpgme++/decryptionresult.h>
#include <QTextEdit>
#include <QToolBar>
#include <QVBoxLayout>
......@@ -160,6 +163,51 @@ public:
mRevertBtn->setVisible(false);
}
void updateRecipientsFromResult(const Kleo::Crypto::DecryptVerifyResult &result)
{
const auto decResult = result.decryptionResult();
for (const auto &recipient: decResult.recipients()) {
if (!recipient.keyID()) {
continue;
}
GpgME::Key key;
if (strlen(recipient.keyID()) < 16) {
key = KeyCache::instance()->findByShortKeyID(recipient.keyID());
} else {
key = KeyCache::instance()->findByKeyIDOrFingerprint(recipient.keyID());
}
if (key.isNull()) {
std::vector<std::string> subids;
subids.push_back(std::string(recipient.keyID()));
for (const auto &subkey: KeyCache::instance()->findSubkeysByKeyID(subids)) {
key = subkey.parent();
break;
}
}
if (key.isNull()) {
qCDebug(KLEOPATRA_LOG) << "Unknown key" << recipient.keyID();
mSigEncWidget->addUnknownRecipient(recipient.keyID());
continue;
}
bool keyFound = false;
for (const auto &existingKey: mSigEncWidget->recipients()) {
if (existingKey.primaryFingerprint() && key.primaryFingerprint() &&
!strcmp (existingKey.primaryFingerprint(), key.primaryFingerprint())) {
keyFound = true;
break;
}
}
if (!keyFound) {
mSigEncWidget->addRecipient(key);
}
}
}
void cryptDone(const std::shared_ptr<const Kleo::Crypto::Task::Result> &result)
{
updateCommitButton();
......@@ -186,11 +234,17 @@ public:
mEdit->setPlainText(QString::fromUtf8(mOutputData));
mOutputData.clear();
mRevertBtn->setVisible(true);
const auto decryptVerifyResult = dynamic_cast<const Kleo::Crypto::DecryptVerifyResult*>(result.get());
if (decryptVerifyResult) {
updateRecipientsFromResult(*decryptVerifyResult);
}
}
void doDecryptVerify()
{
doCryptoCommon();
mSigEncWidget->clearAddedRecipients();
mProgressLabel->setText(i18n("Decrypt / Verify") + QStringLiteral("..."));
auto input = Input::createFromByteArray(&mInputData, i18n("Notepad"));
auto output = Output::createFromByteArray(&mOutputData, i18n("Notepad"));
......@@ -324,6 +378,7 @@ private:
QLabel *mProgressLabel;
QVBoxLayout *mStatusLay;
ResultItemWidget *mLastResultWidget;
QList<GpgME::Key> mAutoAddedKeys;
};
PadWidget::PadWidget(QWidget *parent):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment