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