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<KURL> : public TQVariant {
130  from_helper( const KURL & url ) : TQVariant( url.path() ) {}
131  };
132  template <typename T> struct from_helper< TQValueList<T> > : public TQVariant {
133  from_helper( const TQValueList<T> & l ) {
134  TQValueList<TQVariant> result;
135  for ( typename TQValueList<T>::const_iterator it = l.begin(), end = l.end() ; it != end ; ++it )
136  result.push_back( from( *it ) );
137  TQVariant::operator=( result );
138  }
139  };
140  template <> struct from_helper<KURL::List> : public from_helper< TQValueList<KURL> > {
141  from_helper( const KURL::List & l ) : from_helper< TQValueList<KURL> >( l ) {}
142  };
143 
144  class ChiasmusConfigEntry : public Kleo::CryptoConfigEntry {
145  unsigned int mIdx;
146  TQVariant mValue;
147  bool mDirty;
148  public:
149  ChiasmusConfigEntry( unsigned int i )
150  : Kleo::CryptoConfigEntry(),
151  mIdx( i ), mValue( defaultValue() ), mDirty( false )
152  {
153  assert( i < kleo_chiasmus_config_entries_dim );
154  }
155  TQString name() const { return kleo_chiasmus_config_entries[mIdx].name; }
156  TQString description() const { return i18n( kleo_chiasmus_config_entries[mIdx].description ); }
157  bool isOptional() const { return kleo_chiasmus_config_entries[mIdx].is_optional; }
158  bool isReadOnly() const { return false; }
159  bool isList() const { return kleo_chiasmus_config_entries[mIdx].is_list; }
160  bool isRuntime() const { return kleo_chiasmus_config_entries[mIdx].is_runtime; }
161  Level level() const { return static_cast<Level>( kleo_chiasmus_config_entries[mIdx].level ); }
162  ArgType argType() const { return static_cast<ArgType>( kleo_chiasmus_config_entries[mIdx].type ); }
163  bool isSet() const { return mValue != defaultValue(); }
164  bool boolValue() const { return mValue.toBool(); }
165  TQString stringValue() const { return mValue.toString(); }
166  int intValue() const { return mValue.toInt(); }
167  unsigned int uintValue() const { return mValue.toUInt(); }
168  KURL urlValue() const {
169  if ( argType() != ArgType_Path && argType() != ArgType_DirPath ) return KURL( mValue.toString() );
170  KURL u; u.setPath( mValue.toString() ); return u;
171  }
172  unsigned int numberOfTimesSet() const { return 0; }
173  TQStringList stringValueList() const { return mValue.toStringList(); }
174  TQValueList<int> intValueList() const { return to< TQValueList<int> >( mValue ); }
175  TQValueList<unsigned int> uintValueList() const { return to< TQValueList<unsigned int> >( mValue ); }
176  KURL::List urlValueList() const {
177  if ( argType() != ArgType_Path && argType()!= ArgType_DirPath ) return mValue.toStringList();
178  else return to<KURL::List>( mValue ); }
179  void resetToDefault() { mValue = defaultValue(); mDirty = false; }
180  void setBoolValue( bool value ) { setValue( TQVariant( value ) ); }
181  void setStringValue( const TQString & value ) { setValue( value ); }
182  void setIntValue( int value ) { setValue( value ); }
183  void setUIntValue( unsigned int value ) { setValue( value ); }
184  void setURLValue( const KURL & value ) {
185  if ( argType() != ArgType_Path && argType()!= ArgType_DirPath ) setValue( value.url() );
186  else setValue( value.path() );
187  }
188  void setNumberOfTimesSet( unsigned int ) {}
189  void setStringValueList( const TQStringList & value ) { setValue( value ); }
190  void setIntValueList( const TQValueList<int> & l ) { setValue( from( l ) ); }
191  void setUIntValueList( const TQValueList<unsigned int> & l ) { setValue( from( l ) ); }
192  void setURLValueList( const KURL::List & l ) { setValue( from( l ) ); }
193  bool isDirty() const { return mDirty; }
194 
195  TQVariant value() const { return mValue; }
196 
197  void sync( TDEConfigBase * config ) {
198  if ( !mDirty )
199  return;
200  mDirty = false;
201  config->writeEntry( kleo_chiasmus_config_entries[mIdx].name, mValue );
202  }
203  void read( const TDEConfigBase * config ) {
204  mDirty = false;
205  mValue = config->readPropertyEntry( kleo_chiasmus_config_entries[mIdx].name, defaultValue() );
206  }
207  private:
208  TQVariant defaultValue() const;
209  void setValue( const TQVariant & value ) { mValue = value; mDirty = true; }
210  };
211 
212  TQVariant ChiasmusConfigEntry::defaultValue() const {
213  const kleo_chiasmus_config_data & data = kleo_chiasmus_config_entries[mIdx];
214  switch ( data.type ) {
215  default:
216  return TQVariant();
217  case ArgType_None:
218  if ( isList() )
219  return TQValueList<TQVariant>() << TQVariant( data.defaults.boolean.value );
220  else
221  return TQVariant( data.defaults.boolean.value );
222  case ArgType_String:
223  if ( isList() )
224  return TQStringList( TQString::fromLatin1( data.defaults.string ) );
225  else
226  return TQString::fromLatin1( data.defaults.string );
227  case ArgType_Int:
228  if ( isList() )
229  return TQValueList<TQVariant>() << data.defaults.integer;
230  else
231  return data.defaults.integer;
232  case ArgType_UInt:
233  if ( isList() )
234  return TQValueList<TQVariant>() << data.defaults.unsigned_integer;
235  else
236  return data.defaults.unsigned_integer;
237  case ArgType_Path:
238  case ArgType_DirPath:
239  if ( isList() )
240  return TQValueList<TQVariant>() << TQString::fromLatin1( data.defaults.path );
241  else
242  return TQString::fromLatin1( data.defaults.path );
243  case ArgType_URL:
244  case ArgType_LDAPURL:
245  if ( isList() )
246  return TQValueList<TQVariant>() << TQString::fromLatin1( data.defaults.url );
247  else
248  return TQString::fromLatin1( data.defaults.url );
249  }
250  }
251 
252  class ChiasmusGeneralGroup : public Kleo::CryptoConfigGroup {
253  mutable std::map<TQString,ChiasmusConfigEntry*> mCache;
254  mutable TDEConfig * mConfigObject;
255  public:
256  ChiasmusGeneralGroup() : Kleo::CryptoConfigGroup(), mConfigObject( 0 ) {}
257  ~ChiasmusGeneralGroup() { clear(); delete mConfigObject; }
258  TQString name() const { return "General"; }
259  TQString iconName() const { return "chiasmus_chi"; }
260  TQString description() const { return i18n( "General" ); }
261  Kleo::CryptoConfigEntry::Level level() const { return Kleo::CryptoConfigEntry::Level_Basic; }
262  TQStringList entryList() const {
263  TQStringList result;
264  for ( unsigned int i = 0 ; i < kleo_chiasmus_config_entries_dim ; ++i )
265  result.push_back( kleo_chiasmus_config_entries[i].name );
266  return result;
267  }
268  Kleo::CryptoConfigEntry * entry( const TQString & name ) const {
269  if ( ChiasmusConfigEntry * entry = mCache[name] )
270  return entry;
271  const TDEConfigGroup group( configObject(), "Chiasmus" );
272  for ( unsigned int i = 0 ; i < kleo_chiasmus_config_entries_dim ; ++i )
273  if ( name == kleo_chiasmus_config_entries[i].name ) {
274  ChiasmusConfigEntry * entry = new ChiasmusConfigEntry( i );
275  entry->read( &group );
276  return mCache[name] = entry;
277  }
278  return 0;
279  }
280 
281  void sync() {
282  TDEConfigGroup group( configObject(), "Chiasmus" );
283  for ( std::map<TQString,ChiasmusConfigEntry*>::const_iterator it = mCache.begin(), end = mCache.end() ; it != end ; ++it )
284  it->second->sync( &group );
285  group.sync();
286  clear();
287  }
288  private:
289  TDEConfig * configObject() const {
290  if ( !mConfigObject )
291  // this is unsafe. We're a lib, used by concurrent apps.
292  mConfigObject = new TDEConfig( "chiasmusbackendrc" );
293  return mConfigObject;
294  }
295  void clear() {
296  for ( std::map<TQString,ChiasmusConfigEntry*>::const_iterator it = mCache.begin(), end = mCache.end() ; it != end ; ++it )
297  delete it->second;
298  mCache.clear();
299  }
300  };
301 
302  class ChiasmusComponent : public Kleo::CryptoConfigComponent {
303  mutable ChiasmusGeneralGroup * mGeneralGroup;
304  public:
305  ChiasmusComponent() : Kleo::CryptoConfigComponent(), mGeneralGroup( 0 ) {}
306  ~ChiasmusComponent() { delete mGeneralGroup; }
307 
308  void sync() {
309  if ( mGeneralGroup )
310  mGeneralGroup->sync();
311  }
312 
313  TQString name() const { return "Chiasmus"; }
314  TQString iconName() const { return "chiasmus_chi"; }
315  TQString description() const { return i18n( "Chiasmus" ); }
316  TQStringList groupList() const { return TQStringList() << "General"; }
317  Kleo::CryptoConfigGroup * group( const TQString & name ) const {
318  if ( name != "General" )
319  return 0;
320  if ( !mGeneralGroup )
321  mGeneralGroup = new ChiasmusGeneralGroup();
322  return mGeneralGroup;
323  }
324  };
325 
326 }
327 
328 class Kleo::ChiasmusBackend::CryptoConfig : public Kleo::CryptoConfig {
329  mutable ChiasmusComponent * mComponent;
330 public:
331  CryptoConfig() : Kleo::CryptoConfig(), mComponent( 0 ) {}
332  ~CryptoConfig() { delete mComponent; }
333 
334  TQStringList componentList() const { return TQStringList() << "Chiasmus" ; }
335  ChiasmusComponent * component( const TQString & name ) const {
336  if ( name != "Chiasmus" )
337  return 0;
338  if ( !mComponent )
339  mComponent = new ChiasmusComponent();
340  return mComponent;
341  }
342  void sync( bool ) {
343  if ( mComponent )
344  mComponent->sync();
345  }
346  void clear() { delete mComponent; mComponent = 0; }
347 };
348 
349 class Kleo::ChiasmusBackend::Protocol : public Kleo::CryptoBackend::Protocol {
350  Kleo::CryptoConfig * mCryptoConfig;
351 public:
352  Protocol( Kleo::CryptoConfig * config )
353  : Kleo::CryptoBackend::Protocol(), mCryptoConfig( config )
354  {
355  assert( config );
356  }
357  ~Protocol() {}
358 
359  TQString name() const { return "Chiasmus"; }
360  TQString displayName() const { return i18n( "Chiasmus command line tool" ); }
361  KeyListJob * keyListJob( bool, bool, bool ) const { return 0; }
362  EncryptJob * encryptJob( bool, bool ) const { return 0; }
363  DecryptJob * decryptJob() const { return 0; }
364  SignJob * signJob( bool, bool ) const { return 0; }
365  VerifyDetachedJob * verifyDetachedJob( bool ) const { return 0; }
366  VerifyOpaqueJob * verifyOpaqueJob( bool ) const { return 0; }
367  KeyGenerationJob * keyGenerationJob() const { return 0; }
368  ImportJob * importJob() const { return 0; }
369  ExportJob * publicKeyExportJob( bool ) const { return 0; }
370  ExportJob * secretKeyExportJob( bool, const TQString& ) const { return 0; }
371  DownloadJob * downloadJob( bool ) const { return 0; }
372  DeleteJob * deleteJob() const { return 0; }
373  SignEncryptJob * signEncryptJob( bool, bool ) const { return 0; }
374  DecryptVerifyJob * decryptVerifyJob( bool ) const { return 0; }
375  RefreshKeysJob * refreshKeysJob() const { return 0; }
376 
377  SpecialJob * specialJob( const char * type, const TQStringVariantMap & args ) const {
378  if ( tqstricmp( type, "x-obtain-keys" ) == 0 && args.size() == 0 )
379  return new ObtainKeysJob();
380  if ( tqstricmp( type, "x-encrypt" ) == 0 && args.size() == 0 )
381  return new ChiasmusJob( ChiasmusJob::Encrypt );
382  if ( tqstricmp( type, "x-decrypt" ) == 0 && args.size() == 0 )
383  return new ChiasmusJob( ChiasmusJob::Decrypt );
384  kdDebug(5150) << "ChiasmusBackend::Protocol: tried to instantiate unknown job type \""
385  << type << "\"" << endl;
386 
387  return 0;
388  }
389 };
390 
391 Kleo::ChiasmusBackend * Kleo::ChiasmusBackend::self = 0;
392 
393 Kleo::ChiasmusBackend::ChiasmusBackend()
394  : Kleo::CryptoBackend(),
395  mCryptoConfig( 0 ),
396  mProtocol( 0 )
397 {
398  self = this;
399 }
400 
401 Kleo::ChiasmusBackend::~ChiasmusBackend() {
402  self = 0;
403  delete mCryptoConfig;
404  delete mProtocol;
405 }
406 
407 TQString Kleo::ChiasmusBackend::name() const {
408  return "Chiasmus";
409 }
410 
411 TQString Kleo::ChiasmusBackend::displayName() const {
412  return i18n( "Chiasmus" );
413 }
414 
415 Kleo::CryptoConfig * Kleo::ChiasmusBackend::config() const {
416  if ( !mCryptoConfig )
417  mCryptoConfig = new CryptoConfig();
418  return mCryptoConfig;
419 }
420 
421 Kleo::CryptoBackend::Protocol * Kleo::ChiasmusBackend::protocol( const char * name ) const {
422  if ( tqstricmp( name, "Chiasmus" ) != 0 )
423  return 0;
424  if ( !mProtocol )
425  if ( checkForChiasmus() )
426  mProtocol = new Protocol( config() );
427  return mProtocol;
428 }
429 
430 bool Kleo::ChiasmusBackend::checkForOpenPGP( TQString * reason ) const {
431  if ( reason )
432  *reason = i18n( "Unsupported protocol \"%1\"" ).arg( "OpenPGP" );
433  return false;
434 }
435 
436 bool Kleo::ChiasmusBackend::checkForSMIME( TQString * reason ) const {
437  if ( reason )
438  *reason = i18n( "Unsupported protocol \"%1\"" ).arg( "SMIME" );
439  return false;
440 }
441 
442 bool Kleo::ChiasmusBackend::checkForChiasmus( TQString * reason ) const {
443 
444  // kills the protocol instance when we return false:
445  std::unique_ptr<Protocol> tmp( mProtocol );
446  mProtocol = 0;
447 
448  const CryptoConfigEntry * path = config()->entry( "Chiasmus", "General", "path" );
449  assert( path ); assert( path->argType() == CryptoConfigEntry::ArgType_Path );
450  const TQString chiasmus = path->urlValue().path();
451  const TQFileInfo fi( KShell::tildeExpand( chiasmus ) );
452  if ( !fi.isExecutable() ) {
453  if ( reason )
454  *reason = i18n( "File \"%1\" does not exist or is not executable." ).arg( chiasmus );
455  return false;
456  }
457 
458  // FIXME: more checks?
459  mProtocol = tmp.release();
460  return true;
461 }
462 
463 bool Kleo::ChiasmusBackend::checkForProtocol( const char * name, TQString * reason ) const {
464  if ( tqstricmp( name, "Chiasmus" ) == 0 )
465  return checkForChiasmus( reason );
466  if ( reason )
467  *reason = i18n( "Unsupported protocol \"%1\"" ).arg( name );
468  return 0;
469 }
470 
471 bool Kleo::ChiasmusBackend::supportsProtocol( const char * name ) const {
472  return tqstricmp( name, "Chiasmus" ) == 0;
473 }
474 
475 const char * Kleo::ChiasmusBackend::enumerateProtocols( int i ) const {
476  return i == 0 ? "Chiasmus" : 0 ;
477 }
Crypto config for one component (e.g.
Definition: cryptoconfig.h:295
virtual TQString name() const =0
Return the internal name of this component.
virtual TQString iconName() const =0
Return the name of the icon for this component.
virtual TQString description() const =0
Return user-visible description of this component.
virtual TQStringList groupList() const =0
Returns the list of groups that are known about.
virtual CryptoConfigGroup * group(const TQString &name) const =0
Description of a single option.
Definition: cryptoconfig.h:49
virtual void setBoolValue(bool)=0
Define whether the option is set or not (only allowed for ArgType_None)
virtual bool isList() const =0
virtual ArgType argType() const =0
Argument type.
virtual TQValueList< int > intValueList() const =0
Return value as a list of signed ints.
virtual TQStringList stringValueList() const =0
Return value as a list of strings (mostly meaningful for String, Path and URL argtypes,...
virtual void setNumberOfTimesSet(unsigned int)=0
Set the number of times the option is set (only valid for ArgType_None, if isList())
virtual void setUIntValueList(const TQValueList< unsigned int > &)=0
Set a new list of unsigned int values.
virtual bool isDirty() const =0
virtual void setStringValueList(const TQStringList &)=0
Set a new string-list value (only allowed for String, Path and URL argtypes, if isList())
virtual bool isOptional() const =0
virtual KURL::List urlValueList() const =0
Return value as a list of URLs (only meaningful for Path and URL argtypes, if isList())
virtual TQString name() const =0
Return the internal name of this entry.
virtual void setURLValue(const KURL &)=0
Set value as a URL (only meaningful for Path (if local) and URL argtypes)
virtual TQString stringValue() const =0
Return value as a string (available for all argtypes) The returned string can be empty (explicitely s...
virtual unsigned int uintValue() const =0
Return value as an unsigned int.
virtual void setUIntValue(unsigned int)=0
Set a new unsigned int value.
virtual Level level() const =0
User level.
virtual TQString description() const =0
virtual bool boolValue() const =0
Return value as a bool (only allowed for ArgType_None)
virtual int intValue() const =0
Return value as a signed int.
virtual KURL urlValue() const =0
Return value as a URL (only meaningful for Path and URL argtypes)
virtual TQValueList< unsigned int > uintValueList() const =0
Return value as a list of unsigned ints.
virtual unsigned int numberOfTimesSet() const =0
Return number of times the option is set (only valid for ArgType_None, if isList())
virtual bool isRuntime() const =0
virtual void setURLValueList(const KURL::List &)=0
Set value as a URL list (only meaningful for Path (if all URLs are local) and URL argtypes,...
virtual void setStringValue(const TQString &)=0
Set string value (allowed for all argtypes)
virtual void setIntValueList(const TQValueList< int > &)=0
Set a new list of signed int values.
virtual void resetToDefault()=0
Reset an option to its default value.
virtual bool isSet() const =0
Return true if the option is set, i.e.
virtual void setIntValue(int)=0
Set a new signed int value.
virtual bool isReadOnly() const =0
Group containing a set of config options.
Definition: cryptoconfig.h:252
virtual CryptoConfigEntry::Level level() const =0
User level.
virtual CryptoConfigEntry * entry(const TQString &name) const =0
virtual TQString description() const =0
virtual TQStringList entryList() const =0
Returns the list of entries that are known by this group.
virtual TQString iconName() const =0
Return the name of the icon for this group.
virtual TQString name() const =0
Return the internal name of this group.
Main interface to crypto configuration.
Definition: cryptoconfig.h:334
virtual void sync(bool runtime)=0
Write back changes.
virtual void clear()=0
Tells the CryptoConfig to discard any cached information, including all components,...
virtual TQStringList componentList() const =0
Returns the list of known components (e.g.
virtual CryptoConfigComponent * component(const TQString &name) const =0