certmanager Library API Documentation

keyrequester.cpp

00001 /*  -*- c++ -*-
00002     keyrequester.cpp
00003 
00004     This file is part of libkleopatra, the KDE keymanagement library
00005     Copyright (c) 2004 Klarälvdalens Datakonsult AB
00006 
00007     Libkleopatra is free software; you can redistribute it and/or
00008     modify it under the terms of the GNU General Public License as
00009     published by the Free Software Foundation; either version 2 of the
00010     License, or (at your option) any later version.
00011 
00012     Libkleopatra 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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     Based on kpgpui.cpp
00034     Copyright (C) 2001,2002 the KPGP authors
00035     See file libkdenetwork/AUTHORS.kpgp for details
00036 
00037     This file is part of KPGP, the KDE PGP/GnuPG support library.
00038 
00039     KPGP is free software; you can redistribute it and/or modify
00040     it under the terms of the GNU General Public License as published by
00041     the Free Software Foundation; either version 2 of the License, or
00042     (at your option) any later version.
00043 
00044     You should have received a copy of the GNU General Public License
00045     along with this program; if not, write to the Free Software Foundation,
00046     Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
00047  */
00048 
00049 #ifdef HAVE_CONFIG_H
00050 #include <config.h>
00051 #endif
00052 
00053 #include "keyrequester.h"
00054 
00055 #include "keyselectiondialog.h"
00056 
00057 #include <kleo/keylistjob.h>
00058 #include <kleo/dn.h>
00059 #include <kleo/cryptobackendfactory.h>
00060 
00061 // gpgme++
00062 #include <gpgmepp/key.h>
00063 #include <gpgmepp/keylistresult.h>
00064 
00065 // KDE
00066 #include <klocale.h>
00067 #include <kiconloader.h>
00068 #include <kdialog.h>
00069 #include <kdebug.h>
00070 #include <kmessagebox.h>
00071 
00072 // Qt
00073 #include <qpushbutton.h>
00074 #include <qlayout.h>
00075 #include <qtooltip.h>
00076 #include <qstring.h>
00077 #include <qstringlist.h>
00078 #include <qlabel.h>
00079 #include <qregexp.h>
00080 
00081 #include <assert.h>
00082 
00083 Kleo::KeyRequester::KeyRequester( unsigned int allowedKeys, bool multipleKeys,
00084                   QWidget * parent, const char * name )
00085   : QWidget( parent, name ),
00086     mOpenPGPBackend( 0 ),
00087     mSMIMEBackend( 0 ),
00088     mMulti( multipleKeys ),
00089     mKeyUsage( allowedKeys ),
00090     mJobs( 0 ),
00091     d( 0 )
00092 {
00093   init();
00094 }
00095 
00096 Kleo::KeyRequester::KeyRequester( QWidget * parent, const char * name )
00097   : QWidget( parent, name ),
00098     mOpenPGPBackend( 0 ),
00099     mSMIMEBackend( 0 ),
00100     mMulti( false ),
00101     mKeyUsage( 0 ),
00102     mJobs( 0 ),
00103     d( 0 )
00104 {
00105   init();
00106 }
00107 
00108 void Kleo::KeyRequester::init()
00109 {
00110   QHBoxLayout * hlay = new QHBoxLayout( this, 0, KDialog::spacingHint() );
00111 
00112   // the label where the key id is to be displayed:
00113   mLabel = new QLabel( this );
00114   mLabel->setFrameStyle( QFrame::Panel | QFrame::Sunken );
00115 
00116   // the button to unset any key:
00117   mEraseButton = new QPushButton( this );
00118   mEraseButton->setAutoDefault( false );
00119   mEraseButton->setSizePolicy( QSizePolicy( QSizePolicy::Minimum,
00120                         QSizePolicy::Minimum ) );
00121   mEraseButton->setPixmap( SmallIcon( "clear_left" ) );
00122   QToolTip::add( mEraseButton, i18n("Clear") );
00123 
00124   // the button to call the KeySelectionDialog:
00125   mDialogButton = new QPushButton( i18n("Change..."), this );
00126   mDialogButton->setAutoDefault( false );
00127 
00128   hlay->addWidget( mLabel, 1 );
00129   hlay->addWidget( mEraseButton );
00130   hlay->addWidget( mDialogButton );
00131 
00132   connect( mEraseButton,  SIGNAL(clicked()), SLOT(slotEraseButtonClicked()) );
00133   connect( mDialogButton, SIGNAL(clicked()), SLOT(slotDialogButtonClicked()) );
00134 
00135   setSizePolicy( QSizePolicy( QSizePolicy::MinimumExpanding,
00136                   QSizePolicy::Fixed ) );
00137 
00138   setAllowedKeys( mKeyUsage );
00139 }
00140 
00141 Kleo::KeyRequester::~KeyRequester() {
00142 
00143 }
00144 
00145 const std::vector<GpgME::Key> & Kleo::KeyRequester::keys() const {
00146   return mKeys;
00147 }
00148 
00149 const GpgME::Key & Kleo::KeyRequester::key() const {
00150   if ( mKeys.empty() )
00151     return GpgME::Key::null;
00152   else
00153     return mKeys.front();
00154 }
00155 
00156 void Kleo::KeyRequester::setKeys( const std::vector<GpgME::Key> & keys ) {
00157   mKeys.clear();
00158   for ( std::vector<GpgME::Key>::const_iterator it = keys.begin() ; it != keys.end() ; ++it )
00159     if ( !it->isNull() )
00160       mKeys.push_back( *it );
00161   updateKeys();
00162 }
00163 
00164 void Kleo::KeyRequester::setKey( const GpgME::Key & key ) {
00165   mKeys.clear();
00166   if ( !key.isNull() )
00167     mKeys.push_back( key );
00168   updateKeys();
00169 }
00170 
00171 QString Kleo::KeyRequester::fingerprint() const {
00172   if ( mKeys.empty() )
00173     return QString::null;
00174   else
00175     return mKeys.front().primaryFingerprint();
00176 }
00177 
00178 QStringList Kleo::KeyRequester::fingerprints() const {
00179   QStringList result;
00180   for ( std::vector<GpgME::Key>::const_iterator it = mKeys.begin() ; it != mKeys.end() ; ++it )
00181     if ( !it->isNull() )
00182       if ( const char * fpr = it->primaryFingerprint() )
00183     result.push_back( fpr );
00184   return result;
00185 }
00186 
00187 void Kleo::KeyRequester::setFingerprint( const QString & fingerprint ) {
00188   startKeyListJob( fingerprint );
00189 }
00190 
00191 void Kleo::KeyRequester::setFingerprints( const QStringList & fingerprints ) {
00192   startKeyListJob( fingerprints );
00193 }
00194 
00195 void Kleo::KeyRequester::updateKeys() {
00196   if ( mKeys.empty() ) {
00197     mLabel->clear();
00198     return;
00199   }
00200   if ( mKeys.size() > 1 )
00201     setMultipleKeysEnabled( true );
00202 
00203   QStringList labelTexts;
00204   QString toolTipText;
00205   for ( std::vector<GpgME::Key>::const_iterator it = mKeys.begin() ; it != mKeys.end() ; ++it ) {
00206     if ( it->isNull() )
00207       continue;
00208     const QString fpr = it->primaryFingerprint();
00209     labelTexts.push_back( fpr.right(8) );
00210     toolTipText += fpr.right(8) + ": ";
00211     if ( const char * uid = it->userID(0).id() )
00212       if ( it->protocol() == GpgME::Context::OpenPGP )
00213     toolTipText += QString::fromUtf8( uid );
00214       else
00215     toolTipText += Kleo::DN( uid ).prettyDN();
00216     else
00217       toolTipText += i18n("<unknown>");
00218     toolTipText += '\n';
00219   }
00220 
00221   mLabel->setText( labelTexts.join(", ") );
00222   QToolTip::remove( mLabel );
00223   QToolTip::add( mLabel, toolTipText );
00224 }
00225 
00226 #ifndef __KLEO_UI_SHOW_KEY_LIST_ERROR_H__
00227 #define __KLEO_UI_SHOW_KEY_LIST_ERROR_H__
00228 static void showKeyListError( QWidget * parent, const GpgME::Error & err ) {
00229   assert( err );
00230   const QString msg = i18n( "<qt><p>An error occurred while fetching "
00231                 "the keys from the backend:</p>"
00232                 "<p><b>%1</b></p></qt>" )
00233     .arg( QString::fromLocal8Bit( err.asString() ) );
00234 
00235   KMessageBox::error( parent, msg, i18n( "Key Listing Failed" ) );
00236 }
00237 #endif // __KLEO_UI_SHOW_KEY_LIST_ERROR_H__
00238 
00239 void Kleo::KeyRequester::startKeyListJob( const QStringList & fingerprints ) {
00240   if ( !mSMIMEBackend && !mOpenPGPBackend )
00241     return;
00242 
00243   mTmpKeys.clear();
00244   mJobs = 0;
00245 
00246   unsigned int count = 0;
00247   for ( QStringList::const_iterator it = fingerprints.begin() ; it != fingerprints.end() ; ++it )
00248     if ( !(*it).stripWhiteSpace().isEmpty() )
00249       ++count;
00250 
00251   if ( !count ) {
00252     // don't fall into the trap that an empty pattern means
00253     // "return all keys" :)
00254     setKey( GpgME::Key::null );
00255     return;
00256   }
00257 
00258   if ( mOpenPGPBackend ) {
00259     KeyListJob * job = mOpenPGPBackend->keyListJob( false ); // local, no sigs
00260     if ( !job ) {
00261       KMessageBox::error( this,
00262               i18n("The OpenPGP backend does not support listing keys. "
00263                    "Check your installation."),
00264               i18n("Key Listing Failed") );
00265     } else {
00266       connect( job, SIGNAL(result(const GpgME::KeyListResult&)),
00267            SLOT(slotKeyListResult(const GpgME::KeyListResult&)) );
00268       connect( job, SIGNAL(nextKey(const GpgME::Key&)),
00269            SLOT(slotNextKey(const GpgME::Key&)) );
00270 
00271       const GpgME::Error err = job->start( fingerprints,
00272         mKeyUsage & Kleo::KeySelectionDialog::SecretKeys &&
00273         !( mKeyUsage & Kleo::KeySelectionDialog::PublicKeys ) );
00274 
00275       if ( err )
00276     showKeyListError( this, err );
00277       else
00278     ++mJobs;
00279     }
00280   }
00281 
00282   if ( mSMIMEBackend ) {
00283     KeyListJob * job = mSMIMEBackend->keyListJob( false ); // local, no sigs
00284     if ( !job ) {
00285       KMessageBox::error( this,
00286               i18n("The S/MIME backend does not support listing keys. "
00287                    "Check your installation."),
00288               i18n("Key Listing Failed") );
00289     } else {
00290       connect( job, SIGNAL(result(const GpgME::KeyListResult&)),
00291            SLOT(slotKeyListResult(const GpgME::KeyListResult&)) );
00292       connect( job, SIGNAL(nextKey(const GpgME::Key&)),
00293            SLOT(slotNextKey(const GpgME::Key&)) );
00294 
00295       const GpgME::Error err = job->start( fingerprints,
00296         mKeyUsage & Kleo::KeySelectionDialog::SecretKeys &&
00297         !( mKeyUsage & Kleo::KeySelectionDialog::PublicKeys ) );
00298 
00299       if ( err )
00300     showKeyListError( this, err );
00301       else
00302     ++mJobs;
00303     }
00304   }
00305 
00306   if ( mJobs > 0 ) {
00307     mEraseButton->setEnabled( false );
00308     mDialogButton->setEnabled( false );
00309   }
00310 }
00311 
00312 void Kleo::KeyRequester::slotNextKey( const GpgME::Key & key ) {
00313   if ( !key.isNull() )
00314     mTmpKeys.push_back( key );
00315 }
00316 
00317 void Kleo::KeyRequester::slotKeyListResult( const GpgME::KeyListResult & res ) {
00318   if ( res.error() )
00319     showKeyListError( this, res.error() );
00320 
00321   if ( --mJobs <= 0 ) {
00322     mEraseButton->setEnabled( true );
00323     mDialogButton->setEnabled( true );
00324 
00325     setKeys( mTmpKeys );
00326     mTmpKeys.clear();
00327   }
00328 }
00329 
00330 
00331 void Kleo::KeyRequester::slotDialogButtonClicked() {
00332   KeySelectionDialog * dlg = mKeys.empty()
00333     ? new KeySelectionDialog( mDialogCaption, mDialogMessage, mInitialQuery, mKeyUsage, mMulti, false, this )
00334     : new KeySelectionDialog( mDialogCaption, mDialogCaption, mKeys, mKeyUsage, mMulti, false, this ) ;
00335 
00336   if ( dlg->exec() == QDialog::Accepted ) {
00337     if ( mMulti )
00338       setKeys( dlg->selectedKeys() );
00339     else
00340       setKey( dlg->selectedKey() );
00341     emit changed();
00342   }
00343 
00344   delete dlg;
00345 }
00346 
00347 void Kleo::KeyRequester::slotEraseButtonClicked() {
00348   if ( !mKeys.empty() )
00349     emit changed();
00350   mKeys.clear();
00351   updateKeys();
00352 }
00353 
00354 void Kleo::KeyRequester::setDialogCaption( const QString & caption ) {
00355   mDialogCaption = caption;
00356 }
00357 
00358 void Kleo::KeyRequester::setDialogMessage( const QString & msg ) {
00359   mDialogMessage = msg;
00360 }
00361 
00362 bool Kleo::KeyRequester::isMultipleKeysEnabled() const {
00363   return mMulti;
00364 }
00365 
00366 void Kleo::KeyRequester::setMultipleKeysEnabled( bool multi ) {
00367   if ( multi == mMulti ) return;
00368 
00369   if ( !multi && !mKeys.empty() )
00370     mKeys.erase( mKeys.begin() + 1, mKeys.end() );
00371 
00372   mMulti = multi;
00373   updateKeys();
00374 }
00375 
00376 unsigned int Kleo::KeyRequester::allowedKeys() const {
00377   return mKeyUsage;
00378 }
00379 
00380 void Kleo::KeyRequester::setAllowedKeys( unsigned int keyUsage ) {
00381   mKeyUsage = keyUsage;
00382   mOpenPGPBackend = 0;
00383   mSMIMEBackend = 0;
00384 
00385   if ( mKeyUsage & KeySelectionDialog::OpenPGPKeys )
00386     mOpenPGPBackend = Kleo::CryptoBackendFactory::instance()->openpgp();
00387   if ( mKeyUsage & KeySelectionDialog::SMIMEKeys )
00388     mSMIMEBackend = Kleo::CryptoBackendFactory::instance()->smime();
00389 
00390   if ( mOpenPGPBackend && !mSMIMEBackend ) {
00391     mDialogCaption = i18n("OpenPGP Key Selection");
00392     mDialogMessage = i18n("Please select an OpenPGP key to use.");
00393   } else if ( !mOpenPGPBackend && mSMIMEBackend ) {
00394     mDialogCaption = i18n("S/MIME Key Selection");
00395     mDialogMessage = i18n("Please select an S/MIME key to use.");
00396   } else {
00397     mDialogCaption = i18n("Key Selection");
00398     mDialogMessage = i18n("Please select an (OpenPGP or S/MIME) key to use.");
00399   }
00400 }
00401 
00402 QPushButton * Kleo::KeyRequester::dialogButton() {
00403   return mDialogButton;
00404 }
00405 
00406 QPushButton * Kleo::KeyRequester::eraseButton() {
00407   return mEraseButton;
00408 }
00409 
00410 static inline unsigned int foo( bool openpgp, bool smime, bool trusted, bool valid ) {
00411   unsigned int result = 0;
00412   if ( openpgp )
00413     result |= Kleo::KeySelectionDialog::OpenPGPKeys;
00414   if ( smime )
00415     result |= Kleo::KeySelectionDialog::SMIMEKeys;
00416   if ( trusted )
00417     result |= Kleo::KeySelectionDialog::TrustedKeys;
00418   if ( valid )
00419     result |= Kleo::KeySelectionDialog::ValidKeys;
00420   return result;
00421 }
00422 
00423 static inline unsigned int encryptionKeyUsage( bool openpgp, bool smime, bool trusted, bool valid ) {
00424   return foo( openpgp, smime, trusted, valid ) | Kleo::KeySelectionDialog::EncryptionKeys | Kleo::KeySelectionDialog::PublicKeys;
00425 }
00426 
00427 static inline unsigned int signingKeyUsage( bool openpgp, bool smime, bool trusted, bool valid ) {
00428   return foo( openpgp, smime, trusted, valid ) | Kleo::KeySelectionDialog::SigningKeys | Kleo::KeySelectionDialog::SecretKeys;
00429 }
00430 
00431 Kleo::EncryptionKeyRequester::EncryptionKeyRequester( bool multi, unsigned int proto,
00432                               QWidget * parent, const char * name,
00433                               bool onlyTrusted, bool onlyValid )
00434   : KeyRequester( encryptionKeyUsage( proto & OpenPGP, proto & SMIME, onlyTrusted, onlyValid ), multi,
00435           parent, name )
00436 {
00437 }
00438 
00439 Kleo::EncryptionKeyRequester::EncryptionKeyRequester( QWidget * parent, const char * name )
00440   : KeyRequester( 0, false, parent, name )
00441 {
00442 }
00443 
00444 Kleo::EncryptionKeyRequester::~EncryptionKeyRequester() {}
00445 
00446 
00447 void Kleo::EncryptionKeyRequester::setAllowedKeys( unsigned int proto, bool onlyTrusted, bool onlyValid )
00448 {
00449   KeyRequester::setAllowedKeys( encryptionKeyUsage( proto & OpenPGP, proto & SMIME, onlyTrusted, onlyValid ) );
00450 }
00451 
00452 Kleo::SigningKeyRequester::SigningKeyRequester( bool multi, unsigned int proto,
00453                         QWidget * parent, const char * name,
00454                         bool onlyTrusted, bool onlyValid )
00455   : KeyRequester( signingKeyUsage( proto & OpenPGP, proto & SMIME, onlyTrusted, onlyValid ), multi,
00456           parent, name )
00457 {
00458 }
00459 
00460 Kleo::SigningKeyRequester::SigningKeyRequester( QWidget * parent, const char * name )
00461   : KeyRequester( 0, false, parent, name )
00462 {
00463 }
00464 
00465 Kleo::SigningKeyRequester::~SigningKeyRequester() {}
00466 
00467 void Kleo::SigningKeyRequester::setAllowedKeys( unsigned int proto, bool onlyTrusted, bool onlyValid )
00468 {
00469   KeyRequester::setAllowedKeys( signingKeyUsage( proto & OpenPGP, proto & SMIME, onlyTrusted, onlyValid ) );
00470 }
00471 
00472 void Kleo::KeyRequester::virtual_hook( int, void* ) {}
00473 void Kleo::EncryptionKeyRequester::virtual_hook( int id, void * data ) {
00474   KeyRequester::virtual_hook( id, data );
00475 }
00476 void Kleo::SigningKeyRequester::virtual_hook( int id, void * data ) {
00477   KeyRequester::virtual_hook( id, data );
00478 }
00479 
00480 #include "keyrequester.moc"
KDE Logo
This file is part of the documentation for certmanager Library Version 3.3.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Aug 23 18:19:06 2007 by doxygen 1.4.2 written by Dimitri van Heesch, © 1997-2003