00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "kpgpui.h"
00020 #include "kpgp.h"
00021 #include "kpgpkey.h"
00022
00023 #include <QLabel>
00024 #include <QApplication>
00025 #include <QTextCodec>
00026 #include <QDateTime>
00027 #include <QPixmap>
00028 #include <QLayout>
00029 #include <QTimer>
00030 #include <QMenu>
00031 #include <QRegExp>
00032 #include <QFrame>
00033 #include <QByteArray>
00034 #include <QVBoxLayout>
00035 #include <QHBoxLayout>
00036 #include <QProgressBar>
00037 #include <QButtonGroup>
00038 #include <q3multilineedit.h>
00039 #include <QGroupBox>
00040
00041 #include <k3listview.h>
00042 #include <kvbox.h>
00043 #include <kconfiggroup.h>
00044 #include <klocale.h>
00045 #include <kpassworddialog.h>
00046 #include <kcharsets.h>
00047 #include <kseparator.h>
00048 #include <kiconloader.h>
00049 #include <kconfigbase.h>
00050 #include <kconfig.h>
00051 #include <kprogressdialog.h>
00052 #include <kwindowsystem.h>
00053 #include <kpushbutton.h>
00054 #include <kglobalsettings.h>
00055 #include <klineedit.h>
00056
00057 #include <assert.h>
00058 #include <string.h>
00059
00060 const int Kpgp::KeySelectionDialog::sCheckSelectionDelay = 250;
00061
00062 namespace Kpgp {
00063
00064 PassphraseDialog::PassphraseDialog( QWidget *parent,
00065 const QString &caption,
00066 const QString &keyID )
00067 :KPasswordDialog( parent )
00068 {
00069 setCaption( caption );
00070 setButtons( Ok|Cancel );
00071
00072 setPixmap( BarIcon("dialog-password") );
00073
00074 if (keyID.isNull())
00075 setPrompt(i18n("Please enter your OpenPGP passphrase:"));
00076 else
00077 setPrompt(i18n("Please enter the OpenPGP passphrase for\n\"%1\":", keyID) );
00078 }
00079
00080
00081 PassphraseDialog::~PassphraseDialog()
00082 {
00083 }
00084
00085 QString PassphraseDialog::passphrase()
00086 {
00087 return password();
00088 }
00089
00090
00091
00092
00093
00094 Config::Config( QWidget *parent, bool encrypt )
00095 : QWidget( parent ), pgp( Module::getKpgp() )
00096 {
00097 QGroupBox * group;
00098 QLabel * label;
00099 QString msg;
00100
00101
00102 QVBoxLayout *topLayout = new QVBoxLayout( this );
00103 topLayout->setSpacing( KDialog::spacingHint() );
00104 topLayout->setMargin( 0 );
00105
00106 group = new QGroupBox( i18n("Warning"), this );
00107 QVBoxLayout *lay = new QVBoxLayout(group);
00108 lay->setSpacing( KDialog::spacingHint() );
00109
00110
00111 label = new QLabel( i18n("Please check if encryption really "
00112 "works before you start using it seriously. Also note that attachments "
00113 "are not encrypted by the PGP/GPG module."), group );
00114 label->setWordWrap( true );
00115 lay->addWidget( label );
00116
00117 QFont labelFont = label->font();
00118 labelFont.setBold( true );
00119 label->setFont( labelFont );
00120
00121
00122
00123 topLayout->addWidget( group );
00124 group = new QGroupBox( i18n("Encryption Tool"), this );
00125 lay = new QVBoxLayout(group);
00126 lay->setSpacing( KDialog::spacingHint() );
00127
00128 KHBox * hbox = new KHBox( group );
00129 lay->addWidget( hbox );
00130 label = new QLabel( i18n("Select encryption tool to &use:"), hbox );
00131 toolCombo = new QComboBox( hbox );
00132 toolCombo->setEditable( false );
00133 toolCombo->addItems( QStringList()
00134 << i18n("Autodetect")
00135 << i18n("GnuPG - Gnu Privacy Guard")
00136 << i18n("PGP Version 2.x")
00137 << i18n("PGP Version 5.x")
00138 << i18n("PGP Version 6.x")
00139 << i18n("Do not use any encryption tool") );
00140 label->setBuddy( toolCombo );
00141 hbox->setStretchFactor( toolCombo, 1 );
00142 connect( toolCombo, SIGNAL( activated( int ) ),
00143 this, SIGNAL( changed( void ) ) );
00144
00145
00146 topLayout->addWidget( group );
00147
00148 mpOptionsGroupBox = new QGroupBox( i18n("Options"), this );
00149 lay = new QVBoxLayout( mpOptionsGroupBox );
00150 lay->setSpacing( KDialog::spacingHint() );
00151 storePass = new QCheckBox( i18n("&Keep passphrase in memory"),
00152 mpOptionsGroupBox );
00153 lay->addWidget( storePass );
00154 connect( storePass, SIGNAL( toggled( bool ) ),
00155 this, SIGNAL( changed( void ) ) );
00156 msg = i18n( "<qt><p>When this option is enabled, the passphrase of your "
00157 "private key will be remembered by the application as long "
00158 "as the application is running. Thus you will only have to "
00159 "enter the passphrase once.</p><p>Be aware that this could be a "
00160 "security risk. If you leave your computer, others "
00161 "can use it to send signed messages and/or read your encrypted "
00162 "messages. If a core dump occurs, the contents of your RAM will "
00163 "be saved onto disk, including your passphrase.</p>"
00164 "<p>Note that when using KMail, this setting only applies "
00165 "if you are not using gpg-agent. It is also ignored "
00166 "if you are using crypto plugins.</p></qt>" );
00167 storePass->setWhatsThis( msg );
00168 if( encrypt ) {
00169 encToSelf = new QCheckBox( i18n("Always encr&ypt to self"),
00170 mpOptionsGroupBox );
00171 connect( encToSelf, SIGNAL( toggled( bool ) ),
00172 this, SIGNAL( changed( void ) ) );
00173
00174 msg = i18n( "<qt><p>When this option is enabled, the message/file "
00175 "will not only be encrypted with the receiver's public key, "
00176 "but also with your key. This will enable you to decrypt the "
00177 "message/file at a later time. This is generally a good idea."
00178 "</p></qt>" );
00179 encToSelf->setWhatsThis( msg );
00180 }
00181 else
00182 encToSelf = 0;
00183 showCipherText = new QCheckBox( i18n("&Show signed/encrypted text after "
00184 "composing"));
00185 lay->addWidget( showCipherText );
00186 connect( showCipherText, SIGNAL( toggled( bool ) ),
00187 this, SIGNAL( changed( void ) ) );
00188
00189 msg = i18n( "<qt><p>When this option is enabled, the signed/encrypted text "
00190 "will be shown in a separate window, enabling you to know how "
00191 "it will look before it is sent. This is a good idea when "
00192 "you are verifying that your encryption system works.</p></qt>" );
00193 showCipherText->setWhatsThis( msg );
00194 if( encrypt ) {
00195 showKeyApprovalDlg = new QCheckBox( i18n("Always show the encryption "
00196 "keys &for approval"));
00197 lay->addWidget( showKeyApprovalDlg );
00198 connect( showKeyApprovalDlg, SIGNAL( toggled( bool ) ),
00199 this, SIGNAL( changed( void ) ) );
00200 msg = i18n( "<qt><p>When this option is enabled, the application will "
00201 "always show you a list of public keys from which you can "
00202 "choose the one it will use for encryption. If it is off, "
00203 "the application will only show the dialog if it cannot find "
00204 "the right key or if there are several which could be used. "
00205 "</p></qt>" );
00206 showKeyApprovalDlg->setWhatsThis( msg );
00207 }
00208 else
00209 showKeyApprovalDlg = 0;
00210
00211 topLayout->addWidget( mpOptionsGroupBox );
00212
00213 topLayout->addStretch(1);
00214
00215 setValues();
00216 }
00217
00218
00219 Config::~Config()
00220 {
00221 }
00222
00223 void
00224 Config::setValues()
00225 {
00226
00227 storePass->setChecked( pgp->storePassPhrase() );
00228 if( 0 != encToSelf )
00229 encToSelf->setChecked( pgp->encryptToSelf() );
00230 showCipherText->setChecked( pgp->showCipherText() );
00231 if( 0 != showKeyApprovalDlg )
00232 showKeyApprovalDlg->setChecked( pgp->showKeyApprovalDlg() );
00233
00234 int type = 0;
00235 switch (pgp->pgpType) {
00236
00237 default:
00238 case Module::tAuto: type = 0; break;
00239 case Module::tGPG: type = 1; break;
00240 case Module::tPGP2: type = 2; break;
00241 case Module::tPGP5: type = 3; break;
00242 case Module::tPGP6: type = 4; break;
00243 case Module::tOff: type = 5; break;
00244 }
00245 toolCombo->setCurrentIndex( type );
00246 }
00247
00248 void
00249 Config::applySettings()
00250 {
00251 pgp->setStorePassPhrase(storePass->isChecked());
00252 if( 0 != encToSelf )
00253 pgp->setEncryptToSelf(encToSelf->isChecked());
00254 pgp->setShowCipherText(showCipherText->isChecked());
00255 if( 0 != showKeyApprovalDlg )
00256 pgp->setShowKeyApprovalDlg( showKeyApprovalDlg->isChecked() );
00257
00258 Module::PGPType type;
00259 switch ( toolCombo->currentIndex() ) {
00260
00261 default:
00262 case 0: type = Module::tAuto; break;
00263 case 1: type = Module::tGPG; break;
00264 case 2: type = Module::tPGP2; break;
00265 case 3: type = Module::tPGP5; break;
00266 case 4: type = Module::tPGP6; break;
00267 case 5: type = Module::tOff; break;
00268 }
00269 pgp->pgpType = type;
00270
00271 pgp->writeConfig(true);
00272 }
00273
00274
00275
00276
00277 KeySelectionDialog::KeySelectionDialog( const KeyList& keyList,
00278 const QString& title,
00279 const QString& text,
00280 const KeyIDList& keyIds,
00281 const bool rememberChoice,
00282 const unsigned int allowedKeys,
00283 const bool extendedSelection,
00284 QWidget *parent )
00285 : KDialog( parent ),
00286 mRememberCB( 0 ),
00287 mAllowedKeys( allowedKeys ),
00288 mCurrentContextMenuItem( 0 )
00289 {
00290 setCaption( title );
00291 setButtons( Default|Ok|Cancel );
00292 if ( qApp ) {
00293 KWindowSystem::setIcons( winId(),
00294 qApp->windowIcon().pixmap( IconSize( KIconLoader::Desktop ),
00295 IconSize( KIconLoader::Desktop ) ),
00296 qApp->windowIcon().pixmap( IconSize( KIconLoader::Small ),
00297 IconSize( KIconLoader::Small ) ) );
00298 }
00299 Kpgp::Module *pgp = Kpgp::Module::getKpgp();
00300 KConfig *config = pgp->getConfig();
00301 KConfigGroup dialogConfig( config, "Key Selection Dialog" );
00302
00303 QSize defaultSize( 580, 400 );
00304 QSize dialogSize = dialogConfig.readEntry( "Dialog size", defaultSize );
00305
00306 resize( dialogSize );
00307
00308 mCheckSelectionTimer = new QTimer( this );
00309 mStartSearchTimer = new QTimer( this );
00310 mStartSearchTimer->setSingleShot( true );
00311
00312
00313 mKeyGoodPix = new QPixmap( UserIcon("key_ok") );
00314 mKeyBadPix = new QPixmap( UserIcon("key_bad") );
00315 mKeyUnknownPix = new QPixmap( UserIcon("key_unknown") );
00316 mKeyValidPix = new QPixmap( UserIcon("key") );
00317
00318 QFrame *page = new QFrame( this );
00319 setMainWidget( page );
00320 QVBoxLayout *topLayout = new QVBoxLayout( page );
00321 topLayout->setSpacing( spacingHint() );
00322 topLayout->setMargin( 0 );
00323
00324 if( !text.isEmpty() ) {
00325 QLabel *label = new QLabel( page );
00326 label->setText( text );
00327 topLayout->addWidget( label );
00328 }
00329
00330 QHBoxLayout * hlay = new QHBoxLayout();
00331 topLayout->addLayout( hlay );
00332 QLineEdit * le = new QLineEdit( page );
00333 QLabel *label = new QLabel( i18n("&Search for:"), page );
00334 label->setBuddy( le );
00335 hlay->addWidget( label );
00336 hlay->addWidget( le, 1 );
00337 le->setFocus();
00338
00339 connect( le, SIGNAL(textChanged(const QString&)),
00340 this, SLOT(slotSearch(const QString&)) );
00341 connect( mStartSearchTimer, SIGNAL(timeout()), SLOT(slotFilter()) );
00342
00343 mListView = new K3ListView( page );
00344 mListView->addColumn( i18n("Key ID") );
00345 mListView->addColumn( i18n("User ID") );
00346 mListView->setAllColumnsShowFocus( true );
00347 mListView->setResizeMode( Q3ListView::LastColumn );
00348 mListView->setRootIsDecorated( true );
00349 mListView->setShowSortIndicator( true );
00350 mListView->setSorting( 1, true );
00351 mListView->setShowToolTips( true );
00352 if( extendedSelection ) {
00353 mListView->setSelectionMode( Q3ListView::Extended );
00354
00355 }
00356 topLayout->addWidget( mListView, 10 );
00357
00358 if (rememberChoice) {
00359 mRememberCB = new QCheckBox( i18n("Remember choice"), page );
00360 topLayout->addWidget( mRememberCB );
00361 mRememberCB->setWhatsThis(
00362 i18n("<qt><p>If you check this box your choice will "
00363 "be stored and you will not be asked again."
00364 "</p></qt>"));
00365 }
00366
00367 initKeylist( keyList, keyIds );
00368
00369 Q3ListViewItem *lvi;
00370 if( extendedSelection ) {
00371 lvi = mListView->currentItem();
00372 slotCheckSelection();
00373 }
00374 else {
00375 lvi = mListView->selectedItem();
00376 slotCheckSelection( lvi );
00377 }
00378
00379
00380 if( lvi != 0 )
00381 mListView->center( mListView->contentsX(), mListView->itemPos( lvi ) );
00382
00383 if( extendedSelection ) {
00384 connect( mCheckSelectionTimer, SIGNAL( timeout() ),
00385 this, SLOT( slotCheckSelection() ) );
00386 connect( mListView, SIGNAL( selectionChanged() ),
00387 this, SLOT( slotSelectionChanged() ) );
00388 }
00389 else {
00390 connect( mListView, SIGNAL( selectionChanged( Q3ListViewItem* ) ),
00391 this, SLOT( slotSelectionChanged( Q3ListViewItem* ) ) );
00392 }
00393 connect( mListView, SIGNAL( doubleClicked ( Q3ListViewItem *, const QPoint &, int ) ), this, SLOT( accept() ) );
00394
00395 connect( mListView, SIGNAL( contextMenuRequested( Q3ListViewItem*,
00396 const QPoint&, int ) ),
00397 this, SLOT( slotRMB( Q3ListViewItem*, const QPoint&, int ) ) );
00398
00399 setButtonGuiItem( KDialog::Default, KGuiItem(i18n("&Reread Keys")) );
00400 connect( this, SIGNAL( defaultClicked() ),
00401 this, SLOT( slotRereadKeys() ) );
00402 connect(this, SIGNAL( okClicked()),SLOT(slotOk()));
00403 connect(this,SIGNAL( cancelClicked()),SLOT(slotCancel()));
00404 }
00405
00406
00407 KeySelectionDialog::~KeySelectionDialog()
00408 {
00409 Kpgp::Module *pgp = Kpgp::Module::getKpgp();
00410 KConfig *config = pgp->getConfig();
00411 KConfigGroup dialogConfig( config, "Key Selection Dialog" );
00412 dialogConfig.writeEntry( "Dialog size", size() );
00413 config->sync();
00414 delete mKeyGoodPix;
00415 delete mKeyBadPix;
00416 delete mKeyUnknownPix;
00417 delete mKeyValidPix;
00418 }
00419
00420
00421 KeyID KeySelectionDialog::key() const
00422 {
00423 if( mListView->isMultiSelection() || mKeyIds.isEmpty() )
00424 return KeyID();
00425 else
00426 return mKeyIds.first();
00427 }
00428
00429
00430 void KeySelectionDialog::initKeylist( const KeyList& keyList,
00431 const KeyIDList& keyIds )
00432 {
00433 Q3ListViewItem* firstSelectedItem = 0;
00434 mKeyIds.clear();
00435 mListView->clear();
00436
00437
00438 for( KeyListIterator it( keyList ); it.current(); ++it ) {
00439 KeyID curKeyId = (*it)->primaryKeyID();
00440
00441 Q3ListViewItem* primaryUserID = new Q3ListViewItem( mListView, curKeyId,
00442 (*it)->primaryUserID() );
00443
00444
00445 if( keyIds.indexOf( curKeyId ) != -1 ) {
00446 if( 0 == firstSelectedItem ) {
00447 firstSelectedItem = primaryUserID;
00448 }
00449 mListView->setSelected( primaryUserID, true );
00450 mKeyIds.append( curKeyId );
00451 }
00452 primaryUserID->setOpen( false );
00453
00454
00455 switch( keyValidity( *it ) ) {
00456 case 0:
00457 primaryUserID->setPixmap( 0, *mKeyUnknownPix );
00458 break;
00459 case 1:
00460 primaryUserID->setPixmap( 0, *mKeyValidPix );
00461 break;
00462 case 2:
00463 primaryUserID->setPixmap( 0, *mKeyGoodPix );
00464 break;
00465 case -1:
00466 primaryUserID->setPixmap( 0, *mKeyBadPix );
00467 break;
00468 }
00469
00470 Q3ListViewItem* childItem;
00471
00472 childItem = new Q3ListViewItem( primaryUserID, "",
00473 i18n( "Fingerprint: %1" ,
00474 beautifyFingerprint( (*it)->primaryFingerprint() ) ) );
00475 if( primaryUserID->isSelected() && mListView->isMultiSelection() ) {
00476 mListView->setSelected( childItem, true );
00477 }
00478
00479 childItem = new Q3ListViewItem( primaryUserID, "", keyInfo( *it ) );
00480 if( primaryUserID->isSelected() && mListView->isMultiSelection() ) {
00481 mListView->setSelected( childItem, true );
00482 }
00483
00484 UserIDList userIDs = (*it)->userIDs();
00485 UserIDListIterator uidit( userIDs );
00486 if( *uidit ) {
00487 ++uidit;
00488 for( ; *uidit; ++uidit ) {
00489 childItem = new Q3ListViewItem( primaryUserID, "", (*uidit)->text() );
00490 if( primaryUserID->isSelected() && mListView->isMultiSelection() ) {
00491 mListView->setSelected( childItem, true );
00492 }
00493 }
00494 }
00495 }
00496
00497 if( 0 != firstSelectedItem ) {
00498 mListView->setCurrentItem( firstSelectedItem );
00499 }
00500 }
00501
00502
00503 QString KeySelectionDialog::keyInfo( const Kpgp::Key *key ) const
00504 {
00505 QString status, remark;
00506 if( key->revoked() ) {
00507 status = i18n("Revoked");
00508 }
00509 else if( key->expired() ) {
00510 status = i18n("Expired");
00511 }
00512 else if( key->disabled() ) {
00513 status = i18n("Disabled");
00514 }
00515 else if( key->invalid() ) {
00516 status = i18n("Invalid");
00517 }
00518 else {
00519 Validity keyTrust = key->keyTrust();
00520 switch( keyTrust ) {
00521 case KPGP_VALIDITY_UNDEFINED:
00522 status = i18n("Undefined trust");
00523 break;
00524 case KPGP_VALIDITY_NEVER:
00525 status = i18n("Untrusted");
00526 break;
00527 case KPGP_VALIDITY_MARGINAL:
00528 status = i18n("Marginally trusted");
00529 break;
00530 case KPGP_VALIDITY_FULL:
00531 status = i18n("Fully trusted");
00532 break;
00533 case KPGP_VALIDITY_ULTIMATE:
00534 status = i18n("Ultimately trusted");
00535 break;
00536 case KPGP_VALIDITY_UNKNOWN:
00537 default:
00538 status = i18n("Unknown");
00539 }
00540 if( key->secret() ) {
00541 remark = i18n("Secret key available");
00542 }
00543 else if( !key->canEncrypt() ) {
00544 remark = i18n("Sign only key");
00545 }
00546 else if( !key->canSign() ) {
00547 remark = i18n("Encryption only key");
00548 }
00549 }
00550
00551 QDateTime dt;
00552 dt.setTime_t( key->creationDate() );
00553 if( remark.isEmpty() ) {
00554 return ' ' + i18nc("creation date and status of an OpenPGP key",
00555 "Creation date: %1, Status: %2",
00556 KGlobal::locale()->formatDate( dt.date(), KLocale::ShortDate ) ,
00557 status );
00558 }
00559 else {
00560 return ' ' + i18nc("creation date, status and remark of an OpenPGP key",
00561 "Creation date: %1, Status: %2 (%3)",
00562 KGlobal::locale()->formatDate( dt.date(), KLocale::ShortDate ) ,
00563 status ,
00564 remark );
00565 }
00566 }
00567
00568 QString KeySelectionDialog::beautifyFingerprint( const QByteArray& fpr ) const
00569 {
00570 QByteArray result;
00571
00572 if( 40 == fpr.length() ) {
00573
00574
00575 result.fill( ' ', 50 );
00576 memcpy( result.data() , fpr.data() , 4 );
00577 memcpy( result.data() + 5, fpr.data() + 4, 4 );
00578 memcpy( result.data() + 10, fpr.data() + 8, 4 );
00579 memcpy( result.data() + 15, fpr.data() + 12, 4 );
00580 memcpy( result.data() + 20, fpr.data() + 16, 4 );
00581 memcpy( result.data() + 26, fpr.data() + 20, 4 );
00582 memcpy( result.data() + 31, fpr.data() + 24, 4 );
00583 memcpy( result.data() + 36, fpr.data() + 28, 4 );
00584 memcpy( result.data() + 41, fpr.data() + 32, 4 );
00585 memcpy( result.data() + 46, fpr.data() + 36, 4 );
00586 }
00587 else if( 32 == fpr.length() ) {
00588
00589
00590 result.fill( ' ', 48 );
00591 memcpy( result.data() , fpr.data() , 2 );
00592 memcpy( result.data() + 3, fpr.data() + 2, 2 );
00593 memcpy( result.data() + 6, fpr.data() + 4, 2 );
00594 memcpy( result.data() + 9, fpr.data() + 6, 2 );
00595 memcpy( result.data() + 12, fpr.data() + 8, 2 );
00596 memcpy( result.data() + 15, fpr.data() + 10, 2 );
00597 memcpy( result.data() + 18, fpr.data() + 12, 2 );
00598 memcpy( result.data() + 21, fpr.data() + 14, 2 );
00599 memcpy( result.data() + 25, fpr.data() + 16, 2 );
00600 memcpy( result.data() + 28, fpr.data() + 18, 2 );
00601 memcpy( result.data() + 31, fpr.data() + 20, 2 );
00602 memcpy( result.data() + 34, fpr.data() + 22, 2 );
00603 memcpy( result.data() + 37, fpr.data() + 24, 2 );
00604 memcpy( result.data() + 40, fpr.data() + 26, 2 );
00605 memcpy( result.data() + 43, fpr.data() + 28, 2 );
00606 memcpy( result.data() + 46, fpr.data() + 30, 2 );
00607 }
00608 else {
00609 result = fpr;
00610 }
00611
00612 return result;
00613 }
00614
00615 int KeySelectionDialog::keyValidity( const Kpgp::Key *key ) const
00616 {
00617 if( 0 == key ) {
00618 return -1;
00619 }
00620
00621 if( ( mAllowedKeys & EncrSignKeys ) == EncryptionKeys ) {
00622
00623 if( ( mAllowedKeys & ValidKeys ) && !key->isValidEncryptionKey() ) {
00624
00625 return -1;
00626 }
00627 else if( !key->canEncrypt() ) {
00628 return -1;
00629 }
00630 }
00631 else if( ( mAllowedKeys & EncrSignKeys ) == SigningKeys ) {
00632
00633 if( ( mAllowedKeys & ValidKeys ) && !key->isValidSigningKey() ) {
00634
00635 return -1;
00636 }
00637 else if( !key->canSign() ) {
00638 return -1;
00639 }
00640 }
00641 else if( ( mAllowedKeys & ValidKeys ) && !key->isValid() ) {
00642
00643 return -1;
00644 }
00645
00646
00647 int val = 0;
00648 Validity keyTrust = key->keyTrust();
00649 switch( keyTrust ) {
00650 case KPGP_VALIDITY_NEVER:
00651 val = -1;
00652 break;
00653 case KPGP_VALIDITY_MARGINAL:
00654 case KPGP_VALIDITY_FULL:
00655 case KPGP_VALIDITY_ULTIMATE:
00656 val = 2;
00657 break;
00658 case KPGP_VALIDITY_UNDEFINED:
00659 if( mAllowedKeys & TrustedKeys ) {
00660
00661 val = -1;
00662 }
00663 else {
00664 val = 1;
00665 }
00666 break;
00667 case KPGP_VALIDITY_UNKNOWN:
00668 default:
00669 val = 0;
00670 }
00671
00672 return val;
00673 }
00674
00675
00676 void KeySelectionDialog::updateKeyInfo( const Kpgp::Key* key,
00677 Q3ListViewItem* lvi ) const
00678 {
00679 if( 0 == lvi ) {
00680 return;
00681 }
00682
00683 if( lvi->parent() != 0 ) {
00684 lvi = lvi->parent();
00685 }
00686
00687 if( 0 == key ) {
00688
00689 while( lvi->firstChild() ) {
00690 kDebug( 5326 ) <<"Deleting '" << lvi->firstChild()->text( 1 ) <<"'";
00691 delete lvi->firstChild();
00692 }
00693 kDebug( 5326 ) <<"Deleting key 0x" << lvi->text( 0 ) <<" ("
00694 << lvi->text( 1 ) << ")\n";
00695 delete lvi;
00696 lvi = 0;
00697 return;
00698 }
00699
00700
00701 switch( keyValidity( key ) ) {
00702 case 0:
00703 lvi->setPixmap( 0, *mKeyUnknownPix );
00704 break;
00705 case 1:
00706 lvi->setPixmap( 0, *mKeyValidPix );
00707 break;
00708 case 2:
00709 lvi->setPixmap( 0, *mKeyGoodPix );
00710 break;
00711 case -1:
00712 lvi->setPixmap( 0, *mKeyBadPix );
00713 break;
00714 }
00715
00716
00717
00718
00719 for( lvi = lvi->firstChild(); lvi; lvi = lvi->nextSibling() ) {
00720 if( lvi->text( 1 ).at(0) == ' ' ) {
00721 lvi->setText( 1, keyInfo( key ) );
00722 break;
00723 }
00724 }
00725 }
00726
00727
00728 int
00729 KeySelectionDialog::keyAdmissibility( Q3ListViewItem* lvi,
00730 TrustCheckMode trustCheckMode ) const
00731 {
00732
00733
00734
00735
00736
00737
00738 if( mAllowedKeys == AllKeys ) {
00739 return 1;
00740 }
00741
00742 Kpgp::Module *pgp = Kpgp::Module::getKpgp();
00743
00744 if( 0 == pgp ) {
00745 return 0;
00746 }
00747
00748 KeyID keyId = getKeyId( lvi );
00749 Kpgp::Key* key = pgp->publicKey( keyId );
00750
00751 if( 0 == key ) {
00752 return 0;
00753 }
00754
00755 int val = 0;
00756 if( trustCheckMode == ForceTrustCheck ) {
00757 key = pgp->rereadKey( keyId, true );
00758 updateKeyInfo( key, lvi );
00759 val = keyValidity( key );
00760 }
00761 else {
00762 val = keyValidity( key );
00763 if( ( trustCheckMode == AllowExpensiveTrustCheck ) && ( 0 == val ) ) {
00764 key = pgp->rereadKey( keyId, true );
00765 updateKeyInfo( key, lvi );
00766 val = keyValidity( key );
00767 }
00768 }
00769
00770 switch( val ) {
00771 case -1:
00772 return -1;
00773 break;
00774 case 0:
00775 return 0;
00776 break;
00777 case 1:
00778 if( mAllowedKeys & TrustedKeys ) {
00779
00780 return -1;
00781 }
00782 return 1;
00783 break;
00784 case 2:
00785 return 1;
00786 break;
00787 default:
00788 kDebug( 5326 ) <<"Error: Invalid key status value.";
00789 }
00790
00791 return 0;
00792 }
00793
00794
00795 KeyID
00796 KeySelectionDialog::getKeyId( const Q3ListViewItem* lvi ) const
00797 {
00798 KeyID keyId;
00799
00800 if( 0 != lvi ) {
00801 if( 0 != lvi->parent() ) {
00802 keyId = lvi->parent()->text(0).toLocal8Bit();
00803 }
00804 else {
00805 keyId = lvi->text(0).toLocal8Bit();
00806 }
00807 }
00808
00809 return keyId;
00810 }
00811
00812
00813 void KeySelectionDialog::slotRereadKeys()
00814 {
00815 Kpgp::Module *pgp = Kpgp::Module::getKpgp();
00816
00817 if( 0 == pgp ) {
00818 return;
00819 }
00820
00821 KeyList keys;
00822
00823 if( PublicKeys & mAllowedKeys ) {
00824 pgp->readPublicKeys( true );
00825 keys = pgp->publicKeys();
00826 }
00827 else {
00828 pgp->readSecretKeys( true );
00829 keys = pgp->secretKeys();
00830 }
00831
00832
00833 int offsetY = mListView->contentsY();
00834
00835 if( mListView->isMultiSelection() ) {
00836 disconnect( mListView, SIGNAL( selectionChanged() ),
00837 this, SLOT( slotSelectionChanged() ) );
00838 }
00839 else {
00840 disconnect( mListView, SIGNAL( selectionChanged( Q3ListViewItem * ) ),
00841 this, SLOT( slotSelectionChanged( Q3ListViewItem * ) ) );
00842 }
00843
00844 initKeylist( keys, KeyIDList( mKeyIds ) );
00845 slotFilter();
00846
00847 if( mListView->isMultiSelection() ) {
00848 connect( mListView, SIGNAL( selectionChanged() ),
00849 this, SLOT( slotSelectionChanged() ) );
00850 slotSelectionChanged();
00851 }
00852 else {
00853 connect( mListView, SIGNAL( selectionChanged( Q3ListViewItem * ) ),
00854 this, SLOT( slotSelectionChanged( Q3ListViewItem * ) ) );
00855 }
00856
00857
00858 mListView->setContentsPos( 0, offsetY );
00859 }
00860
00861
00862 void KeySelectionDialog::slotSelectionChanged( Q3ListViewItem * lvi )
00863 {
00864 slotCheckSelection( lvi );
00865 }
00866
00867
00868 void KeySelectionDialog::slotSelectionChanged()
00869 {
00870 kDebug( 5326 ) <<"KeySelectionDialog::slotSelectionChanged()";
00871
00872
00873
00874
00875 mCheckSelectionTimer->start( sCheckSelectionDelay );
00876 }
00877
00878
00879 void KeySelectionDialog::slotCheckSelection( Q3ListViewItem* plvi )
00880 {
00881 kDebug( 5326 ) <<"KeySelectionDialog::slotCheckSelection()";
00882
00883 if( !mListView->isMultiSelection() ) {
00884 mKeyIds.clear();
00885 KeyID keyId = getKeyId( plvi );
00886 if( !keyId.isEmpty() ) {
00887 mKeyIds.append( keyId );
00888 enableButton( Ok, 1 == keyAdmissibility( plvi, AllowExpensiveTrustCheck ) );
00889 }
00890 else {
00891 enableButton( Ok, false );
00892 }
00893 }
00894 else {
00895 mCheckSelectionTimer->stop();
00896
00897
00898
00899 disconnect( mListView, SIGNAL( selectionChanged() ),
00900 this, SLOT( slotSelectionChanged() ) );
00901
00902 KeyIDList newKeyIdList;
00903 QList<Q3ListViewItem*> keysToBeChecked;
00904
00905 bool keysAllowed = true;
00906 enum { UNKNOWN, SELECTED, DESELECTED } userAction = UNKNOWN;
00907
00908 for( Q3ListViewItem *lvi = mListView->firstChild();
00909 0 != lvi;
00910 lvi = lvi->nextSibling() ) {
00911
00912
00913
00914
00915
00916
00917 int itemCount = 1 + lvi->childCount();
00918 int selectedCount = lvi->isSelected() ? 1 : 0;
00919 for( Q3ListViewItem *clvi = lvi->firstChild();
00920 0 != clvi;
00921 clvi = clvi->nextSibling() ) {
00922 if( clvi->isSelected() ) {
00923 ++selectedCount;
00924 }
00925 }
00926
00927 if( userAction == UNKNOWN ) {
00928
00929
00930
00931
00932 if( 0 < selectedCount ) {
00933 if( -1 == mKeyIds.indexOf( lvi->text(0).toLocal8Bit() ) ) {
00934
00935
00936 kDebug( 5326 ) <<"selectedCount:"<<selectedCount<<"/"<<itemCount
00937 <<"--- User selected key"<<lvi->text(0);
00938 userAction = SELECTED;
00939 }
00940 else if( ( itemCount > selectedCount ) &&
00941 ( -1 != mKeyIds.indexOf( lvi->text(0).toLocal8Bit() ) ) ) {
00942
00943
00944 kDebug( 5326 ) <<"selectedCount:"<<selectedCount<<"/"<<itemCount
00945 <<"--- User deselected key"<<lvi->text(0);
00946 userAction = DESELECTED;
00947 }
00948 }
00949 }
00950 if( itemCount == selectedCount ) {
00951
00952 KeyID keyId = lvi->text(0).toLocal8Bit();
00953 newKeyIdList.append( keyId );
00954 int admissibility = keyAdmissibility( lvi, NoExpensiveTrustCheck );
00955 if( -1 == admissibility ) {
00956 keysAllowed = false;
00957 }
00958 else if ( 0 == admissibility ) {
00959 keysToBeChecked.append( lvi );
00960 }
00961 }
00962 else if( 0 < selectedCount ) {
00963
00964
00965 if( userAction == SELECTED ) {
00966
00967 mListView->setSelected( lvi, true );
00968 for( Q3ListViewItem *clvi = lvi->firstChild();
00969 0 != clvi;
00970 clvi = clvi->nextSibling() ) {
00971 mListView->setSelected( clvi, true );
00972 }
00973
00974 KeyID keyId = lvi->text(0).toLocal8Bit();
00975 newKeyIdList.append( keyId );
00976 int admissibility = keyAdmissibility( lvi, NoExpensiveTrustCheck );
00977 if( -1 == admissibility ) {
00978 keysAllowed = false;
00979 }
00980 else if ( 0 == admissibility ) {
00981 keysToBeChecked.append( lvi );
00982 }
00983 }
00984 else {
00985
00986 mListView->setSelected( lvi, false );
00987 for( Q3ListViewItem *clvi = lvi->firstChild();
00988 0 != clvi;
00989 clvi = clvi->nextSibling() ) {
00990 mListView->setSelected( clvi, false );
00991 }