diff options
Diffstat (limited to 'certmanager/lib/backends/chiasmus/chiasmusbackend.cpp')
-rw-r--r-- | certmanager/lib/backends/chiasmus/chiasmusbackend.cpp | 480 |
1 files changed, 480 insertions, 0 deletions
diff --git a/certmanager/lib/backends/chiasmus/chiasmusbackend.cpp b/certmanager/lib/backends/chiasmus/chiasmusbackend.cpp new file mode 100644 index 000000000..15a63de53 --- /dev/null +++ b/certmanager/lib/backends/chiasmus/chiasmusbackend.cpp @@ -0,0 +1,480 @@ +/* + chiasmusbackend.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2005 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "chiasmusbackend.h" + +#include "config_data.h" +#include "obtainkeysjob.h" +#include "chiasmusjob.h" + +#include "kleo/cryptoconfig.h" + +#include <klocale.h> +#include <kconfig.h> +#include <kshell.h> +#include <kdebug.h> + +#include <qstringlist.h> +#include <qvariant.h> +#include <qfileinfo.h> + +#include <map> +#include <memory> + +#include <cassert> + +namespace { + + // + // The usual QVariant template helpers: + // + + // to<> is a demarshaller. It's a class b/c you can't partially + // specialise function templates yet. However, to<> can be used as if + // it was a function: QString s = to<QString>( myVariant ); + template <typename T> class to {}; + +#define MAKE_TO( type, func ) \ + template <> \ + class to< type > { \ + type m; \ + public: \ + to( const QVariant & v ) : m( v.func() ) {} \ + operator type() const { return m; } \ + } + + MAKE_TO( int, toInt ); + MAKE_TO( unsigned int, toUInt ); + + template <> + class to<KURL> { + KURL m; + public: + to( const QVariant & v ) { + m.setPath( v.toString() ); + } + operator KURL() const { return m; } + }; + + template <typename T> + class to< QValueList<T> > { + QValueList<T> m; + public: + to( const QVariant & v ) { + const QValueList<QVariant> vl = v.toList(); + for ( QValueList<QVariant>::const_iterator it = vl.begin(), end = vl.end() ; it != end ; ++it ) + m.push_back( to<T>( *it ) ); + } + operator QValueList<T> () const { return m; } + }; + + template <> + class to<KURL::List> { + KURL::List m; + public: + to( const QVariant & v ) { + // wow, KURL::List is broken... it lacks conversion from and to QVL<KURL>... + m += to< QValueList<KURL> >( v ); + } + operator KURL::List() const { return m; } + }; + + + // from<> is the demarshaller. See to<> for why this is a class... + + template <typename T> + struct from_helper : public QVariant { + from_helper( const T & t ) : QVariant( t ) {} + }; + + template <typename T> + QVariant from( const T & t ) { + return from_helper<T>( t ); + } + + // some special types: + template <> struct from_helper<bool> : public QVariant { + from_helper( bool b ) : QVariant( b, int() ) {} + }; + template <> struct from_helper<KURL> : public QVariant { + from_helper( const KURL & url ) : QVariant( url.path() ) {} + }; + template <typename T> struct from_helper< QValueList<T> > : public QVariant { + from_helper( const QValueList<T> & l ) { + QValueList<QVariant> result; + for ( typename QValueList<T>::const_iterator it = l.begin(), end = l.end() ; it != end ; ++it ) + result.push_back( from( *it ) ); + QVariant::operator=( result ); + } + }; + template <> struct from_helper<KURL::List> : public from_helper< QValueList<KURL> > { + from_helper( const KURL::List & l ) : from_helper< QValueList<KURL> >( l ) {} + }; + + class ChiasmusConfigEntry : public Kleo::CryptoConfigEntry { + unsigned int mIdx; + QVariant mValue; + bool mDirty; + public: + ChiasmusConfigEntry( unsigned int i ) + : Kleo::CryptoConfigEntry(), + mIdx( i ), mValue( defaultValue() ), mDirty( false ) + { + assert( i < kleo_chiasmus_config_entries_dim ); + } + QString name() const { return kleo_chiasmus_config_entries[mIdx].name; } + QString description() const { return i18n( kleo_chiasmus_config_entries[mIdx].description ); } + bool isOptional() const { return kleo_chiasmus_config_entries[mIdx].is_optional; } + bool isReadOnly() const { return false; } + bool isList() const { return kleo_chiasmus_config_entries[mIdx].is_list; } + bool isRuntime() const { return kleo_chiasmus_config_entries[mIdx].is_runtime; } + Level level() const { return static_cast<Level>( kleo_chiasmus_config_entries[mIdx].level ); } + ArgType argType() const { return static_cast<ArgType>( kleo_chiasmus_config_entries[mIdx].type ); } + bool isSet() const { return mValue != defaultValue(); } + bool boolValue() const { return mValue.toBool(); } + QString stringValue() const { return mValue.toString(); } + int intValue() const { return mValue.toInt(); } + unsigned int uintValue() const { return mValue.toUInt(); } + KURL urlValue() const { + if ( argType() != ArgType_Path && argType() != ArgType_DirPath ) return KURL( mValue.toString() ); + KURL u; u.setPath( mValue.toString() ); return u; + } + unsigned int numberOfTimesSet() const { return 0; } + QStringList stringValueList() const { return mValue.toStringList(); } + QValueList<int> intValueList() const { return to< QValueList<int> >( mValue ); } + QValueList<unsigned int> uintValueList() const { return to< QValueList<unsigned int> >( mValue ); } + KURL::List urlValueList() const { + if ( argType() != ArgType_Path && argType()!= ArgType_DirPath ) return mValue.toStringList(); + else return to<KURL::List>( mValue ); } + void resetToDefault() { mValue = defaultValue(); mDirty = false; } + void setBoolValue( bool value ) { setValue( QVariant( value, int() ) ); } + void setStringValue( const QString & value ) { setValue( value ); } + void setIntValue( int value ) { setValue( value ); } + void setUIntValue( unsigned int value ) { setValue( value ); } + void setURLValue( const KURL & value ) { + if ( argType() != ArgType_Path && argType()!= ArgType_DirPath ) setValue( value.url() ); + else setValue( value.path() ); + } + void setNumberOfTimesSet( unsigned int ) {} + void setStringValueList( const QStringList & value ) { setValue( value ); } + void setIntValueList( const QValueList<int> & l ) { setValue( from( l ) ); } + void setUIntValueList( const QValueList<unsigned int> & l ) { setValue( from( l ) ); } + void setURLValueList( const KURL::List & l ) { setValue( from( l ) ); } + bool isDirty() const { return mDirty; } + + QVariant value() const { return mValue; } + + void sync( KConfigBase * config ) { + if ( !mDirty ) + return; + mDirty = false; + config->writeEntry( kleo_chiasmus_config_entries[mIdx].name, mValue ); + } + void read( const KConfigBase * config ) { + mDirty = false; + mValue = config->readPropertyEntry( kleo_chiasmus_config_entries[mIdx].name, defaultValue() ); + } + private: + QVariant defaultValue() const; + void setValue( const QVariant & value ) { mValue = value; mDirty = true; } + }; + + QVariant ChiasmusConfigEntry::defaultValue() const { + const kleo_chiasmus_config_data & data = kleo_chiasmus_config_entries[mIdx]; + switch ( data.type ) { + default: + return QVariant(); + case ArgType_None: + if ( isList() ) + return QValueList<QVariant>() << QVariant( data.defaults.boolean.value, int() ); + else + return QVariant( data.defaults.boolean.value, int() ); + case ArgType_String: + if ( isList() ) + return QStringList( QString::fromLatin1( data.defaults.string ) ); + else + return QString::fromLatin1( data.defaults.string ); + case ArgType_Int: + if ( isList() ) + return QValueList<QVariant>() << data.defaults.integer; + else + return data.defaults.integer; + case ArgType_UInt: + if ( isList() ) + return QValueList<QVariant>() << data.defaults.unsigned_integer; + else + return data.defaults.unsigned_integer; + case ArgType_Path: + case ArgType_DirPath: + if ( isList() ) + return QValueList<QVariant>() << QString::fromLatin1( data.defaults.path ); + else + return QString::fromLatin1( data.defaults.path ); + case ArgType_URL: + case ArgType_LDAPURL: + if ( isList() ) + return QValueList<QVariant>() << QString::fromLatin1( data.defaults.url ); + else + return QString::fromLatin1( data.defaults.url ); + } + } + + class ChiasmusGeneralGroup : public Kleo::CryptoConfigGroup { + mutable std::map<QString,ChiasmusConfigEntry*> mCache; + mutable KConfig * mConfigObject; + public: + ChiasmusGeneralGroup() : Kleo::CryptoConfigGroup(), mConfigObject( 0 ) {} + ~ChiasmusGeneralGroup() { clear(); delete mConfigObject; } + QString name() const { return "General"; } + QString iconName() const { return "chiasmus_chi"; } + QString description() const { return i18n( "General" ); } + Kleo::CryptoConfigEntry::Level level() const { return Kleo::CryptoConfigEntry::Level_Basic; } + QStringList entryList() const { + QStringList result; + for ( unsigned int i = 0 ; i < kleo_chiasmus_config_entries_dim ; ++i ) + result.push_back( kleo_chiasmus_config_entries[i].name ); + return result; + } + Kleo::CryptoConfigEntry * entry( const QString & name ) const { + if ( ChiasmusConfigEntry * entry = mCache[name] ) + return entry; + const KConfigGroup group( configObject(), "Chiasmus" ); + for ( unsigned int i = 0 ; i < kleo_chiasmus_config_entries_dim ; ++i ) + if ( name == kleo_chiasmus_config_entries[i].name ) { + ChiasmusConfigEntry * entry = new ChiasmusConfigEntry( i ); + entry->read( &group ); + return mCache[name] = entry; + } + return 0; + } + + void sync() { + KConfigGroup group( configObject(), "Chiasmus" ); + for ( std::map<QString,ChiasmusConfigEntry*>::const_iterator it = mCache.begin(), end = mCache.end() ; it != end ; ++it ) + it->second->sync( &group ); + group.sync(); + clear(); + } + private: + KConfig * configObject() const { + if ( !mConfigObject ) + // this is unsafe. We're a lib, used by concurrent apps. + mConfigObject = new KConfig( "chiasmusbackendrc" ); + return mConfigObject; + } + void clear() { + for ( std::map<QString,ChiasmusConfigEntry*>::const_iterator it = mCache.begin(), end = mCache.end() ; it != end ; ++it ) + delete it->second; + mCache.clear(); + } + }; + + class ChiasmusComponent : public Kleo::CryptoConfigComponent { + mutable ChiasmusGeneralGroup * mGeneralGroup; + public: + ChiasmusComponent() : Kleo::CryptoConfigComponent(), mGeneralGroup( 0 ) {} + ~ChiasmusComponent() { delete mGeneralGroup; } + + void sync() { + if ( mGeneralGroup ) + mGeneralGroup->sync(); + } + + QString name() const { return "Chiasmus"; } + QString iconName() const { return "chiasmus_chi"; } + QString description() const { return i18n( "Chiasmus" ); } + QStringList groupList() const { return QStringList() << "General"; } + Kleo::CryptoConfigGroup * group( const QString & name ) const { + if ( name != "General" ) + return 0; + if ( !mGeneralGroup ) + mGeneralGroup = new ChiasmusGeneralGroup(); + return mGeneralGroup; + } + }; + +} + +class Kleo::ChiasmusBackend::CryptoConfig : public Kleo::CryptoConfig { + mutable ChiasmusComponent * mComponent; +public: + CryptoConfig() : Kleo::CryptoConfig(), mComponent( 0 ) {} + ~CryptoConfig() { delete mComponent; } + + QStringList componentList() const { return QStringList() << "Chiasmus" ; } + ChiasmusComponent * component( const QString & name ) const { + if ( name != "Chiasmus" ) + return 0; + if ( !mComponent ) + mComponent = new ChiasmusComponent(); + return mComponent; + } + void sync( bool ) { + if ( mComponent ) + mComponent->sync(); + } + void clear() { delete mComponent; mComponent = 0; } +}; + +class Kleo::ChiasmusBackend::Protocol : public Kleo::CryptoBackend::Protocol { + Kleo::CryptoConfig * mCryptoConfig; +public: + Protocol( Kleo::CryptoConfig * config ) + : Kleo::CryptoBackend::Protocol(), mCryptoConfig( config ) + { + assert( config ); + } + ~Protocol() {} + + QString name() const { return "Chiasmus"; } + QString displayName() const { return i18n( "Chiasmus command line tool" ); } + KeyListJob * keyListJob( bool, bool, bool ) const { return 0; } + EncryptJob * encryptJob( bool, bool ) const { return 0; } + DecryptJob * decryptJob() const { return 0; } + SignJob * signJob( bool, bool ) const { return 0; } + VerifyDetachedJob * verifyDetachedJob( bool ) const { return 0; } + VerifyOpaqueJob * verifyOpaqueJob( bool ) const { return 0; } + KeyGenerationJob * keyGenerationJob() const { return 0; } + ImportJob * importJob() const { return 0; } + ExportJob * publicKeyExportJob( bool ) const { return 0; } + ExportJob * secretKeyExportJob( bool, const QString& ) const { return 0; } + DownloadJob * downloadJob( bool ) const { return 0; } + DeleteJob * deleteJob() const { return 0; } + SignEncryptJob * signEncryptJob( bool, bool ) const { return 0; } + DecryptVerifyJob * decryptVerifyJob( bool ) const { return 0; } + RefreshKeysJob * refreshKeysJob() const { return 0; } + + SpecialJob * specialJob( const char * type, const QMap<QString,QVariant> & args ) const { + if ( qstricmp( type, "x-obtain-keys" ) == 0 && args.size() == 0 ) + return new ObtainKeysJob(); + if ( qstricmp( type, "x-encrypt" ) == 0 && args.size() == 0 ) + return new ChiasmusJob( ChiasmusJob::Encrypt ); + if ( qstricmp( type, "x-decrypt" ) == 0 && args.size() == 0 ) + return new ChiasmusJob( ChiasmusJob::Decrypt ); + kdDebug(5150) << "ChiasmusBackend::Protocol: tried to instantiate unknown job type \"" + << type << "\"" << endl; + + return 0; + } +}; + +Kleo::ChiasmusBackend * Kleo::ChiasmusBackend::self = 0; + +Kleo::ChiasmusBackend::ChiasmusBackend() + : Kleo::CryptoBackend(), + mCryptoConfig( 0 ), + mProtocol( 0 ) +{ + self = this; +} + +Kleo::ChiasmusBackend::~ChiasmusBackend() { + self = 0; + delete mCryptoConfig; + delete mProtocol; +} + +QString Kleo::ChiasmusBackend::name() const { + return "Chiasmus"; +} + +QString Kleo::ChiasmusBackend::displayName() const { + return i18n( "Chiasmus" ); +} + +Kleo::CryptoConfig * Kleo::ChiasmusBackend::config() const { + if ( !mCryptoConfig ) + mCryptoConfig = new CryptoConfig(); + return mCryptoConfig; +} + +Kleo::CryptoBackend::Protocol * Kleo::ChiasmusBackend::protocol( const char * name ) const { + if ( qstricmp( name, "Chiasmus" ) != 0 ) + return 0; + if ( !mProtocol ) + if ( checkForChiasmus() ) + mProtocol = new Protocol( config() ); + return mProtocol; +} + +bool Kleo::ChiasmusBackend::checkForOpenPGP( QString * reason ) const { + if ( reason ) + *reason = i18n( "Unsupported protocol \"%1\"" ).arg( "OpenPGP" ); + return false; +} + +bool Kleo::ChiasmusBackend::checkForSMIME( QString * reason ) const { + if ( reason ) + *reason = i18n( "Unsupported protocol \"%1\"" ).arg( "SMIME" ); + return false; +} + +bool Kleo::ChiasmusBackend::checkForChiasmus( QString * reason ) const { + + // kills the protocol instance when we return false: + std::auto_ptr<Protocol> tmp( mProtocol ); + mProtocol = 0; + + const CryptoConfigEntry * path = config()->entry( "Chiasmus", "General", "path" ); + assert( path ); assert( path->argType() == CryptoConfigEntry::ArgType_Path ); + const QString chiasmus = path->urlValue().path(); + const QFileInfo fi( KShell::tildeExpand( chiasmus ) ); + if ( !fi.isExecutable() ) { + if ( reason ) + *reason = i18n( "File \"%1\" does not exist or is not executable." ).arg( chiasmus ); + return false; + } + + // FIXME: more checks? + mProtocol = tmp.release(); + return true; +} + +bool Kleo::ChiasmusBackend::checkForProtocol( const char * name, QString * reason ) const { + if ( qstricmp( name, "Chiasmus" ) == 0 ) + return checkForChiasmus( reason ); + if ( reason ) + *reason = i18n( "Unsupported protocol \"%1\"" ).arg( name ); + return 0; +} + +bool Kleo::ChiasmusBackend::supportsProtocol( const char * name ) const { + return qstricmp( name, "Chiasmus" ) == 0; +} + +const char * Kleo::ChiasmusBackend::enumerateProtocols( int i ) const { + return i == 0 ? "Chiasmus" : 0 ; +} |