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 isReadOnly() const { return false; }
00162 bool isList() const { return kleo_chiasmus_config_entries[mIdx].is_list; }
00163 bool isRuntime() const { return kleo_chiasmus_config_entries[mIdx].is_runtime; }
00164 Level level() const { return static_cast<Level>( kleo_chiasmus_config_entries[mIdx].level ); }
00165 ArgType argType() const { return static_cast<ArgType>( kleo_chiasmus_config_entries[mIdx].type ); }
00166 bool isSet() const { return mValue != defaultValue(); }
00167 bool boolValue() const { return mValue.toBool(); }
00168 QString stringValue() const { return mValue.toString(); }
00169 int intValue() const { return mValue.toInt(); }
00170 unsigned int uintValue() const { return mValue.toUInt(); }
00171 KURL urlValue() const {
00172 if ( argType() != ArgType_Path && argType() != ArgType_DirPath ) return KURL( mValue.toString() );
00173 KURL u; u.setPath( mValue.toString() ); return u;
00174 }
00175 unsigned int numberOfTimesSet() const { return 0; }
00176 QStringList stringValueList() const { return mValue.toStringList(); }
00177 QValueList<int> intValueList() const { return to< QValueList<int> >( mValue ); }
00178 QValueList<unsigned int> uintValueList() const { return to< QValueList<unsigned int> >( mValue ); }
00179 KURL::List urlValueList() const {
00180 if ( argType() != ArgType_Path && argType()!= ArgType_DirPath ) return mValue.toStringList();
00181 else return to<KURL::List>( mValue ); }
00182 void resetToDefault() { mValue = defaultValue(); mDirty = false; }
00183 void setBoolValue( bool value ) { setValue( QVariant( value, int() ) ); }
00184 void setStringValue( const QString & value ) { setValue( value ); }
00185 void setIntValue( int value ) { setValue( value ); }
00186 void setUIntValue( unsigned int value ) { setValue( value ); }
00187 void setURLValue( const KURL & value ) {
00188 if ( argType() != ArgType_Path && argType()!= ArgType_DirPath ) setValue( value.url() );
00189 else setValue( value.path() );
00190 }
00191 void setNumberOfTimesSet( unsigned int ) {}
00192 void setStringValueList( const QStringList & value ) { setValue( value ); }
00193 void setIntValueList( const QValueList<int> & l ) { setValue( from( l ) ); }
00194 void setUIntValueList( const QValueList<unsigned int> & l ) { setValue( from( l ) ); }
00195 void setURLValueList( const KURL::List & l ) { setValue( from( l ) ); }
00196 bool isDirty() const { return mDirty; }
00197
00198 QVariant value() const { return mValue; }
00199
00200 void sync( KConfigBase * config ) {
00201 if ( !mDirty )
00202 return;
00203 mDirty = false;
00204 config->writeEntry( kleo_chiasmus_config_entries[mIdx].name, mValue );
00205 }
00206 void read( const KConfigBase * config ) {
00207 mDirty = false;
00208 mValue = config->readPropertyEntry( kleo_chiasmus_config_entries[mIdx].name, defaultValue() );
00209 }
00210 private:
00211 QVariant defaultValue() const;
00212 void setValue( const QVariant & value ) { mValue = value; mDirty = true; }
00213 };
00214
00215 QVariant ChiasmusConfigEntry::defaultValue() const {
00216 const kleo_chiasmus_config_data & data = kleo_chiasmus_config_entries[mIdx];
00217 switch ( data.type ) {
00218 default:
00219 return QVariant();
00220 case ArgType_None:
00221 if ( isList() )
00222 return QValueList<QVariant>() << QVariant( data.defaults.boolean.value, int() );
00223 else
00224 return QVariant( data.defaults.boolean.value, int() );
00225 case ArgType_String:
00226 if ( isList() )
00227 return QStringList( QString::fromLatin1( data.defaults.string ) );
00228 else
00229 return QString::fromLatin1( data.defaults.string );
00230 case ArgType_Int:
00231 if ( isList() )
00232 return QValueList<QVariant>() << data.defaults.integer;
00233 else
00234 return data.defaults.integer;
00235 case ArgType_UInt:
00236 if ( isList() )
00237 return QValueList<QVariant>() << data.defaults.unsigned_integer;
00238 else
00239 return data.defaults.unsigned_integer;
00240 case ArgType_Path:
00241 case ArgType_DirPath:
00242 if ( isList() )
00243 return QValueList<QVariant>() << QString::fromLatin1( data.defaults.path );
00244 else
00245 return QString::fromLatin1( data.defaults.path );
00246 case ArgType_URL:
00247 case ArgType_LDAPURL:
00248 if ( isList() )
00249 return QValueList<QVariant>() << QString::fromLatin1( data.defaults.url );
00250 else
00251 return QString::fromLatin1( data.defaults.url );
00252 }
00253 }
00254
00255 class ChiasmusGeneralGroup : public Kleo::CryptoConfigGroup {
00256 mutable std::map<QString,ChiasmusConfigEntry*> mCache;
00257 mutable KConfig * mConfigObject;
00258 public:
00259 ChiasmusGeneralGroup() : Kleo::CryptoConfigGroup(), mConfigObject( 0 ) {}
00260 ~ChiasmusGeneralGroup() { clear(); delete mConfigObject; }
00261 QString name() const { return "General"; }
00262 QString iconName() const { return "chiasmus_chi"; }
00263 QString description() const { return i18n( "General" ); }
00264 Kleo::CryptoConfigEntry::Level level() const { return Kleo::CryptoConfigEntry::Level_Basic; }
00265 QStringList entryList() const {
00266 QStringList result;
00267 for ( unsigned int i = 0 ; i < kleo_chiasmus_config_entries_dim ; ++i )
00268 result.push_back( kleo_chiasmus_config_entries[i].name );
00269 return result;
00270 }
00271 Kleo::CryptoConfigEntry * entry( const QString & name ) const {
00272 if ( ChiasmusConfigEntry * entry = mCache[name] )
00273 return entry;
00274 const KConfigGroup group( configObject(), "Chiasmus" );
00275 for ( unsigned int i = 0 ; i < kleo_chiasmus_config_entries_dim ; ++i )
00276 if ( name == kleo_chiasmus_config_entries[i].name ) {
00277 ChiasmusConfigEntry * entry = new ChiasmusConfigEntry( i );
00278 entry->read( &group );
00279 return mCache[name] = entry;
00280 }
00281 return 0;
00282 }
00283
00284 void sync() {
00285 KConfigGroup group( configObject(), "Chiasmus" );
00286 for ( std::map<QString,ChiasmusConfigEntry*>::const_iterator it = mCache.begin(), end = mCache.end() ; it != end ; ++it )
00287 it->second->sync( &group );
00288 group.sync();
00289 clear();
00290 }
00291 private:
00292 KConfig * configObject() const {
00293 if ( !mConfigObject )
00294
00295 mConfigObject = new KConfig( "chiasmusbackendrc" );
00296 return mConfigObject;
00297 }
00298 void clear() {
00299 for ( std::map<QString,ChiasmusConfigEntry*>::const_iterator it = mCache.begin(), end = mCache.end() ; it != end ; ++it )
00300 delete it->second;
00301 mCache.clear();
00302 }
00303 };
00304
00305 class ChiasmusComponent : public Kleo::CryptoConfigComponent {
00306 mutable ChiasmusGeneralGroup * mGeneralGroup;
00307 public:
00308 ChiasmusComponent() : Kleo::CryptoConfigComponent(), mGeneralGroup( 0 ) {}
00309 ~ChiasmusComponent() { delete mGeneralGroup; }
00310
00311 void sync() {
00312 if ( mGeneralGroup )
00313 mGeneralGroup->sync();
00314 }
00315
00316 QString name() const { return "Chiasmus"; }
00317 QString iconName() const { return "chiasmus_chi"; }
00318 QString description() const { return i18n( "Chiasmus" ); }
00319 QStringList groupList() const { return QStringList() << "General"; }
00320 Kleo::CryptoConfigGroup * group( const QString & name ) const {
00321 if ( name != "General" )
00322 return 0;
00323 if ( !mGeneralGroup )
00324 mGeneralGroup = new ChiasmusGeneralGroup();
00325 return mGeneralGroup;
00326 }
00327 };
00328
00329 }
00330
00331 class Kleo::ChiasmusBackend::CryptoConfig : public Kleo::CryptoConfig {
00332 mutable ChiasmusComponent * mComponent;
00333 public:
00334 CryptoConfig() : Kleo::CryptoConfig(), mComponent( 0 ) {}
00335 ~CryptoConfig() { delete mComponent; }
00336
00337 QStringList componentList() const { return QStringList() << "Chiasmus" ; }
00338 ChiasmusComponent * component( const QString & name ) const {
00339 if ( name != "Chiasmus" )
00340 return 0;
00341 if ( !mComponent )
00342 mComponent = new ChiasmusComponent();
00343 return mComponent;
00344 }
00345 void sync( bool ) {
00346 if ( mComponent )
00347 mComponent->sync();
00348 }
00349 void clear() { delete mComponent; mComponent = 0; }
00350 };
00351
00352 class Kleo::ChiasmusBackend::Protocol : public Kleo::CryptoBackend::Protocol {
00353 Kleo::CryptoConfig * mCryptoConfig;
00354 public:
00355 Protocol( Kleo::CryptoConfig * config )
00356 : Kleo::CryptoBackend::Protocol(), mCryptoConfig( config )
00357 {
00358 assert( config );
00359 }
00360 ~Protocol() {}
00361
00362 QString name() const { return "Chiasmus"; }
00363 QString displayName() const { return i18n( "Chiasmus command line tool" ); }
00364 KeyListJob * keyListJob( bool, bool, bool ) const { return 0; }
00365 EncryptJob * encryptJob( bool, bool ) const { return 0; }
00366 DecryptJob * decryptJob() const { return 0; }
00367 SignJob * signJob( bool, bool ) const { return 0; }
00368 VerifyDetachedJob * verifyDetachedJob( bool ) const { return 0; }
00369 VerifyOpaqueJob * verifyOpaqueJob( bool ) const { return 0; }
00370 KeyGenerationJob * keyGenerationJob() const { return 0; }
00371 ImportJob * importJob() const { return 0; }
00372 ExportJob * publicKeyExportJob( bool ) const { return 0; }
00373 ExportJob * secretKeyExportJob( bool, const QString& ) const { return 0; }
00374 DownloadJob * downloadJob( bool ) const { return 0; }
00375 DeleteJob * deleteJob() const { return 0; }
00376 SignEncryptJob * signEncryptJob( bool, bool ) const { return 0; }
00377 DecryptVerifyJob * decryptVerifyJob( bool ) const { return 0; }
00378 RefreshKeysJob * refreshKeysJob() const { return 0; }
00379
00380 SpecialJob * specialJob( const char * type, const QMap<QString,QVariant> & args ) const {
00381 if ( qstricmp( type, "x-obtain-keys" ) == 0 && args.size() == 0 )
00382 return new ObtainKeysJob();
00383 if ( qstricmp( type, "x-encrypt" ) == 0 && args.size() == 0 )
00384 return new ChiasmusJob( ChiasmusJob::Encrypt );
00385 if ( qstricmp( type, "x-decrypt" ) == 0 && args.size() == 0 )
00386 return new ChiasmusJob( ChiasmusJob::Decrypt );
00387 kdDebug(5150) << "ChiasmusBackend::Protocol: tried to instantiate unknown job type \""
00388 << type << "\"" << endl;
00389
00390 return 0;
00391 }
00392 };
00393
00394 Kleo::ChiasmusBackend * Kleo::ChiasmusBackend::self = 0;
00395
00396 Kleo::ChiasmusBackend::ChiasmusBackend()
00397 : Kleo::CryptoBackend(),
00398 mCryptoConfig( 0 ),
00399 mProtocol( 0 )
00400 {
00401 self = this;
00402 }
00403
00404 Kleo::ChiasmusBackend::~ChiasmusBackend() {
00405 self = 0;
00406 delete mCryptoConfig;
00407 delete mProtocol;
00408 }
00409
00410 QString Kleo::ChiasmusBackend::name() const {
00411 return "Chiasmus";
00412 }
00413
00414 QString Kleo::ChiasmusBackend::displayName() const {
00415 return i18n( "Chiasmus" );
00416 }
00417
00418 Kleo::CryptoConfig * Kleo::ChiasmusBackend::config() const {
00419 if ( !mCryptoConfig )
00420 mCryptoConfig = new CryptoConfig();
00421 return mCryptoConfig;
00422 }
00423
00424 Kleo::CryptoBackend::Protocol * Kleo::ChiasmusBackend::protocol( const char * name ) const {
00425 if ( qstricmp( name, "Chiasmus" ) != 0 )
00426 return 0;
00427 if ( !mProtocol )
00428 if ( checkForChiasmus() )
00429 mProtocol = new Protocol( config() );
00430 return mProtocol;
00431 }
00432
00433 bool Kleo::ChiasmusBackend::checkForOpenPGP( QString * reason ) const {
00434 if ( reason )
00435 *reason = i18n( "Unsupported protocol \"%1\"" ).arg( "OpenPGP" );
00436 return false;
00437 }
00438
00439 bool Kleo::ChiasmusBackend::checkForSMIME( QString * reason ) const {
00440 if ( reason )
00441 *reason = i18n( "Unsupported protocol \"%1\"" ).arg( "SMIME" );
00442 return false;
00443 }
00444
00445 bool Kleo::ChiasmusBackend::checkForChiasmus( QString * reason ) const {
00446
00447
00448 std::auto_ptr<Protocol> tmp( mProtocol );
00449 mProtocol = 0;
00450
00451 const CryptoConfigEntry * path = config()->entry( "Chiasmus", "General", "path" );
00452 assert( path ); assert( path->argType() == CryptoConfigEntry::ArgType_Path );
00453 const QString chiasmus = path->urlValue().path();
00454 const QFileInfo fi( KShell::tildeExpand( chiasmus ) );
00455 if ( !fi.isExecutable() ) {
00456 if ( reason )
00457 *reason = i18n( "File \"%1\" does not exist or is not executable." ).arg( chiasmus );
00458 return false;
00459 }
00460
00461
00462 mProtocol = tmp.release();
00463 return true;
00464 }
00465
00466 bool Kleo::ChiasmusBackend::checkForProtocol( const char * name, QString * reason ) const {
00467 if ( qstricmp( name, "Chiasmus" ) == 0 )
00468 return checkForChiasmus( reason );
00469 if ( reason )
00470 *reason = i18n( "Unsupported protocol \"%1\"" ).arg( name );
00471 return 0;
00472 }
00473
00474 bool Kleo::ChiasmusBackend::supportsProtocol( const char * name ) const {
00475 return qstricmp( name, "Chiasmus" ) == 0;
00476 }
00477
00478 const char * Kleo::ChiasmusBackend::enumerateProtocols( int i ) const {
00479 return i == 0 ? "Chiasmus" : 0 ;
00480 }