00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
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
00063
00064
00065
00066
00067
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
00110 m += to< QValueList<KURL> >( v );
00111 }
00112 operator KURL::List() const { return m; }
00113 };
00114
00115
00116
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
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
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
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
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 }