33 #include <config-kleopatra.h>
44 #include <kleo/stl_util.h>
45 #include <kleo/cryptobackend.h>
46 #include <kleo/cryptobackendfactory.h>
47 #include <kleo/multideletejob.h>
48 #include <kleo/deletejob.h>
50 #include <gpgme++/key.h>
52 #include <KLocalizedString>
55 #include <QAbstractItemView>
58 #include <boost/bind.hpp>
65 using namespace boost;
66 using namespace GpgME;
68 using namespace Kleo::Dialogs;
71 friend class ::Kleo::DeleteCertificatesCommand;
77 void startDeleteJob( GpgME::Protocol protocol );
80 void pgpDeleteResult(
const GpgME::Error & );
81 void cmsDeleteResult(
const GpgME::Error & );
82 void showErrorsAndFinish();
84 bool canDelete( GpgME::Protocol proto )
const {
85 if (
const CryptoBackend::Protocol *
const cbp = CryptoBackendFactory::instance()->protocol( proto ) )
86 if ( DeleteJob *
const job = cbp->deleteJob() ) {
93 void ensureDialogCreated() {
97 applyWindowID( dialog );
98 dialog->setAttribute( Qt::WA_DeleteOnClose );
99 dialog->setWindowTitle( i18nc(
"@title:window",
"Delete Certificates") );
100 connect( dialog, SIGNAL(accepted()), q_func(), SLOT(slotDialogAccepted()) );
101 connect( dialog, SIGNAL(rejected()), q_func(), SLOT(slotDialogRejected()) );
103 void ensureDialogShown() {
108 void slotDialogAccepted();
109 void slotDialogRejected() {
116 GpgME::Error cmsError, pgpError;
117 std::vector<Key> cmsKeys, pgpKeys;
120 DeleteCertificatesCommand::Private * DeleteCertificatesCommand::d_func() {
return static_cast<Private*
>(
d.get()); }
121 const DeleteCertificatesCommand::Private * DeleteCertificatesCommand::d_func()
const {
return static_cast<const Private*
>(
d.get()); }
132 DeleteCertificatesCommand::Private::~Private() {}
136 :
Command( new Private( this, p ) )
142 :
Command( v, new Private( this, p ) )
151 enum Action { Nothing = 0, Failure = 1, ClearCMS = 2, ClearPGP = 4 };
157 static const struct {
160 } deletionErrorCases[16] = {
164 { I18N_NOOP(
"Neither the OpenPGP nor the CMS "
165 "backends support certificate deletion.\n"
166 "Check your installation." ),
168 { I18N_NOOP(
"The OpenPGP backend does not support "
169 "certificate deletion.\n"
170 "Check your installation.\n"
171 "Only the selected CMS certificates "
172 "will be deleted." ),
175 { I18N_NOOP(
"The OpenPGP backend does not support "
176 "certificate deletion.\n"
177 "Check your installation." ),
179 { I18N_NOOP(
"The OpenPGP backend does not support "
180 "certificate deletion.\n"
181 "Check your installation." ),
185 { I18N_NOOP(
"The CMS backend does not support "
186 "certificate deletion.\n"
187 "Check your installation.\n"
188 "Only the selected OpenPGP certificates "
189 "will be deleted." ),
201 { I18N_NOOP(
"The CMS backend does not support "
202 "certificate deletion.\n"
203 "Check your installation." ),
214 { I18N_NOOP(
"The CMS backend does not support "
215 "certificate deletion.\n"
216 "Check your installation." ),
228 void DeleteCertificatesCommand::doStart() {
230 std::vector<Key> selected =
d->keys();
231 if ( selected.empty() ) {
236 kdtools::sort( selected, _detail::ByFingerprint<std::less>() );
242 kdtools::sort( toBeDeleted, _detail::ByFingerprint<std::less>() );
244 std::vector<Key> unselected;
245 unselected.reserve( toBeDeleted.size() );
246 std::set_difference( toBeDeleted.begin(), toBeDeleted.end(),
247 selected.begin(), selected.end(),
248 std::back_inserter( unselected ),
249 _detail::ByFingerprint<std::less>() );
251 d->ensureDialogCreated();
253 d->dialog->setSelectedKeys( selected );
254 d->dialog->setUnselectedKeys( unselected );
256 d->ensureDialogShown();
260 void DeleteCertificatesCommand::Private::slotDialogAccepted() {
261 std::vector<Key> keys = dialog->keys();
262 assert( !keys.empty() );
264 std::vector<Key>::iterator
265 pgpBegin = keys.begin(),
266 pgpEnd = std::stable_partition( pgpBegin, keys.end(),
267 boost::bind( &GpgME::Key::protocol, _1 ) !=
CMS ),
269 cmsEnd = keys.end() ;
271 std::vector<Key> openpgp( pgpBegin, pgpEnd );
272 std::vector<Key> cms( cmsBegin, cmsEnd );
274 const unsigned int errorCase =
275 openpgp.empty() << 3U | canDelete(
OpenPGP ) << 2U |
276 cms.empty() << 1U | canDelete(
CMS ) << 0U ;
278 if (
const unsigned int actions = deletionErrorCases[errorCase].actions ) {
279 information( i18n( deletionErrorCases[errorCase].text ),
281 ? i18n(
"Certificate Deletion Failed" )
282 : i18n(
"Certificate Deletion Problem" ) );
283 if ( actions & ClearCMS )
285 if ( actions & ClearPGP )
287 if ( actions & Failure ) {
293 assert( !openpgp.empty() || !cms.empty() );
295 pgpKeys.swap( openpgp );
298 if ( !pgpKeys.empty() )
300 if ( !cmsKeys.empty() )
303 if ( ( pgpKeys.empty() || pgpError.code() ) &&
304 ( cmsKeys.empty() || cmsError.code() ) )
305 showErrorsAndFinish();
308 void DeleteCertificatesCommand::Private::startDeleteJob( GpgME::Protocol protocol ) {
309 assert( protocol != GpgME::UnknownProtocol );
311 const std::vector<Key> & keys = protocol ==
CMS ? cmsKeys : pgpKeys ;
313 const CryptoBackend::Protocol *
const backend = CryptoBackendFactory::instance()->protocol( protocol );
316 std::auto_ptr<MultiDeleteJob> job(
new MultiDeleteJob( backend ) );
318 if ( protocol ==
CMS )
319 connect( job.get(), SIGNAL(result(GpgME::Error,GpgME::Key)),
320 q_func(), SLOT(cmsDeleteResult(GpgME::Error)) );
322 connect( job.get(), SIGNAL(result(GpgME::Error,GpgME::Key)),
323 q_func(), SLOT(pgpDeleteResult(GpgME::Error)) );
325 connect( job.get(), SIGNAL(progress(
QString,
int,
int)),
326 q, SIGNAL(progress(
QString,
int,
int)) );
328 if (
const Error err = job->start( keys,
true ) )
329 ( protocol ==
CMS ? cmsError : pgpError ) = err;
331 ( protocol ==
CMS ? cmsJob : pgpJob ) = job.release();
334 void DeleteCertificatesCommand::Private::showErrorsAndFinish() {
336 assert( !pgpJob ); assert( !cmsJob );
338 if ( pgpError || cmsError ) {
346 const QString msg = i18n(
"<qt><p>An error occurred while trying to delete "
347 "the certificate:</p>"
348 "<p><b>%1</b></p></qt>",
349 pgpError ? cmsError ? pgpErrorString +
QLatin1String(
"</br>") + cmsErrorString : pgpErrorString : cmsErrorString );
350 error( msg, i18n(
"Certificate Deletion Failed") );
352 std::vector<Key> keys = pgpKeys;
353 keys.insert( keys.end(), cmsKeys.begin(), cmsKeys.end() );
360 void DeleteCertificatesCommand::doCancel() {
364 void DeleteCertificatesCommand::Private::pgpDeleteResult(
const Error & err ) {
368 showErrorsAndFinish();
371 void DeleteCertificatesCommand::Private::cmsDeleteResult(
const Error & err ) {
375 showErrorsAndFinish();
378 void DeleteCertificatesCommand::Private::cancelJobs()
381 cmsJob->slotCancel();
383 pgpJob->slotCancel();
389 #include "moc_deletecertificatescommand.cpp"
DeleteCertificatesCommand(QAbstractItemView *view, KeyListController *parent)
kdtools::pimpl_ptr< Private > d
QString fromLocal8Bit(const char *str, int size)
static boost::shared_ptr< const KeyCache > instance()
~DeleteCertificatesCommand()
static boost::shared_ptr< KeyCache > mutableInstance()