Index: messageviewer/autotests/unencryptedmessagetest.cpp =================================================================== --- messageviewer/autotests/unencryptedmessagetest.cpp +++ messageviewer/autotests/unencryptedmessagetest.cpp @@ -39,7 +39,8 @@ void testSignedForwardedOpenPGPSignedEncrypted(); void testOpenPGPEncrypted(); void testOpenPGPEncryptedNotDecrypted(); - void testOpenPGPEncryptedAsync(); + void testAsync_data(); + void testAsync(); void testInlinePGPEncryptedNotDecrypted(); }; @@ -212,9 +213,23 @@ QCOMPARE((bool) unencryptedMessage, false); } -void UnencryptedMessageTest::testOpenPGPEncryptedAsync() +void UnencryptedMessageTest::testAsync_data() { - KMime::Message::Ptr originalMessage = readAndParseMail(QStringLiteral("openpgp-encrypted.mbox")); + QTest::addColumn("mailFileName"); + QTest::addColumn("output"); + + QTest::newRow("openpgp-encrypt") << QStringLiteral("openpgp-encrypted.mbox") << QStringLiteral("encrypted message text"); + QTest::newRow("smime-opaque-sign") << QStringLiteral("smime-opaque-sign.mbox") << QStringLiteral("A simple signed only test."); + QTest::newRow("smime-encrypt") << QStringLiteral("smime-encrypted.mbox") << QStringLiteral("The quick brown fox jumped over the lazy dog."); + QTest::newRow("openpgp-inline-encrypt") << QStringLiteral("openpgp-inline-charset-encrypted.mbox") << QStringLiteral("asdasd asd asd asdf sadf sdaf sadf \u00F6\u00E4\u00FC"); +} + +void UnencryptedMessageTest::testAsync() +{ + QFETCH(QString, mailFileName); + QFETCH(QString, output); + + KMime::Message::Ptr originalMessage = readAndParseMail(mailFileName); NodeHelper nodeHelper; EmptySource emptySource; emptySource.setAllowDecryption(true); @@ -225,16 +240,14 @@ connect(&nodeHelper, SIGNAL(update(MessageViewer::Viewer::UpdateMode)), &loop, SLOT(quit())); otp.setAllowAsync(true); otp.parseObjectTree(originalMessage.data()); - QCOMPARE(otp.plainTextContent().toLatin1().data(), ""); loop.exec(); } - // Cryptjob ended + // Job ended { ObjectTreeParser otp(&emptySource, &nodeHelper); otp.setAllowAsync(true); otp.parseObjectTree(originalMessage.data()); - QCOMPARE(otp.plainTextContent().toLatin1().data(), "encrypted message text"); - QCOMPARE(nodeHelper.overallEncryptionState(originalMessage.data()), KMMsgFullyEncrypted); + QCOMPARE(otp.plainTextContent(), output); } } Index: messageviewer/src/viewer/memento/cryptobodypartmemento.h =================================================================== --- messageviewer/src/viewer/memento/cryptobodypartmemento.h +++ messageviewer/src/viewer/memento/cryptobodypartmemento.h @@ -40,6 +40,8 @@ CryptoBodyPartMemento(); ~CryptoBodyPartMemento(); + virtual bool start() = 0; + virtual void exec() = 0; bool isRunning() const; const QString &auditLogAsHtml() const Index: messageviewer/src/viewer/memento/decryptverifybodypartmemento.h =================================================================== --- messageviewer/src/viewer/memento/decryptverifybodypartmemento.h +++ messageviewer/src/viewer/memento/decryptverifybodypartmemento.h @@ -46,8 +46,8 @@ DecryptVerifyBodyPartMemento(Kleo::DecryptVerifyJob *job, const QByteArray &cipherText); ~DecryptVerifyBodyPartMemento(); - bool start(); - void exec(); + bool start() Q_DECL_OVERRIDE; + void exec() Q_DECL_OVERRIDE; const QByteArray &plainText() const { Index: messageviewer/src/viewer/memento/verifydetachedbodypartmemento.h =================================================================== --- messageviewer/src/viewer/memento/verifydetachedbodypartmemento.h +++ messageviewer/src/viewer/memento/verifydetachedbodypartmemento.h @@ -52,8 +52,8 @@ const QByteArray &plainText); ~VerifyDetachedBodyPartMemento(); - bool start(); - void exec(); + bool start() Q_DECL_OVERRIDE; + void exec() Q_DECL_OVERRIDE; const GpgME::VerificationResult &verifyResult() const { Index: messageviewer/src/viewer/memento/verifyopaquebodypartmemento.h =================================================================== --- messageviewer/src/viewer/memento/verifyopaquebodypartmemento.h +++ messageviewer/src/viewer/memento/verifyopaquebodypartmemento.h @@ -51,8 +51,8 @@ const QByteArray &signature); ~VerifyOpaqueBodyPartMemento(); - bool start(); - void exec(); + bool start() Q_DECL_OVERRIDE; + void exec() Q_DECL_OVERRIDE; const QByteArray &plainText() const { Index: messageviewer/src/viewer/objecttreeparser.h =================================================================== --- messageviewer/src/viewer/objecttreeparser.h +++ messageviewer/src/viewer/objecttreeparser.h @@ -453,7 +453,7 @@ bool &decryptionStarted, PartMetaData &partMetaData); - bool okVerify(const QByteArray &data, const Kleo::CryptoBackend::Protocol *cryptProto, MessageViewer::PartMetaData &messagePart, QByteArray &verifiedText, std::vector< GpgME::Signature > &signatures); + bool okVerify(const QByteArray &data, const Kleo::CryptoBackend::Protocol *cryptProto, MessageViewer::PartMetaData &messagePart, QByteArray &verifiedText, std::vector &signatures, const QByteArray &signature, KMime::Content *sign); void sigStatusToMetaData(const std::vector &signatures, const Kleo::CryptoBackend::Protocol *cryptoProtocol, PartMetaData &messagePart, GpgME::Key key); bool processMailmanMessage(KMime::Content *node); Index: messageviewer/src/viewer/objecttreeparser.cpp =================================================================== --- messageviewer/src/viewer/objecttreeparser.cpp +++ messageviewer/src/viewer/objecttreeparser.cpp @@ -5,6 +5,7 @@ Copyright (c) 2003 Marc Mutz Copyright (C) 2002-2004 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.net Copyright (c) 2009 Andras Mantia + Copyright (c) 2015 Sandro Knauß KMail is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2, as @@ -603,155 +604,19 @@ GpgME::Key key; if (doCheck && cryptProto) { -#ifdef DEBUG_SIGNATURE - qCDebug(MESSAGEVIEWER_LOG) << "tokoe: doCheck and cryptProto"; -#endif GpgME::VerificationResult result; if (data) { // detached -#ifdef DEBUG_SIGNATURE - qCDebug(MESSAGEVIEWER_LOG) << "tokoe: is detached signature"; -#endif - const VerifyDetachedBodyPartMemento *m - = dynamic_cast(mNodeHelper->bodyPartMemento(&sign, "verifydetached")); - if (!m) { -#ifdef DEBUG_SIGNATURE - qCDebug(MESSAGEVIEWER_LOG) << "tokoe: no memento available"; -#endif - Kleo::VerifyDetachedJob *job = cryptProto->verifyDetachedJob(); - if (!job) { - cryptPlugError = CANT_VERIFY_SIGNATURES; - // PENDING(marc) cryptProto = 0 here? - } else { - QByteArray plainData = cleartext; - VerifyDetachedBodyPartMemento *newM - = new VerifyDetachedBodyPartMemento(job, cryptProto->keyListJob(), signaturetext, plainData); - if (allowAsync()) { -#ifdef DEBUG_SIGNATURE - qCDebug(MESSAGEVIEWER_LOG) << "tokoe: allowAsync"; -#endif - QObject::connect(newM, &CryptoBodyPartMemento::update, - mNodeHelper, &NodeHelper::update); - QObject::connect(newM, SIGNAL(update(MessageViewer::Viewer::UpdateMode)), - mSource->sourceObject(), SLOT(update(MessageViewer::Viewer::UpdateMode))); - if (newM->start()) { -#ifdef DEBUG_SIGNATURE - qCDebug(MESSAGEVIEWER_LOG) << "tokoe: new memento started"; -#endif - messagePart.inProgress = true; - mHasPendingAsyncJobs = true; - } else { - m = newM; - } - } else { - newM->exec(); - m = newM; - } - mNodeHelper->setBodyPartMemento(&sign, "verifydetached", newM); - } - } else if (m->isRunning()) { -#ifdef DEBUG_SIGNATURE - qCDebug(MESSAGEVIEWER_LOG) << "tokoe: memento is running"; -#endif - messagePart.inProgress = true; - mHasPendingAsyncJobs = true; - m = 0; - } - - if (m) { -#ifdef DEBUG_SIGNATURE - qCDebug(MESSAGEVIEWER_LOG) << "tokoe: memento finished, assign result"; -#endif - result = m->verifyResult(); - messagePart.auditLogError = m->auditLogError(); - messagePart.auditLog = m->auditLogAsHtml(); - key = m->signingKey(); - } + okVerify(cleartext, cryptProto, messagePart, cleartext, signatures, signaturetext, &sign); } else { // opaque -#ifdef DEBUG_SIGNATURE - qCDebug(MESSAGEVIEWER_LOG) << "tokoe: is opaque signature"; -#endif - const VerifyOpaqueBodyPartMemento *m - = dynamic_cast(mNodeHelper->bodyPartMemento(&sign, "verifyopaque")); - if (!m) { -#ifdef DEBUG_SIGNATURE - qCDebug(MESSAGEVIEWER_LOG) << "tokoe: no memento available"; -#endif - Kleo::VerifyOpaqueJob *job = cryptProto->verifyOpaqueJob(); - if (!job) { - cryptPlugError = CANT_VERIFY_SIGNATURES; - // PENDING(marc) cryptProto = 0 here? - } else { - VerifyOpaqueBodyPartMemento *newM - = new VerifyOpaqueBodyPartMemento(job, cryptProto->keyListJob(), signaturetext); - if (allowAsync()) { -#ifdef DEBUG_SIGNATURE - qCDebug(MESSAGEVIEWER_LOG) << "tokoe: allowAsync"; -#endif - QObject::connect(newM, SIGNAL(update(MessageViewer::Viewer::UpdateMode)), mSource->sourceObject(), - SLOT(update(MessageViewer::Viewer::UpdateMode))); - if (newM->start()) { -#ifdef DEBUG_SIGNATURE - qCDebug(MESSAGEVIEWER_LOG) << "tokoe: new memento started"; -#endif - messagePart.inProgress = true; - mHasPendingAsyncJobs = true; - } else { - m = newM; - } - } else { - newM->exec(); - m = newM; - } - mNodeHelper->setBodyPartMemento(&sign, "verifyopaque", newM); - } - } else if (m->isRunning()) { -#ifdef DEBUG_SIGNATURE - qCDebug(MESSAGEVIEWER_LOG) << "tokoe: memento is running"; -#endif - messagePart.inProgress = true; - mHasPendingAsyncJobs = true; - m = 0; - } - - if (m) { -#ifdef DEBUG_SIGNATURE - qCDebug(MESSAGEVIEWER_LOG) << "tokoe: memento finished, assign result"; -#endif - result = m->verifyResult(); - cleartext = m->plainText(); - messagePart.auditLogError = m->auditLogError(); - messagePart.auditLog = m->auditLogAsHtml(); - key = m->signingKey(); - } + okVerify(signaturetext, cryptProto, messagePart, cleartext, signatures, QByteArray(), &sign); } - std::stringstream ss; - ss << result; -#ifdef DEBUG_SIGNATURE - qCDebug(MESSAGEVIEWER_LOG) << ss.str().c_str(); -#endif - signatures = result.signatures(); } else { messagePart.auditLogError = GpgME::Error(GPG_ERR_NOT_IMPLEMENTED); } -#ifdef DEBUG_SIGNATURE - if (doCheck) { - qCDebug(MESSAGEVIEWER_LOG) << "returned from CRYPTPLUG"; - } -#endif - // ### only one signature supported - if (!signatures.empty()) { -#ifdef DEBUG_SIGNATURE - qCDebug(MESSAGEVIEWER_LOG) << "\nFound signature"; -#endif - messagePart.isSigned = true; + if (messagePart.isSigned) { sigStatusToMetaData(signatures, cryptProto, messagePart, key); -#ifdef DEBUG_SIGNATURE - qCDebug(MESSAGEVIEWER_LOG) << "\n key id:" << messagePart.keyId - << "\n key trust:" << messagePart.keyTrust - << "\n signer:" << messagePart.signer; -#endif } else { messagePart.creationTime = QDateTime(); } @@ -2897,26 +2762,72 @@ writeBodyStr(aStr, aCodec, fromAddress, dummy1, dummy2, false); } -bool ObjectTreeParser::okVerify(const QByteArray &data, const Kleo::CryptoBackend::Protocol *cryptProto, PartMetaData &messagePart, QByteArray &verifiedText, std::vector &signatures) +bool ObjectTreeParser::okVerify(const QByteArray &data, const Kleo::CryptoBackend::Protocol *cryptProto, PartMetaData &messagePart, QByteArray &verifiedText, std::vector &signatures, const QByteArray &signature, KMime::Content *sign) { //copied from ObjectTreeParser::writeOpaqueOrMultipartSignedData messagePart.isSigned = false; messagePart.technicalProblem = (cryptProto == 0); messagePart.keyTrust = GpgME::Signature::Unknown; messagePart.status = i18n("Wrong Crypto Plug-In."); messagePart.status_code = GPGME_SIG_STAT_NONE; - Kleo::VerifyOpaqueJob *job = cryptProto->verifyOpaqueJob(); - VerifyOpaqueBodyPartMemento *m - = new VerifyOpaqueBodyPartMemento(job, cryptProto->keyListJob(), data); - m->exec(); + const QByteArray mementoName = "verification"; + + CryptoBodyPartMemento *m = dynamic_cast(mNodeHelper->bodyPartMemento(sign, mementoName)); - verifiedText = m->plainText(); - messagePart.auditLogError = m->auditLogError(); - messagePart.auditLog = m->auditLogAsHtml(); - signatures = m->verifyResult().signatures(); - messagePart.isSigned = !signatures.empty(); + if (!m) { + if (!signature.isEmpty()) { + Kleo::VerifyDetachedJob *job = cryptProto->verifyDetachedJob(); + if (job) { + m = new VerifyDetachedBodyPartMemento(job, cryptProto->keyListJob(), signature, data); + } + } else { + Kleo::VerifyOpaqueJob *job = cryptProto->verifyOpaqueJob(); + if (job) { + m = new VerifyOpaqueBodyPartMemento(job, cryptProto->keyListJob(), data); + } + } + if (m) { + if (allowAsync()) { + QObject::connect(m, &CryptoBodyPartMemento::update, + mNodeHelper, &NodeHelper::update); + QObject::connect(m, SIGNAL(update(MessageViewer::Viewer::UpdateMode)), + mSource->sourceObject(), SLOT(update(MessageViewer::Viewer::UpdateMode))); + + if (m->start()) { + messagePart.inProgress = true; + mHasPendingAsyncJobs = true; + } + } else { + m->exec(); + } + if (sign) { + mNodeHelper->setBodyPartMemento(sign, mementoName, m); + } + } + } else if (m->isRunning()) { + messagePart.inProgress = true; + mHasPendingAsyncJobs = true; + m = 0; + } else { + messagePart.inProgress = false; + mHasPendingAsyncJobs = false; + } + if (m && !messagePart.inProgress) { + if (!signature.isEmpty()) { + VerifyDetachedBodyPartMemento *vm = dynamic_cast(m); + verifiedText = data; + signatures = vm->verifyResult().signatures(); + } else { + VerifyOpaqueBodyPartMemento *vm = dynamic_cast(m); + verifiedText = vm->plainText(); + signatures = vm->verifyResult().signatures(); + } + messagePart.auditLogError = m->auditLogError(); + messagePart.auditLog = m->auditLogAsHtml(); + messagePart.isSigned = !signatures.empty(); + } return messagePart.isSigned; } @@ -3096,7 +3007,7 @@ messagePart.isDecryptable = false; QByteArray verifiedText; - if (okVerify(block.text(), cryptoProtocol(), messagePart, verifiedText, signatures)) { + if (okVerify(block.text(), cryptoProtocol(), messagePart, verifiedText, signatures, QByteArray(), 0)) { text = aCodec->toUnicode(verifiedText); } }