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

kleopatra

classify.cpp

Go to the documentation of this file.
00001 /* -*- mode: c++; c-basic-offset:4 -*-
00002     utils/classify.cpp
00003 
00004     This file is part of Kleopatra, the KDE keymanager
00005     Copyright (c) 2007 Klarälvdalens Datakonsult AB
00006 
00007     Kleopatra is free software; you can redistribute it and/or modify
00008     it under the terms of the GNU General Public License as published by
00009     the Free Software Foundation; either version 2 of the License, or
00010     (at your option) any later version.
00011 
00012     Kleopatra is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015     General Public License for more details.
00016 
00017     You should have received a copy of the GNU General Public License
00018     along with this program; if not, write to the Free Software
00019     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00020 
00021     In addition, as a special exception, the copyright holders give
00022     permission to link the code of this program with any edition of
00023     the Qt library by Trolltech AS, Norway (or with modified versions
00024     of Qt that use the same license as Qt), and distribute linked
00025     combinations including the two.  You must obey the GNU General
00026     Public License in all respects for all of the code used other than
00027     Qt.  If you modify this file, you may extend this exception to
00028     your version of the file, but you are not obligated to do so.  If
00029     you do not wish to do so, delete this exception statement from
00030     your version.
00031 */
00032 
00033 #include <config-kleopatra.h>
00034 
00035 #include "classify.h"
00036 
00037 #include <QString>
00038 #include <QStringList>
00039 #include <QFile>
00040 #include <QFileInfo>
00041 #include <QtAlgorithms>
00042 #include <QByteArrayMatcher>
00043 
00044 #include <boost/range.hpp>
00045 
00046 #ifdef __GNUC__
00047 # include <ext/algorithm>
00048 #endif
00049 
00050 #include <functional>
00051 
00052 using namespace boost;
00053 using namespace Kleo::Class;
00054 
00055 namespace {
00056 
00057     const unsigned int ExamineContentHint = 0x8000;
00058 
00059     static const struct _classification {
00060         char extension[4];
00061         unsigned int classification;
00062     } classifications[] = {
00063         // ordered by extension
00064         { "asc", OpenPGP|  Ascii  | OpaqueSignature|DetachedSignature|CipherText|AnyCertStoreType | ExamineContentHint },
00065         { "crt", CMS    | Binary  | Certificate },
00066         { "der", CMS    | Binary  | Certificate },
00067         { "gpg", OpenPGP| Binary  | OpaqueSignature|CipherText|AnyCertStoreType },
00068         { "p10", CMS    |  Ascii  | CertificateRequest },
00069         { "p12", CMS    | Binary  | ExportedPSM },
00070         { "p7c", CMS    | Binary  | Certificate  },
00071         { "p7m", CMS    | Binary  | CipherText },
00072         { "p7s", CMS    | Binary  | AnySignature },
00073         { "pem", CMS    |  Ascii  | AnyType | ExamineContentHint },
00074         { "sig", OpenPGP|AnyFormat| DetachedSignature },
00075     };
00076 
00077     static const unsigned int defaultClassification = NoClass;
00078 
00079     template <template <typename U> class Op>
00080     struct ByExtension {
00081         typedef bool result_type;
00082 
00083         template <typename T>
00084         bool operator()( const T & lhs, const T & rhs ) const {
00085             return Op<int>()( qstricmp( lhs.extension, rhs.extension ), 0 );
00086         }
00087         template <typename T>
00088         bool operator()( const T & lhs, const char * rhs ) const {
00089             return Op<int>()( qstricmp( lhs.extension, rhs ), 0 );
00090         }
00091         template <typename T>
00092         bool operator()( const char * lhs, const T & rhs ) const {
00093             return Op<int>()( qstricmp( lhs, rhs.extension ), 0 );
00094         }
00095         bool operator()( const char * lhs, const char * rhs ) const {
00096             return Op<int>()( qstricmp( lhs, rhs ), 0 );
00097         }
00098     };
00099 
00100     static const struct _content_classification {
00101         char content[28];
00102         unsigned int classification;
00103     } content_classifications[] = {
00104         { "CERTIFICATE",       Certificate },
00105         { "MESSAGE",           OpaqueSignature|CipherText },
00106         { "PKCS12",            ExportedPSM },
00107         { "PRIVATE KEY BLOCK", ExportedPSM },
00108         { "PUBLIC KEY BLOCK",  Certificate },
00109         { "SIGNATURE",         DetachedSignature },
00110         { "SIGNED MESSAGE",    ClearsignedMessage },
00111     };
00112 
00113     template <template <typename U> class Op>
00114     struct ByContent {
00115         typedef bool result_type;
00116 
00117         const unsigned int N;
00118         explicit ByContent( unsigned int n ) : N( n ) {}
00119 
00120         template <typename T>
00121         bool operator()( const T & lhs, const T & rhs ) const {
00122             return Op<int>()( qstrncmp( lhs.content, rhs.content, N ), 0 );
00123         }
00124         template <typename T>
00125         bool operator()( const T & lhs, const char * rhs ) const {
00126             return Op<int>()( qstrncmp( lhs.content, rhs, N ), 0 );
00127         }
00128         template <typename T>
00129         bool operator()( const char * lhs, const T & rhs ) const {
00130             return Op<int>()( qstrncmp( lhs, rhs.content, N ), 0 );
00131         }
00132         bool operator()( const char * lhs, const char * rhs ) const {
00133             return Op<int>()( qstrncmp( lhs, rhs, N ), 0 );
00134         }
00135     };
00136 
00137 }
00138 
00139 
00140 unsigned int Kleo::classify( const QString & filename ) {
00141 #ifdef __GNUC__
00142     assert( __gnu_cxx::is_sorted( begin( classifications ), end( classifications ), ByExtension<std::less>() ) );
00143 #endif
00144 
00145     const QFileInfo fi( filename );
00146 
00147     const _classification * const it = qBinaryFind( begin( classifications ), end( classifications ),
00148                                                     fi.suffix().toLatin1().constData(),
00149                                                     ByExtension<std::less>() );
00150     if ( it == end( classifications ) )
00151         return defaultClassification;
00152     if ( !( it->classification & ExamineContentHint ) )
00153         return it->classification;
00154 
00155     QFile file( filename );
00156     if ( !file.open( QIODevice::ReadOnly|QIODevice::Text ) )
00157         return it->classification;
00158 
00159     const unsigned int contentClassification = classifyContent( file.read( 4096 ) );
00160     if ( contentClassification != defaultClassification )
00161         return contentClassification;
00162     else
00163         return it->classification;
00164 }
00165 
00166 unsigned int Kleo::classifyContent( const QByteArray & data ) {
00167 #ifdef __GNUC__
00168     assert( __gnu_cxx::is_sorted( begin( content_classifications ), end( content_classifications ), ByContent<std::less>(100) ) );
00169 #endif
00170     
00171     static const char beginString[] = "-----BEGIN ";
00172     static const QByteArrayMatcher beginMatcher( beginString );
00173     int pos = beginMatcher.indexIn( data );
00174     if ( pos < 0 )
00175         return defaultClassification;
00176     pos += sizeof beginString - 1;
00177 
00178     const bool pgp = qstrncmp( data.data() + pos, "PGP ", 4 ) == 0;
00179     if ( pgp )
00180         pos += 4;
00181 
00182     const int epos = data.indexOf( "-----\n", pos );
00183     if ( epos < 0 )
00184         return defaultClassification;
00185 
00186     const _content_classification * const cit
00187         = qBinaryFind( begin( content_classifications ), end( content_classifications ),
00188                        data.data() + pos, ByContent<std::less>( epos - pos ) );
00189 
00190     if ( cit == end( content_classifications ) )
00191         return defaultClassification;
00192     else
00193         return cit->classification | ( pgp ? OpenPGP : CMS );
00194 }
00195 
00196 QString Kleo::printableClassification( unsigned int classification ) {
00197     QStringList parts;
00198     if ( classification & CMS )
00199         parts.push_back( "CMS" );
00200     if ( classification & OpenPGP )
00201         parts.push_back( "OpenPGP" );
00202     if ( classification & Binary )
00203         parts.push_back( "Binary" );
00204     if ( classification & Ascii )
00205         parts.push_back( "Ascii" );
00206     if ( classification & DetachedSignature )
00207         parts.push_back( "DetachedSignature" );
00208     if ( classification & OpaqueSignature )
00209         parts.push_back( "OpaqueSignature" );
00210     if ( classification & ClearsignedMessage )
00211         parts.push_back( "ClearsignedMessage" );
00212     if ( classification & CipherText )
00213         parts.push_back( "CipherText" );
00214     if ( classification & Certificate )
00215         parts.push_back( "Certificate" );
00216     if ( classification & ExportedPSM )
00217         parts.push_back( "ExportedPSM" );
00218     if ( classification & CertificateRequest )
00219         parts.push_back( "CertificateRequest" );
00220     return parts.join( ", " );
00221 }
00222 
00223 static QString chopped( QString s, unsigned int n ) {
00224     s.chop( n );
00225     return s;
00226 }
00227 
00232 QString Kleo::findSignedData( const QString & signatureFileName ) {
00233     if ( !mayBeDetachedSignature( signatureFileName ) )
00234         return QString();
00235     const QString baseName = chopped( signatureFileName, 4 );
00236     return QFile::exists( baseName ) ? baseName : QString() ;
00237 }
00238 
00245 QStringList Kleo::findSignatures( const QString & signedDataFileName ) {
00246     QStringList result;
00247     for ( unsigned int i = 0, end = size( classifications ) ; i < end ; ++i )
00248         if ( classifications[i].classification & DetachedSignature ) {
00249             const QString candiate = signedDataFileName + '.' + classifications[i].extension;
00250             if ( QFile::exists( candiate ) )
00251                 result.push_back( candiate );
00252         }
00253     return result;
00254 }
00255 
00260 QString Kleo::outputFileName( const QString & inputFileName ) {
00261     const QFileInfo fi( inputFileName );
00262 
00263     if ( qBinaryFind( begin( classifications ), end( classifications ),
00264                       fi.suffix().toLatin1().constData(),
00265                       ByExtension<std::less>() ) == end( classifications ) )
00266         return inputFileName + ".out";
00267     else
00268         return chopped( inputFileName, 4 );
00269 }
00270 
00275 const char * Kleo::outputFileExtension( unsigned int classification ) {
00276     for ( unsigned int i = 0 ; i < sizeof classifications / sizeof *classifications ; ++i )
00277         if ( ( classifications[i].classification & classification ) == classification )
00278             return classifications[i].extension;
00279     return 0;
00280 }

kleopatra

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

kdepim

Skip menu "kdepim"
  • akonadi
  •   clients
  •   kabc
  •   kcal
  •   kcm
  • akregator
  • console
  •   kabcclient
  •   konsolekalendar
  • kaddressbook
  • kalarm
  •   lib
  • kdgantt
  • kdgantt1
  • kjots
  • kleopatra
  • kmail
  • kmobiletools
  • knode
  • knotes
  • kontact
  • kontactinterfaces
  • korganizer
  •   korgac
  • kpilot
  • ktimetracker
  • libkdepim
  • libkholidays
  • libkleo
  • libkpgp
  • maildir
Generated for kdepim by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal