kleopatra
encryptemailcontroller.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include <config-kleopatra.h>
00034
00035 #include "encryptemailcontroller.h"
00036
00037 #include "encryptemailtask.h"
00038 #include "taskcollection.h"
00039
00040 #include <crypto/gui/encryptemailwizard.h>
00041
00042
00043 #include <utils/input.h>
00044 #include <utils/output.h>
00045 #include <utils/stl_util.h>
00046 #include <utils/kleo_assert.h>
00047 #include <utils/exception.h>
00048
00049 #include "emailoperationspreferences.h"
00050
00051 #include <gpgme++/key.h>
00052
00053 #include <kmime/kmime_header_parsing.h>
00054
00055 #include <KLocale>
00056
00057 #include <QPointer>
00058 #include <QTimer>
00059
00060 #include <boost/bind.hpp>
00061 #include <boost/shared_ptr.hpp>
00062
00063 using namespace Kleo;
00064 using namespace Kleo::Crypto;
00065 using namespace Kleo::Crypto::Gui;
00066 using namespace boost;
00067 using namespace GpgME;
00068 using namespace KMime::Types;
00069
00070 class EncryptEMailController::Private {
00071 friend class ::Kleo::Crypto::EncryptEMailController;
00072 EncryptEMailController * const q;
00073 public:
00074 explicit Private( Mode mode, EncryptEMailController * qq );
00075
00076 private:
00077 void slotWizardRecipientsResolved();
00078 void slotWizardCanceled();
00079
00080 private:
00081 void ensureWizardCreated() const;
00082 void ensureWizardVisible();
00083 void cancelAllTasks();
00084
00085 void schedule();
00086 shared_ptr<EncryptEMailTask> takeRunnable( GpgME::Protocol proto );
00087
00088 private:
00089 const Mode mode;
00090 std::vector< shared_ptr<EncryptEMailTask> > runnable, completed;
00091 shared_ptr<EncryptEMailTask> cms, openpgp;
00092 mutable QPointer<EncryptEMailWizard> wizard;
00093 };
00094
00095 EncryptEMailController::Private::Private( Mode m, EncryptEMailController * qq )
00096 : q( qq ),
00097 mode( m ),
00098 runnable(),
00099 cms(),
00100 openpgp(),
00101 wizard()
00102 {
00103
00104 }
00105
00106 EncryptEMailController::EncryptEMailController( const shared_ptr<ExecutionContext> & xc, Mode mode, QObject * p )
00107 : Controller( xc, p ), d( new Private( mode, this ) )
00108 {
00109
00110 }
00111
00112 EncryptEMailController::EncryptEMailController( Mode mode, QObject * p )
00113 : Controller( p ), d( new Private( mode, this ) )
00114 {
00115
00116 }
00117
00118 EncryptEMailController::~EncryptEMailController() {
00119 if ( d->wizard && !d->wizard->isVisible() )
00120 delete d->wizard;
00121
00122 }
00123
00124 EncryptEMailController::Mode EncryptEMailController::mode() const {
00125 return d->mode;
00126 }
00127
00128 void EncryptEMailController::setProtocol( Protocol proto ) {
00129 d->ensureWizardCreated();
00130 const Protocol protocol = d->wizard->presetProtocol();
00131 kleo_assert( protocol == UnknownProtocol ||
00132 protocol == proto );
00133
00134 d->wizard->setPresetProtocol( proto );
00135 }
00136
00137 Protocol EncryptEMailController::protocol() const {
00138 d->ensureWizardCreated();
00139 return d->wizard->selectedProtocol();
00140 }
00141
00142
00143 const char * EncryptEMailController::protocolAsString() const {
00144 switch ( protocol() ) {
00145 case OpenPGP: return "OpenPGP";
00146 case CMS: return "CMS";
00147 default:
00148 throw Kleo::Exception( gpg_error( GPG_ERR_INTERNAL ),
00149 i18n("Call to EncryptEMailController::protocolAsString() is ambiguous.") );
00150 }
00151 }
00152
00153 void EncryptEMailController::startResolveRecipients() {
00154 startResolveRecipients( std::vector<Mailbox>() );
00155 }
00156
00157 void EncryptEMailController::startResolveRecipients( const std::vector<Mailbox> & recipients ) {
00158 d->ensureWizardCreated();
00159 d->wizard->setRecipients( recipients );
00160 d->ensureWizardVisible();
00161 }
00162
00163 void EncryptEMailController::Private::slotWizardRecipientsResolved() {
00164 emit q->recipientsResolved();
00165 }
00166
00167 void EncryptEMailController::Private::slotWizardCanceled() {
00168 emit q->error( gpg_error( GPG_ERR_CANCELED ), i18n("User cancel") );
00169 }
00170
00171 void EncryptEMailController::setInputAndOutput( const shared_ptr<Input> & input, const shared_ptr<Output> & output ) {
00172 setInputsAndOutputs( std::vector< shared_ptr<Input> >( 1, input ), std::vector< shared_ptr<Output> >( 1, output ) );
00173 }
00174
00175 void EncryptEMailController::setInputsAndOutputs( const std::vector< shared_ptr<Input> > & inputs, const std::vector< shared_ptr<Output> > & outputs ) {
00176
00177 kleo_assert( !inputs.empty() );
00178 kleo_assert( outputs.size() == inputs.size() );
00179
00180 std::vector< shared_ptr<EncryptEMailTask> > tasks;
00181 tasks.reserve( inputs.size() );
00182
00183 d->ensureWizardCreated();
00184
00185 const std::vector<Key> keys = d->wizard->resolvedCertificates();
00186 kleo_assert( !keys.empty() );
00187
00188 for ( unsigned int i = 0, end = inputs.size() ; i < end ; ++i ) {
00189
00190 const shared_ptr<EncryptEMailTask> task( new EncryptEMailTask );
00191 task->setInput( inputs[i] );
00192 task->setOutput( outputs[i] );
00193 if ( d->mode == ClipboardMode )
00194 task->setAsciiArmor( true );
00195 task->setRecipients( keys );
00196
00197 tasks.push_back( task );
00198 }
00199
00200 d->runnable.swap( tasks );
00201 }
00202
00203 void EncryptEMailController::start() {
00204 shared_ptr<TaskCollection> coll( new TaskCollection );
00205 std::vector<shared_ptr<Task> > tmp;
00206 std::copy( d->runnable.begin(), d->runnable.end(), std::back_inserter( tmp ) );
00207 coll->setTasks( tmp );
00208 d->ensureWizardCreated();
00209 d->wizard->setTaskCollection( coll );
00210 Q_FOREACH( const shared_ptr<Task> & t, tmp )
00211 connectTask( t );
00212 d->schedule();
00213 }
00214
00215 void EncryptEMailController::Private::schedule() {
00216
00217 if ( !cms )
00218 if ( const shared_ptr<EncryptEMailTask> t = takeRunnable( CMS ) ) {
00219 t->start();
00220 cms = t;
00221 }
00222
00223 if ( !openpgp )
00224 if ( const shared_ptr<EncryptEMailTask> t = takeRunnable( OpenPGP ) ) {
00225 t->start();
00226 openpgp = t;
00227 }
00228
00229 if ( cms || openpgp )
00230 return;
00231 kleo_assert( runnable.empty() );
00232 q->emitDoneOrError();
00233 }
00234
00235 shared_ptr<EncryptEMailTask> EncryptEMailController::Private::takeRunnable( GpgME::Protocol proto ) {
00236 const std::vector< shared_ptr<EncryptEMailTask> >::iterator it
00237 = std::find_if( runnable.begin(), runnable.end(),
00238 bind( &Task::protocol, _1 ) == proto );
00239 if ( it == runnable.end() )
00240 return shared_ptr<EncryptEMailTask>();
00241
00242 const shared_ptr<EncryptEMailTask> result = *it;
00243 runnable.erase( it );
00244 return result;
00245 }
00246
00247 void EncryptEMailController::doTaskDone( const Task * task, const shared_ptr<const Task::Result> & result ) {
00248 assert( task );
00249
00250
00251
00252
00253
00254
00255 if ( task == d->cms.get() ) {
00256 d->completed.push_back( d->cms );
00257 d->cms.reset();
00258 } else if ( task == d->openpgp.get() ) {
00259 d->completed.push_back( d->openpgp );
00260 d->openpgp.reset();
00261 }
00262
00263 QTimer::singleShot( 0, this, SLOT(schedule()) );
00264 }
00265
00266 void EncryptEMailController::cancel() {
00267 try {
00268 if ( d->wizard )
00269 d->wizard->close();
00270 d->cancelAllTasks();
00271 } catch ( const std::exception & e ) {
00272 qDebug( "Caught exception: %s", e.what() );
00273 }
00274 }
00275
00276 void EncryptEMailController::Private::cancelAllTasks() {
00277
00278
00279
00280 runnable.clear();
00281
00282
00283 if ( cms )
00284 cms->cancel();
00285 if ( openpgp )
00286 openpgp->cancel();
00287 }
00288
00289 void EncryptEMailController::Private::ensureWizardCreated() const {
00290 if ( wizard )
00291 return;
00292
00293 std::auto_ptr<EncryptEMailWizard> w( new EncryptEMailWizard );
00294 w->setAttribute( Qt::WA_DeleteOnClose );
00295 Kleo::EMailOperationsPreferences prefs;
00296 w->setQuickMode( prefs.quickEncryptEMail() );
00297 connect( w.get(), SIGNAL(recipientsResolved()), q, SLOT(slotWizardRecipientsResolved()), Qt::QueuedConnection );
00298 connect( w.get(), SIGNAL(canceled()), q, SLOT(slotWizardCanceled()), Qt::QueuedConnection );
00299
00300 wizard = w.release();
00301 }
00302
00303 void EncryptEMailController::Private::ensureWizardVisible() {
00304 ensureWizardCreated();
00305 q->bringToForeground( wizard );
00306 }
00307
00308 #include "moc_encryptemailcontroller.cpp"
00309
00310