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 
57 const int Kpgp::KeySelectionDialog::sCheckSelectionDelay = 250;
58 
59 namespace Kpgp {
60 
61 PassphraseDialog::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 
94 PassphraseDialog::~PassphraseDialog()
95 {
96 }
97 
98 TQString 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
107 Config::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 
224 Config::~Config()
225 {
226 }
227 
228 void
229 Config::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 
253 void
254 Config::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 // ------------------------------------------------------------------------
282 KeySelectionDialog::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 ( kapp )
297  KWin::setIcons( winId(), kapp->icon(), kapp->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 
397 KeySelectionDialog::~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 
411 KeyID KeySelectionDialog::key() const
412 {
413  if( mListView->isMultiSelection() || mKeyIds.isEmpty() )
414  return KeyID();
415  else
416  return mKeyIds.first();
417 }
418 
419 
420 void 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 
493 TQString 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 
558 TQString 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 
605 int 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 
666 void 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 
718 int
719 KeySelectionDialog::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 
785 KeyID
786 KeySelectionDialog::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 
803 void 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 
852 void KeySelectionDialog::slotSelectionChanged( TQListViewItem * lvi )
853 {
854  slotCheckSelection( lvi );
855 }
856 
857 
858 void 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 
869 void 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 
998 bool 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  kapp->processEvents();
1019  keysAllowed = keysAllowed && ( -1 != keyAdmissibility( *it, AllowExpensiveTrustCheck ) );
1020  pProgressDlg->progressBar()->advance( 1 );
1021  kapp->processEvents();
1022  }
1023 
1024  delete pProgressDlg;
1025  pProgressDlg = 0;
1026 
1027  return keysAllowed;
1028 }
1029 
1030 
1031 void 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 
1045 void 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 
1055 void KeySelectionDialog::slotOk()
1056 {
1057  if( mCheckSelectionTimer->isActive() ) {
1058  slotCheckSelection();
1059  }
1060  mStartSearchTimer->stop();
1061  accept();
1062 }
1063 
1064 
1065 void KeySelectionDialog::slotCancel()
1066 {
1067  mCheckSelectionTimer->stop();
1068  mStartSearchTimer->stop();
1069  mKeyIds.clear();
1070  reject();
1071 }
1072 
1073 void KeySelectionDialog::slotSearch( const TQString & text )
1074 {
1075  mSearchText = text.stripWhiteSpace().upper();
1076  mStartSearchTimer->start( sCheckSelectionDelay, true /*single-shot*/ );
1077 }
1078 
1079 void 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 
1101 void 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 
1112 void 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 
1126 void 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 
1139 bool 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 
1154 void KeySelectionDialog::showAllItems()
1155 {
1156  for ( TQListViewItem * item = mListView->firstChild() ; item ; item = item->nextSibling() )
1157  item->setVisible( true );
1158 }
1159 
1160 // ------------------------------------------------------------------------
1161 KeyRequester::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 
1199 KeyRequester::~KeyRequester() {
1200 
1201 }
1202 
1203 KeyIDList KeyRequester::keyIDs() const {
1204  return mKeys;
1205 }
1206 
1207 void 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 
1223 void 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 
1235 void KeyRequester::slotEraseButtonClicked() {
1236  mKeys.clear();
1237  mLabel->clear();
1238  emit changed();
1239 }
1240 
1241 void KeyRequester::setDialogCaption( const TQString & caption ) {
1242  mDialogCaption = caption;
1243 }
1244 
1245 void KeyRequester::setDialogMessage( const TQString & msg ) {
1246  mDialogMessage = msg;
1247 }
1248 
1249 bool KeyRequester::isMultipleKeysEnabled() const {
1250  return mMulti;
1251 }
1252 
1253 void 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 
1262 int KeyRequester::allowedKeys() const {
1263  return mAllowedKeys;
1264 }
1265 
1266 void KeyRequester::setAllowedKeys( int allowedKeys ) {
1267  mAllowedKeys = allowedKeys;
1268 }
1269 
1270 
1271 PublicKeyRequester::PublicKeyRequester( TQWidget * parent, bool multi,
1272  unsigned int allowed, const char * name )
1273  : KeyRequester( parent, multi, allowed & ~SecretKeys, name )
1274 {
1275 
1276 }
1277 
1278 PublicKeyRequester::~PublicKeyRequester() {
1279 
1280 }
1281 
1282 KeyIDList PublicKeyRequester::keyRequestHook( Module * pgp ) const {
1283  assert( pgp );
1284  return pgp->selectPublicKeys( mDialogCaption, mDialogMessage, mKeys, TQString(), mAllowedKeys );
1285 }
1286 
1287 SecretKeyRequester::SecretKeyRequester( TQWidget * parent, bool multi,
1288  unsigned int allowed, const char * name )
1289  : KeyRequester( parent, multi, allowed & ~PublicKeys, name )
1290 {
1291 
1292 }
1293 
1294 SecretKeyRequester::~SecretKeyRequester() {
1295 
1296 }
1297 
1298 KeyIDList 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 // ------------------------------------------------------------------------
1310 KeyApprovalDialog::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 
1512 void
1513 KeyApprovalDialog::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 
1564 void
1565 KeyApprovalDialog::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 
1607 void
1608 KeyApprovalDialog::slotCancel()
1609 {
1610  reject();
1611 }
1612 
1613 
1614 
1615 // ------------------------------------------------------------------------
1616 CipherTextDialog::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 
1650 void 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 
1680 void KeyRequester::virtual_hook( int, void* ) {}
1681 
1682 void PublicKeyRequester::virtual_hook( int id, void* data ) {
1683  base::virtual_hook( id, data );
1684 }
1685 
1686 void 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