Commit 9bb1dd91 authored by Sandro Knauß's avatar Sandro Knauß

move okDecryptMime to CryptoMessagePart

parent 46e73409
......@@ -27,6 +27,8 @@
#include "job/kleojobexecutor.h"
#include "utils/iconnamecache.h"
#include "memento/decryptverifybodypartmemento.h"
#include <MessageCore/StringUtil>
#include <libkleo/importjob.h>
......@@ -46,6 +48,8 @@
#include <KLocalizedString>
#include <KEmailAddress>
#include <sstream>
using namespace MimeTreeParser;
/** Checks whether @p str contains external references. To be precise,
......@@ -1666,6 +1670,7 @@ CryptoMessagePart::CryptoMessagePart(ObjectTreeParser *otp,
KMime::Content *node)
: MessagePart(otp, text)
, mPassphraseError(false)
, mNoSecKey(false)
, mCryptoProto(cryptoProto)
, mFromAddress(fromAddress)
, mNode(node)
......@@ -1724,6 +1729,116 @@ void CryptoMessagePart::startDecryption(const QByteArray &text, const QTextCodec
}
}
bool CryptoMessagePart::okDecryptMIME(KMime::Content &data)
{
mPassphraseError = false;
mMetaData.inProgress = false;
mMetaData.errorText.clear();
mMetaData.auditLogError = GpgME::Error();
mMetaData.auditLog.clear();
bool bDecryptionOk = false;
bool cannotDecrypt = false;
ObjectTreeSourceIf *source = mOtp->mSource;
NodeHelper *nodeHelper = mOtp->nodeHelper();
assert(decryptMessage());
// Check whether the memento contains a result from last time:
const DecryptVerifyBodyPartMemento *m
= dynamic_cast<DecryptVerifyBodyPartMemento *>(nodeHelper->bodyPartMemento(&data, "decryptverify"));
assert(!m || mCryptoProto); //No CryptoPlugin and having a bodyPartMemento -> there is something completly wrong
if (!m && mCryptoProto) {
Kleo::DecryptVerifyJob *job = mCryptoProto->decryptVerifyJob();
if (!job) {
cannotDecrypt = true;
} else {
const QByteArray ciphertext = data.decodedContent();
DecryptVerifyBodyPartMemento *newM
= new DecryptVerifyBodyPartMemento(job, ciphertext);
if (mOtp->allowAsync()) {
QObject::connect(newM, &CryptoBodyPartMemento::update,
nodeHelper, &NodeHelper::update);
QObject::connect(newM, SIGNAL(update(MimeTreeParser::UpdateMode)), source->sourceObject(),
SLOT(update(MimeTreeParser::UpdateMode)));
if (newM->start()) {
mMetaData.inProgress = true;
mOtp->mHasPendingAsyncJobs = true;
} else {
m = newM;
}
} else {
newM->exec();
m = newM;
}
nodeHelper->setBodyPartMemento(&data, "decryptverify", newM);
}
} else if (m->isRunning()) {
mMetaData.inProgress = true;
mOtp->mHasPendingAsyncJobs = true;
m = 0;
}
if (m) {
const QByteArray &plainText = m->plainText();
const GpgME::DecryptionResult &decryptResult = m->decryptResult();
const GpgME::VerificationResult &verifyResult = m->verifyResult();
mMetaData.isSigned = verifyResult.signatures().size() > 0;
mSignatures = verifyResult.signatures();
mDecryptRecipients = decryptResult.recipients();
bDecryptionOk = !decryptResult.error();
mMetaData.auditLogError = m->auditLogError();
mMetaData.auditLog = m->auditLogAsHtml();
// std::stringstream ss;
// ss << decryptResult << '\n' << verifyResult;
// qCDebug(MIMETREEPARSER_LOG) << ss.str().c_str();
if (!bDecryptionOk && mMetaData.isSigned) {
//Only a signed part
mMetaData.isEncrypted = false;
bDecryptionOk = true;
mDecryptedData = plainText;
} else {
mPassphraseError = decryptResult.error().isCanceled() || decryptResult.error().code() == GPG_ERR_NO_SECKEY;
mMetaData.isEncrypted = decryptResult.error().code() != GPG_ERR_NO_DATA;
mMetaData.errorText = QString::fromLocal8Bit(decryptResult.error().asString());
if (mMetaData.isEncrypted && decryptResult.numRecipients() > 0) {
mMetaData.keyId = decryptResult.recipient(0).keyID();
}
if (bDecryptionOk) {
mDecryptedData = plainText;
} else {
mNoSecKey = true;
foreach (const GpgME::DecryptionResult::Recipient &recipient, decryptResult.recipients()) {
mNoSecKey &= (recipient.status().code() == GPG_ERR_NO_SECKEY);
}
}
}
}
if (!bDecryptionOk) {
QString cryptPlugLibName;
if (mCryptoProto) {
cryptPlugLibName = mCryptoProto->name();
}
if (!mCryptoProto) {
mMetaData.errorText = i18n("No appropriate crypto plug-in was found.");
} else if (cannotDecrypt) {
mMetaData.errorText = i18n("Crypto plug-in \"%1\" cannot decrypt messages.",
cryptPlugLibName);
} else if (!passphraseError()) {
mMetaData.errorText = i18n("Crypto plug-in \"%1\" could not decrypt the data.", cryptPlugLibName)
+ QLatin1String("<br />")
+ i18n("Error: %1", mMetaData.errorText);
}
}
return bDecryptionOk;
}
void CryptoMessagePart::startDecryption(KMime::Content *data)
{
if (!mNode && !data) {
......@@ -1734,27 +1849,15 @@ void CryptoMessagePart::startDecryption(KMime::Content *data)
data = mNode;
}
bool signatureFound;
bool actuallyEncrypted = true;
bool decryptionStarted;
mMetaData.isEncrypted = true;
CryptoProtocolSaver saver(mOtp, mCryptoProto);
bool bOkDecrypt = mOtp->okDecryptMIME(*data,
mDecryptedData,
signatureFound,
mSignatures,
true,
mPassphraseError,
actuallyEncrypted,
decryptionStarted,
mMetaData);
if (decryptionStarted) {
mMetaData.inProgress = true;
bool bOkDecrypt = okDecryptMIME(*data);
if (mMetaData.inProgress) {
return;
}
mMetaData.isDecryptable = bOkDecrypt;
mMetaData.isEncrypted = actuallyEncrypted;
mMetaData.isSigned = signatureFound;
if (!mMetaData.isDecryptable) {
setText(QString::fromUtf8(mDecryptedData.constData()));
......@@ -1872,7 +1975,32 @@ void CryptoMessagePart::html(bool decorate)
// In progress has no special body
} else if (mMetaData.isEncrypted && !mMetaData.isDecryptable) {
const CryptoBlock block(mOtp, &mMetaData, mCryptoProto, mOtp->mSource, mFromAddress, mNode);
writer->queue(text()); //Do not quote ErrorText
const QString errorMsg = i18n("Could not decrypt the data.");
const QString sNoSecKeyHeader = i18n("No secret key found to encrypt the message. It is encrypted for following keys:");
QString secKeyList;
if (mNoSecKey) {
foreach (const GpgME::DecryptionResult::Recipient &recipient, mDecryptRecipients) {
if (!secKeyList.isEmpty()) {
secKeyList += QStringLiteral("<br />");
}
secKeyList += QStringLiteral("<a href=\"kmail:showCertificate#%1 ### %2 ### %3\">%4</a>")
.arg(mCryptoProto->displayName(),
mCryptoProto->name(),
QString::fromLatin1(recipient.keyID()),
QString::fromLatin1(QByteArray("0x") + recipient.keyID())
);
}
}
writer->queue(QStringLiteral("<div style=\"font-size:x-large; text-align:center; padding:20pt;\">"));
if (mNoSecKey) {
writer->queue(sNoSecKeyHeader + QStringLiteral("<br />") + secKeyList);
} else {
writer->queue(errorMsg);
}
writer->queue(QStringLiteral("</div>"));
} else {
if (mMetaData.isSigned && mVerifiedText.isEmpty() && !hideErrors) {
const CryptoBlock block(mOtp, &mMetaData, mCryptoProto, mOtp->mSource, mFromAddress, mNode);
......
......@@ -27,6 +27,7 @@
#include <Libkleo/CryptoBackend>
#include <gpgme++/verificationresult.h>
#include <gpgme++/decryptionresult.h>
#include <importresult.h>
#include <QString>
......@@ -423,13 +424,21 @@ private:
but we're deferring decryption for later. */
void writeDeferredDecryptionBlock() const;
/** Handles the dectyptioon of a given content
* returns true if the decryption was successfull
* if used in async mode, check if mMetaData.inProgress is true, it inicates a running decryption process.
*/
bool okDecryptMIME(KMime::Content &data);
protected:
bool mPassphraseError;
bool mNoSecKey;
const Kleo::CryptoBackend::Protocol *mCryptoProto;
QString mFromAddress;
KMime::Content *mNode;
bool mDecryptMessage;
QByteArray mVerifiedText;
std::vector<GpgME::DecryptionResult::Recipient> mDecryptRecipients;
};
}
......
......@@ -39,7 +39,6 @@
#include "memento/verifydetachedbodypartmemento.h"
#include "memento/verifyopaquebodypartmemento.h"
#include "memento/cryptobodypartmemento.h"
#include "memento/decryptverifybodypartmemento.h"
#include "messagepart.h"
#include "objecttreesourceif.h"
......@@ -70,7 +69,6 @@
// KDEPIMLIBS includes
#include <gpgme++/importresult.h>
#include <gpgme++/decryptionresult.h>
#include <gpgme++/key.h>
#include <gpgme++/keylistresult.h>
#include <gpgme.h>
......@@ -565,183 +563,6 @@ void ObjectTreeParser::writeCertificateImportResult(const GpgME::ImportResult &r
htmlWriter()->queue(QStringLiteral("<hr/>"));
}
bool ObjectTreeParser::okDecryptMIME(KMime::Content &data,
QByteArray &decryptedData,
bool &signatureFound,
std::vector<GpgME::Signature> &signatures,
bool showWarning,
bool &passphraseError,
bool &actuallyEncrypted,
bool &decryptionStarted,
PartMetaData &partMetaData)
{
passphraseError = false;
decryptionStarted = false;
partMetaData.errorText.clear();
partMetaData.auditLogError = GpgME::Error();
partMetaData.auditLog.clear();
bool bDecryptionOk = false;
enum { NO_PLUGIN, NOT_INITIALIZED, CANT_DECRYPT }
cryptPlugError = NO_PLUGIN;
const Kleo::CryptoBackend::Protocol *cryptProto = cryptoProtocol();
QString cryptPlugLibName;
if (cryptProto) {
cryptPlugLibName = cryptProto->name();
}
assert(mSource->decryptMessage());
const QString errorMsg = i18n("Could not decrypt the data.");
if (cryptProto) {
QByteArray ciphertext = data.decodedContent();
#ifdef MARCS_DEBUG
QString cipherStr = QString::fromLatin1(ciphertext);
bool cipherIsBinary = (!cipherStr.contains(QStringLiteral("BEGIN ENCRYPTED MESSAGE"), Qt::CaseInsensitive)) &&
(!cipherStr.contains(QStringLiteral("BEGIN PGP ENCRYPTED MESSAGE"), Qt::CaseInsensitive)) &&
(!cipherStr.contains(QStringLiteral("BEGIN PGP MESSAGE"), Qt::CaseInsensitive));
dumpToFile("dat_04_reader.encrypted", ciphertext.data(), ciphertext.size());
QString deb;
deb = QLatin1String("\n\nE N C R Y P T E D D A T A = ");
if (cipherIsBinary) {
deb += QLatin1String("[binary data]");
} else {
deb += QLatin1String("\"");
deb += cipherStr;
deb += QLatin1String("\"");
}
deb += "\n\n";
qCDebug(MIMETREEPARSER_LOG) << deb;
#endif
qCDebug(MIMETREEPARSER_LOG) << "going to call CRYPTPLUG" << cryptPlugLibName;
// Check whether the memento contains a result from last time:
const DecryptVerifyBodyPartMemento *m
= dynamic_cast<DecryptVerifyBodyPartMemento *>(mNodeHelper->bodyPartMemento(&data, "decryptverify"));
if (!m) {
Kleo::DecryptVerifyJob *job = cryptProto->decryptVerifyJob();
if (!job) {
cryptPlugError = CANT_DECRYPT;
cryptProto = 0;
} else {
DecryptVerifyBodyPartMemento *newM
= new DecryptVerifyBodyPartMemento(job, ciphertext);
if (allowAsync()) {
QObject::connect(newM, &CryptoBodyPartMemento::update,
nodeHelper(), &NodeHelper::update);
QObject::connect(newM, SIGNAL(update(MimeTreeParser::UpdateMode)), mSource->sourceObject(),
SLOT(update(MimeTreeParser::UpdateMode)));
if (newM->start()) {
decryptionStarted = true;
mHasPendingAsyncJobs = true;
} else {
m = newM;
}
} else {
newM->exec();
m = newM;
}
mNodeHelper->setBodyPartMemento(&data, "decryptverify", newM);
}
} else if (m->isRunning()) {
decryptionStarted = true;
mHasPendingAsyncJobs = true;
m = 0;
}
if (m) {
const QByteArray &plainText = m->plainText();
const GpgME::DecryptionResult &decryptResult = m->decryptResult();
const GpgME::VerificationResult &verifyResult = m->verifyResult();
std::stringstream ss;
ss << decryptResult << '\n' << verifyResult;
qCDebug(MIMETREEPARSER_LOG) << ss.str().c_str();
signatureFound = verifyResult.signatures().size() > 0;
signatures = verifyResult.signatures();
bDecryptionOk = !decryptResult.error();
partMetaData.auditLogError = m->auditLogError();
partMetaData.auditLog = m->auditLogAsHtml();
if (!bDecryptionOk && signatureFound) {
//Only a signed part
actuallyEncrypted = false;
bDecryptionOk = true;
decryptedData = plainText;
} else {
passphraseError = decryptResult.error().isCanceled() || decryptResult.error().code() == GPG_ERR_NO_SECKEY;
actuallyEncrypted = decryptResult.error().code() != GPG_ERR_NO_DATA;
partMetaData.errorText = QString::fromLocal8Bit(decryptResult.error().asString());
partMetaData.isEncrypted = actuallyEncrypted;
if (actuallyEncrypted && decryptResult.numRecipients() > 0) {
partMetaData.keyId = decryptResult.recipient(0).keyID();
}
qCDebug(MIMETREEPARSER_LOG) << "ObjectTreeParser::decryptMIME: returned from CRYPTPLUG";
if (bDecryptionOk) {
decryptedData = plainText;
} else if (htmlWriter() && showWarning) {
bool noSecKey = true;
const QString sNoSecKeyHeader = i18n("No secret key found to encrypt the message. It is encrypted for following keys:");
QString secKeyList;
foreach (const GpgME::DecryptionResult::Recipient &recipient, decryptResult.recipients()) {
noSecKey &= (recipient.status().code() == GPG_ERR_NO_SECKEY);
if (!secKeyList.isEmpty()) {
secKeyList += QStringLiteral("<br />");
}
secKeyList += QStringLiteral("<a href=\"kmail:showCertificate#%1 ### %2 ### %3\">%4</a>")
.arg(cryptProto->displayName(),
cryptProto->name(),
QString::fromLatin1(recipient.keyID()),
QString::fromLatin1(QByteArray("0x") + recipient.keyID())
);
}
decryptedData = "<div style=\"font-size:x-large; text-align:center; padding:20pt;\">";
if (noSecKey) {
decryptedData += QString(sNoSecKeyHeader + QStringLiteral("<br />") + secKeyList).toUtf8();
} else {
decryptedData += errorMsg.toUtf8();
}
decryptedData += "</div>";
if (!passphraseError) {
partMetaData.errorText = i18n("Crypto plug-in \"%1\" could not decrypt the data.", cryptPlugLibName)
+ QLatin1String("<br />")
+ i18n("Error: %1", partMetaData.errorText);
}
}
}
}
}
if (!cryptProto) {
decryptedData = "<div style=\"text-align:center; padding:20pt;\">"
+ errorMsg.toUtf8()
+ "</div>";
switch (cryptPlugError) {
case NOT_INITIALIZED:
partMetaData.errorText = i18n("Crypto plug-in \"%1\" is not initialized.",
cryptPlugLibName);
break;
case CANT_DECRYPT:
partMetaData.errorText = i18n("Crypto plug-in \"%1\" cannot decrypt messages.",
cryptPlugLibName);
break;
case NO_PLUGIN:
partMetaData.errorText = i18n("No appropriate crypto plug-in was found.");
break;
}
}
dumpToFile("dat_05_reader.decrypted", decryptedData.data(), decryptedData.size());
return bDecryptionOk;
}
MessagePart::Ptr ObjectTreeParser::processTextHtmlSubtype(KMime::Content *curNode, ProcessResult &)
{
HtmlMessagePart::Ptr mp(new HtmlMessagePart(this, curNode, mSource));
......
......@@ -360,18 +360,6 @@ private:
/** Writes out the information contained in a GpgME::ImportResult */
void writeCertificateImportResult(const GpgME::ImportResult &res);
/** Returns the contents of the given multipart/encrypted
object. Data is decypted. May contain body parts. */
bool okDecryptMIME(KMime::Content &data,
QByteArray &decryptedData,
bool &signatureFound,
std::vector<GpgME::Signature> &signatures,
bool showWarning,
bool &passphraseError,
bool &actuallyEncrypted,
bool &decryptionStarted,
PartMetaData &partMetaData);
bool okVerify(const QByteArray &data, const Kleo::CryptoBackend::Protocol *cryptProto, MimeTreeParser::PartMetaData &messagePart, QByteArray &verifiedText, std::vector<GpgME::Signature> &signatures, const QByteArray &signature, KMime::Content *sign);
void sigStatusToMetaData(const std::vector<GpgME::Signature> &signatures, const Kleo::CryptoBackend::Protocol *cryptoProtocol, PartMetaData &messagePart, GpgME::Key key);
......
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