cryptobackendfactory.cpp
00001 /* 00002 cryptobackendfactory.cpp 00003 00004 This file is part of libkleopatra, the KDE key management library 00005 Copyright (c) 2001,2004,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 "cryptobackendfactory.h" 00038 00039 #include <backends/qgpgme/qgpgmebackend.h> 00040 #if 0 // disabled for kde-3.3 00041 #include <backends/kpgp/pgp2backend.h> 00042 #include <backends/kpgp/pgp5backend.h> 00043 #include <backends/kpgp/pgp6backend.h> 00044 #include <backends/kpgp/gpg1backend.h> 00045 #endif 00046 #include <backends/chiasmus/chiasmusbackend.h> 00047 #include <ui/backendconfigwidget.h> 00048 00049 #include <kconfig.h> 00050 #include <klocale.h> 00051 #include <kdebug.h> 00052 #include <kmessagebox.h> 00053 #include <kapplication.h> 00054 00055 #include <iterator> 00056 #include <algorithm> 00057 00058 #include <cassert> 00059 00060 Kleo::CryptoBackendFactory * Kleo::CryptoBackendFactory::mSelf = 0; 00061 00062 static const char * availableProtocols[] = { 00063 "Chiasmus", 00064 "OpenPGP", "SMIME", 00065 }; 00066 static const unsigned int numAvailableProtocols = sizeof availableProtocols / sizeof *availableProtocols; 00067 00068 Kleo::CryptoBackendFactory::CryptoBackendFactory() 00069 : TQObject( tqApp, "CryptoBackendFactory::instance()" ), 00070 mConfigObject( 0 ), 00071 mAvailableProtocols( availableProtocols, availableProtocols + numAvailableProtocols ) 00072 { 00073 mBackendList.push_back( new QGpgMEBackend() ); 00074 #if 0 // disabled for kde-3.3 00075 mBackendList.push_back( new PGP2Backend() ); 00076 mBackendList.push_back( new PGP5Backend() ); 00077 mBackendList.push_back( new PGP6Backend() ); 00078 mBackendList.push_back( new GPG1Backend() ); 00079 #endif 00080 mBackendList.push_back( new ChiasmusBackend() ); 00081 scanForBackends(); 00082 readConfig(); 00083 00084 mSelf = this; // last! 00085 } 00086 00087 Kleo::CryptoBackendFactory::~CryptoBackendFactory() { 00088 mSelf = 0; // first! 00089 00090 for ( std::vector<CryptoBackend*>::iterator it = mBackendList.begin() ; it != mBackendList.end() ; ++it ) { 00091 delete *it; 00092 *it = 0; 00093 } 00094 delete mConfigObject; 00095 mConfigObject = 0; 00096 } 00097 00098 Kleo::CryptoBackendFactory * Kleo::CryptoBackendFactory::instance() { 00099 if ( !mSelf ) 00100 mSelf = new CryptoBackendFactory(); 00101 return mSelf; 00102 } 00103 00104 00105 // const Kleo::CryptoBackend* Kleo::CryptoBackendFactory::smimeBackend() const { 00106 // return mSMIMEBackend; 00107 // } 00108 00109 // const Kleo::CryptoBackend* Kleo::CryptoBackendFactory::openpgpBackend() const { 00110 // return mOpenPGPBackend; 00111 // } 00112 00113 const Kleo::CryptoBackend::Protocol * Kleo::CryptoBackendFactory::smime() const { 00114 const BackendMap::const_iterator it = mBackends.find( "SMIME" ); 00115 if ( it == mBackends.end() ) 00116 return 0; 00117 if ( !it->second ) 00118 return 0; 00119 return it->second->smime(); 00120 } 00121 00122 const Kleo::CryptoBackend::Protocol * Kleo::CryptoBackendFactory::openpgp() const { 00123 const BackendMap::const_iterator it = mBackends.find( "OpenPGP" ); 00124 if ( it == mBackends.end() ) 00125 return 0; 00126 if ( !it->second ) 00127 return 0; 00128 return it->second->openpgp(); 00129 } 00130 00131 const Kleo::CryptoBackend::Protocol * Kleo::CryptoBackendFactory::protocol( const char * name ) const { 00132 const BackendMap::const_iterator it = mBackends.find( name ); 00133 if ( it == mBackends.end() ) 00134 return 0; 00135 if ( !it->second ) 00136 return 0; 00137 return it->second->protocol( name ); 00138 } 00139 00140 Kleo::CryptoConfig * Kleo::CryptoBackendFactory::config() const { 00141 // ## should we use mSMIMEBackend? mOpenPGPBackend? backend(0) i.e. always qgpgme? 00142 return backend( 0 ) ? backend( 0 )->config() : 0; 00143 } 00144 00145 bool Kleo::CryptoBackendFactory::hasBackends() const { 00146 return !mBackendList.empty(); 00147 } 00148 00149 void Kleo::CryptoBackendFactory::scanForBackends( TQStringList * reasons ) { 00150 for ( std::vector<CryptoBackend*>::const_iterator it = mBackendList.begin() ; it != mBackendList.end() ; ++it ) { 00151 assert( *it ); 00152 for ( int i = 0 ; const char * protocol = (*it)->enumerateProtocols( i ) ; ++i ) { 00153 TQString reason; 00154 if ( (*it)->supportsProtocol( protocol ) && !(*it)->checkForProtocol( protocol, &reason ) ) { 00155 if ( reasons ) { 00156 reasons->push_back( i18n("While scanning for %1 support in backend %2:") 00157 .arg( protocol, (*it)->displayName() ) ); 00158 reasons->push_back( " " + reason ); 00159 } 00160 } 00161 } 00162 } 00163 } 00164 00165 const Kleo::CryptoBackend * Kleo::CryptoBackendFactory::backend( unsigned int idx ) const { 00166 return ( idx < mBackendList.size() ) ? mBackendList[idx] : 0 ; 00167 } 00168 00169 const Kleo::CryptoBackend * Kleo::CryptoBackendFactory::backendByName( const TQString& name ) const { 00170 for ( std::vector<CryptoBackend*>::const_iterator it = mBackendList.begin() ; it != mBackendList.end() ; ++it ) { 00171 if ( (*it)->name() == name ) 00172 return *it; 00173 } 00174 return 0; 00175 } 00176 00177 Kleo::BackendConfigWidget * Kleo::CryptoBackendFactory::configWidget( TQWidget * parent, const char * name ) const { 00178 return new Kleo::BackendConfigWidget( mSelf, parent, name ); 00179 } 00180 00181 KConfig* Kleo::CryptoBackendFactory::configObject() const { 00182 if ( !mConfigObject ) 00183 // this is unsafe. We're a lib, used by concurrent apps. 00184 mConfigObject = new KConfig( "libkleopatrarc" ); 00185 return mConfigObject; 00186 } 00187 00188 void Kleo::CryptoBackendFactory::setSMIMEBackend( const CryptoBackend* backend ) { 00189 setProtocolBackend( "SMIME", backend ); 00190 } 00191 00192 void Kleo::CryptoBackendFactory::setOpenPGPBackend( const CryptoBackend* backend ) { 00193 setProtocolBackend( "OpenPGP", backend ); 00194 } 00195 00196 void Kleo::CryptoBackendFactory::setProtocolBackend( const char * protocol, const CryptoBackend * backend ) { 00197 const TQString name = backend ? backend->name() : TQString() ; 00198 KConfigGroup group( configObject(), "Backends" ); 00199 group.writeEntry( protocol, name ); 00200 configObject()->sync(); 00201 mBackends[protocol] = backend; 00202 } 00203 00204 static const char * defaultBackend( const char * proto ) { 00205 static const struct { 00206 const char * proto; 00207 const char * backend; 00208 } defaults[] = { 00209 { "OpenPGP", "gpgme" }, 00210 { "SMIME", "gpgme" }, 00211 { "Chiasmus", "chiasmus" }, 00212 }; 00213 for ( unsigned int i = 0 ; i < sizeof defaults / sizeof *defaults ; ++i ) 00214 if ( qstricmp( proto, defaults[i].proto ) == 0 ) 00215 return defaults[i].backend; 00216 return 0; 00217 } 00218 00219 void Kleo::CryptoBackendFactory::readConfig() { 00220 mBackends.clear(); 00221 const KConfigGroup group( configObject(), "Backends" ); 00222 for ( ProtocolSet::const_iterator it = mAvailableProtocols.begin(), end = mAvailableProtocols.end() ; it != end ; ++it ) { 00223 const TQString backend = group.readEntry( *it, defaultBackend( *it ) ); 00224 mBackends[*it] = backendByName( backend ); 00225 } 00226 } 00227 00228 const char * Kleo::CryptoBackendFactory::enumerateProtocols( int i ) const { 00229 if ( i < 0 || static_cast<unsigned int>( i ) >= mAvailableProtocols.size() ) 00230 return 0; 00231 return mAvailableProtocols[i]; 00232 } 00233 00234 namespace { 00235 class CaseInsensitiveString { 00236 const char * m; 00237 public: 00238 CaseInsensitiveString( const char * s ) : m( s ) {} 00239 #define make_operator( op ) \ 00240 bool operator op( const CaseInsensitiveString & other ) const { \ 00241 return qstricmp( m, other.m ) op 0; \ 00242 } \ 00243 bool operator op( const char * other ) const { \ 00244 return qstricmp( m, other ) op 0; \ 00245 } 00246 make_operator( == ) 00247 make_operator( != ) 00248 make_operator( < ) 00249 make_operator( > ) 00250 make_operator( <= ) 00251 make_operator( >= ) 00252 #undef make_operator 00253 operator const char *() const { return m; } 00254 }; 00255 #define make_ext_operator( op, inv_op ) \ 00256 inline bool operator op( const char * lhs, const CaseInsensitiveString & rhs ) { \ 00257 return rhs.operator inv_op( lhs ); \ 00258 } 00259 make_ext_operator( ==, == ) 00260 make_ext_operator( !=, != ) 00261 make_ext_operator( <, > ) 00262 make_ext_operator( >, < ) 00263 make_ext_operator( <=, >= ) 00264 make_ext_operator( >=, <= ) 00265 #undef make_ext_operator 00266 00267 } 00268 00269 bool Kleo::CryptoBackendFactory::knowsAboutProtocol( const char * name ) const { 00270 return std::find( mAvailableProtocols.begin(), mAvailableProtocols.end(), 00271 CaseInsensitiveString( name ) ) != mAvailableProtocols.end(); 00272 } 00273 00274 #include "cryptobackendfactory.moc" 00275