33 #include <config-kleopatra.h>
37 #include "ui_certificatedetailsdialog.h"
53 #include <kleo/cryptobackendfactory.h>
54 #include <kleo/cryptobackend.h>
55 #include <kleo/keylistjob.h>
58 #include <gpgme++/key.h>
59 #include <gpgme++/keylistresult.h>
62 #include <KMessageBox>
63 #include <KLocalizedString>
64 #include <KGlobalSettings>
67 #include <QHeaderView>
69 #include <boost/mem_fn.hpp>
75 using namespace Kleo::Dialogs;
76 using namespace Kleo::Commands;
77 using namespace GpgME;
78 using namespace boost;
80 static bool own(
const std::vector<UserID::Signature> & sigs ) {
82 Q_FOREACH(
const UserID::Signature & sig, sigs ) {
83 const Key signer = kc->findByKeyIDOrFingerprint( sig.signerKeyID() );
84 if ( signer.isNull() || !signer.hasSecret() )
90 class CertificateDetailsDialog::Private {
91 friend class ::Kleo::Dialogs::CertificateDetailsDialog;
97 certificationsModel(),
101 ui.certificationsTV->setModel( &certificationsModel );
102 connect( ui.certificationsTV->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
103 q, SLOT(slotCertificationSelectionChanged()) );
104 connect( ui.changePassphrasePB, SIGNAL(clicked()),
105 q, SLOT(slotChangePassphraseClicked()) );
106 connect( ui.changeTrustLevelPB, SIGNAL(clicked()),
107 q, SLOT(slotChangeTrustLevelClicked()) );
108 connect( ui.changeExpiryDatePB, SIGNAL(clicked()),
109 q, SLOT(slotChangeExpiryDateClicked()) );
110 connect( ui.revokeCertificationPB, SIGNAL(clicked()),
111 q, SLOT(slotRevokeCertificationClicked()) );
112 connect( ui.addUserIDPB, SIGNAL(clicked()),
113 q, SLOT(slotAddUserIDClicked()) );
114 connect( ui.revokeUserIDPB, SIGNAL(clicked()),
115 q, SLOT(slotRevokeUserIDClicked()) );
116 connect( ui.certifyUserIDPB, SIGNAL(clicked()),
117 q, SLOT(slotCertifyUserIDClicked()) );
118 connect( ui.revokeCertificationPB, SIGNAL(clicked()),
119 q, SLOT(slotRevokeCertificationClicked()) );
120 connect( ui.showCertificationsPB, SIGNAL(clicked()),
121 q, SLOT(slotShowCertificationsClicked()) );
124 ui.subkeyTV->setModel( &subkeysModel );
128 q, SLOT(slotKeysMayHaveChanged()) );
132 void startCommandImplementation(
const QPointer<Command> & ptr,
const char *
slot ) {
133 connect( ptr, SIGNAL(finished()),
q, slot );
135 enableDisableWidgets();
137 template <
typename T,
typename A>
138 void startCommand( QPointer<Command> & ptr,
const A & arg,
const char * slot ) {
142 startCommandImplementation( ptr, slot );
144 template <
typename T>
145 void startCommand( QPointer<Command> & ptr,
const char * slot ) {
146 startCommand<T>( ptr, this->key,
slot );
148 void commandFinished( QPointer<Command> & ptr ) {
150 enableDisableWidgets();
153 void slotChangePassphraseClicked() {
154 startCommand<ChangePassphraseCommand>( changePassphraseCommand, SLOT(slotChangePassphraseCommandFinished()) );
156 void slotChangePassphraseCommandFinished() {
157 commandFinished( changePassphraseCommand );
160 void slotChangeTrustLevelClicked() {
161 startCommand<ChangeOwnerTrustCommand>( changeOwnerTrustCommand, SLOT(slotChangeOwnerTrustCommandFinished()) );
163 void slotChangeOwnerTrustCommandFinished() {
164 commandFinished( changeOwnerTrustCommand );
167 void slotChangeExpiryDateClicked() {
168 startCommand<ChangeExpiryCommand>( changeExpiryDateCommand, SLOT(slotChangeExpiryDateCommandFinished()) );
170 void slotChangeExpiryDateCommandFinished() {
171 commandFinished( changeExpiryDateCommand );
174 void slotAddUserIDClicked() {
175 startCommand<AddUserIDCommand>( addUserIDCommand, SLOT(slotAddUserIDCommandFinished()) );
177 void slotAddUserIDCommandFinished() {
178 commandFinished( addUserIDCommand );
181 void slotCertifyUserIDClicked() {
182 const std::vector<UserID> uids = selectedUserIDs();
185 startCommand<CertifyCertificateCommand>( signCertificateCommand, uids, SLOT(slotSignCertificateCommandFinished()) );
187 void slotSignCertificateCommandFinished() {
188 commandFinished( signCertificateCommand );
191 void slotRevokeCertificateClicked() {
195 void slotRevokeUserIDClicked() {
199 void slotRevokeCertificationClicked() {
203 void slotShowCertificationsClicked() {
204 startSignatureListing();
205 enableDisableWidgets();
208 void startSignatureListing() {
211 const CryptoBackend::Protocol *
const protocol = CryptoBackendFactory::instance()->protocol( key.protocol() );
214 KeyListJob *
const job = protocol->keyListJob(
false,
true,
true );
217 connect( job, SIGNAL(result(GpgME::KeyListResult)),
218 q, SLOT(slotSignatureListingDone(GpgME::KeyListResult)) );
219 connect( job, SIGNAL(nextKey(GpgME::Key)),
220 q, SLOT(slotSignatureListingNextKey(GpgME::Key)) );
221 if (
const Error err = job->start( QStringList( QString::fromLatin1( key.primaryFingerprint() ) ) ) )
222 showSignatureListingErrorDialog( err );
226 void slotSignatureListingNextKey(
const Key & key ) {
229 merged.mergeWith( this->key );
233 ui.certificationsTV->expandAll();
234 ui.certificationsTV->header()->resizeSections( QHeaderView::ResizeToContents );
236 void slotSignatureListingDone(
const KeyListResult & result ) {
237 if ( result.error().isCanceled() )
239 else if ( result.error() )
240 showSignatureListingErrorDialog( result.error() );
245 enableDisableWidgets();
247 void showSignatureListingErrorDialog(
const Error & err ) {
248 KMessageBox::information(
q, i18nc(
"@info",
249 "<para>An error occurred while loading the certifications: "
250 "<message>%1</message></para>",
251 QString::fromLocal8Bit( err.asString() ) ),
252 i18nc(
"@title",
"Certifications Loading Failed") );
255 void slotCertificationSelectionChanged() {
256 enableDisableWidgets();
259 void slotKeysMayHaveChanged() {
260 if (
const char *
const fpr = key.primaryFingerprint() )
261 if ( !(key.keyListMode() & Extern) )
265 void slotDumpCertificate() {
267 if ( dumpCertificateCommand )
270 if ( key.protocol() !=
CMS ) {
275 ui.dumpLTW->setLines( QStringList( i18n(
"Please wait while generating the dump...") ) );
278 dumpCertificateCommand->setUseDialog(
false );
279 QPointer<Command> cmd = dumpCertificateCommand.data();
280 startCommandImplementation( cmd, SLOT(slotDumpCertificateCommandFinished()) );
283 void slotDumpCertificateCommandFinished() {
284 ui.dumpLTW->setLines( dumpCertificateCommand->output() );
288 void updateWidgetVisibility() {
289 const bool x509 = key.protocol() ==
CMS;
290 const bool pgp = key.protocol() ==
OpenPGP;
291 const bool secret = key.hasSecret();
292 const bool sigs = (key.keyListMode() & Signatures);
293 const bool ultimateTrust = key.ownerTrust() == Key::Ultimate;
294 const bool external = (key.keyListMode() & Extern);
297 ui.overviewActionsGB->setVisible( !external );
298 ui.changePassphrasePB->setVisible( secret );
299 ui.changeTrustLevelPB->setVisible( pgp && ( !secret || !ultimateTrust ) );
300 ui.changeExpiryDatePB->setVisible( pgp && secret );
303 ui.userIDsActionsGB->setVisible( !external && pgp );
304 ui.certificationsActionGB->setVisible( !external && pgp );
305 ui.addUserIDPB->setVisible( secret );
306 ui.expandAllCertificationsPB->setVisible( pgp && sigs );
307 ui.collapseAllCertificationsPB->setVisible( pgp && sigs );
308 ui.showCertificationsPB->setVisible( !external && pgp && !sigs );
311 ui.tabWidget->setTabEnabled( ui.tabWidget->indexOf( ui.detailsTab ), pgp );
314 ui.tabWidget->setTabEnabled( ui.tabWidget->indexOf( ui.chainTab ), x509 );
317 ui.tabWidget->setTabEnabled( ui.tabWidget->indexOf( ui.dumpTab ), x509 );
320 ui.revokeCertificatePB->hide();
321 ui.revokeUserIDPB->hide();
322 ui.certificationsActionGB->hide();
325 QModelIndexList selectedCertificationsIndexes()
const {
326 return ui.certificationsTV->selectionModel()->selectedRows();
329 std::vector<UserID> selectedUserIDs()
const {
330 const QModelIndexList mil = selectedCertificationsIndexes();
331 std::vector<UserID> uids = certificationsModel.userIDs( mil,
true );
332 uids.erase( std::remove_if( uids.begin(), uids.end(), mem_fn( &UserID::isNull ) ), uids.end() );
336 std::vector<UserID::Signature> selectedSignatures()
const {
337 const QModelIndexList mil = selectedCertificationsIndexes();
338 std::vector<UserID::Signature> sigs = certificationsModel.signatures( mil );
339 sigs.erase( std::remove_if( sigs.begin(), sigs.end(), mem_fn( &UserID::Signature::isNull ) ), sigs.end() );
343 void enableDisableWidgets() {
345 ui.changePassphrasePB->setEnabled( !changePassphraseCommand );
346 ui.changeTrustLevelPB->setEnabled( !changeOwnerTrustCommand );
347 ui.changeExpiryDatePB->setEnabled( !changeExpiryDateCommand );
350 ui.addUserIDPB->setEnabled( !addUserIDCommand );
351 ui.showCertificationsPB->setEnabled( !keyListJob );
352 ui.showCertificationsPB->setText( keyListJob
353 ? i18n(
"(please wait while certifications are being loaded)")
354 : i18n(
"Load Certifications (may take a while)") );
356 const std::vector<UserID> uids = selectedUserIDs();
357 const std::vector<UserID::Signature> sigs = selectedSignatures();
359 ui.certifyUserIDPB->setEnabled( !uids.empty() && sigs.empty() && !signCertificateCommand );
360 ui.revokeUserIDPB->setEnabled( !uids.empty() && sigs.empty() );
361 ui.revokeCertificationPB->setEnabled( uids.empty() && !sigs.empty() &&
own( sigs ) );
368 void updateChainTab() {
371 if ( key.protocol() !=
CMS )
374 QTreeWidgetItem * last = 0;
378 if ( !chain.back().isRoot() ) {
379 last =
new QTreeWidgetItem( ui.chainTW );
380 last->setText( 0, i18n(
"Issuer Certificate Not Found (%1)",
381 DN( chain.back().issuerName() ).prettyDN() ) );
383 const QBrush & fg = ui.chainTW->palette().brush( QPalette::Disabled, QPalette::WindowText );
384 last->setForeground( 0, fg );
386 for ( std::vector<Key>::const_reverse_iterator it = chain.rbegin(), end = chain.rend() ; it != end ; ++it ) {
387 last = last ?
new QTreeWidgetItem( last ) : new QTreeWidgetItem( ui.chainTW ) ;
388 last->setText( 0, DN( it->userID(0).id() ).prettyDN() );
391 ui.chainTW->expandAll();
394 void propagateKey() {
395 certificationsModel.setKey( key );
396 const QModelIndexList uidIndexes = certificationsModel.indexes( key.userIDs() );
397 Q_FOREACH(
const QModelIndex & idx, uidIndexes )
398 ui.certificationsTV->setFirstColumnSpanned( idx.row(), idx.parent(), true );
400 subkeysModel.setKey( key );
401 ui.subkeyTV->header()->resizeSections(
QHeaderView::ResizeToContents );
404 slotDumpCertificate();
413 QPointer<
Command> changePassphraseCommand;
414 QPointer<
Command> changeOwnerTrustCommand;
415 QPointer<
Command> changeExpiryDateCommand;
417 QPointer<
Command> addUserIDCommand;
418 QPointer<
Command> signCertificateCommand;
422 QPointer<KeyListJob> keyListJob;
424 struct UI : public Ui_CertificateDetailsDialog {
426 : Ui_CertificateDetailsDialog()
428 setupUi( qq->mainWidget() );
429 qq->setButtons( KDialog::Help | KDialog::Close );
430 qq->setHelp(QString(), QLatin1String(
"kleopatra"));
431 chainTW->header()->setResizeMode( 0, QHeaderView::Stretch );
433 dumpLTW->setFont( KGlobalSettings::fixedFont() );
434 dumpLTW->setMinimumVisibleLines( 15 );
435 dumpLTW->setMinimumVisibleColumns( 40 );
437 subkeyHLine->setTitle( i18nc(
"@title",
"Subkeys") );
443 :
KDialog( p, f ),
d( new Private( this ) )
453 d->updateWidgetVisibility();
456 d->enableDisableWidgets();
464 #include "moc_certificatedetailsdialog.cpp"
void setKey(const GpgME::Key &key)
CertificateDetailsDialog(QWidget *parent=0, Qt::WindowFlags f=0)
static bool own(const std::vector< UserID::Signature > &sigs)
~CertificateDetailsDialog()
static boost::shared_ptr< const KeyCache > instance()