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

libkleo

  • sources
  • kde-4.12
  • kdepim
  • libkleo
  • kleo
dn.cpp
Go to the documentation of this file.
1 /*
2  dn.cpp
3 
4  This file is part of libkleopatra, the KDE keymanagement library
5  Copyright (c) 2004 Klarälvdalens Datakonsult AB
6 
7  DN parsing:
8  Copyright (c) 2002 g10 Code GmbH
9  Copyright (c) 2004 Klarälvdalens Datakonsult AB
10 
11  Libkleopatra is free software; you can redistribute it and/or
12  modify it under the terms of the GNU General Public License as
13  published by the Free Software Foundation; either version 2 of the
14  License, or (at your option) any later version.
15 
16  Libkleopatra is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  General Public License for more details.
20 
21  You should have received a copy of the GNU General Public License along
22  with this program; if not, write to the Free Software Foundation, Inc.,
23  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 
25  In addition, as a special exception, the copyright holders give
26  permission to link the code of this program with any edition of
27  the Qt library by Trolltech AS, Norway (or with modified versions
28  of Qt that use the same license as Qt), and distribute linked
29  combinations including the two. You must obey the GNU General
30  Public License in all respects for all of the code used other than
31  Qt. If you modify this file, you may extend this exception to
32  your version of the file, but you are not obligated to do so. If
33  you do not wish to do so, delete this exception statement from
34  your version.
35 */
36 
37 #include "dn.h"
38 
39 #include "oidmap.h"
40 
41 #include "libkleo/ui/dnattributeorderconfigwidget.h"
42 
43 #include <kconfig.h>
44 #include <klocale.h>
45 
46 #include <QStringList>
47 
48 #include <iostream>
49 #include <iterator>
50 #include <algorithm>
51 #include <map>
52 
53 #include <string.h>
54 #include <ctype.h>
55 #include <stdlib.h>
56 #include <kglobal.h>
57 #include <kconfiggroup.h>
58 
59 class Kleo::DN::Private {
60 public:
61  Private() : mRefCount( 0 ) {}
62  Private( const Private & other )
63  : attributes( other.attributes ),
64  reorderedAttributes( other.reorderedAttributes ),
65  mRefCount( 0 )
66  {
67 
68  }
69 
70  int ref() {
71  return ++mRefCount;
72  }
73 
74  int unref() {
75  if ( --mRefCount <= 0 ) {
76  delete this;
77  return 0;
78  } else
79  return mRefCount;
80  }
81 
82  int refCount() const { return mRefCount; }
83 
84  DN::Attribute::List attributes;
85  DN::Attribute::List reorderedAttributes;
86 private:
87  int mRefCount;
88 };
89 
90 namespace {
91  struct DnPair {
92  char * key;
93  char * value;
94  };
95 }
96 
97 // copied from CryptPlug and adapted to work on DN::Attribute::List:
98 
99 #define digitp(p) (*(p) >= '0' && *(p) <= '9')
100 #define hexdigitp(a) (digitp (a) \
101  || (*(a) >= 'A' && *(a) <= 'F') \
102  || (*(a) >= 'a' && *(a) <= 'f'))
103 #define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \
104  *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10))
105 #define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1))
106 
107 static char *
108 trim_trailing_spaces( char *string )
109 {
110  char *p, *mark;
111 
112  for( mark = NULL, p = string; *p; p++ ) {
113  if( isspace( *p ) ) {
114  if( !mark )
115  mark = p;
116  }
117  else
118  mark = NULL;
119  }
120  if( mark )
121  *mark = '\0' ;
122 
123  return string ;
124 }
125 
126 /* Parse a DN and return an array-ized one. This is not a validating
127  parser and it does not support any old-stylish syntax; gpgme is
128  expected to return only rfc2253 compatible strings. */
129 static const unsigned char *
130 parse_dn_part (DnPair *array, const unsigned char *string)
131 {
132  const unsigned char *s, *s1;
133  size_t n;
134  char *p;
135 
136  /* parse attributeType */
137  for (s = string+1; *s && *s != '='; s++)
138  ;
139  if (!*s)
140  return NULL; /* error */
141  n = s - string;
142  if (!n)
143  return NULL; /* empty key */
144  p = (char*)malloc (n+1);
145 
146 
147  memcpy (p, string, n);
148  p[n] = 0;
149  trim_trailing_spaces ((char*)p);
150  // map OIDs to their names:
151  for ( unsigned int i = 0 ; i < numOidMaps ; ++i )
152  if ( !strcasecmp ((char*)p, oidmap[i].oid) ) {
153  free( p );
154  p = strdup( oidmap[i].name );
155  break;
156  }
157  array->key = p;
158  string = s + 1;
159 
160  if (*string == '#')
161  { /* hexstring */
162  string++;
163  for (s=string; hexdigitp (s); s++)
164  s++;
165  n = s - string;
166  if (!n || (n & 1))
167  return NULL; /* empty or odd number of digits */
168  n /= 2;
169  array->value = p = (char*)malloc (n+1);
170 
171 
172  for (s1=string; n; s1 += 2, n--)
173  *p++ = xtoi_2 (s1);
174  *p = 0;
175  }
176  else
177  { /* regular v3 quoted string */
178  for (n=0, s=string; *s; s++)
179  {
180  if (*s == '\\')
181  { /* pair */
182  s++;
183  if (*s == ',' || *s == '=' || *s == '+'
184  || *s == '<' || *s == '>' || *s == '#' || *s == ';'
185  || *s == '\\' || *s == '\"' || *s == ' ')
186  n++;
187  else if (hexdigitp (s) && hexdigitp (s+1))
188  {
189  s++;
190  n++;
191  }
192  else
193  return NULL; /* invalid escape sequence */
194  }
195  else if (*s == '\"')
196  return NULL; /* invalid encoding */
197  else if (*s == ',' || *s == '=' || *s == '+'
198  || *s == '<' || *s == '>' || *s == '#' || *s == ';' )
199  break;
200  else
201  n++;
202  }
203 
204  array->value = p = (char*)malloc (n+1);
205 
206 
207  for (s=string; n; s++, n--)
208  {
209  if (*s == '\\')
210  {
211  s++;
212  if (hexdigitp (s))
213  {
214  *p++ = xtoi_2 (s);
215  s++;
216  }
217  else
218  *p++ = *s;
219  }
220  else
221  *p++ = *s;
222  }
223  *p = 0;
224  }
225  return s;
226 }
227 
228 
229 /* Parse a DN and return an array-ized one. This is not a validating
230  parser and it does not support any old-stylish syntax; gpgme is
231  expected to return only rfc2253 compatible strings. */
232 static Kleo::DN::Attribute::List
233 parse_dn( const unsigned char * string ) {
234  if ( !string )
235  return QVector<Kleo::DN::Attribute>();
236 
237  QVector<Kleo::DN::Attribute> result;
238  while (*string)
239  {
240  while (*string == ' ')
241  string++;
242  if (!*string)
243  break; /* ready */
244 
245  DnPair pair = { 0, 0 };
246  string = parse_dn_part (&pair, string);
247  if (!string)
248  goto failure;
249  if ( pair.key && pair.value )
250  result.push_back( Kleo::DN::Attribute( QString::fromUtf8( pair.key ),
251  QString::fromUtf8( pair.value ) ) );
252  free( pair.key );
253  free( pair.value );
254 
255  while (*string == ' ')
256  string++;
257  if (*string && *string != ',' && *string != ';' && *string != '+')
258  goto failure; /* invalid delimiter */
259  if (*string)
260  string++;
261  }
262  return result;
263 
264 failure:
265  return QVector<Kleo::DN::Attribute>();
266 }
267 
268 static QVector<Kleo::DN::Attribute>
269 parse_dn( const QString & dn ) {
270  return parse_dn( (const unsigned char*)dn.toUtf8().data() );
271 }
272 
273 static QString dn_escape( const QString & s ) {
274  QString result;
275  for ( unsigned int i = 0, end = s.length() ; i != end ; ++i ) {
276  const QChar ch = s[i];
277  switch ( ch.unicode() ) {
278  case ',':
279  case '+':
280  case '"':
281  case '\\':
282  case '<':
283  case '>':
284  case ';':
285  result += QLatin1Char('\\');
286  // fall through
287  default:
288  result += ch;
289  }
290  }
291  return result;
292 }
293 
294 static QString
295 serialise( const QVector<Kleo::DN::Attribute> & dn, const QString & sep ) {
296  QStringList result;
297  for ( QVector<Kleo::DN::Attribute>::const_iterator it = dn.begin() ; it != dn.end() ; ++it )
298  if ( !(*it).name().isEmpty() && !(*it).value().isEmpty() )
299  result.push_back( (*it).name().trimmed() + QLatin1Char('=') + dn_escape( (*it).value().trimmed() ) );
300  return result.join( sep );
301 }
302 
303 static Kleo::DN::Attribute::List
304 reorder_dn( const Kleo::DN::Attribute::List & dn ) {
305  const QStringList & attrOrder = Kleo::DNAttributeMapper::instance()->attributeOrder();
306 
307  Kleo::DN::Attribute::List unknownEntries;
308  Kleo::DN::Attribute::List result;
309  unknownEntries.reserve( dn.size() );
310  result.reserve( dn.size() );
311 
312  // find all unknown entries in their order of appearance
313  for ( Kleo::DN::const_iterator it = dn.begin(); it != dn.end(); ++it )
314  if ( !attrOrder.contains( (*it).name() ) )
315  unknownEntries.push_back( *it );
316 
317  // process the known attrs in the desired order
318  for ( QStringList::const_iterator oit = attrOrder.begin() ; oit != attrOrder.end() ; ++oit )
319  if ( *oit == QLatin1String("_X_") ) {
320  // insert the unknown attrs
321  std::copy( unknownEntries.begin(), unknownEntries.end(),
322  std::back_inserter( result ) );
323  unknownEntries.clear(); // don't produce dup's
324  } else {
325  for ( Kleo::DN::const_iterator dnit = dn.begin() ; dnit != dn.end() ; ++dnit )
326  if ( (*dnit).name() == *oit )
327  result.push_back( *dnit );
328  }
329 
330  return result;
331 }
332 
333 //
334 //
335 // class DN
336 //
337 //
338 
339 Kleo::DN::DN() {
340  d = new Private();
341  d->ref();
342 }
343 
344 Kleo::DN::DN( const QString & dn ) {
345  d = new Private();
346  d->ref();
347  d->attributes = parse_dn( dn );
348 }
349 
350 Kleo::DN::DN( const char * utf8DN ) {
351  d = new Private();
352  d->ref();
353  if ( utf8DN )
354  d->attributes = parse_dn( (const unsigned char*)utf8DN );
355 }
356 
357 Kleo::DN::DN( const DN & other )
358  : d( other.d )
359 {
360  if ( d ) d->ref();
361 }
362 
363 Kleo::DN::~DN() {
364  if ( d ) d->unref();
365 }
366 
367 const Kleo::DN & Kleo::DN::operator=( const DN & that ) {
368  if ( this->d == that.d )
369  return *this;
370 
371  if ( that.d )
372  that.d->ref();
373  if ( this->d )
374  this->d->unref();
375 
376  this->d = that.d;
377 
378  return *this;
379 }
380 
381 QString Kleo::DN::prettyDN() const {
382  if ( !d )
383  return QString();
384  if ( d->reorderedAttributes.empty() )
385  d->reorderedAttributes = reorder_dn( d->attributes );
386  return serialise( d->reorderedAttributes, QLatin1String(",") );
387 }
388 
389 QString Kleo::DN::dn() const {
390  return d ? serialise( d->attributes, QLatin1String(",") ) : QString() ;
391 }
392 
393 QString Kleo::DN::dn( const QString & sep ) const {
394  return d ? serialise( d->attributes, sep ) : QString() ;
395 }
396 
397 // static
398 QString Kleo::DN::escape( const QString & value ) {
399  return dn_escape( value );
400 }
401 
402 void Kleo::DN::detach() {
403  if ( !d ) {
404  d = new Kleo::DN::Private();
405  d->ref();
406  } else if ( d->refCount() > 1 ) {
407  Kleo::DN::Private * d_save = d;
408  d = new Kleo::DN::Private( *d );
409  d->ref();
410  d_save->unref();
411  }
412 }
413 
414 void Kleo::DN::append( const Attribute & attr ) {
415  detach();
416  d->attributes.push_back( attr );
417  d->reorderedAttributes.clear();
418 }
419 
420 QString Kleo::DN::operator[]( const QString & attr ) const {
421  if ( !d )
422  return QString();
423  const QString attrUpper = attr.toUpper();
424  for ( QVector<Attribute>::const_iterator it = d->attributes.constBegin() ;
425  it != d->attributes.constEnd() ; ++it )
426  if ( (*it).name() == attrUpper )
427  return (*it).value();
428  return QString();
429 }
430 
431 static QVector<Kleo::DN::Attribute> empty;
432 
433 Kleo::DN::const_iterator Kleo::DN::begin() const {
434  return d ? d->attributes.constBegin() : empty.constBegin() ;
435 }
436 
437 Kleo::DN::const_iterator Kleo::DN::end() const {
438  return d ? d->attributes.constEnd() : empty.constEnd() ;
439 }
440 
441 
443 
444 namespace {
445  struct ltstr {
446  bool operator()( const char * s1, const char * s2 ) const {
447  return qstrcmp( s1, s2 ) < 0 ;
448  }
449  };
450 }
451 
452 static const char * defaultOrder[] = {
453  "CN", "L", "_X_", "OU", "O", "C"
454 };
455 
456 std::pair<const char*,const char*> attributeLabels[] = {
457 #define MAKE_PAIR(x,y) std::pair<const char*,const char*>( x, y )
458  MAKE_PAIR( "CN", I18N_NOOP("Common name") ),
459  MAKE_PAIR( "SN", I18N_NOOP("Surname") ),
460  MAKE_PAIR( "GN", I18N_NOOP("Given name") ),
461  MAKE_PAIR( "L", I18N_NOOP("Location") ),
462  MAKE_PAIR( "T", I18N_NOOP("Title") ),
463  MAKE_PAIR( "OU", I18N_NOOP("Organizational unit") ),
464  MAKE_PAIR( "O", I18N_NOOP("Organization") ),
465  MAKE_PAIR( "PC", I18N_NOOP("Postal code") ),
466  MAKE_PAIR( "C", I18N_NOOP("Country code") ),
467  MAKE_PAIR( "SP", I18N_NOOP("State or province") ),
468  MAKE_PAIR( "DC", I18N_NOOP("Domain component") ),
469  MAKE_PAIR( "BC", I18N_NOOP("Business category") ),
470  MAKE_PAIR( "EMAIL", I18N_NOOP("Email address") ),
471  MAKE_PAIR( "MAIL", I18N_NOOP("Mail address") ),
472  MAKE_PAIR( "MOBILE", I18N_NOOP("Mobile phone number") ),
473  MAKE_PAIR( "TEL", I18N_NOOP("Telephone number") ),
474  MAKE_PAIR( "FAX", I18N_NOOP("Fax number") ),
475  MAKE_PAIR( "STREET", I18N_NOOP("Street address") ),
476  MAKE_PAIR( "UID", I18N_NOOP("Unique ID") )
477 #undef MAKE_PAIR
478 };
479 static const unsigned int numAttributeLabels = sizeof attributeLabels / sizeof *attributeLabels ;
480 
481 class Kleo::DNAttributeMapper::Private {
482 public:
483  Private();
484  std::map<const char*,const char*,ltstr> map;
485  QStringList attributeOrder;
486 };
487 
488 Kleo::DNAttributeMapper::Private::Private()
489  : map( attributeLabels, attributeLabels + numAttributeLabels ) {}
490 
491 Kleo::DNAttributeMapper::DNAttributeMapper() {
492  d = new Private();
493  const KConfigGroup config( KGlobal::config(), "DN" );
494  d->attributeOrder = config.readEntry( "AttributeOrder" , QStringList() );
495  if ( d->attributeOrder.empty() )
496  std::copy( defaultOrder, defaultOrder + sizeof defaultOrder / sizeof *defaultOrder,
497  std::back_inserter( d->attributeOrder ) );
498  mSelf = this;
499 }
500 
501 Kleo::DNAttributeMapper::~DNAttributeMapper() {
502  mSelf = 0;
503  delete d; d = 0;
504 }
505 
506 Kleo::DNAttributeMapper * Kleo::DNAttributeMapper::mSelf = 0;
507 
508 const Kleo::DNAttributeMapper * Kleo::DNAttributeMapper::instance() {
509  if ( !mSelf )
510  (void)new DNAttributeMapper();
511  return mSelf;
512 }
513 
514 QString Kleo::DNAttributeMapper::name2label( const QString & s ) const {
515  const std::map<const char*,const char*,ltstr>::const_iterator it
516  = d->map.find( s.trimmed().toUpper().toLatin1() );
517  if ( it == d->map.end() )
518  return QString();
519  return i18n( it->second );
520 }
521 
522 QStringList Kleo::DNAttributeMapper::names() const {
523  QStringList result;
524  for ( std::map<const char*,const char*,ltstr>::const_iterator it = d->map.begin() ; it != d->map.end() ; ++it )
525  result.push_back( QLatin1String(it->first) );
526  return result;
527 }
528 
529 const QStringList & Kleo::DNAttributeMapper::attributeOrder() const {
530  return d->attributeOrder;
531 }
532 
533 void Kleo::DNAttributeMapper::setAttributeOrder( const QStringList & order ) {
534  d->attributeOrder = order;
535  if ( order.empty() )
536  std::copy( defaultOrder, defaultOrder + sizeof defaultOrder / sizeof *defaultOrder,
537  std::back_inserter( d->attributeOrder ) );
538  KConfigGroup config( KGlobal::config(), "DN" );
539  config.writeEntry( "AttributeOrder", order );
540 }
541 
542 Kleo::DNAttributeOrderConfigWidget * Kleo::DNAttributeMapper::configWidget( QWidget * parent ) const {
543  return new DNAttributeOrderConfigWidget( mSelf, parent );
544 }
trim_trailing_spaces
static char * trim_trailing_spaces(char *string)
Definition: dn.cpp:108
empty
static QVector< Kleo::DN::Attribute > empty
Definition: dn.cpp:431
name
const char * name
Definition: kconfigbasedkeyfilter.cpp:124
Kleo::DNAttributeMapper::name2label
QString name2label(const QString &s) const
Definition: dn.cpp:514
oid
const char * oid
Definition: oidmap.h:38
Kleo::DNAttributeMapper::setAttributeOrder
void setAttributeOrder(const QStringList &order)
Definition: dn.cpp:533
numOidMaps
static const unsigned int numOidMaps
Definition: oidmap.h:55
Attribute
QWidget
Kleo::DN::DN
DN()
Definition: dn.cpp:339
numAttributeLabels
static const unsigned int numAttributeLabels
Definition: dn.cpp:479
Kleo::DN::prettyDN
QString prettyDN() const
Definition: dn.cpp:381
QString
Kleo::QGpgMEProgressTokenMapper::map
QString map(const char *token, int subtoken)
Definition: qgpgmeprogresstokenmapper.cpp:91
Kleo::DNAttributeMapper::attributeOrder
const QStringList & attributeOrder() const
Definition: dn.cpp:529
dn.h
Kleo::DN::escape
static QString escape(const QString &value)
Definition: dn.cpp:398
Kleo::DNAttributeMapper
DN Attribute mapper.
Definition: dn.h:53
xtoi_2
#define xtoi_2(p)
Definition: dn.cpp:105
reorder_dn
static Kleo::DN::Attribute::List reorder_dn(const Kleo::DN::Attribute::List &dn)
Definition: dn.cpp:304
dnattributeorderconfigwidget.h
Kleo::DNAttributeMapper::names
QStringList names() const
Definition: dn.cpp:522
oidmap.h
Kleo::DNAttributeOrderConfigWidget
Definition: dnattributeorderconfigwidget.h:48
Kleo::DN::append
void append(const Attribute &attr)
Definition: dn.cpp:414
parse_dn_part
static const unsigned char * parse_dn_part(DnPair *array, const unsigned char *string)
Definition: dn.cpp:130
defaultOrder
static const char * defaultOrder[]
Definition: dn.cpp:452
Kleo::DN
DN parser and reorderer.
Definition: dn.h:77
kdtools::copy
O copy(const I &i)
Definition: stl_util.h:425
hexdigitp
#define hexdigitp(a)
Definition: dn.cpp:100
Kleo::DN::operator[]
QString operator[](const QString &attr) const
Definition: dn.cpp:420
parse_dn
static Kleo::DN::Attribute::List parse_dn(const unsigned char *string)
Definition: dn.cpp:233
Kleo::DN::~DN
~DN()
Definition: dn.cpp:363
Kleo::DN::end
const_iterator end() const
Definition: dn.cpp:437
oidmap
static struct @4 oidmap[]
serialise
static QString serialise(const QVector< Kleo::DN::Attribute > &dn, const QString &sep)
Definition: dn.cpp:295
Kleo::DNAttributeMapper::configWidget
DNAttributeOrderConfigWidget * configWidget(QWidget *parent=0) const
Definition: dn.cpp:542
dn_escape
static QString dn_escape(const QString &s)
Definition: dn.cpp:273
Kleo::DN::begin
const_iterator begin() const
Definition: dn.cpp:433
attributeLabels
std::pair< const char *, const char * > attributeLabels[]
Definition: dn.cpp:456
MAKE_PAIR
#define MAKE_PAIR(x, y)
Kleo::DNAttributeMapper::instance
static const DNAttributeMapper * instance()
Definition: dn.cpp:508
Kleo::DN::Attribute
Attribute(const QString &name=QString(), const QString &value=QString())
Definition: dn.h:123
Kleo::DN::dn
QString dn() const
Definition: dn.cpp:389
Kleo::DN::operator=
const DN & operator=(const DN &other)
Definition: dn.cpp:367
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:57:48 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

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