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

libkleo

  • sources
  • kde-4.14
  • kdepim
  • libkleo
  • backends
  • qgpgme
qgpgmecryptoconfig.cpp
Go to the documentation of this file.
1 /*
2  qgpgmecryptoconfig.cpp
3 
4  This file is part of libkleopatra, the KDE keymanagement library
5  Copyright (c) 2004 Klarälvdalens Datakonsult AB
6 
7  Libkleopatra is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of the
10  License, or (at your option) any later version.
11 
12  Libkleopatra 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 "qgpgmecryptoconfig.h"
34 
35 #include <QList>
36 #include <QByteArray>
37 #include <kdebug.h>
38 #include <kprocess.h>
39 #include <errno.h>
40 #include <kmessagebox.h>
41 #include <klocale.h>
42 #include <kshell.h>
43 #include <KStandardDirs>
44 
45 #include <gpgme++/engineinfo.h>
46 #include <gpgme++/global.h>
47 
48 #include <cassert>
49 #include <ktemporaryfile.h>
50 #include <QFile>
51 #include <cstdlib>
52 #include <QTextCodec>
53 #include <iterator>
54 
55 // Just for the Q_ASSERT in the dtor. Not thread-safe, but who would
56 // have 2 threads talking to gpgconf anyway? :)
57 static bool s_duringClear = false;
58 
59 static const int GPGCONF_FLAG_GROUP = 1;
60 static const int GPGCONF_FLAG_OPTIONAL = 2;
61 static const int GPGCONF_FLAG_LIST = 4;
62 static const int GPGCONF_FLAG_RUNTIME = 8;
63 static const int GPGCONF_FLAG_DEFAULT = 16; // fixed default value available
64 static const int GPGCONF_FLAG_DEFAULT_DESC = 32; // runtime default value available
65 static const int GPGCONF_FLAG_NOARG_DESC = 64; // option with optional arg; special meaning if no arg set
66 static const int GPGCONF_FLAG_NO_CHANGE = 128; // readonly
67 // Change size of mFlags bitfield if adding new values here
68 
69 QString QGpgMECryptoConfig::gpgConfPath()
70 {
71  const GpgME::EngineInfo info = GpgME::engineInfo( GpgME::GpgConfEngine );
72  return info.fileName() ? QFile::decodeName( info.fileName() ) : KStandardDirs::findExe( QLatin1String("gpgconf") );
73 }
74 
75 QGpgMECryptoConfig::QGpgMECryptoConfig()
76  : mParsed( false )
77 {
78 }
79 
80 QGpgMECryptoConfig::~QGpgMECryptoConfig()
81 {
82  clear();
83 }
84 
85 void QGpgMECryptoConfig::runGpgConf( bool showErrors )
86 {
87  // Run gpgconf --list-components to make the list of components
88  KProcess process;
89 
90  process << gpgConfPath();
91  process << QLatin1String("--list-components");
92 
93 
94  connect( &process, SIGNAL(readyReadStandardOutput()),
95  this, SLOT(slotCollectStdOut()) );
96 
97  // run the process:
98  int rc = 0;
99  process.setOutputChannelMode( KProcess::OnlyStdoutChannel );
100  process.start();
101  if ( !process.waitForFinished() )
102  rc = -2;
103  else if ( process.exitStatus() == QProcess::NormalExit )
104  rc = process.exitCode();
105  else
106  rc = -1;
107 
108  // handle errors, if any (and if requested)
109  if ( showErrors && rc != 0 ) {
110  QString reason;
111  if ( rc == -1 )
112  reason = i18n( "program terminated unexpectedly" );
113  else if ( rc == -2 )
114  reason = i18n( "program not found or cannot be started" );
115  else
116  reason = QString::fromLocal8Bit( strerror(rc) ); // XXX errno as an exit code?
117  QString wmsg = i18n("<qt>Failed to execute gpgconf:<p>%1</p></qt>", reason);
118  kWarning(5150) << wmsg; // to see it from test_cryptoconfig.cpp
119  KMessageBox::error(0, wmsg);
120  }
121  mParsed = true;
122 }
123 
124 void QGpgMECryptoConfig::slotCollectStdOut()
125 {
126  assert( qobject_cast<KProcess*>( QObject::sender() ) );
127  KProcess * const proc = static_cast<KProcess*>( QObject::sender() );
128  while( proc->canReadLine() ) {
129  QString line = QString::fromUtf8( proc->readLine() );
130  if ( line.endsWith( QLatin1Char('\n') ) )
131  line.chop( 1 );
132  if ( line.endsWith( QLatin1Char('\r') ) )
133  line.chop( 1 );
134  //kDebug(5150) <<"GOT LINE:" << line;
135  // Format: NAME:DESCRIPTION
136  const QStringList lst = line.split( QLatin1Char(':') );
137  if ( lst.count() >= 2 ) {
138  const std::pair<QString,QGpgMECryptoConfigComponent*> pair( lst[0], new QGpgMECryptoConfigComponent( this, lst[0], lst[1] ) );
139  mComponentsNaturalOrder.push_back( pair );
140  mComponentsByName[pair.first] = pair.second;
141  } else {
142  kWarning(5150) <<"Parse error on gpgconf --list-components output:" << line;
143  }
144  }
145 }
146 
147 namespace {
148  struct Select1St {
149  template <typename U, typename V>
150  const U & operator()( const std::pair<U,V> & p ) const { return p.first; }
151  template <typename U, typename V>
152  const U & operator()( const QPair<U,V> & p ) const { return p.first; }
153  };
154 }
155 
156 QStringList QGpgMECryptoConfig::componentList() const
157 {
158  if ( !mParsed )
159  const_cast<QGpgMECryptoConfig*>( this )->runGpgConf( true );
160  QStringList result;
161  std::transform( mComponentsNaturalOrder.begin(), mComponentsNaturalOrder.end(),
162  std::back_inserter( result ), Select1St() );
163  return result;
164 }
165 
166 Kleo::CryptoConfigComponent* QGpgMECryptoConfig::component( const QString& name ) const
167 {
168  if ( !mParsed )
169  const_cast<QGpgMECryptoConfig*>( this )->runGpgConf( false );
170  return mComponentsByName.value( name );
171 }
172 
173 void QGpgMECryptoConfig::sync( bool runtime )
174 {
175  Q_FOREACH (QGpgMECryptoConfigComponent *it, mComponentsByName)
176  it->sync(runtime);
177 }
178 
179 void QGpgMECryptoConfig::clear()
180 {
181  s_duringClear = true;
182  mComponentsNaturalOrder.clear();
183  qDeleteAll(mComponentsByName);
184  mComponentsByName.clear();
185  s_duringClear = false;
186  mParsed = false; // next call to componentList/component will need to run gpgconf again
187 }
188 
190 
191 QGpgMECryptoConfigComponent::QGpgMECryptoConfigComponent( QGpgMECryptoConfig*, const QString& name, const QString& description )
192  : mName( name ), mDescription( description )
193 {
194  runGpgConf();
195 }
196 
197 QGpgMECryptoConfigComponent::~QGpgMECryptoConfigComponent()
198 {
199  mGroupsNaturalOrder.clear();
200  qDeleteAll(mGroupsByName);
201  mGroupsByName.clear();
202 }
203 
204 void QGpgMECryptoConfigComponent::runGpgConf()
205 {
206  const QString gpgconf = QGpgMECryptoConfig::gpgConfPath();
207  if ( gpgconf.isEmpty() ) {
208  kWarning(5150) << "Can't get path to gpgconf executable...";
209  return;
210  }
211 
212  // Run gpgconf --list-options <component>, and create all groups and entries for that component
213  KProcess proc;
214  proc << gpgconf;
215  proc << QLatin1String("--list-options");
216  proc << mName;
217 
218  //kDebug(5150) <<"Running gpgconf --list-options" << mName;
219 
220  connect( &proc, SIGNAL(readyReadStandardOutput()),
221  this, SLOT(slotCollectStdOut()) );
222  mCurrentGroup = 0;
223 
224  // run the process:
225  int rc = 0;
226  proc.setOutputChannelMode( KProcess::OnlyStdoutChannel );
227  proc.start();
228  if ( !proc.waitForFinished() )
229  rc = -2;
230  else if ( proc.exitStatus() == QProcess::NormalExit )
231  rc = proc.exitCode();
232  else
233  rc = -1;
234 
235  if( rc != 0 ) // can happen when using the wrong version of gpg...
236  kWarning(5150) <<"Running 'gpgconf --list-options" << mName <<"' failed." << strerror( rc ) <<", but try that command to see the real output";
237  else {
238  if ( mCurrentGroup && !mCurrentGroup->mEntriesNaturalOrder.empty() ) { // only add non-empty groups
239  mGroupsByName.insert( mCurrentGroupName, mCurrentGroup );
240  mGroupsNaturalOrder.push_back( std::make_pair( mCurrentGroupName, mCurrentGroup ) );
241  }
242  }
243 }
244 
245 void QGpgMECryptoConfigComponent::slotCollectStdOut()
246 {
247  assert( qobject_cast<KProcess*>( QObject::sender() ) );
248  KProcess * const proc = static_cast<KProcess*>( QObject::sender() );
249  while( proc->canReadLine() ) {
250  QString line = QString::fromUtf8( proc->readLine() );
251  if ( line.endsWith( QLatin1Char('\n') ) )
252  line.chop( 1 );
253  if ( line.endsWith( QLatin1Char('\r') ) )
254  line.chop( 1 );
255  //kDebug(5150) <<"GOT LINE:" << line;
256  // Format: NAME:FLAGS:LEVEL:DESCRIPTION:TYPE:ALT-TYPE:ARGNAME:DEFAULT:ARGDEF:VALUE
257  const QStringList lst = line.split( QLatin1Char(':') );
258  if ( lst.count() >= 10 ) {
259  const int flags = lst[1].toInt();
260  const int level = lst[2].toInt();
261  if ( level > 2 ) // invisible or internal -> skip it;
262  continue;
263  if ( flags & GPGCONF_FLAG_GROUP ) {
264  if ( mCurrentGroup && !mCurrentGroup->mEntriesNaturalOrder.empty() ) { // only add non-empty groups
265  mGroupsByName.insert( mCurrentGroupName, mCurrentGroup );
266  mGroupsNaturalOrder.push_back( std::make_pair( mCurrentGroupName, mCurrentGroup ) );
267  }
268  //else
269  // kDebug(5150) <<"Discarding empty group" << mCurrentGroupName;
270  mCurrentGroup = new QGpgMECryptoConfigGroup( this, lst[0], lst[3], level );
271  mCurrentGroupName = lst[0];
272  } else {
273  // normal entry
274  if ( !mCurrentGroup ) { // first toplevel entry -> create toplevel group
275  mCurrentGroup = new QGpgMECryptoConfigGroup( this, QLatin1String("<nogroup>"), QString(), 0 );
276  mCurrentGroupName = QLatin1String("<nogroup>");
277  }
278  const QString & name = lst[0];
279  QGpgMECryptoConfigEntry * value = new QGpgMECryptoConfigEntry( mCurrentGroup, lst );
280  mCurrentGroup->mEntriesByName.insert( name, value );
281  mCurrentGroup->mEntriesNaturalOrder.push_back( std::make_pair( name, value ) );
282  }
283  } else {
284  // This happens on lines like
285  // dirmngr[31465]: error opening `/home/dfaure/.gnupg/dirmngr_ldapservers.conf': No such file or directory
286  // so let's not bother the user with it.
287  //kWarning(5150) <<"Parse error on gpgconf --list-options output:" << line;
288  }
289  }
290 }
291 
292 QStringList QGpgMECryptoConfigComponent::groupList() const
293 {
294  QStringList result;
295  std::transform( mGroupsNaturalOrder.begin(), mGroupsNaturalOrder.end(),
296  std::back_inserter( result ), Select1St() );
297  return result;
298 }
299 
300 Kleo::CryptoConfigGroup* QGpgMECryptoConfigComponent::group(const QString& name ) const
301 {
302  return mGroupsByName.value( name );
303 }
304 
305 void QGpgMECryptoConfigComponent::sync( bool runtime )
306 {
307  KTemporaryFile tmpFile;
308  tmpFile.open();
309 
310  QList<QGpgMECryptoConfigEntry *> dirtyEntries;
311 
312  // Collect all dirty entries
313  const QList<QString> keylist = mGroupsByName.uniqueKeys();
314  Q_FOREACH (const QString & key, keylist) {
315  const QHash<QString,QGpgMECryptoConfigEntry*> entry = mGroupsByName[key]->mEntriesByName;
316  const QList<QString> keylistentry = entry.uniqueKeys();
317  Q_FOREACH (const QString & keyentry, keylistentry) {
318  if(entry[keyentry]->isDirty())
319  {
320  // OK, we can set it.currentKey() to it.current()->outputString()
321  QString line = keyentry;
322  if ( entry[keyentry]->isSet() ) { // set option
323  line += QLatin1String(":0:");
324  line += entry[keyentry]->outputString();
325  } else { // unset option
326  line += QLatin1String(":16:");
327  }
328 #ifdef Q_OS_WIN
329  line += QLatin1Char('\r');
330 #endif
331  line += QLatin1Char('\n');
332  const QByteArray line8bit = line.toUtf8(); // encode with utf8, and K3ProcIO uses utf8 when reading.
333  tmpFile.write( line8bit );
334  dirtyEntries.append( entry[keyentry] );
335 
336  }
337  }
338  }
339 
340  tmpFile.flush();
341  if ( dirtyEntries.isEmpty() )
342  return;
343 
344  // Call gpgconf --change-options <component>
345  const QString gpgconf = QGpgMECryptoConfig::gpgConfPath();
346  QString commandLine = gpgconf.isEmpty()
347  ? QString::fromLatin1( "gpgconf" )
348  : KShell::quoteArg( gpgconf ) ;
349  if ( runtime )
350  commandLine += QLatin1String(" --runtime");
351  commandLine += QLatin1String(" --change-options ");
352  commandLine += KShell::quoteArg( mName );
353  commandLine += QLatin1String(" < ");
354  commandLine += KShell::quoteArg( tmpFile.fileName() );
355 
356  //kDebug(5150) << commandLine;
357  //system( QCString( "cat " ) + tmpFile.name().toLatin1() ); // DEBUG
358 
359  KProcess proc;
360  proc.setShellCommand( commandLine );
361 
362  // run the process:
363  int rc = proc.execute();
364 
365  if ( rc == -2 )
366  {
367  QString wmsg = i18n( "Could not start gpgconf.\nCheck that gpgconf is in the PATH and that it can be started." );
368  kWarning(5150) << wmsg;
369  KMessageBox::error(0, wmsg);
370  }
371  else if( rc != 0 ) // Happens due to bugs in gpgconf (e.g. issues 104/115)
372  {
373  QString wmsg = i18n( "Error from gpgconf while saving configuration: %1", QString::fromLocal8Bit( strerror( rc ) ) );
374  kWarning(5150) <<":" << strerror( rc );
375  KMessageBox::error(0, wmsg);
376  }
377  else
378  {
379  QList<QGpgMECryptoConfigEntry *>::const_iterator it = dirtyEntries.constBegin();
380  for( ; it != dirtyEntries.constEnd(); ++it ) {
381  (*it)->setDirty( false );
382  }
383  }
384 }
385 
387 
388 QGpgMECryptoConfigGroup::QGpgMECryptoConfigGroup( QGpgMECryptoConfigComponent * comp, const QString & name, const QString& description, int level )
389  :
390  mComponent( comp ),
391  mName( name ),
392  mDescription( description ),
393  mLevel( static_cast<Kleo::CryptoConfigEntry::Level>( level ) )
394 {
395 }
396 
397 QGpgMECryptoConfigGroup::~QGpgMECryptoConfigGroup()
398 {
399  mEntriesNaturalOrder.clear();
400  qDeleteAll(mEntriesByName);
401  mEntriesByName.clear();
402 }
403 
404 QStringList QGpgMECryptoConfigGroup::entryList() const
405 {
406  QStringList result;
407  std::transform( mEntriesNaturalOrder.begin(), mEntriesNaturalOrder.end(),
408  std::back_inserter( result ), Select1St() );
409  return result;
410 }
411 
412 Kleo::CryptoConfigEntry* QGpgMECryptoConfigGroup::entry( const QString& name ) const
413 {
414  return mEntriesByName.value( name );
415 }
416 
418 
419 static QString gpgconf_unescape( const QString& str )
420 {
421  // Looks like it's the same rules as KUrl.
422  return KUrl::fromPercentEncoding( str.toLatin1() );
423 }
424 
425 static QString gpgconf_escape( const QString& str )
426 {
427  // Escape special chars (including ':' and '%')
428  QString enc = QLatin1String(KUrl::toPercentEncoding( str )); // and convert to utf8 first (to get %12%34 for one special char)
429  // Also encode commas, for lists.
430  enc.replace( QLatin1Char(','), QLatin1String("%2c") );
431  return enc;
432 }
433 
434 static QString urlpart_encode( const QString& str )
435 {
436  QString enc( str );
437  enc.replace( QLatin1Char('%'), QLatin1String("%25") ); // first!
438  enc.replace( QLatin1Char(':'), QLatin1String("%3a") );
439  //kDebug(5150) <<" urlpart_encode:" << str <<" ->" << enc;
440  return enc;
441 }
442 
443 static QString urlpart_decode( const QString& str )
444 {
445  return KUrl::fromPercentEncoding( str.toLatin1() );
446 }
447 
448 // gpgconf arg type number -> CryptoConfigEntry arg type enum mapping
449 static Kleo::CryptoConfigEntry::ArgType knownArgType( int argType, bool& ok ) {
450  ok = true;
451  switch( argType ) {
452  case 0: // none
453  return Kleo::CryptoConfigEntry::ArgType_None;
454  case 1: // string
455  return Kleo::CryptoConfigEntry::ArgType_String;
456  case 2: // int32
457  return Kleo::CryptoConfigEntry::ArgType_Int;
458  case 3: // uint32
459  return Kleo::CryptoConfigEntry::ArgType_UInt;
460  case 32: // pathname
461  return Kleo::CryptoConfigEntry::ArgType_Path;
462  case 33: // ldap server
463  return Kleo::CryptoConfigEntry::ArgType_LDAPURL;
464  default:
465  ok = false;
466  return Kleo::CryptoConfigEntry::ArgType_None;
467  }
468 }
469 
470 QGpgMECryptoConfigEntry::QGpgMECryptoConfigEntry( QGpgMECryptoConfigGroup * group, const QStringList& parsedLine )
471  : mGroup( group )
472 {
473  // Format: NAME:FLAGS:LEVEL:DESCRIPTION:TYPE:ALT-TYPE:ARGNAME:DEFAULT:ARGDEF:VALUE
474  assert( parsedLine.count() >= 10 ); // called checked for it already
475  QStringList::const_iterator it = parsedLine.constBegin();
476  mName = *it++;
477  mFlags = (*it++).toInt();
478  mLevel = (*it++).toInt();
479  mDescription = *it++;
480  bool ok;
481  // we keep the real (int) arg type, since it influences the parsing (e.g. for ldap urls)
482  mRealArgType = (*it++).toInt();
483  mArgType = knownArgType( mRealArgType, ok );
484  if ( !ok && !(*it).isEmpty() ) {
485  // use ALT-TYPE
486  mRealArgType = (*it).toInt();
487  mArgType = knownArgType( mRealArgType, ok );
488  }
489  if ( !ok )
490  kWarning(5150) <<"Unsupported datatype:" << parsedLine[4] <<" :" << *it <<" for" << parsedLine[0];
491  ++it; // done with alt-type
492  ++it; // skip argname (not useful in GUIs)
493 
494  mSet = false;
495  QString value;
496  if ( mFlags & GPGCONF_FLAG_DEFAULT ) {
497  value = *it; // get default value
498  mDefaultValue = stringToValue( value, true );
499  }
500  ++it; // done with DEFAULT
501  ++it; // ### skip ARGDEF for now. It's only for options with an "optional arg"
502  //kDebug(5150) <<"Entry" << parsedLine[0] <<" val=" << *it;
503 
504  if ( !(*it).isEmpty() ) { // a real value was set
505  mSet = true;
506  value = *it;
507  mValue = stringToValue( value, true );
508  }
509  else {
510  mValue = mDefaultValue;
511  }
512 
513  mDirty = false;
514 }
515 
516 QVariant QGpgMECryptoConfigEntry::stringToValue( const QString& str, bool unescape ) const
517 {
518  const bool isString = isStringType();
519 
520  if ( isList() ) {
521  if ( argType() == ArgType_None ) {
522  bool ok = true;
523  const QVariant v = str.isEmpty() ? 0U : str.toUInt( &ok ) ;
524  if ( !ok )
525  kWarning(5150) << "list-of-none should have an unsigned int as value:" << str;
526  return v;
527  }
528  QList<QVariant> lst;
529  QStringList items = str.split( QLatin1Char(','), QString::SkipEmptyParts );
530  for( QStringList::const_iterator valit = items.constBegin(); valit != items.constEnd(); ++valit ) {
531  QString val = *valit;
532  if ( isString ) {
533  if ( val.isEmpty() ) {
534  lst << QVariant( QString() );
535  continue;
536  }
537  else if ( unescape ) {
538  if( val[0] != QLatin1Char('"') ) // see README.gpgconf
539  kWarning(5150) <<"String value should start with '\"' :" << val;
540  val = val.mid( 1 );
541  }
542  }
543  lst << QVariant( unescape ? gpgconf_unescape( val ) : val );
544  }
545  return lst;
546  } else { // not a list
547  QString val( str );
548  if ( isString ) {
549  if ( val.isEmpty() )
550  return QVariant( QString() ); // not set [ok with lists too?]
551  else if ( unescape ) {
552  if( val[0] != QLatin1Char('"') ) // see README.gpgconf
553  kWarning(5150) <<"String value should start with '\"' :" << val;
554  val = val.mid( 1 );
555  }
556  }
557  return QVariant( unescape ? gpgconf_unescape( val ) : val );
558  }
559 }
560 
561 QGpgMECryptoConfigEntry::~QGpgMECryptoConfigEntry()
562 {
563 #ifndef NDEBUG
564  if ( !s_duringClear && mDirty )
565  kWarning(5150) <<"Deleting a QGpgMECryptoConfigEntry that was modified (" << mDescription <<")"
566  << "You forgot to call sync() (to commit) or clear() (to discard)";
567 #endif
568 }
569 
570 bool QGpgMECryptoConfigEntry::isOptional() const
571 {
572  return mFlags & GPGCONF_FLAG_OPTIONAL;
573 }
574 
575 bool QGpgMECryptoConfigEntry::isReadOnly() const
576 {
577  return mFlags & GPGCONF_FLAG_NO_CHANGE;
578 }
579 
580 bool QGpgMECryptoConfigEntry::isList() const
581 {
582  return mFlags & GPGCONF_FLAG_LIST;
583 }
584 
585 bool QGpgMECryptoConfigEntry::isRuntime() const
586 {
587  return mFlags & GPGCONF_FLAG_RUNTIME;
588 }
589 
590 bool QGpgMECryptoConfigEntry::isSet() const
591 {
592  return mSet;
593 }
594 
595 bool QGpgMECryptoConfigEntry::boolValue() const
596 {
597  Q_ASSERT( mArgType == ArgType_None );
598  Q_ASSERT( !isList() );
599  return mValue.toBool();
600 }
601 
602 QString QGpgMECryptoConfigEntry::stringValue() const
603 {
604  return toString( false );
605 }
606 
607 int QGpgMECryptoConfigEntry::intValue() const
608 {
609  Q_ASSERT( mArgType == ArgType_Int );
610  Q_ASSERT( !isList() );
611  return mValue.toInt();
612 }
613 
614 unsigned int QGpgMECryptoConfigEntry::uintValue() const
615 {
616  Q_ASSERT( mArgType == ArgType_UInt );
617  Q_ASSERT( !isList() );
618  return mValue.toUInt();
619 }
620 
621 static KUrl parseURL( int mRealArgType, const QString& str )
622 {
623  if ( mRealArgType == 33 ) { // LDAP server
624  // The format is HOSTNAME:PORT:USERNAME:PASSWORD:BASE_DN
625  QStringList items = str.split( QLatin1Char(':') );
626  if ( items.count() == 5 ) {
627  QStringList::const_iterator it = items.constBegin();
628  KUrl url;
629  url.setProtocol( QLatin1String("ldap") );
630  url.setHost( urlpart_decode( *it++ ) );
631 
632  bool ok;
633  const int port = (*it++).toInt( &ok );
634  if ( ok )
635  url.setPort( port );
636  else if ( !it->isEmpty() )
637  kWarning(5150) <<"parseURL: malformed LDAP server port, ignoring: \"" << *it << "\"";
638 
639  url.setPath( QLatin1String("/") ); // workaround KUrl parsing bug
640  url.setUserName( urlpart_decode( *it++ ) );
641  url.setPassword( urlpart_decode( *it++ ) );
642  url.setQuery( urlpart_decode( *it ) );
643  return url;
644  } else
645  kWarning(5150) <<"parseURL: malformed LDAP server:" << str;
646  }
647  // other URLs : assume wellformed URL syntax.
648  return KUrl( str );
649 }
650 
651 // The opposite of parseURL
652 static QString splitURL( int mRealArgType, const KUrl& url )
653 {
654  if ( mRealArgType == 33 ) { // LDAP server
655  // The format is HOSTNAME:PORT:USERNAME:PASSWORD:BASE_DN
656  Q_ASSERT( url.protocol() == QLatin1String("ldap") );
657  return urlpart_encode( url.host() ) + QLatin1Char(':') +
658  ( url.port() != -1 ? QString::number( url.port() ) : QString() ) + QLatin1Char(':') + // -1 is used for default ports, omit
659  urlpart_encode( url.user() ) + QLatin1Char(':') +
660  urlpart_encode( url.pass() ) + QLatin1Char(':') +
661  // KUrl automatically encoded the query (e.g. for spaces inside it),
662  // so decode it before writing it out to gpgconf (issue119)
663  urlpart_encode( KUrl::fromPercentEncoding( url.query().mid(1).toLatin1() ) );
664  }
665  return url.path();
666 }
667 
668 KUrl QGpgMECryptoConfigEntry::urlValue() const
669 {
670  Q_ASSERT( mArgType == ArgType_Path || mArgType == ArgType_URL || mArgType == ArgType_LDAPURL );
671  Q_ASSERT( !isList() );
672  QString str = mValue.toString();
673  if ( mArgType == ArgType_Path )
674  {
675  KUrl url;
676  url.setPath( str );
677  return url;
678  }
679  return parseURL( mRealArgType, str );
680 }
681 
682 unsigned int QGpgMECryptoConfigEntry::numberOfTimesSet() const
683 {
684  Q_ASSERT( mArgType == ArgType_None );
685  Q_ASSERT( isList() );
686  return mValue.toUInt();
687 }
688 
689 QStringList QGpgMECryptoConfigEntry::stringValueList() const
690 {
691  Q_ASSERT( isStringType() );
692  Q_ASSERT( isList() );
693  return mValue.toStringList();
694 }
695 
696 std::vector<int> QGpgMECryptoConfigEntry::intValueList() const
697 {
698  Q_ASSERT( mArgType == ArgType_Int );
699  Q_ASSERT( isList() );
700  std::vector<int> ret;
701  QList<QVariant> lst = mValue.toList();
702  ret.reserve( lst.size() );
703  for( QList<QVariant>::const_iterator it = lst.constBegin(); it != lst.constEnd(); ++it ) {
704  ret.push_back( (*it).toInt() );
705  }
706  return ret;
707 }
708 
709 std::vector<unsigned int> QGpgMECryptoConfigEntry::uintValueList() const
710 {
711  Q_ASSERT( mArgType == ArgType_UInt );
712  Q_ASSERT( isList() );
713  std::vector<unsigned int> ret;
714  QList<QVariant> lst = mValue.toList();
715  ret.reserve( lst.size() );
716  for( QList<QVariant>::const_iterator it = lst.constBegin(); it != lst.constEnd(); ++it ) {
717  ret.push_back( (*it).toUInt() );
718  }
719  return ret;
720 }
721 
722 KUrl::List QGpgMECryptoConfigEntry::urlValueList() const
723 {
724  Q_ASSERT( mArgType == ArgType_Path || mArgType == ArgType_URL || mArgType == ArgType_LDAPURL );
725  Q_ASSERT( isList() );
726  QStringList lst = mValue.toStringList();
727 
728  KUrl::List ret;
729  for( QStringList::const_iterator it = lst.constBegin(); it != lst.constEnd(); ++it ) {
730  if ( mArgType == ArgType_Path ) {
731  KUrl url;
732  url.setPath( *it );
733  ret << url;
734  } else {
735  ret << parseURL( mRealArgType, *it );
736  }
737  }
738  return ret;
739 }
740 
741 void QGpgMECryptoConfigEntry::resetToDefault()
742 {
743  mSet = false;
744  mDirty = true;
745  if ( mFlags & GPGCONF_FLAG_DEFAULT )
746  mValue = mDefaultValue;
747  else if ( mArgType == ArgType_None ) {
748  if ( isList() )
749  mValue = 0U;
750  else
751  mValue = false;
752  }
753 }
754 
755 void QGpgMECryptoConfigEntry::setBoolValue( bool b )
756 {
757  Q_ASSERT( mArgType == ArgType_None );
758  Q_ASSERT( !isList() );
759  // A "no arg" option is either set or not set.
760  // Being set means mSet==true + mValue==true, being unset means resetToDefault(), i.e. both false
761  mValue = b;
762  mSet = b;
763  mDirty = true;
764 }
765 
766 void QGpgMECryptoConfigEntry::setStringValue( const QString& str )
767 {
768  mValue = stringToValue( str, false );
769  // When setting a string to empty (and there's no default), we need to act like resetToDefault
770  // Otherwise we try e.g. "ocsp-responder:0:" and gpgconf answers:
771  // "gpgconf: argument required for option ocsp-responder"
772  if ( str.isEmpty() && !isOptional() )
773  mSet = false;
774  else
775  mSet = true;
776  mDirty = true;
777 }
778 
779 void QGpgMECryptoConfigEntry::setIntValue( int i )
780 {
781  Q_ASSERT( mArgType == ArgType_Int );
782  Q_ASSERT( !isList() );
783  mValue = i;
784  mSet = true;
785  mDirty = true;
786 }
787 
788 void QGpgMECryptoConfigEntry::setUIntValue( unsigned int i )
789 {
790  mValue = i;
791  mSet = true;
792  mDirty = true;
793 }
794 
795 void QGpgMECryptoConfigEntry::setURLValue( const KUrl& url )
796 {
797  QString str = splitURL( mRealArgType, url );
798  if ( str.isEmpty() && !isOptional() )
799  mSet = false;
800  else
801  mSet = true;
802  mValue = str;
803  mDirty = true;
804 }
805 
806 void QGpgMECryptoConfigEntry::setNumberOfTimesSet( unsigned int i )
807 {
808  Q_ASSERT( mArgType == ArgType_None );
809  Q_ASSERT( isList() );
810  mValue = i;
811  mSet = i > 0;
812  mDirty = true;
813 }
814 
815 void QGpgMECryptoConfigEntry::setStringValueList( const QStringList& lst )
816 {
817  mValue = lst;
818  if ( lst.isEmpty() && !isOptional() )
819  mSet = false;
820  else
821  mSet = true;
822  mDirty = true;
823 }
824 
825 void QGpgMECryptoConfigEntry::setIntValueList( const std::vector<int>& lst )
826 {
827  QList<QVariant> ret;
828  for( std::vector<int>::const_iterator it = lst.begin(); it != lst.end(); ++it ) {
829  ret << QVariant( *it );
830  }
831  mValue = ret;
832  if ( ret.isEmpty() && !isOptional() )
833  mSet = false;
834  else
835  mSet = true;
836  mDirty = true;
837 }
838 
839 void QGpgMECryptoConfigEntry::setUIntValueList( const std::vector<unsigned int>& lst )
840 {
841  QList<QVariant> ret;
842  for( std::vector<unsigned int>::const_iterator it = lst.begin(); it != lst.end(); ++it ) {
843  ret << QVariant( *it );
844  }
845  if ( ret.isEmpty() && !isOptional() )
846  mSet = false;
847  else
848  mSet = true;
849  mValue = ret;
850  mDirty = true;
851 }
852 
853 void QGpgMECryptoConfigEntry::setURLValueList( const KUrl::List& urls )
854 {
855  QStringList lst;
856  for( KUrl::List::const_iterator it = urls.constBegin(); it != urls.constEnd(); ++it ) {
857  lst << splitURL( mRealArgType, *it );
858  }
859  mValue = lst;
860  if ( lst.isEmpty() && !isOptional() )
861  mSet = false;
862  else
863  mSet = true;
864  mDirty = true;
865 }
866 
867 QString QGpgMECryptoConfigEntry::toString( bool escape ) const
868 {
869  // Basically the opposite of stringToValue
870  if ( isStringType() ) {
871  if ( mValue.isNull() )
872  return QString();
873  else if ( isList() ) { // string list
874  QStringList lst = mValue.toStringList();
875  if ( escape ) {
876  for( QStringList::iterator it = lst.begin(); it != lst.end(); ++it ) {
877  if ( !(*it).isNull() )
878  *it = gpgconf_escape( *it ).prepend( QLatin1String("\"") );
879  }
880  }
881  const QString res = lst.join( QLatin1String(",") );
882  //kDebug(5150) <<"toString:" << res;
883  return res;
884  } else { // normal string
885  QString res = mValue.toString();
886  if ( escape )
887  res = gpgconf_escape( res ).prepend( QLatin1String("\"") );
888  return res;
889  }
890  }
891  if ( !isList() ) // non-list non-string
892  {
893  if ( mArgType == ArgType_None ) {
894  return mValue.toBool() ? QString::fromLatin1( "1" ) : QString();
895  } else { // some int
896  Q_ASSERT( mArgType == ArgType_Int || mArgType == ArgType_UInt );
897  return mValue.toString(); // int to string conversion
898  }
899  }
900 
901  // Lists (of other types than strings)
902  if ( mArgType == ArgType_None )
903  return QString::number( numberOfTimesSet() );
904  QStringList ret;
905  QList<QVariant> lst = mValue.toList();
906  for( QList<QVariant>::const_iterator it = lst.constBegin(); it != lst.constEnd(); ++it ) {
907  ret << (*it).toString(); // QVariant does the conversion
908  }
909  return ret.join( QLatin1String(",") );
910 }
911 
912 QString QGpgMECryptoConfigEntry::outputString() const
913 {
914  Q_ASSERT( mSet );
915  return toString( true );
916 }
917 
918 bool QGpgMECryptoConfigEntry::isStringType() const
919 {
920  return ( mArgType == Kleo::CryptoConfigEntry::ArgType_String
921  || mArgType == Kleo::CryptoConfigEntry::ArgType_Path
922  || mArgType == Kleo::CryptoConfigEntry::ArgType_URL
923  || mArgType == Kleo::CryptoConfigEntry::ArgType_LDAPURL );
924 }
925 
926 void QGpgMECryptoConfigEntry::setDirty( bool b )
927 {
928  mDirty = b;
929 }
930 
QGpgMECryptoConfigEntry::numberOfTimesSet
unsigned int numberOfTimesSet() const
Definition: qgpgmecryptoconfig.cpp:682
QGpgMECryptoConfigEntry::stringToValue
QVariant stringToValue(const QString &value, bool unescape) const
Definition: qgpgmecryptoconfig.cpp:516
ArgType_LDAPURL
Definition: cryptoconfig.h:87
QGpgMECryptoConfigEntry::stringValueList
QStringList stringValueList() const
Definition: qgpgmecryptoconfig.cpp:689
KProcess
QHash::insert
iterator insert(const Key &key, const T &value)
name
const char * name
Definition: kconfigbasedkeyfilter.cpp:126
QGpgMECryptoConfigComponent
For docu, see kleo/cryptoconfig.h.
Definition: qgpgmecryptoconfig.h:88
QGpgMECryptoConfigGroup::~QGpgMECryptoConfigGroup
~QGpgMECryptoConfigGroup()
Definition: qgpgmecryptoconfig.cpp:397
QByteArray
QGpgMECryptoConfigEntry::toString
QString toString(bool escape) const
Definition: qgpgmecryptoconfig.cpp:867
GPGCONF_FLAG_GROUP
static const int GPGCONF_FLAG_GROUP
Definition: qgpgmecryptoconfig.cpp:59
QGpgMECryptoConfigEntry::setDirty
void setDirty(bool b)
Definition: qgpgmecryptoconfig.cpp:926
QVariant::toList
QList< QVariant > toList() const
QObject::sender
QObject * sender() const
QString::split
QStringList split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
GPGCONF_FLAG_DEFAULT_DESC
static const int GPGCONF_FLAG_DEFAULT_DESC
Definition: qgpgmecryptoconfig.cpp:64
QString::prepend
QString & prepend(QChar ch)
s_duringClear
static bool s_duringClear
Definition: qgpgmecryptoconfig.cpp:57
QGpgMECryptoConfigEntry::isReadOnly
bool isReadOnly() const
Definition: qgpgmecryptoconfig.cpp:575
ArgType_String
Definition: cryptoconfig.h:82
GPGCONF_FLAG_NO_CHANGE
static const int GPGCONF_FLAG_NO_CHANGE
Definition: qgpgmecryptoconfig.cpp:66
GPGCONF_FLAG_RUNTIME
static const int GPGCONF_FLAG_RUNTIME
Definition: qgpgmecryptoconfig.cpp:62
QGpgMECryptoConfigEntry::setStringValueList
void setStringValueList(const QStringList &)
Definition: qgpgmecryptoconfig.cpp:815
parseURL
static KUrl parseURL(int mRealArgType, const QString &str)
Definition: qgpgmecryptoconfig.cpp:621
QStringList::join
QString join(const QString &separator) const
urlpart_decode
static QString urlpart_decode(const QString &str)
Definition: qgpgmecryptoconfig.cpp:443
QString::chop
void chop(int n)
gpgconf_unescape
static QString gpgconf_unescape(const QString &str)
Definition: qgpgmecryptoconfig.cpp:419
urlpart_encode
static QString urlpart_encode(const QString &str)
Definition: qgpgmecryptoconfig.cpp:434
QList::const_iterator
QList::size
int size() const
ArgType_Path
Definition: cryptoconfig.h:85
QGpgMECryptoConfigEntry::intValue
int intValue() const
Definition: qgpgmecryptoconfig.cpp:607
QGpgMECryptoConfigComponent::~QGpgMECryptoConfigComponent
~QGpgMECryptoConfigComponent()
Definition: qgpgmecryptoconfig.cpp:197
QGpgMECryptoConfigEntry::boolValue
bool boolValue() const
Definition: qgpgmecryptoconfig.cpp:595
QString::number
QString number(int n, int base)
QList::count
int count(const T &value) const
QString::fromLocal8Bit
QString fromLocal8Bit(const char *str, int size)
QGpgMECryptoConfigEntry::setUIntValueList
void setUIntValueList(const std::vector< unsigned int > &)
Definition: qgpgmecryptoconfig.cpp:839
QGpgMECryptoConfigEntry::argType
ArgType argType() const
Definition: qgpgmecryptoconfig.h:154
QList::append
void append(const T &value)
QString::fromUtf8
QString fromUtf8(const char *str, int size)
QVariant::toUInt
uint toUInt(bool *ok) const
QVariant::toInt
int toInt(bool *ok) const
QVariant::isNull
bool isNull() const
QHash::uniqueKeys
QList< Key > uniqueKeys() const
QHash< QString, QGpgMECryptoConfigEntry * >
QGpgMECryptoConfigEntry::isStringType
bool isStringType() const
Definition: qgpgmecryptoconfig.cpp:918
splitURL
static QString splitURL(int mRealArgType, const KUrl &url)
Definition: qgpgmecryptoconfig.cpp:652
GPGCONF_FLAG_NOARG_DESC
static const int GPGCONF_FLAG_NOARG_DESC
Definition: qgpgmecryptoconfig.cpp:65
QList::isEmpty
bool isEmpty() const
GPGCONF_FLAG_DEFAULT
static const int GPGCONF_FLAG_DEFAULT
Definition: qgpgmecryptoconfig.cpp:63
QGpgMECryptoConfigEntry::setURLValue
void setURLValue(const KUrl &)
Definition: qgpgmecryptoconfig.cpp:795
QString::isEmpty
bool isEmpty() const
kdtools::transform
O transform(const I &i, P p)
Definition: stl_util.h:376
QGpgMECryptoConfig::sync
virtual void sync(bool runtime)
Definition: qgpgmecryptoconfig.cpp:173
QGpgMECryptoConfigEntry::setNumberOfTimesSet
void setNumberOfTimesSet(unsigned int)
Definition: qgpgmecryptoconfig.cpp:806
Level
Level
Definition: cryptoconfig.h:60
QString::endsWith
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const
QGpgMECryptoConfigEntry::~QGpgMECryptoConfigEntry
~QGpgMECryptoConfigEntry()
Definition: qgpgmecryptoconfig.cpp:561
QGpgMECryptoConfigEntry::urlValueList
KUrl::List urlValueList() const
Definition: qgpgmecryptoconfig.cpp:722
QString
QList
QList::iterator
QStringList
QPair
gpgconf_escape
static QString gpgconf_escape(const QString &str)
Definition: qgpgmecryptoconfig.cpp:425
QHash::clear
void clear()
QList::end
iterator end()
QHash::value
const T value(const Key &key) const
GPGCONF_FLAG_LIST
static const int GPGCONF_FLAG_LIST
Definition: qgpgmecryptoconfig.cpp:61
QGpgMECryptoConfig
CryptoConfig implementation around the gpgconf command-line tool For method docu, see kleo/cryptoconf...
Definition: qgpgmecryptoconfig.h:54
QGpgMECryptoConfigEntry::isSet
bool isSet() const
Definition: qgpgmecryptoconfig.cpp:590
QLatin1Char
QGpgMECryptoConfigEntry::setIntValueList
void setIntValueList(const std::vector< int > &)
Definition: qgpgmecryptoconfig.cpp:825
QGpgMECryptoConfigEntry::stringValue
QString stringValue() const
Definition: qgpgmecryptoconfig.cpp:602
ArgType
ArgType
Type of the argument.
Definition: cryptoconfig.h:81
QGpgMECryptoConfig::QGpgMECryptoConfig
QGpgMECryptoConfig()
Constructor.
Definition: qgpgmecryptoconfig.cpp:75
QString::replace
QString & replace(int position, int n, QChar after)
QGpgMECryptoConfigComponent::sync
void sync(bool runtime)
Definition: qgpgmecryptoconfig.cpp:305
QGpgMECryptoConfig::~QGpgMECryptoConfig
virtual ~QGpgMECryptoConfig()
Definition: qgpgmecryptoconfig.cpp:80
QGpgMECryptoConfig::gpgConfPath
static QString gpgConfPath()
Definition: qgpgmecryptoconfig.cpp:69
QGpgMECryptoConfigEntry::uintValue
unsigned int uintValue() const
Definition: qgpgmecryptoconfig.cpp:614
QString::toLatin1
QByteArray toLatin1() const
QGpgMECryptoConfigGroup
Definition: qgpgmecryptoconfig.h:117
QString::mid
QString mid(int position, int n) const
QGpgMECryptoConfigEntry::setStringValue
void setStringValue(const QString &)
Definition: qgpgmecryptoconfig.cpp:766
QVariant::toStringList
QStringList toStringList() const
QGpgMECryptoConfig::component
virtual Kleo::CryptoConfigComponent * component(const QString &name) const
Definition: qgpgmecryptoconfig.cpp:166
QGpgMECryptoConfigEntry::setUIntValue
void setUIntValue(unsigned int)
Definition: qgpgmecryptoconfig.cpp:788
QLatin1String
QGpgMECryptoConfigEntry::isRuntime
bool isRuntime() const
Definition: qgpgmecryptoconfig.cpp:585
QGpgMECryptoConfigGroup::QGpgMECryptoConfigGroup
QGpgMECryptoConfigGroup(QGpgMECryptoConfigComponent *comp, const QString &name, const QString &description, int level)
Definition: qgpgmecryptoconfig.cpp:388
QGpgMECryptoConfigComponent::QGpgMECryptoConfigComponent
QGpgMECryptoConfigComponent(QGpgMECryptoConfig *, const QString &name, const QString &description)
Definition: qgpgmecryptoconfig.cpp:191
ArgType_UInt
Definition: cryptoconfig.h:84
QGpgMECryptoConfigEntry
Definition: qgpgmecryptoconfig.h:141
ArgType_URL
Definition: cryptoconfig.h:86
QGpgMECryptoConfigEntry::QGpgMECryptoConfigEntry
QGpgMECryptoConfigEntry(QGpgMECryptoConfigGroup *group, const QStringList &parsedLine)
Definition: qgpgmecryptoconfig.cpp:470
GPGCONF_FLAG_OPTIONAL
static const int GPGCONF_FLAG_OPTIONAL
Definition: qgpgmecryptoconfig.cpp:60
QGpgMECryptoConfigComponent::group
Kleo::CryptoConfigGroup * group(const QString &name) const
Definition: qgpgmecryptoconfig.cpp:300
QGpgMECryptoConfigEntry::urlValue
KUrl urlValue() const
Definition: qgpgmecryptoconfig.cpp:668
QVariant::toBool
bool toBool() const
QGpgMECryptoConfigEntry::uintValueList
std::vector< unsigned int > uintValueList() const
Definition: qgpgmecryptoconfig.cpp:709
QGpgMECryptoConfigGroup::entryList
QStringList entryList() const
Definition: qgpgmecryptoconfig.cpp:404
knownArgType
static Kleo::CryptoConfigEntry::ArgType knownArgType(int argType, bool &ok)
Definition: qgpgmecryptoconfig.cpp:449
QString::fromLatin1
QString fromLatin1(const char *str, int size)
QGpgMECryptoConfigEntry::isList
bool isList() const
Definition: qgpgmecryptoconfig.cpp:580
ArgType_None
Definition: cryptoconfig.h:81
QGpgMECryptoConfigGroup::entry
Kleo::CryptoConfigEntry * entry(const QString &name) const
Definition: qgpgmecryptoconfig.cpp:412
ArgType_Int
Definition: cryptoconfig.h:83
QGpgMECryptoConfig::clear
virtual void clear()
Definition: qgpgmecryptoconfig.cpp:179
QList::constEnd
const_iterator constEnd() const
QList::constBegin
const_iterator constBegin() const
QGpgMECryptoConfig::componentList
virtual QStringList componentList() const
Definition: qgpgmecryptoconfig.cpp:156
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QGpgMECryptoConfigEntry::setBoolValue
void setBoolValue(bool)
Definition: qgpgmecryptoconfig.cpp:755
QGpgMECryptoConfigEntry::intValueList
std::vector< int > intValueList() const
Definition: qgpgmecryptoconfig.cpp:696
QGpgMECryptoConfigEntry::setURLValueList
void setURLValueList(const KUrl::List &)
Definition: qgpgmecryptoconfig.cpp:853
QVariant::toString
QString toString() const
QGpgMECryptoConfigComponent::groupList
QStringList groupList() const
Definition: qgpgmecryptoconfig.cpp:292
QGpgMECryptoConfigEntry::isOptional
bool isOptional() const
Definition: qgpgmecryptoconfig.cpp:570
QList::begin
iterator begin()
QGpgMECryptoConfigEntry::setIntValue
void setIntValue(int)
Definition: qgpgmecryptoconfig.cpp:779
QGpgMECryptoConfigEntry::outputString
QString outputString() const
Definition: qgpgmecryptoconfig.cpp:912
QFile::decodeName
QString decodeName(const QByteArray &localFileName)
QGpgMECryptoConfigComponent::name
QString name() const
Definition: qgpgmecryptoconfig.h:95
QGpgMECryptoConfigEntry::resetToDefault
void resetToDefault()
Definition: qgpgmecryptoconfig.cpp:741
qgpgmecryptoconfig.h
QString::toUInt
uint toUInt(bool *ok, int base) const
QVariant
QString::toUtf8
QByteArray toUtf8() const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:33:38 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

libkleo

Skip menu "libkleo"
  • 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