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

kleopatra

  • sources
  • kde-4.12
  • kdepim
  • kleopatra
  • crypto
decryptverifyemailcontroller.cpp
Go to the documentation of this file.
1 /* -*- mode: c++; c-basic-offset:4 -*-
2  decryptverifyemailcontroller.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 "decryptverifyemailcontroller.h"
36 
37 #include "emailoperationspreferences.h"
38 
39 #include <crypto/gui/newresultpage.h>
40 #include <crypto/decryptverifytask.h>
41 #include <crypto/taskcollection.h>
42 
43 #include <utils/classify.h>
44 #include <utils/formatting.h>
45 #include <utils/gnupg-helper.h>
46 #include <utils/input.h>
47 #include <utils/output.h>
48 #include <utils/kleo_assert.h>
49 
50 #include <kleo/cryptobackendfactory.h>
51 
52 #include <kmime/kmime_header_parsing.h>
53 
54 #include <KDebug>
55 #include <KLocalizedString>
56 
57 #include <QPoint>
58 #include <QPointer>
59 #include <QTimer>
60 
61 #include <boost/shared_ptr.hpp>
62 
63 #include <memory>
64 #include <vector>
65 
66 using namespace boost;
67 using namespace GpgME;
68 using namespace Kleo;
69 using namespace Kleo::Crypto;
70 using namespace Kleo::Crypto::Gui;
71 using namespace KMime::Types;
72 
73 namespace {
74 
75  class DecryptVerifyEMailWizard : public QWizard {
76  Q_OBJECT
77  public:
78  explicit DecryptVerifyEMailWizard( QWidget * parent=0, Qt::WindowFlags f=0 )
79  : QWizard( parent, f ),
80  m_resultPage( this )
81  {
82  KDAB_SET_OBJECT_NAME( m_resultPage );
83 
84  m_resultPage.setSubTitle( i18n("Status and progress of the crypto operations is shown here.") );
85  // there's no way we're letting users fast-forward over the decryption/verification results...
86  m_resultPage.setKeepOpenWhenDoneShown( false );
87 
88  addPage( &m_resultPage );
89  }
90 
91  void addTaskCollection( const shared_ptr<TaskCollection> & coll ) {
92  m_resultPage.addTaskCollection( coll );
93  }
94 
95  public Q_SLOTS:
96  void accept() {
97  EMailOperationsPreferences prefs;
98  prefs.setDecryptVerifyPopupGeometry( geometry() );
99  prefs.writeConfig();
100  QWizard::accept();
101  }
102 
103  private:
104  NewResultPage m_resultPage;
105  };
106 
107 }
108 
109 
110 class DecryptVerifyEMailController::Private {
111  DecryptVerifyEMailController* const q;
112 public:
113 
114  explicit Private( DecryptVerifyEMailController* qq );
115 
116  void slotWizardCanceled();
117  void schedule();
118 
119  std::vector<shared_ptr<AbstractDecryptVerifyTask> > buildTasks();
120 
121  static DecryptVerifyEMailWizard * findOrCreateWizard( unsigned int id );
122 
123  void ensureWizardCreated();
124  void ensureWizardVisible();
125  void reportError( int err, const QString & details ) {
126  q->setLastError( err, details );
127  q->emitDoneOrError();
128  }
129 
130  void cancelAllTasks();
131 
132  std::vector<shared_ptr<Input> > m_inputs, m_signedDatas;
133  std::vector<shared_ptr<Output> > m_outputs;
134 
135  unsigned int m_sessionId;
136  QPointer<DecryptVerifyEMailWizard> m_wizard;
137  std::vector<shared_ptr<const DecryptVerifyResult> > m_results;
138  std::vector<shared_ptr<AbstractDecryptVerifyTask> > m_runnableTasks, m_completedTasks;
139  shared_ptr<AbstractDecryptVerifyTask> m_runningTask;
140  bool m_silent;
141  bool m_operationCompleted;
142  DecryptVerifyOperation m_operation;
143  Protocol m_protocol;
144  VerificationMode m_verificationMode;
145  std::vector<KMime::Types::Mailbox> m_informativeSenders;
146 };
147 
148 DecryptVerifyEMailController::Private::Private( DecryptVerifyEMailController* qq )
149  : q( qq ),
150  m_sessionId( 0 ),
151  m_silent( false ),
152  m_operationCompleted( false ),
153  m_operation( DecryptVerify ),
154  m_protocol( UnknownProtocol ),
155  m_verificationMode( Detached )
156 {
157  qRegisterMetaType<VerificationResult>();
158 }
159 
160 void DecryptVerifyEMailController::Private::slotWizardCanceled()
161 {
162  kDebug();
163  if ( !m_operationCompleted )
164  reportError( gpg_error( GPG_ERR_CANCELED ), i18n("User canceled") );
165 }
166 
167 void DecryptVerifyEMailController::doTaskDone( const Task* task, const shared_ptr<const Task::Result> & result ) {
168  assert( task );
169 
170  // We could just delete the tasks here, but we can't use
171  // Qt::QueuedConnection here (we need sender()) and other slots
172  // might not yet have executed. Therefore, we push completed tasks
173  // into a burial container
174 
175  if ( task == d->m_runningTask.get() ) {
176  d->m_completedTasks.push_back( d->m_runningTask );
177  const shared_ptr<const DecryptVerifyResult> & dvr = boost::dynamic_pointer_cast<const DecryptVerifyResult>( result );
178  assert( dvr );
179  d->m_results.push_back( dvr );
180  d->m_runningTask.reset();
181  }
182 
183  QTimer::singleShot( 0, this, SLOT(schedule()) );
184 
185 }
186 
187 void DecryptVerifyEMailController::Private::schedule()
188 {
189  if ( !m_runningTask && !m_runnableTasks.empty() ) {
190  const shared_ptr<AbstractDecryptVerifyTask> t = m_runnableTasks.back();
191  m_runnableTasks.pop_back();
192  t->start();
193  m_runningTask = t;
194  }
195  if ( !m_runningTask ) {
196  kleo_assert( m_runnableTasks.empty() );
197  Q_FOREACH ( const shared_ptr<const DecryptVerifyResult> & i, m_results )
198  emit q->verificationResult( i->verificationResult() );
199  // if there is a popup, wait for either the client cancel or the user closing the popup.
200  // Otherwise (silent case), finish immediately
201  m_operationCompleted = true;
202  q->emitDoneOrError();
203  }
204 }
205 
206 void DecryptVerifyEMailController::Private::ensureWizardCreated()
207 {
208  if ( m_wizard )
209  return;
210 
211  DecryptVerifyEMailWizard * w = findOrCreateWizard( m_sessionId );
212  connect( w, SIGNAL(destroyed()), q, SLOT(slotWizardCanceled()), Qt::QueuedConnection );
213  m_wizard = w;
214 
215 }
216 
217 namespace {
218  template <typename C>
219  void collectGarbage( C & c ) {
220  typename C::iterator it = c.begin();
221  while ( it != c.end() /*sic!*/ )
222  if ( it->second )
223  ++it;
224  else
225  c.erase( it++ /*sic!*/ );
226  }
227 }
228 
229 // static
230 DecryptVerifyEMailWizard * DecryptVerifyEMailController::Private::findOrCreateWizard( unsigned int id )
231 {
232 
233  static std::map<unsigned int, QPointer<DecryptVerifyEMailWizard> > s_wizards;
234 
235  collectGarbage( s_wizards );
236 
237  kDebug() << "id = " << id;
238 
239  if ( id != 0 ) {
240 
241  const std::map<unsigned int, QPointer<DecryptVerifyEMailWizard> >::const_iterator it
242  = s_wizards.find( id );
243 
244  if ( it != s_wizards.end() ) {
245  assert( it->second && "This should have been garbage-collected" );
246  return it->second;
247  }
248 
249  }
250 
251  DecryptVerifyEMailWizard * w = new DecryptVerifyEMailWizard;
252  w->setWindowTitle( i18n( "Decrypt/Verify E-Mail" ) );
253  w->setAttribute( Qt::WA_DeleteOnClose );
254 
255  const QRect preferredGeometry = EMailOperationsPreferences().decryptVerifyPopupGeometry();
256  if ( preferredGeometry.isValid() )
257  w->setGeometry( preferredGeometry );
258 
259  s_wizards[id] = w;
260 
261  return w;
262 }
263 
264 std::vector< shared_ptr<AbstractDecryptVerifyTask> > DecryptVerifyEMailController::Private::buildTasks()
265 {
266  const uint numInputs = m_inputs.size();
267  const uint numMessages = m_signedDatas.size();
268  const uint numOutputs = m_outputs.size();
269  const uint numInformativeSenders = m_informativeSenders.size();
270 
271  // these are duplicated from DecryptVerifyCommandEMailBase::Private::checkForErrors with slightly modified error codes/messages
272  if ( !numInputs )
273  throw Kleo::Exception( makeGnuPGError( GPG_ERR_CONFLICT ),
274  i18n("At least one input needs to be provided") );
275 
276  if ( numInformativeSenders > 0 && numInformativeSenders != numInputs )
277  throw Kleo::Exception( makeGnuPGError( GPG_ERR_CONFLICT ), //TODO use better error code if possible
278  i18n("Informative sender/signed data count mismatch") );
279 
280  if ( numMessages ) {
281  if ( numMessages != numInputs )
282  throw Kleo::Exception( makeGnuPGError( GPG_ERR_CONFLICT ), //TODO use better error code if possible
283  i18n("Signature/signed data count mismatch") );
284  else if ( m_operation != Verify || m_verificationMode != Detached )
285  throw Kleo::Exception( makeGnuPGError( GPG_ERR_CONFLICT ),
286  i18n("Signed data can only be given for detached signature verification") );
287  }
288 
289  if ( numOutputs ) {
290  if ( numOutputs != numInputs )
291  throw Kleo::Exception( makeGnuPGError( GPG_ERR_CONFLICT ), //TODO use better error code if possible
292  i18n("Input/Output count mismatch") );
293  else if ( numMessages )
294  throw Kleo::Exception( makeGnuPGError( GPG_ERR_CONFLICT ),
295  i18n("Cannot use output and signed data simultaneously") );
296  }
297 
298  kleo_assert( m_protocol != UnknownProtocol );
299 
300  const CryptoBackend::Protocol * const backend = CryptoBackendFactory::instance()->protocol( m_protocol );
301  if ( !backend )
302  throw Kleo::Exception( makeGnuPGError( GPG_ERR_UNSUPPORTED_PROTOCOL ), i18n("No backend support for %1", Formatting::displayName( m_protocol ) ) );
303 
304 
305 
306  if ( m_operation != Decrypt && !m_silent )
307  ensureWizardVisible();
308 
309  std::vector< shared_ptr<AbstractDecryptVerifyTask> > tasks;
310 
311  for ( unsigned int i = 0 ; i < numInputs ; ++i ) {
312  shared_ptr<AbstractDecryptVerifyTask> task;
313  switch ( m_operation ) {
314  case Decrypt:
315  {
316  shared_ptr<DecryptTask> t( new DecryptTask );
317  t->setInput( m_inputs.at( i ) );
318  assert( numOutputs );
319  t->setOutput( m_outputs.at( i ) );
320  t->setProtocol( m_protocol );
321  task = t;
322  }
323  break;
324  case Verify:
325  {
326  if ( m_verificationMode == Detached ) {
327  shared_ptr<VerifyDetachedTask> t( new VerifyDetachedTask );
328  t->setInput( m_inputs.at( i ) );
329  t->setSignedData( m_signedDatas.at( i ) );
330  if ( numInformativeSenders > 0 )
331  t->setInformativeSender( m_informativeSenders.at( i ) );
332  t->setProtocol( m_protocol );
333  task = t;
334  } else {
335  shared_ptr<VerifyOpaqueTask> t( new VerifyOpaqueTask );
336  t->setInput( m_inputs.at( i ) );
337  if ( numOutputs )
338  t->setOutput( m_outputs.at( i ) );
339  if ( numInformativeSenders > 0 )
340  t->setInformativeSender( m_informativeSenders.at( i ) );
341  t->setProtocol( m_protocol );
342  task = t;
343  }
344  }
345  break;
346  case DecryptVerify:
347  {
348  shared_ptr<DecryptVerifyTask> t( new DecryptVerifyTask );
349  t->setInput( m_inputs.at( i ) );
350  assert( numOutputs );
351  t->setOutput( m_outputs.at( i ) );
352  if ( numInformativeSenders > 0 )
353  t->setInformativeSender( m_informativeSenders.at( i ) );
354  t->setProtocol( m_protocol );
355  task = t;
356  }
357  }
358 
359  assert( task );
360  tasks.push_back( task );
361  }
362 
363  return tasks;
364 }
365 
366 void DecryptVerifyEMailController::Private::ensureWizardVisible()
367 {
368  ensureWizardCreated();
369  q->bringToForeground( m_wizard );
370 }
371 
372 DecryptVerifyEMailController::DecryptVerifyEMailController( QObject* parent ) : Controller( parent ), d( new Private( this ) )
373 {
374 }
375 
376 DecryptVerifyEMailController::DecryptVerifyEMailController( const shared_ptr<const ExecutionContext> & ctx, QObject* parent ) : Controller( ctx, parent ), d( new Private( this ) )
377 {
378 }
379 
380 DecryptVerifyEMailController::~DecryptVerifyEMailController() { kDebug(); }
381 
382 void DecryptVerifyEMailController::start()
383 {
384  d->m_runnableTasks = d->buildTasks();
385 
386  const shared_ptr<TaskCollection> coll( new TaskCollection );
387  std::vector<shared_ptr<Task> > tsks;
388  Q_FOREACH( const shared_ptr<Task> & i, d->m_runnableTasks ) {
389  connectTask( i );
390  tsks.push_back( i );
391  }
392  coll->setTasks( tsks );
393  d->ensureWizardCreated();
394  d->m_wizard->addTaskCollection( coll );
395 
396  d->ensureWizardVisible();
397  QTimer::singleShot( 0, this, SLOT(schedule()) );
398 }
399 
400 void DecryptVerifyEMailController::setInput( const shared_ptr<Input> & input )
401 {
402  d->m_inputs.resize( 1, input );
403 }
404 
405 void DecryptVerifyEMailController::setInputs( const std::vector<shared_ptr<Input> > & inputs )
406 {
407  d->m_inputs = inputs;
408 }
409 
410 void DecryptVerifyEMailController::setSignedData( const shared_ptr<Input> & data )
411 {
412  d->m_signedDatas.resize( 1, data );
413 }
414 
415 void DecryptVerifyEMailController::setSignedData( const std::vector<shared_ptr<Input> > & data )
416 {
417  d->m_signedDatas = data;
418 }
419 
420 void DecryptVerifyEMailController::setOutput( const shared_ptr<Output> & output )
421 {
422  d->m_outputs.resize( 1, output );
423 }
424 
425 void DecryptVerifyEMailController::setOutputs( const std::vector<shared_ptr<Output> > & outputs )
426 {
427  d->m_outputs = outputs;
428 }
429 
430 void DecryptVerifyEMailController::setInformativeSenders( const std::vector<KMime::Types::Mailbox> & senders )
431 {
432  d->m_informativeSenders = senders;
433 }
434 
435 void DecryptVerifyEMailController::setWizardShown( bool shown )
436 {
437  d->m_silent = !shown;
438  if ( d->m_wizard )
439  d->m_wizard->setVisible( shown );
440 }
441 
442 void DecryptVerifyEMailController::setOperation( DecryptVerifyOperation operation )
443 {
444  d->m_operation = operation;
445 }
446 
447 void DecryptVerifyEMailController::setVerificationMode( VerificationMode vm )
448 {
449  d->m_verificationMode = vm;
450 }
451 
452 void DecryptVerifyEMailController::setProtocol( Protocol prot )
453 {
454  d->m_protocol = prot;
455 }
456 
457 void DecryptVerifyEMailController::setSessionId( unsigned int id )
458 {
459  kDebug() << "id = " << id;
460  d->m_sessionId = id;
461 }
462 
463 void DecryptVerifyEMailController::cancel()
464 {
465  kDebug();
466  try {
467  if ( d->m_wizard ) {
468  disconnect( d->m_wizard );
469  d->m_wizard->close();
470  }
471  d->cancelAllTasks();
472  } catch ( const std::exception & e ) {
473  kDebug() << "Caught exception: " << e.what();
474  }
475 }
476 
477 void DecryptVerifyEMailController::Private::cancelAllTasks() {
478 
479  // we just kill all runnable tasks - this will not result in
480  // signal emissions.
481  m_runnableTasks.clear();
482 
483  // a cancel() will result in a call to
484  if ( m_runningTask )
485  m_runningTask->cancel();
486 }
487 
488 #include "decryptverifyemailcontroller.moc"
489 #include "moc_decryptverifyemailcontroller.cpp"
emailoperationspreferences.h
Kleo::Detached
Definition: types.h:55
output.h
input.h
Kleo::Crypto::DecryptVerifyEMailController::~DecryptVerifyEMailController
~DecryptVerifyEMailController()
Definition: decryptverifyemailcontroller.cpp:380
decryptverifytask.h
Kleo::Formatting::displayName
QString displayName(GpgME::Protocol prot)
QWidget
Kleo::Crypto::Task
Definition: task.h:55
classify.h
formatting.h
Kleo::Crypto::VerifyDetachedTask
Definition: decryptverifytask.h:130
Kleo::DecryptVerify
Definition: types.h:48
Kleo::Crypto::Gui::NewResultPage
Definition: newresultpage.h:61
Kleo::Crypto::DecryptVerifyEMailController::setSignedData
void setSignedData(const boost::shared_ptr< Input > &data)
Definition: decryptverifyemailcontroller.cpp:410
Kleo::Crypto::DecryptVerifyEMailController::setOutput
void setOutput(const boost::shared_ptr< Output > &output)
Definition: decryptverifyemailcontroller.cpp:420
kleo_assert.h
Kleo::Crypto::DecryptVerifyEMailController::setOperation
void setOperation(DecryptVerifyOperation operation)
Definition: decryptverifyemailcontroller.cpp:442
Kleo::Crypto::DecryptVerifyEMailController::setInputs
void setInputs(const std::vector< boost::shared_ptr< Input > > &inputs)
Definition: decryptverifyemailcontroller.cpp:405
boost::shared_ptr< TaskCollection >
Kleo::Crypto::VerifyOpaqueTask
Definition: decryptverifytask.h:161
d
#define d
Definition: adduseridcommand.cpp:90
Kleo::Crypto::DecryptVerifyTask
Definition: decryptverifytask.h:192
Kleo::Crypto::DecryptVerifyEMailController::setVerificationMode
void setVerificationMode(VerificationMode vm)
Definition: decryptverifyemailcontroller.cpp:447
Kleo::Crypto::DecryptVerifyEMailController
Definition: decryptverifyemailcontroller.h:69
Kleo::Crypto::DecryptVerifyEMailController::setOutputs
void setOutputs(const std::vector< boost::shared_ptr< Output > > &outputs)
Definition: decryptverifyemailcontroller.cpp:425
KDAB_SET_OBJECT_NAME
#define KDAB_SET_OBJECT_NAME(x)
Definition: kdtoolsglobal.h:66
Kleo::Verify
Definition: types.h:47
Kleo::Crypto::DecryptVerifyEMailController::DecryptVerifyEMailController
DecryptVerifyEMailController(QObject *parent=0)
Definition: decryptverifyemailcontroller.cpp:372
Kleo::EMailOperationsPreferences
Definition: emailoperationspreferences.h:12
Kleo::DecryptVerifyOperation
DecryptVerifyOperation
Definition: types.h:45
decryptverifyemailcontroller.h
Kleo::Crypto::DecryptVerifyEMailController::setWizardShown
void setWizardShown(bool shown)
Definition: decryptverifyemailcontroller.cpp:435
gnupg-helper.h
Kleo::Crypto::DecryptVerifyEMailController::start
void start()
Definition: decryptverifyemailcontroller.cpp:382
Kleo::Crypto::DecryptTask
Definition: decryptverifytask.h:99
Kleo::makeGnuPGError
int makeGnuPGError(int code)
Definition: gnupg-helper.cpp:69
Kleo::Crypto::Controller::connectTask
void connectTask(const boost::shared_ptr< Task > &task)
Definition: controller.cpp:86
Kleo::Crypto::DecryptVerifyEMailController::setProtocol
void setProtocol(GpgME::Protocol protocol)
Definition: decryptverifyemailcontroller.cpp:452
kleo_assert
#define kleo_assert(cond)
Definition: kleo_assert.h:84
Kleo::Crypto::TaskCollection
Definition: taskcollection.h:49
q
#define q
Definition: adduseridcommand.cpp:91
Kleo::VerificationMode
VerificationMode
Definition: types.h:53
Kleo::Crypto::DecryptVerifyEMailController::cancel
void cancel()
Definition: decryptverifyemailcontroller.cpp:463
Kleo::EMailOperationsPreferences::decryptVerifyPopupGeometry
QRect decryptVerifyPopupGeometry() const
Get Decrypt/Verify Popup Geometry.
Definition: emailoperationspreferences.h:65
newresultpage.h
Kleo::EMailOperationsPreferences::setDecryptVerifyPopupGeometry
void setDecryptVerifyPopupGeometry(const QRect &v)
Set Decrypt/Verify Popup Geometry.
Definition: emailoperationspreferences.h:56
Kleo::Decrypt
Definition: types.h:46
Kleo::Crypto::Controller
Definition: controller.h:50
Kleo::Crypto::DecryptVerifyEMailController::setInformativeSenders
void setInformativeSenders(const std::vector< KMime::Types::Mailbox > &senders)
Definition: decryptverifyemailcontroller.cpp:430
taskcollection.h
Kleo::Crypto::DecryptVerifyEMailController::setInput
void setInput(const boost::shared_ptr< Input > &input)
Definition: decryptverifyemailcontroller.cpp:400
Kleo::Crypto::DecryptVerifyEMailController::setSessionId
void setSessionId(unsigned int id)
Definition: decryptverifyemailcontroller.cpp:457
Kleo::Crypto::DecryptVerifyResult
Definition: decryptverifytask.h:224
QWizard
The QWizard class provides a framework for wizards.
Definition: qwizard.h:51
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:56:40 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

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