diff --git a/Makefile.am b/Makefile.am index 72edfead5..85059deef 100644 --- a/Makefile.am +++ b/Makefile.am @@ -91,6 +91,7 @@ libkmailprivate_la_SOURCES = kmmessage.cpp kmmainwin.cpp configuredialog.cpp \ headerstrategy.cpp headerstyle.cpp khtmlparthtmlwriter.cpp \ filehtmlwriter.cpp teehtmlwriter.cpp \ mailcomposerIface.skel objecttreeparser.cpp \ + objecttreeparser_p.cpp \ attachmentcollector.cpp \ bodypartformatter.cpp bodypartformatterfactory.cpp \ partNode.cpp \ diff --git a/kmreaderwin.cpp b/kmreaderwin.cpp index 7752db7c4..a1df40008 100644 --- a/kmreaderwin.cpp +++ b/kmreaderwin.cpp @@ -1598,6 +1598,7 @@ void KMReaderWin::parseMsg(KMMessage* aMsg) // show message content ObjectTreeParser otp( this ); + otp.setAllowAsync( true ); otp.parseObjectTree( mRootNode ); // store encrypted/signed status information in the KMMessage diff --git a/objecttreeparser.cpp b/objecttreeparser.cpp index 855f7f761..8bbf4debb 100644 --- a/objecttreeparser.cpp +++ b/objecttreeparser.cpp @@ -34,6 +34,7 @@ // my header file #include "objecttreeparser.h" +#include "objecttreeparser_p.h" // other KMail headers #include "kmkernel.h" @@ -147,6 +148,8 @@ namespace KMail { mShowOnlyOneMimePart( showOnlyOneMimePart ), mKeepEncryptions( keepEncryptions ), mIncludeSignatures( includeSignatures ), + mHasPendingAsyncJobs( false ), + mAllowAsync( false ), mAttachmentStrategy( strategy ), mHtmlWriter( htmlWriter ), mCSSHelper( cssHelper ) @@ -166,6 +169,8 @@ namespace KMail { mShowOnlyOneMimePart( other.showOnlyOneMimePart() ), mKeepEncryptions( other.keepEncryptions() ), mIncludeSignatures( other.includeSignatures() ), + mHasPendingAsyncJobs( other.hasPendingAsyncJobs() ), + mAllowAsync( other.allowAsync() ), mAttachmentStrategy( other.attachmentStrategy() ), mHtmlWriter( other.htmlWriter() ), mCSSHelper( other.cssHelper() ) @@ -245,6 +250,9 @@ namespace KMail { if ( !node ) return; + // reset pending async jobs state (we'll rediscover pending jobs as we go) + mHasPendingAsyncJobs = false; + // reset "processed" flags for... if ( showOnlyOneMimePart() ) { // ... this node and all descendants @@ -455,29 +463,85 @@ namespace KMail { messagePart.status = i18n("Wrong Crypto Plug-In."); messagePart.status_code = GPGME_SIG_STAT_NONE; + GpgME::Key key; + if ( doCheck && cryptProto ) { GpgME::VerificationResult result; if ( data ) { // detached - const STD_NAMESPACE_PREFIX auto_ptr job( cryptProto->verifyDetachedJob() ); - if ( job.get() ) { - QByteArray plainData = cleartext; - plainData.resize( cleartext.size() - 1 ); - result = job->exec( signaturetext, plainData ); - messagePart.auditLogError = job->auditLogError(); - messagePart.auditLog = job->auditLogAsHtml(); - } else { - cryptPlugError = CANT_VERIFY_SIGNATURES; + const VerifyDetachedBodyPartMemento * m + = dynamic_cast( data->bodyPartMemento( "verifydetached" ) ); + if ( !m ) { + Kleo::VerifyDetachedJob * job = cryptProto->verifyDetachedJob(); + if ( !job ) { + cryptPlugError = CANT_VERIFY_SIGNATURES; + // PENDING(marc) cryptProto = 0 here? + } else { + QByteArray plainData = cleartext; + plainData.resize( cleartext.size() - 1 ); + VerifyDetachedBodyPartMemento * newM + = new VerifyDetachedBodyPartMemento( job, cryptProto->keyListJob(), signaturetext, plainData ); + if ( allowAsync() ) { + if ( newM->start() ) { + messagePart.inProgress = true; + mHasPendingAsyncJobs = true; + } else { + m = newM; + } + } else { + newM->exec(); + m = newM; + } + data->setBodyPartMemento( "verifydetached", newM ); + } + } else if ( m->isRunning() ) { + messagePart.inProgress = true; + mHasPendingAsyncJobs = true; + m = 0; + } + + if ( m ) { + result = m->verifyResult(); + messagePart.auditLogError = m->auditLogError(); + messagePart.auditLog = m->auditLogAsHtml(); + key = m->signingKey(); } } else { // opaque - const STD_NAMESPACE_PREFIX auto_ptr job( cryptProto->verifyOpaqueJob() ); - if ( job.get() ) { - QByteArray plainData; - result = job->exec( signaturetext, plainData ); + const VerifyOpaqueBodyPartMemento * m + = dynamic_cast( data->bodyPartMemento( "verifyopaque" ) ); + if ( !m ) { + 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() ) { + if ( newM->start() ) { + messagePart.inProgress = true; + mHasPendingAsyncJobs = true; + } else { + m = newM; + } + } else { + newM->exec(); + m = newM; + } + data->setBodyPartMemento( "verifyopaque", newM ); + } + } else if ( m->isRunning() ) { + messagePart.inProgress = true; + mHasPendingAsyncJobs = true; + m = 0; + } + + if ( m ) { + result = m->verifyResult(); + const QByteArray & plainData = m->plainText(); cleartext = QCString( plainData.data(), plainData.size() + 1 ); - messagePart.auditLogError = job->auditLogError(); - messagePart.auditLog = job->auditLogAsHtml(); - } else { - cryptPlugError = CANT_VERIFY_SIGNATURES; + messagePart.auditLogError = m->auditLogError(); + messagePart.auditLog = m->auditLogAsHtml(); + key = m->signingKey(); } } std::stringstream ss; @@ -505,16 +569,6 @@ namespace KMail { if ( messagePart.status_code & GPGME_SIG_STAT_GOOD ) messagePart.isGoodSignature = true; - // get key for this signature - const STD_NAMESPACE_PREFIX auto_ptr job( cryptProto->keyListJob() ); - std::vector keys; - GpgME::KeyListResult keyListRes = job->exec( QString::fromLatin1( signature.fingerprint() ), false, keys ); - GpgME::Key key; - if ( keys.size() == 1 ) - key = keys[0]; - else if ( keys.size() > 1 ) - assert( false ); // ### wtf, what should we do in this case?? - // save extended signature status flags messagePart.sigSummary = signature.summary(); @@ -698,11 +752,13 @@ bool ObjectTreeParser::okDecryptMIME( partNode& data, bool showWarning, bool& passphraseError, bool& actuallyEncrypted, + bool& decryptionStarted, QString& aErrorText, GpgME::Error & auditLogError, QString& auditLog ) { passphraseError = false; + decryptionStarted = false; aErrorText = QString::null; auditLogError = GpgME::Error(); auditLog = QString::null; @@ -747,15 +803,40 @@ bool ObjectTreeParser::okDecryptMIME( partNode& data, if ( mReader ) emit mReader->noDrag(); // in case pineentry pops up, don't let kmheaders start a drag afterwards - const STD_NAMESPACE_PREFIX auto_ptr job( cryptProto->decryptVerifyJob() ); - if ( !job.get() ) { - cryptPlugError = CANT_DECRYPT; - cryptProto = 0; - } else { - QByteArray plainText; - const std::pair res = job->exec( ciphertext, plainText ); - const GpgME::DecryptionResult & decryptResult = res.first; - const GpgME::VerificationResult & verifyResult = res.second; + // Check whether the memento contains a result from last time: + const DecryptVerifyBodyPartMemento * m + = dynamic_cast( data.bodyPartMemento( "decryptverify" ) ); + if ( !m ) { + Kleo::DecryptVerifyJob * job = cryptProto->decryptVerifyJob(); + if ( !job ) { + cryptPlugError = CANT_DECRYPT; + cryptProto = 0; + } else { + DecryptVerifyBodyPartMemento * newM + = new DecryptVerifyBodyPartMemento( job, ciphertext ); + if ( allowAsync() ) { + if ( newM->start() ) { + decryptionStarted = true; + mHasPendingAsyncJobs = true; + } else { + m = newM; + } + } else { + newM->exec(); + m = newM; + } + data.setBodyPartMemento( "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; kdDebug(5006) << ss.str().c_str() << endl; @@ -766,8 +847,8 @@ bool ObjectTreeParser::okDecryptMIME( partNode& data, || decryptResult.error().code() == GPG_ERR_NO_SECKEY; actuallyEncrypted = decryptResult.error().code() != GPG_ERR_NO_DATA; aErrorText = QString::fromLocal8Bit( decryptResult.error().asString() ); - auditLogError = job->auditLogError(); - auditLog = job->auditLogAsHtml(); + auditLogError = m->auditLogError(); + auditLog = m->auditLogAsHtml(); kdDebug(5006) << "ObjectTreeParser::decryptMIME: returned from CRYPTPLUG" << endl; @@ -1272,6 +1353,7 @@ namespace KMail { std::vector signatures; bool passphraseError; bool actuallyEncrypted = true; + bool decryptionStarted; bool bOkDecrypt = okDecryptMIME( *data, decryptedData, @@ -1280,10 +1362,16 @@ namespace KMail { true, passphraseError, actuallyEncrypted, + decryptionStarted, messagePart.errorText, messagePart.auditLogError, messagePart.auditLog ); + if ( decryptionStarted ) { + writeDecryptionInProgressBlock(); + return true; + } + // paint the frame if ( mReader ) { messagePart.isDecryptable = bOkDecrypt; @@ -1427,6 +1515,7 @@ namespace KMail { std::vector signatures; bool passphraseError; bool actuallyEncrypted = true; + bool decryptionStarted; bool bOkDecrypt = okDecryptMIME( *node, decryptedData, @@ -1435,10 +1524,16 @@ namespace KMail { true, passphraseError, actuallyEncrypted, + decryptionStarted, messagePart.errorText, messagePart.auditLogError, messagePart.auditLog ); + if ( decryptionStarted ) { + writeDecryptionInProgressBlock(); + return true; + } + // paint the frame if ( mReader ) { messagePart.isDecryptable = bOkDecrypt; @@ -1591,6 +1686,7 @@ namespace KMail { std::vector signatures; bool passphraseError; bool actuallyEncrypted = true; + bool decryptionStarted; if ( mReader && !mReader->decryptMessage() ) { writeDeferredDecryptionBlock(); @@ -1602,6 +1698,7 @@ namespace KMail { false, passphraseError, actuallyEncrypted, + decryptionStarted, messagePart.errorText, messagePart.auditLogError, messagePart.auditLog ) ) { @@ -1609,17 +1706,21 @@ namespace KMail { isEncrypted = true; node->setEncryptionState( KMMsgFullyEncrypted ); signTestNode = 0; - // paint the frame - messagePart.isDecryptable = true; - if ( mReader ) - htmlWriter()->queue( writeSigstatHeader( messagePart, - cryptoProtocol(), - node->trueFromAddress() ) ); - insertAndParseNewChildNode( *node, - &*decryptedData, - "encrypted data" ); - if ( mReader ) - htmlWriter()->queue( writeSigstatFooter( messagePart ) ); + if ( decryptionStarted ) { + writeDecryptionInProgressBlock(); + } else { + // paint the frame + messagePart.isDecryptable = true; + if ( mReader ) + htmlWriter()->queue( writeSigstatHeader( messagePart, + cryptoProtocol(), + node->trueFromAddress() ) ); + insertAndParseNewChildNode( *node, + &*decryptedData, + "encrypted data" ); + if ( mReader ) + htmlWriter()->queue( writeSigstatFooter( messagePart ) ); + } } else { // decryption failed, which could be because the part was encrypted but // decryption failed, or because we didn't know if it was encrypted, tried, diff --git a/objecttreeparser.h b/objecttreeparser.h index 59725d49b..795e4e5b7 100644 --- a/objecttreeparser.h +++ b/objecttreeparser.h @@ -40,6 +40,8 @@ #include #include +#include + class KMReaderWin; class KMMessagePart; class QString; @@ -114,6 +116,11 @@ namespace KMail { KMail::CSSHelper * cssHelper=0 ); virtual ~ObjectTreeParser(); + void setAllowAsync( bool allow ) { assert( !mHasPendingAsyncJobs ); mAllowAsync = allow; } + bool allowAsync() const { return mAllowAsync; } + + bool hasPendingAsyncJobs() const { return mHasPendingAsyncJobs; } + QCString rawReplyString() const { return mRawReplyString; } /*! @return the text of the message, ie. what would appear in the @@ -210,6 +217,7 @@ namespace KMail { bool showWarning, bool& passphraseError, bool& actuallyEncrypted, + bool& decryptionStarted, QString& aErrorText, GpgME::Error & auditLogError, QString& auditLog ); @@ -294,6 +302,8 @@ namespace KMail { bool mShowOnlyOneMimePart; bool mKeepEncryptions; bool mIncludeSignatures; + bool mHasPendingAsyncJobs; + bool mAllowAsync; const KMail::AttachmentStrategy * mAttachmentStrategy; KMail::HtmlWriter * mHtmlWriter; KMail::CSSHelper * mCSSHelper; diff --git a/objecttreeparser_p.cpp b/objecttreeparser_p.cpp new file mode 100644 index 000000000..4333e3061 --- /dev/null +++ b/objecttreeparser_p.cpp @@ -0,0 +1,342 @@ +/* -*- mode: C++; c-file-style: "gnu" -*- + objecttreeparser_p.cpp + + This file is part of KMail, the KDE mail client. + Copyright (c) 2009 Klarälvdalens Datakonsult AB + Authors: Marc Mutz + + KMail is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License, version 2, as + published by the Free Software Foundation. + + KMail 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 "objecttreeparser_p.h" + +#include +#include +#include +#include + +#include + +#include +#include + +#include + +using namespace KMail; +using namespace Kleo; +using namespace GpgME; + +DecryptVerifyBodyPartMemento::DecryptVerifyBodyPartMemento( DecryptVerifyJob * job, const QByteArray & cipherText ) + : QObject( 0 ), + Interface::BodyPartMemento(), + ISubject(), + m_cipherText( cipherText ), + m_job( job ), + m_running( false ) +{ + assert( m_job ); +} + +DecryptVerifyBodyPartMemento::~DecryptVerifyBodyPartMemento() { + if ( m_job ) + m_job->slotCancel(); +} + +bool DecryptVerifyBodyPartMemento::start() { + assert( m_job ); + if ( const Error err = m_job->start( m_cipherText ) ) { + m_dr = DecryptionResult( err ); + return false; + } + connect( m_job, SIGNAL(result(const GpgME::DecryptionResult&,const GpgME::VerificationResult&,const QByteArray&)), + this, SLOT(slotResult(const GpgME::DecryptionResult&,const GpgME::VerificationResult&,const QByteArray&)) ); + m_running = true; + return true; +} + +void DecryptVerifyBodyPartMemento::exec() { + assert( m_job ); + QByteArray plainText; + m_running = true; + const std::pair p = m_job->exec( m_cipherText, plainText ); + saveResult( p.first, p.second, plainText ); + m_job->deleteLater(); // exec'ed jobs don't delete themselves + m_job = 0; +} + +void DecryptVerifyBodyPartMemento::saveResult( const DecryptionResult & dr, + const VerificationResult & vr, + const QByteArray & plainText ) +{ + assert( m_job ); + m_running = false; + m_dr = dr; + m_vr = vr; + m_plainText = plainText; + m_auditLog = m_job->auditLogAsHtml(); + m_auditLogError = m_job->auditLogError(); +} + +void DecryptVerifyBodyPartMemento::slotResult( const DecryptionResult & dr, + const VerificationResult & vr, + const QByteArray & plainText ) +{ + saveResult( dr, vr, plainText ); + m_job = 0; + QTimer::singleShot( 100, this, SLOT(notify()) ); +} + + + + +VerifyDetachedBodyPartMemento::VerifyDetachedBodyPartMemento( VerifyDetachedJob * job, + KeyListJob * klj, + const QByteArray & signature, + const QByteArray & plainText ) + : QObject( 0 ), + Interface::BodyPartMemento(), + ISubject(), + m_signature( signature ), + m_plainText( plainText ), + m_job( job ), + m_keylistjob( klj ), + m_running( false ) +{ + assert( m_job ); +} + +VerifyDetachedBodyPartMemento::~VerifyDetachedBodyPartMemento() { + if ( m_job ) + m_job->slotCancel(); + if ( m_keylistjob ) + m_keylistjob->slotCancel(); +} + +bool VerifyDetachedBodyPartMemento::start() { + assert( m_job ); + if ( const Error err = m_job->start( m_signature, m_plainText ) ) { + m_vr = VerificationResult( err ); + return false; + } + connect( m_job, SIGNAL(result(const GpgME::VerificationResult&)), + this, SLOT(slotResult(const GpgME::VerificationResult&)) ); + m_running = true; + return true; +} + +void VerifyDetachedBodyPartMemento::exec() { + assert( m_job ); + m_running = true; + saveResult( m_job->exec( m_signature, m_plainText ) ); + m_job->deleteLater(); // exec'ed jobs don't delete themselves + m_job = 0; + if ( canStartKeyListJob() ) { + std::vector keys; + m_keylistjob->exec( keyListPattern(), /*secretOnly=*/false, keys ); + if ( !keys.empty() ) + m_key = keys.back(); + } + if ( m_keylistjob ) + m_keylistjob->deleteLater(); // exec'ed jobs don't delete themselves + m_keylistjob = 0; + m_running = false; +} + +bool VerifyDetachedBodyPartMemento::canStartKeyListJob() const +{ + if ( !m_keylistjob ) + return false; + const char * const fpr = m_vr.signature( 0 ).fingerprint(); + return fpr && *fpr; +} + +QStringList VerifyDetachedBodyPartMemento::keyListPattern() const +{ + assert( canStartKeyListJob() ); + return QStringList( QString::fromLatin1( m_vr.signature( 0 ).fingerprint() ) ); +} + +void VerifyDetachedBodyPartMemento::saveResult( const VerificationResult & vr ) +{ + assert( m_job ); + m_vr = vr; + m_auditLog = m_job->auditLogAsHtml(); + m_auditLogError = m_job->auditLogError(); +} + +void VerifyDetachedBodyPartMemento::slotResult( const VerificationResult & vr ) +{ + saveResult( vr ); + m_job = 0; + if ( canStartKeyListJob() && startKeyListJob() ) + return; + if ( m_keylistjob ) + m_keylistjob->deleteLater(); + m_keylistjob = 0; + m_running = false; + QTimer::singleShot( 100, this, SLOT(notify()) ); +} + +bool VerifyDetachedBodyPartMemento::startKeyListJob() +{ + assert( canStartKeyListJob() ); + if ( const GpgME::Error err = m_keylistjob->start( keyListPattern() ) ) + return false; + connect( m_keylistjob, SIGNAL(done()), this, SLOT(slotKeyListJobDone()) ); + connect( m_keylistjob, SIGNAL(nextKey(const GpgME::Key&)), + this, SLOT(slotNextKey(const GpgME::Key&)) ); + return true; +} + +void VerifyDetachedBodyPartMemento::slotNextKey( const GpgME::Key & key ) +{ + m_key = key; +} + +void VerifyDetachedBodyPartMemento::slotKeyListJobDone() +{ + m_keylistjob = 0; + m_running = false; + QTimer::singleShot( 100, this, SLOT(notify()) ); +} + + +VerifyOpaqueBodyPartMemento::VerifyOpaqueBodyPartMemento( VerifyOpaqueJob * job, + KeyListJob * klj, + const QByteArray & signature ) + : QObject( 0 ), + Interface::BodyPartMemento(), + ISubject(), + m_signature( signature ), + m_job( job ), + m_keylistjob( klj ), + m_running( false ) +{ + assert( m_job ); +} + +VerifyOpaqueBodyPartMemento::~VerifyOpaqueBodyPartMemento() { + if ( m_job ) + m_job->slotCancel(); + if ( m_keylistjob ) + m_keylistjob->slotCancel(); +} + +bool VerifyOpaqueBodyPartMemento::start() { + assert( m_job ); + if ( const Error err = m_job->start( m_signature ) ) { + m_vr = VerificationResult( err ); + return false; + } + connect( m_job, SIGNAL(result(const GpgME::VerificationResult&,const QByteArray&)), + this, SLOT(slotResult(const GpgME::VerificationResult&,const QByteArray&)) ); + m_running = true; + return true; +} + +void VerifyOpaqueBodyPartMemento::exec() { + assert( m_job ); + m_running = true; + QByteArray plainText; + saveResult( m_job->exec( m_signature, plainText ), plainText ); + m_job->deleteLater(); // exec'ed jobs don't delete themselves + m_job = 0; + if ( canStartKeyListJob() ) { + std::vector keys; + m_keylistjob->exec( keyListPattern(), /*secretOnly=*/false, keys ); + if ( !keys.empty() ) + m_key = keys.back(); + } + if ( m_keylistjob ) + m_keylistjob->deleteLater(); // exec'ed jobs don't delete themselves + m_keylistjob = 0; + m_running = false; +} + +bool VerifyOpaqueBodyPartMemento::canStartKeyListJob() const +{ + if ( !m_keylistjob ) + return false; + const char * const fpr = m_vr.signature( 0 ).fingerprint(); + return fpr && *fpr; +} + +QStringList VerifyOpaqueBodyPartMemento::keyListPattern() const +{ + assert( canStartKeyListJob() ); + return QStringList( QString::fromLatin1( m_vr.signature( 0 ).fingerprint() ) ); +} + +void VerifyOpaqueBodyPartMemento::saveResult( const VerificationResult & vr, + const QByteArray & plainText ) +{ + assert( m_job ); + m_vr = vr; + m_plainText = plainText; + m_auditLog = m_job->auditLogAsHtml(); + m_auditLogError = m_job->auditLogError(); +} + +void VerifyOpaqueBodyPartMemento::slotResult( const VerificationResult & vr, + const QByteArray & plainText ) +{ + saveResult( vr, plainText ); + m_job = 0; + if ( canStartKeyListJob() && startKeyListJob() ) + return; + if ( m_keylistjob ) + m_keylistjob->deleteLater(); + m_keylistjob = 0; + m_running = false; + QTimer::singleShot( 100, this, SLOT(notify()) ); +} + +bool VerifyOpaqueBodyPartMemento::startKeyListJob() +{ + assert( canStartKeyListJob() ); + if ( const GpgME::Error err = m_keylistjob->start( keyListPattern() ) ) + return false; + connect( m_keylistjob, SIGNAL(done()), this, SLOT(slotKeyListJobDone()) ); + connect( m_keylistjob, SIGNAL(nextKey(const GpgME::Key&)), + this, SLOT(slotNextKey(const GpgME::Key&)) ); + return true; +} + +void VerifyOpaqueBodyPartMemento::slotNextKey( const GpgME::Key & key ) +{ + m_key = key; +} + +void VerifyOpaqueBodyPartMemento::slotKeyListJobDone() +{ + m_keylistjob = 0; + m_running = false; + QTimer::singleShot( 100, this, SLOT(notify()) ); +} + + +#include "objecttreeparser_p.moc" diff --git a/objecttreeparser_p.h b/objecttreeparser_p.h new file mode 100644 index 000000000..149cb7be1 --- /dev/null +++ b/objecttreeparser_p.h @@ -0,0 +1,220 @@ +/* -*- mode: C++; c-file-style: "gnu" -*- + objecttreeparser_p.h + + This file is part of KMail, the KDE mail client. + Copyright (c) 2009 Klarälvdalens Datakonsult AB + + KMail is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License, version 2, as + published by the Free Software Foundation. + + KMail 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 _KMAIL_OBJECTTREEPARSER_P_H_ +#define _KMAIL_OBJECTTREEPARSER_P_H_ + +#include +#include +#include + +#include +#include +#include +#include + +#include "isubject.h" +#include "interfaces/bodypart.h" + +namespace Kleo { + class DecryptVerifyJob; + class VerifyDetachedJob; + class VerifyOpaqueJob; + class KeyListJob; +} + +class QStringList; + +namespace KMail { + + class DecryptVerifyBodyPartMemento + : public QObject, + public KMail::Interface::BodyPartMemento, + public KMail::ISubject + { + Q_OBJECT + public: + DecryptVerifyBodyPartMemento( Kleo::DecryptVerifyJob * job, const QByteArray & cipherText ); + ~DecryptVerifyBodyPartMemento(); + + /* reimp */ Interface::Observer * asObserver() { return 0; } + /* reimp */ Interface::Observable * asObservable() { return this; } + + bool start(); + void exec(); + + bool isRunning() const { return m_running; } + + const QByteArray & plainText() const { return m_plainText; } + const GpgME::DecryptionResult & decryptResult() const { return m_dr; } + const GpgME::VerificationResult & verifyResult() const { return m_vr; } + const QString & auditLogAsHtml() const { return m_auditLog; } + GpgME::Error auditLogError() const { return m_auditLogError; } + + private slots: + void slotResult( const GpgME::DecryptionResult & dr, + const GpgME::VerificationResult & vr, + const QByteArray & plainText ); + void notify() { + ISubject::notify(); + } + + private: + void saveResult( const GpgME::DecryptionResult &, + const GpgME::VerificationResult &, + const QByteArray & ); + private: + // input: + const QByteArray m_cipherText; + QGuardedPtr m_job; + bool m_running; + // output: + GpgME::DecryptionResult m_dr; + GpgME::VerificationResult m_vr; + QByteArray m_plainText; + QString m_auditLog; + GpgME::Error m_auditLogError; + }; + + + class VerifyDetachedBodyPartMemento + : public QObject, + public KMail::Interface::BodyPartMemento, + public KMail::ISubject + { + Q_OBJECT + public: + VerifyDetachedBodyPartMemento( Kleo::VerifyDetachedJob * job, + Kleo::KeyListJob * klj, + const QByteArray & signature, + const QByteArray & plainText ); + ~VerifyDetachedBodyPartMemento(); + + /* reimp */ Interface::Observer * asObserver() { return 0; } + /* reimp */ Interface::Observable * asObservable() { return this; } + + bool start(); + void exec(); + + bool isRunning() const { return m_running; } + + const GpgME::VerificationResult & verifyResult() const { return m_vr; } + const QString & auditLogAsHtml() const { return m_auditLog; } + GpgME::Error auditLogError() const { return m_auditLogError; } + const GpgME::Key & signingKey() const { return m_key; } + + private slots: + void slotResult( const GpgME::VerificationResult & vr ); + void slotKeyListJobDone(); + void slotNextKey( const GpgME::Key & ); + void notify() { + ISubject::notify(); + } + + private: + void saveResult( const GpgME::VerificationResult & ); + bool canStartKeyListJob() const; + QStringList keyListPattern() const; + bool startKeyListJob(); + private: + // input: + const QByteArray m_signature; + const QByteArray m_plainText; + QGuardedPtr m_job; + QGuardedPtr m_keylistjob; + bool m_running; + // output: + GpgME::VerificationResult m_vr; + QString m_auditLog; + GpgME::Error m_auditLogError; + GpgME::Key m_key; + }; + + + class VerifyOpaqueBodyPartMemento + : public QObject, + public KMail::Interface::BodyPartMemento, + public KMail::ISubject + { + Q_OBJECT + public: + VerifyOpaqueBodyPartMemento( Kleo::VerifyOpaqueJob * job, + Kleo::KeyListJob * klj, + const QByteArray & signature ); + ~VerifyOpaqueBodyPartMemento(); + + /* reimp */ Interface::Observer * asObserver() { return 0; } + /* reimp */ Interface::Observable * asObservable() { return this; } + + bool start(); + void exec(); + + bool isRunning() const { return m_running; } + + const QByteArray & plainText() const { return m_plainText; } + const GpgME::VerificationResult & verifyResult() const { return m_vr; } + const QString & auditLogAsHtml() const { return m_auditLog; } + GpgME::Error auditLogError() const { return m_auditLogError; } + const GpgME::Key & signingKey() const { return m_key; } + + private slots: + void slotResult( const GpgME::VerificationResult & vr, + const QByteArray & plainText ); + void slotKeyListJobDone(); + void slotNextKey( const GpgME::Key & ); + void notify() { + ISubject::notify(); + } + + private: + void saveResult( const GpgME::VerificationResult &, + const QByteArray & ); + bool canStartKeyListJob() const; + QStringList keyListPattern() const; + bool startKeyListJob(); + private: + // input: + const QByteArray m_signature; + QGuardedPtr m_job; + QGuardedPtr m_keylistjob; + bool m_running; + // output: + GpgME::VerificationResult m_vr; + QByteArray m_plainText; + QString m_auditLog; + GpgME::Error m_auditLogError; + GpgME::Key m_key; + }; + + +} // namespace KMail + +#endif // _KMAIL_OBJECTTREEPARSER_H_