• 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
  • uiserver
assuanserverconnection.cpp
Go to the documentation of this file.
1 /* -*- mode: c++; c-basic-offset:4 -*-
2  uiserver/assuanserverconnection.cpp
3 
4  This file is part of Kleopatra, the KDE keymanager
5  Copyright (c) 2007 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 #ifndef QT_NO_CAST_TO_ASCII
33 # define QT_NO_CAST_TO_ASCII
34 #endif
35 #ifndef QT_NO_CAST_FROM_ASCII
36 # define QT_NO_CAST_FROM_ASCII
37 #endif
38 
39 #include <config-kleopatra.h>
40 #include <version-kleopatra.h>
41 
42 #include "assuanserverconnection.h"
43 #include "assuancommand.h"
44 #include "sessiondata.h"
45 
46 #include <models/keycache.h> // :(
47 
48 #include <utils/input.h>
49 #include <utils/output.h>
50 #include <utils/gnupg-helper.h>
51 #include <utils/detail_p.h>
52 #include <utils/hex.h>
53 #include <utils/log.h>
54 #include <utils/kleo_assert.h>
55 #include <utils/getpid.h>
56 
57 #include <kleo/stl_util.h>
58 #include <kleo/exception.h>
59 
60 #include <gpgme++/data.h>
61 #include <gpgme++/key.h>
62 
63 #include <kmime/kmime_header_parsing.h>
64 
65 #include <KDebug>
66 #include <KLocalizedString>
67 #include <KWindowSystem>
68 #include <KMessageBox>
69 
70 #include <QSocketNotifier>
71 #include <QTimer>
72 #include <QVariant>
73 #include <QPointer>
74 #include <QFileInfo>
75 #include <QStringList>
76 #include <QDialog>
77 #include <QRegExp>
78 
79 #include <kleo-assuan.h>
80 
81 #ifndef Q_MOC_RUN // QTBUG-22829
82 #include <boost/type_traits/remove_pointer.hpp>
83 #ifndef _WIN32_WCE
84 #include <boost/lexical_cast.hpp>
85 #endif
86 #include <boost/bind.hpp>
87 #include <boost/mem_fn.hpp>
88 #include <boost/mpl/if.hpp>
89 #endif
90 
91 #include <vector>
92 #include <map>
93 #include <string>
94 #include <memory>
95 #include <algorithm>
96 
97 #include <errno.h>
98 
99 #ifdef __GNUC__
100 # include <ext/algorithm> // for is_sorted
101 #endif
102 
103 #ifdef Q_OS_WIN32
104 # include <io.h>
105 # include <process.h>
106 #else
107 # include <sys/types.h>
108 # include <unistd.h>
109 #endif
110 
111 #ifdef Q_WS_X11
112 # include <qx11info_x11.h>
113 # include <X11/Xlib.h>
114 #endif
115 
116 using namespace Kleo;
117 using namespace boost;
118 
119 static const unsigned int INIT_SOCKET_FLAGS = 3; // says info assuan...
120 //static int(*USE_DEFAULT_HANDLER)(assuan_context_t,char*) = 0;
121 static const int FOR_READING = 0;
122 static const unsigned int MAX_ACTIVE_FDS = 32;
123 
124 #ifdef HAVE_ASSUAN2
125 static void my_assuan_release( assuan_context_t ctx ) {
126  if ( ctx )
127  assuan_release( ctx );
128 }
129 
130 #endif
131 // shared_ptr for assuan_context_t w/ deleter enforced to assuan_deinit_server:
132 typedef shared_ptr< remove_pointer<assuan_context_t>::type > AssuanContextBase;
133 struct AssuanContext : AssuanContextBase {
134  AssuanContext() : AssuanContextBase() {}
135 #ifndef HAVE_ASSUAN2
136  explicit AssuanContext( assuan_context_t ctx ) : AssuanContextBase( ctx, &assuan_deinit_server ) {}
137 #else
138  explicit AssuanContext( assuan_context_t ctx ) : AssuanContextBase( ctx, &my_assuan_release ) {}
139 #endif
140 
141 #ifndef HAVE_ASSUAN2
142  void reset( assuan_context_t ctx=0 ) { AssuanContextBase::reset( ctx, &assuan_deinit_server ); }
143 #else
144  void reset( assuan_context_t ctx=0 ) { AssuanContextBase::reset( ctx, &my_assuan_release ); }
145 #endif
146 };
147 
148 static inline gpg_error_t assuan_process_done_msg( assuan_context_t ctx, gpg_error_t err, const char * err_msg ) {
149  return assuan_process_done( ctx, assuan_set_error( ctx, err, err_msg ) );
150 }
151 
152 static inline gpg_error_t assuan_process_done_msg( assuan_context_t ctx, gpg_error_t err, const std::string & err_msg ) {
153  return assuan_process_done_msg( ctx, err, err_msg.c_str() );
154 }
155 
156 static inline gpg_error_t assuan_process_done_msg( assuan_context_t ctx, gpg_error_t err, const QString & err_msg ) {
157  return assuan_process_done_msg( ctx, err, err_msg.toUtf8().constData() );
158 }
159 
160 static std::map<std::string,std::string> upcase_option( const char * option, std::map<std::string,std::string> options ) {
161  std::string value;
162  bool value_found = false;
163  std::map<std::string,std::string>::iterator it = options.begin();
164  while ( it != options.end() )
165  if ( qstricmp( it->first.c_str(), option ) == 0 ) {
166  value = it->second;
167  options.erase( it++ );
168  value_found = true;
169  } else {
170  ++it;
171  }
172  if ( value_found )
173  options[option] = value;
174  return options;
175 }
176 
177 static std::map<std::string,std::string> parse_commandline( const char * line ) {
178  std::map<std::string,std::string> result;
179  if ( line ) {
180  const char * begin = line;
181  const char * lastEQ = 0;
182  while ( *line ) {
183  if ( *line == ' ' || *line == '\t' ) {
184  if ( begin != line ) {
185  if ( begin[0] == '-' && begin[1] == '-' )
186  begin += 2; // skip initial "--"
187  if ( lastEQ && lastEQ > begin )
188  result[ std::string( begin, lastEQ - begin ) ] = hexdecode( std::string( lastEQ+1, line - (lastEQ+1) ) );
189  else
190  result[ std::string( begin, line - begin ) ] = std::string();
191  }
192  begin = line + 1;
193  } else if ( *line == '=' ) {
194  if ( line == begin )
195  throw Exception( gpg_error( GPG_ERR_ASS_SYNTAX ),
196  i18n("No option name given") );
197  else
198  lastEQ = line;
199  }
200  ++line;
201  }
202  if ( begin != line ) {
203  if ( begin[0] == '-' && begin[1] == '-' )
204  begin += 2; // skip initial "--"
205  if ( lastEQ && lastEQ > begin )
206  result[ std::string( begin, lastEQ - begin ) ] = hexdecode( std::string( lastEQ+1, line - (lastEQ+1 ) ) );
207  else
208  result[ begin ] = std::string();
209  }
210  }
211 
212  return result;
213 }
214 
215 static WId wid_from_string( const QString & winIdStr, bool * ok=0 ) {
216  return
217 #if defined(Q_OS_WIN32) || defined(_WIN32_WCE)
218  reinterpret_cast<WId>
219 #else
220  static_cast<WId>
221 #endif
222  ( winIdStr.toULongLong( ok, 16 ) );
223 }
224 
225 static void apply_window_id( QWidget * widget, const QString & winIdStr ) {
226  if ( !widget || winIdStr.isEmpty() )
227  return;
228  bool ok = false;
229  const WId wid = wid_from_string( winIdStr, &ok );
230  if ( !ok ) {
231  kDebug() << "window-id value" << wid << "doesn't look like a number";
232  return;
233  }
234  if ( QWidget * pw = QWidget::find( wid ) )
235  widget->setParent( pw, widget->windowFlags() );
236  else {
237  KWindowSystem::setMainWindow( widget, wid );
238  }
239 }
240 
241 //
242 //
243 // AssuanServerConnection:
244 //
245 //
246 
247 class AssuanServerConnection::Private : public QObject {
248  Q_OBJECT
249  friend class ::Kleo::AssuanServerConnection;
250  friend class ::Kleo::AssuanCommandFactory;
251  friend class ::Kleo::AssuanCommand;
252  AssuanServerConnection * const q;
253 public:
254  Private( assuan_fd_t fd_, const std::vector< shared_ptr<AssuanCommandFactory> > & factories_, AssuanServerConnection * qq );
255  ~Private();
256 
257 Q_SIGNALS:
258  void startKeyManager();
259 
260 public Q_SLOTS:
261  void slotReadActivity( int ) {
262  assert( ctx );
263 #ifndef HAVE_ASSUAN2
264  if ( const int err = assuan_process_next( ctx.get() ) ) {
265 #else
266  int done = false;
267  if ( const int err = assuan_process_next( ctx.get(), &done ) || done ) {
268 #endif
269  //if ( err == -1 || gpg_err_code(err) == GPG_ERR_EOF ) {
270  topHalfDeletion();
271  if ( nohupedCommands.empty() )
272  bottomHalfDeletion();
273  //} else {
274  //assuan_process_done( ctx.get(), err );
275  //return;
276  //}
277  }
278  }
279 
280  int startCommandBottomHalf();
281 
282 private:
283  void nohupDone( AssuanCommand * cmd ) {
284  const std::vector< shared_ptr<AssuanCommand> >::iterator it
285  = std::find_if( nohupedCommands.begin(), nohupedCommands.end(),
286  boost::bind( &shared_ptr<AssuanCommand>::get, _1 ) == cmd );
287  assert( it != nohupedCommands.end() );
288  nohupedCommands.erase( it );
289  if ( nohupedCommands.empty() && closed )
290  bottomHalfDeletion();
291  }
292 
293  void commandDone( AssuanCommand * cmd ) {
294  if ( !cmd || cmd != currentCommand.get() )
295  return;
296  currentCommand.reset();
297  }
298 
299  void topHalfDeletion() {
300  if ( currentCommand )
301  currentCommand->canceled();
302  if ( fd != ASSUAN_INVALID_FD ) {
303 #ifdef _WIN32_WCE
304  CloseHandle( (HANDLE)fd );
305 #elif defined(Q_OS_WIN32)
306  CloseHandle( fd );
307 #else
308  ::close( fd );
309 #endif
310  }
311  notifiers.clear();
312  closed = true;
313  }
314 
315  void bottomHalfDeletion() {
316  if ( sessionId )
317  SessionDataHandler::instance()->exitSession( sessionId );
318  cleanup();
319  const QPointer<Private> that = this;
320  emit q->closed( q );
321  if ( that ) // still there
322  q->deleteLater();
323  }
324 
325 private:
326 #ifndef HAVE_ASSUAN2
327  static void reset_handler( assuan_context_t ctx_ ) {
328 #else
329  static gpg_error_t reset_handler( assuan_context_t ctx_, char * ) {
330 #endif
331  assert( assuan_get_pointer( ctx_ ) );
332 
333  AssuanServerConnection::Private & conn = *static_cast<AssuanServerConnection::Private*>( assuan_get_pointer( ctx_ ) );
334 
335  conn.reset();
336 #ifdef HAVE_ASSUAN2
337 
338  return 0;
339 #endif
340  }
341 
342 #ifndef HAVE_ASSUAN2
343  static int option_handler( assuan_context_t ctx_, const char * key, const char * value ) {
344 #else
345  static gpg_error_t option_handler( assuan_context_t ctx_, const char * key, const char * value ) {
346 #endif
347  assert( assuan_get_pointer( ctx_ ) );
348 
349  AssuanServerConnection::Private & conn = *static_cast<AssuanServerConnection::Private*>( assuan_get_pointer( ctx_ ) );
350 
351  if ( key && key[0] == '-' && key[1] == '-' )
352  key += 2; // skip "--"
353  conn.options[key] = QString::fromUtf8( value );
354 
355  return 0;
356  //return gpg_error( GPG_ERR_UNKNOWN_OPTION );
357  }
358 
359 #ifndef HAVE_ASSUAN2
360  static int session_handler( assuan_context_t ctx_, char * line ) {
361 #else
362  static gpg_error_t session_handler( assuan_context_t ctx_, char * line ) {
363 #endif
364  assert( assuan_get_pointer( ctx_ ) );
365  AssuanServerConnection::Private & conn = *static_cast<AssuanServerConnection::Private*>( assuan_get_pointer( ctx_ ) );
366 
367  const QString str = QString::fromUtf8( line );
368  QRegExp rx( QLatin1String( "(\\d+)(?:\\s+(.*))?" ) );
369  if ( !rx.exactMatch( str ) ) {
370  static const QString errorString = i18n("Parse error");
371  return assuan_process_done_msg( ctx_, gpg_error( GPG_ERR_ASS_SYNTAX ), errorString );
372  }
373  bool ok = false;
374  if ( const qulonglong id = rx.cap( 1 ).toULongLong( &ok ) ) {
375  if ( ok && id <= std::numeric_limits<unsigned int>::max() ) {
376  SessionDataHandler::instance()->enterSession( id );
377  conn.sessionId = id;
378  } else {
379  static const QString errorString = i18n("Parse error: numeric session id too large");
380  return assuan_process_done_msg( ctx_, gpg_error( GPG_ERR_ASS_SYNTAX ), errorString );
381  }
382  }
383  if ( !rx.cap( 2 ).isEmpty() )
384  conn.sessionTitle = rx.cap( 2 );
385  kDebug() << "session_handler: "
386  << "id=" << static_cast<unsigned long>( conn.sessionId )
387  << ", title=" << qPrintable( conn.sessionTitle );
388  return assuan_process_done( ctx_, 0 );
389  }
390 
391 #ifndef HAVE_ASSUAN2
392  static int capabilities_handler( assuan_context_t ctx_, char * line ) {
393 #else
394  static gpg_error_t capabilities_handler( assuan_context_t ctx_, char * line ) {
395 #endif
396  if ( !QByteArray( line ).trimmed().isEmpty() ) {
397  static const QString errorString = i18n("CAPABILITIES does not take arguments");
398  return assuan_process_done_msg( ctx_, gpg_error( GPG_ERR_ASS_PARAMETER ), errorString );
399  }
400  static const char capabilities[] =
401  "SENDER=info\n"
402  "RECIPIENT=info\n"
403  "SESSION\n"
404  ;
405  return assuan_process_done( ctx_, assuan_send_data( ctx_, capabilities, sizeof capabilities - 1 ) );
406  }
407 
408 #ifndef HAVE_ASSUAN2
409  static int getinfo_handler( assuan_context_t ctx_, char * line ) {
410 #else
411  static gpg_error_t getinfo_handler( assuan_context_t ctx_, char * line ) {
412 #endif
413  assert( assuan_get_pointer( ctx_ ) );
414  AssuanServerConnection::Private & conn = *static_cast<AssuanServerConnection::Private*>( assuan_get_pointer( ctx_ ) );
415 
416  if ( qstrcmp( line, "version" ) == 0 ) {
417  static const char version[] = "Kleopatra " KLEOPATRA_VERSION_STRING ;
418  return assuan_process_done( ctx_, assuan_send_data( ctx_, version, sizeof version - 1 ) );
419  }
420 
421  QByteArray ba;
422  if ( qstrcmp( line, "pid" ) == 0 )
423  ba = QByteArray::number( mygetpid() );
424  else if ( qstrcmp( line, "options" ) == 0 )
425  ba = conn.dumpOptions();
426  else if ( qstrcmp( line, "x-mementos" ) == 0 )
427  ba = conn.dumpMementos();
428  else if ( qstrcmp( line, "senders" ) == 0 )
429  ba = conn.dumpSenders();
430  else if ( qstrcmp( line, "recipients" ) == 0 )
431  ba = conn.dumpRecipients();
432  else if ( qstrcmp( line, "x-files" ) == 0 )
433  ba = conn.dumpFiles();
434  else {
435  static const QString errorString = i18n("Unknown value for WHAT");
436  return assuan_process_done_msg( ctx_, gpg_error( GPG_ERR_ASS_PARAMETER ), errorString );
437  }
438  return assuan_process_done( ctx_, assuan_send_data( ctx_, ba.constData(), ba.size() ) );
439  }
440 
441 #ifndef HAVE_ASSUAN2
442  static int start_keymanager_handler( assuan_context_t ctx_, char * line ) {
443 #else
444  static gpg_error_t start_keymanager_handler( assuan_context_t ctx_, char * line ) {
445 #endif
446  assert( assuan_get_pointer( ctx_ ) );
447  AssuanServerConnection::Private & conn = *static_cast<AssuanServerConnection::Private*>( assuan_get_pointer( ctx_ ) );
448 
449  if ( line && *line ) {
450  static const QString errorString = i18n("START_KEYMANAGER does not take arguments");
451  return assuan_process_done_msg( ctx_, gpg_error( GPG_ERR_ASS_PARAMETER ), errorString );
452  }
453 
454  emit conn.q->startKeyManagerRequested();
455 
456  return assuan_process_done( ctx_, 0 );
457  }
458 
459 #ifndef HAVE_ASSUAN2
460  static int start_confdialog_handler( assuan_context_t ctx_, char * line ) {
461 #else
462  static gpg_error_t start_confdialog_handler( assuan_context_t ctx_, char * line ) {
463 #endif
464  assert( assuan_get_pointer( ctx_ ) );
465  AssuanServerConnection::Private & conn = *static_cast<AssuanServerConnection::Private*>( assuan_get_pointer( ctx_ ) );
466 
467  if ( line && *line ) {
468  static const QString errorString = i18n("START_CONFDIALOG does not take arguments");
469  return assuan_process_done_msg( ctx_, gpg_error( GPG_ERR_ASS_PARAMETER ), errorString );
470  }
471 
472  emit conn.q->startConfigDialogRequested();
473 
474  return assuan_process_done( ctx_, 0 );
475  }
476 
477  template <bool in> struct Input_or_Output : mpl::if_c<in,Input,Output> {};
478 
479  // format: TAG (FD|FD=\d+|FILE=...)
480  template <bool in, typename T_memptr>
481 #ifndef HAVE_ASSUAN2
482  static int IO_handler( assuan_context_t ctx_, char * line_, T_memptr which ) {
483 #else
484  static gpg_error_t IO_handler( assuan_context_t ctx_, char * line_, T_memptr which ) {
485 #endif
486  assert( assuan_get_pointer( ctx_ ) );
487  AssuanServerConnection::Private & conn = *static_cast<AssuanServerConnection::Private*>( assuan_get_pointer( ctx_ ) );
488 
489  char *binOpt = strstr ( line_, "--binary" );
490 
491  if ( binOpt && !in ) {
492  /* Note there is also --armor and --base64 allowed but we don't need
493  * to parse those because they are default.
494  * We remove it here so that it is not parsed as an Option.*/
495  memset (binOpt, ' ', 8 );
496  }
497 
498  try {
499 
500  /*const*/ std::map<std::string,std::string> options = upcase_option( "FD", upcase_option( "FILE", parse_commandline( line_ ) ) );
501  if ( options.size() < 1 || options.size() > 2 )
502  throw gpg_error( GPG_ERR_ASS_SYNTAX );
503 
504  shared_ptr< typename Input_or_Output<in>::type > io;
505 
506  if ( options.count( "FD" ) ) {
507 
508  if ( options.count( "FILE" ) )
509  throw gpg_error( GPG_ERR_CONFLICT );
510 
511  assuan_fd_t fd = ASSUAN_INVALID_FD;
512 
513  const std::string fdstr = options["FD"];
514 
515  if ( fdstr.empty() ) {
516  if ( const gpg_error_t err = assuan_receivefd( conn.ctx.get(), &fd ) )
517  throw err;
518  } else {
519 #ifdef _WIN32_WCE
520  fd = (assuan_fd_t)atoi( fdstr.c_str() );
521 #elif defined(Q_OS_WIN32)
522  fd = (assuan_fd_t)lexical_cast<intptr_t>( fdstr );
523 #else
524  fd = lexical_cast<assuan_fd_t>( fdstr );
525 #endif
526  }
527 
528  io = Input_or_Output<in>::type::createFromPipeDevice( fd, in ? i18n( "Message #%1", (conn.*which).size() + 1 ) : QString() );
529 
530  options.erase( "FD" );
531 
532  } else if ( options.count( "FILE" ) ) {
533 
534  if ( options.count( "FD" ) )
535  throw gpg_error( GPG_ERR_CONFLICT );
536 
537  const QString filePath = QFile::decodeName( options["FILE"].c_str() );
538  if ( filePath.isEmpty() )
539  throw Exception( gpg_error( GPG_ERR_ASS_SYNTAX ), i18n("Empty file path") );
540  const QFileInfo fi( filePath );
541  if ( !fi.isAbsolute() )
542  throw Exception( gpg_error( GPG_ERR_INV_ARG ), i18n("Only absolute file paths are allowed") );
543  if ( !fi.isFile() )
544  throw Exception( gpg_error( GPG_ERR_INV_ARG ), i18n("Only files are allowed in INPUT/OUTPUT FILE") );
545  else
546  io = Input_or_Output<in>::type::createFromFile( fi.absoluteFilePath(), true );
547 
548  options.erase( "FILE" );
549 
550  } else {
551 
552  throw gpg_error( GPG_ERR_ASS_PARAMETER );
553 
554  }
555 
556  if ( options.size() )
557  throw gpg_error( GPG_ERR_UNKNOWN_OPTION );
558 
559  (conn.*which).push_back( io );
560 
561  if ( binOpt && !in ) {
562  Output* out = reinterpret_cast <Output*>( io.get() );
563  out->setBinaryOpt( true );
564  kDebug() << "Configured output for binary data";
565  }
566 
567  kDebug() << "AssuanServerConnection: added" << io->label();
568 
569  return assuan_process_done( conn.ctx.get(), 0 );
570  } catch ( const GpgME::Exception & e ) {
571  return assuan_process_done_msg( conn.ctx.get(), e.error().encodedError(), e.message().c_str() );
572  } catch ( const std::exception & ) {
573  return assuan_process_done( conn.ctx.get(), gpg_error( GPG_ERR_ASS_SYNTAX ) );
574  } catch ( const gpg_error_t e ) {
575  return assuan_process_done( conn.ctx.get(), e );
576  } catch ( ... ) {
577  return assuan_process_done_msg( conn.ctx.get(), gpg_error( GPG_ERR_UNEXPECTED ), "unknown exception caught" );
578  }
579 
580  }
581 
582 #ifndef HAVE_ASSUAN2
583  static int input_handler( assuan_context_t ctx, char * line ) {
584 #else
585  static gpg_error_t input_handler( assuan_context_t ctx, char * line ) {
586 #endif
587  return IO_handler<true>( ctx, line, &Private::inputs );
588  }
589 
590 #ifndef HAVE_ASSUAN2
591  static int output_handler( assuan_context_t ctx, char * line ) {
592 #else
593  static gpg_error_t output_handler( assuan_context_t ctx, char * line ) {
594 #endif
595  return IO_handler<false>( ctx, line, &Private::outputs );
596  }
597 
598 #ifndef HAVE_ASSUAN2
599  static int message_handler( assuan_context_t ctx, char * line ) {
600 #else
601  static gpg_error_t message_handler( assuan_context_t ctx, char * line ) {
602 #endif
603  return IO_handler<true>( ctx, line, &Private::messages );
604  }
605 
606 #ifndef HAVE_ASSUAN2
607  static int file_handler( assuan_context_t ctx_, char * line ) {
608 #else
609  static gpg_error_t file_handler( assuan_context_t ctx_, char * line ) {
610 #endif
611  assert( assuan_get_pointer( ctx_ ) );
612  AssuanServerConnection::Private & conn = *static_cast<AssuanServerConnection::Private*>( assuan_get_pointer( ctx_ ) );
613 
614  try {
615  const QFileInfo fi( QFile::decodeName( hexdecode( line ).c_str() ) );
616  if ( !fi.isAbsolute() )
617  throw Exception( gpg_error( GPG_ERR_INV_ARG ), i18n("Only absolute file paths are allowed") );
618  if ( !fi.exists() )
619  throw gpg_error( GPG_ERR_ENOENT );
620  if ( !fi.isReadable() || ( fi.isDir() && !fi.isExecutable() ) )
621  throw gpg_error( GPG_ERR_EPERM );
622 
623  conn.files.push_back( fi.absoluteFilePath() );
624 
625  return assuan_process_done( conn.ctx.get(), 0 );
626  } catch ( const Exception & e ) {
627  return assuan_process_done_msg( conn.ctx.get(), e.error().encodedError(), e.message().toUtf8().constData() );
628  } catch ( const gpg_error_t e ) {
629  return assuan_process_done( conn.ctx.get(), e );
630  } catch ( ... ) {
631  return assuan_process_done_msg( conn.ctx.get(), gpg_error( GPG_ERR_UNEXPECTED ), i18n("unknown exception caught").toUtf8().constData() );
632  }
633  }
634 
635  static bool parse_informative( const char * & begin, GpgME::Protocol & protocol ) {
636  protocol = GpgME::UnknownProtocol;
637  bool informative = false;
638  const char * pos = begin;
639  while ( true ) {
640  while ( *pos == ' ' || *pos == '\t' )
641  ++pos;
642  if ( qstrnicmp( pos, "--info", strlen("--info") ) == 0 ) {
643  informative = true;
644  pos += strlen("--info");
645  if ( *pos == '=' ) {
646  ++pos;
647  break;
648  }
649  } else if ( qstrnicmp( pos, "--protocol=", strlen("--protocol=") ) == 0 ) {
650  pos += strlen("--protocol=");
651  if ( qstrnicmp( pos, "OpenPGP", strlen("OpenPGP") ) == 0 ) {
652  protocol = GpgME::OpenPGP;
653  pos += strlen("OpenPGP");
654  } else if ( qstrnicmp( pos, "CMS", strlen("CMS") ) == 0 ) {
655  protocol = GpgME::CMS;
656  pos += strlen("CMS");
657  } else {
658  ;
659  }
660  } else if ( qstrncmp( pos, "-- ", strlen("-- ") ) == 0 ) {
661  pos += 3;
662  while ( *pos == ' ' || *pos == '\t' )
663  ++pos;
664  break;
665  } else
666  break;
667  }
668  begin = pos;
669  return informative;
670  }
671 
672  template <typename T_memptr, typename T_memptr2>
673 #ifndef HAVE_ASSUAN2
674  static int recipient_sender_handler( T_memptr mp, T_memptr2 info, assuan_context_t ctx, char * line, bool sender=false ) {
675 #else
676  static gpg_error_t recipient_sender_handler( T_memptr mp, T_memptr2 info, assuan_context_t ctx, char * line, bool sender=false ) {
677 #endif
678  assert( assuan_get_pointer( ctx ) );
679  AssuanServerConnection::Private & conn = *static_cast<AssuanServerConnection::Private*>( assuan_get_pointer( ctx ) );
680 
681  if ( !line || !*line )
682  return assuan_process_done( conn.ctx.get(), gpg_error( GPG_ERR_INV_ARG ) );
683  const char * begin = line;
684  const char * const end = begin + qstrlen( line );
685  GpgME::Protocol proto = GpgME::UnknownProtocol;
686  const bool informative = parse_informative( begin, proto );
687  if ( !(conn.*mp).empty() && informative != (conn.*info) )
688  return assuan_process_done_msg( conn.ctx.get(), gpg_error( GPG_ERR_CONFLICT ),
689  i18n("Cannot mix --info with non-info SENDER or RECIPIENT").toUtf8().constData() );
690  KMime::Types::Mailbox mb;
691  if ( !KMime::HeaderParsing::parseMailbox( begin, end, mb ) )
692  return assuan_process_done_msg( conn.ctx.get(), gpg_error( GPG_ERR_INV_ARG ),
693  i18n("Argument is not a valid RFC-2822 mailbox").toUtf8().constData() );
694  if ( begin != end )
695  return assuan_process_done_msg( conn.ctx.get(), gpg_error( GPG_ERR_INV_ARG ),
696  i18n("Garbage after valid RFC-2822 mailbox detected").toUtf8().constData() );
697  (conn.*info) = informative;
698  (conn.*mp).push_back( mb );
699 
700  const QString email = mb.addrSpec().asString();
701  (void)assuan_write_line( conn.ctx.get(), qPrintable( QString().sprintf( "# ok, parsed as \"%s\"", qPrintable( email ) ) ) );
702  if ( sender && !informative )
703  return AssuanCommandFactory::_handle( conn.ctx.get(), line, "PREP_SIGN" );
704  else
705  return assuan_process_done( ctx, 0 );
706  }
707 
708 #ifndef HAVE_ASSUAN2
709  static int recipient_handler( assuan_context_t ctx, char * line ) {
710 #else
711  static gpg_error_t recipient_handler( assuan_context_t ctx, char * line ) {
712 #endif
713  return recipient_sender_handler( &Private::recipients, &Private::informativeRecipients, ctx, line );
714  }
715 
716 #ifndef HAVE_ASSUAN2
717  static int sender_handler( assuan_context_t ctx, char * line ) {
718 #else
719  static gpg_error_t sender_handler( assuan_context_t ctx, char * line ) {
720 #endif
721  return recipient_sender_handler( &Private::senders, &Private::informativeSenders, ctx, line, true );
722  }
723 
724  QByteArray dumpOptions() const {
725  QByteArray result;
726  for ( std::map<std::string,QVariant>::const_iterator it = options.begin(), end = options.end() ; it != end ; ++it )
727  result += it->first.c_str() + it->second.toString().toUtf8() + '\n';
728  return result;
729  }
730 
731  static QByteArray dumpStringList( const QStringList & sl ) {
732  return sl.join( QLatin1String( "\n" ) ).toUtf8();
733  }
734 
735  template <typename T_container>
736  static QByteArray dumpStringList( const T_container & c ) {
737  QStringList sl;
738  std::copy( c.begin(), c.end(), std::back_inserter( sl ) );
739  return dumpStringList( sl );
740  }
741 
742  template <typename T_container>
743  static QByteArray dumpMailboxes( const T_container & c ) {
744  QStringList sl;
745  std::transform( c.begin(), c.end(),
746  std::back_inserter( sl ),
747  boost::bind( &KMime::Types::Mailbox::prettyAddress, _1 ) );
748  return dumpStringList( sl );
749  }
750 
751  QByteArray dumpSenders() const {
752  return dumpMailboxes( senders );
753  }
754 
755  QByteArray dumpRecipients() const {
756  return dumpMailboxes( recipients );
757  }
758 
759  QByteArray dumpMementos() const {
760  QByteArray result;
761  for ( std::map< QByteArray, shared_ptr<AssuanCommand::Memento> >::const_iterator it = mementos.begin(), end = mementos.end() ; it != end ; ++it ) {
762  char buf[2 + 2*sizeof(void*) + 2];
763  sprintf( buf, "0x%p\n", ( void* )it->second.get() );
764  buf[sizeof(buf)-1] = '\0';
765  result += it->first + QByteArray::fromRawData( buf, sizeof buf );
766  }
767  return result;
768  }
769 
770  QByteArray dumpFiles() const {
771  return dumpStringList( kdtools::copy<QStringList>( files ) );
772  }
773 
774  void cleanup();
775  void reset() {
776  options.clear();
777  senders.clear();
778  informativeSenders = false;
779  recipients.clear();
780  informativeRecipients = false;
781  sessionTitle.clear();
782  sessionId = 0;
783  mementos.clear();
784  files.clear();
785  std::for_each( inputs.begin(), inputs.end(),
786  boost::bind( &Input::finalize, _1 ) );
787  inputs.clear();
788  std::for_each( outputs.begin(), outputs.end(),
789  boost::bind( &Output::finalize, _1 ) );
790  outputs.clear();
791  std::for_each( messages.begin(), messages.end(),
792  boost::bind( &Input::finalize, _1 ) );
793  messages.clear();
794  bias = GpgME::UnknownProtocol;
795  }
796 
797  assuan_fd_t fd;
798  AssuanContext ctx;
799  bool closed : 1;
800  bool cryptoCommandsEnabled : 1;
801  bool commandWaitingForCryptoCommandsEnabled : 1;
802  bool currentCommandIsNohup : 1;
803  bool informativeSenders; // address taken, so no : 1
804  bool informativeRecipients; // address taken, so no : 1
805  GpgME::Protocol bias;
806  QString sessionTitle;
807  unsigned int sessionId;
808  std::vector< shared_ptr<QSocketNotifier> > notifiers;
809  std::vector< shared_ptr<AssuanCommandFactory> > factories; // sorted: _detail::ByName<std::less>
810  shared_ptr<AssuanCommand> currentCommand;
811  std::vector< shared_ptr<AssuanCommand> > nohupedCommands;
812  std::map<std::string,QVariant> options;
813  std::vector<KMime::Types::Mailbox> senders, recipients;
814  std::vector< shared_ptr<Input> > inputs, messages;
815  std::vector< shared_ptr<Output> > outputs;
816  std::vector<QString> files;
817  std::map< QByteArray, shared_ptr<AssuanCommand::Memento> > mementos;
818 };
819 
820 void AssuanServerConnection::Private::cleanup() {
821  assert( nohupedCommands.empty() );
822  reset();
823  currentCommand.reset();
824  currentCommandIsNohup = false;
825  commandWaitingForCryptoCommandsEnabled = false;
826  notifiers.clear();
827  ctx.reset();
828  fd = ASSUAN_INVALID_FD;
829 }
830 
831 AssuanServerConnection::Private::Private( assuan_fd_t fd_, const std::vector< shared_ptr<AssuanCommandFactory> > & factories_, AssuanServerConnection * qq )
832  : QObject(),
833  q( qq ),
834  fd( fd_ ),
835  closed( false ),
836  cryptoCommandsEnabled( false ),
837  commandWaitingForCryptoCommandsEnabled( false ),
838  currentCommandIsNohup( false ),
839  informativeSenders( false ),
840  informativeRecipients( false ),
841  bias( GpgME::UnknownProtocol ),
842  sessionId( 0 ),
843  factories( factories_ )
844 {
845 #ifdef __GNUC__
846  assert( __gnu_cxx::is_sorted( factories_.begin(), factories_.end(), _detail::ByName<std::less>() ) );
847 #endif
848 
849  if ( fd == ASSUAN_INVALID_FD )
850  throw Exception( gpg_error( GPG_ERR_INV_ARG ), "pre-assuan_init_socket_server_ext" );
851 
852 #ifndef HAVE_ASSUAN2
853  assuan_context_t naked_ctx = 0;
854  if ( const gpg_error_t err = assuan_init_socket_server_ext( &naked_ctx, fd, INIT_SOCKET_FLAGS ) )
855 #else
856  {
857  assuan_context_t naked_ctx = 0;
858  if ( const gpg_error_t err = assuan_new( &naked_ctx ) )
859  throw Exception( err, "assuan_new" );
860  ctx.reset( naked_ctx );
861  }
862  if ( const gpg_error_t err = assuan_init_socket_server( ctx.get(), fd, INIT_SOCKET_FLAGS ) )
863 #endif
864  throw Exception( err, "assuan_init_socket_server_ext" );
865 
866 #ifndef HAVE_ASSUAN2
867  ctx.reset( naked_ctx ); naked_ctx = 0;
868 #endif
869 
870  // for callbacks, associate the context with this connection:
871  assuan_set_pointer( ctx.get(), this );
872 
873  FILE* const logFile = Log::instance()->logFile();
874  assuan_set_log_stream( ctx.get(), logFile ? logFile : stderr );
875 
876  // register FDs with the event loop:
877  assuan_fd_t fds[MAX_ACTIVE_FDS];
878  const int numFDs = assuan_get_active_fds( ctx.get(), FOR_READING, fds, MAX_ACTIVE_FDS );
879  assert( numFDs != -1 ); // == 1
880 
881  if ( !numFDs || fds[0] != fd ) {
882  const shared_ptr<QSocketNotifier> sn( new QSocketNotifier( (intptr_t)fd, QSocketNotifier::Read ), mem_fn( &QObject::deleteLater ) );
883  connect( sn.get(), SIGNAL(activated(int)), this, SLOT(slotReadActivity(int)) );
884  notifiers.push_back( sn );
885  }
886 
887  notifiers.reserve( notifiers.size() + numFDs );
888  for ( int i = 0 ; i < numFDs ; ++i ) {
889  const shared_ptr<QSocketNotifier> sn( new QSocketNotifier( (intptr_t)fds[i], QSocketNotifier::Read ), mem_fn( &QObject::deleteLater ) );
890  connect( sn.get(), SIGNAL(activated(int)), this, SLOT(slotReadActivity(int)) );
891  notifiers.push_back( sn );
892  }
893 
894 
895  // register our INPUT/OUTPUT/MESSGAE/FILE handlers:
896 #ifndef HAVE_ASSUAN2
897  if ( const gpg_error_t err = assuan_register_command( ctx.get(), "INPUT", input_handler ) )
898 #else
899  if ( const gpg_error_t err = assuan_register_command( ctx.get(), "INPUT", input_handler, "" ) )
900 #endif
901  throw Exception( err, "register \"INPUT\" handler" );
902 #ifndef HAVE_ASSUAN2
903  if ( const gpg_error_t err = assuan_register_command( ctx.get(), "MESSAGE", message_handler ) )
904 #else
905  if ( const gpg_error_t err = assuan_register_command( ctx.get(), "MESSAGE", message_handler, "" ) )
906 #endif
907  throw Exception( err, "register \"MESSAGE\" handler" );
908 #ifndef HAVE_ASSUAN2
909  if ( const gpg_error_t err = assuan_register_command( ctx.get(), "OUTPUT", output_handler ) )
910 #else
911  if ( const gpg_error_t err = assuan_register_command( ctx.get(), "OUTPUT", output_handler, "" ) )
912 #endif
913  throw Exception( err, "register \"OUTPUT\" handler" );
914 #ifndef HAVE_ASSUAN2
915  if ( const gpg_error_t err = assuan_register_command( ctx.get(), "FILE", file_handler ) )
916 #else
917  if ( const gpg_error_t err = assuan_register_command( ctx.get(), "FILE", file_handler, "" ) )
918 #endif
919  throw Exception( err, "register \"FILE\" handler" );
920 
921 
922  // register user-defined commands:
923  Q_FOREACH( shared_ptr<AssuanCommandFactory> fac, factories )
924 #ifndef HAVE_ASSUAN2
925  if ( const gpg_error_t err = assuan_register_command( ctx.get(), fac->name(), fac->_handler() ) )
926 #else
927  if ( const gpg_error_t err = assuan_register_command( ctx.get(), fac->name(), fac->_handler(), "" ) )
928 #endif
929  throw Exception( err, std::string( "register \"" ) + fac->name() + "\" handler" );
930 
931 #ifndef HAVE_ASSUAN2
932  if ( const gpg_error_t err = assuan_register_command( ctx.get(), "GETINFO", getinfo_handler ) )
933 #else
934  if ( const gpg_error_t err = assuan_register_command( ctx.get(), "GETINFO", getinfo_handler, "" ) )
935 #endif
936  throw Exception( err, "register \"GETINFO\" handler" );
937 #ifndef HAVE_ASSUAN2
938  if ( const gpg_error_t err = assuan_register_command( ctx.get(), "START_KEYMANAGER", start_keymanager_handler ) )
939 #else
940  if ( const gpg_error_t err = assuan_register_command( ctx.get(), "START_KEYMANAGER", start_keymanager_handler, "" ) )
941 #endif
942  throw Exception( err, "register \"START_KEYMANAGER\" handler" );
943 #ifndef HAVE_ASSUAN2
944  if ( const gpg_error_t err = assuan_register_command( ctx.get(), "START_CONFDIALOG", start_confdialog_handler ) )
945 #else
946  if ( const gpg_error_t err = assuan_register_command( ctx.get(), "START_CONFDIALOG", start_confdialog_handler, "" ) )
947 #endif
948  throw Exception( err, "register \"START_CONFDIALOG\" handler" );
949 #ifndef HAVE_ASSUAN2
950  if ( const gpg_error_t err = assuan_register_command( ctx.get(), "RECIPIENT", recipient_handler ) )
951 #else
952  if ( const gpg_error_t err = assuan_register_command( ctx.get(), "RECIPIENT", recipient_handler, "" ) )
953 #endif
954  throw Exception( err, "register \"RECIPIENT\" handler" );
955 #ifndef HAVE_ASSUAN2
956  if ( const gpg_error_t err = assuan_register_command( ctx.get(), "SENDER", sender_handler ) )
957 #else
958  if ( const gpg_error_t err = assuan_register_command( ctx.get(), "SENDER", sender_handler, "" ) )
959 #endif
960  throw Exception( err, "register \"SENDER\" handler" );
961 #ifndef HAVE_ASSUAN2
962  if ( const gpg_error_t err = assuan_register_command( ctx.get(), "SESSION", session_handler ) )
963 #else
964  if ( const gpg_error_t err = assuan_register_command( ctx.get(), "SESSION", session_handler, "" ) )
965 #endif
966  throw Exception( err, "register \"SESSION\" handler" );
967 #ifndef HAVE_ASSUAN2
968  if ( const gpg_error_t err = assuan_register_command( ctx.get(), "CAPABILITIES", capabilities_handler ) )
969 #else
970  if ( const gpg_error_t err = assuan_register_command( ctx.get(), "CAPABILITIES", capabilities_handler, "" ) )
971 #endif
972  throw Exception( err, "register \"CAPABILITIES\" handler" );
973 
974  assuan_set_hello_line( ctx.get(), "GPG UI server (Kleopatra/" KLEOPATRA_VERSION_STRING ") ready to serve" );
975  //assuan_set_hello_line( ctx.get(), GPG UI server (qApp->applicationName() + " v" + kapp->applicationVersion() + "ready to serve" )
976 
977 
978  // some notifiers we're interested in:
979  if ( const gpg_error_t err = assuan_register_reset_notify( ctx.get(), reset_handler ) )
980  throw Exception( err, "register reset notify" );
981  if ( const gpg_error_t err = assuan_register_option_handler( ctx.get(), option_handler ) )
982  throw Exception( err, "register option handler" );
983 
984  // and last, we need to call assuan_accept, which doesn't block
985  // (d/t INIT_SOCKET_FLAGS), but performs vital connection
986  // establishing handling:
987  if ( const gpg_error_t err = assuan_accept( ctx.get() ) )
988  throw Exception( err, "assuan_accept" );
989 }
990 
991 AssuanServerConnection::Private::~Private() {
992  cleanup();
993 }
994 
995 AssuanServerConnection::AssuanServerConnection( assuan_fd_t fd, const std::vector< shared_ptr<AssuanCommandFactory> > & factories, QObject * p )
996  : QObject( p ), d( new Private( fd, factories, this ) )
997 {
998 
999 }
1000 
1001 AssuanServerConnection::~AssuanServerConnection() {}
1002 
1003 void AssuanServerConnection::enableCryptoCommands( bool on ) {
1004  if ( on == d->cryptoCommandsEnabled )
1005  return;
1006  d->cryptoCommandsEnabled = on;
1007  if ( d->commandWaitingForCryptoCommandsEnabled )
1008  QTimer::singleShot( 0, d.get(), SLOT(startCommandBottomHalf()) );
1009 }
1010 
1011 
1012 //
1013 //
1014 // AssuanCommand:
1015 //
1016 //
1017 
1018 namespace Kleo {
1019 
1020 class InquiryHandler : public QObject {
1021  Q_OBJECT
1022 public:
1023 
1024 #if defined(HAVE_ASSUAN2) || defined(HAVE_ASSUAN_INQUIRE_EXT)
1025  explicit InquiryHandler( const char * keyword_, QObject * p=0 )
1026  : QObject( p ),
1027 # if !defined(HAVE_ASSUAN2) && !defined(HAVE_NEW_STYLE_ASSUAN_INQUIRE_EXT)
1028  buffer( 0 ),
1029  buflen( 0 ),
1030 # endif
1031  keyword( keyword_ )
1032  {
1033 
1034  }
1035 
1036 # if defined(HAVE_ASSUAN2) || defined(HAVE_NEW_STYLE_ASSUAN_INQUIRE_EXT)
1037 # ifndef HAVE_ASSUAN2
1038  static int handler( void * cb_data, int rc, unsigned char * buffer, size_t buflen )
1039 # else
1040  static gpg_error_t handler( void * cb_data, gpg_error_t rc, unsigned char * buffer, size_t buflen )
1041 # endif
1042  {
1043  assert( cb_data );
1044  InquiryHandler * this_ = static_cast<InquiryHandler*>(cb_data);
1045  emit this_->signal( rc, QByteArray::fromRawData( reinterpret_cast<const char*>(buffer), buflen ), this_->keyword );
1046  std::free( buffer );
1047  delete this_;
1048  return 0;
1049  }
1050 # else
1051  static int handler( void * cb_data, int rc )
1052  {
1053  assert( cb_data );
1054  InquiryHandler * this_ = static_cast<InquiryHandler*>(cb_data);
1055  emit this_->signal( rc, QByteArray::fromRawData( reinterpret_cast<const char*>(this_->buffer), this_->buflen ), this_->keyword );
1056  std::free( this_->buffer );
1057  delete this_;
1058  return 0;
1059  }
1060 # endif
1061 
1062 private:
1063 #if !defined(HAVE_ASSUAN2) && !defined(HAVE_NEW_STYLE_ASSUAN_INQUIRE_EXT)
1064  friend class ::Kleo::AssuanCommand;
1065  unsigned char * buffer;
1066  size_t buflen;
1067 #endif
1068  const char * keyword;
1069 #endif // defined(HAVE_ASSUAN2) || defined(HAVE_ASSUAN_INQUIRE_EXT)
1070 
1071 Q_SIGNALS:
1072  void signal( int rc, const QByteArray & data, const QByteArray & keyword );
1073 };
1074 
1075 } // namespace Kleo
1076 
1077 class AssuanCommand::Private {
1078 public:
1079  Private()
1080  : informativeRecipients( false ),
1081  informativeSenders( false ),
1082  bias( GpgME::UnknownProtocol ),
1083  done( false ),
1084  nohup( false )
1085  {
1086 
1087  }
1088 
1089  std::map<std::string,QVariant> options;
1090  std::vector< shared_ptr<Input> > inputs, messages;
1091  std::vector< shared_ptr<Output> > outputs;
1092  std::vector<QString> files;
1093  std::vector<KMime::Types::Mailbox> recipients, senders;
1094  bool informativeRecipients, informativeSenders;
1095  GpgME::Protocol bias;
1096  QString sessionTitle;
1097  unsigned int sessionId;
1098  QByteArray utf8ErrorKeepAlive;
1099  AssuanContext ctx;
1100  bool done;
1101  bool nohup;
1102 };
1103 
1104 AssuanCommand::AssuanCommand()
1105  : d( new Private )
1106 {
1107 
1108 }
1109 
1110 AssuanCommand::~AssuanCommand() {
1111 
1112 }
1113 
1114 int AssuanCommand::start() {
1115  try {
1116  if ( const int err = doStart() )
1117  if ( !d->done )
1118  done( err );
1119  return 0;
1120  } catch ( const Exception & e ) {
1121  if ( !d->done )
1122  done( e.error_code(), e.message() );
1123  return 0;
1124  } catch ( const GpgME::Exception & e ) {
1125  if ( !d->done )
1126  done( e.error(), QString::fromLocal8Bit( e.message().c_str() ) );
1127  return 0;
1128  } catch ( const std::exception & e ) {
1129  if ( !d->done )
1130  done( makeError( GPG_ERR_INTERNAL ), i18n("Caught unexpected exception: %1", QString::fromLocal8Bit( e.what() ) ) );
1131  return 0;
1132  } catch ( ... ) {
1133  if ( !d->done )
1134  done( makeError( GPG_ERR_INTERNAL ), i18n("Caught unknown exception - please report this error to the developers." ) );
1135  return 0;
1136  }
1137 }
1138 
1139 void AssuanCommand::canceled() {
1140  d->done = true;
1141  doCanceled();
1142 }
1143 
1144 // static
1145 int AssuanCommand::makeError( int code ) {
1146  return makeGnuPGError( code );
1147 }
1148 
1149 bool AssuanCommand::hasOption( const char * opt ) const {
1150  return d->options.count( opt );
1151 }
1152 
1153 QVariant AssuanCommand::option( const char * opt ) const {
1154  const std::map<std::string,QVariant>::const_iterator it = d->options.find( opt );
1155  if ( it == d->options.end() )
1156  return QVariant();
1157  else
1158  return it->second;
1159 }
1160 
1161 const std::map<std::string,QVariant> & AssuanCommand::options() const {
1162  return d->options;
1163 }
1164 
1165 namespace {
1166  template <typename U, typename V>
1167  std::vector<U> keys( const std::map<U,V> & map ) {
1168  std::vector<U> result;
1169  result.resize( map.size() );
1170  for ( typename std::map<U,V>::const_iterator it = map.begin(), end = map.end() ; it != end ; ++it )
1171  result.push_back( it->first );
1172  return result;
1173  }
1174 }
1175 
1176 const std::map< QByteArray, shared_ptr<AssuanCommand::Memento> > & AssuanCommand::mementos() const {
1177  // oh, hack :(
1178  assert( assuan_get_pointer( d->ctx.get() ) );
1179  const AssuanServerConnection::Private & conn = *static_cast<AssuanServerConnection::Private*>( assuan_get_pointer( d->ctx.get() ) );
1180  return conn.mementos;
1181 }
1182 
1183 bool AssuanCommand::hasMemento( const QByteArray & tag ) const {
1184  if ( const unsigned int id = sessionId() )
1185  return SessionDataHandler::instance()->sessionData(id)->mementos.count( tag ) || mementos().count( tag ) ;
1186  else
1187  return mementos().count( tag );
1188 }
1189 
1190 shared_ptr<AssuanCommand::Memento> AssuanCommand::memento( const QByteArray & tag ) const {
1191  if ( const unsigned int id = sessionId() ) {
1192  const shared_ptr<SessionDataHandler> sdh = SessionDataHandler::instance();
1193  const shared_ptr<SessionData> sd = sdh->sessionData(id);
1194  const std::map< QByteArray, shared_ptr<Memento> >::const_iterator it = sd->mementos.find( tag );
1195  if ( it != sd->mementos.end() )
1196  return it->second;
1197  }
1198  const std::map< QByteArray, shared_ptr<Memento> >::const_iterator it = mementos().find( tag );
1199  if ( it == mementos().end() )
1200  return shared_ptr<Memento>();
1201  else
1202  return it->second;
1203 }
1204 
1205 QByteArray AssuanCommand::registerMemento( const shared_ptr<Memento> & mem ) {
1206  const QByteArray tag = QByteArray::number( reinterpret_cast<qulonglong>( mem.get() ), 36 );
1207  return registerMemento( tag, mem );
1208 }
1209 
1210 QByteArray AssuanCommand::registerMemento( const QByteArray & tag, const shared_ptr<Memento> & mem ) {
1211  // oh, hack :(
1212  assert( assuan_get_pointer( d->ctx.get() ) );
1213  AssuanServerConnection::Private & conn = *static_cast<AssuanServerConnection::Private*>( assuan_get_pointer( d->ctx.get() ) );
1214 
1215  if ( const unsigned int id = sessionId() )
1216  SessionDataHandler::instance()->sessionData(id)->mementos[tag] = mem;
1217  else
1218  conn.mementos[tag] = mem;
1219  return tag;
1220 }
1221 
1222 void AssuanCommand::removeMemento( const QByteArray & tag ) {
1223  // oh, hack :(
1224  assert( assuan_get_pointer( d->ctx.get() ) );
1225  AssuanServerConnection::Private & conn = *static_cast<AssuanServerConnection::Private*>( assuan_get_pointer( d->ctx.get() ) );
1226 
1227  conn.mementos.erase( tag );
1228  if ( const unsigned int id = sessionId() )
1229  SessionDataHandler::instance()->sessionData(id)->mementos.erase( tag );
1230 }
1231 
1232 const std::vector< shared_ptr<Input> > & AssuanCommand::inputs() const {
1233  return d->inputs;
1234 }
1235 
1236 const std::vector< shared_ptr<Input> > & AssuanCommand::messages() const {
1237  return d->messages;
1238 }
1239 
1240 const std::vector< shared_ptr<Output> > & AssuanCommand::outputs() const {
1241  return d->outputs;
1242 }
1243 
1244 QStringList AssuanCommand::fileNames() const {
1245  return kdtools::copy<QStringList>( d->files );
1246 }
1247 
1248 unsigned int AssuanCommand::numFiles() const {
1249  return d->files.size();
1250 }
1251 
1252 void AssuanCommand::sendStatus( const char * keyword, const QString & text ) {
1253  sendStatusEncoded( keyword, text.toUtf8().constData() );
1254 }
1255 
1256 void AssuanCommand::sendStatusEncoded( const char * keyword, const std::string & text ) {
1257  if ( d->nohup )
1258  return;
1259  if ( const int err = assuan_write_status( d->ctx.get(), keyword, text.c_str() ) )
1260  throw Exception( err, i18n( "Cannot send \"%1\" status", QString::fromLatin1( keyword ) ) );
1261 }
1262 
1263 void AssuanCommand::sendData( const QByteArray & data, bool moreToCome ) {
1264  if ( d->nohup )
1265  return;
1266  if ( const gpg_error_t err = assuan_send_data( d->ctx.get(), data.constData(), data.size() ) )
1267  throw Exception( err, i18n( "Cannot send data" ) );
1268  if ( !moreToCome )
1269  if ( const gpg_error_t err = assuan_send_data( d->ctx.get(), 0, 0 ) ) // flush
1270  throw Exception( err, i18n( "Cannot flush data" ) );
1271 }
1272 
1273 int AssuanCommand::inquire( const char * keyword, QObject * receiver, const char * slot, unsigned int maxSize ) {
1274  assert( keyword );
1275  assert( receiver );
1276  assert( slot );
1277 
1278  if ( d->nohup )
1279  return makeError( GPG_ERR_INV_OP );
1280 
1281 #if defined(HAVE_ASSUAN2) || defined(HAVE_ASSUAN_INQUIRE_EXT)
1282  std::auto_ptr<InquiryHandler> ih( new InquiryHandler( keyword, receiver ) );
1283  receiver->connect( ih.get(), SIGNAL(signal(int,QByteArray,QByteArray)), slot );
1284  if ( const gpg_error_t err = assuan_inquire_ext( d->ctx.get(), keyword,
1285 # if !defined(HAVE_ASSUAN2) && !defined(HAVE_NEW_STYLE_ASSUAN_INQUIRE_EXT)
1286  &ih->buffer, &ih->buflen,
1287 # endif
1288  maxSize, InquiryHandler::handler, ih.get() ) )
1289  return err;
1290  ih.release();
1291  return 0;
1292 #else
1293  return makeError( GPG_ERR_NOT_SUPPORTED ); // libassuan too old
1294 #endif // defined(HAVE_ASSUAN2) || defined(HAVE_ASSUAN_INQUIRE_EXT)
1295 }
1296 
1297 void AssuanCommand::done( const GpgME::Error& err, const QString & details ) {
1298  if ( d->ctx && !d->done && !details.isEmpty() ) {
1299  kDebug() << "Error: " << details;
1300  d->utf8ErrorKeepAlive = details.toUtf8();
1301  if ( !d->nohup )
1302  assuan_set_error( d->ctx.get(), err.encodedError(), d->utf8ErrorKeepAlive.constData() );
1303  }
1304  done( err );
1305 }
1306 
1307 void AssuanCommand::done( const GpgME::Error& err ) {
1308  if ( !d->ctx ) {
1309  kDebug() << err.asString() << ": called with NULL ctx.";
1310  return;
1311  }
1312  if ( d->done ) {
1313  kDebug() << err.asString() << ": called twice!";
1314  return;
1315  }
1316 
1317  d->done = true;
1318 
1319  std::for_each( d->messages.begin(), d->messages.end(),
1320  boost::bind( &Input::finalize, _1 ) );
1321  std::for_each( d->inputs.begin(), d->inputs.end(),
1322  boost::bind( &Input::finalize, _1 ) );
1323  std::for_each( d->outputs.begin(), d->outputs.end(),
1324  boost::bind( &Output::finalize, _1 ) );
1325  d->messages.clear();
1326  d->inputs.clear();
1327  d->outputs.clear();
1328  d->files.clear();
1329 
1330  // oh, hack :(
1331  assert( assuan_get_pointer( d->ctx.get() ) );
1332  AssuanServerConnection::Private & conn = *static_cast<AssuanServerConnection::Private*>( assuan_get_pointer( d->ctx.get() ) );
1333 
1334  if ( d->nohup ) {
1335  conn.nohupDone( this );
1336  return;
1337  }
1338 
1339  const gpg_error_t rc = assuan_process_done( d->ctx.get(), err.encodedError() );
1340  if ( gpg_err_code( rc ) != GPG_ERR_NO_ERROR )
1341  qFatal( "AssuanCommand::done: assuan_process_done returned error %d (%s)",
1342  static_cast<int>(rc), gpg_strerror(rc) );
1343 
1344  d->utf8ErrorKeepAlive.clear();
1345 
1346  conn.commandDone( this );
1347 }
1348 
1349 
1350 void AssuanCommand::setNohup( bool nohup ) {
1351  d->nohup = nohup;
1352 }
1353 
1354 bool AssuanCommand::isNohup() const {
1355  return d->nohup;
1356 }
1357 
1358 bool AssuanCommand::isDone() const {
1359  return d->done;
1360 }
1361 
1362 QString AssuanCommand::sessionTitle() const {
1363  return d->sessionTitle;
1364 }
1365 
1366 unsigned int AssuanCommand::sessionId() const {
1367  return d->sessionId;
1368 }
1369 
1370 bool AssuanCommand::informativeSenders() const {
1371  return d->informativeSenders;
1372 }
1373 
1374 bool AssuanCommand::informativeRecipients() const {
1375  return d->informativeRecipients;
1376 }
1377 
1378 const std::vector<KMime::Types::Mailbox> & AssuanCommand::recipients() const {
1379  return d->recipients;
1380 }
1381 
1382 const std::vector<KMime::Types::Mailbox> & AssuanCommand::senders() const {
1383  return d->senders;
1384 }
1385 
1386 #ifndef HAVE_ASSUAN2
1387 int AssuanCommandFactory::_handle( assuan_context_t ctx, char * line, const char * commandName ) {
1388 #else
1389 gpg_error_t AssuanCommandFactory::_handle( assuan_context_t ctx, char * line, const char * commandName ) {
1390 #endif
1391  assert( assuan_get_pointer( ctx ) );
1392  AssuanServerConnection::Private & conn = *static_cast<AssuanServerConnection::Private*>( assuan_get_pointer( ctx ) );
1393 
1394  try {
1395 
1396  const std::vector< shared_ptr<AssuanCommandFactory> >::const_iterator it
1397  = std::lower_bound( conn.factories.begin(), conn.factories.end(), commandName, _detail::ByName<std::less>() );
1398  kleo_assert( it != conn.factories.end() );
1399  kleo_assert( *it );
1400  kleo_assert( qstricmp( (*it)->name(), commandName ) == 0 );
1401 
1402  const shared_ptr<AssuanCommand> cmd = (*it)->create();
1403  kleo_assert( cmd );
1404 
1405  cmd->d->ctx = conn.ctx;
1406  cmd->d->options = conn.options;
1407  cmd->d->inputs.swap( conn.inputs ); kleo_assert( conn.inputs.empty() );
1408  cmd->d->messages.swap( conn.messages ); kleo_assert( conn.messages.empty() );
1409  cmd->d->outputs.swap( conn.outputs ); kleo_assert( conn.outputs.empty() );
1410  cmd->d->files.swap( conn.files ); kleo_assert( conn.files.empty() );
1411  cmd->d->senders.swap( conn.senders ); kleo_assert( conn.senders.empty() );
1412  cmd->d->recipients.swap( conn.recipients ); kleo_assert( conn.recipients.empty() );
1413  cmd->d->informativeRecipients = conn.informativeRecipients;
1414  cmd->d->informativeSenders = conn.informativeSenders;
1415  cmd->d->bias = conn.bias;
1416  cmd->d->sessionTitle = conn.sessionTitle;
1417  cmd->d->sessionId = conn.sessionId;
1418 
1419  const std::map<std::string,std::string> cmdline_options = parse_commandline( line );
1420  for ( std::map<std::string,std::string>::const_iterator it = cmdline_options.begin(), end = cmdline_options.end() ; it != end ; ++it )
1421  cmd->d->options[it->first] = QString::fromUtf8( it->second.c_str() );
1422 
1423  bool nohup = false;
1424  if ( cmd->d->options.count( "nohup" ) ) {
1425  if ( !cmd->d->options["nohup"].toString().isEmpty() )
1426  return assuan_process_done_msg( conn.ctx.get(), gpg_error( GPG_ERR_ASS_PARAMETER ), "--nohup takes no argument" );
1427  nohup = true;
1428  cmd->d->options.erase( "nohup" );
1429  }
1430 
1431  conn.currentCommand = cmd;
1432  conn.currentCommandIsNohup = nohup;
1433 
1434  QTimer::singleShot( 0, &conn, SLOT(startCommandBottomHalf()) );
1435 
1436  return 0;
1437 
1438  } catch ( const Exception & e ) {
1439  return assuan_process_done_msg( conn.ctx.get(), e.error_code(), e.message() );
1440  } catch ( const std::exception & e ) {
1441  return assuan_process_done_msg( conn.ctx.get(), gpg_error( GPG_ERR_UNEXPECTED ), e.what() );
1442  } catch ( ... ) {
1443  return assuan_process_done_msg( conn.ctx.get(), gpg_error( GPG_ERR_UNEXPECTED ), i18n("Caught unknown exception") );
1444  }
1445 }
1446 
1447 int AssuanServerConnection::Private::startCommandBottomHalf() {
1448 
1449  commandWaitingForCryptoCommandsEnabled = currentCommand && !cryptoCommandsEnabled;
1450 
1451  if ( !cryptoCommandsEnabled )
1452  return 0;
1453 
1454  const shared_ptr<AssuanCommand> cmd = currentCommand;
1455  if ( !cmd )
1456  return 0;
1457 
1458  currentCommand.reset();
1459 
1460  const bool nohup = currentCommandIsNohup;
1461  currentCommandIsNohup = false;
1462 
1463  try {
1464 
1465  if ( const int err = cmd->start() ) {
1466  if ( cmd->isDone() )
1467  return err;
1468  else
1469  return assuan_process_done( ctx.get(), err );
1470  }
1471 
1472  if ( cmd->isDone() )
1473  return 0;
1474 
1475  if ( nohup ) {
1476  cmd->setNohup( true );
1477  nohupedCommands.push_back( cmd );
1478  return assuan_process_done_msg( ctx.get(), 0, "Command put in the background to continue executing after connection end." );
1479  } else {
1480  currentCommand = cmd;
1481  return 0;
1482  }
1483 
1484  } catch ( const Exception & e ) {
1485  return assuan_process_done_msg( ctx.get(), e.error_code(), e.message() );
1486  } catch ( const std::exception & e ) {
1487  return assuan_process_done_msg( ctx.get(), gpg_error( GPG_ERR_UNEXPECTED ), e.what() );
1488  } catch ( ... ) {
1489  return assuan_process_done_msg( ctx.get(), gpg_error( GPG_ERR_UNEXPECTED ), i18n("Caught unknown exception") );
1490  }
1491 
1492 }
1493 
1494 //
1495 //
1496 // AssuanCommand convenience methods
1497 //
1498 //
1499 
1508 AssuanCommand::Mode AssuanCommand::checkMode() const {
1509  if ( !hasOption( "mode" ) )
1510  throw Exception( makeError( GPG_ERR_MISSING_VALUE ), i18n( "Required --mode option missing" ) );
1511 
1512  const QString modeString = option("mode").toString().toLower();
1513  if ( modeString == QLatin1String( "filemanager" ) )
1514  return FileManager;
1515  if ( modeString == QLatin1String( "email" ) )
1516  return EMail;
1517  throw Exception( makeError( GPG_ERR_INV_ARG ), i18n( "invalid mode: \"%1\"", modeString ) );
1518 }
1519 
1533 GpgME::Protocol AssuanCommand::checkProtocol( Mode mode, int options ) const {
1534  if ( !hasOption("protocol") )
1535  if ( d->bias != GpgME::UnknownProtocol )
1536  return d->bias;
1537  else if ( mode == AssuanCommand::EMail && ( options & AllowProtocolMissing ) == 0 )
1538  throw Exception( makeError( GPG_ERR_MISSING_VALUE ), i18n( "Required --protocol option missing" ) );
1539  else
1540  return GpgME::UnknownProtocol;
1541  else
1542  if ( mode == AssuanCommand::FileManager )
1543  throw Exception( makeError( GPG_ERR_INV_FLAG ), i18n("--protocol is not allowed here") );
1544 
1545  const QString protocolString = option("protocol").toString().toLower();
1546  if ( protocolString == QLatin1String( "openpgp" ) )
1547  return GpgME::OpenPGP;
1548  if ( protocolString == QLatin1String( "cms" ) )
1549  return GpgME::CMS;
1550  throw Exception( makeError( GPG_ERR_INV_ARG ), i18n( "invalid protocol \"%1\"", protocolString ) );
1551 }
1552 
1553 void AssuanCommand::doApplyWindowID( QWidget * widget ) const {
1554  if ( !widget || !hasOption( "window-id" ) )
1555  return;
1556  apply_window_id( widget, option("window-id").toString() );
1557 }
1558 
1559 WId AssuanCommand::parentWId() const {
1560  return wid_from_string( option("window-id").toString() );
1561 }
1562 
1563 #include "assuanserverconnection.moc"
1564 #include "moc_assuanserverconnection.cpp"
Kleo::AssuanCommand::isNohup
bool isNohup() const
Definition: assuanserverconnection.cpp:1354
FOR_READING
static const int FOR_READING
Definition: assuanserverconnection.cpp:121
signal
const char * signal
Definition: keytreeview.cpp:359
MAX_ACTIVE_FDS
static const unsigned int MAX_ACTIVE_FDS
Definition: assuanserverconnection.cpp:122
AssuanContextBase
shared_ptr< remove_pointer< assuan_context_t >::type > AssuanContextBase
Definition: assuanserverconnection.cpp:132
Kleo::AssuanCommand::~AssuanCommand
virtual ~AssuanCommand()
Definition: assuanserverconnection.cpp:1110
output.h
apply_window_id
static void apply_window_id(QWidget *widget, const QString &winIdStr)
Definition: assuanserverconnection.cpp:225
Kleo::AssuanCommand::FileManager
Definition: assuancommand.h:247
Kleo::AssuanServerConnection::~AssuanServerConnection
~AssuanServerConnection()
Definition: assuanserverconnection.cpp:1001
input.h
Kleo::AssuanCommand::hasMemento
bool hasMemento(const QByteArray &tag) const
Definition: assuanserverconnection.cpp:1183
Kleo::Output::finalize
virtual void finalize()=0
kleo-assuan.h
parse_commandline
static std::map< std::string, std::string > parse_commandline(const char *line)
Definition: assuanserverconnection.cpp:177
getpid.h
email
static std::string email(const UserID &uid)
Definition: keycache.cpp:593
assuan_process_done_msg
static gpg_error_t assuan_process_done_msg(assuan_context_t ctx, gpg_error_t err, const char *err_msg)
Definition: assuanserverconnection.cpp:148
QWidget
Kleo::AssuanCommand::sendStatusEncoded
void sendStatusEncoded(const char *keyword, const std::string &text)
Definition: assuanserverconnection.cpp:1256
Kleo::AssuanCommand::setNohup
void setNohup(bool on)
Definition: assuanserverconnection.cpp:1350
Kleo::AssuanCommand::EMail
Definition: assuancommand.h:247
Kleo::AssuanCommand::memento
boost::shared_ptr< Memento > memento(const QByteArray &tag) const
Definition: assuanserverconnection.cpp:1190
upcase_option
static std::map< std::string, std::string > upcase_option(const char *option, std::map< std::string, std::string > options)
Definition: assuanserverconnection.cpp:160
Kleo::AssuanCommand::removeMemento
void removeMemento(const QByteArray &tag)
Definition: assuanserverconnection.cpp:1222
option
const char * option
Definition: kleopatraapplication.cpp:91
INIT_SOCKET_FLAGS
static const unsigned int INIT_SOCKET_FLAGS
Definition: assuanserverconnection.cpp:119
Kleo::AssuanCommand::fileNames
QStringList fileNames() const
Definition: assuanserverconnection.cpp:1244
Kleo::AssuanCommand::senders
const std::vector< KMime::Types::Mailbox > & senders() const
Definition: assuanserverconnection.cpp:1382
Kleo::AssuanCommand::sendData
void sendData(const QByteArray &data, bool moreToCome=false)
Definition: assuanserverconnection.cpp:1263
wid_from_string
static WId wid_from_string(const QString &winIdStr, bool *ok=0)
Definition: assuanserverconnection.cpp:215
Kleo::AssuanCommand::Mode
Mode
Definition: assuancommand.h:247
Kleo::SessionDataHandler::instance
static boost::shared_ptr< SessionDataHandler > instance()
Definition: sessiondata.cpp:59
kleo_assert.h
Kleo::AssuanCommand::checkMode
Mode checkMode() const
Definition: assuanserverconnection.cpp:1508
boost::shared_ptr
Definition: encryptemailcontroller.h:51
Kleo::AssuanCommand::inquire
int inquire(const char *keyword, QObject *receiver, const char *slot, unsigned int maxSize=0)
Definition: assuanserverconnection.cpp:1273
Kleo::AssuanCommand::outputs
const std::vector< boost::shared_ptr< Output > > & outputs() const
Definition: assuanserverconnection.cpp:1240
d
#define d
Definition: adduseridcommand.cpp:90
sessiondata.h
ASSUAN_INVALID_FD
#define ASSUAN_INVALID_FD
Definition: kleo-assuan.h:73
Kleo::Class::OpenPGP
Definition: classify.h:49
hex.h
Kleo::AssuanCommand::option
QVariant option(const char *opt) const
Definition: assuanserverconnection.cpp:1153
Kleo::AssuanCommand::sessionTitle
QString sessionTitle() const
Definition: assuanserverconnection.cpp:1362
Kleo::Output
Definition: output.h:71
kdtools::pimpl_ptr::get
T * get()
Definition: pimpl_ptr.h:39
Kleo::Class::CMS
Definition: classify.h:48
Kleo::AssuanServerConnection::enableCryptoCommands
void enableCryptoCommands(bool enable=true)
Definition: assuanserverconnection.cpp:1003
Kleo::AssuanCommand::AssuanCommand
AssuanCommand()
Definition: assuanserverconnection.cpp:1104
gnupg-helper.h
assuancommand.h
Kleo::AssuanCommand::sendStatus
void sendStatus(const char *keyword, const QString &text)
Definition: assuanserverconnection.cpp:1252
Kleo::AssuanCommand::recipients
const std::vector< KMime::Types::Mailbox > & recipients() const
Definition: assuanserverconnection.cpp:1378
Kleo::AssuanCommandFactory::_handle
static int _handle(assuan_context_s *, char *, const char *)
Definition: assuanserverconnection.cpp:1387
Kleo::Output::setBinaryOpt
virtual void setBinaryOpt(bool value)=0
Kleo::AssuanCommand::makeError
static int makeError(int code)
Definition: assuanserverconnection.cpp:1145
Kleo::makeGnuPGError
int makeGnuPGError(int code)
Definition: gnupg-helper.cpp:69
Kleo::AssuanCommand::numFiles
unsigned int numFiles() const
Definition: assuanserverconnection.cpp:1248
kleo_assert
#define kleo_assert(cond)
Definition: kleo_assert.h:84
assuanserverconnection.h
Kleo::AssuanCommand::parentWId
WId parentWId() const
Definition: assuanserverconnection.cpp:1559
string
const char * string
Definition: verifychecksumscontroller.cpp:511
Kleo::AssuanCommand::inputs
const std::vector< boost::shared_ptr< Input > > & inputs() const
Definition: assuanserverconnection.cpp:1232
Kleo::AssuanCommand::start
int start()
Definition: assuanserverconnection.cpp:1114
Kleo::AssuanCommand
Base class for GnuPG UI Server commands.
Definition: assuancommand.h:213
Kleo::AssuanCommand::done
void done(const GpgME::Error &err=GpgME::Error())
Definition: assuanserverconnection.cpp:1307
Kleo::Input::finalize
void finalize()
Definition: input.cpp:373
Kleo::AssuanCommand::hasOption
bool hasOption(const char *opt) const
Definition: assuanserverconnection.cpp:1149
Kleo::AssuanCommand::canceled
void canceled()
Definition: assuanserverconnection.cpp:1139
q
#define q
Definition: adduseridcommand.cpp:91
Kleo::_detail::ByName
Definition: detail_p.h:52
detail_p.h
Kleo::AssuanCommand::registerMemento
QByteArray registerMemento(const boost::shared_ptr< Memento > &mem)
Definition: assuanserverconnection.cpp:1205
assuan_fd_t
int assuan_fd_t
Definition: kleo-assuan.h:72
Kleo::AssuanCommand::checkProtocol
GpgME::Protocol checkProtocol(Mode mode, int options=0) const
Definition: assuanserverconnection.cpp:1533
Kleo::AssuanCommand::sessionId
unsigned int sessionId() const
Definition: assuanserverconnection.cpp:1366
keycache.h
Kleo::AssuanCommand::informativeSenders
bool informativeSenders() const
Definition: assuanserverconnection.cpp:1370
log.h
Kleo::AssuanCommand::informativeRecipients
bool informativeRecipients() const
Definition: assuanserverconnection.cpp:1374
Kleo::AssuanServerConnection
Definition: assuanserverconnection.h:51
Kleo::AssuanCommand::options
const std::map< std::string, QVariant > & options() const
Definition: assuanserverconnection.cpp:1161
Kleo::mygetpid
static qint64 mygetpid()
Definition: getpid.h:49
slot
const char * slot
Definition: keytreeview.cpp:360
Kleo::hexdecode
std::string hexdecode(const char *s)
Definition: hex.cpp:117
Kleo::AssuanCommand::messages
const std::vector< boost::shared_ptr< Input > > & messages() const
Definition: assuanserverconnection.cpp:1236
Kleo::AssuanCommand::isDone
bool isDone() const
Definition: assuanserverconnection.cpp:1358
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