• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdepim
  • Sitemap
  • Contact Us
 

kleopatra

decryptverifytask.cpp

Go to the documentation of this file.
00001 /* -*- mode: c++; c-basic-offset:4 -*-
00002     decryptverifytask.cpp
00003 
00004     This file is part of Kleopatra, the KDE keymanager
00005     Copyright (c) 2008 Klarälvdalens Datakonsult AB
00006 
00007     Kleopatra is free software; you can redistribute it and/or modify
00008     it under the terms of the GNU General Public License as published by
00009     the Free Software Foundation; either version 2 of the License, or
00010     (at your option) any later version.
00011 
00012     Kleopatra is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015     General Public License for more details.
00016 
00017     You should have received a copy of the GNU General Public License
00018     along with this program; if not, write to the Free Software
00019     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00020 
00021     In addition, as a special exception, the copyright holders give
00022     permission to link the code of this program with any edition of
00023     the Qt library by Trolltech AS, Norway (or with modified versions
00024     of Qt that use the same license as Qt), and distribute linked
00025     combinations including the two.  You must obey the GNU General
00026     Public License in all respects for all of the code used other than
00027     Qt.  If you modify this file, you may extend this exception to
00028     your version of the file, but you are not obligated to do so.  If
00029     you do not wish to do so, delete this exception statement from
00030     your version.
00031 */
00032 
00033 #include <config-kleopatra.h>
00034 
00035 #include "decryptverifytask.h"
00036 
00037 
00038 #include <kleo/cryptobackendfactory.h>
00039 #include <kleo/verifyopaquejob.h>
00040 #include <kleo/verifydetachedjob.h>
00041 #include <kleo/decryptjob.h>
00042 #include <kleo/decryptverifyjob.h>
00043 #include <kleo/dn.h>
00044 
00045 #include <models/keycache.h>
00046 #include <models/predicates.h>
00047 
00048 #include <utils/detail_p.h>
00049 #include <utils/input.h>
00050 #include <utils/output.h>
00051 #include <utils/classify.h>
00052 #include <utils/formatting.h>
00053 #include <utils/stl_util.h>
00054 #include <utils/kleo_assert.h>
00055 #include <utils/exception.h>
00056 
00057 #include <kmime/kmime_header_parsing.h>
00058 
00059 #include <gpgme++/error.h>
00060 #include <gpgme++/key.h>
00061 #include <gpgme++/verificationresult.h>
00062 #include <gpgme++/decryptionresult.h>
00063 
00064 #include <gpg-error.h>
00065 
00066 #include <KIconLoader>
00067 #include <KLocale>
00068 #include <KLocalizedString>
00069 
00070 #include <QByteArray>
00071 #include <QColor>
00072 #include <QDateTime>
00073 #include <QStringList>
00074 #include <QTextDocument> // Qt::escape
00075 
00076 #include <boost/bind.hpp>
00077 
00078 #include <algorithm>
00079 #include <cassert>
00080 
00081 using namespace Kleo::Crypto;
00082 using namespace Kleo;
00083 using namespace GpgME;
00084 using namespace boost;
00085 using namespace KMime::Types;
00086 
00087 namespace {
00088 
00089 static QString auditLogFromSender( QObject* sender ) {
00090     const Job * const job = qobject_cast<const Job*>( sender );
00091     return job ? job->auditLogAsHtml() : QString();
00092 }
00093 
00094 static bool addrspec_equal( const AddrSpec & lhs, const AddrSpec & rhs, Qt::CaseSensitivity cs  ) {
00095     return lhs.localPart.compare( rhs.localPart, cs ) == 0 && lhs.domain.compare( rhs.domain, Qt::CaseInsensitive ) == 0;
00096 }
00097 
00098 static bool mailbox_equal( const Mailbox & lhs, const Mailbox & rhs, Qt::CaseSensitivity cs ) {
00099     return addrspec_equal( lhs.addrSpec(), rhs.addrSpec(), cs );
00100 }
00101 
00102 static std::string stripAngleBrackets( const std::string & str ) {
00103     if ( str.empty() )
00104         return str;
00105     if ( str[0] == '<' && str[str.size()-1] == '>' )
00106         return str.substr( 1, str.size() - 2 );
00107     return str;
00108 }
00109 
00110 static std::string email( const UserID & uid ) {
00111 
00112     if ( uid.parent().protocol() == OpenPGP )
00113         return stripAngleBrackets( uid.email() );
00114 
00115     assert( uid.parent().protocol() == CMS );
00116     const std::string id = uid.id();
00117     if ( !id.empty() && id[0] == '<' )
00118         return stripAngleBrackets( id );
00119     return DN( uid.id() )["EMAIL"].trimmed().toUtf8().constData();
00120 }
00121 
00122 static Mailbox mailbox( const UserID & uid ) {
00123     Mailbox mbox;
00124     mbox.setAddress( email( uid ).c_str() );
00125     return mbox;
00126 }
00127 
00128 static std::vector<Mailbox> extractMailboxes( const Key & key ) {
00129     std::vector<Mailbox> res;
00130     Q_FOREACH( const UserID & id, key.userIDs() ) {
00131         const Mailbox mbox = mailbox( id );
00132         if ( !mbox.addrSpec().isEmpty() )
00133             res.push_back( mbox );
00134     }
00135     return res;
00136 }
00137 
00138 static std::vector<Mailbox> extractMailboxes( const std::vector<Key> & signers ) {
00139     std::vector<Mailbox> res;
00140     Q_FOREACH( const Key & i, signers ) {
00141         const std::vector<Mailbox> bxs = extractMailboxes( i );
00142         res.insert( res.end(), bxs.begin(), bxs.end() );
00143     }
00144     return res;
00145 }
00146 
00147 static bool keyContainsMailbox( const Key & key, const Mailbox & mbox ) {
00148     const std::vector<Mailbox> mbxs = extractMailboxes( key );
00149     return std::find_if( mbxs.begin(), mbxs.end(), bind( mailbox_equal, mbox, _1, Qt::CaseInsensitive ) ) != mbxs.end();
00150 }
00151 
00152 static bool keysContainMailbox( const std::vector<Key> & keys, const Mailbox & mbox ) {
00153     return std::find_if( keys.begin(), keys.end(), bind( keyContainsMailbox, _1, mbox ) ) != keys.end();
00154 }
00155 
00156 static bool relevantInDecryptVerifyContext( const VerificationResult & r ) {
00157     // for D/V operations, we ignore verification results which are not errors and contain
00158     // no signatures (which means that the data was just not signed)
00159     return r.error() || r.numSignatures() > 0;
00160 }
00161 
00162 static QString signatureSummaryToString( int summary )
00163 {
00164     if ( summary & Signature::None )
00165         return i18n( "Error: Signature not verified" );
00166     else if ( summary & Signature::Valid || summary & Signature::Green )
00167         return i18n( "Good signature" );
00168     else if ( summary & Signature::Red )
00169         return i18n( "Bad signature" );
00170     else if ( summary & Signature::KeyRevoked )
00171         return i18n( "Signing certificate revoked" );
00172     else if ( summary & Signature::KeyExpired )
00173         return i18n( "Signing certificate expired" );
00174         else if ( summary & Signature::KeyMissing )
00175         return i18n( "No public key to verify the signature" );
00176     else if ( summary & Signature::SigExpired )
00177         return i18n( "Signature expired" );
00178     else if ( summary & Signature::KeyMissing )
00179         return i18n( "Key missing" );
00180     else if ( summary & Signature::CrlMissing )
00181         return i18n( "CRL missing" );
00182     else if ( summary & Signature::CrlTooOld )
00183         return i18n( "CRL too old" );
00184     else if ( summary & Signature::BadPolicy )
00185         return i18n( "Bad policy" );
00186     else if ( summary & Signature::SysError )
00187         return i18n( "System error" ); //### retrieve system error details?
00188     return QString();
00189 }
00190 
00191 static QString formatValidSignatureWithTrustLevel( const Key & key, const UserID & id ) {
00192     assert( !key.isNull() );
00193     assert( !id.isNull() );
00194     switch ( id.validity() ) {
00195         case UserID::Marginal:
00196             return i18n( "The signature is valid but the trust in the certificate's validity is only marginal." );
00197         case UserID::Full:
00198             return i18n( "The signature is valid and the certificate's validity is fully trusted." );
00199         case UserID::Ultimate:
00200             return i18n( "The signature is valid and the certificate's validity is ultimately trusted." );
00201         case UserID::Never:
00202             return i18n( "The signature is valid but the certificate's validity is <em>not trusted</em>." );
00203         case UserID::Unknown:
00204             return i18n( "The signature is valid but the certificate's validity is unknown." );
00205         case UserID::Undefined:
00206         default:
00207             return i18n( "The signature is valid but the certificate's validity is undefined." );
00208     }
00209 }
00210 
00211 static QString renderFingerprint( const char * fpr ) {
00212     if ( !fpr )
00213         return QString();
00214     return QString( "0x%1" ).arg( QString::fromAscii( fpr ).toUpper() );
00215 }
00216 
00217 static QString renderKeyLink( const QString & fpr, const QString & text ) {
00218     return QString::fromLatin1( "<a href=\"key:%1\">%2</a>" ).arg( fpr ).arg( text );
00219 }
00220 
00221 static QString renderKey( const Key & key ) {
00222     if ( key.isNull() )
00223         return i18n( "Unknown key" );
00224     return renderKeyLink( key.primaryFingerprint(), Formatting::prettyName( key ) );
00225 }
00226 
00227 static QString renderKeyEMailOnlyNameAsFallback( const Key & key ) {
00228     if ( key.isNull() )
00229         return i18n( "Unknown key" );
00230     const QString email = Formatting::prettyEMail( key );
00231     const QString user = !email.isNull() ? email : Formatting::prettyName( key );
00232     return renderKeyLink( key.primaryFingerprint(), user );
00233 }
00234 
00235 static QString formatDate( const QDateTime & dt ) {
00236     return KGlobal::locale()->formatDateTime( dt );
00237 }
00238 static QString formatSigningInformation( const Signature & sig, const Key & key ) {
00239     if ( sig.isNull() )
00240         return QString();
00241     const QDateTime dt = sig.creationTime() != 0 ? QDateTime::fromTime_t( sig.creationTime() ) : QDateTime();
00242     const QString signer = key.isNull() ? QString() : renderKeyEMailOnlyNameAsFallback( key );
00243     const bool haveKey = !key.isNull();
00244     const bool haveSigner = !signer.isEmpty();
00245     const bool haveDate = dt.isValid();
00246     if ( !haveKey ) {
00247         if ( haveDate )
00248             return i18n( "Signed on %1 with unknown key %2.", formatDate( dt ), renderFingerprint( sig.fingerprint() ) );
00249         else
00250             return i18n( "Signed with unknown key %1.", renderFingerprint( sig.fingerprint() ) );
00251     }
00252     if ( haveSigner ) {
00253         if ( haveDate )
00254             return i18nc( "date, key owner, key ID",
00255                           "Signed on %1 by %2 (Key ID: %3).",
00256                           formatDate( dt ),
00257                           signer,
00258                           renderFingerprint( key.keyID() ) );
00259         else
00260             return i18n( "Signed by %1 with key %2.", signer, renderKey( key ) );
00261     }
00262     if ( haveDate )
00263         return i18n( "Signed on %1 with key %2.", formatDate( dt ), renderKey( key ) );
00264     return i18n( "Signed with key %1.", renderKey( key ) );
00265 
00266 }
00267 
00268 static QString strikeOut( const QString & str, bool strike ) {
00269     return QString( strike ? "<s>%1</s>" : "%1" ).arg( Qt::escape( str ) );
00270 }
00271 
00272 static QString formatInputOutputLabel( const QString & input, const QString & output, bool inputDeleted, bool outputDeleted ) {
00273     if ( output.isEmpty() )
00274         return strikeOut( input, inputDeleted );
00275     return i18nc( "Input file --> Output file (rarr is arrow", "%1 &rarr; %2",
00276                   strikeOut( input, inputDeleted ),
00277                   strikeOut( output, outputDeleted ) );
00278 }
00279 
00280 static const char * iconForSignature( const Signature & sig ) {
00281     if ( sig.summary() & Signature::Green )
00282         return "dialog-ok";
00283     if ( sig.summary() & Signature::Red )
00284         return "dialog-error";
00285     return "dialog-warning";
00286 }
00287 
00288 static QColor color( const DecryptionResult & dr, const VerificationResult & vr ) {
00289     if ( !dr.isNull() && dr.error() )
00290         return Qt::red;
00291     if ( !vr.isNull() && vr.error() )
00292         return Qt::red;
00293     return Qt::gray;
00294 }
00295 
00296 static QColor color( const Signature & sig ) {
00297     if ( sig.summary() & GpgME::Signature::Red )
00298         return Qt::red;
00299     if ( sig.summary() & GpgME::Signature::Green )
00300         return Qt::green;
00301     return Qt::yellow;
00302 }
00303 
00304 static bool IsErrorOrCanceled( const GpgME::Error & err )
00305 {
00306     return err || err.isCanceled();
00307 }
00308 
00309 static bool IsErrorOrCanceled( const Result & res )
00310 {
00311     return IsErrorOrCanceled( res.error() );
00312 }
00313 
00314 static bool IsBad( const Signature & sig ) {
00315     return sig.summary() & Signature::Red;
00316 }
00317 
00318 static bool IsGoodOrValid( const Signature & sig ) {
00319     return (sig.summary() & Signature::Valid) || (sig.summary() & Signature::Green);
00320 }
00321 
00322 static UserID findUserIDByMailbox( const Key & key, const Mailbox & mbox ) {
00323     Q_FOREACH( const UserID & id, key.userIDs() )
00324         if ( mailbox_equal( mailbox( id ), mbox, Qt::CaseInsensitive ) )
00325             return id;
00326     return UserID();
00327 }
00328 
00329 }
00330 
00331 class DecryptVerifyResult::SenderInfo {
00332 public:
00333     explicit SenderInfo( const Mailbox & infSender, const std::vector<Key> & signers_ ) : informativeSender( infSender ), signers( signers_ ) {}
00334     const Mailbox informativeSender;
00335     const std::vector<Key> signers;
00336     bool hasInformativeSender() const { return !informativeSender.addrSpec().isEmpty(); }
00337     bool conflicts() const { return hasInformativeSender() && !keysContainMailbox( signers, informativeSender ); }
00338     std::vector<Mailbox> signerMailboxes() const {return extractMailboxes( signers ); }
00339 };
00340 
00341 namespace {
00342 
00343 static Task::Result::VisualCode codeForVerificationResult( const VerificationResult & res )
00344 {
00345     if ( res.isNull() )
00346         return Task::Result::NeutralSuccess;
00347 
00348     const std::vector<Signature> sigs = res.signatures();
00349     if ( sigs.empty() )
00350         return Task::Result::Warning;
00351 
00352     if ( std::find_if( sigs.begin(), sigs.end(), IsBad ) != sigs.end() )
00353         return Task::Result::Danger;
00354 
00355     if ( std::count_if( sigs.begin(), sigs.end(), IsGoodOrValid ) == sigs.size() )
00356         return Task::Result::AllGood;
00357 
00358     return Task::Result::Warning;
00359 }
00360 
00361 static QString formatVerificationResultOverview( const VerificationResult & res, const DecryptVerifyResult::SenderInfo & info ) {
00362     if ( res.isNull() )
00363         return QString();
00364 
00365     const Error err = res.error();
00366 
00367     if ( err.isCanceled() )
00368         return i18n("<b>Verification canceled.</b>");
00369     else if ( err )
00370         return i18n( "<b>Verification failed: %1.</b>", Qt::escape( QString::fromLocal8Bit( err.asString() ) ) );
00371 
00372     const std::vector<Signature> sigs = res.signatures();
00373     const std::vector<Key> signers = info.signers;
00374 
00375     if ( sigs.empty() )
00376         return i18n( "<b>No signatures found.</b>" );
00377 
00378     const uint bad = std::count_if( sigs.begin(), sigs.end(), IsBad );
00379     if ( bad > 0 ) {
00380         return i18np("<b>Invalid signature.</b>", "<b>%1 invalid signatures.</b>", bad );
00381     }
00382     const uint warn = std::count_if( sigs.begin(), sigs.end(), !bind( IsGoodOrValid, _1 ) );
00383     if ( warn > 0 )
00384         return i18np("<b>Not enough information to check signature validity.</b>", "<b>%1 signatures could not be verified.</b>", warn );
00385 
00386     //Good signature:
00387     QString text;
00388     if ( sigs.size() == 1 ) {
00389         const Key key = DecryptVerifyResult::keyForSignature( sigs[0], signers );
00390         if ( key.isNull() )
00391             text = i18n( "<b>Signature is valid.</b>" );
00392         else
00393             text = i18n( "<b>Signed by %1</b>", renderKeyEMailOnlyNameAsFallback( key ) );
00394         if ( info.conflicts() )
00395             text += i18n( "<br/><b>Warning:</b> The sender's mail address is not stored in the %1 used for signing.",
00396                           key.isNull() ? i18n( "certificate" ) : renderKeyLink( key.primaryFingerprint(), i18n( "certificate" ) ) );
00397     }
00398     else {
00399         text = i18np("<b>Valid signature.</b>", "<b>%1 valid signatures.</b>", sigs.size() );
00400         if ( info.conflicts() )
00401             text += i18n( "<br/><b>Warning:</b> The sender's mail address is not stored in the certificates used for signing." );
00402     }
00403 
00404     return text;
00405 }
00406 
00407 static QString formatDecryptionResultOverview( const DecryptionResult & result )
00408 {
00409     const Error err = result.error();
00410 
00411     if ( err.isCanceled() )
00412         return i18n("<b>Decryption canceled.</b>");
00413     else if ( err )
00414         return i18n( "<b>Decryption failed: %1.</b>", Qt::escape( QString::fromLocal8Bit( err.asString() ) ) );
00415     return i18n("<b>Decryption succeeded.</b>" );
00416 }
00417 
00418 static QString formatSignature( const Signature & sig, const Key & key, const DecryptVerifyResult::SenderInfo & info ) {
00419     if ( sig.isNull() )
00420         return QString();
00421 
00422     QString text = formatSigningInformation( sig, key ) + "<br/>";
00423 
00424     const bool red = sig.summary() & Signature::Red;
00425     if ( sig.summary() & Signature::Valid ) {
00426         const UserID id = findUserIDByMailbox( key, info.informativeSender );
00427         return text + formatValidSignatureWithTrustLevel( key, !id.isNull() ? id : key.userID( 0 ) ); // ### TODO handle key.isNull()?
00428     }
00429     if ( red ) {
00430         if ( key.isNull() )
00431             if ( const char * fpr = sig.fingerprint() )
00432                 return text + i18n("Bad signature by unknown key %1.", renderFingerprint( fpr ) );
00433             else
00434                 return text + i18n("Bad signature by an unknown key." );
00435         else
00436             return text + i18n("Bad signature by %1.", renderKey( key ) );
00437     }
00438     if ( key.isNull() )
00439         if ( const char * fpr = sig.fingerprint() )
00440             return text + i18n("Invalid signature by unknown key %1: %2", renderFingerprint( fpr ), signatureSummaryToString( sig.summary() ) );
00441         else
00442             return text + i18n("Invalid signature by an unknown key: %1", signatureSummaryToString( sig.summary() ) );
00443     else
00444         return text + i18n("Invalid signature by %1: %2", renderKey( key ), signatureSummaryToString( sig.summary() ) );
00445 }
00446 
00447 static QStringList format( const std::vector<Mailbox> & mbxs ) {
00448     QStringList res;
00449     std::transform( mbxs.begin(), mbxs.end(), std::back_inserter( res ), bind( &Mailbox::prettyAddress, _1 ) );
00450     return res;
00451 }
00452 
00453 static QString formatVerificationResultDetails( const VerificationResult & res, const DecryptVerifyResult::SenderInfo & info )
00454 {
00455     const std::vector<Signature> sigs = res.signatures();
00456     const std::vector<Key> signers = KeyCache::instance()->findSigners( res );
00457     QString details;
00458     Q_FOREACH ( const Signature & sig, sigs )
00459         details += formatSignature( sig, DecryptVerifyResult::keyForSignature( sig, signers ), info ) + '\n';
00460     details = details.trimmed();
00461     details.replace( '\n', "<br/>" );
00462     if ( info.conflicts() )
00463         details += i18n( "<p>The sender's address %1 is not stored in the certificate. Stored: %2</p>", info.informativeSender.prettyAddress(), format( info.signerMailboxes() ).join( i18nc("separator for a list of e-mail addresses", ", " ) ) );
00464     return details;
00465 }
00466 
00467 static QString formatDecryptionResultDetails( const DecryptionResult & res, const std::vector<Key> & recipients )
00468 {
00469     if ( res.isNull() || !res.error() || res.error().isCanceled() )
00470         return QString();
00471 
00472     if ( recipients.empty() && res.numRecipients() > 0 )
00473         return QString( "<i>" + i18np( "One unknown recipient.", "%1 unknown recipients.", res.numRecipients() ) + "</i>" );
00474 
00475     QString details;
00476     if ( !recipients.empty() ) {
00477         details += i18np( "Recipients:", "Recipients:", res.numRecipients() );
00478         if ( res.numRecipients() == 1 )
00479             return details + renderKey( recipients.front() );
00480 
00481         details += "<ul>";
00482         Q_FOREACH( const Key & key, recipients )
00483             details += "<li>" + renderKey( key ) + "</li>";
00484         if ( recipients.size() < res.numRecipients() )
00485             details += "<li><i>" + i18np( "One unknown recipient", "%1 unknown recipients",
00486                                        res.numRecipients() - recipients.size() ) + "</i></li>";
00487 
00488         details += "</ul>";
00489     }
00490 
00491     return details;
00492 }
00493 
00494 static QString formatDecryptVerifyResultOverview( const DecryptionResult & dr, const VerificationResult & vr, const  DecryptVerifyResult::SenderInfo & info )
00495 {
00496     if ( IsErrorOrCanceled( dr ) || !relevantInDecryptVerifyContext( vr ) )
00497         return formatDecryptionResultOverview( dr );
00498     return formatVerificationResultOverview( vr, info );
00499 }
00500 
00501 static QString formatDecryptVerifyResultDetails( const DecryptionResult & dr,
00502                                                  const VerificationResult & vr,
00503                                                  const std::vector<Key> & recipients,
00504                                                  const DecryptVerifyResult::SenderInfo & info )
00505 {
00506     const QString drDetails = formatDecryptionResultDetails( dr, recipients );
00507     if ( IsErrorOrCanceled( dr ) || !relevantInDecryptVerifyContext( vr ) )
00508         return drDetails;
00509     return drDetails + ( drDetails.isEmpty() ? "" : "<br/>" ) + formatVerificationResultDetails( vr, info );
00510 }
00511 
00512 } // anon namespace
00513 
00514 class DecryptVerifyResult::Private {
00515     DecryptVerifyResult* const q;
00516 public:
00517     Private( DecryptVerifyOperation type,
00518              const VerificationResult & vr,
00519              const DecryptionResult & dr,
00520              const QByteArray & stuff,
00521              int errCode,
00522              const QString & errString,
00523              const QString & input,
00524              const QString & output,
00525              const QString & auditLog,
00526              const Mailbox & informativeSender,
00527              DecryptVerifyResult* qq ) :
00528                  q( qq ),
00529                  m_type( type ),
00530                  m_verificationResult( vr ),
00531                  m_decryptionResult( dr ),
00532                  m_stuff( stuff ),
00533                  m_error( errCode ),
00534                  m_errorString( errString ),
00535                  m_inputLabel( input ),
00536                  m_outputLabel( output ),
00537                  m_auditLog( auditLog ),
00538                  m_informativeSender( informativeSender )
00539     {
00540     }
00541 
00542     QString label() const {
00543         return formatInputOutputLabel( m_inputLabel, m_outputLabel, false, q->hasError() );
00544     }
00545 
00546     DecryptVerifyResult::SenderInfo makeSenderInfo() const;
00547 
00548     bool isDecryptOnly() const { return m_type == Decrypt; }
00549     bool isVerifyOnly() const { return m_type == Verify; }
00550     bool isDecryptVerify() const { return m_type == DecryptVerify; }
00551     DecryptVerifyOperation m_type;
00552     VerificationResult m_verificationResult;
00553     DecryptionResult m_decryptionResult;
00554     QByteArray m_stuff;
00555     int m_error;
00556     QString m_errorString;
00557     QString m_inputLabel;
00558     QString m_outputLabel;
00559     const QString m_auditLog;
00560     const Mailbox m_informativeSender;
00561 };
00562 
00563 DecryptVerifyResult::SenderInfo DecryptVerifyResult::Private::makeSenderInfo() const {
00564     return SenderInfo( m_informativeSender, KeyCache::instance()->findSigners( m_verificationResult ) );
00565 }
00566 
00567 shared_ptr<DecryptVerifyResult> AbstractDecryptVerifyTask::fromDecryptResult( const DecryptionResult & dr, const QByteArray & plaintext, const QString & auditLog ) {
00568     return shared_ptr<DecryptVerifyResult>( new DecryptVerifyResult(
00569         Decrypt,
00570         VerificationResult(),
00571         dr,
00572         plaintext,
00573         0,
00574         QString(),
00575         inputLabel(),
00576         outputLabel(),
00577         auditLog,
00578         informativeSender() ) );
00579 }
00580 
00581 shared_ptr<DecryptVerifyResult> AbstractDecryptVerifyTask::fromDecryptResult( const GpgME::Error & err, const QString& what, const QString & auditLog ) {
00582     return shared_ptr<DecryptVerifyResult>( new DecryptVerifyResult(
00583         Decrypt,
00584         VerificationResult(),
00585         DecryptionResult( err ),
00586         QByteArray(),
00587         err.code(),
00588         what,
00589         inputLabel(),
00590         outputLabel(),
00591         auditLog,
00592         informativeSender() ) );
00593 }
00594 
00595 shared_ptr<DecryptVerifyResult> AbstractDecryptVerifyTask::fromDecryptVerifyResult( const DecryptionResult & dr, const VerificationResult & vr, const QByteArray & plaintext, const QString & auditLog ) {
00596     return shared_ptr<DecryptVerifyResult>( new DecryptVerifyResult(
00597         DecryptVerify,
00598         vr,
00599         dr,
00600         plaintext,
00601         0,
00602         QString(),
00603         inputLabel(),
00604         outputLabel(),
00605         auditLog,
00606         informativeSender() ) );
00607 }
00608 
00609 shared_ptr<DecryptVerifyResult> AbstractDecryptVerifyTask::fromDecryptVerifyResult( const GpgME::Error & err, const QString & details, const QString & auditLog ) {
00610     return shared_ptr<DecryptVerifyResult>( new DecryptVerifyResult(
00611         DecryptVerify,
00612         VerificationResult(),
00613         DecryptionResult( err ),
00614         QByteArray(),
00615         err.code(),
00616         details,
00617         inputLabel(),
00618         outputLabel(),
00619         auditLog,
00620         informativeSender() ) );
00621 }
00622 
00623 shared_ptr<DecryptVerifyResult> AbstractDecryptVerifyTask::fromVerifyOpaqueResult( const VerificationResult & vr, const QByteArray & plaintext, const QString & auditLog ) {
00624     return shared_ptr<DecryptVerifyResult>( new DecryptVerifyResult(
00625         Verify,
00626         vr,
00627         DecryptionResult(),
00628         plaintext,
00629         0,
00630         QString(),
00631         inputLabel(),
00632         outputLabel(),
00633         auditLog,
00634         informativeSender() ) );
00635 }
00636 shared_ptr<DecryptVerifyResult> AbstractDecryptVerifyTask::fromVerifyOpaqueResult( const GpgME::Error & err, const QString & details, const QString & auditLog ) {
00637     return shared_ptr<DecryptVerifyResult>( new DecryptVerifyResult(
00638         Verify,
00639         VerificationResult( err ),
00640         DecryptionResult(),
00641         QByteArray(),
00642         err.code(),
00643         details,
00644         inputLabel(),
00645         outputLabel(),
00646         auditLog,
00647         informativeSender() ) );
00648 }
00649 
00650 shared_ptr<DecryptVerifyResult> AbstractDecryptVerifyTask::fromVerifyDetachedResult( const VerificationResult & vr, const QString & auditLog ) {
00651     return shared_ptr<DecryptVerifyResult>( new DecryptVerifyResult(
00652         Verify,
00653         vr,
00654         DecryptionResult(),
00655         QByteArray(),
00656         0,
00657         QString(),
00658         inputLabel(),
00659         outputLabel(),
00660         auditLog,
00661         informativeSender() ) );
00662 }
00663 shared_ptr<DecryptVerifyResult> AbstractDecryptVerifyTask::fromVerifyDetachedResult( const GpgME::Error & err, const QString & details, const QString & auditLog ) {
00664     return shared_ptr<DecryptVerifyResult>( new DecryptVerifyResult(
00665         Verify,
00666         VerificationResult( err ),
00667         DecryptionResult(),
00668         QByteArray(),
00669         err.code(),
00670         details,
00671         inputLabel(),
00672         outputLabel(),
00673         auditLog,
00674         informativeSender() ) );
00675 }
00676 
00677 DecryptVerifyResult::DecryptVerifyResult( DecryptVerifyOperation type,
00678                     const VerificationResult& vr,
00679                     const DecryptionResult& dr,
00680                     const QByteArray& stuff,
00681                     int errCode,
00682                     const QString & errString,
00683                     const QString & inputLabel,
00684                     const QString & outputLabel,
00685                     const QString & auditLog,
00686                     const Mailbox & informativeSender )
00687     : Task::Result(), d( new Private( type, vr, dr, stuff, errCode, errString, inputLabel, outputLabel, auditLog, informativeSender, this ) )
00688 {
00689 }
00690 
00691 QString DecryptVerifyResult::overview() const
00692 {
00693     QString ov;
00694     if ( d->isDecryptOnly() )
00695         ov = formatDecryptionResultOverview( d->m_decryptionResult );
00696     else if ( d->isVerifyOnly() )
00697         ov = formatVerificationResultOverview( d->m_verificationResult, d->makeSenderInfo() );
00698     else
00699         ov = formatDecryptVerifyResultOverview( d->m_decryptionResult, d->m_verificationResult, d->makeSenderInfo() );
00700     return i18nc( "label: result example: foo.sig: Verification failed. ", "%1: %2", d->label(), ov );
00701 }
00702 
00703 QString DecryptVerifyResult::details() const
00704 {
00705     if ( d->isDecryptOnly() )
00706         return formatDecryptionResultDetails( d->m_decryptionResult, KeyCache::instance()->findRecipients( d->m_decryptionResult ) );
00707     if ( d->isVerifyOnly() )
00708         return formatVerificationResultDetails( d->m_verificationResult, d->makeSenderInfo() );
00709     return formatDecryptVerifyResultDetails( d->m_decryptionResult, d->m_verificationResult, KeyCache::instance()->findRecipients( d->m_decryptionResult ), d->makeSenderInfo() );
00710 }
00711 
00712 bool DecryptVerifyResult::hasError() const
00713 {
00714     return d->m_error != 0;
00715 }
00716 
00717 int DecryptVerifyResult::errorCode() const
00718 {
00719     return d->m_error;
00720 }
00721 
00722 QString DecryptVerifyResult::errorString() const
00723 {
00724     return d->m_errorString;
00725 }
00726 
00727 QString DecryptVerifyResult::auditLogAsHtml() const {
00728     return d->m_auditLog;
00729 }
00730 
00731 Task::Result::VisualCode DecryptVerifyResult::code() const {
00732     if ( ( d->m_type == DecryptVerify || d->m_type == Verify ) && relevantInDecryptVerifyContext( verificationResult() ) )
00733         return codeForVerificationResult( verificationResult() );
00734     return hasError() ? NeutralError : NeutralSuccess;
00735 }
00736 
00737 GpgME::VerificationResult DecryptVerifyResult::verificationResult() const
00738 {
00739     return d->m_verificationResult;
00740 }
00741 
00742 const Key & DecryptVerifyResult::keyForSignature( const Signature & sig, const std::vector<Key> & keys ) {
00743     if ( const char * const fpr = sig.fingerprint() ) {
00744         const std::vector<Key>::const_iterator it
00745             = std::lower_bound( keys.begin(), keys.end(), fpr, _detail::ByFingerprint<std::less>() );
00746         if ( it != keys.end() && _detail::ByFingerprint<std::equal_to>()( *it, fpr ) )
00747             return *it;
00748     }
00749     static const Key null;
00750     return null;
00751 }
00752 
00753 class AbstractDecryptVerifyTask::Private {
00754 public:
00755     Mailbox informativeSender;
00756 };
00757 
00758 
00759 AbstractDecryptVerifyTask::AbstractDecryptVerifyTask( QObject * parent ) : Task( parent ), d( new Private ) {}
00760 
00761 AbstractDecryptVerifyTask::~AbstractDecryptVerifyTask() {}
00762 
00763 
00764 Mailbox AbstractDecryptVerifyTask::informativeSender() const {
00765     return d->informativeSender;
00766 }
00767 
00768 
00769 void AbstractDecryptVerifyTask::setInformativeSender( const Mailbox & sender ) {
00770     d->informativeSender = sender;
00771 }
00772 
00773 class DecryptVerifyTask::Private {
00774     DecryptVerifyTask* const q;
00775 public:
00776     explicit Private( DecryptVerifyTask* qq ) : q( qq ), m_backend( 0 ), m_protocol( UnknownProtocol )  {}
00777 
00778     void slotResult( const DecryptionResult&, const VerificationResult&, const QByteArray& );
00779 
00780     void registerJob( DecryptVerifyJob * job ) {
00781         q->connect( job, SIGNAL(result(GpgME::DecryptionResult,GpgME::VerificationResult,QByteArray)),
00782                     q, SLOT(slotResult(GpgME::DecryptionResult,GpgME::VerificationResult,QByteArray)) );
00783         q->connect( job, SIGNAL(progress(QString,int,int)),
00784                     q, SLOT(setProgress(QString,int,int)) );
00785     }
00786 
00787     void emitResult( const shared_ptr<DecryptVerifyResult>& result );
00788 
00789     shared_ptr<Input> m_input;
00790     shared_ptr<Output> m_output;
00791     const CryptoBackend::Protocol* m_backend;
00792     Protocol m_protocol;
00793 };
00794 
00795 
00796 void DecryptVerifyTask::Private::emitResult( const shared_ptr<DecryptVerifyResult>& result )
00797 {
00798     q->emitResult( result );
00799     emit q->decryptVerifyResult( result );
00800 }
00801 
00802 void DecryptVerifyTask::Private::slotResult( const DecryptionResult& dr, const VerificationResult& vr, const QByteArray& plainText )
00803 {
00804     const QString auditLog = auditLogFromSender( q->sender() );
00805     if ( dr.error().code() || vr.error().code() ) {
00806         m_output->cancel();
00807     } else {
00808         try {
00809             kleo_assert( !dr.isNull() || !vr.isNull() );
00810             m_output->finalize();
00811         } catch ( const GpgME::Exception & e ) {
00812             emitResult( q->fromDecryptResult( e.error(), QString::fromLocal8Bit( e.what() ), auditLog ) );
00813             return;
00814         }
00815     }
00816 
00817     emitResult( q->fromDecryptVerifyResult( dr, vr, plainText, auditLog ) );
00818 }
00819 
00820 
00821 DecryptVerifyTask::DecryptVerifyTask( QObject* parent ) : AbstractDecryptVerifyTask( parent ), d( new Private( this ) )
00822 {
00823 }
00824 
00825 DecryptVerifyTask::~DecryptVerifyTask()
00826 {
00827 }
00828 
00829 void DecryptVerifyTask::setInput( const shared_ptr<Input> & input )
00830 {
00831     d->m_input = input;
00832     kleo_assert( d->m_input && d->m_input->ioDevice() );
00833 }
00834 
00835 void DecryptVerifyTask::setOutput( const shared_ptr<Output> & output )
00836 {
00837     d->m_output = output;
00838     kleo_assert( d->m_output && d->m_output->ioDevice() );
00839 }
00840 
00841 void DecryptVerifyTask::setProtocol( Protocol prot )
00842 {
00843     kleo_assert( prot != UnknownProtocol );
00844     d->m_protocol = prot;
00845     d->m_backend = CryptoBackendFactory::instance()->protocol( prot );
00846     kleo_assert( d->m_backend );
00847 }
00848 
00849 void DecryptVerifyTask::autodetectProtocolFromInput()
00850 {
00851     if ( d->m_input )
00852         setProtocol( findProtocol( d->m_input->classification() ) );
00853 }
00854 
00855 QString DecryptVerifyTask::label() const
00856 {
00857     return i18n( "Decrypting: %1...", d->m_input->label() );
00858 }
00859 
00860 unsigned long long DecryptVerifyTask::inputSize() const
00861 {
00862     return d->m_input ? d->m_input->size() : 0;
00863 }
00864 
00865 QString DecryptVerifyTask::inputLabel() const
00866 {
00867     return d->m_input ? d->m_input->label() : QString();
00868 }
00869 
00870 QString DecryptVerifyTask::outputLabel() const
00871 {
00872     return d->m_output ? d->m_output->label() : QString();
00873 }
00874 
00875 Protocol DecryptVerifyTask::protocol() const
00876 {
00877     return d->m_protocol;
00878 }
00879 
00880 void DecryptVerifyTask::cancel()
00881 {
00882 
00883 }
00884 
00885 void DecryptVerifyTask::doStart()
00886 {
00887     kleo_assert( d->m_backend );
00888     try {
00889         DecryptVerifyJob * const job = d->m_backend->decryptVerifyJob();
00890         kleo_assert( job );
00891         d->registerJob( job );
00892         job->start( d->m_input->ioDevice(), d->m_output->ioDevice() );
00893     } catch ( con