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

kleopatra

  • sources
  • kde-4.14
  • kdepim
  • kleopatra
  • utils
classify.cpp
Go to the documentation of this file.
1 /* -*- mode: c++; c-basic-offset:4 -*-
2  utils/classify.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 
33 #include <config-kleopatra.h>
34 
35 #include "classify.h"
36 
37 #include "fileoperationspreferences.h"
38 
39 #include <QString>
40 #include <QStringList>
41 #include <QFile>
42 #include <QFileInfo>
43 #include <QtAlgorithms>
44 #include <QByteArrayMatcher>
45 
46 #ifndef Q_MOC_RUN
47 #include <boost/range.hpp>
48 #endif
49 
50 #ifdef __GLIBCXX__
51 # include <ext/algorithm>
52 #endif
53 
54 #include <functional>
55 
56 using namespace boost;
57 using namespace Kleo::Class;
58 
59 namespace {
60 
61  const unsigned int ExamineContentHint = 0x8000;
62 
63  static const struct _classification {
64  char extension[4];
65  unsigned int classification;
66  } classifications[] = {
67  // ordered by extension
68  { "arl", CMS | Binary | CertificateRevocationList },
69  { "asc", OpenPGP| Ascii | OpaqueSignature|DetachedSignature|CipherText|AnyCertStoreType | ExamineContentHint },
70  { "crl", CMS | Binary | CertificateRevocationList },
71  { "crt", CMS | Binary | Certificate },
72  { "der", CMS | Binary | Certificate|CertificateRevocationList },
73  { "gpg", OpenPGP| Binary | OpaqueSignature|CipherText|AnyCertStoreType },
74  { "p10", CMS | Ascii | CertificateRequest },
75  { "p12", CMS | Binary | ExportedPSM },
76  { "p7c", CMS | Binary | Certificate },
77  { "p7m", CMS | Binary | CipherText },
78  { "p7s", CMS | Binary | AnySignature },
79  { "pem", CMS | Ascii | AnyType | ExamineContentHint },
80  { "pgp", OpenPGP| Binary | OpaqueSignature|CipherText|AnyCertStoreType },
81  { "sig", OpenPGP|AnyFormat| DetachedSignature },
82  };
83 
84  static const unsigned int defaultClassification = NoClass;
85 
86  template <template <typename U> class Op>
87  struct ByExtension {
88  typedef bool result_type;
89 
90  template <typename T>
91  bool operator()( const T & lhs, const T & rhs ) const {
92  return Op<int>()( qstricmp( lhs.extension, rhs.extension ), 0 );
93  }
94  template <typename T>
95  bool operator()( const T & lhs, const char * rhs ) const {
96  return Op<int>()( qstricmp( lhs.extension, rhs ), 0 );
97  }
98  template <typename T>
99  bool operator()( const char * lhs, const T & rhs ) const {
100  return Op<int>()( qstricmp( lhs, rhs.extension ), 0 );
101  }
102  bool operator()( const char * lhs, const char * rhs ) const {
103  return Op<int>()( qstricmp( lhs, rhs ), 0 );
104  }
105  };
106 
107  static const struct _content_classification {
108  char content[28];
109  unsigned int classification;
110  } content_classifications[] = {
111  { "CERTIFICATE", Certificate },
112  { "ENCRYPTED MESSAGE", CipherText },
113  { "MESSAGE", OpaqueSignature|CipherText },
114  { "PKCS12", ExportedPSM },
115  { "PRIVATE KEY BLOCK", ExportedPSM },
116  { "PUBLIC KEY BLOCK", Certificate },
117  { "SIGNATURE", DetachedSignature },
118  { "SIGNED MESSAGE", ClearsignedMessage|DetachedSignature },
119  };
120 
121  template <template <typename U> class Op>
122  struct ByContent {
123  typedef bool result_type;
124 
125  const unsigned int N;
126  explicit ByContent( unsigned int n ) : N( n ) {}
127 
128  template <typename T>
129  bool operator()( const T & lhs, const T & rhs ) const {
130  return Op<int>()( qstrncmp( lhs.content, rhs.content, N ), 0 );
131  }
132  template <typename T>
133  bool operator()( const T & lhs, const char * rhs ) const {
134  return Op<int>()( qstrncmp( lhs.content, rhs, N ), 0 );
135  }
136  template <typename T>
137  bool operator()( const char * lhs, const T & rhs ) const {
138  return Op<int>()( qstrncmp( lhs, rhs.content, N ), 0 );
139  }
140  bool operator()( const char * lhs, const char * rhs ) const {
141  return Op<int>()( qstrncmp( lhs, rhs, N ), 0 );
142  }
143  };
144 
145 }
146 
147 unsigned int Kleo::classify( const QStringList & fileNames ) {
148  if ( fileNames.empty() )
149  return 0;
150  unsigned int result = classify( fileNames.front() );
151  Q_FOREACH( const QString & fileName, fileNames )
152  result &= classify( fileName );
153  return result;
154 }
155 
156 unsigned int Kleo::classify( const QString & filename ) {
157 #ifdef __GLIBCXX__
158  assert( __gnu_cxx::is_sorted( begin( classifications ), end( classifications ), ByExtension<std::less>() ) );
159 #endif
160 
161  const QFileInfo fi( filename );
162 
163  const _classification * const it = qBinaryFind( begin( classifications ), end( classifications ),
164  fi.suffix().toLatin1().constData(),
165  ByExtension<std::less>() );
166  if ( it != end( classifications ) )
167  if ( !( it->classification & ExamineContentHint ) )
168  return it->classification;
169 
170  const unsigned int bestGuess =
171  it == end( classifications ) ? defaultClassification
172  /* else */ : it->classification ;
173 
174  QFile file( filename );
175  if ( !file.open( QIODevice::ReadOnly|QIODevice::Text ) )
176  return bestGuess;
177 
178  const unsigned int contentClassification = classifyContent( file.read( 4096 ) );
179  if ( contentClassification != defaultClassification )
180  return contentClassification;
181  else
182  return bestGuess;
183 }
184 
185 unsigned int Kleo::classifyContent( const QByteArray & data ) {
186 #ifdef __GLIBCXX__
187  assert( __gnu_cxx::is_sorted( begin( content_classifications ), end( content_classifications ), ByContent<std::less>(100) ) );
188 #endif
189 
190  static const char beginString[] = "-----BEGIN ";
191  static const QByteArrayMatcher beginMatcher( beginString );
192  int pos = beginMatcher.indexIn( data );
193  if ( pos < 0 )
194  return defaultClassification;
195  pos += sizeof beginString - 1;
196 
197  const bool pgp = qstrncmp( data.data() + pos, "PGP ", 4 ) == 0;
198  if ( pgp )
199  pos += 4;
200 
201  const int epos = data.indexOf( "-----\n", pos );
202  if ( epos < 0 )
203  return defaultClassification;
204 
205  const _content_classification * const cit
206  = qBinaryFind( begin( content_classifications ), end( content_classifications ),
207  data.data() + pos, ByContent<std::less>( epos - pos ) );
208 
209  if ( cit == end( content_classifications ) )
210  return defaultClassification;
211  else
212  return cit->classification | ( pgp ? OpenPGP : CMS );
213 }
214 
215 QString Kleo::printableClassification( unsigned int classification ) {
216  QStringList parts;
217  if ( classification & CMS )
218  parts.push_back( QLatin1String("CMS") );
219  if ( classification & OpenPGP )
220  parts.push_back( QLatin1String("OpenPGP") );
221  if ( classification & Binary )
222  parts.push_back( QLatin1String("Binary") );
223  if ( classification & Ascii )
224  parts.push_back( QLatin1String("Ascii") );
225  if ( classification & DetachedSignature )
226  parts.push_back( QLatin1String("DetachedSignature") );
227  if ( classification & OpaqueSignature )
228  parts.push_back( QLatin1String("OpaqueSignature") );
229  if ( classification & ClearsignedMessage )
230  parts.push_back( QLatin1String("ClearsignedMessage") );
231  if ( classification & CipherText )
232  parts.push_back( QLatin1String("CipherText") );
233  if ( classification & Certificate )
234  parts.push_back( QLatin1String("Certificate" ));
235  if ( classification & ExportedPSM )
236  parts.push_back( QLatin1String("ExportedPSM") );
237  if ( classification & CertificateRequest )
238  parts.push_back( QLatin1String("CertificateRequest") );
239  return parts.join( QLatin1String(", ") );
240 }
241 
242 static QString chopped( QString s, unsigned int n ) {
243  s.chop( n );
244  return s;
245 }
246 
251 QString Kleo::findSignedData( const QString & signatureFileName ) {
252  if ( !mayBeDetachedSignature( signatureFileName ) )
253  return QString();
254  const QString baseName = chopped( signatureFileName, 4 );
255  return QFile::exists( baseName ) ? baseName : QString() ;
256 }
257 
264 QStringList Kleo::findSignatures( const QString & signedDataFileName ) {
265  QStringList result;
266  for ( unsigned int i = 0, end = size( classifications ) ; i < end ; ++i )
267  if ( classifications[i].classification & DetachedSignature ) {
268  const QString candiate = signedDataFileName + QLatin1Char('.') + QLatin1String(classifications[i].extension);
269  if ( QFile::exists( candiate ) )
270  result.push_back( candiate );
271  }
272  return result;
273 }
274 
279 QString Kleo::outputFileName( const QString & inputFileName ) {
280  const QFileInfo fi( inputFileName );
281 
282  if ( qBinaryFind( begin( classifications ), end( classifications ),
283  fi.suffix().toLatin1().constData(),
284  ByExtension<std::less>() ) == end( classifications ) )
285  return inputFileName + QLatin1String(".out");
286  else
287  return chopped( inputFileName, 4 );
288 }
289 
294 const char * Kleo::outputFileExtension( unsigned int classification ) {
295 
296  if ( classification & OpenPGP ) {
297  FileOperationsPreferences filePrefs;
298  if ( filePrefs.usePGPFileExt() ) {
299  return "pgp";
300  }
301  }
302 
303  for ( unsigned int i = 0 ; i < sizeof classifications / sizeof *classifications ; ++i )
304  if ( ( classifications[i].classification & classification ) == classification )
305  return classifications[i].extension;
306  return 0;
307 }
Kleo::outputFileExtension
const char * outputFileExtension(unsigned int classification)
Definition: classify.cpp:294
Kleo::Class::AnySignature
Definition: classify.h:66
Kleo::Class::NoClass
Definition: classify.h:45
Kleo::findSignedData
QString findSignedData(const QString &signatureFileName)
Definition: classify.cpp:251
QByteArrayMatcher::indexIn
int indexIn(const QByteArray &ba, int from) const
Kleo::Class::CertificateRevocationList
Definition: classify.h:80
QList::push_back
void push_back(const T &value)
QByteArray
Kleo::Class::DetachedSignature
Definition: classify.h:62
Kleo::Class::ExportedPSM
Definition: classify.h:74
classify.h
Kleo::printableClassification
QString printableClassification(unsigned int classification)
Definition: classify.cpp:215
Kleo::Class::CipherText
Definition: classify.h:68
QStringList::join
QString join(const QString &separator) const
QFile::exists
bool exists() const
QString::chop
void chop(int n)
Kleo::Class::Ascii
Definition: classify.h:56
QFile
QByteArray::indexOf
int indexOf(char ch, int from) const
QList::empty
bool empty() const
Kleo::Class::AnyCertStoreType
Definition: classify.h:76
Kleo::Class::OpenPGP
Definition: classify.h:49
QByteArray::constData
const char * constData() const
Kleo::Class::CMS
Definition: classify.h:48
QIODevice::read
qint64 read(char *data, qint64 maxSize)
QList::front
T & front()
QString
Kleo::Class::OpaqueSignature
Definition: classify.h:63
QFile::open
virtual bool open(QFlags< QIODevice::OpenModeFlag > mode)
QStringList
Kleo::outputFileName
QString outputFileName(const QString &input)
Definition: classify.cpp:279
QFileInfo
Kleo::Class::CertificateRequest
Definition: classify.h:78
QLatin1Char
Kleo::Class::Binary
Definition: classify.h:55
Kleo::Class::AnyType
Definition: classify.h:82
Kleo::findSignatures
QStringList findSignatures(const QString &signedDataFileName)
Definition: classify.cpp:264
QByteArrayMatcher
Kleo::classify
unsigned int classify(const QString &filename)
Definition: classify.cpp:156
QString::toLatin1
QByteArray toLatin1() const
QFileInfo::suffix
QString suffix() const
QLatin1String
Kleo::Class::Certificate
Definition: classify.h:73
chopped
static QString chopped(QString s, unsigned int n)
Definition: classify.cpp:242
QByteArray::data
char * data()
Kleo::classifyContent
unsigned int classifyContent(const QByteArray &data)
Definition: classify.cpp:185
extension
static const char * extension(bool pgp, bool sign, bool encrypt, bool ascii, bool detached)
Definition: signencryptfilescontroller.cpp:287
Kleo::Class::AnyFormat
Definition: classify.h:58
Kleo::Class::ClearsignedMessage
Definition: classify.h:64
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:33:10 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kleopatra

Skip menu "kleopatra"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

kdepim API Reference

Skip menu "kdepim API Reference"
  • akonadi_next
  • akregator
  • blogilo
  • calendarsupport
  • console
  •   kabcclient
  •   konsolekalendar
  • kaddressbook
  • kalarm
  •   lib
  • kdgantt2
  • kjots
  • kleopatra
  • kmail
  • knode
  • knotes
  • kontact
  • korgac
  • korganizer
  • ktimetracker
  • libkdepim
  • libkleo
  • libkpgp
  • mailcommon
  • messagelist
  • messageviewer
  • pimprint

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal