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

kleopatra

certificatedetailsdialog.cpp

Go to the documentation of this file.
00001 /* -*- mode: c++; c-basic-offset:4 -*-
00002     dialogs/certificatedetailsdialog.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 "certificatedetailsdialog.h"
00036 
00037 #include "ui_certificatedetailsdialog.h"
00038 
00039 #include <models/useridlistmodel.h>
00040 #include <models/subkeylistmodel.h>
00041 #include <models/keycache.h>
00042 
00043 #include <commands/changepassphrasecommand.h>
00044 #include <commands/changeownertrustcommand.h>
00045 #include <commands/changeexpirycommand.h>
00046 #include <commands/adduseridcommand.h>
00047 #include <commands/certifycertificatecommand.h>
00048 #include <commands/dumpcertificatecommand.h>
00049 
00050 #include <utils/formatting.h>
00051 #include <utils/gnupg-helper.h>
00052 
00053 #include <kleo/cryptobackendfactory.h>
00054 #include <kleo/cryptobackend.h>
00055 #include <kleo/keylistjob.h>
00056 #include <kleo/dn.h>
00057 
00058 #include <gpgme++/key.h>
00059 #include <gpgme++/keylistresult.h>
00060 
00061 #include <KDebug>
00062 #include <KMessageBox>
00063 #include <KLocalizedString>
00064 #include <KGlobalSettings>
00065 
00066 #include <QPointer>
00067 #include <QHeaderView>
00068 
00069 #include <boost/mem_fn.hpp>
00070 
00071 #include <algorithm>
00072 #include <cassert>
00073 
00074 using namespace Kleo;
00075 using namespace Kleo::Dialogs;
00076 using namespace Kleo::Commands;
00077 using namespace GpgME;
00078 using namespace boost;
00079 
00080 static bool own( const std::vector<UserID::Signature> & sigs ) {
00081     const shared_ptr<const KeyCache> kc = KeyCache::instance();
00082     Q_FOREACH( const UserID::Signature & sig, sigs ) {
00083         const Key signer = kc->findByKeyIDOrFingerprint( sig.signerKeyID() );
00084         if ( signer.isNull() || !signer.hasSecret() )
00085             return false;
00086     }
00087     return !sigs.empty();
00088 }
00089 
00090 class CertificateDetailsDialog::Private {
00091     friend class ::Kleo::Dialogs::CertificateDetailsDialog;
00092     CertificateDetailsDialog * const q;
00093 public:
00094     explicit Private( CertificateDetailsDialog * qq )
00095         : q( qq ),
00096           key(),
00097           certificationsModel(),
00098           subkeysModel(),
00099           ui( q )
00100     {
00101         ui.certificationsTV->setModel( &certificationsModel );
00102         connect( ui.certificationsTV->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
00103                  q, SLOT(slotCertificationSelectionChanged()) );
00104 
00105         ui.subkeyTV->setModel( &subkeysModel );
00106         // no selection (yet)
00107 
00108         connect( KeyCache::instance().get(), SIGNAL(keysMayHaveChanged()),
00109                  q, SLOT(slotKeysMayHaveChanged()) );
00110     }
00111 
00112 private:
00113     void startCommandImplementation( const QPointer<Command> & ptr, const char * slot ) {
00114         connect( ptr, SIGNAL(finished()), q, slot );
00115         ptr->start();
00116         enableDisableWidgets();
00117     }
00118     template <typename T, typename A>
00119     void startCommand( QPointer<Command> & ptr, const A & arg, const char * slot ) {
00120         if ( ptr )
00121             return;
00122         ptr = new T( arg );
00123         startCommandImplementation( ptr, slot );
00124     }
00125     template <typename T>
00126     void startCommand( QPointer<Command> & ptr, const char * slot ) {
00127         startCommand<T>( ptr, this->key, slot );
00128     }
00129     void commandFinished( QPointer<Command> & ptr ) {
00130         ptr = 0;
00131         enableDisableWidgets();
00132     }
00133 
00134     void slotChangePassphraseClicked() {
00135         startCommand<ChangePassphraseCommand>( changePassphraseCommand, SLOT(slotChangePassphraseCommandFinished()) );
00136     }
00137     void slotChangePassphraseCommandFinished() {
00138         commandFinished( changePassphraseCommand );
00139     }
00140 
00141     void slotChangeTrustLevelClicked() {
00142         startCommand<ChangeOwnerTrustCommand>( changeOwnerTrustCommand, SLOT(slotChangeOwnerTrustCommandFinished()) );
00143     }
00144     void slotChangeOwnerTrustCommandFinished() {
00145         commandFinished( changeOwnerTrustCommand );
00146     }
00147 
00148     void slotChangeExpiryDateClicked() {
00149         startCommand<ChangeExpiryCommand>( changeExpiryDateCommand, SLOT(slotChangeExpiryDateCommandFinished()) );
00150     }
00151     void slotChangeExpiryDateCommandFinished() {
00152         commandFinished( changeExpiryDateCommand );
00153     }
00154 
00155     void slotAddUserIDClicked() {
00156         startCommand<AddUserIDCommand>( addUserIDCommand, SLOT(slotAddUserIDCommandFinished()) );
00157     }
00158     void slotAddUserIDCommandFinished() {
00159         commandFinished( addUserIDCommand );
00160     }
00161 
00162     void slotCertifyUserIDClicked() {
00163         const std::vector<UserID> uids = selectedUserIDs();
00164         if ( uids.empty() )
00165             return;
00166         startCommand<CertifyCertificateCommand>( signCertificateCommand, uids, SLOT(slotSignCertificateCommandFinished()) );
00167     }
00168     void slotSignCertificateCommandFinished() {
00169         commandFinished( signCertificateCommand );
00170     }
00171 
00172     void slotRevokeCertificateClicked() {
00173 
00174     }
00175 
00176     void slotRevokeUserIDClicked() {
00177 
00178     }
00179 
00180     void slotRevokeCertificationClicked() {
00181 
00182     }
00183 
00184     void slotShowCertificationsClicked() {
00185         startSignatureListing();
00186         enableDisableWidgets();
00187     }
00188 
00189     void startSignatureListing() {
00190         if ( keyListJob )
00191             return;
00192         const CryptoBackend::Protocol * const protocol = CryptoBackendFactory::instance()->protocol( key.protocol() );
00193         if ( !protocol )
00194             return;
00195         KeyListJob * const job = protocol->keyListJob( /*remote*/false, /*includeSigs*/true, /*validate*/true );
00196         if ( !job )
00197             return;
00198         connect( job, SIGNAL(result(GpgME::KeyListResult)),
00199                  q, SLOT(slotSignatureListingDone(GpgME::KeyListResult)) );
00200         connect( job, SIGNAL(nextKey(GpgME::Key)),
00201                  q, SLOT(slotSignatureListingNextKey(GpgME::Key)) );
00202         if ( const Error err = job->start( QStringList( QString::fromLatin1( key.primaryFingerprint() ) ) ) )
00203             showSignatureListingErrorDialog( err );
00204         else
00205             keyListJob = job;
00206     }
00207     void slotSignatureListingNextKey( const Key & key ) {
00208         // don't lose the secret flags ...
00209         Key merged = key;
00210         merged.mergeWith( this->key );
00211         q->setKey( merged );
00212 
00213         // fixup the tree view
00214         ui.certificationsTV->expandAll();
00215         ui.certificationsTV->header()->resizeSections( QHeaderView::ResizeToContents );
00216     }
00217     void slotSignatureListingDone( const KeyListResult & result ) {
00218         if ( result.error().isCanceled() )
00219             ;
00220         else if ( result.error() )
00221             showSignatureListingErrorDialog( result.error() );
00222         else
00223             ;
00224         keyListJob = 0;
00225         enableDisableWidgets();
00226     }
00227     void showSignatureListingErrorDialog( const Error & err ) {
00228         KMessageBox::information( q, i18nc("@info",
00229                                            "<para>An error occurred while loading the certifications: "
00230                                            "<message>%1</message></para>",
00231                                            QString::fromLocal8Bit( err.asString() ) ),
00232                                   i18nc("@title","Certifications Loading Failed") );
00233     }
00234 
00235     void slotCertificationSelectionChanged() {
00236         enableDisableWidgets();
00237     }
00238 
00239     void slotKeysMayHaveChanged() {
00240         if ( const char * const fpr = key.primaryFingerprint() )
00241             if ( !(key.keyListMode() & Extern) )
00242                 q->setKey( KeyCache::instance()->findByFingerprint( fpr ) );
00243     }
00244 
00245     void slotDumpCertificate() {
00246 
00247         if ( dumpCertificateCommand )
00248             return;
00249 
00250         if ( key.protocol() != CMS ) {
00251             ui.dumpLTW->clear();
00252             return;
00253         }
00254 
00255         ui.dumpLTW->setLines( QStringList( i18n("Please wait while generating the dump...") ) );
00256 
00257         dumpCertificateCommand = new DumpCertificateCommand( key );
00258         dumpCertificateCommand->setUseDialog( false );
00259         QPointer<Command> cmd = dumpCertificateCommand.data();
00260         startCommandImplementation( cmd, SLOT(slotDumpCertificateCommandFinished()) );
00261     }
00262 
00263     void slotDumpCertificateCommandFinished() {
00264         ui.dumpLTW->setLines( dumpCertificateCommand->output() );
00265     }
00266 
00267 private:
00268     void updateWidgetVisibility() {
00269         const bool x509 = key.protocol() == CMS;
00270         const bool pgp = key.protocol() == OpenPGP;
00271         const bool secret = key.hasSecret();
00272         const bool sigs = (key.keyListMode() & Signatures);
00273         const bool ultimateTrust = key.ownerTrust() == Key::Ultimate;
00274         const bool external = (key.keyListMode() & Extern);
00275 
00276         // Overview Tab
00277         ui.overviewActionsGB->setVisible( !external );
00278         ui.changePassphrasePB->setVisible(         secret );
00279         ui.changeTrustLevelPB->setVisible( pgp && ( !secret || !ultimateTrust ) );
00280         ui.changeExpiryDatePB->setVisible( pgp &&  secret );
00281 
00282         // Certifications Tab
00283         ui.userIDsActionsGB->setVisible( !external && pgp );
00284         ui.certificationsActionGB->setVisible( !external && pgp );
00285         ui.addUserIDPB->setVisible( secret );
00286         ui.expandAllCertificationsPB->setVisible( pgp && sigs );
00287         ui.collapseAllCertificationsPB->setVisible( pgp && sigs );
00288         ui.showCertificationsPB->setVisible( pgp && !sigs );
00289 
00290         // Technical Details Tab
00291         ui.tabWidget->setTabEnabled( ui.tabWidget->indexOf( ui.detailsTab ), pgp );
00292 
00293         // Chain tab
00294         ui.tabWidget->setTabEnabled( ui.tabWidget->indexOf( ui.chainTab ), x509 );
00295 
00296         // Dump tab
00297         ui.tabWidget->setTabEnabled( ui.tabWidget->indexOf( ui.dumpTab ), x509 );
00298 
00299         // not implemented:
00300         ui.revokeCertificatePB->hide();
00301         ui.revokeUserIDPB->hide();
00302         ui.certificationsActionGB->hide();
00303     }
00304 
00305     QModelIndexList selectedCertificationsIndexes() const {
00306         return ui.certificationsTV->selectionModel()->selectedRows();
00307     }
00308 
00309     std::vector<UserID> selectedUserIDs() const {
00310         const QModelIndexList mil = selectedCertificationsIndexes();
00311         std::vector<UserID> uids = certificationsModel.userIDs( mil, true );
00312         uids.erase( std::remove_if( uids.begin(), uids.end(), mem_fn( &UserID::isNull ) ), uids.end() );
00313         return uids;
00314     }
00315 
00316     std::vector<UserID::Signature> selectedSignatures() const {
00317         const QModelIndexList mil = selectedCertificationsIndexes();
00318         std::vector<UserID::Signature> sigs = certificationsModel.signatures( mil );
00319         sigs.erase( std::remove_if( sigs.begin(), sigs.end(), mem_fn( &UserID::Signature::isNull ) ), sigs.end() );
00320         return sigs;
00321     }
00322 
00323     void enableDisableWidgets() {
00324         // Overview Tab
00325         ui.changePassphrasePB->setEnabled( !changePassphraseCommand );
00326         ui.changeTrustLevelPB->setEnabled( !changeOwnerTrustCommand );
00327         ui.changeExpiryDatePB->setEnabled( !changeExpiryDateCommand );
00328 
00329         // Certifications Tab
00330         ui.addUserIDPB->setEnabled( !addUserIDCommand );
00331         ui.showCertificationsPB->setEnabled( !keyListJob );
00332         ui.showCertificationsPB->setText( keyListJob
00333                                           ? i18n("(please wait while certifications are being loaded)")
00334                                           : i18n("Load Certifications (may take a while)") );
00335 
00336         const std::vector<UserID> uids = selectedUserIDs();
00337         const std::vector<UserID::Signature> sigs = selectedSignatures();
00338 
00339         ui.certifyUserIDPB->setEnabled(      !uids.empty() &&  sigs.empty() && !signCertificateCommand );
00340         ui.revokeUserIDPB->setEnabled(       !uids.empty() &&  sigs.empty() );
00341         ui.revokeCertificationPB->setEnabled( uids.empty() && !sigs.empty() && own( sigs ) );
00342     }
00343 
00344     void updateLabel() {
00345         ui.overviewLB->setText( Formatting::formatOverview( key ) );
00346     }
00347 
00348     void updateChainTab() {
00349         ui.chainTW->clear();
00350 
00351         if ( key.protocol() != CMS )
00352             return;
00353 
00354         QTreeWidgetItem * last = 0;
00355         const std::vector<Key> chain = KeyCache::instance()->findIssuers( key, KeyCache::RecursiveSearch|KeyCache::IncludeSubject );
00356         if ( chain.empty() )
00357             return;
00358         if ( !chain.back().isRoot() ) {
00359             last = new QTreeWidgetItem( ui.chainTW );
00360             last->setText( 0, i18n("Issuer Certificate Not Found (%1)",
00361                                    DN( chain.back().issuerName() ).prettyDN() ) );
00362             //last->setSelectable( false );
00363             const QBrush & fg = ui.chainTW->palette().brush( QPalette::Disabled, QPalette::WindowText );
00364             last->setForeground( 0, fg );
00365         }
00366         for ( std::vector<Key>::const_reverse_iterator it = chain.rbegin(), end = chain.rend() ; it != end ; ++it ) {
00367             last = last ? new QTreeWidgetItem( last ) : new QTreeWidgetItem( ui.chainTW ) ;
00368             last->setText( 0, DN( it->userID(0).id() ).prettyDN() );
00369             //last->setSelectable( true );
00370         }
00371         ui.chainTW->expandAll();
00372     }
00373 
00374     void propagateKey() {
00375         certificationsModel.setKey( key );
00376         const QModelIndexList uidIndexes = certificationsModel.indexes( key.userIDs() );
00377         Q_FOREACH( const QModelIndex & idx, uidIndexes )
00378             ui.certificationsTV->setFirstColumnSpanned( idx.row(), idx.parent(), true );
00379 
00380         subkeysModel.setKey( key );
00381         ui.subkeyTV->header()->resizeSections( QHeaderView::ResizeToContents );
00382 
00383         updateChainTab();
00384         slotDumpCertificate();
00385     }
00386 
00387 
00388 private:
00389     Key key;
00390     UserIDListModel certificationsModel;
00391     SubkeyListModel subkeysModel;
00392 
00393     QPointer<Command> changePassphraseCommand;
00394     QPointer<Command> changeOwnerTrustCommand;
00395     QPointer<Command> changeExpiryDateCommand;
00396 
00397     QPointer<Command> addUserIDCommand;
00398     QPointer<Command> signCertificateCommand;
00399 
00400     QPointer<DumpCertificateCommand> dumpCertificateCommand;
00401 
00402     QPointer<KeyListJob> keyListJob;
00403 
00404     struct UI : public Ui_CertificateDetailsDialog {
00405         explicit UI( Dialogs::CertificateDetailsDialog * qq )
00406             : Ui_CertificateDetailsDialog()
00407         {
00408             setupUi( qq );
00409 
00410             chainTW->header()->setResizeMode( 0, QHeaderView::Stretch );
00411 
00412             dumpLTW->setFont( KGlobalSettings::fixedFont() );
00413             dumpLTW->setMinimumVisibleLines( 15 );
00414             dumpLTW->setMinimumVisibleColumns( 40 );
00415 
00416             subkeyHLine->setTitle( i18nc("@title","Subkeys") );
00417         }
00418     } ui;
00419 };
00420 
00421 CertificateDetailsDialog::CertificateDetailsDialog( QWidget * p, Qt::WindowFlags f )
00422     : QDialog( p, f ), d( new Private( this ) )
00423 {
00424 
00425 }
00426 
00427 CertificateDetailsDialog::~CertificateDetailsDialog() {}
00428 
00429 
00430 void CertificateDetailsDialog::setKey( const Key & key ) {
00431     d->key = key;
00432     d->updateWidgetVisibility();
00433     d->updateLabel();
00434     d->propagateKey();
00435     d->enableDisableWidgets();
00436 }
00437 
00438 Key CertificateDetailsDialog::key() const {
00439     return d->key;
00440 }
00441 
00442 
00443 #include "moc_certificatedetailsdialog.cpp"

kleopatra

Skip menu "kleopatra"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members

kdepim

Skip menu "kdepim"
  • akonadi
  •   clients
  •   kabc
  •   kcal
  •   kcm
  • akregator
  • console
  •   kabcclient
  •   konsolekalendar
  • kaddressbook
  • kalarm
  •   lib
  • kdgantt
  • kdgantt1
  • kjots
  • kleopatra
  • kmail
  • kmobiletools
  • knode
  • knotes
  • kontact
  • kontactinterfaces
  • korganizer
  •   korgac
  • kpilot
  • ktimetracker
  •   doc
  • libkdepim
  • libkholidays
  • libkleo
  • libkpgp
  • maildir
Generated for kdepim by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal