chiasmusbackend.cpp
1 /*
2  chiasmusbackend.cpp
3 
4  This file is part of libkleopatra, the KDE keymanagement library
5  Copyright (c) 2005 Klarälvdalens Datakonsult AB
6 
7  Libkleopatra is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of the
10  License, or (at your option) any later version.
11 
12  Libkleopatra is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 
21  In addition, as a special exception, the copyright holders give
22  permission to link the code of this program with any edition of
23  the TQt library by Trolltech AS, Norway (or with modified versions
24  of TQt that use the same license as TQt), and distribute linked
25  combinations including the two. You must obey the GNU General
26  Public License in all respects for all of the code used other than
27  TQt. If you modify this file, you may extend this exception to
28  your version of the file, but you are not obligated to do so. If
29  you do not wish to do so, delete this exception statement from
30  your version.
31 */
32 
33 #ifdef HAVE_CONFIG_H
34 #include <config.h>
35 #endif
36 
37 #include "chiasmusbackend.h"
38 
39 #include "config_data.h"
40 #include "obtainkeysjob.h"
41 #include "chiasmusjob.h"
42 
43 #include "kleo/cryptoconfig.h"
44 
45 #include <tdelocale.h>
46 #include <tdeconfig.h>
47 #include <kshell.h>
48 #include <kdebug.h>
49 
50 #include <tqstringlist.h>
51 #include <tqvariant.h>
52 #include <tqfileinfo.h>
53 
54 #include <map>
55 #include <memory>
56 
57 #include <cassert>
58 
59 namespace {
60 
61  //
62  // The usual TQVariant template helpers:
63  //
64 
65  // to<> is a demarshaller. It's a class b/c you can't partially
66  // specialise function templates yet. However, to<> can be used as if
67  // it was a function: TQString s = to<TQString>( myVariant );
68  template <typename T> class to {};
69 
70 #define MAKE_TO( type, func ) \
71  template <> \
72  class to< type > { \
73  type m; \
74  public: \
75  to( const TQVariant & v ) : m( v.func() ) {} \
76  operator type() const { return m; } \
77  }
78 
79  MAKE_TO( int, toInt );
80  MAKE_TO( unsigned int, toUInt );
81 
82  template <>
83  class to<KURL> {
84  KURL m;
85  public:
86  to( const TQVariant & v ) {
87  m.setPath( v.toString() );
88  }
89  operator KURL() const { return m; }
90  };
91 
92  template <typename T>
93  class to< TQValueList<T> > {
94  TQValueList<T> m;
95  public:
96  to( const TQVariant & v ) {
97  const TQValueList<TQVariant> vl = v.toList();
98  for ( TQValueList<TQVariant>::const_iterator it = vl.begin(), end = vl.end() ; it != end ; ++it )
99  m.push_back( to<T>( *it ) );
100  }
101  operator TQValueList<T> () const { return m; }
102  };
103 
104  template <>
105  class to<KURL::List> {
106  KURL::List m;
107  public:
108  to( const TQVariant & v ) {
109  // wow, KURL::List is broken... it lacks conversion from and to TQVL<KURL>...
110  m += to< TQValueList<KURL> >( v );
111  }
112  operator KURL::List() const { return m; }
113  };
114 
115 
116  // from<> is the demarshaller. See to<> for why this is a class...
117 
118  template <typename T>
119  struct from_helper : public TQVariant {
120  from_helper( const T & t ) : TQVariant( t ) {}
121  };
122 
123  template <typename T>
124  TQVariant from( const T & t ) {
125  return from_helper<T>( t );
126  }
127 
128  // some special types:
129  template <> struct from_helper<bool> : public TQVariant {
130  from_helper( bool b ) : TQVariant( b, int() ) {}
131  };
132  template <> struct from_helper<KURL> : public TQVariant {
133  from_helper( const KURL & url ) : TQVariant( url.path() ) {}
134  };
135  template <typename T> struct from_helper< TQValueList<T> > : public TQVariant {
136  from_helper( const TQValueList<T> & l ) {
137  TQValueList<TQVariant> result;
138  for ( typename TQValueList<T>::const_iterator it = l.begin(), end = l.end() ; it != end ; ++it )
139  result.push_back( from( *it ) );
140  TQVariant::operator=( result );
141  }
142  };
143  template <> struct from_helper<KURL::List> : public from_helper< TQValueList<KURL> > {
144  from_helper( const KURL::List & l ) : from_helper< TQValueList<KURL> >( l ) {}
145  };
146 
147  class ChiasmusConfigEntry : public Kleo::CryptoConfigEntry {
148  unsigned int mIdx;
149  TQVariant mValue;
150  bool mDirty;
151  public:
152  ChiasmusConfigEntry( unsigned int i )
153  : Kleo::CryptoConfigEntry(),
154  mIdx( i ), mValue( defaultValue() ), mDirty( false )
155  {
156  assert( i < kleo_chiasmus_config_entries_dim );
157  }
158  TQString name() const { return kleo_chiasmus_config_entries[mIdx].name; }
159  TQString description() const { return i18n( kleo_chiasmus_config_entries[mIdx].description ); }
160  bool isOptional() const { return kleo_chiasmus_config_entries[mIdx].is_optional; }
161  bool isReadOnly() const { return false; }
162  bool isList() const { return kleo_chiasmus_config_entries[mIdx].is_list; }
163  bool isRuntime() const { return kleo_chiasmus_config_entries[mIdx].is_runtime; }
164  Level level() const { return static_cast<Level>( kleo_chiasmus_config_entries[mIdx].level ); }
165  ArgType argType() const { return static_cast<ArgType>( kleo_chiasmus_config_entries[mIdx].type ); }
166  bool isSet() const { return mValue != defaultValue(); }
167  bool boolValue() const { return mValue.toBool(); }
168  TQString stringValue() const { return mValue.toString(); }
169  int intValue() const { return mValue.toInt(); }
170  unsigned int uintValue() const { return mValue.toUInt(); }
171  KURL urlValue() const {
172  if ( argType() != ArgType_Path && argType() != ArgType_DirPath ) return KURL( mValue.toString() );
173  KURL u; u.setPath( mValue.toString() ); return u;
174  }
175  unsigned int numberOfTimesSet() const { return 0; }
176  TQStringList stringValueList() const { return mValue.toStringList(); }
177  TQValueList<int> intValueList() const { return to< TQValueList<int> >( mValue ); }
178  TQValueList<unsigned int> uintValueList() const { return to< TQValueList<unsigned int> >( mValue ); }
179  KURL::List urlValueList() const {
180  if ( argType() != ArgType_Path && argType()!= ArgType_DirPath ) return mValue.toStringList();
181  else return to<KURL::List>( mValue ); }
182  void resetToDefault() { mValue = defaultValue(); mDirty = false; }
183  void setBoolValue( bool value ) { setValue( TQVariant( value, int() ) ); }
184  void setStringValue( const TQString & value ) { setValue( value ); }
185  void setIntValue( int value ) { setValue( value ); }
186  void setUIntValue( unsigned int value ) { setValue( value ); }
187  void setURLValue( const KURL & value ) {
188  if ( argType() != ArgType_Path && argType()!= ArgType_DirPath ) setValue( value.url() );
189  else setValue( value.path() );
190  }
191  void setNumberOfTimesSet( unsigned int ) {}
192  void setStringValueList( const TQStringList & value ) { setValue( value ); }
193  void setIntValueList( const TQValueList<int> & l ) { setValue( from( l ) ); }
194  void setUIntValueList( const TQValueList<unsigned int> & l ) { setValue( from( l ) ); }
195  void setURLValueList( const KURL::List & l ) { setValue( from( l ) ); }
196  bool isDirty() const { return mDirty; }
197 
198  TQVariant value() const { return mValue; }
199 
200  void sync( TDEConfigBase * config ) {
201  if ( !mDirty )
202  return;
203  mDirty = false;
204  config->writeEntry( kleo_chiasmus_config_entries[mIdx].name, mValue );
205  }
206  void read( const TDEConfigBase * config ) {
207  mDirty = false;
208  mValue = config->readPropertyEntry( kleo_chiasmus_config_entries[mIdx].name, defaultValue() );
209  }
210  private:
211  TQVariant defaultValue() const;
212  void setValue( const TQVariant & value ) { mValue = value; mDirty = true; }
213  };
214 
215  TQVariant ChiasmusConfigEntry::defaultValue() const {
216  const kleo_chiasmus_config_data & data = kleo_chiasmus_config_entries[mIdx];
217  switch ( data.type ) {
218  default:
219  return TQVariant();
220  case ArgType_None:
221  if ( isList() )
222  return TQValueList<TQVariant>() << TQVariant( data.defaults.boolean.value, int() );
223  else
224  return TQVariant( data.defaults.boolean.value, int() );
225  case ArgType_String:
226  if ( isList() )
227  return TQStringList( TQString::fromLatin1( data.defaults.string ) );
228  else
229  return TQString::fromLatin1( data.defaults.string );
230  case ArgType_Int:
231  if ( isList() )
232  return TQValueList<TQVariant>() << data.defaults.integer;
233  else
234  return data.defaults.integer;
235  case ArgType_UInt:
236  if ( isList() )
237  return TQValueList<TQVariant>() << data.defaults.unsigned_integer;
238  else
239  return data.defaults.unsigned_integer;
240  case ArgType_Path:
241  case ArgType_DirPath:
242  if ( isList() )
243  return TQValueList<TQVariant>() << TQString::fromLatin1( data.defaults.path );
244  else
245  return TQString::fromLatin1( data.defaults.path );
246  case ArgType_URL:
247  case ArgType_LDAPURL:
248  if ( isList() )
249  return TQValueList<TQVariant>() << TQString::fromLatin1( data.defaults.url );
250  else
251  return TQString::fromLatin1( data.defaults.url );
252  }
253  }
254 
255  class ChiasmusGeneralGroup : public Kleo::CryptoConfigGroup {
256  mutable std::map<TQString,ChiasmusConfigEntry*> mCache;
257  mutable TDEConfig * mConfigObject;
258  public:
259  ChiasmusGeneralGroup() : Kleo::CryptoConfigGroup(), mConfigObject( 0 ) {}
260  ~ChiasmusGeneralGroup() { clear(); delete mConfigObject; }
261  TQString name() const { return "General"; }
262  TQString iconName() const { return "chiasmus_chi"; }
263  TQString description() const { return i18n( "General" ); }
264  Kleo::CryptoConfigEntry::Level level() const { return Kleo::CryptoConfigEntry::Level_Basic; }
265  TQStringList entryList() const {
266  TQStringList result;
267  for ( unsigned int i = 0 ; i < kleo_chiasmus_config_entries_dim ; ++i )
268  result.push_back( kleo_chiasmus_config_entries[i].name );
269  return result;
270  }
271  Kleo::CryptoConfigEntry * entry( const TQString & name ) const {
272  if ( ChiasmusConfigEntry * entry = mCache[name] )
273  return entry;
274  const TDEConfigGroup group( configObject(), "Chiasmus" );
275  for ( unsigned int i = 0 ; i < kleo_chiasmus_config_entries_dim ; ++i )
276  if ( name == kleo_chiasmus_config_entries[i].name ) {
277  ChiasmusConfigEntry * entry = new ChiasmusConfigEntry( i );
278  entry->read( &group );
279  return mCache[name] = entry;
280  }
281  return 0;
282  }
283 
284  void sync() {
285  TDEConfigGroup group( configObject(), "Chiasmus" );
286  for ( std::map<TQString,ChiasmusConfigEntry*>::const_iterator it = mCache.begin(), end = mCache.end() ; it != end ; ++it )
287  it->second->sync( &group );
288  group.sync();
289  clear();
290  }
291  private:
292  TDEConfig * configObject() const {
293  if ( !mConfigObject )
294  // this is unsafe. We're a lib, used by concurrent apps.
295  mConfigObject = new TDEConfig( "chiasmusbackendrc" );
296  return mConfigObject;
297  }
298  void clear() {
299  for ( std::map<TQString,ChiasmusConfigEntry*>::const_iterator it = mCache.begin(), end = mCache.end() ; it != end ; ++it )
300  delete it->second;
301  mCache.clear();
302  }
303  };
304 
305  class ChiasmusComponent : public Kleo::CryptoConfigComponent {
306  mutable ChiasmusGeneralGroup * mGeneralGroup;
307  public:
308  ChiasmusComponent() : Kleo::CryptoConfigComponent(), mGeneralGroup( 0 ) {}
309  ~ChiasmusComponent() { delete mGeneralGroup; }
310 
311  void sync() {
312  if ( mGeneralGroup )
313  mGeneralGroup->sync();
314  }
315 
316  TQString name() const { return "Chiasmus"; }
317  TQString iconName() const { return "chiasmus_chi"; }
318  TQString description() const { return i18n( "Chiasmus" ); }
319  TQStringList groupList() const { return TQStringList() << "General"; }
320  Kleo::CryptoConfigGroup * group( const TQString & name ) const {
321  if ( name != "General" )
322  return 0;
323  if ( !mGeneralGroup )
324  mGeneralGroup = new ChiasmusGeneralGroup();
325  return mGeneralGroup;
326  }
327  };
328 
329 }
330 
331 class Kleo::ChiasmusBackend::CryptoConfig : public Kleo::CryptoConfig {
332  mutable ChiasmusComponent * mComponent;
333 public:
334  CryptoConfig() : Kleo::CryptoConfig(), mComponent( 0 ) {}
335  ~CryptoConfig() { delete mComponent; }
336 
337  TQStringList componentList() const { return TQStringList() << "Chiasmus" ; }
338  ChiasmusComponent * component( const TQString & name ) const {
339  if ( name != "Chiasmus" )
340  return 0;
341  if ( !mComponent )
342  mComponent = new ChiasmusComponent();
343  return mComponent;
344  }
345  void sync( bool ) {
346  if ( mComponent )
347  mComponent->sync();
348  }
349  void clear() { delete mComponent; mComponent = 0; }
350 };
351 
352 class Kleo::ChiasmusBackend::Protocol : public Kleo::CryptoBackend::Protocol {
353  Kleo::CryptoConfig * mCryptoConfig;
354 public:
355  Protocol( Kleo::CryptoConfig * config )
356  : Kleo::CryptoBackend::Protocol(), mCryptoConfig( config )
357  {
358  assert( config );
359  }
360  ~Protocol() {}
361 
362  TQString name() const { return "Chiasmus"; }
363  TQString displayName() const { return i18n( "Chiasmus command line tool" ); }
364  KeyListJob * keyListJob( bool, bool, bool ) const { return 0; }
365  EncryptJob * encryptJob( bool, bool ) const { return 0; }
366  DecryptJob * decryptJob() const { return 0; }
367  SignJob * signJob( bool, bool ) const { return 0; }
368  VerifyDetachedJob * verifyDetachedJob( bool ) const { return 0; }
369  VerifyOpaqueJob * verifyOpaqueJob( bool ) const { return 0; }
370  KeyGenerationJob * keyGenerationJob() const { return 0; }
371  ImportJob * importJob() const { return 0; }
372  ExportJob * publicKeyExportJob( bool ) const { return 0; }
373  ExportJob * secretKeyExportJob( bool, const TQString& ) const { return 0; }
374  DownloadJob * downloadJob( bool ) const { return 0; }
375  DeleteJob * deleteJob() const { return 0; }
376  SignEncryptJob * signEncryptJob( bool, bool ) const { return 0; }
377  DecryptVerifyJob * decryptVerifyJob( bool ) const { return 0; }
378  RefreshKeysJob * refreshKeysJob() const { return 0; }
379 
380  SpecialJob * specialJob( const char * type, const TQMap<TQString,TQVariant> & args ) const {
381  if ( tqstricmp( type, "x-obtain-keys" ) == 0 && args.size() == 0 )
382  return new ObtainKeysJob();
383  if ( tqstricmp( type, "x-encrypt" ) == 0 && args.size() == 0 )
384  return new ChiasmusJob( ChiasmusJob::Encrypt );
385  if ( tqstricmp( type, "x-decrypt" ) == 0 && args.size() == 0 )
386  return new ChiasmusJob( ChiasmusJob::Decrypt );
387  kdDebug(5150) << "ChiasmusBackend::Protocol: tried to instantiate unknown job type \""
388  << type << "\"" << endl;
389 
390  return 0;
391  }
392 };
393 
394 Kleo::ChiasmusBackend * Kleo::ChiasmusBackend::self = 0;
395 
396 Kleo::ChiasmusBackend::ChiasmusBackend()
397  : Kleo::CryptoBackend(),
398  mCryptoConfig( 0 ),
399  mProtocol( 0 )
400 {
401  self = this;
402 }
403 
404 Kleo::ChiasmusBackend::~ChiasmusBackend() {
405  self = 0;
406  delete mCryptoConfig;
407  delete mProtocol;
408 }
409 
410 TQString Kleo::ChiasmusBackend::name() const {
411  return "Chiasmus";
412 }
413 
414 TQString Kleo::ChiasmusBackend::displayName() const {
415  return i18n( "Chiasmus" );
416 }
417 
418 Kleo::CryptoConfig * Kleo::ChiasmusBackend::config() const {
419  if ( !mCryptoConfig )
420  mCryptoConfig = new CryptoConfig();
421  return mCryptoConfig;
422 }
423 
424 Kleo::CryptoBackend::Protocol * Kleo::ChiasmusBackend::protocol( const char * name ) const {
425  if ( tqstricmp( name, "Chiasmus" ) != 0 )
426  return 0;
427  if ( !mProtocol )
428  if ( checkForChiasmus() )
429  mProtocol = new Protocol( config() );
430  return mProtocol;
431 }
432 
433 bool Kleo::ChiasmusBackend::checkForOpenPGP( TQString * reason ) const {
434  if ( reason )
435  *reason = i18n( "Unsupported protocol \"%1\"" ).arg( "OpenPGP" );
436  return false;
437 }
438 
439 bool Kleo::ChiasmusBackend::checkForSMIME( TQString * reason ) const {
440  if ( reason )
441  *reason = i18n( "Unsupported protocol \"%1\"" ).arg( "SMIME" );
442  return false;
443 }
444 
445 bool Kleo::ChiasmusBackend::checkForChiasmus( TQString * reason ) const {
446 
447  // kills the protocol instance when we return false:
448  std::auto_ptr<Protocol> tmp( mProtocol );
449  mProtocol = 0;
450 
451  const CryptoConfigEntry * path = config()->entry( "Chiasmus", "General", "path" );
452  assert( path ); assert( path->argType() == CryptoConfigEntry::ArgType_Path );
453  const TQString chiasmus = path->urlValue().path();
454  const TQFileInfo fi( KShell::tildeExpand( chiasmus ) );
455  if ( !fi.isExecutable() ) {
456  if ( reason )
457  *reason = i18n( "File \"%1\" does not exist or is not executable." ).arg( chiasmus );
458  return false;
459  }
460 
461  // FIXME: more checks?
462  mProtocol = tmp.release();
463  return true;
464 }
465 
466 bool Kleo::ChiasmusBackend::checkForProtocol( const char * name, TQString * reason ) const {
467  if ( tqstricmp( name, "Chiasmus" ) == 0 )
468  return checkForChiasmus( reason );
469  if ( reason )
470  *reason = i18n( "Unsupported protocol \"%1\"" ).arg( name );
471  return 0;
472 }
473 
474 bool Kleo::ChiasmusBackend::supportsProtocol( const char * name ) const {
475  return tqstricmp( name, "Chiasmus" ) == 0;
476 }
477 
478 const char * Kleo::ChiasmusBackend::enumerateProtocols( int i ) const {
479  return i == 0 ? "Chiasmus" : 0 ;
480 }
virtual CryptoConfigComponent * component(const TQString &name) const =0
virtual void sync(bool runtime)=0
Write back changes.
virtual TQStringList componentList() const =0
Returns the list of known components (e.g.
Description of a single option.
Definition: cryptoconfig.h:49
virtual void clear()=0
Tells the CryptoConfig to discard any cached information, including all components,...
Crypto config for one component (e.g.
Definition: cryptoconfig.h:295
Main interface to crypto configuration.
Definition: cryptoconfig.h:334
Group containing a set of config options.
Definition: cryptoconfig.h:252