libkdenetwork Library API Documentation

kpgpui.cpp

00001 /* 00002 kpgpui.cpp 00003 00004 Copyright (C) 2001,2002 the KPGP authors 00005 See file AUTHORS.kpgp for details 00006 00007 This file is part of KPGP, the KDE PGP/GnuPG support library. 00008 00009 KPGP is free software; you can redistribute it and/or modify 00010 it under the terms of the GNU General Public License as published by 00011 the Free Software Foundation; either version 2 of the License, or 00012 (at your option) any later version. 00013 00014 You should have received a copy of the GNU General Public License 00015 along with this program; if not, write to the Free Software Foundation, 00016 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 00017 */ 00018 00019 //#include <stdio.h> 00020 00021 #include <qvgroupbox.h> 00022 #include <qvbox.h> 00023 #include <qlabel.h> 00024 #include <qwhatsthis.h> 00025 #include <qtooltip.h> 00026 #include <qapplication.h> 00027 #include <qtextcodec.h> 00028 #include <qdatetime.h> 00029 #include <qpixmap.h> 00030 #include <qlayout.h> 00031 #include <qtimer.h> 00032 #include <qpopupmenu.h> 00033 #include <qregexp.h> 00034 00035 #include <klocale.h> 00036 #include <kpassdlg.h> 00037 #include <kcharsets.h> 00038 #include <kseparator.h> 00039 #include <kiconloader.h> 00040 #include <klistview.h> 00041 #include <kconfigbase.h> 00042 #include <kconfig.h> 00043 #include <kprogress.h> 00044 #include <kapplication.h> 00045 #include <kwin.h> 00046 #if KDE_IS_VERSION( 3, 1, 90 ) 00047 #include <kglobalsettings.h> 00048 #endif 00049 00050 #include "kpgp.h" 00051 #include "kpgpui.h" 00052 #include "kpgpkey.h" 00053 00054 #include <assert.h> 00055 #include <string.h> // for memcpy(3) 00056 00057 const int Kpgp::KeySelectionDialog::sCheckSelectionDelay = 250; 00058 00059 namespace Kpgp { 00060 00061 PassphraseDialog::PassphraseDialog( QWidget *parent, 00062 const QString &caption, bool modal, 00063 const QString &keyID ) 00064 :KDialogBase( parent, 0, modal, caption, Ok|Cancel ) 00065 { 00066 QHBox *hbox = makeHBoxMainWidget(); 00067 hbox->setSpacing( spacingHint() ); 00068 hbox->setMargin( marginHint() ); 00069 00070 QLabel *label = new QLabel(hbox); 00071 label->setPixmap( BarIcon("pgp-keys") ); 00072 00073 QWidget *rightArea = new QWidget( hbox ); 00074 QVBoxLayout *vlay = new QVBoxLayout( rightArea, 0, spacingHint() ); 00075 00076 if (keyID.isNull()) 00077 label = new QLabel(i18n("Please enter your OpenPGP passphrase:"),rightArea); 00078 else 00079 label = new QLabel(i18n("Please enter the OpenPGP passphrase for\n\"%1\":").arg(keyID), 00080 rightArea); 00081 lineedit = new KPasswordEdit( rightArea ); 00082 lineedit->setEchoMode(QLineEdit::Password); 00083 lineedit->setMinimumWidth( fontMetrics().maxWidth()*20 ); 00084 lineedit->setFocus(); 00085 connect( lineedit, SIGNAL(returnPressed()), this, SLOT(slotOk()) ); 00086 00087 vlay->addWidget( label ); 00088 vlay->addWidget( lineedit ); 00089 00090 disableResize(); 00091 } 00092 00093 00094 PassphraseDialog::~PassphraseDialog() 00095 { 00096 } 00097 00098 const char * PassphraseDialog::passphrase() 00099 { 00100 return lineedit->password(); 00101 } 00102 00103 00104 // ------------------------------------------------------------------------ 00105 // Forbidden accels for KMail: AC GH OP 00106 // for KNode: ACE H O 00107 Config::Config( QWidget *parent, const char *name, bool encrypt ) 00108 : QWidget( parent, name ), pgp( Module::getKpgp() ) 00109 { 00110 QGroupBox * group; 00111 QLabel * label; 00112 QString msg; 00113 00114 00115 QVBoxLayout *topLayout = new QVBoxLayout( this, 0, KDialog::spacingHint() ); 00116 00117 group = new QVGroupBox( i18n("Warning"), this ); 00118 group->layout()->setSpacing( KDialog::spacingHint() ); 00119 // (mmutz) work around Qt label bug in 3.0.0 (and possibly later): 00120 // 1. Don't use rich text: No <qt><b>...</b></qt> 00121 label = new QLabel( i18n("Please check if encryption really " 00122 "works before you start using it seriously. Also note that attachments " 00123 "are not encrypted by the PGP/GPG module."), group ); 00124 // 2. instead, set the font to bold: 00125 QFont labelFont = label->font(); 00126 labelFont.setBold( true ); 00127 label->setFont( labelFont ); 00128 // 3. and activate wordwarp: 00129 label->setAlignment( AlignLeft|WordBreak ); 00130 // end; to remove the workaround, add <qt><b>..</b></qt> around the 00131 // text and remove lines QFont... -> label->setAlignment(...). 00132 topLayout->addWidget( group ); 00133 00134 group = new QVGroupBox( i18n("Encryption Tool"), this ); 00135 group->layout()->setSpacing( KDialog::spacingHint() ); 00136 00137 QHBox * hbox = new QHBox( group ); 00138 label = new QLabel( i18n("Select encryption tool to &use:"), hbox ); 00139 toolCombo = new QComboBox( false, hbox ); 00140 toolCombo->insertStringList( QStringList() 00141 << i18n("Autodetect") 00142 << i18n("GnuPG - Gnu Privacy Guard") 00143 << i18n("PGP Version 2.x") 00144 << i18n("PGP Version 5.x") 00145 << i18n("PGP Version 6.x") 00146 << i18n("Do not use any encryption tool") ); 00147 label->setBuddy( toolCombo ); 00148 hbox->setStretchFactor( toolCombo, 1 ); 00149 connect( toolCombo, SIGNAL( activated( int ) ), 00150 this, SIGNAL( changed( void ) ) ); 00151 // This is the place to add a KURLRequester to be used for asking 00152 // the user for the path to the executable... 00153 topLayout->addWidget( group ); 00154 00155 mpOptionsGroupBox = new QVGroupBox( i18n("Options"), this ); 00156 mpOptionsGroupBox->layout()->setSpacing( KDialog::spacingHint() ); 00157 storePass = new QCheckBox( i18n("&Keep passphrase in memory"), 00158 mpOptionsGroupBox ); 00159 connect( storePass, SIGNAL( toggled( bool ) ), 00160 this, SIGNAL( changed( void ) ) ); 00161 msg = i18n( "<qt><p>When this option is enabled, the passphrase of your " 00162 "private key will be remembered by the application as long " 00163 "as the application is running. Thus you will only have to " 00164 "enter the passphrase once.</p><p>Be aware that this could be a " 00165 "security risk. If you leave your computer, others " 00166 "can use it to send signed messages and/or read your encrypted " 00167 "messages. If a core dump occurs, the contents of your RAM will " 00168 "be saved onto disk, including your passphrase.</p>" 00169 "<p>Note that when using KMail, this setting only applies " 00170 "if you are not using gpg-agent. It is also ignored " 00171 "if you are using crypto plugins.</p></qt>" ); 00172 QWhatsThis::add( storePass, msg ); 00173 if( encrypt ) { 00174 encToSelf = new QCheckBox( i18n("Always encr&ypt to self"), 00175 mpOptionsGroupBox ); 00176 connect( encToSelf, SIGNAL( toggled( bool ) ), 00177 this, SIGNAL( changed( void ) ) ); 00178 00179 msg = i18n( "<qt><p>When this option is enabled, the message/file " 00180 "will not only be encrypted with the receiver's public key, " 00181 "but also with your key. This will enable you to decrypt the " 00182 "message/file at a later time. This is generally a good idea." 00183 "</p></qt>" ); 00184 QWhatsThis::add( encToSelf, msg ); 00185 } 00186 else 00187 encToSelf = 0; 00188 showCipherText = new QCheckBox( i18n("&Show signed/encrypted text after " 00189 "composing"), 00190 mpOptionsGroupBox ); 00191 connect( showCipherText, SIGNAL( toggled( bool ) ), 00192 this, SIGNAL( changed( void ) ) ); 00193 00194 msg = i18n( "<qt><p>When this option is enabled, the signed/encrypted text " 00195 "will be shown in a separate window, enabling you to know how " 00196 "it will look before it is sent. This is a good idea when " 00197 "you are verifying that your encryption system works.</p></qt>" ); 00198 QWhatsThis::add( showCipherText, msg ); 00199 if( encrypt ) { 00200 showKeyApprovalDlg = new QCheckBox( i18n("Always show the encryption " 00201 "keys &for approval"), 00202 mpOptionsGroupBox ); 00203 connect( showKeyApprovalDlg, SIGNAL( toggled( bool ) ), 00204 this, SIGNAL( changed( void ) ) ); 00205 msg = i18n( "<qt><p>When this option is enabled, the application will " 00206 "always show you a list of public keys from which you can " 00207 "choose the one it will use for encryption. If it is off, " 00208 "the application will only show the dialog if it cannot find " 00209 "the right key or if there are several which could be used. " 00210 "</p></qt>" ); 00211 QWhatsThis::add( showKeyApprovalDlg, msg ); 00212 } 00213 else 00214 showKeyApprovalDlg = 0; 00215 00216 topLayout->addWidget( mpOptionsGroupBox ); 00217 00218 topLayout->addStretch(1); 00219 00220 setValues(); // is this needed by KNode, b/c for KMail, it's not. 00221 } 00222 00223 00224 Config::~Config() 00225 { 00226 } 00227 00228 void 00229 Config::setValues() 00230 { 00231 // set default values 00232 storePass->setChecked( pgp->storePassPhrase() ); 00233 if( 0 != encToSelf ) 00234 encToSelf->setChecked( pgp->encryptToSelf() ); 00235 showCipherText->setChecked( pgp->showCipherText() ); 00236 if( 0 != showKeyApprovalDlg ) 00237 showKeyApprovalDlg->setChecked( pgp->showKeyApprovalDlg() ); 00238 00239 int type = 0; 00240 switch (pgp->pgpType) { 00241 // translate Kpgp::Module enum to combobox' entries: 00242 default: 00243 case Module::tAuto: type = 0; break; 00244 case Module::tGPG: type = 1; break; 00245 case Module::tPGP2: type = 2; break; 00246 case Module::tPGP5: type = 3; break; 00247 case Module::tPGP6: type = 4; break; 00248 case Module::tOff: type = 5; break; 00249 } 00250 toolCombo->setCurrentItem( type ); 00251 } 00252 00253 void 00254 Config::applySettings() 00255 { 00256 pgp->setStorePassPhrase(storePass->isChecked()); 00257 if( 0 != encToSelf ) 00258 pgp->setEncryptToSelf(encToSelf->isChecked()); 00259 pgp->setShowCipherText(showCipherText->isChecked()); 00260 if( 0 != showKeyApprovalDlg ) 00261 pgp->setShowKeyApprovalDlg( showKeyApprovalDlg->isChecked() ); 00262 00263 Module::PGPType type; 00264 switch ( toolCombo->currentItem() ) { 00265 // convert combobox entry indices to Kpgp::Module constants: 00266 default: 00267 case 0: type = Module::tAuto; break; 00268 case 1: type = Module::tGPG; break; 00269 case 2: type = Module::tPGP2; break; 00270 case 3: type = Module::tPGP5; break; 00271 case 4: type = Module::tPGP6; break; 00272 case 5: type = Module::tOff; break; 00273 } 00274 pgp->pgpType = type; 00275 00276 pgp->writeConfig(true); 00277 } 00278 00279 00280 00281 // ------------------------------------------------------------------------ 00282 KeySelectionDialog::KeySelectionDialog( const KeyList& keyList, 00283 const QString& title, 00284 const QString& text, 00285 const KeyIDList& keyIds, 00286 const bool rememberChoice, 00287 const unsigned int allowedKeys, 00288 const bool extendedSelection, 00289 QWidget *parent, const char *name, 00290 bool modal ) 00291 : KDialogBase( parent, name, modal, title, Default|Ok|Cancel, Ok ), 00292 mRememberCB( 0 ), 00293 mAllowedKeys( allowedKeys ), 00294 mCurrentContextMenuItem( 0 ) 00295 { 00296 if ( kapp ) 00297 KWin::setIcons( winId(), kapp->icon(), kapp->miniIcon() ); 00298 Kpgp::Module *pgp = Kpgp::Module::getKpgp(); 00299 KConfig *config = pgp->getConfig(); 00300 KConfigGroup dialogConfig( config, "Key Selection Dialog" ); 00301 00302 QSize defaultSize( 580, 400 ); 00303 QSize dialogSize = dialogConfig.readSizeEntry( "Dialog size", &defaultSize ); 00304 00305 resize( dialogSize ); 00306 00307 mCheckSelectionTimer = new QTimer( this ); 00308 mStartSearchTimer = new QTimer( this ); 00309 00310 // load the key status icons 00311 mKeyGoodPix = new QPixmap( UserIcon("key_ok") ); 00312 mKeyBadPix = new QPixmap( UserIcon("key_bad") ); 00313 mKeyUnknownPix = new QPixmap( UserIcon("key_unknown") ); 00314 mKeyValidPix = new QPixmap( UserIcon("key") ); 00315 00316 QFrame *page = makeMainWidget(); 00317 QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() ); 00318 00319 if( !text.isEmpty() ) { 00320 QLabel *label = new QLabel( page ); 00321 label->setText( text ); 00322 topLayout->addWidget( label ); 00323 } 00324 00325 QHBoxLayout * hlay = new QHBoxLayout( topLayout ); // inherits spacing 00326 QLineEdit * le = new QLineEdit( page ); 00327 hlay->addWidget( new QLabel( le, i18n("&Search for:"), page ) ); 00328 hlay->addWidget( le, 1 ); 00329 le->setFocus(); 00330 00331 connect( le, SIGNAL(textChanged(const QString&)), 00332 this, SLOT(slotSearch(const QString&)) ); 00333 connect( mStartSearchTimer, SIGNAL(timeout()), SLOT(slotFilter()) ); 00334 00335 mListView = new KListView( page ); 00336 mListView->addColumn( i18n("Key ID") ); 00337 mListView->addColumn( i18n("User ID") ); 00338 mListView->setAllColumnsShowFocus( true ); 00339 mListView->setResizeMode( QListView::LastColumn ); 00340 mListView->setRootIsDecorated( true ); 00341 mListView->setShowSortIndicator( true ); 00342 mListView->setSorting( 1, true ); // sort by User ID 00343 mListView->setShowToolTips( true ); 00344 if( extendedSelection ) { 00345 mListView->setSelectionMode( QListView::Extended ); 00346 //mListView->setSelectionMode( QListView::Multi ); 00347 } 00348 topLayout->addWidget( mListView, 10 ); 00349 00350 if (rememberChoice) { 00351 mRememberCB = new QCheckBox( i18n("Remember choice"), page ); 00352 topLayout->addWidget( mRememberCB ); 00353 QWhatsThis::add(mRememberCB, 00354 i18n("<qt><p>If you check this box your choice will " 00355 "be stored and you will not be asked again." 00356 "</p></qt>")); 00357 } 00358 00359 initKeylist( keyList, keyIds ); 00360 00361 QListViewItem *lvi; 00362 if( extendedSelection ) { 00363 lvi = mListView->currentItem(); 00364 slotCheckSelection(); 00365 } 00366 else { 00367 lvi = mListView->selectedItem(); 00368 slotCheckSelection( lvi ); 00369 } 00370 // make sure that the selected item is visible 00371 // (ensureItemVisible(...) doesn't work correctly in Qt 3.0.0) 00372 if( lvi != 0 ) 00373 mListView->center( mListView->contentsX(), mListView->itemPos( lvi ) ); 00374 00375 if( extendedSelection ) { 00376 connect( mCheckSelectionTimer, SIGNAL( timeout() ), 00377 this, SLOT( slotCheckSelection() ) ); 00378 connect( mListView, SIGNAL( selectionChanged() ), 00379 this, SLOT( slotSelectionChanged() ) ); 00380 } 00381 else { 00382 connect( mListView, SIGNAL( selectionChanged( QListViewItem* ) ), 00383 this, SLOT( slotSelectionChanged( QListViewItem* ) ) ); 00384 } 00385 connect( mListView, SIGNAL( doubleClicked ( QListViewItem *, const QPoint &, int ) ), this, SLOT( accept() ) ); 00386 00387 connect( mListView, SIGNAL( contextMenuRequested( QListViewItem*, 00388 const QPoint&, int ) ), 00389 this, SLOT( slotRMB( QListViewItem*, const QPoint&, int ) ) ); 00390 00391 setButtonText( KDialogBase::Default, i18n("&Reread Keys") ); 00392 connect( this, SIGNAL( defaultClicked() ), 00393 this, SLOT( slotRereadKeys() ) ); 00394 } 00395 00396 00397 KeySelectionDialog::~KeySelectionDialog() 00398 { 00399 Kpgp::Module *pgp = Kpgp::Module::getKpgp(); 00400 KConfig *config = pgp->getConfig(); 00401 KConfigGroup dialogConfig( config, "Key Selection Dialog" ); 00402 dialogConfig.writeEntry( "Dialog size", size() ); 00403 config->sync(); 00404 delete mKeyGoodPix; 00405 delete mKeyBadPix; 00406 delete mKeyUnknownPix; 00407 delete mKeyValidPix; 00408 } 00409 00410 00411 KeyID KeySelectionDialog::key() const 00412 { 00413 if( mListView->isMultiSelection() || mKeyIds.isEmpty() ) 00414 return KeyID(); 00415 else 00416 return mKeyIds.first(); 00417 } 00418 00419 00420 void KeySelectionDialog::initKeylist( const KeyList& keyList, 00421 const KeyIDList& keyIds ) 00422 { 00423 QListViewItem* firstSelectedItem = 0; 00424 mKeyIds.clear(); 00425 mListView->clear(); 00426 00427 // build a list of all public keys 00428 for( KeyListIterator it( keyList ); it.current(); ++it ) { 00429 KeyID curKeyId = (*it)->primaryKeyID(); 00430 00431 QListViewItem* primaryUserID = new QListViewItem( mListView, curKeyId, 00432 (*it)->primaryUserID() ); 00433 00434 // select and open the given key 00435 if( keyIds.findIndex( curKeyId ) != -1 ) { 00436 if( 0 == firstSelectedItem ) { 00437 firstSelectedItem = primaryUserID; 00438 } 00439 mListView->setSelected( primaryUserID, true ); 00440 mKeyIds.append( curKeyId ); 00441 } 00442 primaryUserID->setOpen( false ); 00443 00444 // set icon for this key 00445 switch( keyValidity( *it ) ) { 00446 case 0: // the key's validity can't be determined 00447 primaryUserID->setPixmap( 0, *mKeyUnknownPix ); 00448 break; 00449 case 1: // key is valid but not trusted 00450 primaryUserID->setPixmap( 0, *mKeyValidPix ); 00451 break; 00452 case 2: // key is valid and trusted 00453 primaryUserID->setPixmap( 0, *mKeyGoodPix ); 00454 break; 00455 case -1: // key is invalid 00456 primaryUserID->setPixmap( 0, *mKeyBadPix ); 00457 break; 00458 } 00459 00460 QListViewItem* childItem; 00461 00462 childItem = new QListViewItem( primaryUserID, "", 00463 i18n( "Fingerprint: %1" ) 00464 .arg( beautifyFingerprint( (*it)->primaryFingerprint() ) ) ); 00465 if( primaryUserID->isSelected() && mListView->isMultiSelection() ) { 00466 mListView->setSelected( childItem, true ); 00467 } 00468 00469 childItem = new QListViewItem( primaryUserID, "", keyInfo( *it ) ); 00470 if( primaryUserID->isSelected() && mListView->isMultiSelection() ) { 00471 mListView->setSelected( childItem, true ); 00472 } 00473 00474 UserIDList userIDs = (*it)->userIDs(); 00475 UserIDListIterator uidit( userIDs ); 00476 if( *uidit ) { 00477 ++uidit; // skip the primary user ID 00478 for( ; *uidit; ++uidit ) { 00479 childItem = new QListViewItem( primaryUserID, "", (*uidit)->text() ); 00480 if( primaryUserID->isSelected() && mListView->isMultiSelection() ) { 00481 mListView->setSelected( childItem, true ); 00482 } 00483 } 00484 } 00485 } 00486 00487 if( 0 != firstSelectedItem ) { 00488 mListView->setCurrentItem( firstSelectedItem ); 00489 } 00490 } 00491 00492 00493 QString KeySelectionDialog::keyInfo( const Kpgp::Key *key ) const 00494 { 00495 QString status, remark; 00496 if( key->revoked() ) { 00497 status = i18n("Revoked"); 00498 } 00499 else if( key->expired() ) { 00500 status = i18n("Expired"); 00501 } 00502 else if( key->disabled() ) { 00503 status = i18n("Disabled"); 00504 } 00505 else if( key->invalid() ) { 00506 status = i18n("Invalid"); 00507 } 00508 else { 00509 Validity keyTrust = key->keyTrust(); 00510 switch( keyTrust ) { 00511 case KPGP_VALIDITY_UNDEFINED: 00512 status = i18n("Undefined trust"); 00513 break; 00514 case KPGP_VALIDITY_NEVER: 00515 status = i18n("Untrusted"); 00516 break; 00517 case KPGP_VALIDITY_MARGINAL: 00518 status = i18n("Marginally trusted"); 00519 break; 00520 case KPGP_VALIDITY_FULL: 00521 status = i18n("Fully trusted"); 00522 break; 00523 case KPGP_VALIDITY_ULTIMATE: 00524 status = i18n("Ultimately trusted"); 00525 break; 00526 case KPGP_VALIDITY_UNKNOWN: 00527 default: 00528 status = i18n("Unknown"); 00529 } 00530 if( key->secret() ) { 00531 remark = i18n("Secret key available"); 00532 } 00533 else if( !key->canEncrypt() ) { 00534 remark = i18n("Sign only key"); 00535 } 00536 else if( !key->canSign() ) { 00537 remark = i18n("Encryption only key"); 00538 } 00539 } 00540 00541 QDateTime dt; 00542 dt.setTime_t( key->creationDate() ); 00543 if( remark.isEmpty() ) { 00544 return " " + i18n("creation date and status of an OpenPGP key", 00545 "Creation date: %1, Status: %2") 00546 .arg( KGlobal::locale()->formatDate( dt.date(), true ) ) 00547 .arg( status ); 00548 } 00549 else { 00550 return " " + i18n("creation date, status and remark of an OpenPGP key", 00551 "Creation date: %1, Status: %2 (%3)") 00552 .arg( KGlobal::locale()->formatDate( dt.date(), true ) ) 00553 .arg( status ) 00554 .arg( remark ); 00555 } 00556 } 00557 00558 QString KeySelectionDialog::beautifyFingerprint( const QCString& fpr ) const 00559 { 00560 QCString result; 00561 00562 if( 40 == fpr.length() ) { 00563 // convert to this format: 00564 // 0000 1111 2222 3333 4444 5555 6666 7777 8888 9999 00565 result.fill( ' ', 50 ); 00566 memcpy( result.data() , fpr.data() , 4 ); 00567 memcpy( result.data() + 5, fpr.data() + 4, 4 ); 00568 memcpy( result.data() + 10, fpr.data() + 8, 4 ); 00569 memcpy( result.data() + 15, fpr.data() + 12, 4 ); 00570 memcpy( result.data() + 20, fpr.data() + 16, 4 ); 00571 memcpy( result.data() + 26, fpr.data() + 20, 4 ); 00572 memcpy( result.data() + 31, fpr.data() + 24, 4 ); 00573 memcpy( result.data() + 36, fpr.data() + 28, 4 ); 00574 memcpy( result.data() + 41, fpr.data() + 32, 4 ); 00575 memcpy( result.data() + 46, fpr.data() + 36, 4 ); 00576 } 00577 else if( 32 == fpr.length() ) { 00578 // convert to this format: 00579 // 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF 00580 result.fill( ' ', 48 ); 00581 memcpy( result.data() , fpr.data() , 2 ); 00582 memcpy( result.data() + 3, fpr.data() + 2, 2 ); 00583 memcpy( result.data() + 6, fpr.data() + 4, 2 ); 00584 memcpy( result.data() + 9, fpr.data() + 6, 2 ); 00585 memcpy( result.data() + 12, fpr.data() + 8, 2 ); 00586 memcpy( result.data() + 15, fpr.data() + 10, 2 ); 00587 memcpy( result.data() + 18, fpr.data() + 12, 2 ); 00588 memcpy( result.data() + 21, fpr.data() + 14, 2 ); 00589 memcpy( result.data() + 25, fpr.data() + 16, 2 ); 00590 memcpy( result.data() + 28, fpr.data() + 18, 2 ); 00591 memcpy( result.data() + 31, fpr.data() + 20, 2 ); 00592 memcpy( result.data() + 34, fpr.data() + 22, 2 ); 00593 memcpy( result.data() + 37, fpr.data() + 24, 2 ); 00594 memcpy( result.data() + 40, fpr.data() + 26, 2 ); 00595 memcpy( result.data() + 43, fpr.data() + 28, 2 ); 00596 memcpy( result.data() + 46, fpr.data() + 30, 2 ); 00597 } 00598 else { // unknown length of fingerprint 00599 result = fpr; 00600 } 00601 00602 return result; 00603 } 00604 00605 int KeySelectionDialog::keyValidity( const Kpgp::Key *key ) const 00606 { 00607 if( 0 == key ) { 00608 return -1; 00609 } 00610 00611 if( ( mAllowedKeys & EncrSignKeys ) == EncryptionKeys ) { 00612 // only encryption keys are allowed 00613 if( ( mAllowedKeys & ValidKeys ) && !key->isValidEncryptionKey() ) { 00614 // only valid encryption keys are allowed 00615 return -1; 00616 } 00617 else if( !key->canEncrypt() ) { 00618 return -1; 00619 } 00620 } 00621 else if( ( mAllowedKeys & EncrSignKeys ) == SigningKeys ) { 00622 // only signing keys are allowed 00623 if( ( mAllowedKeys & ValidKeys ) && !key->isValidSigningKey() ) { 00624 // only valid signing keys are allowed 00625 return -1; 00626 } 00627 else if( !key->canSign() ) { 00628 return -1; 00629 } 00630 } 00631 else if( ( mAllowedKeys & ValidKeys ) && !key->isValid() ) { 00632 // only valid keys are allowed 00633 return -1; 00634 } 00635 00636 // check the key's trust 00637 int val = 0; 00638 Validity keyTrust = key->keyTrust(); 00639 switch( keyTrust ) { 00640 case KPGP_VALIDITY_NEVER: 00641 val = -1; 00642 break; 00643 case KPGP_VALIDITY_MARGINAL: 00644 case KPGP_VALIDITY_FULL: 00645 case KPGP_VALIDITY_ULTIMATE: 00646 val = 2; 00647 break; 00648 case KPGP_VALIDITY_UNDEFINED: 00649 if( mAllowedKeys & TrustedKeys ) { 00650 // only trusted keys are allowed 00651 val = -1; 00652 } 00653 else { 00654 val = 1; 00655 } 00656 break; 00657 case KPGP_VALIDITY_UNKNOWN: 00658 default: 00659 val = 0; 00660 } 00661 00662 return val; 00663 } 00664 00665 00666 void KeySelectionDialog::updateKeyInfo( const Kpgp::Key* key, 00667 QListViewItem* lvi ) const 00668 { 00669 if( 0 == lvi ) { 00670 return; 00671 } 00672 00673 if( lvi->parent() != 0 ) { 00674 lvi = lvi->parent(); 00675 } 00676 00677 if( 0 == key ) { 00678 // the key doesn't exist anymore -> delete it from the list view 00679 while( lvi->firstChild() ) { 00680 kdDebug(5100) << "Deleting '" << lvi->firstChild()->text( 1 ) << "'\n"; 00681 delete lvi->firstChild(); 00682 } 00683 kdDebug(5100) << "Deleting key 0x" << lvi->text( 0 ) << " (" 00684 << lvi->text( 1 ) << ")\n"; 00685 delete lvi; 00686 lvi = 0; 00687 return; 00688 } 00689 00690 // update the icon for this key 00691 switch( keyValidity( key ) ) { 00692 case 0: // the key's validity can't be determined 00693 lvi->setPixmap( 0, *mKeyUnknownPix ); 00694 break; 00695 case 1: // key is valid but not trusted 00696 lvi->setPixmap( 0, *mKeyValidPix ); 00697 break; 00698 case 2: // key is valid and trusted 00699 lvi->setPixmap( 0, *mKeyGoodPix ); 00700 break; 00701 case -1: // key is invalid 00702 lvi->setPixmap( 0, *mKeyBadPix ); 00703 break; 00704 } 00705 00706 // update the key info for this key 00707 // the key info is identified by a leading space; this shouldn't be 00708 // a problem because User Ids shouldn't start with a space 00709 for( lvi = lvi->firstChild(); lvi; lvi = lvi->nextSibling() ) { 00710 if( lvi->text( 1 ).at(0) == ' ' ) { 00711 lvi->setText( 1, keyInfo( key ) ); 00712 break; 00713 } 00714 } 00715 } 00716 00717 00718 int 00719 KeySelectionDialog::keyAdmissibility( QListViewItem* lvi, 00720 TrustCheckMode trustCheckMode ) const 00721 { 00722 // Return: 00723 // -1 = key must not be chosen, 00724 // 0 = not enough information to decide whether the give key is allowed 00725 // or not, 00726 // 1 = key can be chosen 00727 00728 if( mAllowedKeys == AllKeys ) { 00729 return 1; 00730 } 00731 00732 Kpgp::Module *pgp = Kpgp::Module::getKpgp(); 00733 00734 if( 0 == pgp ) { 00735 return 0; 00736 } 00737 00738 KeyID keyId = getKeyId( lvi ); 00739 Kpgp::Key* key = pgp->publicKey( keyId ); 00740 00741 if( 0 == key ) { 00742 return 0; 00743 } 00744 00745 int val = 0; 00746 if( trustCheckMode == ForceTrustCheck ) { 00747 key = pgp->rereadKey( keyId, true ); 00748 updateKeyInfo( key, lvi ); 00749 val = keyValidity( key ); 00750 } 00751 else { 00752 val = keyValidity( key ); 00753 if( ( trustCheckMode == AllowExpensiveTrustCheck ) && ( 0 == val ) ) { 00754 key = pgp->rereadKey( keyId, true ); 00755 updateKeyInfo( key, lvi ); 00756 val = keyValidity( key ); 00757 } 00758 } 00759 00760 switch( val ) { 00761 case -1: // key is not usable 00762 return -1; 00763 break; 00764 case 0: // key status unknown 00765 return 0; 00766 break; 00767 case 1: // key is valid, but untrusted 00768 if( mAllowedKeys & TrustedKeys ) { 00769 // only trusted keys are allowed 00770 return -1; 00771 } 00772 return 1; 00773 break; 00774 case 2: // key is trusted 00775 return 1; 00776 break; 00777 default: 00778 kdDebug( 5100 ) << "Error: Invalid key status value.\n"; 00779 } 00780 00781 return 0; 00782 } 00783 00784 00785 KeyID 00786 KeySelectionDialog::getKeyId( const QListViewItem* lvi ) const 00787 { 00788 KeyID keyId; 00789 00790 if( 0 != lvi ) { 00791 if( 0 != lvi->parent() ) { 00792 keyId = lvi->parent()->text(0).local8Bit(); 00793 } 00794 else { 00795 keyId = lvi->text(0).local8Bit(); 00796 } 00797 } 00798 00799 return keyId; 00800 } 00801 00802 00803 void KeySelectionDialog::slotRereadKeys() 00804 { 00805 Kpgp::Module *pgp = Kpgp::Module::getKpgp(); 00806 00807 if( 0 == pgp ) { 00808 return; 00809 } 00810 00811 KeyList keys; 00812 00813 if( PublicKeys & mAllowedKeys ) { 00814 pgp->readPublicKeys( true ); 00815 keys = pgp->publicKeys(); 00816 } 00817 else { 00818 pgp->readSecretKeys( true ); 00819 keys = pgp->secretKeys(); 00820 } 00821 00822 // save the current position of the contents 00823 int offsetY = mListView->contentsY(); 00824 00825 if( mListView->isMultiSelection() ) { 00826 disconnect( mListView, SIGNAL( selectionChanged() ), 00827 this, SLOT( slotSelectionChanged() ) ); 00828 } 00829 else { 00830 disconnect( mListView, SIGNAL( selectionChanged( QListViewItem * ) ), 00831 this, SLOT( slotSelectionChanged( QListViewItem * ) ) ); 00832 } 00833 00834 initKeylist( keys, KeyIDList( mKeyIds ) ); 00835 slotFilter(); 00836 00837 if( mListView->isMultiSelection() ) { 00838 connect( mListView, SIGNAL( selectionChanged() ), 00839 this, SLOT( slotSelectionChanged() ) ); 00840 slotSelectionChanged(); 00841 } 00842 else { 00843 connect( mListView, SIGNAL( selectionChanged( QListViewItem * ) ), 00844 this, SLOT( slotSelectionChanged( QListViewItem * ) ) ); 00845 } 00846 00847 // restore the saved position of the contents 00848 mListView->setContentsPos( 0, offsetY ); 00849 } 00850 00851 00852 void KeySelectionDialog::slotSelectionChanged( QListViewItem * lvi ) 00853 { 00854 slotCheckSelection( lvi ); 00855 } 00856 00857 00858 void KeySelectionDialog::slotSelectionChanged() 00859 { 00860 kdDebug(5100) << "KeySelectionDialog::slotSelectionChanged()\n"; 00861 00862 // (re)start the check selection timer. Checking the selection is delayed 00863 // because else drag-selection doesn't work very good (checking key trust 00864 // is slow). 00865 mCheckSelectionTimer->start( sCheckSelectionDelay ); 00866 } 00867 00868 00869 void KeySelectionDialog::slotCheckSelection( QListViewItem* plvi /* = 0 */ ) 00870 { 00871 kdDebug(5100) << "KeySelectionDialog::slotCheckSelection()\n"; 00872 00873 if( !mListView->isMultiSelection() ) { 00874 mKeyIds.clear(); 00875 KeyID keyId = getKeyId( plvi ); 00876 if( !keyId.isEmpty() ) { 00877 mKeyIds.append( keyId ); 00878 enableButtonOK( 1 == keyAdmissibility( plvi, AllowExpensiveTrustCheck ) ); 00879 } 00880 else { 00881 enableButtonOK( false ); 00882 } 00883 } 00884 else { 00885 mCheckSelectionTimer->stop(); 00886 00887 // As we might change the selection, we have to disconnect the slot 00888 // to prevent recursion 00889 disconnect( mListView, SIGNAL( selectionChanged() ), 00890 this, SLOT( slotSelectionChanged() ) ); 00891 00892 KeyIDList newKeyIdList; 00893 QValueList<QListViewItem*> keysToBeChecked; 00894 00895 bool keysAllowed = true; 00896 enum { UNKNOWN, SELECTED, DESELECTED } userAction = UNKNOWN; 00897 // Iterate over the tree to find selected keys. 00898 for( QListViewItem *lvi = mListView->firstChild(); 00899 0 != lvi; 00900 lvi = lvi->nextSibling() ) { 00901 // We make sure that either all items belonging to a key are selected 00902 // or unselected. As it's possible to select/deselect multiple keys at 00903 // once in extended selection mode we have to figure out whether the user 00904 // selected or deselected keys. 00905 00906 // First count the selected items of this key 00907 int itemCount = 1 + lvi->childCount(); 00908 int selectedCount = lvi->isSelected() ? 1 : 0; 00909 for( QListViewItem *clvi = lvi->firstChild(); 00910 0 != clvi; 00911 clvi = clvi->nextSibling() ) { 00912 if( clvi->isSelected() ) { 00913 ++selectedCount; 00914 } 00915 } 00916 00917 if( userAction == UNKNOWN ) { 00918 // Figure out whether the user selected or deselected this key 00919 // Remark: A selected count of 0 doesn't mean anything since in 00920 // extended selection mode a normal left click deselects 00921 // the not clicked items. 00922 if( 0 < selectedCount ) { 00923 if( -1 == mKeyIds.findIndex( lvi->text(0).local8Bit() ) ) { 00924 // some items of this key are selected and the key wasn't selected 00925 // before => the user selected something 00926 kdDebug(5100) << "selectedCount: "<<selectedCount<<"/"<<itemCount 00927 <<" --- User selected key "<<lvi->text(0)<<endl; 00928 userAction = SELECTED; 00929 } 00930 else if( ( itemCount > selectedCount ) && 00931 ( -1 != mKeyIds.findIndex( lvi->text(0).local8Bit() ) ) ) { 00932 // some items of this key are unselected and the key was selected 00933 // before => the user deselected something 00934 kdDebug(5100) << "selectedCount: "<<selectedCount<<"/"<<itemCount 00935 <<" --- User deselected key "<<lvi->text(0)<<endl; 00936 userAction = DESELECTED; 00937 } 00938 } 00939 } 00940 if( itemCount == selectedCount ) { 00941 // add key to the list of selected keys 00942 KeyID keyId = lvi->text(0).local8Bit(); 00943 newKeyIdList.append( keyId ); 00944 int admissibility = keyAdmissibility( lvi, NoExpensiveTrustCheck ); 00945 if( -1 == admissibility ) { 00946 keysAllowed = false; 00947 } 00948 else if ( 0 == admissibility ) { 00949 keysToBeChecked.append( lvi ); 00950 } 00951 } 00952 else if( 0 < selectedCount ) { 00953 // not all items of this key are selected or unselected. change this 00954 // according to the user's action 00955 if( userAction == SELECTED ) { 00956 // select all items of this key 00957 mListView->setSelected( lvi, true ); 00958 for( QListViewItem *clvi = lvi->firstChild(); 00959 0 != clvi; 00960 clvi = clvi->nextSibling() ) { 00961 mListView->setSelected( clvi, true ); 00962 } 00963 // add key to the list of selected keys 00964 KeyID keyId = lvi->text(0).local8Bit(); 00965 newKeyIdList.append( keyId ); 00966 int admissibility = keyAdmissibility( lvi, NoExpensiveTrustCheck ); 00967 if( -1 == admissibility ) { 00968 keysAllowed = false; 00969 } 00970 else if ( 0 == admissibility ) { 00971 keysToBeChecked.append( lvi ); 00972 } 00973 } 00974 else { // userAction == DESELECTED 00975 // deselect all items of this key 00976 mListView->setSelected( lvi, false ); 00977 for( QListViewItem *clvi = lvi->firstChild(); 00978 0 != clvi; 00979 clvi = clvi->nextSibling() ) { 00980 mListView->setSelected( clvi, false ); 00981 } 00982 } 00983 } 00984 } 00985 kdDebug(5100) << "Selected keys: " << newKeyIdList.toStringList().join(", ") << endl; 00986 mKeyIds = newKeyIdList; 00987 if( !keysToBeChecked.isEmpty() ) { 00988 keysAllowed &= checkKeys( keysToBeChecked ); 00989 } 00990 enableButtonOK( keysAllowed ); 00991 00992 connect( mListView, SIGNAL( selectionChanged() ), 00993 this, SLOT( slotSelectionChanged() ) ); 00994 } 00995 } 00996 00997 00998 bool KeySelectionDialog::checkKeys( const QValueList<QListViewItem*>& keys ) const 00999 { 01000 KProgressDialog* pProgressDlg = 0; 01001 bool keysAllowed = true; 01002 kdDebug(5100) << "Checking keys...\n"; 01003 01004 pProgressDlg = new KProgressDialog( 0, 0, i18n("Checking Keys"), 01005 i18n("Checking key 0xMMMMMMMM..."), 01006 true ); 01007 pProgressDlg->setAllowCancel( false ); 01008 pProgressDlg->progressBar()->setTotalSteps( keys.count() ); 01009 pProgressDlg->setMinimumDuration( 1000 ); 01010 pProgressDlg->show(); 01011 01012 for( QValueList<QListViewItem*>::ConstIterator it = keys.begin(); 01013 it != keys.end(); 01014 ++it ) { 01015 kdDebug(5100) << "Checking key 0x" << getKeyId( *it ) << "...\n"; 01016 pProgressDlg->setLabel( i18n("Checking key 0x%1...") 01017 .arg( getKeyId( *it ) ) ); 01018 kapp->processEvents(); 01019 keysAllowed &= ( -1 != keyAdmissibility( *it, AllowExpensiveTrustCheck ) ); 01020 pProgressDlg->progressBar()->advance( 1 ); 01021 kapp->processEvents(); 01022 } 01023 01024 delete pProgressDlg; 01025 pProgressDlg = 0; 01026 01027 return keysAllowed; 01028 } 01029 01030 01031 void KeySelectionDialog::slotRMB( QListViewItem* lvi, const QPoint& pos, int ) 01032 { 01033 if( !lvi ) { 01034 return; 01035 } 01036 01037 mCurrentContextMenuItem = lvi; 01038 01039 QPopupMenu menu(this); 01040 menu.insertItem( i18n( "Recheck Key" ), this, SLOT( slotRecheckKey() ) ); 01041 menu.exec( pos ); 01042 } 01043 01044 01045 void KeySelectionDialog::slotRecheckKey() 01046 { 01047 if( 0 != mCurrentContextMenuItem ) { 01048 // force rereading the key 01049 keyAdmissibility( mCurrentContextMenuItem, ForceTrustCheck ); 01050 // recheck the selection 01051 slotCheckSelection( mCurrentContextMenuItem ); 01052 } 01053 } 01054 01055 void KeySelectionDialog::slotOk() 01056 { 01057 if( mCheckSelectionTimer->isActive() ) { 01058 slotCheckSelection(); 01059 } 01060 mStartSearchTimer->stop(); 01061 accept(); 01062 } 01063 01064 01065 void KeySelectionDialog::slotCancel() 01066 { 01067 mCheckSelectionTimer->stop(); 01068 mStartSearchTimer->stop(); 01069 mKeyIds.clear(); 01070 reject(); 01071 } 01072 01073 void KeySelectionDialog::slotSearch( const QString & text ) 01074 { 01075 mSearchText = text.stripWhiteSpace().upper(); 01076 mStartSearchTimer->start( sCheckSelectionDelay, true /*single-shot*/ ); 01077 } 01078 01079 void KeySelectionDialog::slotFilter() 01080 { 01081 if ( mSearchText.isEmpty() ) { 01082 showAllItems(); 01083 return; 01084 } 01085 01086 // OK, so we need to filter: 01087 QRegExp keyIdRegExp( "(?:0x)?[A-F0-9]{1,8}", false /*case-insens.*/ ); 01088 if ( keyIdRegExp.exactMatch( mSearchText ) ) { 01089 if ( mSearchText.startsWith( "0X" ) ) 01090 // search for keyID only: 01091 filterByKeyID( mSearchText.mid( 2 ) ); 01092 else 01093 // search for UID and keyID: 01094 filterByKeyIDOrUID( mSearchText ); 01095 } else { 01096 // search in UID: 01097 filterByUID( mSearchText ); 01098 } 01099 } 01100 01101 void KeySelectionDialog::filterByKeyID( const QString & keyID ) 01102 { 01103 assert( keyID.length() <= 8 ); 01104 assert( !keyID.isEmpty() ); // regexp in slotFilter should prevent these 01105 if ( keyID.isEmpty() ) 01106 showAllItems(); 01107 else 01108 for ( QListViewItem * item = mListView->firstChild() ; item ; item = item->nextSibling() ) 01109 item->setVisible( item->text( 0 ).upper().startsWith( keyID ) ); 01110 } 01111 01112 void KeySelectionDialog::filterByKeyIDOrUID( const QString & str ) 01113 { 01114 assert( !str.isEmpty() ); 01115 01116 // match beginnings of words: 01117 QRegExp rx( "\\b" + QRegExp::escape( str ), false ); 01118 01119 for ( QListViewItem * item = mListView->firstChild() ; item ; item = item->nextSibling() ) 01120 item->setVisible( item->text( 0 ).upper().startsWith( str ) 01121 || rx.search( item->text( 1 ) ) >= 0 01122 || anyChildMatches( item, rx ) ); 01123 01124 } 01125 01126 void KeySelectionDialog::filterByUID( const QString & str ) 01127 { 01128 assert( !str.isEmpty() ); 01129 01130 // match beginnings of words: 01131 QRegExp rx( "\\b" + QRegExp::escape( str ), false ); 01132 01133 for ( QListViewItem * item = mListView->firstChild() ; item ; item = item->nextSibling() ) 01134 item->setVisible( rx.search( item->text( 1 ) ) >= 0 01135 || anyChildMatches( item, rx ) ); 01136 } 01137 01138 01139 bool KeySelectionDialog::anyChildMatches( const QListViewItem * item, QRegExp & rx ) const 01140 { 01141 if ( !item ) 01142 return false; 01143 01144 QListViewItem * stop = item->nextSibling(); // It's OK if stop is NULL... 01145 01146 for ( QListViewItemIterator it( item->firstChild() ) ; it.current() && it.current() != stop ; ++it ) 01147 if ( rx.search( it.current()->text( 1 ) ) >= 0 ) { 01148 //item->setOpen( true ); // do we want that? 01149 return true; 01150 } 01151 return false; 01152 } 01153 01154 void KeySelectionDialog::showAllItems() 01155 { 01156 for ( QListViewItem * item = mListView->firstChild() ; item ; item = item->nextSibling() ) 01157 item->setVisible( true ); 01158 } 01159 01160 // ------------------------------------------------------------------------ 01161 KeyRequester::KeyRequester( QWidget * parent, bool multipleKeys, 01162 unsigned int allowedKeys, const char * name ) 01163 : QWidget( parent, name ), 01164 mDialogCaption( i18n("OpenPGP Key Selection") ), 01165 mDialogMessage( i18n("Please select an OpenPGP key to use.") ), 01166 mMulti( multipleKeys ), 01167 mAllowedKeys( allowedKeys ), 01168 d( 0 ) 01169 { 01170 QHBoxLayout * hlay = new QHBoxLayout( this, 0, KDialog::spacingHint() ); 01171 01172 // the label where the key id is to be displayed: 01173 mLabel = new QLabel( this ); 01174 mLabel->setFrameStyle( QFrame::Panel | QFrame::Sunken ); 01175 01176 // the button to unset any key: 01177 mEraseButton = new QPushButton( this ); 01178 mEraseButton->setAutoDefault( false ); 01179 mEraseButton->setSizePolicy( QSizePolicy( QSizePolicy::Minimum, 01180 QSizePolicy::Minimum ) ); 01181 mEraseButton->setPixmap( SmallIcon( "clear_left" ) ); 01182 QToolTip::add( mEraseButton, i18n("Clear") ); 01183 01184 // the button to call the KeySelectionDialog: 01185 mDialogButton = new QPushButton( i18n("Change..."), this ); 01186 mDialogButton->setAutoDefault( false ); 01187 01188 hlay->addWidget( mLabel, 1 ); 01189 hlay->addWidget( mEraseButton ); 01190 hlay->addWidget( mDialogButton ); 01191 01192 connect( mEraseButton, SIGNAL(clicked()), mLabel, SLOT(clear()) ); 01193 connect( mDialogButton, SIGNAL(clicked()), SLOT(slotDialogButtonClicked()) ); 01194 01195 setSizePolicy( QSizePolicy( QSizePolicy::MinimumExpanding, 01196 QSizePolicy::Fixed ) ); 01197 } 01198 01199 KeyRequester::~KeyRequester() { 01200 01201 } 01202 01203 KeyIDList KeyRequester::keyIDs() const { 01204 return mKeys; 01205 } 01206 01207 void KeyRequester::setKeyIDs( const KeyIDList & keyIDs ) { 01208 mKeys = keyIDs; 01209 if ( mKeys.empty() ) { 01210 mLabel->clear(); 01211 return; 01212 } 01213 if ( mKeys.size() > 1 ) 01214 setMultipleKeysEnabled( true ); 01215 01216 QString s = mKeys.toStringList().join(", "); 01217 01218 mLabel->setText( s ); 01219 QToolTip::remove( mLabel ); 01220 QToolTip::add( mLabel, s ); 01221 } 01222 01223 void KeyRequester::slotDialogButtonClicked() { 01224 Module * pgp = Module::getKpgp(); 01225 01226 if ( !pgp ) { 01227 kdWarning() << "Kpgp::KeyRequester::slotDialogButtonClicked(): No pgp module found!" << endl; 01228 return; 01229 } 01230 01231 setKeyIDs( keyRequestHook( pgp ) ); 01232 } 01233 01234 void KeyRequester::setDialogCaption( const QString & caption ) { 01235 mDialogCaption = caption; 01236 } 01237 01238 void KeyRequester::setDialogMessage( const QString & msg ) { 01239 mDialogMessage = msg; 01240 } 01241 01242 bool KeyRequester::isMultipleKeysEnabled() const { 01243 return mMulti; 01244 } 01245 01246 void KeyRequester::setMultipleKeysEnabled( bool multi ) { 01247 if ( multi == mMulti ) return; 01248 01249 if ( !multi && mKeys.size() > 1 ) 01250 mKeys.erase( ++mKeys.begin(), mKeys.end() ); 01251 01252 mMulti = multi; 01253 } 01254 01255 int KeyRequester::allowedKeys() const { 01256 return mAllowedKeys; 01257 } 01258 01259 void KeyRequester::setAllowedKeys( int allowedKeys ) { 01260 mAllowedKeys = allowedKeys; 01261 } 01262 01263 01264 PublicKeyRequester::PublicKeyRequester( QWidget * parent, bool multi, 01265 unsigned int allowed, const char * name ) 01266 : KeyRequester( parent, multi, allowed & ~SecretKeys, name ) 01267 { 01268 01269 } 01270 01271 PublicKeyRequester::~PublicKeyRequester() { 01272 01273 } 01274 01275 KeyIDList PublicKeyRequester::keyRequestHook( Module * pgp ) const { 01276 assert( pgp ); 01277 return pgp->selectPublicKeys( mDialogCaption, mDialogMessage, mKeys, QString::null, mAllowedKeys ); 01278 } 01279 01280 SecretKeyRequester::SecretKeyRequester( QWidget * parent, bool multi, 01281 unsigned int allowed, const char * name ) 01282 : KeyRequester( parent, multi, allowed & ~PublicKeys, name ) 01283 { 01284 01285 } 01286 01287 SecretKeyRequester::~SecretKeyRequester() { 01288 01289 } 01290 01291 KeyIDList SecretKeyRequester::keyRequestHook( Module * pgp ) const { 01292 assert( pgp ); 01293 01294 KeyID keyID = mKeys.first(); 01295 keyID = pgp->selectSecretKey( mDialogCaption, mDialogMessage, keyID ); 01296 01297 return KeyIDList() << keyID; 01298 } 01299 01300 01301 01302 // ------------------------------------------------------------------------ 01303 KeyApprovalDialog::KeyApprovalDialog( const QStringList& addresses, 01304 const QValueVector<KeyIDList>& keyIDs, 01305 const int allowedKeys, 01306 QWidget *parent, const char *name, 01307 bool modal ) 01308 : KDialogBase( parent, name, modal, i18n("Encryption Key Approval"), 01309 Ok|Cancel, Ok ), 01310 mKeys( keyIDs ), 01311 mAllowedKeys( allowedKeys ), 01312 mPrefsChanged( false ) 01313 { 01314 Kpgp::Module *pgp = Kpgp::Module::getKpgp(); 01315 01316 if( pgp == 0 ) 01317 return; 01318 01319 // ##### error handling 01320 // if( addresses.isEmpty() || keyList.isEmpty() || 01321 // addresses.count()+1 != keyList.count() ) 01322 // do something; 01323 01324 QFrame *page = makeMainWidget(); 01325 QVBoxLayout *topLayout = new QVBoxLayout( page, 0, KDialog::spacingHint() ); 01326 01327 QLabel *label = new QLabel( i18n("The following keys will be used for " 01328 "encryption:"), 01329 page ); 01330 topLayout->addWidget( label ); 01331 01332 QScrollView* sv = new QScrollView( page ); 01333 sv->setResizePolicy( QScrollView::AutoOneFit ); 01334 topLayout->addWidget( sv ); 01335 QVBox* bigvbox = new QVBox( sv->viewport() ); 01336 bigvbox->setMargin( KDialog::marginHint() ); 01337 bigvbox->setSpacing( KDialog::spacingHint() ); 01338 sv->addChild( bigvbox ); 01339 01340 QButtonGroup *mChangeButtonGroup = new QButtonGroup( bigvbox ); 01341 mChangeButtonGroup->hide(); 01342 mAddressLabels.resize( addresses.count() ); 01343 mKeyIdsLabels.resize( keyIDs.size() ); 01344 //mKeyIdListBoxes.resize( keyIDs.size() ); 01345 mEncrPrefCombos.resize( addresses.count() ); 01346 01347 // the sender's key 01348 if( pgp->encryptToSelf() ) { 01349 mEncryptToSelf = 1; 01350 QHBox* hbox = new QHBox( bigvbox ); 01351 new QLabel( i18n("Your keys:"), hbox ); 01352 QLabel* keyidsL = new QLabel( hbox ); 01353 if( keyIDs[0].isEmpty() ) { 01354 keyidsL->setText( i18n("<none> means 'no key'", "<none>") ); 01355 } 01356 else { 01357 keyidsL->setText( "0x" + keyIDs[0].toStringList().join( "\n0x" ) ); 01358 } 01359 keyidsL->setFrameStyle( QFrame::Panel | QFrame::Sunken ); 01360 /* 01361 QListBox* keyidLB = new QListBox( hbox ); 01362 if( keyIDs[0].isEmpty() ) { 01363 keyidLB->insertItem( i18n("<none>") ); 01364 } 01365 else { 01366 keyidLB->insertStringList( keyIDs[0].toStringList() ); 01367 } 01368 keyidLB->setSelectionMode( QListBox::NoSelection ); 01369 keyidLB->setFrameStyle( QFrame::Panel | QFrame::Sunken ); 01370 */ 01371 QPushButton *button = new QPushButton( i18n("Change..."), hbox ); 01372 mChangeButtonGroup->insert( button ); 01373 button->setAutoDefault( false ); 01374 hbox->setStretchFactor( keyidsL, 10 ); 01375 mKeyIdsLabels.insert( 0, keyidsL ); 01376 //hbox->setStretchFactor( keyidLB, 10 ); 01377 //mKeyIdListBoxes.insert( 0, keyidLB ); 01378 01379 new KSeparator( Horizontal, bigvbox ); 01380 } 01381 else { 01382 mEncryptToSelf = 0; 01383 // insert dummy KeyIdListBox 01384 mKeyIdsLabels.insert( 0, 0 ); 01385 //mKeyIdListBoxes.insert( 0, 0 ); 01386 } 01387 01388 QStringList::ConstIterator ait; 01389 QValueVector<KeyIDList>::const_iterator kit; 01390 int i; 01391 for( ait = addresses.begin(), kit = keyIDs.begin(), i = 0; 01392 ( ait != addresses.end() ) && ( kit != keyIDs.end() ); 01393 ++ait, ++kit, ++i ) { 01394 if( i == 0 ) { 01395 ++kit; // skip the sender's key id 01396 } 01397 else { 01398 new KSeparator( Horizontal, bigvbox ); 01399 } 01400 01401 QHBox *hbox = new QHBox( bigvbox ); 01402 new QLabel( i18n("Recipient:"), hbox ); 01403 QLabel *addressL = new QLabel( *ait, hbox ); 01404 hbox->setStretchFactor( addressL, 10 ); 01405 mAddressLabels.insert( i, addressL ); 01406 01407 hbox = new QHBox( bigvbox ); 01408 new QLabel( i18n("Encryption keys:"), hbox ); 01409 QLabel* keyidsL = new QLabel( hbox ); 01410 if( (*kit).isEmpty() ) { 01411 keyidsL->setText( i18n("<none> means 'no key'", "<none>") ); 01412 } 01413 else { 01414 keyidsL->setText( "0x" + (*kit).toStringList().join( "\n0x" ) ); 01415 } 01416 keyidsL->setFrameStyle( QFrame::Panel | QFrame::Sunken ); 01417 /* 01418 QListBox* keyidLB = new QListBox( hbox ); 01419 if( (*kit).isEmpty() ) { 01420 keyidLB->insertItem( i18n("<none>") ); 01421 } 01422 else { 01423 keyidLB->insertStringList( (*kit).toStringList() ); 01424 } 01425 keyidLB->setSelectionMode( QListBox::NoSelection ); 01426 keyidLB->setFrameStyle( QFrame::Panel | QFrame::Sunken ); 01427 */ 01428 QPushButton *button = new QPushButton( i18n("Change..."), hbox ); 01429 mChangeButtonGroup->insert( button ); 01430 button->setAutoDefault( false ); 01431 hbox->setStretchFactor( keyidsL, 10 ); 01432 mKeyIdsLabels.insert( i + 1, keyidsL ); 01433 //hbox->setStretchFactor( keyidLB, 10 ); 01434 //mKeyIdListBoxes.insert( i + 1, keyidLB ); 01435 01436 hbox = new QHBox( bigvbox ); 01437 new QLabel( i18n("Encryption preference:"), hbox ); 01438 QComboBox *encrPrefCombo = new QComboBox( hbox ); 01439 encrPrefCombo->insertItem( i18n("<none>") ); 01440 encrPrefCombo->insertItem( i18n("Never Encrypt with This Key") ); 01441 encrPrefCombo->insertItem( i18n("Always Encrypt with This Key") ); 01442 encrPrefCombo->insertItem( i18n("Encrypt Whenever Encryption is Possible") ); 01443 encrPrefCombo->insertItem( i18n("Always Ask") ); 01444 encrPrefCombo->insertItem( i18n("Ask Whenever Encryption is Possible") ); 01445 01446 EncryptPref encrPref = pgp->encryptionPreference( *ait ); 01447 switch( encrPref ) { 01448 case NeverEncrypt: 01449 encrPrefCombo->setCurrentItem( 1 ); 01450 break; 01451 case AlwaysEncrypt: 01452 encrPrefCombo->setCurrentItem( 2 ); 01453 break; 01454 case AlwaysEncryptIfPossible: 01455 encrPrefCombo->setCurrentItem( 3 ); 01456 break; 01457 case AlwaysAskForEncryption: 01458 encrPrefCombo->setCurrentItem( 4 ); 01459 break; 01460 case AskWheneverPossible: 01461 encrPrefCombo->setCurrentItem( 5 ); 01462 break; 01463 default: 01464 encrPrefCombo->setCurrentItem( 0 ); 01465 } 01466 connect( encrPrefCombo, SIGNAL(activated(int)), 01467 this, SLOT(slotPrefsChanged(int)) ); 01468 mEncrPrefCombos.insert( i, encrPrefCombo ); 01469 } 01470 connect( mChangeButtonGroup, SIGNAL(clicked(int)), 01471 this, SLOT(slotChangeEncryptionKey(int)) ); 01472 01473 // calculate the optimal width for the dialog 01474 int dialogWidth = marginHint() 01475 + sv->frameWidth() 01476 + bigvbox->sizeHint().width() 01477 + sv->verticalScrollBar()->sizeHint().width() 01478 + sv->frameWidth() 01479 + marginHint() 01480 + 2; 01481 // calculate the optimal height for the dialog 01482 int dialogHeight = marginHint() 01483 + label->sizeHint().height() 01484 + topLayout->spacing() 01485 + sv->frameWidth() 01486 + bigvbox->sizeHint().height() 01487 + sv->horizontalScrollBar()->sizeHint().height() 01488 + sv->frameWidth() 01489 + topLayout->spacing() 01490 + actionButton( KDialogBase::Cancel )->sizeHint().height() 01491 + marginHint() 01492 + 2; 01493 // don't make the dialog too large 01494 QRect desk = KGlobalSettings::desktopGeometry(this); 01495 int screenWidth = desk.width(); 01496 if( dialogWidth > 3*screenWidth/4 ) 01497 dialogWidth = 3*screenWidth/4; 01498 int screenHeight = desk.height(); 01499 if( dialogHeight > 7*screenHeight/8 ) 01500 dialogHeight = 7*screenHeight/8; 01501 01502 setInitialSize( QSize( dialogWidth, dialogHeight ) ); 01503 } 01504 01505 void 01506 KeyApprovalDialog::slotChangeEncryptionKey( int nr ) 01507 { 01508 Kpgp::Module *pgp = Kpgp::Module::getKpgp(); 01509 01510 kdDebug(5100)<<"Key approval dialog size is " 01511 <<width()<<"x"<<height()<<endl; 01512 01513 if( pgp == 0 ) 01514 return; 01515 01516 if( !mEncryptToSelf ) 01517 nr++; 01518 KeyIDList keyIds = mKeys[nr]; 01519 if( nr == 0 ) { 01520 keyIds = pgp->selectPublicKeys( i18n("Encryption Key Selection"), 01521 i18n("if in your language something like " 01522 "'key(s)' isn't possible please " 01523 "use the plural in the translation", 01524 "Select the key(s) which should " 01525 "be used to encrypt the message " 01526 "to yourself."), 01527 keyIds, 01528 "", 01529 mAllowedKeys ); 01530 } 01531 else { 01532 keyIds = pgp->selectPublicKeys( i18n("Encryption Key Selection"), 01533 i18n("if in your language something like " 01534 "'key(s)' isn't possible please " 01535 "use the plural in the translation", 01536 "Select the key(s) which should " 01537 "be used to encrypt the message " 01538 "for\n%1") 01539 .arg( mAddressLabels[nr-1]->text() ), 01540 keyIds, 01541 mAddressLabels[nr-1]->text(), 01542 mAllowedKeys ); 01543 } 01544 if( !keyIds.isEmpty() ) { 01545 mKeys[nr] = keyIds; 01546 QLabel* keyidsL = mKeyIdsLabels[nr]; 01547 keyidsL->setText( "0x" + keyIds.toStringList().join( "\n0x" ) ); 01548 /* 01549 QListBox* qlb = mKeyIdListBoxes[nr]; 01550 qlb->clear(); 01551 qlb->insertStringList( keyIds.toStringList() ); 01552 */ 01553 } 01554 } 01555 01556 01557 void 01558 KeyApprovalDialog::slotOk() 01559 { 01560 Kpgp::Module *pgp = Kpgp::Module::getKpgp(); 01561 01562 if( pgp == 0 ) { 01563 accept(); 01564 return; 01565 } 01566 01567 if( mPrefsChanged ) { 01568 // store the changed preferences 01569 for( unsigned int i = 0; i < mAddressLabels.size(); i++ ) { 01570 // traverse all Address and Encryption Preference widgets 01571 EncryptPref encrPref; 01572 switch( mEncrPrefCombos[i]->currentItem() ) { 01573 case 1: 01574 encrPref = NeverEncrypt; 01575 break; 01576 case 2: 01577 encrPref = AlwaysEncrypt; 01578 break; 01579 case 3: 01580 encrPref = AlwaysEncryptIfPossible; 01581 break; 01582 case 4: 01583 encrPref = AlwaysAskForEncryption; 01584 break; 01585 case 5: 01586 encrPref = AskWheneverPossible; 01587 break; 01588 default: 01589 case 0: 01590 encrPref = UnknownEncryptPref; 01591 } 01592 pgp->setEncryptionPreference( mAddressLabels[i]->text(), encrPref ); 01593 } 01594 } 01595 01596 accept(); 01597 } 01598 01599 01600 void 01601 KeyApprovalDialog::slotCancel() 01602 { 01603 reject(); 01604 } 01605 01606 01607 01608 // ------------------------------------------------------------------------ 01609 CipherTextDialog::CipherTextDialog( const QCString & text, 01610 const QCString & charset, QWidget *parent, 01611 const char *name, bool modal ) 01612 :KDialogBase( parent, name, modal, i18n("OpenPGP Information"), Ok|Cancel, Ok) 01613 { 01614 // FIXME (post KDE2.2): show some more info, e.g. the output of GnuPG/PGP 01615 QFrame *page = makeMainWidget(); 01616 QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() ); 01617 01618 QLabel *label = new QLabel( page ); 01619 label->setText(i18n("Result of the last encryption/sign operation:")); 01620 topLayout->addWidget( label ); 01621 01622 mEditBox = new QMultiLineEdit( page ); 01623 mEditBox->setReadOnly(true); 01624 topLayout->addWidget( mEditBox, 10 ); 01625 01626 QString unicodeText; 01627 if (charset.isEmpty()) 01628 unicodeText = QString::fromLocal8Bit(text.data()); 01629 else { 01630 bool ok=true; 01631 QTextCodec *codec = KGlobal::charsets()->codecForName(charset, ok); 01632 if(!ok) 01633 unicodeText = QString::fromLocal8Bit(text.data()); 01634 else 01635 unicodeText = codec->toUnicode(text.data(), text.length()); 01636 } 01637 01638 mEditBox->setText(unicodeText); 01639 01640 setMinimumSize(); 01641 } 01642 01643 void CipherTextDialog::setMinimumSize() 01644 { 01645 // this seems to force a layout of the entire document, so we get a 01646 // a proper contentsWidth(). Is there a better way? 01647 for ( int i = 0; i < mEditBox->paragraphs(); i++ ) 01648 (void) mEditBox->paragraphRect( i ); 01649 01650 mEditBox->setMinimumHeight( mEditBox->fontMetrics().lineSpacing() * 25 ); 01651 01652 int textWidth = mEditBox->contentsWidth() + 30; 01653 01654 01655 #if KDE_IS_VERSION( 3, 1, 90 ) 01656 int maxWidth = KGlobalSettings::desktopGeometry(parentWidget()).width()-100; 01657 #else 01658 KConfig gc("kdeglobals", false, false); 01659 gc.setGroup("Windows"); 01660 int maxWidth; 01661 if (QApplication::desktop()->isVirtualDesktop() && 01662 gc.readBoolEntry("XineramaEnabled", true) && 01663 gc.readBoolEntry("XineramaPlacementEnabled", true)) { 01664 maxWidth = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(parentWidget())).width()-100; 01665 } else { 01666 maxWidth = QApplication::desktop()->geometry().width()-100; 01667 } 01668 #endif 01669 01670 mEditBox->setMinimumWidth( QMIN( textWidth, maxWidth ) ); 01671 } 01672 01673 void KeyRequester::virtual_hook( int, void* ) {} 01674 01675 void PublicKeyRequester::virtual_hook( int id, void* data ) { 01676 base::virtual_hook( id, data ); 01677 } 01678 01679 void SecretKeyRequester::virtual_hook( int id, void* data ) { 01680 base::virtual_hook( id, data ); 01681 } 01682 01683 } // namespace Kpgp 01684 01685 01686 01687 #include "kpgpui.moc"
KDE Logo
This file is part of the documentation for libkdenetwork Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Oct 21 19:46:17 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003