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> 
   53 #include <KMessageBox> 
   56 #include <QAbstractItemView> 
   58 #include <boost/bind.hpp> 
   64 using namespace boost;
 
   65 using namespace GpgME;
 
   67 using namespace Kleo::Dialogs;
 
   70     friend class ::Kleo::DeleteCertificatesCommand;
 
   76     void startDeleteJob( GpgME::Protocol protocol );
 
   79     void pgpDeleteResult( 
const GpgME::Error & );
 
   80     void cmsDeleteResult( 
const GpgME::Error & );
 
   81     void showErrorsAndFinish();
 
   83     bool canDelete( GpgME::Protocol proto )
 const {
 
   84         if ( 
const CryptoBackend::Protocol * 
const cbp = CryptoBackendFactory::instance()->protocol( proto ) )
 
   85             if ( DeleteJob * 
const job = cbp->deleteJob() ) {
 
   92     void ensureDialogCreated() {
 
   96         applyWindowID( dialog );
 
   97         dialog->setAttribute( Qt::WA_DeleteOnClose );
 
   98         dialog->setWindowTitle( i18nc(
"@title:window", 
"Delete Certificates") );
 
   99         connect( dialog, SIGNAL(accepted()), q_func(), SLOT(slotDialogAccepted()) );
 
  100         connect( dialog, SIGNAL(rejected()), q_func(), SLOT(slotDialogRejected()) );
 
  102     void ensureDialogShown() {
 
  107     void slotDialogAccepted();
 
  108     void slotDialogRejected() {
 
  113     QPointer<DeleteCertificatesDialog> dialog;
 
  114     QPointer<MultiDeleteJob> cmsJob, pgpJob;
 
  115     GpgME::Error cmsError, pgpError;
 
  116     std::vector<Key> cmsKeys, pgpKeys;
 
  119 DeleteCertificatesCommand::Private * DeleteCertificatesCommand::d_func() { 
return static_cast<Private*
>(
d.get()); }
 
  120 const DeleteCertificatesCommand::Private * DeleteCertificatesCommand::d_func()
 const { 
return static_cast<const Private*
>(
d.get()); }
 
  131 DeleteCertificatesCommand::Private::~Private() {}
 
  135     : 
Command( new Private( this, p ) )
 
  141     : 
Command( v, new Private( this, p ) )
 
  150     enum Action { Nothing = 0, Failure = 1, ClearCMS = 2, ClearPGP = 4 };
 
  156     static const struct {
 
  159     } deletionErrorCases[16] = {
 
  163         { I18N_NOOP( 
"Neither the OpenPGP nor the CMS " 
  164                      "backends support certificate deletion.\n" 
  165                      "Check your installation." ),
 
  167         { I18N_NOOP( 
"The OpenPGP backend does not support " 
  168                      "certificate deletion.\n" 
  169                      "Check your installation.\n" 
  170                      "Only the selected CMS certificates " 
  171                      "will be deleted." ),
 
  174         { I18N_NOOP( 
"The OpenPGP backend does not support " 
  175                      "certificate deletion.\n" 
  176                      "Check your installation." ),
 
  178         { I18N_NOOP( 
"The OpenPGP backend does not support " 
  179                      "certificate deletion.\n" 
  180                      "Check your installation." ),
 
  184         { I18N_NOOP( 
"The CMS backend does not support " 
  185                      "certificate deletion.\n" 
  186                      "Check your installation.\n" 
  187                      "Only the selected OpenPGP certificates " 
  188                      "will be deleted." ),
 
  200         { I18N_NOOP( 
"The CMS backend does not support " 
  201                      "certificate deletion.\n" 
  202                      "Check your installation." ),
 
  213         { I18N_NOOP( 
"The CMS backend does not support " 
  214                      "certificate deletion.\n" 
  215                      "Check your installation." ),
 
  227 void DeleteCertificatesCommand::doStart() {
 
  229     std::vector<Key> selected = 
d->keys();
 
  230     if ( selected.empty() ) {
 
  235     kdtools::sort( selected, _detail::ByFingerprint<std::less>() );
 
  241     kdtools::sort( toBeDeleted, _detail::ByFingerprint<std::less>() );
 
  243     std::vector<Key> unselected;
 
  244     unselected.reserve( toBeDeleted.size() );
 
  245     std::set_difference( toBeDeleted.begin(), toBeDeleted.end(),
 
  246                          selected.begin(), selected.end(),
 
  247                          std::back_inserter( unselected ),
 
  248                          _detail::ByFingerprint<std::less>() );
 
  250     d->ensureDialogCreated();
 
  252     d->dialog->setSelectedKeys( selected );
 
  253     d->dialog->setUnselectedKeys( unselected );
 
  255     d->ensureDialogShown();
 
  259 void DeleteCertificatesCommand::Private::slotDialogAccepted() {
 
  260     std::vector<Key> keys = dialog->keys();
 
  261     assert( !keys.empty() );
 
  263     std::vector<Key>::iterator
 
  264         pgpBegin = keys.begin(),
 
  265         pgpEnd = std::stable_partition( pgpBegin, keys.end(),
 
  266                                         boost::bind( &GpgME::Key::protocol, _1 ) != 
CMS ),
 
  268         cmsEnd = keys.end() ;
 
  270     std::vector<Key> openpgp( pgpBegin, pgpEnd );
 
  271     std::vector<Key>     cms( cmsBegin, cmsEnd );
 
  273     const unsigned int errorCase =
 
  274         openpgp.empty() << 3U | canDelete( 
OpenPGP ) << 2U |
 
  275             cms.empty() << 1U |     canDelete( 
CMS ) << 0U ;
 
  277     if ( 
const unsigned int actions = deletionErrorCases[errorCase].actions ) {
 
  278         information( i18n( deletionErrorCases[errorCase].text ),
 
  280                      ? i18n( 
"Certificate Deletion Failed" )
 
  281                      : i18n( 
"Certificate Deletion Problem" ) );
 
  282         if ( actions & ClearCMS )
 
  284         if ( actions & ClearPGP )
 
  286         if ( actions & Failure ) {
 
  292     assert( !openpgp.empty() || !cms.empty() );
 
  294     pgpKeys.swap( openpgp );
 
  297     if ( !pgpKeys.empty() )
 
  299     if ( !cmsKeys.empty() )
 
  302     if ( ( pgpKeys.empty() || pgpError.code() ) &&
 
  303          ( cmsKeys.empty() || cmsError.code() ) )
 
  304         showErrorsAndFinish();
 
  307 void DeleteCertificatesCommand::Private::startDeleteJob( GpgME::Protocol protocol ) {
 
  308     assert( protocol != GpgME::UnknownProtocol );
 
  310     const std::vector<Key> & keys = protocol == 
CMS ? cmsKeys : pgpKeys ;
 
  312     const CryptoBackend::Protocol * 
const backend = CryptoBackendFactory::instance()->protocol( protocol );
 
  315     std::auto_ptr<MultiDeleteJob> job( 
new MultiDeleteJob( backend ) );
 
  317     if ( protocol == 
CMS )
 
  318         connect( job.get(), SIGNAL(result(GpgME::Error,GpgME::Key)),
 
  319                  q_func(), SLOT(cmsDeleteResult(GpgME::Error)) );
 
  321         connect( job.get(), SIGNAL(result(GpgME::Error,GpgME::Key)),
 
  322                  q_func(), SLOT(pgpDeleteResult(GpgME::Error)) );
 
  324     connect( job.get(), SIGNAL(progress(QString,
int,
int)),
 
  325              q, SIGNAL(progress(QString,
int,
int)) );
 
  327     if ( 
const Error err = job->start( keys, 
true  ) )
 
  328         ( protocol == 
CMS ? cmsError : pgpError ) = err;
 
  330         ( protocol == 
CMS ? cmsJob : pgpJob ) = job.release();
 
  333 void DeleteCertificatesCommand::Private::showErrorsAndFinish() {
 
  335     assert( !pgpJob ); assert( !cmsJob );
 
  337     if ( pgpError || cmsError ) {
 
  338         QString pgpErrorString;
 
  340             pgpErrorString = i18n( 
"OpenPGP backend: %1", QString::fromLocal8Bit( pgpError.asString() ) );
 
  341         QString cmsErrorString;
 
  343             cmsErrorString = i18n( 
"CMS backend: %1", QString::fromLocal8Bit( cmsError.asString() ) );
 
  345         const QString msg = i18n(
"<qt><p>An error occurred while trying to delete " 
  346                                  "the certificate:</p>" 
  347                                  "<p><b>%1</b></p></qt>",
 
  348                                  pgpError ? cmsError ? pgpErrorString + QLatin1String(
"</br>") + cmsErrorString : pgpErrorString : cmsErrorString );
 
  349         error( msg, i18n(
"Certificate Deletion Failed") );
 
  351         std::vector<Key> keys = pgpKeys;
 
  352         keys.insert( keys.end(), cmsKeys.begin(), cmsKeys.end() );
 
  359 void DeleteCertificatesCommand::doCancel() {
 
  363 void DeleteCertificatesCommand::Private::pgpDeleteResult( 
const Error & err ) {
 
  367         showErrorsAndFinish();
 
  370 void DeleteCertificatesCommand::Private::cmsDeleteResult( 
const Error & err ) {
 
  374         showErrorsAndFinish();
 
  377 void DeleteCertificatesCommand::Private::cancelJobs()
 
  380         cmsJob->slotCancel();
 
  382         pgpJob->slotCancel();
 
  388 #include "moc_deletecertificatescommand.cpp" 
DeleteCertificatesCommand(QAbstractItemView *view, KeyListController *parent)
kdtools::pimpl_ptr< Private > d
static boost::shared_ptr< const KeyCache > instance()
~DeleteCertificatesCommand()
static boost::shared_ptr< KeyCache > mutableInstance()