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 
55 const int Kpgp::KeySelectionDialog::sCheckSelectionDelay = 250;
56 
57 namespace Kpgp {
58 
59 PassphraseDialog::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 
92 PassphraseDialog::~PassphraseDialog()
93 {
94 }
95 
96 TQString 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
105 Config::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 
222 Config::~Config()
223 {
224 }
225 
226 void
227 Config::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 
251 void
252 Config::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 // ------------------------------------------------------------------------
280 KeySelectionDialog::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 ( kapp )
295  KWin::setIcons( winId(), kapp->icon(), kapp->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 
395 KeySelectionDialog::~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 
409 KeyID KeySelectionDialog::key() const
410 {
411  if( mListView->isMultiSelection() || mKeyIds.isEmpty() )
412  return KeyID();
413  else
414  return mKeyIds.first();
415 }
416 
417 
418 void 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 
491 TQString 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 
556 TQString 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 
603 int 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 
664 void 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 
716 int
717 KeySelectionDialog::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 
783 KeyID
784 KeySelectionDialog::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 
801 void 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 
850 void KeySelectionDialog::slotSelectionChanged( TQListViewItem * lvi )
851 {
852  slotCheckSelection( lvi );
853 }
854 
855 
856 void 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 
867 void 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 
996 bool 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  kapp->processEvents();
1017  keysAllowed = keysAllowed && ( -1 != keyAdmissibility( *it, AllowExpensiveTrustCheck ) );
1018  pProgressDlg->progressBar()->advance( 1 );
1019  kapp->processEvents();
1020  }
1021 
1022  delete pProgressDlg;
1023  pProgressDlg = 0;
1024 
1025  return keysAllowed;
1026 }
1027 
1028 
1029 void 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 
1043 void 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 
1053 void KeySelectionDialog::slotOk()
1054 {
1055  if( mCheckSelectionTimer->isActive() ) {
1056  slotCheckSelection();
1057  }
1058  mStartSearchTimer->stop();
1059  accept();
1060 }
1061 
1062 
1063 void KeySelectionDialog::slotCancel()
1064 {
1065  mCheckSelectionTimer->stop();
1066  mStartSearchTimer->stop();
1067  mKeyIds.clear();
1068  reject();
1069 }
1070 
1071 void KeySelectionDialog::slotSearch( const TQString & text )
1072 {
1073  mSearchText = text.stripWhiteSpace().upper();
1074  mStartSearchTimer->start( sCheckSelectionDelay, true /*single-shot*/ );
1075 }
1076 
1077 void 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 
1099 void 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 
1110 void 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 
1124 void 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 
1137 bool 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 
1152 void KeySelectionDialog::showAllItems()
1153 {
1154  for ( TQListViewItem * item = mListView->firstChild() ; item ; item = item->nextSibling() )
1155  item->setVisible( true );
1156 }
1157 
1158 // ------------------------------------------------------------------------
1159 KeyRequester::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 
1197 KeyRequester::~KeyRequester() {
1198 
1199 }
1200 
1201 KeyIDList KeyRequester::keyIDs() const {
1202  return mKeys;
1203 }
1204 
1205 void 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 
1221 void 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 
1233 void KeyRequester::slotEraseButtonClicked() {
1234  mKeys.clear();
1235  mLabel->clear();
1236  emit changed();
1237 }
1238 
1239 void KeyRequester::setDialogCaption( const TQString & caption ) {
1240  mDialogCaption = caption;
1241 }
1242 
1243 void KeyRequester::setDialogMessage( const TQString & msg ) {
1244  mDialogMessage = msg;
1245 }
1246 
1247 bool KeyRequester::isMultipleKeysEnabled() const {
1248  return mMulti;
1249 }
1250 
1251 void 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 
1260 int KeyRequester::allowedKeys() const {
1261  return mAllowedKeys;
1262 }
1263 
1264 void KeyRequester::setAllowedKeys( int allowedKeys ) {
1265  mAllowedKeys = allowedKeys;
1266 }
1267 
1268 
1269 PublicKeyRequester::PublicKeyRequester( TQWidget * parent, bool multi,
1270  unsigned int allowed, const char * name )
1271  : KeyRequester( parent, multi, allowed & ~SecretKeys, name )
1272 {
1273 
1274 }
1275 
1276 PublicKeyRequester::~PublicKeyRequester() {
1277 
1278 }
1279 
1280 KeyIDList PublicKeyRequester::keyRequestHook( Module * pgp ) const {
1281  assert( pgp );
1282  return pgp->selectPublicKeys( mDialogCaption, mDialogMessage, mKeys, TQString(), mAllowedKeys );
1283 }
1284 
1285 SecretKeyRequester::SecretKeyRequester( TQWidget * parent, bool multi,
1286  unsigned int allowed, const char * name )
1287  : KeyRequester( parent, multi, allowed & ~PublicKeys, name )
1288 {
1289 
1290 }
1291 
1292 SecretKeyRequester::~SecretKeyRequester() {
1293 
1294 }
1295 
1296 KeyIDList 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 // ------------------------------------------------------------------------
1308 KeyApprovalDialog::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 
1510 void
1511 KeyApprovalDialog::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 
1562 void
1563 KeyApprovalDialog::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 
1605 void
1606 KeyApprovalDialog::slotCancel()
1607 {
1608  reject();
1609 }
1610 
1611 
1612 
1613 // ------------------------------------------------------------------------
1614 CipherTextDialog::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 
1648 void 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 
1663 void KeyRequester::virtual_hook( int, void* ) {}
1664 
1665 void PublicKeyRequester::virtual_hook( int id, void* data ) {
1666  base::virtual_hook( id, data );
1667 }
1668 
1669 void 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