00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
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>
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
00158
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" );
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 → %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
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 ) );
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 }
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