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
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
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
00062 #include <gpgmepp/key.h>
00063 #include <gpgmepp/keylistresult.h>
00064
00065
00066 #include <klocale.h>
00067 #include <kiconloader.h>
00068 #include <kdialog.h>
00069 #include <kdebug.h>
00070 #include <kmessagebox.h>
00071 #include <kpushbutton.h>
00072
00073
00074 #include <qapplication.h>
00075 #include <qlayout.h>
00076 #include <qtooltip.h>
00077 #include <qstring.h>
00078 #include <qstringlist.h>
00079 #include <qlabel.h>
00080 #include <qregexp.h>
00081
00082 #include <assert.h>
00083
00084 Kleo::KeyRequester::KeyRequester( unsigned int allowedKeys, bool multipleKeys,
00085 QWidget * parent, const char * name )
00086 : QWidget( parent, name ),
00087 mOpenPGPBackend( 0 ),
00088 mSMIMEBackend( 0 ),
00089 mMulti( multipleKeys ),
00090 mKeyUsage( allowedKeys ),
00091 mJobs( 0 ),
00092 d( 0 )
00093 {
00094 init();
00095 }
00096
00097 Kleo::KeyRequester::KeyRequester( QWidget * parent, const char * name )
00098 : QWidget( parent, name ),
00099 mOpenPGPBackend( 0 ),
00100 mSMIMEBackend( 0 ),
00101 mMulti( false ),
00102 mKeyUsage( 0 ),
00103 mJobs( 0 ),
00104 d( 0 )
00105 {
00106 init();
00107 }
00108
00109 void Kleo::KeyRequester::init()
00110 {
00111 QHBoxLayout * hlay = new QHBoxLayout( this, 0, KDialog::spacingHint() );
00112
00113
00114 mLabel = new QLabel( this );
00115 mLabel->setFrameStyle( QFrame::Panel | QFrame::Sunken );
00116
00117
00118 mEraseButton = new KPushButton( this );
00119 mEraseButton->setAutoDefault( false );
00120 mEraseButton->setSizePolicy( QSizePolicy( QSizePolicy::Minimum,
00121 QSizePolicy::Minimum ) );
00122 mEraseButton->setIconSet( SmallIconSet( QApplication::reverseLayout() ? "locationbar_erase" : "clear_left" ) );
00123 QToolTip::add( mEraseButton, i18n("Clear") );
00124
00125
00126 mDialogButton = new QPushButton( i18n("Change..."), this );
00127 mDialogButton->setAutoDefault( false );
00128
00129 hlay->addWidget( mLabel, 1 );
00130 hlay->addWidget( mEraseButton );
00131 hlay->addWidget( mDialogButton );
00132
00133 connect( mEraseButton, SIGNAL(clicked()), SLOT(slotEraseButtonClicked()) );
00134 connect( mDialogButton, SIGNAL(clicked()), SLOT(slotDialogButtonClicked()) );
00135
00136 setSizePolicy( QSizePolicy( QSizePolicy::MinimumExpanding,
00137 QSizePolicy::Fixed ) );
00138
00139 setAllowedKeys( mKeyUsage );
00140 }
00141
00142 Kleo::KeyRequester::~KeyRequester() {
00143
00144 }
00145
00146 const std::vector<GpgME::Key> & Kleo::KeyRequester::keys() const {
00147 return mKeys;
00148 }
00149
00150 const GpgME::Key & Kleo::KeyRequester::key() const {
00151 if ( mKeys.empty() )
00152 return GpgME::Key::null;
00153 else
00154 return mKeys.front();
00155 }
00156
00157 void Kleo::KeyRequester::setKeys( const std::vector<GpgME::Key> & keys ) {
00158 mKeys.clear();
00159 for ( std::vector<GpgME::Key>::const_iterator it = keys.begin() ; it != keys.end() ; ++it )
00160 if ( !it->isNull() )
00161 mKeys.push_back( *it );
00162 updateKeys();
00163 }
00164
00165 void Kleo::KeyRequester::setKey( const GpgME::Key & key ) {
00166 mKeys.clear();
00167 if ( !key.isNull() )
00168 mKeys.push_back( key );
00169 updateKeys();
00170 }
00171
00172 QString Kleo::KeyRequester::fingerprint() const {
00173 if ( mKeys.empty() )
00174 return QString::null;
00175 else
00176 return mKeys.front().primaryFingerprint();
00177 }
00178
00179 QStringList Kleo::KeyRequester::fingerprints() const {
00180 QStringList result;
00181 for ( std::vector<GpgME::Key>::const_iterator it = mKeys.begin() ; it != mKeys.end() ; ++it )
00182 if ( !it->isNull() )
00183 if ( const char * fpr = it->primaryFingerprint() )
00184 result.push_back( fpr );
00185 return result;
00186 }
00187
00188 void Kleo::KeyRequester::setFingerprint( const QString & fingerprint ) {
00189 startKeyListJob( fingerprint );
00190 }
00191
00192 void Kleo::KeyRequester::setFingerprints( const QStringList & fingerprints ) {
00193 startKeyListJob( fingerprints );
00194 }
00195
00196 void Kleo::KeyRequester::updateKeys() {
00197 if ( mKeys.empty() ) {
00198 mLabel->clear();
00199 return;
00200 }
00201 if ( mKeys.size() > 1 )
00202 setMultipleKeysEnabled( true );
00203
00204 QStringList labelTexts;
00205 QString toolTipText;
00206 for ( std::vector<GpgME::Key>::const_iterator it = mKeys.begin() ; it != mKeys.end() ; ++it ) {
00207 if ( it->isNull() )
00208 continue;
00209 const QString fpr = it->primaryFingerprint();
00210 labelTexts.push_back( fpr.right(8) );
00211 toolTipText += fpr.right(8) + ": ";
00212 if ( const char * uid = it->userID(0).id() )
00213 if ( it->protocol() == GpgME::Context::OpenPGP )
00214 toolTipText += QString::fromUtf8( uid );
00215 else
00216 toolTipText += Kleo::DN( uid ).prettyDN();
00217 else
00218 toolTipText += i18n("<unknown>");
00219 toolTipText += '\n';
00220 }
00221
00222 mLabel->setText( labelTexts.join(", ") );
00223 QToolTip::remove( mLabel );
00224 QToolTip::add( mLabel, toolTipText );
00225 }
00226
00227 #ifndef __KLEO_UI_SHOW_KEY_LIST_ERROR_H__
00228 #define __KLEO_UI_SHOW_KEY_LIST_ERROR_H__
00229 static void showKeyListError( QWidget * parent, const GpgME::Error & err ) {
00230 assert( err );
00231 const QString msg = i18n( "<qt><p>An error occurred while fetching "
00232 "the keys from the backend:</p>"
00233 "<p><b>%1</b></p></qt>" )
00234 .arg( QString::fromLocal8Bit( err.asString() ) );
00235
00236 KMessageBox::error( parent, msg, i18n( "Key Listing Failed" ) );
00237 }
00238 #endif // __KLEO_UI_SHOW_KEY_LIST_ERROR_H__
00239
00240 void Kleo::KeyRequester::startKeyListJob( const QStringList & fingerprints ) {
00241 if ( !mSMIMEBackend && !mOpenPGPBackend )
00242 return;
00243
00244 mTmpKeys.clear();
00245 mJobs = 0;
00246
00247 unsigned int count = 0;
00248 for ( QStringList::const_iterator it = fingerprints.begin() ; it != fingerprints.end() ; ++it )
00249 if ( !(*it).stripWhiteSpace().isEmpty() )
00250 ++count;
00251
00252 if ( !count ) {
00253
00254
00255 setKey( GpgME::Key::null );
00256 return;
00257 }
00258
00259 if ( mOpenPGPBackend ) {
00260 KeyListJob * job = mOpenPGPBackend->keyListJob( false );
00261 if ( !job ) {
00262 KMessageBox::error( this,
00263 i18n("The OpenPGP backend does not support listing keys. "
00264 "Check your installation."),
00265 i18n("Key Listing Failed") );
00266 } else {
00267 connect( job, SIGNAL(result(const GpgME::KeyListResult&)),
00268 SLOT(slotKeyListResult(const GpgME::KeyListResult&)) );
00269 connect( job, SIGNAL(nextKey(const GpgME::Key&)),
00270 SLOT(slotNextKey(const GpgME::Key&)) );
00271
00272 const GpgME::Error err = job->start( fingerprints,
00273 mKeyUsage & Kleo::KeySelectionDialog::SecretKeys &&
00274 !( mKeyUsage & Kleo::KeySelectionDialog::PublicKeys ) );
00275
00276 if ( err )
00277 showKeyListError( this, err );
00278 else
00279 ++mJobs;
00280 }
00281 }
00282
00283 if ( mSMIMEBackend ) {
00284 KeyListJob * job = mSMIMEBackend->keyListJob( false );
00285 if ( !job ) {
00286 KMessageBox::error( this,
00287 i18n("The S/MIME backend does not support listing keys. "
00288 "Check your installation."),
00289 i18n("Key Listing Failed") );
00290 } else {
00291 connect( job, SIGNAL(result(const GpgME::KeyListResult&)),
00292 SLOT(slotKeyListResult(const GpgME::KeyListResult&)) );
00293 connect( job, SIGNAL(nextKey(const GpgME::Key&)),
00294 SLOT(slotNextKey(const GpgME::Key&)) );
00295
00296 const GpgME::Error err = job->start( fingerprints,
00297 mKeyUsage & Kleo::KeySelectionDialog::SecretKeys &&
00298 !( mKeyUsage & Kleo::KeySelectionDialog::PublicKeys ) );
00299
00300 if ( err )
00301 showKeyListError( this, err );
00302 else
00303 ++mJobs;
00304 }
00305 }
00306
00307 if ( mJobs > 0 ) {
00308 mEraseButton->setEnabled( false );
00309 mDialogButton->setEnabled( false );
00310 }
00311 }
00312
00313 void Kleo::KeyRequester::slotNextKey( const GpgME::Key & key ) {
00314 if ( !key.isNull() )
00315 mTmpKeys.push_back( key );
00316 }
00317
00318 void Kleo::KeyRequester::slotKeyListResult( const GpgME::KeyListResult & res ) {
00319 if ( res.error() )
00320 showKeyListError( this, res.error() );
00321
00322 if ( --mJobs <= 0 ) {
00323 mEraseButton->setEnabled( true );
00324 mDialogButton->setEnabled( true );
00325
00326 setKeys( mTmpKeys );
00327 mTmpKeys.clear();
00328 }
00329 }
00330
00331
00332 void Kleo::KeyRequester::slotDialogButtonClicked() {
00333 KeySelectionDialog * dlg = mKeys.empty()
00334 ? new KeySelectionDialog( mDialogCaption, mDialogMessage, mInitialQuery, mKeyUsage, mMulti, false, this )
00335 : new KeySelectionDialog( mDialogCaption, mDialogCaption, mKeys, mKeyUsage, mMulti, false, this ) ;
00336
00337 if ( dlg->exec() == QDialog::Accepted ) {
00338 if ( mMulti )
00339 setKeys( dlg->selectedKeys() );
00340 else
00341 setKey( dlg->selectedKey() );
00342 emit changed();
00343 }
00344
00345 delete dlg;
00346 }
00347
00348 void Kleo::KeyRequester::slotEraseButtonClicked() {
00349 if ( !mKeys.empty() )
00350 emit changed();
00351 mKeys.clear();
00352 updateKeys();
00353 }
00354
00355 void Kleo::KeyRequester::setDialogCaption( const QString & caption ) {
00356 mDialogCaption = caption;
00357 }
00358
00359 void Kleo::KeyRequester::setDialogMessage( const QString & msg ) {
00360 mDialogMessage = msg;
00361 }
00362
00363 bool Kleo::KeyRequester::isMultipleKeysEnabled() const {
00364 return mMulti;
00365 }
00366
00367 void Kleo::KeyRequester::setMultipleKeysEnabled( bool multi ) {
00368 if ( multi == mMulti ) return;
00369
00370 if ( !multi && !mKeys.empty() )
00371 mKeys.erase( mKeys.begin() + 1, mKeys.end() );
00372
00373 mMulti = multi;
00374 updateKeys();
00375 }
00376
00377 unsigned int Kleo::KeyRequester::allowedKeys() const {
00378 return mKeyUsage;
00379 }
00380
00381 void Kleo::KeyRequester::setAllowedKeys( unsigned int keyUsage ) {
00382 mKeyUsage = keyUsage;
00383 mOpenPGPBackend = 0;
00384 mSMIMEBackend = 0;
00385
00386 if ( mKeyUsage & KeySelectionDialog::OpenPGPKeys )
00387 mOpenPGPBackend = Kleo::CryptoBackendFactory::instance()->openpgp();
00388 if ( mKeyUsage & KeySelectionDialog::SMIMEKeys )
00389 mSMIMEBackend = Kleo::CryptoBackendFactory::instance()->smime();
00390
00391 if ( mOpenPGPBackend && !mSMIMEBackend ) {
00392 mDialogCaption = i18n("OpenPGP Key Selection");
00393 mDialogMessage = i18n("Please select an OpenPGP key to use.");
00394 } else if ( !mOpenPGPBackend && mSMIMEBackend ) {
00395 mDialogCaption = i18n("S/MIME Key Selection");
00396 mDialogMessage = i18n("Please select an S/MIME key to use.");
00397 } else {
00398 mDialogCaption = i18n("Key Selection");
00399 mDialogMessage = i18n("Please select an (OpenPGP or S/MIME) key to use.");
00400 }
00401 }
00402
00403 QPushButton * Kleo::KeyRequester::dialogButton() {
00404 return mDialogButton;
00405 }
00406
00407 QPushButton * Kleo::KeyRequester::eraseButton() {
00408 return mEraseButton;
00409 }
00410
00411 static inline unsigned int foo( bool openpgp, bool smime, bool trusted, bool valid ) {
00412 unsigned int result = 0;
00413 if ( openpgp )
00414 result |= Kleo::KeySelectionDialog::OpenPGPKeys;
00415 if ( smime )
00416 result |= Kleo::KeySelectionDialog::SMIMEKeys;
00417 if ( trusted )
00418 result |= Kleo::KeySelectionDialog::TrustedKeys;
00419 if ( valid )
00420 result |= Kleo::KeySelectionDialog::ValidKeys;
00421 return result;
00422 }
00423
00424 static inline unsigned int encryptionKeyUsage( bool openpgp, bool smime, bool trusted, bool valid ) {
00425 return foo( openpgp, smime, trusted, valid ) | Kleo::KeySelectionDialog::EncryptionKeys | Kleo::KeySelectionDialog::PublicKeys;
00426 }
00427
00428 static inline unsigned int signingKeyUsage( bool openpgp, bool smime, bool trusted, bool valid ) {
00429 return foo( openpgp, smime, trusted, valid ) | Kleo::KeySelectionDialog::SigningKeys | Kleo::KeySelectionDialog::SecretKeys;
00430 }
00431
00432 Kleo::EncryptionKeyRequester::EncryptionKeyRequester( bool multi, unsigned int proto,
00433 QWidget * parent, const char * name,
00434 bool onlyTrusted, bool onlyValid )
00435 : KeyRequester( encryptionKeyUsage( proto & OpenPGP, proto & SMIME, onlyTrusted, onlyValid ), multi,
00436 parent, name )
00437 {
00438 }
00439
00440 Kleo::EncryptionKeyRequester::EncryptionKeyRequester( QWidget * parent, const char * name )
00441 : KeyRequester( 0, false, parent, name )
00442 {
00443 }
00444
00445 Kleo::EncryptionKeyRequester::~EncryptionKeyRequester() {}
00446
00447
00448 void Kleo::EncryptionKeyRequester::setAllowedKeys( unsigned int proto, bool onlyTrusted, bool onlyValid )
00449 {
00450 KeyRequester::setAllowedKeys( encryptionKeyUsage( proto & OpenPGP, proto & SMIME, onlyTrusted, onlyValid ) );
00451 }
00452
00453 Kleo::SigningKeyRequester::SigningKeyRequester( bool multi, unsigned int proto,
00454 QWidget * parent, const char * name,
00455 bool onlyTrusted, bool onlyValid )
00456 : KeyRequester( signingKeyUsage( proto & OpenPGP, proto & SMIME, onlyTrusted, onlyValid ), multi,
00457 parent, name )
00458 {
00459 }
00460
00461 Kleo::SigningKeyRequester::SigningKeyRequester( QWidget * parent, const char * name )
00462 : KeyRequester( 0, false, parent, name )
00463 {
00464 }
00465
00466 Kleo::SigningKeyRequester::~SigningKeyRequester() {}
00467
00468 void Kleo::SigningKeyRequester::setAllowedKeys( unsigned int proto, bool onlyTrusted, bool onlyValid )
00469 {
00470 KeyRequester::setAllowedKeys( signingKeyUsage( proto & OpenPGP, proto & SMIME, onlyTrusted, onlyValid ) );
00471 }
00472
00473 void Kleo::KeyRequester::virtual_hook( int, void* ) {}
00474 void Kleo::EncryptionKeyRequester::virtual_hook( int id, void * data ) {
00475 KeyRequester::virtual_hook( id, data );
00476 }
00477 void Kleo::SigningKeyRequester::virtual_hook( int id, void * data ) {
00478 KeyRequester::virtual_hook( id, data );
00479 }
00480
00481 #include "keyrequester.moc"