• 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
  • kleo
kconfigbasedkeyfilter.cpp
Go to the documentation of this file.
1 /*
2  kconfigbasedkeyfilter.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 
34 #include "kconfigbasedkeyfilter.h"
35 
36 #include <kconfigbase.h>
37 #include <kconfiggroup.h>
38 #include <klocale.h>
39 
40 #ifndef Q_MOC_RUN
41 #include <boost/mem_fn.hpp>
42 #endif
43 #include <algorithm>
44 
45 using namespace Kleo;
46 using namespace GpgME;
47 using namespace boost;
48 
49 //
50 //
51 // FontDescription - intuitive font property resolving
52 // (QFont::resolve doesn't work for us)
53 //
54 //
55 struct KeyFilter::FontDescription::Private {
56  bool bold, italic, strikeOut, fullFont;
57  QFont font;
58 };
59 
60 KeyFilter::FontDescription::FontDescription()
61  : d( new Private )
62 {
63  d->bold = d->italic = d->strikeOut = d->fullFont = false;
64 }
65 
66 KeyFilter::FontDescription::FontDescription( const FontDescription & other )
67  : d( new Private( *other.d ) )
68 {
69 
70 }
71 
72 KeyFilter::FontDescription::~FontDescription() {
73  delete d;
74 }
75 
76 KeyFilter::FontDescription KeyFilter::FontDescription::create( bool b, bool i, bool s ) {
77  FontDescription fd;
78  fd.d->bold = b;
79  fd.d->italic = i;
80  fd.d->strikeOut = s;
81  return fd;
82 }
83 
84 KeyFilter::FontDescription KeyFilter::FontDescription::create( const QFont & f, bool b, bool i, bool s ) {
85  FontDescription fd;
86  fd.d->fullFont = true;
87  fd.d->font = f;
88  fd.d->bold = b;
89  fd.d->italic = i;
90  fd.d->strikeOut = s;
91  return fd;
92 }
93 
94 QFont KeyFilter::FontDescription::font( const QFont & base ) const {
95  QFont font;
96  if ( d->fullFont ) {
97  font = d->font;
98  font.setPointSize( base.pointSize() );
99  } else {
100  font = base;
101  }
102  if ( d->bold )
103  font.setBold( true );
104  if ( d->italic )
105  font.setItalic( true );
106  if ( d->strikeOut )
107  font.setStrikeOut( true );
108  return font;
109 }
110 
111 KeyFilter::FontDescription KeyFilter::FontDescription::resolve( const FontDescription & other ) const {
112  FontDescription fd;
113  fd.d->fullFont = this->d->fullFont || other.d->fullFont ;
114  if ( fd.d->fullFont )
115  fd.d->font = this->d->fullFont ? this->d->font : other.d->font ;
116  fd.d->bold = this->d->bold || other.d->bold ;
117  fd.d->italic = this->d->italic || other.d->italic ;
118  fd.d->strikeOut = this->d->strikeOut || other.d->strikeOut ;
119  return fd;
120 }
121 
122 
123 
124 
125 static const struct {
126  const char * name;
127  Key::OwnerTrust trust;
128  UserID::Validity validity;
129 } ownerTrustAndValidityMap[] = {
130  { "unknown", Key::Unknown, UserID::Unknown },
131  { "undefined", Key::Undefined, UserID::Undefined },
132  { "never", Key::Never, UserID::Never },
133  { "marginal", Key::Marginal, UserID::Marginal },
134  { "full", Key::Full, UserID::Full },
135  { "ultimate", Key::Ultimate, UserID::Ultimate },
136 };
137 
138 static Key::OwnerTrust map2OwnerTrust( const QString & s ) {
139  for ( unsigned int i = 0 ; i < sizeof ownerTrustAndValidityMap / sizeof *ownerTrustAndValidityMap ; ++i )
140  if ( s.toLower() == QLatin1String(ownerTrustAndValidityMap[i].name) )
141  return ownerTrustAndValidityMap[i].trust;
142  return ownerTrustAndValidityMap[0].trust;
143 }
144 
145 static UserID::Validity map2Validity( const QString & s ) {
146  for ( unsigned int i = 0 ; i < sizeof ownerTrustAndValidityMap / sizeof *ownerTrustAndValidityMap ; ++i )
147  if ( s.toLower() == QLatin1String(ownerTrustAndValidityMap[i].name) )
148  return ownerTrustAndValidityMap[i].validity;
149  return ownerTrustAndValidityMap[0].validity;
150 }
151 
152 
153 KeyFilterImplBase::KeyFilterImplBase()
154  : KeyFilter(),
155  mMatchContexts( AnyMatchContext ),
156  mSpecificity( 0 ),
157  mItalic( false ),
158  mBold( false ),
159  mStrikeOut( false ),
160  mUseFullFont( false ),
161  mRevoked( DoesNotMatter ),
162  mExpired( DoesNotMatter ),
163  mDisabled( DoesNotMatter ),
164  mRoot( DoesNotMatter ),
165  mCanEncrypt( DoesNotMatter ),
166  mCanSign( DoesNotMatter ),
167  mCanCertify( DoesNotMatter ),
168  mCanAuthenticate( DoesNotMatter ),
169  mQualified( DoesNotMatter ),
170  mCardKey( DoesNotMatter ),
171  mHasSecret( DoesNotMatter ),
172  mIsOpenPGP( DoesNotMatter ),
173  mWasValidated( DoesNotMatter ),
174  mOwnerTrust( LevelDoesNotMatter ),
175  mOwnerTrustReferenceLevel( Key::Unknown ),
176  mValidity( LevelDoesNotMatter ),
177  mValidityReferenceLevel( UserID::Unknown )
178 {
179 
180 }
181 
182 KeyFilterImplBase::~KeyFilterImplBase() {}
183 
184 KConfigBasedKeyFilter::KConfigBasedKeyFilter( const KConfigGroup & config )
185  : KeyFilterImplBase()
186 {
187  mFgColor = config.readEntry<QColor>( "foreground-color", QColor() );
188  mBgColor = config.readEntry<QColor>( "background-color", QColor() );
189  mName = config.readEntry( "Name", config.name() );
190  mIcon = config.readEntry( "icon" );
191  mId = config.readEntry( "id", config.name() );
192  if ( config.hasKey( "font" ) ) {
193  mUseFullFont = true;
194  mFont = config.readEntry( "font" );
195  } else {
196  mUseFullFont = false;
197  mItalic = config.readEntry( "font-italic", false );
198  mBold = config.readEntry( "font-bold", false );
199  }
200  mStrikeOut = config.readEntry( "font-strikeout", false );
201 #ifdef SET
202 #undef SET
203 #endif
204 #define SET(member,key) \
205  if ( config.hasKey( key ) ) { \
206  member = config.readEntry( key, false ) ? Set : NotSet ; \
207  ++mSpecificity; \
208  }
209  SET( mRevoked, "is-revoked" );
210  SET( mExpired, "is-expired" );
211  SET( mDisabled, "is-disabled" );
212  SET( mRoot, "is-root-certificate" );
213  SET( mCanEncrypt, "can-encrypt" );
214  SET( mCanSign, "can-sign" );
215  SET( mCanCertify, "can-certify" );
216  SET( mCanAuthenticate, "can-authenticate" );
217  SET( mQualified, "is-qualified" );
218  SET( mCardKey, "is-cardkey" );
219  SET( mHasSecret, "has-secret-key" );
220  SET( mIsOpenPGP, "is-openpgp-key" );
221  SET( mWasValidated, "was-validated" );
222 #undef SET
223  static const struct {
224  const char * prefix;
225  LevelState state;
226  } prefixMap[] = {
227  { "is-", Is },
228  { "is-not-", IsNot },
229  { "is-at-least-", IsAtLeast },
230  { "is-at-most-", IsAtMost },
231  };
232  for ( unsigned int i = 0 ; i < sizeof prefixMap / sizeof *prefixMap ; ++i ) {
233  const QString key = QLatin1String( prefixMap[i].prefix ) + QLatin1String("ownertrust");
234  if ( config.hasKey( key ) ) {
235  mOwnerTrust = prefixMap[i].state;
236  mOwnerTrustReferenceLevel = map2OwnerTrust( config.readEntry( key, QString() ) );
237  ++mSpecificity;
238  break;
239  }
240  }
241  for ( unsigned int i = 0 ; i < sizeof prefixMap / sizeof *prefixMap ; ++i ) {
242  const QString key = QLatin1String( prefixMap[i].prefix ) + QLatin1String("validity");
243  if ( config.hasKey( key ) ) {
244  mValidity = prefixMap[i].state;
245  mValidityReferenceLevel = map2Validity( config.readEntry( key, QString() ) );
246  ++mSpecificity;
247  break;
248  }
249  }
250  static const struct {
251  const char * key;
252  MatchContext context;
253  } matchMap[] = {
254  { "any", AnyMatchContext },
255  { "appearance", Appearance },
256  { "filtering", Filtering },
257  };
258  const QStringList contexts = config.readEntry( "match-contexts", "any" ).toLower().split( QRegExp( QLatin1String("[^a-zA-Z0-9_-!]+") ), QString::SkipEmptyParts );
259  mMatchContexts = NoMatchContext;
260  Q_FOREACH( const QString & ctx, contexts ) {
261  bool found = false;
262  for ( unsigned int i = 0 ; i < sizeof matchMap / sizeof *matchMap ; ++i )
263  if ( ctx == QLatin1String(matchMap[i].key) ) {
264  mMatchContexts |= matchMap[i].context;
265  found = true;
266  break;
267  } else if ( ctx.startsWith( QLatin1Char('!') ) && ctx.mid( 1 ) == QLatin1String(matchMap[i].key) ) {
268  mMatchContexts &= ~matchMap[i].context;
269  found = true;
270  break;
271  }
272  if ( !found )
273  qWarning( "KConfigBasedKeyFilter: found unknown match context '%s' in group '%s'",
274  qPrintable( ctx ), qPrintable( config.name() ) );
275  }
276  if ( mMatchContexts == NoMatchContext ) {
277  qWarning( "KConfigBasedKeyFilter: match context in group '%s' evaluates to NoMatchContext, "
278  "replaced by AnyMatchContext", qPrintable( config.name() ) );
279  mMatchContexts = AnyMatchContext;
280  }
281 }
282 
283 static bool is_card_key( const Key & key ) {
284  const std::vector<Subkey> sks = key.subkeys();
285  return std::find_if( sks.begin(), sks.end(),
286  mem_fn( &Subkey::isCardKey ) ) != sks.end() ;
287 }
288 
289 bool KeyFilterImplBase::matches( const Key & key, MatchContexts contexts ) const {
290  if ( !( mMatchContexts & contexts ) )
291  return false;
292 #ifdef MATCH
293 #undef MATCH
294 #endif
295 #define MATCH(member,method) \
296  if ( member != DoesNotMatter && key.method() != bool( member == Set ) ) \
297  return false
298 #define IS_MATCH(what) MATCH( m##what, is##what )
299 #define CAN_MATCH(what) MATCH( mCan##what, can##what )
300  IS_MATCH( Revoked );
301  IS_MATCH( Expired );
302  IS_MATCH( Disabled );
303  IS_MATCH( Root );
304  CAN_MATCH( Encrypt );
305  CAN_MATCH( Sign );
306  CAN_MATCH( Certify );
307  CAN_MATCH( Authenticate );
308  IS_MATCH( Qualified );
309  if ( mCardKey != DoesNotMatter )
310  if ( ( mCardKey == Set && !is_card_key( key ) ) ||
311  ( mCardKey == NotSet && is_card_key( key ) ) )
312  return false;
313  MATCH( mHasSecret, hasSecret );
314 #undef MATCH
315  if ( mIsOpenPGP != DoesNotMatter &&
316  bool( key.protocol() == GpgME::OpenPGP ) != bool( mIsOpenPGP == Set ) )
317  return false;
318  if ( mWasValidated != DoesNotMatter &&
319  bool( key.keyListMode() & GpgME::Validate ) != bool( mWasValidated == Set ) )
320  return false;
321  switch ( mOwnerTrust ) {
322  default:
323  case LevelDoesNotMatter:
324  break;
325  case Is:
326  if ( key.ownerTrust() != mOwnerTrustReferenceLevel )
327  return false;
328  break;
329  case IsNot:
330  if ( key.ownerTrust() == mOwnerTrustReferenceLevel )
331  return false;
332  break;
333  case IsAtLeast:
334  if ( (int)key.ownerTrust() < (int)mOwnerTrustReferenceLevel )
335  return false;
336  break;
337  case IsAtMost:
338  if ( (int)key.ownerTrust() > (int)mOwnerTrustReferenceLevel )
339  return false;
340  break;
341  }
342  const UserID uid = key.userID(0);
343  switch ( mValidity ) {
344  default:
345  case LevelDoesNotMatter:
346  break;
347  case Is:
348  if ( uid.validity() != mValidityReferenceLevel )
349  return false;
350  break;
351  case IsNot:
352  if ( uid.validity() == mValidityReferenceLevel )
353  return false;
354  break;
355  case IsAtLeast:
356  if ( (int)uid.validity() < (int)mValidityReferenceLevel )
357  return false;
358  break;
359  case IsAtMost:
360  if ( (int)uid.validity() > (int)mValidityReferenceLevel )
361  return false;
362  break;
363  }
364  return true;
365 }
366 
367 KeyFilter::FontDescription KeyFilterImplBase::fontDesription() const {
368  if ( mUseFullFont )
369  return FontDescription::create( mFont, mBold, mItalic, mStrikeOut );
370  else
371  return FontDescription::create( mBold, mItalic, mStrikeOut );
372 }
Kleo::KeyFilterImplBase::KeyFilterImplBase
KeyFilterImplBase()
Definition: kconfigbasedkeyfilter.cpp:153
QFont::setPointSize
void setPointSize(int pointSize)
IS_MATCH
#define IS_MATCH(what)
Kleo::KeyFilterImplBase::mId
QString mId
Definition: kconfigbasedkeyfilter.h:70
Kleo::KeyFilterImplBase::mValidityReferenceLevel
GpgME::UserID::Validity mValidityReferenceLevel
Definition: kconfigbasedkeyfilter.h:107
Kleo::KeyFilterImplBase::mUseFullFont
bool mUseFullFont
Definition: kconfigbasedkeyfilter.h:76
QFont
Kleo::KeyFilter::FontDescription::resolve
FontDescription resolve(const FontDescription &other) const
Definition: kconfigbasedkeyfilter.cpp:111
Kleo::KeyFilterImplBase::mRoot
TriState mRoot
Definition: kconfigbasedkeyfilter.h:87
Kleo::KeyFilter::AnyMatchContext
Definition: keyfilter.h:63
Kleo::KeyFilter::FontDescription::create
static FontDescription create(bool bold, bool italic, bool strikeOut)
Definition: kconfigbasedkeyfilter.cpp:76
Kleo::KeyFilterImplBase::mValidity
LevelState mValidity
Definition: kconfigbasedkeyfilter.h:106
CAN_MATCH
#define CAN_MATCH(what)
validity
UserID::Validity validity
Definition: kconfigbasedkeyfilter.cpp:128
Kleo::KeyFilterImplBase::mName
QString mName
Definition: kconfigbasedkeyfilter.h:68
Kleo::KeyFilterImplBase::mCanCertify
TriState mCanCertify
Definition: kconfigbasedkeyfilter.h:90
Kleo::KeyFilter::Appearance
Definition: keyfilter.h:60
Kleo::KeyFilterImplBase::mOwnerTrust
LevelState mOwnerTrust
Definition: kconfigbasedkeyfilter.h:104
Kleo::KeyFilterImplBase::mMatchContexts
MatchContexts mMatchContexts
Definition: kconfigbasedkeyfilter.h:71
Kleo::KeyFilter::name
virtual QString name() const =0
is_card_key
static bool is_card_key(const Key &key)
Definition: kconfigbasedkeyfilter.cpp:283
Kleo::KeyFilterImplBase::mFont
QFont mFont
Definition: kconfigbasedkeyfilter.h:77
Kleo::KeyFilterImplBase
Definition: kconfigbasedkeyfilter.h:49
QFont::setBold
void setBold(bool enable)
QRegExp
map2Validity
static UserID::Validity map2Validity(const QString &s)
Definition: kconfigbasedkeyfilter.cpp:145
Kleo::KeyFilterImplBase::Is
Definition: kconfigbasedkeyfilter.h:99
Kleo::KeyFilterImplBase::mRevoked
TriState mRevoked
Definition: kconfigbasedkeyfilter.h:84
Kleo::KeyFilterImplBase::mCardKey
TriState mCardKey
Definition: kconfigbasedkeyfilter.h:93
Kleo::KeyFilterImplBase::IsAtLeast
Definition: kconfigbasedkeyfilter.h:101
Kleo::KeyFilterImplBase::LevelDoesNotMatter
Definition: kconfigbasedkeyfilter.h:98
Kleo::KeyFilterImplBase::mBgColor
QColor mBgColor
Definition: kconfigbasedkeyfilter.h:67
Kleo::KeyFilterImplBase::mExpired
TriState mExpired
Definition: kconfigbasedkeyfilter.h:85
Kleo::KeyFilterImplBase::mCanEncrypt
TriState mCanEncrypt
Definition: kconfigbasedkeyfilter.h:88
Kleo::KeyFilterImplBase::mBold
bool mBold
Definition: kconfigbasedkeyfilter.h:74
Kleo::KeyFilterImplBase::IsNot
Definition: kconfigbasedkeyfilter.h:100
MATCH
#define MATCH(member, method)
Kleo::KeyFilterImplBase::~KeyFilterImplBase
~KeyFilterImplBase()
Definition: kconfigbasedkeyfilter.cpp:182
Kleo::KeyFilterImplBase::mDisabled
TriState mDisabled
Definition: kconfigbasedkeyfilter.h:86
QString::startsWith
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
Kleo::KeyFilter::Filtering
Definition: keyfilter.h:61
QString
QColor
ownerTrustAndValidityMap
static const struct @3 ownerTrustAndValidityMap[]
Kleo::KeyFilterImplBase::Set
Definition: kconfigbasedkeyfilter.h:81
Kleo::KeyFilterImplBase::mFgColor
QColor mFgColor
Definition: kconfigbasedkeyfilter.h:67
QStringList
Kleo::KeyFilterImplBase::mIsOpenPGP
TriState mIsOpenPGP
Definition: kconfigbasedkeyfilter.h:95
Kleo::KeyFilterImplBase::IsAtMost
Definition: kconfigbasedkeyfilter.h:102
kconfigbasedkeyfilter.h
Kleo::KeyFilterImplBase::mCanSign
TriState mCanSign
Definition: kconfigbasedkeyfilter.h:89
QString::toLower
QString toLower() const
QLatin1Char
QFont::setItalic
void setItalic(bool enable)
Kleo::KeyFilterImplBase::DoesNotMatter
Definition: kconfigbasedkeyfilter.h:80
Kleo::KeyFilter
An abstract base class key filters.
Definition: keyfilter.h:54
Kleo::KeyFilterImplBase::NotSet
Definition: kconfigbasedkeyfilter.h:82
Kleo::KeyFilterImplBase::mQualified
TriState mQualified
Definition: kconfigbasedkeyfilter.h:92
Kleo::KeyFilter::NoMatchContext
Definition: keyfilter.h:59
Kleo::KeyFilterImplBase::mWasValidated
TriState mWasValidated
Definition: kconfigbasedkeyfilter.h:96
SET
#define SET(member, key)
QString::mid
QString mid(int position, int n) const
Kleo::KeyFilterImplBase::mSpecificity
unsigned int mSpecificity
Definition: kconfigbasedkeyfilter.h:72
QLatin1String
Kleo::KeyFilter::FontDescription::~FontDescription
~FontDescription()
Definition: kconfigbasedkeyfilter.cpp:72
Kleo::KeyFilterImplBase::mOwnerTrustReferenceLevel
GpgME::Key::OwnerTrust mOwnerTrustReferenceLevel
Definition: kconfigbasedkeyfilter.h:105
trust
Key::OwnerTrust trust
Definition: kconfigbasedkeyfilter.cpp:127
Kleo::KeyFilterImplBase::mCanAuthenticate
TriState mCanAuthenticate
Definition: kconfigbasedkeyfilter.h:91
Kleo::KeyFilterImplBase::mIcon
QString mIcon
Definition: kconfigbasedkeyfilter.h:69
Kleo::KeyFilterImplBase::fontDesription
FontDescription fontDesription() const
Definition: kconfigbasedkeyfilter.cpp:367
QStringList::split
QStringList split(const QString &sep, const QString &str, bool allowEmptyEntries)
QFont::setStrikeOut
void setStrikeOut(bool enable)
Kleo::KConfigBasedKeyFilter::KConfigBasedKeyFilter
KConfigBasedKeyFilter(const KConfigGroup &group)
Definition: kconfigbasedkeyfilter.cpp:184
Kleo::KeyFilter::FontDescription::font
QFont font(const QFont &base) const
Definition: kconfigbasedkeyfilter.cpp:94
Kleo::KeyFilter::FontDescription
Definition: keyfilter.h:80
Kleo::KeyFilterImplBase::mHasSecret
TriState mHasSecret
Definition: kconfigbasedkeyfilter.h:94
kdtools::find_if
boost::range_iterator< C >::type find_if(C &c, P p)
Definition: stl_util.h:338
map2OwnerTrust
static Key::OwnerTrust map2OwnerTrust(const QString &s)
Definition: kconfigbasedkeyfilter.cpp:138
Kleo::KeyFilter::FontDescription::FontDescription
FontDescription()
Definition: kconfigbasedkeyfilter.cpp:60
Kleo::KeyFilterImplBase::mItalic
bool mItalic
Definition: kconfigbasedkeyfilter.h:73
Kleo::KeyFilterImplBase::mStrikeOut
bool mStrikeOut
Definition: kconfigbasedkeyfilter.h:75
QFont::pointSize
int pointSize() const
Kleo::KeyFilter::MatchContext
MatchContext
Definition: keyfilter.h:58
Kleo::KeyFilterImplBase::matches
bool matches(const GpgME::Key &key, MatchContexts ctx) const
Definition: kconfigbasedkeyfilter.cpp:289
Kleo::KeyFilterImplBase::LevelState
LevelState
Definition: kconfigbasedkeyfilter.h:97
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