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

kleopatra

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

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