certmanager/lib

chiasmusbackend.cpp

00001 /*
00002     chiasmusbackend.cpp
00003 
00004     This file is part of libkleopatra, the KDE keymanagement library
00005     Copyright (c) 2005 Klarälvdalens Datakonsult AB
00006 
00007     Libkleopatra is free software; you can redistribute it and/or
00008     modify it under the terms of the GNU General Public License as
00009     published by the Free Software Foundation; either version 2 of the
00010     License, or (at your option) any later version.
00011 
00012     Libkleopatra 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 #ifdef HAVE_CONFIG_H
00034 #include <config.h>
00035 #endif
00036 
00037 #include "chiasmusbackend.h"
00038 
00039 #include "config_data.h"
00040 #include "obtainkeysjob.h"
00041 #include "chiasmusjob.h"
00042 
00043 #include "kleo/cryptoconfig.h"
00044 
00045 #include <klocale.h>
00046 #include <kconfig.h>
00047 #include <kshell.h>
00048 #include <kdebug.h>
00049 
00050 #include <qstringlist.h>
00051 #include <qvariant.h>
00052 #include <qfileinfo.h>
00053 
00054 #include <map>
00055 #include <memory>
00056 
00057 #include <cassert>
00058 
00059 namespace {
00060 
00061   //
00062   // The usual QVariant template helpers:
00063   //
00064 
00065   // to<> is a demarshaller. It's a class b/c you can't partially
00066   // specialise function templates yet. However, to<> can be used as if
00067   // it was a function: QString s = to<QString>( myVariant );
00068   template <typename T> class to {};
00069 
00070 #define MAKE_TO( type, func ) \
00071   template <> \
00072   class to< type > { \
00073     type m; \
00074   public: \
00075     to( const QVariant & v ) : m( v.func() ) {} \
00076     operator type() const { return m; } \
00077   }
00078 
00079   MAKE_TO( int, toInt );
00080   MAKE_TO( unsigned int, toUInt );
00081 
00082   template <>
00083   class to<KURL> {
00084     KURL m;
00085   public:
00086     to( const QVariant & v ) {
00087       m.setPath( v.toString() );
00088     }
00089     operator KURL() const { return m; }
00090   };
00091 
00092   template <typename T>
00093   class to< QValueList<T> > {
00094     QValueList<T> m;
00095   public:
00096     to( const QVariant & v ) {
00097       const QValueList<QVariant> vl = v.toList();
00098       for ( QValueList<QVariant>::const_iterator it = vl.begin(), end = vl.end() ; it != end ; ++it )
00099         m.push_back( to<T>( *it ) );
00100     }
00101     operator QValueList<T> () const { return m; }
00102   };
00103 
00104   template <>
00105   class to<KURL::List> {
00106     KURL::List m;
00107   public:
00108     to( const QVariant & v ) {
00109       // wow, KURL::List is broken... it lacks conversion from and to QVL<KURL>...
00110       m += to< QValueList<KURL> >( v );
00111     }
00112     operator KURL::List() const { return m; }
00113   };
00114 
00115 
00116   // from<> is the demarshaller. See to<> for why this is a class...
00117 
00118   template <typename T>
00119   struct from_helper : public QVariant {
00120     from_helper( const T & t ) : QVariant( t ) {}
00121   };
00122 
00123   template <typename T>
00124   QVariant from( const T & t ) {
00125     return from_helper<T>( t );
00126   }
00127 
00128   // some special types:
00129   template <> struct from_helper<bool> : public QVariant {
00130     from_helper( bool b ) : QVariant( b, int() ) {}
00131   };
00132   template <> struct from_helper<KURL> : public QVariant {
00133     from_helper( const KURL & url ) : QVariant( url.path() ) {}
00134   };
00135   template <typename T> struct from_helper< QValueList<T> > : public QVariant {
00136     from_helper( const QValueList<T> & l ) {
00137       QValueList<QVariant> result;
00138       for ( typename QValueList<T>::const_iterator it = l.begin(), end = l.end() ; it != end ; ++it )
00139         result.push_back( from( *it ) );
00140       QVariant::operator=( result );
00141     }
00142   };
00143   template <> struct from_helper<KURL::List> : public from_helper< QValueList<KURL> > {
00144     from_helper( const KURL::List & l ) : from_helper< QValueList<KURL> >( l ) {}
00145   };
00146 
00147   class ChiasmusConfigEntry : public Kleo::CryptoConfigEntry {
00148     unsigned int mIdx;
00149     QVariant mValue;
00150     bool mDirty;
00151   public:
00152     ChiasmusConfigEntry( unsigned int i )
00153       : Kleo::CryptoConfigEntry(),
00154         mIdx( i ), mValue( defaultValue() ), mDirty( false )
00155     {
00156       assert( i < kleo_chiasmus_config_entries_dim );
00157     }
00158     QString name() const { return kleo_chiasmus_config_entries[mIdx].name; }
00159     QString description() const { return i18n( kleo_chiasmus_config_entries[mIdx].description ); }
00160     bool isOptional() const { return kleo_chiasmus_config_entries[mIdx].is_optional; }
00161     bool isList() const { return kleo_chiasmus_config_entries[mIdx].is_list; }
00162     bool isRuntime() const { return kleo_chiasmus_config_entries[mIdx].is_runtime; }
00163     Level level() const { return static_cast<Level>( kleo_chiasmus_config_entries[mIdx].level ); }
00164     ArgType argType() const { return static_cast<ArgType>( kleo_chiasmus_config_entries[mIdx].type ); }
00165     bool isSet() const { return mValue != defaultValue(); }
00166     bool boolValue() const { return mValue.toBool(); }
00167     QString stringValue() const { return mValue.toString(); }
00168     int intValue() const { return mValue.toInt(); }
00169     unsigned int uintValue() const { return mValue.toUInt(); }
00170     KURL urlValue() const {
00171       if ( argType() != ArgType_Path && argType() != ArgType_DirPath ) return KURL( mValue.toString() );
00172       KURL u; u.setPath( mValue.toString() ); return u;
00173     }
00174     unsigned int numberOfTimesSet() const { return 0; }
00175     QStringList stringValueList() const { return mValue.toStringList(); }
00176     QValueList<int> intValueList() const { return to< QValueList<int> >( mValue ); }
00177     QValueList<unsigned int> uintValueList() const { return to< QValueList<unsigned int> >( mValue ); }
00178     KURL::List urlValueList() const {
00179       if ( argType() != ArgType_Path && argType()!= ArgType_DirPath ) return mValue.toStringList();
00180       else return to<KURL::List>( mValue ); }
00181     void resetToDefault() { mValue = defaultValue(); mDirty = false; }
00182     void setBoolValue( bool value ) { setValue( QVariant( value, int() ) ); }
00183     void setStringValue( const QString & value ) { setValue( value ); }
00184     void setIntValue( int value ) { setValue( value ); }
00185     void setUIntValue( unsigned int value ) { setValue( value ); }
00186     void setURLValue( const KURL & value ) {
00187       if ( argType() != ArgType_Path && argType()!= ArgType_DirPath ) setValue( value.url() );
00188       else setValue( value.path() );
00189     }
00190     void setNumberOfTimesSet( unsigned int ) {}
00191     void setStringValueList( const QStringList & value ) { setValue( value ); }
00192     void setIntValueList( const QValueList<int> & l ) { setValue( from( l ) ); }
00193     void setUIntValueList( const QValueList<unsigned int> & l ) { setValue( from( l ) ); }
00194     void setURLValueList( const KURL::List & l ) { setValue( from( l ) ); }
00195     bool isDirty() const { return mDirty; }
00196 
00197     QVariant value() const { return mValue; }
00198 
00199     void sync( KConfigBase * config ) {
00200       if ( !mDirty )
00201         return;
00202       mDirty = false;
00203       config->writeEntry( kleo_chiasmus_config_entries[mIdx].name, mValue );
00204     }
00205     void read( const KConfigBase * config ) {
00206       mDirty = false;
00207       mValue = config->readPropertyEntry( kleo_chiasmus_config_entries[mIdx].name, defaultValue() );
00208     }
00209   private:
00210     QVariant defaultValue() const;
00211     void setValue( const QVariant & value ) { mValue = value; mDirty = true; }
00212   };
00213 
00214   QVariant ChiasmusConfigEntry::defaultValue() const {
00215     const kleo_chiasmus_config_data & data = kleo_chiasmus_config_entries[mIdx];
00216     switch ( data.type ) {
00217     default:
00218       return QVariant();
00219     case ArgType_None:
00220       if ( isList() )
00221         return QValueList<QVariant>() << QVariant( data.defaults.boolean.value, int() );
00222       else
00223         return QVariant( data.defaults.boolean.value, int() );
00224     case ArgType_String:
00225       if ( isList() )
00226         return QStringList( QString::fromLatin1( data.defaults.string ) );
00227       else
00228         return QString::fromLatin1( data.defaults.string );
00229     case ArgType_Int:
00230       if ( isList() )
00231         return QValueList<QVariant>() << data.defaults.integer;
00232       else
00233         return data.defaults.integer;
00234     case ArgType_UInt:
00235       if ( isList() )
00236         return QValueList<QVariant>() << data.defaults.unsigned_integer;
00237       else
00238         return data.defaults.unsigned_integer;
00239     case ArgType_Path:
00240     case ArgType_DirPath:
00241       if ( isList() )
00242         return QValueList<QVariant>() << QString::fromLatin1( data.defaults.path );
00243       else
00244         return QString::fromLatin1( data.defaults.path );
00245     case ArgType_URL:
00246     case ArgType_LDAPURL:
00247       if ( isList() )
00248         return QValueList<QVariant>() << QString::fromLatin1( data.defaults.url );
00249       else
00250         return QString::fromLatin1( data.defaults.url );
00251     }
00252   }
00253 
00254   class ChiasmusGeneralGroup : public Kleo::CryptoConfigGroup {
00255     mutable std::map<QString,ChiasmusConfigEntry*> mCache;
00256     mutable KConfig * mConfigObject;
00257   public:
00258     ChiasmusGeneralGroup() : Kleo::CryptoConfigGroup(), mConfigObject( 0 ) {}
00259     ~ChiasmusGeneralGroup() { clear(); delete mConfigObject; }
00260     QString name() const { return "General"; }
00261     QString iconName() const { return "chiasmus_chi"; }
00262     QString description() const { return i18n( "General" ); }
00263     Kleo::CryptoConfigEntry::Level level() const { return Kleo::CryptoConfigEntry::Level_Basic; }
00264     QStringList entryList() const {
00265       QStringList result;
00266       for ( unsigned int i = 0 ; i < kleo_chiasmus_config_entries_dim ; ++i )
00267         result.push_back( kleo_chiasmus_config_entries[i].name );
00268       return result;
00269     }
00270     Kleo::CryptoConfigEntry * entry( const QString & name ) const {
00271       if ( ChiasmusConfigEntry * entry = mCache[name] )
00272         return entry;
00273       const KConfigGroup group( configObject(), "Chiasmus" );
00274       for ( unsigned int i = 0 ; i < kleo_chiasmus_config_entries_dim ; ++i )
00275         if ( name == kleo_chiasmus_config_entries[i].name ) {
00276           ChiasmusConfigEntry * entry = new ChiasmusConfigEntry( i );
00277           entry->read( &group );
00278           return mCache[name] = entry;
00279         }
00280       return 0;
00281     }
00282 
00283     void sync() {
00284       KConfigGroup group( configObject(), "Chiasmus" );
00285       for ( std::map<QString,ChiasmusConfigEntry*>::const_iterator it = mCache.begin(), end = mCache.end() ; it != end ; ++it )
00286         it->second->sync( &group );
00287       group.sync();
00288       clear();
00289     }
00290   private:
00291     KConfig * configObject() const {
00292       if ( !mConfigObject )
00293         // this is unsafe. We're a lib, used by concurrent apps.
00294         mConfigObject = new KConfig( "chiasmusbackendrc" );
00295       return mConfigObject;
00296     }
00297     void clear() {
00298       for ( std::map<QString,ChiasmusConfigEntry*>::const_iterator it = mCache.begin(), end = mCache.end() ; it != end ; ++it )
00299         delete it->second;
00300       mCache.clear();
00301     }
00302   };
00303 
00304   class ChiasmusComponent : public Kleo::CryptoConfigComponent {
00305     mutable ChiasmusGeneralGroup * mGeneralGroup;
00306   public:
00307     ChiasmusComponent() : Kleo::CryptoConfigComponent(), mGeneralGroup( 0 ) {}
00308     ~ChiasmusComponent() { delete mGeneralGroup; }
00309 
00310     void sync() {
00311       if ( mGeneralGroup )
00312         mGeneralGroup->sync();
00313     }
00314 
00315     QString name() const { return "Chiasmus"; }
00316     QString iconName() const { return "chiasmus_chi"; }
00317     QString description() const { return i18n( "Chiasmus" ); }
00318     QStringList groupList() const { return QStringList() << "General"; }
00319     Kleo::CryptoConfigGroup * group( const QString & name ) const {
00320       if ( name != "General" )
00321         return 0;
00322       if ( !mGeneralGroup )
00323         mGeneralGroup = new ChiasmusGeneralGroup();
00324       return mGeneralGroup;
00325     }
00326   };
00327 
00328 }
00329 
00330 class Kleo::ChiasmusBackend::CryptoConfig : public Kleo::CryptoConfig {
00331   mutable ChiasmusComponent * mComponent;
00332 public:
00333   CryptoConfig() : Kleo::CryptoConfig(), mComponent( 0 ) {}
00334   ~CryptoConfig() { delete mComponent; }
00335 
00336   QStringList componentList() const { return QStringList() << "Chiasmus" ; }
00337   ChiasmusComponent * component( const QString & name ) const {
00338     if ( name != "Chiasmus" )
00339       return 0;
00340     if ( !mComponent )
00341       mComponent = new ChiasmusComponent();
00342     return mComponent;
00343   }
00344   void sync( bool ) {
00345     if ( mComponent )
00346       mComponent->sync();
00347   }
00348   void clear() { delete mComponent; mComponent = 0; }
00349 };
00350 
00351 class Kleo::ChiasmusBackend::Protocol : public Kleo::CryptoBackend::Protocol {
00352   Kleo::CryptoConfig * mCryptoConfig;
00353 public:
00354   Protocol( Kleo::CryptoConfig * config )
00355     : Kleo::CryptoBackend::Protocol(), mCryptoConfig( config )
00356   {
00357     assert( config );
00358   }
00359   ~Protocol() {}
00360 
00361   QString name() const { return "Chiasmus"; }
00362   QString displayName() const { return i18n( "Chiasmus command line tool" ); }
00363   KeyListJob * keyListJob( bool, bool, bool ) const { return 0; }
00364   EncryptJob * encryptJob( bool, bool ) const { return 0; }
00365   DecryptJob * decryptJob() const { return 0; }
00366   SignJob * signJob( bool, bool ) const { return 0; }
00367   VerifyDetachedJob * verifyDetachedJob( bool ) const { return 0; }
00368   VerifyOpaqueJob * verifyOpaqueJob( bool ) const { return 0; }
00369   KeyGenerationJob * keyGenerationJob() const { return 0; }
00370   ImportJob * importJob() const { return 0; }
00371   ExportJob * publicKeyExportJob( bool ) const { return 0; }
00372   ExportJob * secretKeyExportJob( bool ) const { return 0; }
00373   DownloadJob * downloadJob( bool ) const { return 0; }
00374   DeleteJob * deleteJob() const { return 0; }
00375   SignEncryptJob * signEncryptJob( bool, bool ) const { return 0; }
00376   DecryptVerifyJob * decryptVerifyJob( bool ) const { return 0; }
00377   RefreshKeysJob * refreshKeysJob() const { return 0; }
00378 
00379   SpecialJob * specialJob( const char * type, const QMap<QString,QVariant> & args ) const {
00380     if ( qstricmp( type, "x-obtain-keys" ) == 0 && args.size() == 0 )
00381       return new ObtainKeysJob();
00382     if ( qstricmp( type, "x-encrypt" ) == 0 && args.size() == 0 )
00383       return new ChiasmusJob( ChiasmusJob::Encrypt );
00384     if ( qstricmp( type, "x-decrypt" ) == 0 && args.size() == 0 )
00385       return new ChiasmusJob( ChiasmusJob::Decrypt );
00386     kdDebug(5150) << "ChiasmusBackend::Protocol: tried to instantiate unknown job type \""
00387                   << type << "\"" << endl;
00388 
00389     return 0;
00390   }
00391 };
00392 
00393 Kleo::ChiasmusBackend * Kleo::ChiasmusBackend::self = 0;
00394 
00395 Kleo::ChiasmusBackend::ChiasmusBackend()
00396   : Kleo::CryptoBackend(),
00397     mCryptoConfig( 0 ),
00398     mProtocol( 0 )
00399 {
00400   self = this;
00401 }
00402 
00403 Kleo::ChiasmusBackend::~ChiasmusBackend() {
00404   self = 0;
00405   delete mCryptoConfig;
00406   delete mProtocol;
00407 }
00408 
00409 QString Kleo::ChiasmusBackend::name() const {
00410   return "Chiasmus";
00411 }
00412 
00413 QString Kleo::ChiasmusBackend::displayName() const {
00414   return i18n( "Chiasmus" );
00415 }
00416 
00417 Kleo::CryptoConfig * Kleo::ChiasmusBackend::config() const {
00418   if ( !mCryptoConfig )
00419     mCryptoConfig = new CryptoConfig();
00420   return mCryptoConfig;
00421 }
00422 
00423 Kleo::CryptoBackend::Protocol * Kleo::ChiasmusBackend::protocol( const char * name ) const {
00424   if ( qstricmp( name, "Chiasmus" ) != 0 )
00425     return 0;
00426   if ( !mProtocol )
00427     if ( checkForChiasmus() )
00428       mProtocol = new Protocol( config() );
00429   return mProtocol;
00430 }
00431 
00432 bool Kleo::ChiasmusBackend::checkForOpenPGP( QString * reason ) const {
00433   if ( reason )
00434     *reason = i18n( "Unsupported protocol \"%1\"" ).arg( "OpenPGP" );
00435   return false;
00436 }
00437 
00438 bool Kleo::ChiasmusBackend::checkForSMIME( QString * reason ) const {
00439   if ( reason )
00440     *reason = i18n( "Unsupported protocol \"%1\"" ).arg( "SMIME" );
00441   return false;
00442 }
00443 
00444 bool Kleo::ChiasmusBackend::checkForChiasmus( QString * reason ) const {
00445 
00446   // kills the protocol instance when we return false:
00447   std::auto_ptr<Protocol> tmp( mProtocol );
00448   mProtocol = 0;
00449 
00450   const CryptoConfigEntry * path = config()->entry( "Chiasmus", "General", "path" );
00451   assert( path ); assert( path->argType() == CryptoConfigEntry::ArgType_Path );
00452   const QString chiasmus = path->urlValue().path();
00453   const QFileInfo fi( KShell::tildeExpand( chiasmus ) );
00454   if ( !fi.isExecutable() ) {
00455     if ( reason )
00456       *reason = i18n( "File \"%1\" does not exist or is not executable." ).arg( chiasmus );
00457     return false;
00458   }
00459 
00460   // FIXME: more checks?
00461   mProtocol = tmp.release();
00462   return true;
00463 }
00464 
00465 bool Kleo::ChiasmusBackend::checkForProtocol( const char * name, QString * reason ) const {
00466   if ( qstricmp( name, "Chiasmus" ) == 0 )
00467     return checkForChiasmus( reason );
00468   if ( reason )
00469     *reason = i18n( "Unsupported protocol \"%1\"" ).arg( name );
00470   return 0;
00471 }
00472 
00473 bool Kleo::ChiasmusBackend::supportsProtocol( const char * name ) const {
00474   return qstricmp( name, "Chiasmus" ) == 0;
00475 }
00476 
00477 const char * Kleo::ChiasmusBackend::enumerateProtocols( int i ) const {
00478   return i == 0 ? "Chiasmus" : 0 ;
00479 }
KDE Home | KDE Accessibility Home | Description of Access Keys