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