diff --git a/src/crypto/gui/certificateselectionline.cpp b/src/crypto/gui/certificateselectionline.cpp index e5d3eaea5..94a4581f2 100644 --- a/src/crypto/gui/certificateselectionline.cpp +++ b/src/crypto/gui/certificateselectionline.cpp @@ -1,341 +1,341 @@ /* crypto/gui/certificateselectionline.cpp This file is part of Kleopatra, the KDE keymanager Copyright (c) 2009 Klarälvdalens Datakonsult AB 2016 by Bundesamt für Sicherheit in der Informationstechnik Software engineering 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 "certificateselectionline.h" #include #include #include #include #include #include #include #include "utils/kleo_assert.h" #include #include #include using namespace Kleo; using namespace GpgME; Q_DECLARE_METATYPE(GpgME::Key) namespace { static QString make_initial_text(const std::vector &keys) { if (keys.empty()) { return i18n("(no matching certificates found)"); } else { return i18n("Please select a certificate"); } } // A QComboBox with an initial text (as known from web browsers) // // only works with read-only QComboBoxen, doesn't affect sizeHint // as it should... // class ComboBox : public QComboBox { Q_OBJECT Q_PROPERTY(QString initialText READ initialText WRITE setInitialText) Q_PROPERTY(QIcon initialIcon READ initialIcon WRITE setInitialIcon) public: explicit ComboBox(QWidget *parent = nullptr) : QComboBox(parent), m_initialText(), m_initialIcon() { } explicit ComboBox(const QString &initialText, QWidget *parent = nullptr) : QComboBox(parent), m_initialText(initialText), m_initialIcon() { } explicit ComboBox(const QIcon &initialIcon, const QString &initialText, QWidget *parent = nullptr) : QComboBox(parent), m_initialText(initialText), m_initialIcon(initialIcon) { } QString initialText() const { return m_initialText; } QIcon initialIcon() const { return m_initialIcon; } public Q_SLOTS: void setInitialText(const QString &txt) { if (txt == m_initialText) { return; } m_initialText = txt; if (currentIndex() == -1) { update(); } } void setInitialIcon(const QIcon &icon) { if (icon.cacheKey() == m_initialIcon.cacheKey()) { return; } m_initialIcon = icon; if (currentIndex() == -1) { update(); } } protected: void paintEvent(QPaintEvent *) override { QStylePainter p(this); p.setPen(palette().color(QPalette::Text)); QStyleOptionComboBox opt; initStyleOption(&opt); p.drawComplexControl(QStyle::CC_ComboBox, opt); if (currentIndex() == -1) { opt.currentText = m_initialText; opt.currentIcon = m_initialIcon; } p.drawControl(QStyle::CE_ComboBoxLabel, opt); } private: QString m_initialText; QIcon m_initialIcon; }; } // anonymous namespace class Kleo::KeysComboBox : public ComboBox { Q_OBJECT public: explicit KeysComboBox(QWidget *parent = nullptr) : ComboBox(parent) {} explicit KeysComboBox(const QString &initialText, QWidget *parent = nullptr) : ComboBox(initialText, parent) {} explicit KeysComboBox(const std::vector &keys, QWidget *parent = nullptr) : ComboBox(make_initial_text(keys), parent) { setKeys(keys); } void setKeys(const std::vector &keys) { clear(); for (const Key &key : keys) { addItem(Formatting::formatForComboBox(key), qVariantFromValue(key)); } } std::vector keys() const { std::vector result; result.reserve(count()); for (int i = 0, end = count(); i != end; ++i) { result.push_back(qvariant_cast(itemData(i))); } - return result;; + return result; } int findOrAdd(const Key &key) { for (int i = 0, end = count(); i != end; ++i) if (_detail::ByFingerprint()(key, qvariant_cast(itemData(i)))) { return i; } insertItem(0, Formatting::formatForComboBox(key), qVariantFromValue(key)); return 0; } void addAndSelectCertificate(const Key &key) { setCurrentIndex(findOrAdd(key)); } Key currentKey() const { return qvariant_cast(itemData(currentIndex())); } }; CertificateSelectionLine::CertificateSelectionLine(const QString &toFrom, const QString &mailbox, const std::vector &pgp, bool pgpAmbig, const std::vector &cms, bool cmsAmbig, QWidget *q, QGridLayout &glay) : pgpAmbiguous(pgpAmbig), cmsAmbiguous(cmsAmbig), mToFromLB(new QLabel(toFrom, q)), mMailboxLB(new QLabel(mailbox, q)), mSbox(new QStackedWidget(q)), mPgpCB(new KeysComboBox(pgp, mSbox)), mCmsCB(new KeysComboBox(cms, mSbox)), noProtocolCB(new KeysComboBox(i18n("(please choose between OpenPGP and S/MIME first)"), mSbox)), mToolTB(new QToolButton(q)) { QFont bold; bold.setBold(true); mToFromLB->setFont(bold); mMailboxLB->setTextFormat(Qt::PlainText); mToolTB->setText(i18n("...")); mPgpCB->setEnabled(!pgp.empty()); mCmsCB->setEnabled(!cms.empty()); noProtocolCB->setEnabled(false); mPgpCB->setKeys(pgp); if (pgpAmbiguous) { mPgpCB->setCurrentIndex(-1); } mCmsCB->setKeys(cms); if (cmsAmbiguous) { mCmsCB->setCurrentIndex(-1); } mSbox->addWidget(mPgpCB); mSbox->addWidget(mCmsCB); mSbox->addWidget(noProtocolCB); mSbox->setCurrentWidget(noProtocolCB); const int row = glay.rowCount(); unsigned int col = 0; glay.addWidget(mToFromLB, row, col++); glay.addWidget(mMailboxLB, row, col++); glay.addWidget(mSbox, row, col++); glay.addWidget(mToolTB, row, col++); Q_ASSERT(col == NumColumns); q->connect(mPgpCB, SIGNAL(currentIndexChanged(int)), SLOT(slotCompleteChanged())); q->connect(mCmsCB, SIGNAL(currentIndexChanged(int)), SLOT(slotCompleteChanged())); q->connect(mToolTB, SIGNAL(clicked()), SLOT(slotCertificateSelectionDialogRequested())); } QString CertificateSelectionLine::mailboxText() const { return mMailboxLB->text(); } void CertificateSelectionLine::addAndSelectCertificate(const Key &key) const { if (KeysComboBox *const cb = comboBox(key.protocol())) { cb->addAndSelectCertificate(key); cb->setEnabled(true); } } void CertificateSelectionLine::showHide(Protocol proto, bool &first, bool showAll, bool op) const { if (op && (showAll || wasInitiallyAmbiguous(proto))) { mToFromLB->setVisible(first); first = false; QFont font = mMailboxLB->font(); font.setBold(wasInitiallyAmbiguous(proto)); mMailboxLB->setFont(font); mSbox->setCurrentIndex(proto); mMailboxLB->show(); mSbox->show(); mToolTB->show(); } else { mToFromLB->hide(); mMailboxLB->hide(); mSbox->hide(); mToolTB->hide(); } } bool CertificateSelectionLine::wasInitiallyAmbiguous(Protocol proto) const { return (proto == OpenPGP && pgpAmbiguous) || (proto == CMS && cmsAmbiguous); } bool CertificateSelectionLine::isStillAmbiguous(Protocol proto) const { kleo_assert(proto == OpenPGP || proto == CMS); const KeysComboBox *const cb = comboBox(proto); return cb->currentIndex() == -1; } Key CertificateSelectionLine::key(Protocol proto) const { kleo_assert(proto == OpenPGP || proto == CMS); const KeysComboBox *const cb = comboBox(proto); return cb->currentKey(); } const QToolButton *CertificateSelectionLine::toolButton() const { return mToolTB; } void CertificateSelectionLine::kill() { delete mToFromLB; delete mMailboxLB; delete mSbox; delete mToolTB; } KeysComboBox *CertificateSelectionLine::comboBox(Protocol proto) const { if (proto == OpenPGP) { return mPgpCB; } if (proto == CMS) { return mCmsCB; } return nullptr; } #include "certificateselectionline.moc" diff --git a/src/uiserver/decryptverifycommandemailbase.cpp b/src/uiserver/decryptverifycommandemailbase.cpp index ca6846253..b7067703d 100644 --- a/src/uiserver/decryptverifycommandemailbase.cpp +++ b/src/uiserver/decryptverifycommandemailbase.cpp @@ -1,235 +1,235 @@ /* -*- mode: c++; c-basic-offset:4 -*- uiserver/decryptverifycommandemailbase.cpp This file is part of Kleopatra, the KDE keymanager Copyright (c) 2007 Klarälvdalens Datakonsult AB 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 #include "decryptverifycommandemailbase.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace Kleo; using namespace Kleo::Crypto; using namespace Kleo::Formatting; using namespace GpgME; class DecryptVerifyCommandEMailBase::Private : public QObject { Q_OBJECT friend class ::Kleo::DecryptVerifyCommandEMailBase; DecryptVerifyCommandEMailBase *const q; public: explicit Private(DecryptVerifyCommandEMailBase *qq) : QObject(), q(qq), controller() { } ~Private() { } void checkForErrors() const; public Q_SLOTS: void slotProgress(const QString &what, int current, int total); void verificationResult(const GpgME::VerificationResult &); void slotDone() { q->done(); } void slotError(int err, const QString &details) { q->done(err, details); } public: private: std::shared_ptr controller; }; DecryptVerifyCommandEMailBase::DecryptVerifyCommandEMailBase() : AssuanCommandMixin(), d(new Private(this)) { } DecryptVerifyCommandEMailBase::~DecryptVerifyCommandEMailBase() {} int DecryptVerifyCommandEMailBase::doStart() { d->checkForErrors(); d->controller.reset(new DecryptVerifyEMailController(shared_from_this())); const QString st = sessionTitle(); if (!st.isEmpty()) Q_FOREACH (const std::shared_ptr &i, inputs()) { i->setLabel(st); } d->controller->setSessionId(sessionId()); d->controller->setOperation(operation()); d->controller->setVerificationMode(messages().empty() ? Opaque : Detached); d->controller->setInputs(inputs()); d->controller->setSignedData(messages()); d->controller->setOutputs(outputs()); d->controller->setWizardShown(!hasOption("silent")); d->controller->setProtocol(checkProtocol(mode())); if (informativeSenders()) { d->controller->setInformativeSenders(senders()); } QObject::connect(d->controller.get(), SIGNAL(done()), d.get(), SLOT(slotDone()), Qt::QueuedConnection); QObject::connect(d->controller.get(), SIGNAL(error(int,QString)), d.get(), SLOT(slotError(int,QString)), Qt::QueuedConnection); QObject::connect(d->controller.get(), &DecryptVerifyEMailController::verificationResult, d.get(), &Private::verificationResult, Qt::QueuedConnection); d->controller->start(); return 0; } void DecryptVerifyCommandEMailBase::Private::checkForErrors() const { if (!q->senders().empty() && !q->informativeSenders()) throw Kleo::Exception(q->makeError(GPG_ERR_CONFLICT), i18n("Cannot use non-info SENDER")); if (!q->recipients().empty() && !q->informativeRecipients()) throw Kleo::Exception(q->makeError(GPG_ERR_CONFLICT), i18n("Cannot use non-info RECIPIENT")); // ### use informative recipients and senders const unsigned int numInputs = q->inputs().size(); const unsigned int numMessages = q->messages().size(); const unsigned int numOutputs = q->outputs().size(); const unsigned int numInformativeSenders = q->informativeSenders() ? q->senders().size() : 0; - const DecryptVerifyOperation op = q->operation();; + const DecryptVerifyOperation op = q->operation(); const GpgME::Protocol proto = q->checkProtocol(q->mode()); const unsigned int numFiles = q->numFiles(); if (numFiles) { throw Kleo::Exception(q->makeError(GPG_ERR_CONFLICT), i18n("FILES present")); } if (!numInputs) throw Kleo::Exception(q->makeError(GPG_ERR_ASS_NO_INPUT), i18n("At least one INPUT needs to be provided")); if (numInformativeSenders != 0) if (numInformativeSenders != numInputs) throw Kleo::Exception(q->makeError(GPG_ERR_ASS_NO_INPUT), //TODO use better error code if possible i18n("INPUT/SENDER --info count mismatch")); if (numMessages) { if (numMessages != numInputs) throw Kleo::Exception(q->makeError(GPG_ERR_ASS_NO_INPUT), //TODO use better error code if possible i18n("INPUT/MESSAGE count mismatch")); else if (op != Verify) throw Kleo::Exception(q->makeError(GPG_ERR_CONFLICT), i18n("MESSAGE can only be given for detached signature verification")); } if (numOutputs) { if (numOutputs != numInputs) throw Kleo::Exception(q->makeError(GPG_ERR_ASS_NO_OUTPUT), //TODO use better error code if possible i18n("INPUT/OUTPUT count mismatch")); else if (numMessages) throw Kleo::Exception(q->makeError(GPG_ERR_CONFLICT), i18n("Cannot use OUTPUT and MESSAGE simultaneously")); } kleo_assert(proto != UnknownProtocol); const auto backend = (proto == GpgME::OpenPGP) ? QGpgME::openpgp() : QGpgME::smime(); if (!backend) throw Kleo::Exception(q->makeError(GPG_ERR_UNSUPPORTED_PROTOCOL), proto == OpenPGP ? i18n("No backend support for OpenPGP") : proto == CMS ? i18n("No backend support for S/MIME") : QString()); } void DecryptVerifyCommandEMailBase::doCanceled() { if (d->controller) { d->controller->cancel(); } } void DecryptVerifyCommandEMailBase::Private::slotProgress(const QString &what, int current, int total) { Q_UNUSED(what); Q_UNUSED(current); Q_UNUSED(total); // ### FIXME report progress, via sendStatus() } void DecryptVerifyCommandEMailBase::Private::verificationResult(const VerificationResult &vResult) { try { const std::vector sigs = vResult.signatures(); Q_FOREACH (const Signature &sig, sigs) { const QString s = signatureToString(sig, sig.key(true, true)); const char *color = summaryToString(sig.summary()); q->sendStatusEncoded("SIGSTATUS", color + (' ' + hexencode(s.toUtf8().constData()))); } } catch (...) {} } #include "decryptverifycommandemailbase.moc"