• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdepim API Reference
  • KDE Home
  • Contact Us
 

kleopatra

  • sources
  • kde-4.14
  • kdepim
  • kleopatra
  • dialogs
certificatedetailsdialog.cpp
Go to the documentation of this file.
1 /* -*- mode: c++; c-basic-offset:4 -*-
2  dialogs/certificatedetailsdialog.cpp
3 
4  This file is part of Kleopatra, the KDE keymanager
5  Copyright (c) 2008 Klarälvdalens Datakonsult AB
6 
7  Kleopatra is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 2 of the License, or
10  (at your option) any later version.
11 
12  Kleopatra is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 
21  In addition, as a special exception, the copyright holders give
22  permission to link the code of this program with any edition of
23  the Qt library by Trolltech AS, Norway (or with modified versions
24  of Qt that use the same license as Qt), and distribute linked
25  combinations including the two. You must obey the GNU General
26  Public License in all respects for all of the code used other than
27  Qt. If you modify this file, you may extend this exception to
28  your version of the file, but you are not obligated to do so. If
29  you do not wish to do so, delete this exception statement from
30  your version.
31 */
32 
33 #include <config-kleopatra.h>
34 
35 #include "certificatedetailsdialog.h"
36 
37 #include "ui_certificatedetailsdialog.h"
38 
39 #include <models/useridlistmodel.h>
40 #include <models/subkeylistmodel.h>
41 #include <models/keycache.h>
42 
43 #include <commands/changepassphrasecommand.h>
44 #include <commands/changeownertrustcommand.h>
45 #include <commands/changeexpirycommand.h>
46 #include <commands/adduseridcommand.h>
47 #include <commands/certifycertificatecommand.h>
48 #include <commands/dumpcertificatecommand.h>
49 
50 #include <utils/formatting.h>
51 #include <utils/gnupg-helper.h>
52 
53 #include <kleo/cryptobackendfactory.h>
54 #include <kleo/cryptobackend.h>
55 #include <kleo/keylistjob.h>
56 #include <kleo/dn.h>
57 
58 #include <gpgme++/key.h>
59 #include <gpgme++/keylistresult.h>
60 
61 #include <KDebug>
62 #include <KMessageBox>
63 #include <KLocalizedString>
64 #include <KGlobalSettings>
65 
66 #include <QPointer>
67 #include <QHeaderView>
68 
69 #ifndef Q_MOC_RUN
70 #include <boost/mem_fn.hpp>
71 #endif
72 
73 #include <algorithm>
74 #include <cassert>
75 
76 using namespace Kleo;
77 using namespace Kleo::Dialogs;
78 using namespace Kleo::Commands;
79 using namespace GpgME;
80 using namespace boost;
81 
82 static bool own( const std::vector<UserID::Signature> & sigs ) {
83  const shared_ptr<const KeyCache> kc = KeyCache::instance();
84  Q_FOREACH( const UserID::Signature & sig, sigs ) {
85  const Key signer = kc->findByKeyIDOrFingerprint( sig.signerKeyID() );
86  if ( signer.isNull() || !signer.hasSecret() )
87  return false;
88  }
89  return !sigs.empty();
90 }
91 
92 class CertificateDetailsDialog::Private {
93  friend class ::Kleo::Dialogs::CertificateDetailsDialog;
94  CertificateDetailsDialog * const q;
95 public:
96  explicit Private( CertificateDetailsDialog * qq )
97  : q( qq ),
98  key(),
99  certificationsModel(),
100  subkeysModel(),
101  ui( q )
102  {
103  ui.certificationsTV->setModel( &certificationsModel );
104  connect( ui.certificationsTV->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
105  q, SLOT(slotCertificationSelectionChanged()) );
106  connect( ui.changePassphrasePB, SIGNAL(clicked()),
107  q, SLOT(slotChangePassphraseClicked()) );
108  connect( ui.changeTrustLevelPB, SIGNAL(clicked()),
109  q, SLOT(slotChangeTrustLevelClicked()) );
110  connect( ui.changeExpiryDatePB, SIGNAL(clicked()),
111  q, SLOT(slotChangeExpiryDateClicked()) );
112  connect( ui.revokeCertificationPB, SIGNAL(clicked()),
113  q, SLOT(slotRevokeCertificationClicked()) );
114  connect( ui.addUserIDPB, SIGNAL(clicked()),
115  q, SLOT(slotAddUserIDClicked()) );
116  connect( ui.revokeUserIDPB, SIGNAL(clicked()),
117  q, SLOT(slotRevokeUserIDClicked()) );
118  connect( ui.certifyUserIDPB, SIGNAL(clicked()),
119  q, SLOT(slotCertifyUserIDClicked()) );
120  connect( ui.revokeCertificationPB, SIGNAL(clicked()),
121  q, SLOT(slotRevokeCertificationClicked()) );
122  connect( ui.showCertificationsPB, SIGNAL(clicked()),
123  q, SLOT(slotShowCertificationsClicked()) );
124 
125 
126  ui.subkeyTV->setModel( &subkeysModel );
127  // no selection (yet)
128 
129  connect( KeyCache::instance().get(), SIGNAL(keysMayHaveChanged()),
130  q, SLOT(slotKeysMayHaveChanged()) );
131  }
132 
133  void readConfig()
134  {
135  KConfigGroup dialog( KGlobal::config(), "CertificateDetailsDialog" );
136  const QSize size = dialog.readEntry( "Size", QSize(600, 400) );
137  if ( size.isValid() ) {
138  q->resize( size );
139  }
140  }
141 
142  void writeConfig()
143  {
144  KConfigGroup dialog( KGlobal::config(), "CertificateDetailsDialog" );
145  dialog.writeEntry( "Size", q->size() );
146  dialog.sync();
147  }
148 
149 private:
150  void startCommandImplementation( const QPointer<Command> & ptr, const char * slot ) {
151  connect( ptr, SIGNAL(finished()), q, slot );
152  ptr->start();
153  enableDisableWidgets();
154  }
155  template <typename T, typename A>
156  void startCommand( QPointer<Command> & ptr, const A & arg, const char * slot ) {
157  if ( ptr )
158  return;
159  ptr = new T( arg );
160  startCommandImplementation( ptr, slot );
161  }
162  template <typename T>
163  void startCommand( QPointer<Command> & ptr, const char * slot ) {
164  startCommand<T>( ptr, this->key, slot );
165  }
166  void commandFinished( QPointer<Command> & ptr ) {
167  ptr = 0;
168  enableDisableWidgets();
169  }
170 
171  void slotChangePassphraseClicked() {
172  startCommand<ChangePassphraseCommand>( changePassphraseCommand, SLOT(slotChangePassphraseCommandFinished()) );
173  }
174  void slotChangePassphraseCommandFinished() {
175  commandFinished( changePassphraseCommand );
176  }
177 
178  void slotChangeTrustLevelClicked() {
179  startCommand<ChangeOwnerTrustCommand>( changeOwnerTrustCommand, SLOT(slotChangeOwnerTrustCommandFinished()) );
180  }
181  void slotChangeOwnerTrustCommandFinished() {
182  commandFinished( changeOwnerTrustCommand );
183  }
184 
185  void slotChangeExpiryDateClicked() {
186  startCommand<ChangeExpiryCommand>( changeExpiryDateCommand, SLOT(slotChangeExpiryDateCommandFinished()) );
187  }
188  void slotChangeExpiryDateCommandFinished() {
189  commandFinished( changeExpiryDateCommand );
190  }
191 
192  void slotAddUserIDClicked() {
193  startCommand<AddUserIDCommand>( addUserIDCommand, SLOT(slotAddUserIDCommandFinished()) );
194  }
195  void slotAddUserIDCommandFinished() {
196  commandFinished( addUserIDCommand );
197  }
198 
199  void slotCertifyUserIDClicked() {
200  const std::vector<UserID> uids = selectedUserIDs();
201  if ( uids.empty() )
202  return;
203  startCommand<CertifyCertificateCommand>( signCertificateCommand, uids, SLOT(slotSignCertificateCommandFinished()) );
204  }
205  void slotSignCertificateCommandFinished() {
206  commandFinished( signCertificateCommand );
207  }
208 
209  void slotRevokeCertificateClicked() {
210 
211  }
212 
213  void slotRevokeUserIDClicked() {
214 
215  }
216 
217  void slotRevokeCertificationClicked() {
218 
219  }
220 
221  void slotShowCertificationsClicked() {
222  startSignatureListing();
223  enableDisableWidgets();
224  }
225 
226  void startSignatureListing() {
227  if ( keyListJob )
228  return;
229  const CryptoBackend::Protocol * const protocol = CryptoBackendFactory::instance()->protocol( key.protocol() );
230  if ( !protocol )
231  return;
232  KeyListJob * const job = protocol->keyListJob( /*remote*/false, /*includeSigs*/true, /*validate*/true );
233  if ( !job )
234  return;
235  connect( job, SIGNAL(result(GpgME::KeyListResult)),
236  q, SLOT(slotSignatureListingDone(GpgME::KeyListResult)) );
237  connect( job, SIGNAL(nextKey(GpgME::Key)),
238  q, SLOT(slotSignatureListingNextKey(GpgME::Key)) );
239  if ( const Error err = job->start( QStringList( QString::fromLatin1( key.primaryFingerprint() ) ) ) )
240  showSignatureListingErrorDialog( err );
241  else
242  keyListJob = job;
243  }
244  void slotSignatureListingNextKey( const Key & key ) {
245  // don't lose the secret flags ...
246  Key merged = key;
247  merged.mergeWith( this->key );
248  q->setKey( merged );
249 
250  // fixup the tree view
251  ui.certificationsTV->expandAll();
252  ui.certificationsTV->header()->resizeSections( QHeaderView::ResizeToContents );
253  }
254  void slotSignatureListingDone( const KeyListResult & result ) {
255  if ( result.error().isCanceled() )
256  ;
257  else if ( result.error() )
258  showSignatureListingErrorDialog( result.error() );
259  else {
260  ; // nothing to do
261  }
262  keyListJob = 0;
263  enableDisableWidgets();
264  }
265  void showSignatureListingErrorDialog( const Error & err ) {
266  KMessageBox::information( q, i18nc("@info",
267  "<para>An error occurred while loading the certifications: "
268  "<message>%1</message></para>",
269  QString::fromLocal8Bit( err.asString() ) ),
270  i18nc("@title","Certifications Loading Failed") );
271  }
272 
273  void slotCertificationSelectionChanged() {
274  enableDisableWidgets();
275  }
276 
277  void slotKeysMayHaveChanged() {
278  if ( const char * const fpr = key.primaryFingerprint() )
279  if ( !(key.keyListMode() & Extern) )
280  q->setKey( KeyCache::instance()->findByFingerprint( fpr ) );
281  }
282 
283  void slotDumpCertificate() {
284 
285  if ( dumpCertificateCommand )
286  return;
287 
288  if ( key.protocol() != CMS ) {
289  ui.dumpLTW->clear();
290  return;
291  }
292 
293  ui.dumpLTW->setLines( QStringList( i18n("Please wait while generating the dump...") ) );
294 
295  dumpCertificateCommand = new DumpCertificateCommand( key );
296  dumpCertificateCommand->setUseDialog( false );
297  QPointer<Command> cmd = dumpCertificateCommand.data();
298  startCommandImplementation( cmd, SLOT(slotDumpCertificateCommandFinished()) );
299  }
300 
301  void slotDumpCertificateCommandFinished() {
302  ui.dumpLTW->setLines( dumpCertificateCommand->output() );
303  }
304 
305 private:
306  void updateWidgetVisibility() {
307  const bool x509 = key.protocol() == CMS;
308  const bool pgp = key.protocol() == OpenPGP;
309  const bool secret = key.hasSecret();
310  const bool sigs = (key.keyListMode() & Signatures);
311  const bool ultimateTrust = key.ownerTrust() == Key::Ultimate;
312  const bool external = (key.keyListMode() & Extern);
313 
314  // Overview Tab
315  ui.overviewActionsGB->setVisible( !external );
316  ui.changePassphrasePB->setVisible( secret );
317  ui.changeTrustLevelPB->setVisible( pgp && ( !secret || !ultimateTrust ) );
318  ui.changeExpiryDatePB->setVisible( pgp && secret );
319 
320  // Certifications Tab
321  ui.userIDsActionsGB->setVisible( !external && pgp );
322  ui.certificationsActionGB->setVisible( !external && pgp );
323  ui.addUserIDPB->setVisible( secret );
324  ui.expandAllCertificationsPB->setVisible( pgp && sigs );
325  ui.collapseAllCertificationsPB->setVisible( pgp && sigs );
326  ui.showCertificationsPB->setVisible( !external && pgp && !sigs );
327 
328  // Technical Details Tab
329  ui.tabWidget->setTabEnabled( ui.tabWidget->indexOf( ui.detailsTab ), pgp );
330 
331  // Chain tab
332  ui.tabWidget->setTabEnabled( ui.tabWidget->indexOf( ui.chainTab ), x509 );
333 
334  // Dump tab
335  ui.tabWidget->setTabEnabled( ui.tabWidget->indexOf( ui.dumpTab ), x509 );
336 
337  // not implemented:
338  ui.revokeCertificatePB->hide();
339  ui.revokeUserIDPB->hide();
340  ui.certificationsActionGB->hide();
341  }
342 
343  QModelIndexList selectedCertificationsIndexes() const {
344  return ui.certificationsTV->selectionModel()->selectedRows();
345  }
346 
347  std::vector<UserID> selectedUserIDs() const {
348  const QModelIndexList mil = selectedCertificationsIndexes();
349  std::vector<UserID> uids = certificationsModel.userIDs( mil, true );
350  uids.erase( std::remove_if( uids.begin(), uids.end(), mem_fn( &UserID::isNull ) ), uids.end() );
351  return uids;
352  }
353 
354  std::vector<UserID::Signature> selectedSignatures() const {
355  const QModelIndexList mil = selectedCertificationsIndexes();
356  std::vector<UserID::Signature> sigs = certificationsModel.signatures( mil );
357  sigs.erase( std::remove_if( sigs.begin(), sigs.end(), mem_fn( &UserID::Signature::isNull ) ), sigs.end() );
358  return sigs;
359  }
360 
361  void enableDisableWidgets() {
362  // Overview Tab
363  ui.changePassphrasePB->setEnabled( !changePassphraseCommand );
364  ui.changeTrustLevelPB->setEnabled( !changeOwnerTrustCommand );
365  ui.changeExpiryDatePB->setEnabled( !changeExpiryDateCommand );
366 
367  // Certifications Tab
368  ui.addUserIDPB->setEnabled( !addUserIDCommand );
369  ui.showCertificationsPB->setEnabled( !keyListJob );
370  ui.showCertificationsPB->setText( keyListJob
371  ? i18n("(please wait while certifications are being loaded)")
372  : i18n("Load Certifications (may take a while)") );
373 
374  const std::vector<UserID> uids = selectedUserIDs();
375  const std::vector<UserID::Signature> sigs = selectedSignatures();
376 
377  ui.certifyUserIDPB->setEnabled( !uids.empty() && sigs.empty() && !signCertificateCommand );
378  ui.revokeUserIDPB->setEnabled( !uids.empty() && sigs.empty() );
379  ui.revokeCertificationPB->setEnabled( uids.empty() && !sigs.empty() && own( sigs ) );
380  }
381 
382  void updateLabel() {
383  ui.overviewLB->setText( Formatting::formatOverview( key ) );
384  }
385 
386  void updateChainTab() {
387  ui.chainTW->clear();
388 
389  if ( key.protocol() != CMS )
390  return;
391 
392  QTreeWidgetItem * last = 0;
393  const std::vector<Key> chain = KeyCache::instance()->findIssuers( key, KeyCache::RecursiveSearch|KeyCache::IncludeSubject );
394  if ( chain.empty() )
395  return;
396  if ( !chain.back().isRoot() ) {
397  last = new QTreeWidgetItem( ui.chainTW );
398  last->setText( 0, i18n("Issuer Certificate Not Found (%1)",
399  DN( chain.back().issuerName() ).prettyDN() ) );
400  //last->setSelectable( false );
401  const QBrush & fg = ui.chainTW->palette().brush( QPalette::Disabled, QPalette::WindowText );
402  last->setForeground( 0, fg );
403  }
404  for ( std::vector<Key>::const_reverse_iterator it = chain.rbegin(), end = chain.rend() ; it != end ; ++it ) {
405  last = last ? new QTreeWidgetItem( last ) : new QTreeWidgetItem( ui.chainTW ) ;
406  last->setText( 0, DN( it->userID(0).id() ).prettyDN() );
407  //last->setSelectable( true );
408  }
409  ui.chainTW->expandAll();
410  }
411 
412  void propagateKey() {
413  certificationsModel.setKey( key );
414  const QModelIndexList uidIndexes = certificationsModel.indexes( key.userIDs() );
415  Q_FOREACH( const QModelIndex & idx, uidIndexes )
416  ui.certificationsTV->setFirstColumnSpanned( idx.row(), idx.parent(), true );
417 
418  subkeysModel.setKey( key );
419  ui.subkeyTV->header()->resizeSections( QHeaderView::ResizeToContents );
420 
421  updateChainTab();
422  slotDumpCertificate();
423  }
424 
425 
426 private:
427  Key key;
428  UserIDListModel certificationsModel;
429  SubkeyListModel subkeysModel;
430 
431  QPointer<Command> changePassphraseCommand;
432  QPointer<Command> changeOwnerTrustCommand;
433  QPointer<Command> changeExpiryDateCommand;
434 
435  QPointer<Command> addUserIDCommand;
436  QPointer<Command> signCertificateCommand;
437 
438  QPointer<DumpCertificateCommand> dumpCertificateCommand;
439 
440  QPointer<KeyListJob> keyListJob;
441 
442  struct UI : public Ui_CertificateDetailsDialog {
443  explicit UI( Dialogs::CertificateDetailsDialog * qq )
444  : Ui_CertificateDetailsDialog()
445  {
446  setupUi( qq->mainWidget() );
447  qq->setButtons( KDialog::Help | KDialog::Close );
448  qq->setHelp(QString(), QLatin1String("kleopatra"));
449  chainTW->header()->setResizeMode( 0, QHeaderView::Stretch );
450 
451  dumpLTW->setFont( KGlobalSettings::fixedFont() );
452  dumpLTW->setMinimumVisibleLines( 15 );
453  dumpLTW->setMinimumVisibleColumns( 40 );
454 
455  subkeyHLine->setTitle( i18nc("@title","Subkeys") );
456  }
457  } ui;
458 };
459 
460 CertificateDetailsDialog::CertificateDetailsDialog( QWidget * p, Qt::WindowFlags f )
461  : KDialog( p, f ), d( new Private( this ) )
462 {
463  d->readConfig();
464 }
465 
466 CertificateDetailsDialog::~CertificateDetailsDialog()
467 {
468  d->writeConfig();
469 }
470 
471 
472 void CertificateDetailsDialog::setKey( const Key & key ) {
473  d->key = key;
474  d->updateWidgetVisibility();
475  d->updateLabel();
476  d->propagateKey();
477  d->enableDisableWidgets();
478 }
479 
480 Key CertificateDetailsDialog::key() const {
481  return d->key;
482 }
483 
484 
485 #include "moc_certificatedetailsdialog.cpp"
Kleo::Dialogs::CertificateDetailsDialog::setKey
void setKey(const GpgME::Key &key)
Definition: certificatedetailsdialog.cpp:472
QModelIndex
Kleo::Dialogs::CertificateDetailsDialog::CertificateDetailsDialog
CertificateDetailsDialog(QWidget *parent=0, Qt::WindowFlags f=0)
Definition: certificatedetailsdialog.cpp:460
QWidget
adduseridcommand.h
QSize::isValid
bool isValid() const
QPointer::data
T * data() const
useridlistmodel.h
Kleo::Formatting::formatOverview
QString formatOverview(const GpgME::Key &key)
QPointer
formatting.h
QBrush
KDialog
Kleo::KeyCache::RecursiveSearch
Definition: keycache.h:123
boost::shared_ptr
Definition: encryptemailcontroller.h:51
QString::fromLocal8Bit
QString fromLocal8Bit(const char *str, int size)
d
#define d
Definition: adduseridcommand.cpp:89
own
static bool own(const std::vector< UserID::Signature > &sigs)
Definition: certificatedetailsdialog.cpp:82
Kleo::SubkeyListModel
Definition: subkeylistmodel.h:48
Kleo::Dialogs::CertificateDetailsDialog::~CertificateDetailsDialog
~CertificateDetailsDialog()
Definition: certificatedetailsdialog.cpp:466
Kleo::Class::OpenPGP
Definition: classify.h:49
changeownertrustcommand.h
Kleo::Class::CMS
Definition: classify.h:48
subkeylistmodel.h
QString
QStringList
gnupg-helper.h
QSize
Kleo::KeyCache::IncludeSubject
Definition: keycache.h:124
QItemSelection
dumpcertificatecommand.h
QTreeWidgetItem
QLatin1String
slot
const char * slot
Definition: keylistcontroller.cpp:290
Kleo::UserIDListModel
Definition: useridlistmodel.h:45
q
#define q
Definition: adduseridcommand.cpp:90
QTreeWidgetItem::setText
void setText(int column, const QString &text)
Kleo::KeyCache::instance
static boost::shared_ptr< const KeyCache > instance()
Definition: keycache.cpp:190
certifycertificatecommand.h
certificatedetailsdialog.h
QString::fromLatin1
QString fromLatin1(const char *str, int size)
Kleo::Commands::DumpCertificateCommand
Definition: dumpcertificatecommand.h:41
Qt::WindowFlags
typedef WindowFlags
QHeaderView
keycache.h
changeexpirycommand.h
Kleo::Command
Definition: commands/command.h:58
Kleo::Dialogs::CertificateDetailsDialog::key
GpgME::Key key() const
Definition: certificatedetailsdialog.cpp:480
Kleo::Dialogs::CertificateDetailsDialog
Definition: certificatedetailsdialog.h:49
QTreeWidgetItem::setForeground
void setForeground(int column, const QBrush &brush)
changepassphrasecommand.h
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:33:10 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kleopatra

Skip menu "kleopatra"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

kdepim API Reference

Skip menu "kdepim API Reference"
  • akonadi_next
  • akregator
  • blogilo
  • calendarsupport
  • console
  •   kabcclient
  •   konsolekalendar
  • kaddressbook
  • kalarm
  •   lib
  • kdgantt2
  • kjots
  • kleopatra
  • kmail
  • knode
  • knotes
  • kontact
  • korgac
  • korganizer
  • ktimetracker
  • libkdepim
  • libkleo
  • libkpgp
  • mailcommon
  • messagelist
  • messageviewer
  • pimprint

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal