libkpgp

kpgpui.cpp
1/*
2 kpgpui.cpp
3
4 Copyright (C) 2001,2002 the KPGP authors
5 See file AUTHORS.kpgp for details
6
7 This file is part of KPGP, the KDE PGP/GnuPG support library.
8
9 KPGP is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
19//#include <stdio.h>
20
21#include <tqvgroupbox.h>
22#include <tqvbox.h>
23#include <tqlabel.h>
24#include <tqwhatsthis.h>
25#include <tqtooltip.h>
26#include <tqapplication.h>
27#include <tqtextcodec.h>
28#include <tqdatetime.h>
29#include <tqpixmap.h>
30#include <tqlayout.h>
31#include <tqtimer.h>
32#include <tqpopupmenu.h>
33#include <tqregexp.h>
34
35#include <tdelocale.h>
36#include <kpassdlg.h>
37#include <kcharsets.h>
38#include <kseparator.h>
39#include <kiconloader.h>
40#include <tdelistview.h>
41#include <tdeconfigbase.h>
42#include <tdeconfig.h>
43#include <kprogress.h>
44#include <tdeapplication.h>
45#include <twin.h>
46#if KDE_IS_VERSION( 3, 1, 90 )
47#include <tdeglobalsettings.h>
48#endif
49
50#include "kpgp.h"
51#include "kpgpui.h"
52#include "kpgpkey.h"
53
54#include <assert.h>
55#include <string.h> // for memcpy(3)
56
57const int Kpgp::KeySelectionDialog::sCheckSelectionDelay = 250;
58
59namespace Kpgp {
60
61PassphraseDialog::PassphraseDialog( TQWidget *parent,
62 const TQString &caption, bool modal,
63 const TQString &keyID )
64 :KDialogBase( parent, 0, modal, caption, Ok|Cancel )
65{
66 TQHBox *hbox = makeHBoxMainWidget();
67 hbox->setSpacing( spacingHint() );
68 hbox->setMargin( marginHint() );
69
70 TQLabel *label = new TQLabel(hbox);
71 label->setPixmap( BarIcon("pgp-keys") );
72
73 TQWidget *rightArea = new TQWidget( hbox );
74 TQVBoxLayout *vlay = new TQVBoxLayout( rightArea, 0, spacingHint() );
75
76 if (keyID.isNull())
77 label = new TQLabel(i18n("Please enter your OpenPGP passphrase:"),rightArea);
78 else
79 label = new TQLabel(i18n("Please enter the OpenPGP passphrase for\n\"%1\":").arg(keyID),
80 rightArea);
81 lineedit = new KPasswordEdit( rightArea );
82 lineedit->setEchoMode(TQLineEdit::Password);
83 lineedit->setMinimumWidth( fontMetrics().maxWidth()*20 );
84 lineedit->setFocus();
85 connect( lineedit, TQ_SIGNAL(returnPressed()), this, TQ_SLOT(slotOk()) );
86
87 vlay->addWidget( label );
88 vlay->addWidget( lineedit );
89
90 disableResize();
91}
92
93
94PassphraseDialog::~PassphraseDialog()
95{
96}
97
98TQString PassphraseDialog::passphrase()
99{
100 return lineedit->password();
101}
102
103
104// ------------------------------------------------------------------------
105// Forbidden accels for KMail: AC GH OP
106// for KNode: ACE H O
107Config::Config( TQWidget *parent, const char *name, bool encrypt )
108 : TQWidget( parent, name ), pgp( Module::getKpgp() )
109{
110 TQGroupBox * group;
111 TQLabel * label;
112 TQString msg;
113
114
115 TQVBoxLayout *topLayout = new TQVBoxLayout( this, 0, KDialog::spacingHint() );
116
117 group = new TQVGroupBox( i18n("Warning"), this );
118 group->layout()->setSpacing( KDialog::spacingHint() );
119 // (mmutz) work around TQt label bug in 3.0.0 (and possibly later):
120 // 1. Don't use rich text: No <qt><b>...</b></qt>
121 label = new TQLabel( i18n("Please check if encryption really "
122 "works before you start using it seriously. Also note that attachments "
123 "are not encrypted by the PGP/GPG module."), group );
124 // 2. instead, set the font to bold:
125 TQFont labelFont = label->font();
126 labelFont.setBold( true );
127 label->setFont( labelFont );
128 // 3. and activate wordwarp:
129 label->setAlignment( AlignLeft|WordBreak );
130 // end; to remove the workaround, add <qt><b>..</b></qt> around the
131 // text and remove lines TQFont... -> label->setAlignment(...).
132 topLayout->addWidget( group );
133
134 group = new TQVGroupBox( i18n("Encryption Tool"), this );
135 group->layout()->setSpacing( KDialog::spacingHint() );
136
137 TQHBox * hbox = new TQHBox( group );
138 label = new TQLabel( i18n("Select encryption tool to &use:"), hbox );
139 toolCombo = new TQComboBox( false, hbox );
140 toolCombo->insertStringList( TQStringList()
141 << i18n("Autodetect")
142 << i18n("GnuPG - Gnu Privacy Guard")
143 << i18n("PGP Version 2.x")
144 << i18n("PGP Version 5.x")
145 << i18n("PGP Version 6.x")
146 << i18n("Do not use any encryption tool") );
147 label->setBuddy( toolCombo );
148 hbox->setStretchFactor( toolCombo, 1 );
149 connect( toolCombo, TQ_SIGNAL( activated( int ) ),
150 this, TQ_SIGNAL( changed( void ) ) );
151 // This is the place to add a KURLRequester to be used for asking
152 // the user for the path to the executable...
153 topLayout->addWidget( group );
154
155 mpOptionsGroupBox = new TQVGroupBox( i18n("Options"), this );
156 mpOptionsGroupBox->layout()->setSpacing( KDialog::spacingHint() );
157 storePass = new TQCheckBox( i18n("&Keep passphrase in memory"),
158 mpOptionsGroupBox );
159 connect( storePass, TQ_SIGNAL( toggled( bool ) ),
160 this, TQ_SIGNAL( changed( void ) ) );
161 msg = i18n( "<qt><p>When this option is enabled, the passphrase of your "
162 "private key will be remembered by the application as long "
163 "as the application is running. Thus you will only have to "
164 "enter the passphrase once.</p><p>Be aware that this could be a "
165 "security risk. If you leave your computer, others "
166 "can use it to send signed messages and/or read your encrypted "
167 "messages. If a core dump occurs, the contents of your RAM will "
168 "be saved onto disk, including your passphrase.</p>"
169 "<p>Note that when using KMail, this setting only applies "
170 "if you are not using gpg-agent. It is also ignored "
171 "if you are using crypto plugins.</p></qt>" );
172 TQWhatsThis::add( storePass, msg );
173 if( encrypt ) {
174 encToSelf = new TQCheckBox( i18n("Always encr&ypt to self"),
175 mpOptionsGroupBox );
176 connect( encToSelf, TQ_SIGNAL( toggled( bool ) ),
177 this, TQ_SIGNAL( changed( void ) ) );
178
179 msg = i18n( "<qt><p>When this option is enabled, the message/file "
180 "will not only be encrypted with the receiver's public key, "
181 "but also with your key. This will enable you to decrypt the "
182 "message/file at a later time. This is generally a good idea."
183 "</p></qt>" );
184 TQWhatsThis::add( encToSelf, msg );
185 }
186 else
187 encToSelf = 0;
188 showCipherText = new TQCheckBox( i18n("&Show signed/encrypted text after "
189 "composing"),
190 mpOptionsGroupBox );
191 connect( showCipherText, TQ_SIGNAL( toggled( bool ) ),
192 this, TQ_SIGNAL( changed( void ) ) );
193
194 msg = i18n( "<qt><p>When this option is enabled, the signed/encrypted text "
195 "will be shown in a separate window, enabling you to know how "
196 "it will look before it is sent. This is a good idea when "
197 "you are verifying that your encryption system works.</p></qt>" );
198 TQWhatsThis::add( showCipherText, msg );
199 if( encrypt ) {
200 showKeyApprovalDlg = new TQCheckBox( i18n("Always show the encryption "
201 "keys &for approval"),
202 mpOptionsGroupBox );
203 connect( showKeyApprovalDlg, TQ_SIGNAL( toggled( bool ) ),
204 this, TQ_SIGNAL( changed( void ) ) );
205 msg = i18n( "<qt><p>When this option is enabled, the application will "
206 "always show you a list of public keys from which you can "
207 "choose the one it will use for encryption. If it is off, "
208 "the application will only show the dialog if it cannot find "
209 "the right key or if there are several which could be used. "
210 "</p></qt>" );
211 TQWhatsThis::add( showKeyApprovalDlg, msg );
212}
213 else
214 showKeyApprovalDlg = 0;
215
216 topLayout->addWidget( mpOptionsGroupBox );
217
218 topLayout->addStretch(1);
219
220 setValues(); // is this needed by KNode, b/c for KMail, it's not.
221}
222
223
224Config::~Config()
225{
226}
227
228void
229Config::setValues()
230{
231 // set default values
232 storePass->setChecked( pgp->storePassPhrase() );
233 if( 0 != encToSelf )
234 encToSelf->setChecked( pgp->encryptToSelf() );
235 showCipherText->setChecked( pgp->showCipherText() );
236 if( 0 != showKeyApprovalDlg )
237 showKeyApprovalDlg->setChecked( pgp->showKeyApprovalDlg() );
238
239 int type = 0;
240 switch (pgp->pgpType) {
241 // translate Kpgp::Module enum to combobox' entries:
242 default:
243 case Module::tAuto: type = 0; break;
244 case Module::tGPG: type = 1; break;
245 case Module::tPGP2: type = 2; break;
246 case Module::tPGP5: type = 3; break;
247 case Module::tPGP6: type = 4; break;
248 case Module::tOff: type = 5; break;
249 }
250 toolCombo->setCurrentItem( type );
251}
252
253void
254Config::applySettings()
255{
256 pgp->setStorePassPhrase(storePass->isChecked());
257 if( 0 != encToSelf )
258 pgp->setEncryptToSelf(encToSelf->isChecked());
259 pgp->setShowCipherText(showCipherText->isChecked());
260 if( 0 != showKeyApprovalDlg )
261 pgp->setShowKeyApprovalDlg( showKeyApprovalDlg->isChecked() );
262
263 Module::PGPType type;
264 switch ( toolCombo->currentItem() ) {
265 // convert combobox entry indices to Kpgp::Module constants:
266 default:
267 case 0: type = Module::tAuto; break;
268 case 1: type = Module::tGPG; break;
269 case 2: type = Module::tPGP2; break;
270 case 3: type = Module::tPGP5; break;
271 case 4: type = Module::tPGP6; break;
272 case 5: type = Module::tOff; break;
273 }
274 pgp->pgpType = type;
275
276 pgp->writeConfig(true);
277}
278
279
280
281// ------------------------------------------------------------------------
282KeySelectionDialog::KeySelectionDialog( const KeyList& keyList,
283 const TQString& title,
284 const TQString& text,
285 const KeyIDList& keyIds,
286 const bool rememberChoice,
287 const unsigned int allowedKeys,
288 const bool extendedSelection,
289 TQWidget *parent, const char *name,
290 bool modal )
291 : KDialogBase( parent, name, modal, title, Default|Ok|Cancel, Ok ),
292 mRememberCB( 0 ),
293 mAllowedKeys( allowedKeys ),
294 mCurrentContextMenuItem( 0 )
295{
296 if ( tdeApp )
297 KWin::setIcons( winId(), tdeApp->icon(), tdeApp->miniIcon() );
298 Kpgp::Module *pgp = Kpgp::Module::getKpgp();
299 TDEConfig *config = pgp->getConfig();
300 TDEConfigGroup dialogConfig( config, "Key Selection Dialog" );
301
302 TQSize defaultSize( 580, 400 );
303 TQSize dialogSize = dialogConfig.readSizeEntry( "Dialog size", &defaultSize );
304
305 resize( dialogSize );
306
307 mCheckSelectionTimer = new TQTimer( this, "mCheckSelectionTimer" );
308 mStartSearchTimer = new TQTimer( this, "mStartSearchTimer" );
309
310 // load the key status icons
311 mKeyGoodPix = new TQPixmap( UserIcon("key_ok") );
312 mKeyBadPix = new TQPixmap( UserIcon("key_bad") );
313 mKeyUnknownPix = new TQPixmap( UserIcon("key_unknown") );
314 mKeyValidPix = new TQPixmap( UserIcon("key") );
315
316 TQFrame *page = makeMainWidget();
317 TQVBoxLayout *topLayout = new TQVBoxLayout( page, 0, spacingHint() );
318
319 if( !text.isEmpty() ) {
320 TQLabel *label = new TQLabel( page );
321 label->setText( text );
322 topLayout->addWidget( label );
323 }
324
325 TQHBoxLayout * hlay = new TQHBoxLayout( topLayout ); // inherits spacing
326 TQLineEdit * le = new TQLineEdit( page );
327 hlay->addWidget( new TQLabel( le, i18n("&Search for:"), page ) );
328 hlay->addWidget( le, 1 );
329 le->setFocus();
330
331 connect( le, TQ_SIGNAL(textChanged(const TQString&)),
332 this, TQ_SLOT(slotSearch(const TQString&)) );
333 connect( mStartSearchTimer, TQ_SIGNAL(timeout()), TQ_SLOT(slotFilter()) );
334
335 mListView = new TDEListView( page );
336 mListView->addColumn( i18n("Key ID") );
337 mListView->addColumn( i18n("User ID") );
338 mListView->setAllColumnsShowFocus( true );
339 mListView->setResizeMode( TQListView::LastColumn );
340 mListView->setRootIsDecorated( true );
341 mListView->setShowSortIndicator( true );
342 mListView->setSorting( 1, true ); // sort by User ID
343 mListView->setShowToolTips( true );
344 if( extendedSelection ) {
345 mListView->setSelectionMode( TQListView::Extended );
346 //mListView->setSelectionMode( TQListView::Multi );
347 }
348 topLayout->addWidget( mListView, 10 );
349
350 if (rememberChoice) {
351 mRememberCB = new TQCheckBox( i18n("Remember choice"), page );
352 topLayout->addWidget( mRememberCB );
353 TQWhatsThis::add(mRememberCB,
354 i18n("<qt><p>If you check this box your choice will "
355 "be stored and you will not be asked again."
356 "</p></qt>"));
357 }
358
359 initKeylist( keyList, keyIds );
360
361 TQListViewItem *lvi;
362 if( extendedSelection ) {
363 lvi = mListView->currentItem();
364 slotCheckSelection();
365 }
366 else {
367 lvi = mListView->selectedItem();
368 slotCheckSelection( lvi );
369 }
370 // make sure that the selected item is visible
371 // (ensureItemVisible(...) doesn't work correctly in TQt 3.0.0)
372 if( lvi != 0 )
373 mListView->center( mListView->contentsX(), mListView->itemPos( lvi ) );
374
375 if( extendedSelection ) {
376 connect( mCheckSelectionTimer, TQ_SIGNAL( timeout() ),
377 this, TQ_SLOT( slotCheckSelection() ) );
378 connect( mListView, TQ_SIGNAL( selectionChanged() ),
379 this, TQ_SLOT( slotSelectionChanged() ) );
380 }
381 else {
382 connect( mListView, TQ_SIGNAL( selectionChanged( TQListViewItem* ) ),
383 this, TQ_SLOT( slotSelectionChanged( TQListViewItem* ) ) );
384 }
385 connect( mListView, TQ_SIGNAL( doubleClicked ( TQListViewItem *, const TQPoint &, int ) ), this, TQ_SLOT( accept() ) );
386
387 connect( mListView, TQ_SIGNAL( contextMenuRequested( TQListViewItem*,
388 const TQPoint&, int ) ),
389 this, TQ_SLOT( slotRMB( TQListViewItem*, const TQPoint&, int ) ) );
390
391 setButtonText( KDialogBase::Default, i18n("&Reread Keys") );
392 connect( this, TQ_SIGNAL( defaultClicked() ),
393 this, TQ_SLOT( slotRereadKeys() ) );
394}
395
396
397KeySelectionDialog::~KeySelectionDialog()
398{
399 Kpgp::Module *pgp = Kpgp::Module::getKpgp();
400 TDEConfig *config = pgp->getConfig();
401 TDEConfigGroup dialogConfig( config, "Key Selection Dialog" );
402 dialogConfig.writeEntry( "Dialog size", size() );
403 config->sync();
404 delete mKeyGoodPix;
405 delete mKeyBadPix;
406 delete mKeyUnknownPix;
407 delete mKeyValidPix;
408}
409
410
411KeyID KeySelectionDialog::key() const
412{
413 if( mListView->isMultiSelection() || mKeyIds.isEmpty() )
414 return KeyID();
415 else
416 return mKeyIds.first();
417}
418
419
420void KeySelectionDialog::initKeylist( const KeyList& keyList,
421 const KeyIDList& keyIds )
422{
423 TQListViewItem* firstSelectedItem = 0;
424 mKeyIds.clear();
425 mListView->clear();
426
427 // build a list of all public keys
428 for( KeyListIterator it( keyList ); it.current(); ++it ) {
429 KeyID curKeyId = (*it)->primaryKeyID();
430
431 TQListViewItem* primaryUserID = new TQListViewItem( mListView, curKeyId,
432 (*it)->primaryUserID() );
433
434 // select and open the given key
435 if( keyIds.findIndex( curKeyId ) != -1 ) {
436 if( 0 == firstSelectedItem ) {
437 firstSelectedItem = primaryUserID;
438 }
439 mListView->setSelected( primaryUserID, true );
440 mKeyIds.append( curKeyId );
441 }
442 primaryUserID->setOpen( false );
443
444 // set icon for this key
445 switch( keyValidity( *it ) ) {
446 case 0: // the key's validity can't be determined
447 primaryUserID->setPixmap( 0, *mKeyUnknownPix );
448 break;
449 case 1: // key is valid but not trusted
450 primaryUserID->setPixmap( 0, *mKeyValidPix );
451 break;
452 case 2: // key is valid and trusted
453 primaryUserID->setPixmap( 0, *mKeyGoodPix );
454 break;
455 case -1: // key is invalid
456 primaryUserID->setPixmap( 0, *mKeyBadPix );
457 break;
458 }
459
460 TQListViewItem* childItem;
461
462 childItem = new TQListViewItem( primaryUserID, "",
463 i18n( "Fingerprint: %1" )
464 .arg( beautifyFingerprint( (*it)->primaryFingerprint() ) ) );
465 if( primaryUserID->isSelected() && mListView->isMultiSelection() ) {
466 mListView->setSelected( childItem, true );
467 }
468
469 childItem = new TQListViewItem( primaryUserID, "", keyInfo( *it ) );
470 if( primaryUserID->isSelected() && mListView->isMultiSelection() ) {
471 mListView->setSelected( childItem, true );
472 }
473
474 UserIDList userIDs = (*it)->userIDs();
475 UserIDListIterator uidit( userIDs );
476 if( *uidit ) {
477 ++uidit; // skip the primary user ID
478 for( ; *uidit; ++uidit ) {
479 childItem = new TQListViewItem( primaryUserID, "", (*uidit)->text() );
480 if( primaryUserID->isSelected() && mListView->isMultiSelection() ) {
481 mListView->setSelected( childItem, true );
482 }
483 }
484 }
485 }
486
487 if( 0 != firstSelectedItem ) {
488 mListView->setCurrentItem( firstSelectedItem );
489 }
490}
491
492
493TQString KeySelectionDialog::keyInfo( const Kpgp::Key *key ) const
494{
495 TQString status, remark;
496 if( key->revoked() ) {
497 status = i18n("Revoked");
498 }
499 else if( key->expired() ) {
500 status = i18n("Expired");
501 }
502 else if( key->disabled() ) {
503 status = i18n("Disabled");
504 }
505 else if( key->invalid() ) {
506 status = i18n("Invalid");
507 }
508 else {
509 Validity keyTrust = key->keyTrust();
510 switch( keyTrust ) {
511 case KPGP_VALIDITY_UNDEFINED:
512 status = i18n("Undefined trust");
513 break;
514 case KPGP_VALIDITY_NEVER:
515 status = i18n("Untrusted");
516 break;
517 case KPGP_VALIDITY_MARGINAL:
518 status = i18n("Marginally trusted");
519 break;
520 case KPGP_VALIDITY_FULL:
521 status = i18n("Fully trusted");
522 break;
523 case KPGP_VALIDITY_ULTIMATE:
524 status = i18n("Ultimately trusted");
525 break;
526 case KPGP_VALIDITY_UNKNOWN:
527 default:
528 status = i18n("Unknown");
529 }
530 if( key->secret() ) {
531 remark = i18n("Secret key available");
532 }
533 else if( !key->canEncrypt() ) {
534 remark = i18n("Sign only key");
535 }
536 else if( !key->canSign() ) {
537 remark = i18n("Encryption only key");
538 }
539 }
540
541 TQDateTime dt;
542 dt.setTime_t( key->creationDate() );
543 if( remark.isEmpty() ) {
544 return " " + i18n("creation date and status of an OpenPGP key",
545 "Creation date: %1, Status: %2")
546 .arg( TDEGlobal::locale()->formatDate( dt.date(), true ) )
547 .arg( status );
548 }
549 else {
550 return " " + i18n("creation date, status and remark of an OpenPGP key",
551 "Creation date: %1, Status: %2 (%3)")
552 .arg( TDEGlobal::locale()->formatDate( dt.date(), true ) )
553 .arg( status )
554 .arg( remark );
555 }
556}
557
558TQString KeySelectionDialog::beautifyFingerprint( const TQCString& fpr ) const
559{
560 TQCString result;
561
562 if( 40 == fpr.length() ) {
563 // convert to this format:
564 // 0000 1111 2222 3333 4444 5555 6666 7777 8888 9999
565 result.fill( ' ', 50 );
566 memcpy( result.data() , fpr.data() , 4 );
567 memcpy( result.data() + 5, fpr.data() + 4, 4 );
568 memcpy( result.data() + 10, fpr.data() + 8, 4 );
569 memcpy( result.data() + 15, fpr.data() + 12, 4 );
570 memcpy( result.data() + 20, fpr.data() + 16, 4 );
571 memcpy( result.data() + 26, fpr.data() + 20, 4 );
572 memcpy( result.data() + 31, fpr.data() + 24, 4 );
573 memcpy( result.data() + 36, fpr.data() + 28, 4 );
574 memcpy( result.data() + 41, fpr.data() + 32, 4 );
575 memcpy( result.data() + 46, fpr.data() + 36, 4 );
576 }
577 else if( 32 == fpr.length() ) {
578 // convert to this format:
579 // 00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF
580 result.fill( ' ', 48 );
581 memcpy( result.data() , fpr.data() , 2 );
582 memcpy( result.data() + 3, fpr.data() + 2, 2 );
583 memcpy( result.data() + 6, fpr.data() + 4, 2 );
584 memcpy( result.data() + 9, fpr.data() + 6, 2 );
585 memcpy( result.data() + 12, fpr.data() + 8, 2 );
586 memcpy( result.data() + 15, fpr.data() + 10, 2 );
587 memcpy( result.data() + 18, fpr.data() + 12, 2 );
588 memcpy( result.data() + 21, fpr.data() + 14, 2 );
589 memcpy( result.data() + 25, fpr.data() + 16, 2 );
590 memcpy( result.data() + 28, fpr.data() + 18, 2 );
591 memcpy( result.data() + 31, fpr.data() + 20, 2 );
592 memcpy( result.data() + 34, fpr.data() + 22, 2 );
593 memcpy( result.data() + 37, fpr.data() + 24, 2 );
594 memcpy( result.data() + 40, fpr.data() + 26, 2 );
595 memcpy( result.data() + 43, fpr.data() + 28, 2 );
596 memcpy( result.data() + 46, fpr.data() + 30, 2 );
597 }
598 else { // unknown length of fingerprint
599 result = fpr;
600 }
601
602 return result;
603}
604
605int KeySelectionDialog::keyValidity( const Kpgp::Key *key ) const
606{
607 if( 0 == key ) {
608 return -1;
609 }
610
611 if( ( mAllowedKeys & EncrSignKeys ) == EncryptionKeys ) {
612 // only encryption keys are allowed
613 if( ( mAllowedKeys & ValidKeys ) && !key->isValidEncryptionKey() ) {
614 // only valid encryption keys are allowed
615 return -1;
616 }
617 else if( !key->canEncrypt() ) {
618 return -1;
619 }
620 }
621 else if( ( mAllowedKeys & EncrSignKeys ) == SigningKeys ) {
622 // only signing keys are allowed
623 if( ( mAllowedKeys & ValidKeys ) && !key->isValidSigningKey() ) {
624 // only valid signing keys are allowed
625 return -1;
626 }
627 else if( !key->canSign() ) {
628 return -1;
629 }
630 }
631 else if( ( mAllowedKeys & ValidKeys ) && !key->isValid() ) {
632 // only valid keys are allowed
633 return -1;
634 }
635
636 // check the key's trust
637 int val = 0;
638 Validity keyTrust = key->keyTrust();
639 switch( keyTrust ) {
640 case KPGP_VALIDITY_NEVER:
641 val = -1;
642 break;
643 case KPGP_VALIDITY_MARGINAL:
644 case KPGP_VALIDITY_FULL:
645 case KPGP_VALIDITY_ULTIMATE:
646 val = 2;
647 break;
648 case KPGP_VALIDITY_UNDEFINED:
649 if( mAllowedKeys & TrustedKeys ) {
650 // only trusted keys are allowed
651 val = -1;
652 }
653 else {
654 val = 1;
655 }
656 break;
657 case KPGP_VALIDITY_UNKNOWN:
658 default:
659 val = 0;
660 }
661
662 return val;
663}
664
665
666void KeySelectionDialog::updateKeyInfo( const Kpgp::Key* key,
667 TQListViewItem* lvi ) const
668{
669 if( 0 == lvi ) {
670 return;
671 }
672
673 if( lvi->parent() != 0 ) {
674 lvi = lvi->parent();
675 }
676
677 if( 0 == key ) {
678 // the key doesn't exist anymore -> delete it from the list view
679 while( lvi->firstChild() ) {
680 kdDebug(5100) << "Deleting '" << lvi->firstChild()->text( 1 ) << "'\n";
681 delete lvi->firstChild();
682 }
683 kdDebug(5100) << "Deleting key 0x" << lvi->text( 0 ) << " ("
684 << lvi->text( 1 ) << ")\n";
685 delete lvi;
686 lvi = 0;
687 return;
688 }
689
690 // update the icon for this key
691 switch( keyValidity( key ) ) {
692 case 0: // the key's validity can't be determined
693 lvi->setPixmap( 0, *mKeyUnknownPix );
694 break;
695 case 1: // key is valid but not trusted
696 lvi->setPixmap( 0, *mKeyValidPix );
697 break;
698 case 2: // key is valid and trusted
699 lvi->setPixmap( 0, *mKeyGoodPix );
700 break;
701 case -1: // key is invalid
702 lvi->setPixmap( 0, *mKeyBadPix );
703 break;
704 }
705
706 // update the key info for this key
707 // the key info is identified by a leading space; this shouldn't be
708 // a problem because User Ids shouldn't start with a space
709 for( lvi = lvi->firstChild(); lvi; lvi = lvi->nextSibling() ) {
710 if( lvi->text( 1 ).at(0) == ' ' ) {
711 lvi->setText( 1, keyInfo( key ) );
712 break;
713 }
714 }
715}
716
717
718int
719KeySelectionDialog::keyAdmissibility( TQListViewItem* lvi,
720 TrustCheckMode trustCheckMode ) const
721{
722 // Return:
723 // -1 = key must not be chosen,
724 // 0 = not enough information to decide whether the give key is allowed
725 // or not,
726 // 1 = key can be chosen
727
728 if( mAllowedKeys == AllKeys ) {
729 return 1;
730 }
731
732 Kpgp::Module *pgp = Kpgp::Module::getKpgp();
733
734 if( 0 == pgp ) {
735 return 0;
736 }
737
738 KeyID keyId = getKeyId( lvi );
739 Kpgp::Key* key = pgp->publicKey( keyId );
740
741 if( 0 == key ) {
742 return 0;
743 }
744
745 int val = 0;
746 if( trustCheckMode == ForceTrustCheck ) {
747 key = pgp->rereadKey( keyId, true );
748 updateKeyInfo( key, lvi );
749 val = keyValidity( key );
750 }
751 else {
752 val = keyValidity( key );
753 if( ( trustCheckMode == AllowExpensiveTrustCheck ) && ( 0 == val ) ) {
754 key = pgp->rereadKey( keyId, true );
755 updateKeyInfo( key, lvi );
756 val = keyValidity( key );
757 }
758 }
759
760 switch( val ) {
761 case -1: // key is not usable
762 return -1;
763 break;
764 case 0: // key status unknown
765 return 0;
766 break;
767 case 1: // key is valid, but untrusted
768 if( mAllowedKeys & TrustedKeys ) {
769 // only trusted keys are allowed
770 return -1;
771 }
772 return 1;
773 break;
774 case 2: // key is trusted
775 return 1;
776 break;
777 default:
778 kdDebug( 5100 ) << "Error: Invalid key status value.\n";
779 }
780
781 return 0;
782}
783
784
785KeyID
786KeySelectionDialog::getKeyId( const TQListViewItem* lvi ) const
787{
788 KeyID keyId;
789
790 if( 0 != lvi ) {
791 if( 0 != lvi->parent() ) {
792 keyId = lvi->parent()->text(0).local8Bit();
793 }
794 else {
795 keyId = lvi->text(0).local8Bit();
796 }
797 }
798
799 return keyId;
800}
801
802
803void KeySelectionDialog::slotRereadKeys()
804{
805 Kpgp::Module *pgp = Kpgp::Module::getKpgp();
806
807 if( 0 == pgp ) {
808 return;
809 }
810
811 KeyList keys;
812
813 if( PublicKeys & mAllowedKeys ) {
814 pgp->readPublicKeys( true );
815 keys = pgp->publicKeys();
816 }
817 else {
818 pgp->readSecretKeys( true );
819 keys = pgp->secretKeys();
820 }
821
822 // save the current position of the contents
823 int offsetY = mListView->contentsY();
824
825 if( mListView->isMultiSelection() ) {
826 disconnect( mListView, TQ_SIGNAL( selectionChanged() ),
827 this, TQ_SLOT( slotSelectionChanged() ) );
828 }
829 else {
830 disconnect( mListView, TQ_SIGNAL( selectionChanged( TQListViewItem * ) ),
831 this, TQ_SLOT( slotSelectionChanged( TQListViewItem * ) ) );
832 }
833
834 initKeylist( keys, KeyIDList( mKeyIds ) );
835 slotFilter();
836
837 if( mListView->isMultiSelection() ) {
838 connect( mListView, TQ_SIGNAL( selectionChanged() ),
839 this, TQ_SLOT( slotSelectionChanged() ) );
840 slotSelectionChanged();
841 }
842 else {
843 connect( mListView, TQ_SIGNAL( selectionChanged( TQListViewItem * ) ),
844 this, TQ_SLOT( slotSelectionChanged( TQListViewItem * ) ) );
845 }
846
847 // restore the saved position of the contents
848 mListView->setContentsPos( 0, offsetY );
849}
850
851
852void KeySelectionDialog::slotSelectionChanged( TQListViewItem * lvi )
853{
854 slotCheckSelection( lvi );
855}
856
857
858void KeySelectionDialog::slotSelectionChanged()
859{
860 kdDebug(5100) << "KeySelectionDialog::slotSelectionChanged()\n";
861
862 // (re)start the check selection timer. Checking the selection is delayed
863 // because else drag-selection doesn't work very good (checking key trust
864 // is slow).
865 mCheckSelectionTimer->start( sCheckSelectionDelay );
866}
867
868
869void KeySelectionDialog::slotCheckSelection( TQListViewItem* plvi /* = 0 */ )
870{
871 kdDebug(5100) << "KeySelectionDialog::slotCheckSelection()\n";
872
873 if( !mListView->isMultiSelection() ) {
874 mKeyIds.clear();
875 KeyID keyId = getKeyId( plvi );
876 if( !keyId.isEmpty() ) {
877 mKeyIds.append( keyId );
878 enableButtonOK( 1 == keyAdmissibility( plvi, AllowExpensiveTrustCheck ) );
879 }
880 else {
881 enableButtonOK( false );
882 }
883 }
884 else {
885 mCheckSelectionTimer->stop();
886
887 // As we might change the selection, we have to disconnect the slot
888 // to prevent recursion
889 disconnect( mListView, TQ_SIGNAL( selectionChanged() ),
890 this, TQ_SLOT( slotSelectionChanged() ) );
891
892 KeyIDList newKeyIdList;
893 TQValueList<TQListViewItem*> keysToBeChecked;
894
895 bool keysAllowed = true;
896 enum { UNKNOWN, SELECTED, DESELECTED } userAction = UNKNOWN;
897 // Iterate over the tree to find selected keys.
898 for( TQListViewItem *lvi = mListView->firstChild();
899 0 != lvi;
900 lvi = lvi->nextSibling() ) {
901 // We make sure that either all items belonging to a key are selected
902 // or unselected. As it's possible to select/deselect multiple keys at
903 // once in extended selection mode we have to figure out whether the user
904 // selected or deselected keys.
905
906 // First count the selected items of this key
907 int itemCount = 1 + lvi->childCount();
908 int selectedCount = lvi->isSelected() ? 1 : 0;
909 for( TQListViewItem *clvi = lvi->firstChild();
910 0 != clvi;
911 clvi = clvi->nextSibling() ) {
912 if( clvi->isSelected() ) {
913 ++selectedCount;
914 }
915 }
916
917 if( userAction == UNKNOWN ) {
918 // Figure out whether the user selected or deselected this key
919 // Remark: A selected count of 0 doesn't mean anything since in
920 // extended selection mode a normal left click deselects
921 // the not clicked items.
922 if( 0 < selectedCount ) {
923 if( -1 == mKeyIds.findIndex( lvi->text(0).local8Bit() ) ) {
924 // some items of this key are selected and the key wasn't selected
925 // before => the user selected something
926 kdDebug(5100) << "selectedCount: "<<selectedCount<<"/"<<itemCount
927 <<" --- User selected key "<<lvi->text(0)<<endl;
928 userAction = SELECTED;
929 }
930 else if( ( itemCount > selectedCount ) &&
931 ( -1 != mKeyIds.findIndex( lvi->text(0).local8Bit() ) ) ) {
932 // some items of this key are unselected and the key was selected
933 // before => the user deselected something
934 kdDebug(5100) << "selectedCount: "<<selectedCount<<"/"<<itemCount
935 <<" --- User deselected key "<<lvi->text(0)<<endl;
936 userAction = DESELECTED;
937 }
938 }
939 }
940 if( itemCount == selectedCount ) {
941 // add key to the list of selected keys
942 KeyID keyId = lvi->text(0).local8Bit();
943 newKeyIdList.append( keyId );
944 int admissibility = keyAdmissibility( lvi, NoExpensiveTrustCheck );
945 if( -1 == admissibility ) {
946 keysAllowed = false;
947 }
948 else if ( 0 == admissibility ) {
949 keysToBeChecked.append( lvi );
950 }
951 }
952 else if( 0 < selectedCount ) {
953 // not all items of this key are selected or unselected. change this
954 // according to the user's action
955 if( userAction == SELECTED ) {
956 // select all items of this key
957 mListView->setSelected( lvi, true );
958 for( TQListViewItem *clvi = lvi->firstChild();
959 0 != clvi;
960 clvi = clvi->nextSibling() ) {
961 mListView->setSelected( clvi, true );
962 }
963 // add key to the list of selected keys
964 KeyID keyId = lvi->text(0).local8Bit();
965 newKeyIdList.append( keyId );
966 int admissibility = keyAdmissibility( lvi, NoExpensiveTrustCheck );
967 if( -1 == admissibility ) {
968 keysAllowed = false;
969 }
970 else if ( 0 == admissibility ) {
971 keysToBeChecked.append( lvi );
972 }
973 }
974 else { // userAction == DESELECTED
975 // deselect all items of this key
976 mListView->setSelected( lvi, false );
977 for( TQListViewItem *clvi = lvi->firstChild();
978 0 != clvi;
979 clvi = clvi->nextSibling() ) {
980 mListView->setSelected( clvi, false );
981 }
982 }
983 }
984 }
985 kdDebug(5100) << "Selected keys: " << newKeyIdList.toStringList().join(", ") << endl;
986 mKeyIds = newKeyIdList;
987 if( !keysToBeChecked.isEmpty() ) {
988 keysAllowed = keysAllowed && checkKeys( keysToBeChecked );
989 }
990 enableButtonOK( keysAllowed );
991
992 connect( mListView, TQ_SIGNAL( selectionChanged() ),
993 this, TQ_SLOT( slotSelectionChanged() ) );
994 }
995}
996
997
998bool KeySelectionDialog::checkKeys( const TQValueList<TQListViewItem*>& keys ) const
999{
1000 KProgressDialog* pProgressDlg = 0;
1001 bool keysAllowed = true;
1002 kdDebug(5100) << "Checking keys...\n";
1003
1004 pProgressDlg = new KProgressDialog( 0, 0, i18n("Checking Keys"),
1005 i18n("Checking key 0xMMMMMMMM..."),
1006 true );
1007 pProgressDlg->setAllowCancel( false );
1008 pProgressDlg->progressBar()->setTotalSteps( keys.count() );
1009 pProgressDlg->setMinimumDuration( 1000 );
1010 pProgressDlg->show();
1011
1012 for( TQValueList<TQListViewItem*>::ConstIterator it = keys.begin();
1013 it != keys.end();
1014 ++it ) {
1015 kdDebug(5100) << "Checking key 0x" << getKeyId( *it ) << "...\n";
1016 pProgressDlg->setLabel( i18n("Checking key 0x%1...")
1017 .arg( TQString( getKeyId( *it ) ) ) );
1018 tdeApp->processEvents();
1019 keysAllowed = keysAllowed && ( -1 != keyAdmissibility( *it, AllowExpensiveTrustCheck ) );
1020 pProgressDlg->progressBar()->advance( 1 );
1021 tdeApp->processEvents();
1022 }
1023
1024 delete pProgressDlg;
1025 pProgressDlg = 0;
1026
1027 return keysAllowed;
1028}
1029
1030
1031void KeySelectionDialog::slotRMB( TQListViewItem* lvi, const TQPoint& pos, int )
1032{
1033 if( !lvi ) {
1034 return;
1035 }
1036
1037 mCurrentContextMenuItem = lvi;
1038
1039 TQPopupMenu menu(this);
1040 menu.insertItem( i18n( "Recheck Key" ), this, TQ_SLOT( slotRecheckKey() ) );
1041 menu.exec( pos );
1042}
1043
1044
1045void KeySelectionDialog::slotRecheckKey()
1046{
1047 if( 0 != mCurrentContextMenuItem ) {
1048 // force rereading the key
1049 keyAdmissibility( mCurrentContextMenuItem, ForceTrustCheck );
1050 // recheck the selection
1051 slotCheckSelection( mCurrentContextMenuItem );
1052 }
1053}
1054
1055void KeySelectionDialog::slotOk()
1056{
1057 if( mCheckSelectionTimer->isActive() ) {
1058 slotCheckSelection();
1059 }
1060 mStartSearchTimer->stop();
1061 accept();
1062}
1063
1064
1065void KeySelectionDialog::slotCancel()
1066{
1067 mCheckSelectionTimer->stop();
1068 mStartSearchTimer->stop();
1069 mKeyIds.clear();
1070 reject();
1071}
1072
1073void KeySelectionDialog::slotSearch( const TQString & text )
1074{
1075 mSearchText = text.stripWhiteSpace().upper();
1076 mStartSearchTimer->start( sCheckSelectionDelay, true /*single-shot*/ );
1077}
1078
1079void KeySelectionDialog::slotFilter()
1080{
1081 if ( mSearchText.isEmpty() ) {
1082 showAllItems();
1083 return;
1084 }
1085
1086 // OK, so we need to filter:
1087 TQRegExp keyIdRegExp( "(?:0x)?[A-F0-9]{1,8}", false /*case-insens.*/ );
1088 if ( keyIdRegExp.exactMatch( mSearchText ) ) {
1089 if ( mSearchText.startsWith( "0X" ) )
1090 // search for keyID only:
1091 filterByKeyID( mSearchText.mid( 2 ) );
1092 else
1093 // search for UID and keyID:
1094 filterByKeyIDOrUID( mSearchText );
1095 } else {
1096 // search in UID:
1097 filterByUID( mSearchText );
1098 }
1099}
1100
1101void KeySelectionDialog::filterByKeyID( const TQString & keyID )
1102{
1103 assert( keyID.length() <= 8 );
1104 assert( !keyID.isEmpty() ); // regexp in slotFilter should prevent these
1105 if ( keyID.isEmpty() )
1106 showAllItems();
1107 else
1108 for ( TQListViewItem * item = mListView->firstChild() ; item ; item = item->nextSibling() )
1109 item->setVisible( item->text( 0 ).upper().startsWith( keyID ) );
1110}
1111
1112void KeySelectionDialog::filterByKeyIDOrUID( const TQString & str )
1113{
1114 assert( !str.isEmpty() );
1115
1116 // match beginnings of words:
1117 TQRegExp rx( "\\b" + TQRegExp::escape( str ), false );
1118
1119 for ( TQListViewItem * item = mListView->firstChild() ; item ; item = item->nextSibling() )
1120 item->setVisible( item->text( 0 ).upper().startsWith( str )
1121 || rx.search( item->text( 1 ) ) >= 0
1122 || anyChildMatches( item, rx ) );
1123
1124}
1125
1126void KeySelectionDialog::filterByUID( const TQString & str )
1127{
1128 assert( !str.isEmpty() );
1129
1130 // match beginnings of words:
1131 TQRegExp rx( "\\b" + TQRegExp::escape( str ), false );
1132
1133 for ( TQListViewItem * item = mListView->firstChild() ; item ; item = item->nextSibling() )
1134 item->setVisible( rx.search( item->text( 1 ) ) >= 0
1135 || anyChildMatches( item, rx ) );
1136}
1137
1138
1139bool KeySelectionDialog::anyChildMatches( const TQListViewItem * item, TQRegExp & rx ) const
1140{
1141 if ( !item )
1142 return false;
1143
1144 TQListViewItem * stop = item->nextSibling(); // It's OK if stop is NULL...
1145
1146 for ( TQListViewItemIterator it( item->firstChild() ) ; it.current() && it.current() != stop ; ++it )
1147 if ( rx.search( it.current()->text( 1 ) ) >= 0 ) {
1148 //item->setOpen( true ); // do we want that?
1149 return true;
1150 }
1151 return false;
1152}
1153
1154void KeySelectionDialog::showAllItems()
1155{
1156 for ( TQListViewItem * item = mListView->firstChild() ; item ; item = item->nextSibling() )
1157 item->setVisible( true );
1158}
1159
1160// ------------------------------------------------------------------------
1161KeyRequester::KeyRequester( TQWidget * parent, bool multipleKeys,
1162 unsigned int allowedKeys, const char * name )
1163 : TQWidget( parent, name ),
1164 mDialogCaption( i18n("OpenPGP Key Selection") ),
1165 mDialogMessage( i18n("Please select an OpenPGP key to use.") ),
1166 mMulti( multipleKeys ),
1167 mAllowedKeys( allowedKeys ),
1168 d( 0 )
1169{
1170 TQHBoxLayout * hlay = new TQHBoxLayout( this, 0, KDialog::spacingHint() );
1171
1172 // the label where the key id is to be displayed:
1173 mLabel = new TQLabel( this );
1174 mLabel->setFrameStyle( TQFrame::Panel | TQFrame::Sunken );
1175
1176 // the button to unset any key:
1177 mEraseButton = new TQPushButton( this );
1178 mEraseButton->setAutoDefault( false );
1179 mEraseButton->setSizePolicy( TQSizePolicy( TQSizePolicy::Minimum,
1180 TQSizePolicy::Minimum ) );
1181 mEraseButton->setPixmap( SmallIcon( "clear_left" ) );
1182 TQToolTip::add( mEraseButton, i18n("Clear") );
1183
1184 // the button to call the KeySelectionDialog:
1185 mDialogButton = new TQPushButton( i18n("Change..."), this );
1186 mDialogButton->setAutoDefault( false );
1187
1188 hlay->addWidget( mLabel, 1 );
1189 hlay->addWidget( mEraseButton );
1190 hlay->addWidget( mDialogButton );
1191
1192 connect( mEraseButton, TQ_SIGNAL(clicked()), TQ_SLOT(slotEraseButtonClicked()) );
1193 connect( mDialogButton, TQ_SIGNAL(clicked()), TQ_SLOT(slotDialogButtonClicked()) );
1194
1195 setSizePolicy( TQSizePolicy( TQSizePolicy::MinimumExpanding,
1196 TQSizePolicy::Fixed ) );
1197}
1198
1199KeyRequester::~KeyRequester() {
1200
1201}
1202
1203KeyIDList KeyRequester::keyIDs() const {
1204 return mKeys;
1205}
1206
1207void KeyRequester::setKeyIDs( const KeyIDList & keyIDs ) {
1208 mKeys = keyIDs;
1209 if ( mKeys.empty() ) {
1210 mLabel->clear();
1211 return;
1212 }
1213 if ( mKeys.size() > 1 )
1214 setMultipleKeysEnabled( true );
1215
1216 TQString s = mKeys.toStringList().join(", ");
1217
1218 mLabel->setText( s );
1219 TQToolTip::remove( mLabel );
1220 TQToolTip::add( mLabel, s );
1221}
1222
1223void KeyRequester::slotDialogButtonClicked() {
1224 Module * pgp = Module::getKpgp();
1225
1226 if ( !pgp ) {
1227 kdWarning() << "Kpgp::KeyRequester::slotDialogButtonClicked(): No pgp module found!" << endl;
1228 return;
1229 }
1230
1231 setKeyIDs( keyRequestHook( pgp ) );
1232 emit changed();
1233}
1234
1235void KeyRequester::slotEraseButtonClicked() {
1236 mKeys.clear();
1237 mLabel->clear();
1238 emit changed();
1239}
1240
1241void KeyRequester::setDialogCaption( const TQString & caption ) {
1242 mDialogCaption = caption;
1243}
1244
1245void KeyRequester::setDialogMessage( const TQString & msg ) {
1246 mDialogMessage = msg;
1247}
1248
1249bool KeyRequester::isMultipleKeysEnabled() const {
1250 return mMulti;
1251}
1252
1253void KeyRequester::setMultipleKeysEnabled( bool multi ) {
1254 if ( multi == mMulti ) return;
1255
1256 if ( !multi && mKeys.size() > 1 )
1257 mKeys.erase( ++mKeys.begin(), mKeys.end() );
1258
1259 mMulti = multi;
1260}
1261
1262int KeyRequester::allowedKeys() const {
1263 return mAllowedKeys;
1264}
1265
1266void KeyRequester::setAllowedKeys( int allowedKeys ) {
1267 mAllowedKeys = allowedKeys;
1268}
1269
1270
1271PublicKeyRequester::PublicKeyRequester( TQWidget * parent, bool multi,
1272 unsigned int allowed, const char * name )
1273 : KeyRequester( parent, multi, allowed & ~SecretKeys, name )
1274{
1275
1276}
1277
1278PublicKeyRequester::~PublicKeyRequester() {
1279
1280}
1281
1282KeyIDList PublicKeyRequester::keyRequestHook( Module * pgp ) const {
1283 assert( pgp );
1284 return pgp->selectPublicKeys( mDialogCaption, mDialogMessage, mKeys, TQString(), mAllowedKeys );
1285}
1286
1287SecretKeyRequester::SecretKeyRequester( TQWidget * parent, bool multi,
1288 unsigned int allowed, const char * name )
1289 : KeyRequester( parent, multi, allowed & ~PublicKeys, name )
1290{
1291
1292}
1293
1294SecretKeyRequester::~SecretKeyRequester() {
1295
1296}
1297
1298KeyIDList SecretKeyRequester::keyRequestHook( Module * pgp ) const {
1299 assert( pgp );
1300
1301 KeyID keyID = mKeys.first();
1302 keyID = pgp->selectSecretKey( mDialogCaption, mDialogMessage, keyID );
1303
1304 return KeyIDList() << keyID;
1305}
1306
1307
1308
1309// ------------------------------------------------------------------------
1310KeyApprovalDialog::KeyApprovalDialog( const TQStringList& addresses,
1311 const TQValueVector<KeyIDList>& keyIDs,
1312 const int allowedKeys,
1313 TQWidget *parent, const char *name,
1314 bool modal )
1315 : KDialogBase( parent, name, modal, i18n("Encryption Key Approval"),
1316 Ok|Cancel, Ok ),
1317 mKeys( keyIDs ),
1318 mAllowedKeys( allowedKeys ),
1319 mPrefsChanged( false )
1320{
1321 Kpgp::Module *pgp = Kpgp::Module::getKpgp();
1322
1323 if( pgp == 0 )
1324 return;
1325
1326 // ##### error handling
1327 // if( addresses.isEmpty() || keyList.isEmpty() ||
1328 // addresses.count()+1 != keyList.count() )
1329 // do something;
1330
1331 TQFrame *page = makeMainWidget();
1332 TQVBoxLayout *topLayout = new TQVBoxLayout( page, 0, KDialog::spacingHint() );
1333
1334 TQLabel *label = new TQLabel( i18n("The following keys will be used for "
1335 "encryption:"),
1336 page );
1337 topLayout->addWidget( label );
1338
1339 TQScrollView* sv = new TQScrollView( page );
1340 sv->setResizePolicy( TQScrollView::AutoOneFit );
1341 topLayout->addWidget( sv );
1342 TQVBox* bigvbox = new TQVBox( sv->viewport() );
1343 bigvbox->setMargin( KDialog::marginHint() );
1344 bigvbox->setSpacing( KDialog::spacingHint() );
1345 sv->addChild( bigvbox );
1346
1347 TQButtonGroup *mChangeButtonGroup = new TQButtonGroup( bigvbox );
1348 mChangeButtonGroup->hide();
1349 mAddressLabels.resize( addresses.count() );
1350 mKeyIdsLabels.resize( keyIDs.size() );
1351 //mKeyIdListBoxes.resize( keyIDs.size() );
1352 mEncrPrefCombos.resize( addresses.count() );
1353
1354 // the sender's key
1355 if( pgp->encryptToSelf() ) {
1356 mEncryptToSelf = 1;
1357 TQHBox* hbox = new TQHBox( bigvbox );
1358 new TQLabel( i18n("Your keys:"), hbox );
1359 TQLabel* keyidsL = new TQLabel( hbox );
1360 if( keyIDs[0].isEmpty() ) {
1361 keyidsL->setText( i18n("<none> means 'no key'", "<none>") );
1362 }
1363 else {
1364 keyidsL->setText( "0x" + keyIDs[0].toStringList().join( "\n0x" ) );
1365 }
1366 keyidsL->setFrameStyle( TQFrame::Panel | TQFrame::Sunken );
1367 /*
1368 TQListBox* keyidLB = new TQListBox( hbox );
1369 if( keyIDs[0].isEmpty() ) {
1370 keyidLB->insertItem( i18n("<none>") );
1371 }
1372 else {
1373 keyidLB->insertStringList( keyIDs[0].toStringList() );
1374 }
1375 keyidLB->setSelectionMode( TQListBox::NoSelection );
1376 keyidLB->setFrameStyle( TQFrame::Panel | TQFrame::Sunken );
1377 */
1378 TQPushButton *button = new TQPushButton( i18n("Change..."), hbox );
1379 mChangeButtonGroup->insert( button );
1380 button->setAutoDefault( false );
1381 hbox->setStretchFactor( keyidsL, 10 );
1382 mKeyIdsLabels.insert( 0, keyidsL );
1383 //hbox->setStretchFactor( keyidLB, 10 );
1384 //mKeyIdListBoxes.insert( 0, keyidLB );
1385
1386 new KSeparator( TQt::Horizontal, bigvbox );
1387 }
1388 else {
1389 mEncryptToSelf = 0;
1390 // insert dummy KeyIdListBox
1391 mKeyIdsLabels.insert( 0, 0 );
1392 //mKeyIdListBoxes.insert( 0, 0 );
1393 }
1394
1395 TQStringList::ConstIterator ait;
1396 TQValueVector<KeyIDList>::const_iterator kit;
1397 int i;
1398 for( ait = addresses.begin(), kit = keyIDs.begin(), i = 0;
1399 ( ait != addresses.end() ) && ( kit != keyIDs.end() );
1400 ++ait, ++kit, ++i ) {
1401 if( i == 0 ) {
1402 ++kit; // skip the sender's key id
1403 }
1404 else {
1405 new KSeparator( TQt::Horizontal, bigvbox );
1406 }
1407
1408 TQHBox *hbox = new TQHBox( bigvbox );
1409 new TQLabel( i18n("Recipient:"), hbox );
1410 TQLabel *addressL = new TQLabel( *ait, hbox );
1411 hbox->setStretchFactor( addressL, 10 );
1412 mAddressLabels.insert( i, addressL );
1413
1414 hbox = new TQHBox( bigvbox );
1415 new TQLabel( i18n("Encryption keys:"), hbox );
1416 TQLabel* keyidsL = new TQLabel( hbox );
1417 if( (*kit).isEmpty() ) {
1418 keyidsL->setText( i18n("<none> means 'no key'", "<none>") );
1419 }
1420 else {
1421 keyidsL->setText( "0x" + (*kit).toStringList().join( "\n0x" ) );
1422 }
1423 keyidsL->setFrameStyle( TQFrame::Panel | TQFrame::Sunken );
1424 /*
1425 TQListBox* keyidLB = new TQListBox( hbox );
1426 if( (*kit).isEmpty() ) {
1427 keyidLB->insertItem( i18n("<none>") );
1428 }
1429 else {
1430 keyidLB->insertStringList( (*kit).toStringList() );
1431 }
1432 keyidLB->setSelectionMode( TQListBox::NoSelection );
1433 keyidLB->setFrameStyle( TQFrame::Panel | TQFrame::Sunken );
1434 */
1435 TQPushButton *button = new TQPushButton( i18n("Change..."), hbox );
1436 mChangeButtonGroup->insert( button );
1437 button->setAutoDefault( false );
1438 hbox->setStretchFactor( keyidsL, 10 );
1439 mKeyIdsLabels.insert( i + 1, keyidsL );
1440 //hbox->setStretchFactor( keyidLB, 10 );
1441 //mKeyIdListBoxes.insert( i + 1, keyidLB );
1442
1443 hbox = new TQHBox( bigvbox );
1444 new TQLabel( i18n("Encryption preference:"), hbox );
1445 TQComboBox *encrPrefCombo = new TQComboBox( hbox );
1446 encrPrefCombo->insertItem( i18n("<none>") );
1447 encrPrefCombo->insertItem( i18n("Never Encrypt with This Key") );
1448 encrPrefCombo->insertItem( i18n("Always Encrypt with This Key") );
1449 encrPrefCombo->insertItem( i18n("Encrypt Whenever Encryption is Possible") );
1450 encrPrefCombo->insertItem( i18n("Always Ask") );
1451 encrPrefCombo->insertItem( i18n("Ask Whenever Encryption is Possible") );
1452
1453 EncryptPref encrPref = pgp->encryptionPreference( *ait );
1454 switch( encrPref ) {
1455 case NeverEncrypt:
1456 encrPrefCombo->setCurrentItem( 1 );
1457 break;
1458 case AlwaysEncrypt:
1459 encrPrefCombo->setCurrentItem( 2 );
1460 break;
1461 case AlwaysEncryptIfPossible:
1462 encrPrefCombo->setCurrentItem( 3 );
1463 break;
1464 case AlwaysAskForEncryption:
1465 encrPrefCombo->setCurrentItem( 4 );
1466 break;
1467 case AskWheneverPossible:
1468 encrPrefCombo->setCurrentItem( 5 );
1469 break;
1470 default:
1471 encrPrefCombo->setCurrentItem( 0 );
1472 }
1473 connect( encrPrefCombo, TQ_SIGNAL(activated(int)),
1474 this, TQ_SLOT(slotPrefsChanged(int)) );
1475 mEncrPrefCombos.insert( i, encrPrefCombo );
1476 }
1477 connect( mChangeButtonGroup, TQ_SIGNAL(clicked(int)),
1478 this, TQ_SLOT(slotChangeEncryptionKey(int)) );
1479
1480 // calculate the optimal width for the dialog
1481 int dialogWidth = marginHint()
1482 + sv->frameWidth()
1483 + bigvbox->sizeHint().width()
1484 + sv->verticalScrollBar()->sizeHint().width()
1485 + sv->frameWidth()
1486 + marginHint()
1487 + 2;
1488 // calculate the optimal height for the dialog
1489 int dialogHeight = marginHint()
1490 + label->sizeHint().height()
1491 + topLayout->spacing()
1492 + sv->frameWidth()
1493 + bigvbox->sizeHint().height()
1494 + sv->horizontalScrollBar()->sizeHint().height()
1495 + sv->frameWidth()
1496 + topLayout->spacing()
1497 + actionButton( KDialogBase::Cancel )->sizeHint().height()
1498 + marginHint()
1499 + 2;
1500 // don't make the dialog too large
1501 TQRect desk = TDEGlobalSettings::desktopGeometry(this);
1502 int screenWidth = desk.width();
1503 if( dialogWidth > 3*screenWidth/4 )
1504 dialogWidth = 3*screenWidth/4;
1505 int screenHeight = desk.height();
1506 if( dialogHeight > 7*screenHeight/8 )
1507 dialogHeight = 7*screenHeight/8;
1508
1509 setInitialSize( TQSize( dialogWidth, dialogHeight ) );
1510}
1511
1512void
1513KeyApprovalDialog::slotChangeEncryptionKey( int nr )
1514{
1515 Kpgp::Module *pgp = Kpgp::Module::getKpgp();
1516
1517 kdDebug(5100)<<"Key approval dialog size is "
1518 <<width()<<"x"<<height()<<endl;
1519
1520 if( pgp == 0 )
1521 return;
1522
1523 if( !mEncryptToSelf )
1524 nr++;
1525 KeyIDList keyIds = mKeys[nr];
1526 if( nr == 0 ) {
1527 keyIds = pgp->selectPublicKeys( i18n("Encryption Key Selection"),
1528 i18n("if in your language something like "
1529 "'key(s)' isn't possible please "
1530 "use the plural in the translation",
1531 "Select the key(s) which should "
1532 "be used to encrypt the message "
1533 "to yourself."),
1534 keyIds,
1535 "",
1536 mAllowedKeys );
1537 }
1538 else {
1539 keyIds = pgp->selectPublicKeys( i18n("Encryption Key Selection"),
1540 i18n("if in your language something like "
1541 "'key(s)' isn't possible please "
1542 "use the plural in the translation",
1543 "Select the key(s) which should "
1544 "be used to encrypt the message "
1545 "for\n%1")
1546 .arg( mAddressLabels[nr-1]->text() ),
1547 keyIds,
1548 mAddressLabels[nr-1]->text(),
1549 mAllowedKeys );
1550 }
1551 if( !keyIds.isEmpty() ) {
1552 mKeys[nr] = keyIds;
1553 TQLabel* keyidsL = mKeyIdsLabels[nr];
1554 keyidsL->setText( "0x" + keyIds.toStringList().join( "\n0x" ) );
1555 /*
1556 TQListBox* qlb = mKeyIdListBoxes[nr];
1557 qlb->clear();
1558 qlb->insertStringList( keyIds.toStringList() );
1559 */
1560 }
1561}
1562
1563
1564void
1565KeyApprovalDialog::slotOk()
1566{
1567 Kpgp::Module *pgp = Kpgp::Module::getKpgp();
1568
1569 if( pgp == 0 ) {
1570 accept();
1571 return;
1572 }
1573
1574 if( mPrefsChanged ) {
1575 // store the changed preferences
1576 for( unsigned int i = 0; i < mAddressLabels.size(); i++ ) {
1577 // traverse all Address and Encryption Preference widgets
1578 EncryptPref encrPref;
1579 switch( mEncrPrefCombos[i]->currentItem() ) {
1580 case 1:
1581 encrPref = NeverEncrypt;
1582 break;
1583 case 2:
1584 encrPref = AlwaysEncrypt;
1585 break;
1586 case 3:
1587 encrPref = AlwaysEncryptIfPossible;
1588 break;
1589 case 4:
1590 encrPref = AlwaysAskForEncryption;
1591 break;
1592 case 5:
1593 encrPref = AskWheneverPossible;
1594 break;
1595 default:
1596 case 0:
1597 encrPref = UnknownEncryptPref;
1598 }
1599 pgp->setEncryptionPreference( mAddressLabels[i]->text(), encrPref );
1600 }
1601 }
1602
1603 accept();
1604}
1605
1606
1607void
1608KeyApprovalDialog::slotCancel()
1609{
1610 reject();
1611}
1612
1613
1614
1615// ------------------------------------------------------------------------
1616CipherTextDialog::CipherTextDialog( const TQCString & text,
1617 const TQCString & charset, TQWidget *parent,
1618 const char *name, bool modal )
1619 :KDialogBase( parent, name, modal, i18n("OpenPGP Information"), Ok|Cancel, Ok)
1620{
1621 // FIXME (post KDE2.2): show some more info, e.g. the output of GnuPG/PGP
1622 TQFrame *page = makeMainWidget();
1623 TQVBoxLayout *topLayout = new TQVBoxLayout( page, 0, spacingHint() );
1624
1625 TQLabel *label = new TQLabel( page );
1626 label->setText(i18n("Result of the last encryption/sign operation:"));
1627 topLayout->addWidget( label );
1628
1629 mEditBox = new TQMultiLineEdit( page );
1630 mEditBox->setReadOnly(true);
1631 topLayout->addWidget( mEditBox, 10 );
1632
1633 TQString unicodeText;
1634 if (charset.isEmpty())
1635 unicodeText = TQString::fromLocal8Bit(text.data());
1636 else {
1637 bool ok=true;
1638 TQTextCodec *codec = TDEGlobal::charsets()->codecForName(charset, ok);
1639 if(!ok)
1640 unicodeText = TQString::fromLocal8Bit(text.data());
1641 else
1642 unicodeText = codec->toUnicode(text.data(), text.length());
1643 }
1644
1645 mEditBox->setText(unicodeText);
1646
1647 setMinimumSize();
1648}
1649
1650void CipherTextDialog::setMinimumSize()
1651{
1652 // this seems to force a layout of the entire document, so we get a
1653 // a proper contentsWidth(). Is there a better way?
1654 for ( int i = 0; i < mEditBox->paragraphs(); i++ )
1655 (void) mEditBox->paragraphRect( i );
1656
1657 mEditBox->setMinimumHeight( mEditBox->fontMetrics().lineSpacing() * 25 );
1658
1659 int textWidth = mEditBox->contentsWidth() + 30;
1660
1661
1662#if KDE_IS_VERSION( 3, 1, 90 )
1663 int maxWidth = TDEGlobalSettings::desktopGeometry(parentWidget()).width()-100;
1664#else
1665 TDEConfig gc("kdeglobals", false, false);
1666 gc.setGroup("Windows");
1667 int maxWidth;
1668 if (TQApplication::desktop()->isVirtualDesktop() &&
1669 gc.readBoolEntry("XineramaEnabled", true) &&
1670 gc.readBoolEntry("XineramaPlacementEnabled", true)) {
1671 maxWidth = TQApplication::desktop()->screenGeometry(TQApplication::desktop()->screenNumber(parentWidget())).width()-100;
1672 } else {
1673 maxWidth = TQApplication::desktop()->geometry().width()-100;
1674 }
1675#endif
1676
1677 mEditBox->setMinimumWidth( TQMIN( textWidth, maxWidth ) );
1678}
1679
1680void KeyRequester::virtual_hook( int, void* ) {}
1681
1682void PublicKeyRequester::virtual_hook( int id, void* data ) {
1683 base::virtual_hook( id, data );
1684}
1685
1686void SecretKeyRequester::virtual_hook( int id, void* data ) {
1687 base::virtual_hook( id, data );
1688}
1689
1690} // namespace Kpgp
1691
1692
1693
1694#include "kpgpui.moc"
This class is used to store information about a PGP key.
Definition: kpgpkey.h:433
bool invalid() const
Returns true if the key is invalid.
Definition: kpgpkey.h:623
bool secret() const
Returns true if the key is a secret key.
Definition: kpgpkey.h:603
bool isValid() const
Returns true if the key is valid, i.e.
Definition: kpgpkey.cpp:177
bool canSign() const
Returns true if the key can be used to sign data.
Definition: kpgpkey.h:633
bool canEncrypt() const
Returns true if the key can be used to encrypt data.
Definition: kpgpkey.h:628
bool disabled() const
Returns true if the key has been disabled.
Definition: kpgpkey.h:618
bool revoked() const
Returns true if the key has been revoked.
Definition: kpgpkey.h:608
bool expired() const
Returns true if the key has expired.
Definition: kpgpkey.h:613
bool isValidEncryptionKey() const
Returns true if the key is a valid encryption key.
Definition: kpgpkey.cpp:184
Validity keyTrust() const
Returns the trust value of this key.
Definition: kpgpkey.cpp:134
bool isValidSigningKey() const
Returns true if the key is a valid signing key.
Definition: kpgpkey.cpp:191
time_t creationDate() const
Returns the creation date of the primary subkey.
Definition: kpgpkey.h:738