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 TQt library by Trolltech AS, Norway (or with modified versions 00024 of TQt that use the same license as TQt), 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 TQt. 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 <tqstringlist.h> 00051 #include <tqvariant.h> 00052 #include <tqfileinfo.h> 00053 00054 #include <map> 00055 #include <memory> 00056 00057 #include <cassert> 00058 00059 namespace { 00060 00061 // 00062 // The usual TQVariant 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: TQString s = to<TQString>( 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 TQVariant & 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 TQVariant & v ) { 00087 m.setPath( v.toString() ); 00088 } 00089 operator KURL() const { return m; } 00090 }; 00091 00092 template <typename T> 00093 class to< TQValueList<T> > { 00094 TQValueList<T> m; 00095 public: 00096 to( const TQVariant & v ) { 00097 const TQValueList<TQVariant> vl = v.toList(); 00098 for ( TQValueList<TQVariant>::const_iterator it = vl.begin(), end = vl.end() ; it != end ; ++it ) 00099 m.push_back( to<T>( *it ) ); 00100 } 00101 operator TQValueList<T> () const { return m; } 00102 }; 00103 00104 template <> 00105 class to<KURL::List> { 00106 KURL::List m; 00107 public: 00108 to( const TQVariant & v ) { 00109 // wow, KURL::List is broken... it lacks conversion from and to TQVL<KURL>... 00110 m += to< TQValueList<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 TQVariant { 00120 from_helper( const T & t ) : TQVariant( t ) {} 00121 }; 00122 00123 template <typename T> 00124 TQVariant from( const T & t ) { 00125 return from_helper<T>( t ); 00126 } 00127 00128 // some special types: 00129 template <> struct from_helper<bool> : public TQVariant { 00130 from_helper( bool b ) : TQVariant( b, int() ) {} 00131 }; 00132 template <> struct from_helper<KURL> : public TQVariant { 00133 from_helper( const KURL & url ) : TQVariant( url.path() ) {} 00134 }; 00135 template <typename T> struct from_helper< TQValueList<T> > : public TQVariant { 00136 from_helper( const TQValueList<T> & l ) { 00137 TQValueList<TQVariant> result; 00138 for ( typename TQValueList<T>::const_iterator it = l.begin(), end = l.end() ; it != end ; ++it ) 00139 result.push_back( from( *it ) ); 00140 TQVariant::operator=( result ); 00141 } 00142 }; 00143 template <> struct from_helper<KURL::List> : public from_helper< TQValueList<KURL> > { 00144 from_helper( const KURL::List & l ) : from_helper< TQValueList<KURL> >( l ) {} 00145 }; 00146 00147 class ChiasmusConfigEntry : public Kleo::CryptoConfigEntry { 00148 unsigned int mIdx; 00149 TQVariant 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 TQString name() const { return kleo_chiasmus_config_entries[mIdx].name; } 00159 TQString 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 TQString 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 TQStringList stringValueList() const { return mValue.toStringList(); } 00177 TQValueList<int> intValueList() const { return to< TQValueList<int> >( mValue ); } 00178 TQValueList<unsigned int> uintValueList() const { return to< TQValueList<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( TQVariant( value, int() ) ); } 00184 void setStringValue( const TQString & 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 TQStringList & value ) { setValue( value ); } 00193 void setIntValueList( const TQValueList<int> & l ) { setValue( from( l ) ); } 00194 void setUIntValueList( const TQValueList<unsigned int> & l ) { setValue( from( l ) ); } 00195 void setURLValueList( const KURL::List & l ) { setValue( from( l ) ); } 00196 bool isDirty() const { return mDirty; } 00197 00198 TQVariant 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 TQVariant defaultValue() const; 00212 void setValue( const TQVariant & value ) { mValue = value; mDirty = true; } 00213 }; 00214 00215 TQVariant ChiasmusConfigEntry::defaultValue() const { 00216 const kleo_chiasmus_config_data & data = kleo_chiasmus_config_entries[mIdx]; 00217 switch ( data.type ) { 00218 default: 00219 return TQVariant(); 00220 case ArgType_None: 00221 if ( isList() ) 00222 return TQValueList<TQVariant>() << TQVariant( data.defaults.boolean.value, int() ); 00223 else 00224 return TQVariant( data.defaults.boolean.value, int() ); 00225 case ArgType_String: 00226 if ( isList() ) 00227 return TQStringList( TQString::fromLatin1( data.defaults.string ) ); 00228 else 00229 return TQString::fromLatin1( data.defaults.string ); 00230 case ArgType_Int: 00231 if ( isList() ) 00232 return TQValueList<TQVariant>() << data.defaults.integer; 00233 else 00234 return data.defaults.integer; 00235 case ArgType_UInt: 00236 if ( isList() ) 00237 return TQValueList<TQVariant>() << 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 TQValueList<TQVariant>() << TQString::fromLatin1( data.defaults.path ); 00244 else 00245 return TQString::fromLatin1( data.defaults.path ); 00246 case ArgType_URL: 00247 case ArgType_LDAPURL: 00248 if ( isList() ) 00249 return TQValueList<TQVariant>() << TQString::fromLatin1( data.defaults.url ); 00250 else 00251 return TQString::fromLatin1( data.defaults.url ); 00252 } 00253 } 00254 00255 class ChiasmusGeneralGroup : public Kleo::CryptoConfigGroup { 00256 mutable std::map<TQString,ChiasmusConfigEntry*> mCache; 00257 mutable KConfig * mConfigObject; 00258 public: 00259 ChiasmusGeneralGroup() : Kleo::CryptoConfigGroup(), mConfigObject( 0 ) {} 00260 ~ChiasmusGeneralGroup() { clear(); delete mConfigObject; } 00261 TQString name() const { return "General"; } 00262 TQString iconName() const { return "chiasmus_chi"; } 00263 TQString description() const { return i18n( "General" ); } 00264 Kleo::CryptoConfigEntry::Level level() const { return Kleo::CryptoConfigEntry::Level_Basic; } 00265 TQStringList entryList() const { 00266 TQStringList 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 TQString & 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<TQString,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 // this is unsafe. We're a lib, used by concurrent apps. 00295 mConfigObject = new KConfig( "chiasmusbackendrc" ); 00296 return mConfigObject; 00297 } 00298 void clear() { 00299 for ( std::map<TQString,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 TQString name() const { return "Chiasmus"; } 00317 TQString iconName() const { return "chiasmus_chi"; } 00318 TQString description() const { return i18n( "Chiasmus" ); } 00319 TQStringList groupList() const { return TQStringList() << "General"; } 00320 Kleo::CryptoConfigGroup * group( const TQString & 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 TQStringList componentList() const { return TQStringList() << "Chiasmus" ; } 00338 ChiasmusComponent * component( const TQString & 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 TQString name() const { return "Chiasmus"; } 00363 TQString 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 TQString& ) 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 TQMap<TQString,TQVariant> & 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 TQString Kleo::ChiasmusBackend::name() const { 00411 return "Chiasmus"; 00412 } 00413 00414 TQString 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( TQString * reason ) const { 00434 if ( reason ) 00435 *reason = i18n( "Unsupported protocol \"%1\"" ).arg( "OpenPGP" ); 00436 return false; 00437 } 00438 00439 bool Kleo::ChiasmusBackend::checkForSMIME( TQString * reason ) const { 00440 if ( reason ) 00441 *reason = i18n( "Unsupported protocol \"%1\"" ).arg( "SMIME" ); 00442 return false; 00443 } 00444 00445 bool Kleo::ChiasmusBackend::checkForChiasmus( TQString * reason ) const { 00446 00447 // kills the protocol instance when we return false: 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 TQString chiasmus = path->urlValue().path(); 00454 const TQFileInfo 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 // FIXME: more checks? 00462 mProtocol = tmp.release(); 00463 return true; 00464 } 00465 00466 bool Kleo::ChiasmusBackend::checkForProtocol( const char * name, TQString * 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 }