diff options
Diffstat (limited to 'certmanager/lib')
177 files changed, 25848 insertions, 0 deletions
diff --git a/certmanager/lib/Makefile.am b/certmanager/lib/Makefile.am new file mode 100644 index 000000000..ae101fd0e --- /dev/null +++ b/certmanager/lib/Makefile.am @@ -0,0 +1,49 @@ +INCLUDES = -I$(top_srcdir)/libkdenetwork $(GPGME_CFLAGS) $(all_includes) + +SUBDIRS = pics kleo backends ui . tests + +lib_LTLIBRARIES = libkleopatra.la + +libkleopatra_la_SOURCES = \ + cryptplug.cpp \ + cryptplugwrapper.cpp \ + cryptplugwrapperlist.cpp \ + cryptplugfactory.cpp + +libkleopatra_la_LIBADD = \ + kleo/libkleopatra_core.la \ + backends/qgpgme/libkleopatra_backend_qgpgme.la \ + backends/chiasmus/libkleopatra_backend_chiasmus.la \ + ui/libkleopatra_ui.la \ + \ + $(top_builddir)/libkdenetwork/qgpgme/libqgpgme.la \ + $(LIB_KIO) $(LIB_KDEUI) + +# Disabled for kdepim-3.3, see also kleo/cryptobackendfactory.cpp +# backends/kpgp/libkleopatra_backend_kpgp.la + +# --version-info CURRENT:REVISION:AGE +# (Code changed: REVISION++) +# (Interfaces added/removed/changed: CURRENT++, REVISION=0) +# (Interfaces added: AGE++) +# (Interfaces removed/changed: AGE=0) +libkleopatra_la_LDFLAGS = $(all_libraries) -version-info 1:0:0 -no-undefined + +METASOURCES = AUTO + +# remove the .desktop suffix on install (which is needed for translation) +install-data-local: + $(mkinstalldirs) $(DESTDIR)$(kde_confdir) + $(INSTALL_DATA) $(srcdir)/libkleopatrarc.desktop $(DESTDIR)$(kde_confdir)/libkleopatrarc + +uninstall-local: + rm -f $(DESTDIR)$(kde_confdir)/libkleopatrarc + +messages: #rc.cpp + $(EXTRACTRC) */*.ui > rc.cpp + $(XGETTEXT) *.cpp *.h \ + kleo/*.cpp kleo/*.h \ + ui/*.cpp ui/*.h \ + backends/*/*.cpp backends/*/*.h -o $(podir)/libkleopatra.pot + +include $(top_srcdir)/admin/Doxyfile.am diff --git a/certmanager/lib/backends/Makefile.am b/certmanager/lib/backends/Makefile.am new file mode 100644 index 000000000..0219d7627 --- /dev/null +++ b/certmanager/lib/backends/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = qgpgme chiasmus diff --git a/certmanager/lib/backends/chiasmus/Makefile.am b/certmanager/lib/backends/chiasmus/Makefile.am new file mode 100644 index 000000000..8a5d85bd4 --- /dev/null +++ b/certmanager/lib/backends/chiasmus/Makefile.am @@ -0,0 +1,16 @@ +INCLUDES = -I$(top_srcdir)/certmanager/lib -I$(top_srcdir)/libkdenetwork $(GPGME_CFLAGS) $(all_includes) + +KDE_CXXFLAGS = '-DGPG_ERR_SOURCE_DEFAULT=((gpg_err_source_t)176)' + +noinst_LTLIBRARIES = libkleopatra_backend_chiasmus.la + +libkleopatra_backend_chiasmus_la_SOURCES = \ + config_data.c \ + obtainkeysjob.cpp \ + symcryptrunprocessbase.cpp \ + chiasmusjob.cpp \ + chiasmuslibrary.cpp \ + chiasmusbackend.cpp + + +METASOURCES = AUTO diff --git a/certmanager/lib/backends/chiasmus/chiasmusbackend.cpp b/certmanager/lib/backends/chiasmus/chiasmusbackend.cpp new file mode 100644 index 000000000..15a63de53 --- /dev/null +++ b/certmanager/lib/backends/chiasmus/chiasmusbackend.cpp @@ -0,0 +1,480 @@ +/* + chiasmusbackend.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2005 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "chiasmusbackend.h" + +#include "config_data.h" +#include "obtainkeysjob.h" +#include "chiasmusjob.h" + +#include "kleo/cryptoconfig.h" + +#include <klocale.h> +#include <kconfig.h> +#include <kshell.h> +#include <kdebug.h> + +#include <qstringlist.h> +#include <qvariant.h> +#include <qfileinfo.h> + +#include <map> +#include <memory> + +#include <cassert> + +namespace { + + // + // The usual QVariant template helpers: + // + + // to<> is a demarshaller. It's a class b/c you can't partially + // specialise function templates yet. However, to<> can be used as if + // it was a function: QString s = to<QString>( myVariant ); + template <typename T> class to {}; + +#define MAKE_TO( type, func ) \ + template <> \ + class to< type > { \ + type m; \ + public: \ + to( const QVariant & v ) : m( v.func() ) {} \ + operator type() const { return m; } \ + } + + MAKE_TO( int, toInt ); + MAKE_TO( unsigned int, toUInt ); + + template <> + class to<KURL> { + KURL m; + public: + to( const QVariant & v ) { + m.setPath( v.toString() ); + } + operator KURL() const { return m; } + }; + + template <typename T> + class to< QValueList<T> > { + QValueList<T> m; + public: + to( const QVariant & v ) { + const QValueList<QVariant> vl = v.toList(); + for ( QValueList<QVariant>::const_iterator it = vl.begin(), end = vl.end() ; it != end ; ++it ) + m.push_back( to<T>( *it ) ); + } + operator QValueList<T> () const { return m; } + }; + + template <> + class to<KURL::List> { + KURL::List m; + public: + to( const QVariant & v ) { + // wow, KURL::List is broken... it lacks conversion from and to QVL<KURL>... + m += to< QValueList<KURL> >( v ); + } + operator KURL::List() const { return m; } + }; + + + // from<> is the demarshaller. See to<> for why this is a class... + + template <typename T> + struct from_helper : public QVariant { + from_helper( const T & t ) : QVariant( t ) {} + }; + + template <typename T> + QVariant from( const T & t ) { + return from_helper<T>( t ); + } + + // some special types: + template <> struct from_helper<bool> : public QVariant { + from_helper( bool b ) : QVariant( b, int() ) {} + }; + template <> struct from_helper<KURL> : public QVariant { + from_helper( const KURL & url ) : QVariant( url.path() ) {} + }; + template <typename T> struct from_helper< QValueList<T> > : public QVariant { + from_helper( const QValueList<T> & l ) { + QValueList<QVariant> result; + for ( typename QValueList<T>::const_iterator it = l.begin(), end = l.end() ; it != end ; ++it ) + result.push_back( from( *it ) ); + QVariant::operator=( result ); + } + }; + template <> struct from_helper<KURL::List> : public from_helper< QValueList<KURL> > { + from_helper( const KURL::List & l ) : from_helper< QValueList<KURL> >( l ) {} + }; + + class ChiasmusConfigEntry : public Kleo::CryptoConfigEntry { + unsigned int mIdx; + QVariant mValue; + bool mDirty; + public: + ChiasmusConfigEntry( unsigned int i ) + : Kleo::CryptoConfigEntry(), + mIdx( i ), mValue( defaultValue() ), mDirty( false ) + { + assert( i < kleo_chiasmus_config_entries_dim ); + } + QString name() const { return kleo_chiasmus_config_entries[mIdx].name; } + QString description() const { return i18n( kleo_chiasmus_config_entries[mIdx].description ); } + bool isOptional() const { return kleo_chiasmus_config_entries[mIdx].is_optional; } + bool isReadOnly() const { return false; } + bool isList() const { return kleo_chiasmus_config_entries[mIdx].is_list; } + bool isRuntime() const { return kleo_chiasmus_config_entries[mIdx].is_runtime; } + Level level() const { return static_cast<Level>( kleo_chiasmus_config_entries[mIdx].level ); } + ArgType argType() const { return static_cast<ArgType>( kleo_chiasmus_config_entries[mIdx].type ); } + bool isSet() const { return mValue != defaultValue(); } + bool boolValue() const { return mValue.toBool(); } + QString stringValue() const { return mValue.toString(); } + int intValue() const { return mValue.toInt(); } + unsigned int uintValue() const { return mValue.toUInt(); } + KURL urlValue() const { + if ( argType() != ArgType_Path && argType() != ArgType_DirPath ) return KURL( mValue.toString() ); + KURL u; u.setPath( mValue.toString() ); return u; + } + unsigned int numberOfTimesSet() const { return 0; } + QStringList stringValueList() const { return mValue.toStringList(); } + QValueList<int> intValueList() const { return to< QValueList<int> >( mValue ); } + QValueList<unsigned int> uintValueList() const { return to< QValueList<unsigned int> >( mValue ); } + KURL::List urlValueList() const { + if ( argType() != ArgType_Path && argType()!= ArgType_DirPath ) return mValue.toStringList(); + else return to<KURL::List>( mValue ); } + void resetToDefault() { mValue = defaultValue(); mDirty = false; } + void setBoolValue( bool value ) { setValue( QVariant( value, int() ) ); } + void setStringValue( const QString & value ) { setValue( value ); } + void setIntValue( int value ) { setValue( value ); } + void setUIntValue( unsigned int value ) { setValue( value ); } + void setURLValue( const KURL & value ) { + if ( argType() != ArgType_Path && argType()!= ArgType_DirPath ) setValue( value.url() ); + else setValue( value.path() ); + } + void setNumberOfTimesSet( unsigned int ) {} + void setStringValueList( const QStringList & value ) { setValue( value ); } + void setIntValueList( const QValueList<int> & l ) { setValue( from( l ) ); } + void setUIntValueList( const QValueList<unsigned int> & l ) { setValue( from( l ) ); } + void setURLValueList( const KURL::List & l ) { setValue( from( l ) ); } + bool isDirty() const { return mDirty; } + + QVariant value() const { return mValue; } + + void sync( KConfigBase * config ) { + if ( !mDirty ) + return; + mDirty = false; + config->writeEntry( kleo_chiasmus_config_entries[mIdx].name, mValue ); + } + void read( const KConfigBase * config ) { + mDirty = false; + mValue = config->readPropertyEntry( kleo_chiasmus_config_entries[mIdx].name, defaultValue() ); + } + private: + QVariant defaultValue() const; + void setValue( const QVariant & value ) { mValue = value; mDirty = true; } + }; + + QVariant ChiasmusConfigEntry::defaultValue() const { + const kleo_chiasmus_config_data & data = kleo_chiasmus_config_entries[mIdx]; + switch ( data.type ) { + default: + return QVariant(); + case ArgType_None: + if ( isList() ) + return QValueList<QVariant>() << QVariant( data.defaults.boolean.value, int() ); + else + return QVariant( data.defaults.boolean.value, int() ); + case ArgType_String: + if ( isList() ) + return QStringList( QString::fromLatin1( data.defaults.string ) ); + else + return QString::fromLatin1( data.defaults.string ); + case ArgType_Int: + if ( isList() ) + return QValueList<QVariant>() << data.defaults.integer; + else + return data.defaults.integer; + case ArgType_UInt: + if ( isList() ) + return QValueList<QVariant>() << data.defaults.unsigned_integer; + else + return data.defaults.unsigned_integer; + case ArgType_Path: + case ArgType_DirPath: + if ( isList() ) + return QValueList<QVariant>() << QString::fromLatin1( data.defaults.path ); + else + return QString::fromLatin1( data.defaults.path ); + case ArgType_URL: + case ArgType_LDAPURL: + if ( isList() ) + return QValueList<QVariant>() << QString::fromLatin1( data.defaults.url ); + else + return QString::fromLatin1( data.defaults.url ); + } + } + + class ChiasmusGeneralGroup : public Kleo::CryptoConfigGroup { + mutable std::map<QString,ChiasmusConfigEntry*> mCache; + mutable KConfig * mConfigObject; + public: + ChiasmusGeneralGroup() : Kleo::CryptoConfigGroup(), mConfigObject( 0 ) {} + ~ChiasmusGeneralGroup() { clear(); delete mConfigObject; } + QString name() const { return "General"; } + QString iconName() const { return "chiasmus_chi"; } + QString description() const { return i18n( "General" ); } + Kleo::CryptoConfigEntry::Level level() const { return Kleo::CryptoConfigEntry::Level_Basic; } + QStringList entryList() const { + QStringList result; + for ( unsigned int i = 0 ; i < kleo_chiasmus_config_entries_dim ; ++i ) + result.push_back( kleo_chiasmus_config_entries[i].name ); + return result; + } + Kleo::CryptoConfigEntry * entry( const QString & name ) const { + if ( ChiasmusConfigEntry * entry = mCache[name] ) + return entry; + const KConfigGroup group( configObject(), "Chiasmus" ); + for ( unsigned int i = 0 ; i < kleo_chiasmus_config_entries_dim ; ++i ) + if ( name == kleo_chiasmus_config_entries[i].name ) { + ChiasmusConfigEntry * entry = new ChiasmusConfigEntry( i ); + entry->read( &group ); + return mCache[name] = entry; + } + return 0; + } + + void sync() { + KConfigGroup group( configObject(), "Chiasmus" ); + for ( std::map<QString,ChiasmusConfigEntry*>::const_iterator it = mCache.begin(), end = mCache.end() ; it != end ; ++it ) + it->second->sync( &group ); + group.sync(); + clear(); + } + private: + KConfig * configObject() const { + if ( !mConfigObject ) + // this is unsafe. We're a lib, used by concurrent apps. + mConfigObject = new KConfig( "chiasmusbackendrc" ); + return mConfigObject; + } + void clear() { + for ( std::map<QString,ChiasmusConfigEntry*>::const_iterator it = mCache.begin(), end = mCache.end() ; it != end ; ++it ) + delete it->second; + mCache.clear(); + } + }; + + class ChiasmusComponent : public Kleo::CryptoConfigComponent { + mutable ChiasmusGeneralGroup * mGeneralGroup; + public: + ChiasmusComponent() : Kleo::CryptoConfigComponent(), mGeneralGroup( 0 ) {} + ~ChiasmusComponent() { delete mGeneralGroup; } + + void sync() { + if ( mGeneralGroup ) + mGeneralGroup->sync(); + } + + QString name() const { return "Chiasmus"; } + QString iconName() const { return "chiasmus_chi"; } + QString description() const { return i18n( "Chiasmus" ); } + QStringList groupList() const { return QStringList() << "General"; } + Kleo::CryptoConfigGroup * group( const QString & name ) const { + if ( name != "General" ) + return 0; + if ( !mGeneralGroup ) + mGeneralGroup = new ChiasmusGeneralGroup(); + return mGeneralGroup; + } + }; + +} + +class Kleo::ChiasmusBackend::CryptoConfig : public Kleo::CryptoConfig { + mutable ChiasmusComponent * mComponent; +public: + CryptoConfig() : Kleo::CryptoConfig(), mComponent( 0 ) {} + ~CryptoConfig() { delete mComponent; } + + QStringList componentList() const { return QStringList() << "Chiasmus" ; } + ChiasmusComponent * component( const QString & name ) const { + if ( name != "Chiasmus" ) + return 0; + if ( !mComponent ) + mComponent = new ChiasmusComponent(); + return mComponent; + } + void sync( bool ) { + if ( mComponent ) + mComponent->sync(); + } + void clear() { delete mComponent; mComponent = 0; } +}; + +class Kleo::ChiasmusBackend::Protocol : public Kleo::CryptoBackend::Protocol { + Kleo::CryptoConfig * mCryptoConfig; +public: + Protocol( Kleo::CryptoConfig * config ) + : Kleo::CryptoBackend::Protocol(), mCryptoConfig( config ) + { + assert( config ); + } + ~Protocol() {} + + QString name() const { return "Chiasmus"; } + QString displayName() const { return i18n( "Chiasmus command line tool" ); } + KeyListJob * keyListJob( bool, bool, bool ) const { return 0; } + EncryptJob * encryptJob( bool, bool ) const { return 0; } + DecryptJob * decryptJob() const { return 0; } + SignJob * signJob( bool, bool ) const { return 0; } + VerifyDetachedJob * verifyDetachedJob( bool ) const { return 0; } + VerifyOpaqueJob * verifyOpaqueJob( bool ) const { return 0; } + KeyGenerationJob * keyGenerationJob() const { return 0; } + ImportJob * importJob() const { return 0; } + ExportJob * publicKeyExportJob( bool ) const { return 0; } + ExportJob * secretKeyExportJob( bool, const QString& ) const { return 0; } + DownloadJob * downloadJob( bool ) const { return 0; } + DeleteJob * deleteJob() const { return 0; } + SignEncryptJob * signEncryptJob( bool, bool ) const { return 0; } + DecryptVerifyJob * decryptVerifyJob( bool ) const { return 0; } + RefreshKeysJob * refreshKeysJob() const { return 0; } + + SpecialJob * specialJob( const char * type, const QMap<QString,QVariant> & args ) const { + if ( qstricmp( type, "x-obtain-keys" ) == 0 && args.size() == 0 ) + return new ObtainKeysJob(); + if ( qstricmp( type, "x-encrypt" ) == 0 && args.size() == 0 ) + return new ChiasmusJob( ChiasmusJob::Encrypt ); + if ( qstricmp( type, "x-decrypt" ) == 0 && args.size() == 0 ) + return new ChiasmusJob( ChiasmusJob::Decrypt ); + kdDebug(5150) << "ChiasmusBackend::Protocol: tried to instantiate unknown job type \"" + << type << "\"" << endl; + + return 0; + } +}; + +Kleo::ChiasmusBackend * Kleo::ChiasmusBackend::self = 0; + +Kleo::ChiasmusBackend::ChiasmusBackend() + : Kleo::CryptoBackend(), + mCryptoConfig( 0 ), + mProtocol( 0 ) +{ + self = this; +} + +Kleo::ChiasmusBackend::~ChiasmusBackend() { + self = 0; + delete mCryptoConfig; + delete mProtocol; +} + +QString Kleo::ChiasmusBackend::name() const { + return "Chiasmus"; +} + +QString Kleo::ChiasmusBackend::displayName() const { + return i18n( "Chiasmus" ); +} + +Kleo::CryptoConfig * Kleo::ChiasmusBackend::config() const { + if ( !mCryptoConfig ) + mCryptoConfig = new CryptoConfig(); + return mCryptoConfig; +} + +Kleo::CryptoBackend::Protocol * Kleo::ChiasmusBackend::protocol( const char * name ) const { + if ( qstricmp( name, "Chiasmus" ) != 0 ) + return 0; + if ( !mProtocol ) + if ( checkForChiasmus() ) + mProtocol = new Protocol( config() ); + return mProtocol; +} + +bool Kleo::ChiasmusBackend::checkForOpenPGP( QString * reason ) const { + if ( reason ) + *reason = i18n( "Unsupported protocol \"%1\"" ).arg( "OpenPGP" ); + return false; +} + +bool Kleo::ChiasmusBackend::checkForSMIME( QString * reason ) const { + if ( reason ) + *reason = i18n( "Unsupported protocol \"%1\"" ).arg( "SMIME" ); + return false; +} + +bool Kleo::ChiasmusBackend::checkForChiasmus( QString * reason ) const { + + // kills the protocol instance when we return false: + std::auto_ptr<Protocol> tmp( mProtocol ); + mProtocol = 0; + + const CryptoConfigEntry * path = config()->entry( "Chiasmus", "General", "path" ); + assert( path ); assert( path->argType() == CryptoConfigEntry::ArgType_Path ); + const QString chiasmus = path->urlValue().path(); + const QFileInfo fi( KShell::tildeExpand( chiasmus ) ); + if ( !fi.isExecutable() ) { + if ( reason ) + *reason = i18n( "File \"%1\" does not exist or is not executable." ).arg( chiasmus ); + return false; + } + + // FIXME: more checks? + mProtocol = tmp.release(); + return true; +} + +bool Kleo::ChiasmusBackend::checkForProtocol( const char * name, QString * reason ) const { + if ( qstricmp( name, "Chiasmus" ) == 0 ) + return checkForChiasmus( reason ); + if ( reason ) + *reason = i18n( "Unsupported protocol \"%1\"" ).arg( name ); + return 0; +} + +bool Kleo::ChiasmusBackend::supportsProtocol( const char * name ) const { + return qstricmp( name, "Chiasmus" ) == 0; +} + +const char * Kleo::ChiasmusBackend::enumerateProtocols( int i ) const { + return i == 0 ? "Chiasmus" : 0 ; +} diff --git a/certmanager/lib/backends/chiasmus/chiasmusbackend.h b/certmanager/lib/backends/chiasmus/chiasmusbackend.h new file mode 100644 index 000000000..6d51cad77 --- /dev/null +++ b/certmanager/lib/backends/chiasmus/chiasmusbackend.h @@ -0,0 +1,86 @@ +/* -*- mode: C++; c-file-style: "gnu" -*- + chiasmusbackend.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2005 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + + +#ifndef __KLEO_CHIASMUSBACKEND_H__ +#define __KLEO_CHIASMUSBACKEND_H__ + +#include "kleo/cryptobackend.h" + +class CryptPlugWrapper; + +namespace Kleo { + class CryptoConfig; +} +class QString; + +namespace Kleo { + + class ChiasmusBackend : public Kleo::CryptoBackend { + public: + ChiasmusBackend(); + ~ChiasmusBackend(); + + static const ChiasmusBackend * instance() { return self; } + + QString name() const; + QString displayName() const; + + Kleo::CryptoConfig * config() const; + + Kleo::CryptoBackend::Protocol * openpgp() const { return 0; } + Kleo::CryptoBackend::Protocol * smime() const { return 0; } + Kleo::CryptoBackend::Protocol * protocol( const char * name ) const; + + bool checkForOpenPGP( QString * reason=0 ) const; + bool checkForSMIME( QString * reason=0 ) const; + bool checkForChiasmus( QString * reason=0 ) const; + bool checkForProtocol( const char * name, QString * reason=0 ) const; + + bool supportsOpenPGP() const { return false; } + bool supportsSMIME() const { return false; } + bool supportsProtocol( const char * name ) const; + + const char * enumerateProtocols( int i ) const; + + private: + class CryptoConfig; + class Protocol; + mutable CryptoConfig * mCryptoConfig; + mutable Protocol * mProtocol; + static ChiasmusBackend * self; + }; + +} + + +#endif // __KLEO_CHIASMUSBACKEND_H__ diff --git a/certmanager/lib/backends/chiasmus/chiasmusjob.cpp b/certmanager/lib/backends/chiasmus/chiasmusjob.cpp new file mode 100644 index 000000000..3ac7513df --- /dev/null +++ b/certmanager/lib/backends/chiasmus/chiasmusjob.cpp @@ -0,0 +1,220 @@ +/* + chiasmusjob.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2005 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "chiasmusjob.h" +#include "chiasmusbackend.h" +#include "symcryptrunprocessbase.h" + +#include "kleo/cryptoconfig.h" +#include "ui/passphrasedialog.h" + +#include <gpg-error.h> + +#include <kshell.h> +#include <klocale.h> +#include <kdebug.h> +#include <kmessagebox.h> + +#include <qtimer.h> +#include <qfileinfo.h> +#include <qvariant.h> + +#include <memory> + +#include <cassert> + +Kleo::ChiasmusJob::ChiasmusJob( Mode mode ) + : Kleo::SpecialJob( 0, 0 ), + mSymCryptRun( 0 ), + mError( 0 ), + mCanceled( false ), + mTimeout( false ), + mMode( mode ) +{ + +} + +Kleo::ChiasmusJob::~ChiasmusJob() {} + +GpgME::Error Kleo::ChiasmusJob::setup() { + if ( !checkPreconditions() ) + return mError = gpg_error( GPG_ERR_INV_VALUE ); + + const Kleo::CryptoConfigEntry * class_ + = ChiasmusBackend::instance()->config()->entry( "Chiasmus", "General", "symcryptrun-class" ); + const Kleo::CryptoConfigEntry * chiasmus + = ChiasmusBackend::instance()->config()->entry( "Chiasmus", "General", "path" ); + const Kleo::CryptoConfigEntry * timeoutEntry + = ChiasmusBackend::instance()->config()->entry( "Chiasmus", "General", "timeout" ); + if ( !class_ || !chiasmus || !timeoutEntry ) + return mError = gpg_error( GPG_ERR_INTERNAL ); + + mSymCryptRun = new SymCryptRunProcessBase( class_->stringValue(), + KShell::tildeExpand( chiasmus->urlValue().path() ), + mKey, mOptions, + mMode == Encrypt + ? SymCryptRunProcessBase::Encrypt + : SymCryptRunProcessBase::Decrypt, + this, "symcryptrun" ); + QTimer::singleShot( timeoutEntry->uintValue() * 1000, this, + SLOT( slotTimeout() ) ); + return 0; +} + +namespace { + struct LaterDeleter { + QObject * _this; + LaterDeleter( QObject * o ) : _this( o ) {} + ~LaterDeleter() { if ( _this ) _this->deleteLater(); } + void disable() { _this = 0; } + }; +} + +GpgME::Error Kleo::ChiasmusJob::start() { + + LaterDeleter d( this ); + + if ( const GpgME::Error err = setup() ) + return mError = err; + + connect( mSymCryptRun, SIGNAL(processExited(KProcess*)), + this, SLOT(slotProcessExited(KProcess*)) ); + + if ( !mSymCryptRun->launch( mInput ) ) + return mError = gpg_error( GPG_ERR_ENOENT ); // what else? + + d.disable(); + return mError = 0; +} + +GpgME::Error Kleo::ChiasmusJob::slotProcessExited( KProcess * proc ) { + if ( proc != mSymCryptRun ) + mError = gpg_error( GPG_ERR_INTERNAL ); + else if ( mCanceled ) + mError = gpg_error( GPG_ERR_CANCELED ); + else if ( mTimeout ) + mError = gpg_error( GPG_ERR_TIMEOUT ); + else if ( !proc->normalExit() ) + mError = gpg_error( GPG_ERR_GENERAL ); + else + switch ( proc->exitStatus() ) { + case 0: // success + mOutput = mSymCryptRun->output(); + mError = 0; + break; + default: + case 1: // Some error occured + mStderr = mSymCryptRun->stdErr(); + mError = gpg_error( GPG_ERR_GENERAL ); + break; + case 2: // No valid passphrase was provided + mError = gpg_error( GPG_ERR_INV_PASSPHRASE ); + break; + case 3: // Canceled + mError = gpg_error( GPG_ERR_CANCELED ); + break; + } + + const Kleo::CryptoConfigEntry * showOutput + = ChiasmusBackend::instance()->config()->entry( "Chiasmus", "General", "show-output" ); + if ( showOutput && showOutput->boolValue() ) { + showChiasmusOutput(); + } + + emit done(); + emit SpecialJob::result( mError, QVariant( mOutput ) ); + return mError; +} + +void Kleo::ChiasmusJob::showChiasmusOutput() { + kdDebug() << k_funcinfo << endl; + if ( mStderr.isEmpty() ) + return; + KMessageBox::information( 0 /*how to get a parent widget?*/, + mStderr, + i18n( "Output from chiasmus" ) ); +} + +GpgME::Error Kleo::ChiasmusJob::exec() { + if ( const GpgME::Error err = setup() ) + return mError = err; + + if ( !mSymCryptRun->launch( mInput, KProcess::Block ) ) { + delete mSymCryptRun; mSymCryptRun = 0; + return mError = gpg_error( GPG_ERR_ENOENT ); // what else? + } + + const GpgME::Error err = slotProcessExited( mSymCryptRun ); + delete mSymCryptRun; mSymCryptRun = 0; + return err; +} + +bool Kleo::ChiasmusJob::checkPreconditions() const { + return !mKey.isEmpty(); +} + +void Kleo::ChiasmusJob::slotCancel() { + if ( mSymCryptRun ) + mSymCryptRun->kill(); + mCanceled = true; +} + +void Kleo::ChiasmusJob::slotTimeout() { + if ( !mSymCryptRun ) + return; + mSymCryptRun->kill(); + mTimeout = true; +} + + +void Kleo::ChiasmusJob::showErrorDialog( QWidget * parent, const QString & caption ) const { + if ( !mError ) + return; + if ( mError.isCanceled() ) + return; + const QString msg = ( mMode == Encrypt + ? i18n( "Encryption failed: %1" ) + : i18n( "Decryption failed: %1" ) ) + .arg( QString::fromLocal8Bit( mError.asString() ) ); + if ( !mStderr.isEmpty() ) { + const QString details = i18n( "The following was received on stderr:\n%1" ).arg( mStderr ); + KMessageBox::detailedError( parent, msg, details, caption ); + } else { + KMessageBox::error( parent, msg, caption ); + } +} + +#include "chiasmusjob.moc" diff --git a/certmanager/lib/backends/chiasmus/chiasmusjob.h b/certmanager/lib/backends/chiasmus/chiasmusjob.h new file mode 100644 index 000000000..6393a0905 --- /dev/null +++ b/certmanager/lib/backends/chiasmus/chiasmusjob.h @@ -0,0 +1,116 @@ +/* -*- mode: C++; c-file-style: "gnu" -*- + chiasmusjob.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2005 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + + +#ifndef __KLEO_CHIASMUSJOB_H__ +#define __KLEO_CHIASMUSJOB_H__ + +#include "kleo/specialjob.h" + +#include <qstringlist.h> + +#include <gpgmepp/context.h> + +class KProcess; + +namespace Kleo { + + class SymCryptRunProcessBase; + + /** + @short SpecialJob for Chiasmus operations + */ + class ChiasmusJob : public Kleo::SpecialJob { + Q_OBJECT + Q_ENUMS( Mode ) + Q_PROPERTY( Mode mode READ mode ) + Q_PROPERTY( QString key READ key WRITE setKey ) + Q_PROPERTY( QString options READ options WRITE setOptions ) + Q_PROPERTY( QByteArray input READ input WRITE setInput ) + Q_PROPERTY( QByteArray result READ result ) + public: + enum Mode { + Encrypt, Decrypt + }; + ChiasmusJob( Mode op ); + ~ChiasmusJob(); + + /*!\reimp SpecialJob */ + GpgME::Error start(); + /*!\reimp SpecialJob */ + GpgME::Error exec(); + + /*!\reimp Kleo::Job */ + void showErrorDialog( QWidget *, const QString & ) const; + + Mode mode() const { return mMode; } + + QString key() const { return mKey; } + void setKey( const QString & key ) { mKey = key; } + + QString options() const { return mOptions; } + void setOptions( const QString & options ) { mOptions = options; } + + QByteArray input() const { return mInput; } + void setInput( const QByteArray & input ) { mInput = input; } + + //using SpecialJob::result; + QByteArray result() const { return mOutput; } + + public slots: + void slotCancel(); + + private slots: + GpgME::Error slotProcessExited( KProcess * ); + void slotTimeout(); + + private: + bool checkPreconditions() const; + GpgME::Error setup(); + void showChiasmusOutput(); + + private: + SymCryptRunProcessBase * mSymCryptRun; + QString mKey; + QString mOptions; + QByteArray mInput, mOutput; + GpgME::Error mError; + QString mStderr; + bool mCanceled; + bool mTimeout; + const Mode mMode; + }; + +} + + +#endif // __KLEO_CHIASMUSJOB_H__ diff --git a/certmanager/lib/backends/chiasmus/chiasmuslibrary.cpp b/certmanager/lib/backends/chiasmus/chiasmuslibrary.cpp new file mode 100644 index 000000000..2e3225492 --- /dev/null +++ b/certmanager/lib/backends/chiasmus/chiasmuslibrary.cpp @@ -0,0 +1,115 @@ +/* + chiasmuslibrary.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2005 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + + +#include "chiasmuslibrary.h" + +#include "chiasmusbackend.h" + +#include "kleo/cryptoconfig.h" + +#include <klibloader.h> +#include <kdebug.h> +#include <klocale.h> + +#include <qfile.h> + +#include <vector> +#include <algorithm> + +#include <cassert> +#include <cstdlib> +#include <cstring> + +Kleo::ChiasmusLibrary * Kleo::ChiasmusLibrary::self = 0; + +Kleo::ChiasmusLibrary::ChiasmusLibrary() : mXiaLibrary( 0 ) { + self = this; +} + +Kleo::ChiasmusLibrary::~ChiasmusLibrary() { + //delete mXiaLibrary; // hmm, how to get rid of it, then? +} + +Kleo::ChiasmusLibrary::main_func Kleo::ChiasmusLibrary::chiasmus( QString * reason ) const { + assert( ChiasmusBackend::instance() ); + assert( ChiasmusBackend::instance()->config() ); + const CryptoConfigEntry * lib = ChiasmusBackend::instance()->config()->entry( "Chiasmus", "General", "lib" ); + assert( lib ); + const QString libfile = lib->urlValue().path(); + if ( !mXiaLibrary ) + mXiaLibrary = KLibLoader::self()->library( QFile::encodeName( libfile ) ); + if ( !mXiaLibrary ) { + if ( reason ) + *reason = i18n( "Failed to load %1: %2" ) + .arg( libfile,KLibLoader::self()->lastErrorMessage() ); + kdDebug(5150) << "ChiasmusLibrary: loading \"" << libfile + << "\" failed: " << KLibLoader::self()->lastErrorMessage() << endl; + return 0; + } + if ( !mXiaLibrary->hasSymbol( "Chiasmus" ) ) { + if ( reason ) + *reason = i18n( "Failed to load %1: %2" ) + .arg( libfile, i18n( "Library does not contain the symbol \"Chiasmus\"." ) ); + kdDebug(5150) << "ChiasmusLibrary: loading \"" << libfile + << "\" failed: " << "Library does not contain the symbol \"Chiasmus\"." << endl; + return 0; + } + void * symbol = mXiaLibrary->symbol( "Chiasmus" ); + assert( symbol ); + return ( main_func )symbol; +} + +namespace { + class ArgvProvider { + char ** mArgv; + int mArgc; + public: + ArgvProvider( const QValueVector<QCString> & args ) { + mArgv = new char * [args.size()]; + for ( unsigned int i = 0 ; i < args.size() ; ++i ) + mArgv[i] = strdup( args[i].data() ); + } + ~ArgvProvider() { + std::for_each( mArgv, mArgv + mArgc, std::free ); + delete[] mArgv; + } + char ** argv() const { return mArgv; } + }; +} + +int Kleo::ChiasmusLibrary::perform( const QValueVector<QCString> & args ) const { + if ( main_func func = chiasmus() ) + return func( args.size(), ArgvProvider( args ).argv() ); + else + return -1; +} diff --git a/certmanager/lib/backends/chiasmus/chiasmuslibrary.h b/certmanager/lib/backends/chiasmus/chiasmuslibrary.h new file mode 100644 index 000000000..b04e162b4 --- /dev/null +++ b/certmanager/lib/backends/chiasmus/chiasmuslibrary.h @@ -0,0 +1,68 @@ +/* -*- mode: C++; c-file-style: "gnu" -*- + chiasmuslibrary.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2005 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + + +#ifndef __KLEO_CHIASMUSLIBRARY_H__ +#define __KLEO_CHIASMUSLIBRARY_H__ + +#include <qvaluevector.h> +#include <qcstring.h> + +class KLibrary; + +namespace Kleo { + + /** + @short small helper class to load xia.o through xia.so and make + the functionality available. + */ + class ChiasmusLibrary { + ChiasmusLibrary(); + ~ChiasmusLibrary(); + public: + static const ChiasmusLibrary * instance(); + static void deleteInstance(); + + int perform( const QValueVector<QCString> & args ) const; + private: + typedef int ( *main_func )( int, char** ); + main_func chiasmus( QString * reason=0 ) const; + + private: + static ChiasmusLibrary * self; + mutable KLibrary * mXiaLibrary; + }; + +} + + +#endif // __KLEO_CHIASMUSLIBRARY_H__ diff --git a/certmanager/lib/backends/chiasmus/config_data.c b/certmanager/lib/backends/chiasmus/config_data.c new file mode 100644 index 000000000..bb3f33916 --- /dev/null +++ b/certmanager/lib/backends/chiasmus/config_data.c @@ -0,0 +1,95 @@ +/* + chiasmusbackend.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2005 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "config_data.h" + +#include "kleo/cryptoconfig.h" /* for the enum values */ + +/* + This data structure uses C99 designated initializers. This is why + it's in a .c file, and not in a .cpp file. If your compiler doesn't + like this, just don't compile Chiasmus support, or live without the + wrapper option :) Sorry. +*/ + +#ifdef PATH +# undef PATH +#endif +#ifdef HAVE_C99_INITIALIZERS +# define PATH .path = +#else +# define PATH +#endif + +#define I18N_NOOP(x) (x) + +const struct kleo_chiasmus_config_data kleo_chiasmus_config_entries[] = { + { + "path", I18N_NOOP( "Path to Chiasmus executable" ), + Level_Basic, ArgType_Path, + { PATH "/usr/local/bin/chiasmus" }, /* in the absence of C99, we assume path is first in the union here */ + 0, 0, 1 + }, + { + "keydir", I18N_NOOP( "Key directory" ), + Level_Basic, ArgType_DirPath, + { PATH "~/.chiasmus/keys" }, + 0, 0, 1 /* FIXME: should be a list */ + }, +#ifdef HAVE_C99_INITIALIZERS + { + "show-output", I18N_NOOP( "Show output from chiasmus operations" ), + Level_Expert, ArgType_None, + { .boolean = { .value = 0, .numTimesSet = 0 } }, + 0, 0, 1 + }, + { + "symcryptrun-class", I18N_NOOP( "SymCryptRun class to use" ), + Level_Expert, ArgType_String, + { .string = "confucius" }, + 0, 0, 1 + }, + { + "timeout", I18N_NOOP( "Timeout in seconds for Chiasmus operations" ), + Level_Advanced, ArgType_UInt, + { .unsigned_integer = 60 }, + 0, 0, 1 + }, +#endif /* HAVE_C99_INITIALIZERS */ +}; +const unsigned int kleo_chiasmus_config_entries_dim + = sizeof kleo_chiasmus_config_entries / sizeof *kleo_chiasmus_config_entries ; + diff --git a/certmanager/lib/backends/chiasmus/config_data.h b/certmanager/lib/backends/chiasmus/config_data.h new file mode 100644 index 000000000..c5c7b6c4e --- /dev/null +++ b/certmanager/lib/backends/chiasmus/config_data.h @@ -0,0 +1,34 @@ +#ifndef __KLEO__CHIASMUS_CONFIG_DATA_H__ +#define __KLEO__CHIASMUS_CONFIG_DATA_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +struct kleo_chiasmus_config_data { + const char * name; + const char * description; + int level; + int type; + union { + const char * path; /* must be first, see config_data.c */ + const char * string; + const char * url; + struct { unsigned int value : 1; unsigned int numTimesSet : 31; } boolean; + int integer; + unsigned int unsigned_integer; + } defaults; + unsigned int is_optional : 1; + unsigned int is_list : 1; + unsigned int is_runtime : 1; +}; + +extern const struct kleo_chiasmus_config_data kleo_chiasmus_config_entries[]; +extern const unsigned int kleo_chiasmus_config_entries_dim; + +#ifdef __cplusplus +} +#endif + +#endif /* __KLEO__CHIASMUS_CONFIG_DATA_H__ */ + diff --git a/certmanager/lib/backends/chiasmus/configure.in.in b/certmanager/lib/backends/chiasmus/configure.in.in new file mode 100644 index 000000000..8cea56ad3 --- /dev/null +++ b/certmanager/lib/backends/chiasmus/configure.in.in @@ -0,0 +1,16 @@ +dnl +dnl Check for C99 designated initializers: +dnl +AC_LANG_SAVE +AC_LANG_C +AC_MSG_CHECKING([for C99 designated initializers]) +AC_TRY_COMPILE([ + union { int one; const char * two } foo = { .two = "Hello" }; +], [], [ + AC_DEFINE(HAVE_C99_INITIALIZERS, 1, [Define to 1 if your C compiler support C99 designated initializers]) + AC_MSG_RESULT([yes]) +], [ + AC_MSG_RESULT([no]) +]) + +AC_LANG_RESTORE diff --git a/certmanager/lib/backends/chiasmus/obtainkeysjob.cpp b/certmanager/lib/backends/chiasmus/obtainkeysjob.cpp new file mode 100644 index 000000000..a9de8d658 --- /dev/null +++ b/certmanager/lib/backends/chiasmus/obtainkeysjob.cpp @@ -0,0 +1,126 @@ +/* + obtainkeysjob.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2005 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "obtainkeysjob.h" + +#include "chiasmusbackend.h" + +#include "kleo/cryptoconfig.h" + +#include <klocale.h> +#include <kmessagebox.h> +#include <kshell.h> + +#include <qdir.h> +#include <qstringlist.h> +#include <qvariant.h> +#include <qtimer.h> +#include <qfileinfo.h> + +#include <gpg-error.h> + +#include <cassert> + +Kleo::ObtainKeysJob::ObtainKeysJob() + : SpecialJob( 0, 0 ), + mIndex( 0 ), + mCanceled( false ) +{ + assert( ChiasmusBackend::instance() ); + assert( ChiasmusBackend::instance()->config() ); + const CryptoConfigEntry * keypaths = + ChiasmusBackend::instance()->config()->entry( "Chiasmus", "General", "keydir" ); + assert( keypaths ); + mKeyPaths = QStringList( keypaths->urlValue().path() ); +} + +Kleo::ObtainKeysJob::~ObtainKeysJob() {} + +GpgME::Error Kleo::ObtainKeysJob::start() { + QTimer::singleShot( 0, this, SLOT(slotPerform()) ); + return mError = 0; +} + +GpgME::Error Kleo::ObtainKeysJob::exec() { + slotPerform( false ); + return mError; +} + +void Kleo::ObtainKeysJob::slotCancel() { + mCanceled = true; +} + +void Kleo::ObtainKeysJob::slotPerform() { + slotPerform( true ); +} + +void Kleo::ObtainKeysJob::slotPerform( bool async ) { + if ( mCanceled && !mError ) + mError = gpg_error( GPG_ERR_CANCELED ); + if ( mIndex >= mKeyPaths.size() || mError ) { + emit done(); + emit SpecialJob::result( mError, QVariant( mResult ) ); + return; + } + + emit progress( i18n( "Scanning directory %1..." ).arg( mKeyPaths[mIndex] ), + mIndex, mKeyPaths.size() ); + + const QDir dir( KShell::tildeExpand( mKeyPaths[mIndex] ) ); + + if ( const QFileInfoList * xisFiles = dir.entryInfoList( "*.xis;*.XIS", QDir::Files ) ) + for ( QFileInfoList::const_iterator it = xisFiles->begin(), end = xisFiles->end() ; it != end ; ++it ) + if ( (*it)->isReadable() ) + mResult.push_back( (*it)->absFilePath() ); + + ++mIndex; + + if ( async ) + QTimer::singleShot( 0, this, SLOT(slotPerform()) ); + else + slotPerform( false ); +} + +void Kleo::ObtainKeysJob::showErrorDialog( QWidget * parent, const QString & caption ) const { + if ( !mError ) + return; + if ( mError.isCanceled() ) + return; + const QString msg = QString::fromUtf8( mError.asString() ); + KMessageBox::error( parent, msg, caption ); +} + +#include "obtainkeysjob.moc" diff --git a/certmanager/lib/backends/chiasmus/obtainkeysjob.h b/certmanager/lib/backends/chiasmus/obtainkeysjob.h new file mode 100644 index 000000000..4b8392d46 --- /dev/null +++ b/certmanager/lib/backends/chiasmus/obtainkeysjob.h @@ -0,0 +1,101 @@ +/* -*- mode: C++; c-file-style: "gnu" -*- + obtainkeysjob.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2005 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + + +#ifndef __KLEO_OBTAINKEYSJOB_H__ +#define __KLEO_OBTAINKEYSJOB_H__ + +#include "kleo/specialjob.h" + +#include <qstringlist.h> + +#include <gpgmepp/context.h> + +namespace Kleo { + + /** + @short SpecialJob for listing Chiasmus key files. + + In the Chiasmus system, keys are mapped 1:1 to + files. Furthermore, we have to definition of the format of those + keys, so we cannot display more than the filename anyway. Due to + all of these limitations, we don't use KeyListJob here, but roll + our own interface. + + The name of the function is x-obtain-keys. It takes no parameters. + + To use, create an ObtainKeysJob instance like this: + <code> + Kleo::SpecialJob * job = + protocol->specialJob("x-obtain-keys", QMap<QString,QVariant>()); + </code> + + The resulting QVariant will contain a QStringList containing the + absolute filenames of the keys found in the configured key files. + */ + class ObtainKeysJob : public Kleo::SpecialJob { + Q_OBJECT + Q_PROPERTY( QStringList result READ result ) + public: + ObtainKeysJob(); + ~ObtainKeysJob(); + + /*!\reimp SpecialJob */ + GpgME::Error start(); + /*!\reimp SpecialJob */ + GpgME::Error exec(); + + /*!\reimp Kleo::Job */ + void showErrorDialog( QWidget *, const QString & ) const; + + //using SpecialJob::result; + QStringList result() const { return mResult; } + + public slots: + void slotCancel(); + + private slots: + void slotPerform(); + void slotPerform( bool async ); + + private: + GpgME::Error mError; + QStringList mKeyPaths; + unsigned int mIndex; + QStringList mResult; + bool mCanceled; + }; + +} + + +#endif // __KLEO_OBTAINKEYSJOB_H__ diff --git a/certmanager/lib/backends/chiasmus/symcryptrunprocessbase.cpp b/certmanager/lib/backends/chiasmus/symcryptrunprocessbase.cpp new file mode 100644 index 000000000..1b8627252 --- /dev/null +++ b/certmanager/lib/backends/chiasmus/symcryptrunprocessbase.cpp @@ -0,0 +1,109 @@ +/* + symcryptrunbackend.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2005 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "symcryptrunprocessbase.h" + +#include <ktempfile.h> +#include <kdebug.h> +#include <kshell.h> + +#include <qtimer.h> +#include <qfile.h> + +#include <cstring> + +Kleo::SymCryptRunProcessBase::SymCryptRunProcessBase( const QString & class_, const QString & program, + const QString & keyFile, const QString & options, + Operation mode, + QObject * parent, const char * name ) + : KProcess( parent, name ), + mOperation( mode ), mOptions( options ) +{ + *this << "symcryptrun" + << "--class" << class_ + << "--program" << program + << "--keyfile" << keyFile + << ( mode == Encrypt ? "--encrypt" : "--decrypt" ); +} + +Kleo::SymCryptRunProcessBase::~SymCryptRunProcessBase() {} + +bool Kleo::SymCryptRunProcessBase::launch( const QByteArray & input, RunMode rm ) { + connect( this, SIGNAL(receivedStdout(KProcess*,char*,int)), + this, SLOT(slotReceivedStdout(KProcess*,char*,int)) ); + connect( this, SIGNAL(receivedStderr(KProcess*,char*,int)), + this, SLOT(slotReceivedStderr(KProcess*,char*,int)) ); + if ( rm == Block ) { + KTempFile tempfile; + tempfile.setAutoDelete( true ); + if ( QFile * file = tempfile.file() ) + file->writeBlock( input ); + else + return false; + tempfile.close(); + *this << "--input" << tempfile.name(); + addOptions(); + return KProcess::start( Block, All ); + } else { + addOptions(); + const bool ok = KProcess::start( rm, All ); + if ( !ok ) + return ok; + mInput = input.copy(); + writeStdin( mInput.begin(), mInput.size() ); + connect( this, SIGNAL(wroteStdin(KProcess*)), this, SLOT(closeStdin()) ); + return true; + } +} + +void Kleo::SymCryptRunProcessBase::addOptions() { + if ( !mOptions.isEmpty() ) + { + const QStringList args = KShell::splitArgs( mOptions ); + *this << "--" << args; + } +} + +void Kleo::SymCryptRunProcessBase::slotReceivedStdout( KProcess * proc, char * buf, int len ) { + Q_ASSERT( proc == this ); + const int oldsize = mOutput.size(); + mOutput.resize( oldsize + len ); + memcpy( mOutput.data() + oldsize, buf, len ); +} + +void Kleo::SymCryptRunProcessBase::slotReceivedStderr( KProcess * proc, char * buf, int len ) { + Q_ASSERT( proc == this ); + if ( len > 0 ) + mStderr += QString::fromLocal8Bit( buf, len ); +} + +#include "symcryptrunprocessbase.moc" diff --git a/certmanager/lib/backends/chiasmus/symcryptrunprocessbase.h b/certmanager/lib/backends/chiasmus/symcryptrunprocessbase.h new file mode 100644 index 000000000..d74db60cc --- /dev/null +++ b/certmanager/lib/backends/chiasmus/symcryptrunprocessbase.h @@ -0,0 +1,81 @@ +/* + symcryptrunbackend.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2005 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_BACKEND_CHIASMUS__SYMCRYPTRUNPROCESSBASE_H__ +#define __KLEO_BACKEND_CHIASMUS__SYMCRYPTRUNPROCESSBASE_H__ + +#include <kprocess.h> + +#include <qcstring.h> + +class QString; + +namespace Kleo { + +class SymCryptRunProcessBase : public KProcess { + Q_OBJECT +public: + enum Operation { + Encrypt, Decrypt + }; + SymCryptRunProcessBase( const QString & class_, const QString & program, + const QString & keyFile, const QString& options, + Operation op, + QObject * parent=0, const char * name=0 ); + ~SymCryptRunProcessBase(); + + bool launch( const QByteArray & input, RunMode rm=NotifyOnExit ); + + const QByteArray & output() const { return mOutput; } + const QString & stdErr() const { return mStderr; } + +public slots: + /*! upgraded to slot */ + void closeStdin() { KProcess::closeStdin(); } + +private slots: + void slotReceivedStdout( KProcess *, char *, int ); + void slotReceivedStderr( KProcess *, char *, int ); + +private: + void addOptions(); + + QByteArray mInput; + QByteArray mOutput; + QString mStderr; + const Operation mOperation; + QString mOptions; +}; + +} + +#endif // __KLEO_BACKEND_CHIASMUS__SYMCRYPTRUNPROCESSBASE_H__ diff --git a/certmanager/lib/backends/kpgp/Makefile.am b/certmanager/lib/backends/kpgp/Makefile.am new file mode 100644 index 000000000..ad350f22c --- /dev/null +++ b/certmanager/lib/backends/kpgp/Makefile.am @@ -0,0 +1,12 @@ +INCLUDES = -I$(top_srcdir)/libkdenetwork \ + -I$(top_srcdir)/certmanager/lib \ + -I$(top_srcdir)/libkpgp \ + $(GPGME_CFLAGS) $(all_includes) + +noinst_LTLIBRARIES = libkleopatra_backend_kpgp.la + +libkleopatra_backend_kpgp_la_SOURCES = \ + kpgpbackendbase.cpp kpgpwrapper.cpp \ + kpgpkeylistjob.cpp + +METASOURCES = AUTO diff --git a/certmanager/lib/backends/kpgp/gpg1backend.h b/certmanager/lib/backends/kpgp/gpg1backend.h new file mode 100644 index 000000000..f9413accf --- /dev/null +++ b/certmanager/lib/backends/kpgp/gpg1backend.h @@ -0,0 +1,52 @@ +/* -*- mode: C++; c-file-style: "gnu" -*- + gpg1backend.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + + +#ifndef __KLEO_GPG1BACKEND_H__ +#define __KLEO_GPG1BACKEND_H__ + +#include "kpgpbackendbase.h" + +class QString; + +namespace Kleo { + + class GPG1Backend : public KpgpBackendBase { + public: + QString name() const; + QString displayName() const; + }; + +} + + +#endif // __KLEO_GPG1BACKEND_H__ diff --git a/certmanager/lib/backends/kpgp/kpgpbackendbase.cpp b/certmanager/lib/backends/kpgp/kpgpbackendbase.cpp new file mode 100644 index 000000000..2d4d17ab2 --- /dev/null +++ b/certmanager/lib/backends/kpgp/kpgpbackendbase.cpp @@ -0,0 +1,111 @@ +/* -*- mode: C++; c-file-style: "gnu" -*- + kpgpbackendbase.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "kpgpbackendbase.h" + +#include "pgp2backend.h" +#include "pgp5backend.h" +#include "pgp6backend.h" +#include "gpg1backend.h" + +#include <klocale.h> + +#include <qstring.h> + +#include "kpgpwrapper.h" + +Kleo::KpgpBackendBase::KpgpBackendBase() + : Kleo::CryptoBackend(), + mOpenPGPProtocol( 0 ) +{ +} + +Kleo::KpgpBackendBase::~KpgpBackendBase() +{ + delete mOpenPGPProtocol; mOpenPGPProtocol = 0; +} + +QString Kleo::GPG1Backend::name() const { + return GPG1_BACKEND_NAME; +} + +QString Kleo::GPG1Backend::displayName() const { + return i18n("Kpgp/gpg"); +} + +QString Kleo::PGP2Backend::name() const { + return PGP2_BACKEND_NAME; +} + +QString Kleo::PGP2Backend::displayName() const { + return i18n("Kpgp/pgp v2"); +} + +QString Kleo::PGP5Backend::name() const { + return PGP5_BACKEND_NAME; +} + +QString Kleo::PGP5Backend::displayName() const { + return i18n("Kpgp/pgp v5"); +} + +QString Kleo::PGP6Backend::name() const { + return PGP6_BACKEND_NAME; +} + +QString Kleo::PGP6Backend::displayName() const { + return i18n("Kpgp/pgp v6"); +} + +static const QString notSupported() { + return i18n("This backend does not support S/MIME"); +} + +bool Kleo::KpgpBackendBase::checkForOpenPGP( QString * /*reason*/ ) const { + return true; +} + +bool Kleo::KpgpBackendBase::checkForSMIME( QString * reason ) const { + if ( reason ) *reason = notSupported(); + return false; +} + +Kleo::CryptoBackend::Protocol * Kleo::KpgpBackendBase::openpgp() const { + if ( !mOpenPGPProtocol ) + if ( checkForOpenPGP() ) + mOpenPGPProtocol = new KpgpWrapper( name() ); + return mOpenPGPProtocol; +} diff --git a/certmanager/lib/backends/kpgp/kpgpbackendbase.h b/certmanager/lib/backends/kpgp/kpgpbackendbase.h new file mode 100644 index 000000000..854e800c3 --- /dev/null +++ b/certmanager/lib/backends/kpgp/kpgpbackendbase.h @@ -0,0 +1,73 @@ +/* -*- mode: C++; c-file-style: "gnu" -*- + kpgpbackendbase.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + + +#ifndef __KLEO_KPGPBACKENDBASE_H__ +#define __KLEO_KPGPBACKENDBASE_H__ + +#include "kleo/cryptobackend.h" + +#define GPG1_BACKEND_NAME "Kpgp/gpg1" +#define PGP2_BACKEND_NAME "Kpgp/pgp2" +#define PGP5_BACKEND_NAME "Kpgp/pgp5" +#define PGP6_BACKEND_NAME "Kpgp/pgp6" + +namespace Kleo { + class CryptoConfig; +} +class QString; +class KpgpWrapper; + +namespace Kleo { + + class KpgpBackendBase : public Kleo::CryptoBackend { + public: + KpgpBackendBase(); + ~KpgpBackendBase(); + + CryptoConfig * config() const { return 0; } + Protocol * openpgp() const; + Protocol * smime() const { return 0; } + + bool supportsOpenPGP() const { return true; } + bool supportsSMIME() const { return false; } + + bool checkForOpenPGP( QString * reason=0 ) const; + bool checkForSMIME( QString * reason=0 ) const; + private: + mutable KpgpWrapper * mOpenPGPProtocol; + }; + +} + + +#endif // __KLEO_KPGPBACKENDBASE_H__ diff --git a/certmanager/lib/backends/kpgp/kpgpkeylistjob.cpp b/certmanager/lib/backends/kpgp/kpgpkeylistjob.cpp new file mode 100644 index 000000000..4c328adee --- /dev/null +++ b/certmanager/lib/backends/kpgp/kpgpkeylistjob.cpp @@ -0,0 +1,303 @@ +/* + kpgpkeylistjob.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Ingo Kloecker <kloecker@kde.org> + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "kpgpkeylistjob.h" + +#include <kpgpbase.h> +#include <kpgpkey.h> + +#include <gpgmepp/key.h> +#include <gpgmepp/keylistresult.h> + +#include <gpgme.h> + +#include <qtimer.h> + +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +Kleo::KpgpKeyListJob::KpgpKeyListJob( Kpgp::Base * pgpBase ) + : KeyListJob( 0, "Kleo::KpgpKeyListJob" ), + mPgpBase( pgpBase ) +{ +} + +Kleo::KpgpKeyListJob::~KpgpKeyListJob() { +} + +// the following function is a verbatim copy from gpgme/key.c +static char * +set_user_id_part (char *tail, const char *buf, size_t len) +{ + while (len && (buf[len - 1] == ' ' || buf[len - 1] == '\t')) + len--; + for (; len; len--) + *tail++ = *buf++; + *tail++ = 0; + return tail; +} + +// the following function is a verbatim copy from gpgme/key.c +static void +parse_user_id (char *src, char **name, char **email, + char **comment, char *tail) +{ + const char *start = NULL; + int in_name = 0; + int in_email = 0; + int in_comment = 0; + + while (*src) + { + if (in_email) + { + if (*src == '<') + /* Not legal but anyway. */ + in_email++; + else if (*src == '>') + { + if (!--in_email && !*email) + { + *email = tail; + tail = set_user_id_part (tail, start, src - start); + } + } + } + else if (in_comment) + { + if (*src == '(') + in_comment++; + else if (*src == ')') + { + if (!--in_comment && !*comment) + { + *comment = tail; + tail = set_user_id_part (tail, start, src - start); + } + } + } + else if (*src == '<') + { + if (in_name) + { + if (!*name) + { + *name = tail; + tail = set_user_id_part (tail, start, src - start); + } + in_name = 0; + } + in_email = 1; + start = src + 1; + } + else if (*src == '(') + { + if (in_name) + { + if (!*name) + { + *name = tail; + tail = set_user_id_part (tail, start, src - start); + } + in_name = 0; + } + in_comment = 1; + start = src + 1; + } + else if (!in_name && *src != ' ' && *src != '\t') + { + in_name = 1; + start = src; + } + src++; + } + + if (in_name) + { + if (!*name) + { + *name = tail; + tail = set_user_id_part (tail, start, src - start); + } + } + + /* Let unused parts point to an EOS. */ + tail--; + if (!*name) + *name = tail; + if (!*email) + *email = tail; + if (!*comment) + *comment = tail; +} + +gpgme_user_id_t KpgpUserID2GPGMEUserID( const Kpgp::UserID * kUserId ) +{ + // inspired by _gpgme_key_append_name + + const QCString text = kUserId->text().utf8(); + const int src_len = text.length(); + + gpgme_user_id_t uid; + /* Allocate enough memory for the _gpgme_user_id struct, for the actual user + id (the text) and for the parsed version. */ + uid = (gpgme_user_id_t) malloc( sizeof( *uid ) + 2 * src_len + 3 ); + memset( uid, 0, sizeof *uid ); + uid->revoked = kUserId->revoked(); + uid->invalid = kUserId->invalid(); + uid->validity = (gpgme_validity_t) kUserId->validity(); + + uid->uid = ((char *) uid) + sizeof (*uid); + char *dst = uid->uid; + memcpy( dst, text.data(), src_len + 1 ); + + dst += src_len + 1; + parse_user_id( uid->uid, &uid->name, &uid->email, + &uid->comment, dst ); + + return uid; +} + +gpgme_subkey_t KpgpSubkey2GPGMESubKey( const Kpgp::Subkey * kSubkey ) +{ + gpgme_subkey_t subkey; + + const QCString fpr = kSubkey->fingerprint(); + const unsigned int fpr_len = fpr.length(); + const QCString keyId = kSubkey->longKeyID(); + + subkey = (gpgme_subkey_t) calloc( 1, sizeof( *subkey ) + fpr_len + 1 ); + subkey->revoked = kSubkey->revoked(); + subkey->expired = kSubkey->expired(); + subkey->disabled = kSubkey->disabled(); + subkey->invalid = kSubkey->invalid(); + subkey->can_encrypt = kSubkey->canEncrypt(); + subkey->can_sign = kSubkey->canSign(); + subkey->can_certify = kSubkey->canCertify(); + subkey->secret = kSubkey->secret(); + subkey->pubkey_algo = (gpgme_pubkey_algo_t) kSubkey->keyAlgorithm(); + subkey->length = kSubkey->keyLength(); + subkey->keyid = subkey->_keyid; + memcpy( subkey->_keyid, keyId.data(), keyId.length() + 1 ); + subkey->fpr = ((char *) subkey) + sizeof( *subkey ); + memcpy( subkey->fpr, fpr.data(), fpr_len + 1 ); + subkey->timestamp = kSubkey->creationDate(); + subkey->expires = kSubkey->expirationDate(); + + return subkey; +} + +gpgme_key_t KpgpKey2gpgme_key( const Kpgp::Key * kKey ) +{ + gpgme_key_t key; + + key = (gpgme_key_t) calloc( 1, sizeof( *key ) ); + key->revoked = kKey->revoked(); + key->expired = kKey->expired(); + key->disabled = kKey->disabled(); + key->invalid = kKey->invalid(); + key->can_encrypt = kKey->canEncrypt(); + key->can_sign = kKey->canSign(); + key->can_certify = kKey->canCertify(); + key->secret = kKey->secret(); + key->protocol = GPGME_PROTOCOL_OpenPGP; + key->owner_trust = GPGME_VALIDITY_UNKNOWN; // FIXME? + + Kpgp::UserIDList kUserIDs = kKey->userIDs(); + for ( Kpgp::UserIDListIterator it( kUserIDs ); it.current(); ++it ) { + gpgme_user_id_t uid = KpgpUserID2GPGMEUserID( *it ); + if ( !key->uids ) + key->uids = uid; + if ( key->_last_uid ) + key->_last_uid->next = uid; + key->_last_uid = uid; + } + + Kpgp::SubkeyList kSubkeys = kKey->subkeys(); + for ( Kpgp::SubkeyListIterator it( kSubkeys ); it.current(); ++it ) { + gpgme_subkey_t subkey = KpgpSubkey2GPGMESubKey( *it ); + if (!key->subkeys) + key->subkeys = subkey; + if (key->_last_subkey) + key->_last_subkey->next = subkey; + key->_last_subkey = subkey; + } + + return key; +} + +GpgME::Error Kleo::KpgpKeyListJob::start( const QStringList & patterns, + bool secretOnly ) { + mPatterns = patterns; + mSecretOnly = secretOnly; + QTimer::singleShot( 0, this, SLOT( slotDoIt() ) ); + return GpgME::Error( 0 ); +} + +void Kleo::KpgpKeyListJob::slotDoIt() { + std::vector<GpgME::Key> keys; + GpgME::KeyListResult res = exec( mPatterns, mSecretOnly, keys ); + for ( std::vector<GpgME::Key>::const_iterator it = keys.begin(); + it != keys.end(); ++it ) + emit nextKey( *it ); + emit done(); + emit result( res ); + deleteLater(); +} + +GpgME::KeyListResult Kleo::KpgpKeyListJob::exec( const QStringList & patterns, + bool secretOnly, + std::vector<GpgME::Key> & keys ) { + Kpgp::KeyList kKeys; + if ( secretOnly ) + kKeys = mPgpBase->secretKeys( patterns ); + else + kKeys = mPgpBase->publicKeys( patterns ); + + keys.clear(); + for ( Kpgp::KeyListIterator it( kKeys ); it.current(); ++it ) { + keys.push_back( GpgME::Key( KpgpKey2gpgme_key(*it), true ) ); + } + + _gpgme_op_keylist_result res; + res.truncated = 0; // key list is not truncated + res._unused = 0; + + return GpgME::KeyListResult( GpgME::Error( 0 ), res ); +} + +#include "kpgpkeylistjob.moc" diff --git a/certmanager/lib/backends/kpgp/kpgpkeylistjob.h b/certmanager/lib/backends/kpgp/kpgpkeylistjob.h new file mode 100644 index 000000000..779680c2d --- /dev/null +++ b/certmanager/lib/backends/kpgp/kpgpkeylistjob.h @@ -0,0 +1,79 @@ +/* -*- mode: C++ -*- + kpgpkeylistjob.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Ingo Kloecker <kloecker@kde.org> + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_KPGPKEYLISTJOB_H__ +#define __KLEO_KPGPKEYLISTJOB_H__ + +#include <kleo/keylistjob.h> + +#include <qstringlist.h> + +namespace GpgME { + class Error; + class Context; + class Key; +} + +namespace Kpgp { + class Base; +} + +namespace Kleo { + + class KpgpKeyListJob : public KeyListJob { + Q_OBJECT + public: + KpgpKeyListJob( Kpgp::Base * pgpBase ); + ~KpgpKeyListJob(); + + /*! \reimp from KeyListJob */ + GpgME::Error start( const QStringList & patterns, bool secretOnly ); + + /*! \reimp from KeyListJob */ + GpgME::KeyListResult exec( const QStringList & patterns, bool secretOnly, + std::vector<GpgME::Key> & keys ); + + /*! \reimp from Job */ + void slotCancel() { /*FIXME*/ } + + private slots: + void slotDoIt(); + + private: + Kpgp::Base * mPgpBase; + QStringList mPatterns; + bool mSecretOnly; + }; + +} + +#endif // __KLEO_KPGPKEYLISTJOB_H__ diff --git a/certmanager/lib/backends/kpgp/kpgpwrapper.cpp b/certmanager/lib/backends/kpgp/kpgpwrapper.cpp new file mode 100644 index 000000000..20d885dd5 --- /dev/null +++ b/certmanager/lib/backends/kpgp/kpgpwrapper.cpp @@ -0,0 +1,173 @@ +/* -*- mode: C++; c-file-style: "gnu" -*- + kpgpwrapper.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Ingo Kloecker <kloecker@kde.org> + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "kpgpwrapper.h" + +#include "kpgpbackendbase.h" + +#include <kpgpbase.h> + +#include <backends/kpgp/kpgpkeylistjob.h> +//#include <backends/kpgp/kpgpencryptjob.h> +//#include <backends/kpgp/kpgpdecryptjob.h> +//#include <backends/kpgp/kpgpsignjob.h> +//#include <backends/kpgp/kpgpverifydetachedjob.h> +//#include <backends/kpgp/kpgpverifyopaquejob.h> +//#include <backends/kpgp/kpgpkeygenerationjob.h> +//#include <backends/kpgp/kpgpimportjob.h> +//#include <backends/kpgp/kpgpexportjob.h> +//#include <backends/kpgp/kpgpsecretkeyexportjob.h> +//#include <backends/kpgp/kpgpdownloadjob.h> +//#include <backends/kpgp/kpgpdeletejob.h> +//#include <backends/kpgp/kpgpsignencryptjob.h> +//#include <backends/kpgp/kpgpdecryptverifyjob.h> +//#include <backends/kpgp/kpgpcryptoconfig.h> + +KpgpWrapper::KpgpWrapper( const QString & name ) + : mName( name ), + mPgpBase( 0 ) +{ + +} + +KpgpWrapper::~KpgpWrapper() +{ + +} + +QString KpgpWrapper::name() const +{ + return mName; +} + +QString KpgpWrapper::displayName() const +{ + return mName; +} + +Kleo::KeyListJob * KpgpWrapper::keyListJob( bool /*remote*/, + bool /*includeSigs*/, + bool /*validate*/ ) const +{ + return new Kleo::KpgpKeyListJob( pgpBase() ); +} + +Kleo::EncryptJob * KpgpWrapper::encryptJob( bool /*armor*/, + bool /*textmode*/ ) const +{ + return 0; +} + +Kleo::DecryptJob * KpgpWrapper::decryptJob() const +{ + return 0; +} + +Kleo::SignJob * KpgpWrapper::signJob( bool /*armor*/, bool /*textMode*/ ) const +{ + return 0; +} + +Kleo::VerifyDetachedJob * KpgpWrapper::verifyDetachedJob( bool /*textmode*/ ) const +{ + return 0; +} + +Kleo::VerifyOpaqueJob * KpgpWrapper::verifyOpaqueJob( bool /*textmode*/ ) const +{ + return 0; +} + +Kleo::KeyGenerationJob * KpgpWrapper::keyGenerationJob() const +{ + return 0; +} + +Kleo::ImportJob * KpgpWrapper::importJob() const +{ + return 0; +} + +Kleo::ExportJob * KpgpWrapper::publicKeyExportJob( bool /*armor*/ ) const +{ + return 0; +} + +Kleo::ExportJob * KpgpWrapper::secretKeyExportJob( bool /*armor*/ ) const +{ + return 0; +} + +Kleo::DownloadJob * KpgpWrapper::downloadJob( bool /*armor*/ ) const +{ + return 0; +} + +Kleo::DeleteJob * KpgpWrapper::deleteJob() const +{ + return 0; +} + +Kleo::SignEncryptJob * KpgpWrapper::signEncryptJob( bool /*armor*/, + bool /*textMode*/ ) const +{ + return 0; +} + +Kleo::DecryptVerifyJob * KpgpWrapper::decryptVerifyJob( bool /*textmode*/ ) const +{ + return 0; +} + +Kleo::RefreshKeysJob * KpgpWrapper::refreshKeysJob() const +{ + return 0; +} + +Kpgp::Base * KpgpWrapper::pgpBase() const +{ + if ( !mPgpBase ) { + if ( name() == GPG1_BACKEND_NAME ) + mPgpBase = new Kpgp::BaseG(); + else if ( name() == PGP2_BACKEND_NAME ) + mPgpBase = new Kpgp::Base2(); + else if ( name() == PGP5_BACKEND_NAME ) + mPgpBase = new Kpgp::Base5(); + else if ( name() == PGP6_BACKEND_NAME ) + mPgpBase = new Kpgp::Base6(); + } + return mPgpBase; +} diff --git a/certmanager/lib/backends/kpgp/kpgpwrapper.h b/certmanager/lib/backends/kpgp/kpgpwrapper.h new file mode 100644 index 000000000..182661ec4 --- /dev/null +++ b/certmanager/lib/backends/kpgp/kpgpwrapper.h @@ -0,0 +1,97 @@ +/* -*- mode: C++; c-file-style: "gnu" -*- + kpgpwrapper.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Ingo Kloecker <kloecker@kde.org> + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_KPGPWRAPPER_H__ +#define __KLEO_KPGPWRAPPER_H__ + +#include <kleo/cryptobackend.h> + +#include <qstring.h> + +namespace Kleo { + class KeyListJob; + class EncryptJob; + class DecryptJob; + class SignJob; + class VerifyDetachedJob; + class VerifyOpaqueJob; + class KeyGenerationJob; + class ImportJob; + class ExportJob; + class DownloadJob; + class DeleteJob; + class SignEncryptJob; + class DecryptVerifyJob; + class CryptoConfig; + class RefreshKeysJob; +} + +namespace Kpgp { + class Base; +} + +class KpgpWrapper : public Kleo::CryptoBackend::Protocol { +public: + KpgpWrapper( const QString & name ); + ~KpgpWrapper(); + + QString name() const; + + QString displayName() const; + + Kleo::KeyListJob * keyListJob( bool remote=false, bool includeSigs=false, + bool validate=false ) const; + Kleo::EncryptJob * encryptJob( bool armor=false, bool textmode=false ) const; + Kleo::DecryptJob * decryptJob() const; + Kleo::SignJob * signJob( bool armor=false, bool textMode=false ) const; + Kleo::VerifyDetachedJob * verifyDetachedJob( bool textmode=false) const; + Kleo::VerifyOpaqueJob * verifyOpaqueJob( bool textmode=false ) const; + Kleo::KeyGenerationJob * keyGenerationJob() const; + Kleo::ImportJob * importJob() const; + Kleo::ExportJob * publicKeyExportJob( bool armor=false ) const; + Kleo::ExportJob * secretKeyExportJob( bool armor=false ) const; + Kleo::DownloadJob * downloadJob( bool armor=false ) const; + Kleo::DeleteJob * deleteJob() const; + Kleo::SignEncryptJob * signEncryptJob( bool armor=false, + bool textMode=false ) const; + Kleo::DecryptVerifyJob * decryptVerifyJob( bool textmode=false ) const; + Kleo::RefreshKeysJob * refreshKeysJob() const; + +private: + Kpgp::Base * pgpBase() const; + +private: + QString mName; + mutable Kpgp::Base * mPgpBase; +}; + +#endif // __KLEO_KPGPWRAPPER_H__ diff --git a/certmanager/lib/backends/kpgp/pgp2backend.h b/certmanager/lib/backends/kpgp/pgp2backend.h new file mode 100644 index 000000000..fc053a20c --- /dev/null +++ b/certmanager/lib/backends/kpgp/pgp2backend.h @@ -0,0 +1,52 @@ +/* -*- mode: C++; c-file-style: "gnu" -*- + pgp2backend.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + + +#ifndef __KLEO_PGP2BACKEND_H__ +#define __KLEO_PGP2BACKEND_H__ + +#include "kpgpbackendbase.h" + +class QString; + +namespace Kleo { + + class PGP2Backend : public KpgpBackendBase { + public: + QString name() const; + QString displayName() const; + }; + +} + + +#endif // __KLEO_PGP2BACKEND_H__ diff --git a/certmanager/lib/backends/kpgp/pgp5backend.h b/certmanager/lib/backends/kpgp/pgp5backend.h new file mode 100644 index 000000000..bf323b6fb --- /dev/null +++ b/certmanager/lib/backends/kpgp/pgp5backend.h @@ -0,0 +1,52 @@ +/* -*- mode: C++; c-file-style: "gnu" -*- + pgp5backend.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + + +#ifndef __KLEO_PGP5BACKEND_H__ +#define __KLEO_PGP5BACKEND_H__ + +#include "kpgpbackendbase.h" + +class QString; + +namespace Kleo { + + class PGP5Backend : public KpgpBackendBase { + public: + QString name() const; + QString displayName() const; + }; + +} + + +#endif // __KLEO_PGP5BACKEND_H__ diff --git a/certmanager/lib/backends/kpgp/pgp6backend.h b/certmanager/lib/backends/kpgp/pgp6backend.h new file mode 100644 index 000000000..827cf239b --- /dev/null +++ b/certmanager/lib/backends/kpgp/pgp6backend.h @@ -0,0 +1,52 @@ +/* -*- mode: C++; c-file-style: "gnu" -*- + pgp6backend.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + + +#ifndef __KLEO_PGP6BACKEND_H__ +#define __KLEO_PGP6BACKEND_H__ + +#include "kpgpbackendbase.h" + +class QString; + +namespace Kleo { + + class PGP6Backend : public KpgpBackendBase { + public: + QString name() const; + QString displayName() const; + }; + +} + + +#endif // __KLEO_PGP6BACKEND_H__ diff --git a/certmanager/lib/backends/qgpgme/Makefile.am b/certmanager/lib/backends/qgpgme/Makefile.am new file mode 100644 index 000000000..a7336a029 --- /dev/null +++ b/certmanager/lib/backends/qgpgme/Makefile.am @@ -0,0 +1,34 @@ +#KDE_OPTIONS = nofinal + +INCLUDES = -I$(top_srcdir)/libkdenetwork \ + -I$(top_srcdir)/certmanager/lib \ + $(GPGME_CFLAGS) $(all_includes) + +noinst_LTLIBRARIES = libkleopatra_backend_qgpgme.la + +libkleopatra_backend_qgpgme_la_SOURCES = \ + gnupgprocessbase.cpp \ + qgpgmeprogresstokenmapper.cpp \ + \ + qgpgmebackend.cpp \ + \ + qgpgmejob.cpp \ + \ + qgpgmekeylistjob.cpp \ + qgpgmekeygenerationjob.cpp \ + qgpgmeimportjob.cpp \ + qgpgmeexportjob.cpp \ + qgpgmesecretkeyexportjob.cpp \ + qgpgmedownloadjob.cpp \ + qgpgmedeletejob.cpp \ + qgpgmeencryptjob.cpp \ + qgpgmedecryptjob.cpp \ + qgpgmesignjob.cpp \ + qgpgmeverifydetachedjob.cpp \ + qgpgmeverifyopaquejob.cpp \ + qgpgmesignencryptjob.cpp \ + qgpgmedecryptverifyjob.cpp \ + qgpgmecryptoconfig.cpp \ + qgpgmerefreshkeysjob.cpp + +METASOURCES = AUTO diff --git a/certmanager/lib/backends/qgpgme/gnupgprocessbase.cpp b/certmanager/lib/backends/qgpgme/gnupgprocessbase.cpp new file mode 100644 index 000000000..2d3ca7409 --- /dev/null +++ b/certmanager/lib/backends/qgpgme/gnupgprocessbase.cpp @@ -0,0 +1,198 @@ +/* + gnupgprocessbase.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "gnupgprocessbase.h" + +#include <kdebug.h> +#include <kurl.h> + +#include <qsocketnotifier.h> +#include <qtextcodec.h> +#include <qstringlist.h> + +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <assert.h> + +struct Kleo::GnuPGProcessBase::Private { + Private() : useStatusFD( false ), statnot( 0 ) { + statusFD[0] = statusFD[1] = -1; + } + + bool useStatusFD; + int statusFD[2]; + QSocketNotifier * statnot; + QCString statusBuffer; +}; + + +Kleo::GnuPGProcessBase::GnuPGProcessBase( QObject * parent, const char * name ) + : KProcess( parent, name ) +{ + d = new Private(); +} + +Kleo::GnuPGProcessBase::~GnuPGProcessBase() { + delete d; d = 0; +} + +void Kleo::GnuPGProcessBase::setUseStatusFD( bool use ) { + assert( d ); + d->useStatusFD = use; +} + +bool Kleo::GnuPGProcessBase::start( RunMode runmode, Communication comm ) { + if ( d->useStatusFD ) { + // set up the status-fd. This should be in setupCommunication(), + // but then it's too late: we need the fd of the pipe to pass it + // as argument to the --status-fd option: + // PENDING(marc) find out why KProcess uses both pipe() and socketpair()... + if ( ::pipe( d->statusFD ) < 0 ) { + kdDebug( 5150 ) << "Kleo::GnuPGProcessBase::start: pipe(2) failed: " << perror << endl; + return false; + } + ::fcntl( d->statusFD[0], F_SETFD, FD_CLOEXEC ); + ::fcntl( d->statusFD[1], F_SETFD, FD_CLOEXEC ); + if ( !arguments.empty() ) { + QValueList<QCString>::iterator it = arguments.begin(); + ++it; + arguments.insert( it, "--status-fd" ); + char buf[25]; + sprintf( buf, "%d", d->statusFD[1] ); + arguments.insert( it, buf ); + arguments.insert( it, "--no-tty" ); + //arguments.insert( it, "--enable-progress-filter" ); // gpgsm doesn't know this + } + } + return KProcess::start( runmode, comm ); +} + +int Kleo::GnuPGProcessBase::setupCommunication( Communication comm ) { + if ( int ok = KProcess::setupCommunication( comm ) ) + return ok; + if ( d->useStatusFD ) { + // base class impl returned error, so close our fd's, too + ::close( d->statusFD[0] ); + ::close( d->statusFD[1] ); + d->statusFD[0] = d->statusFD[1] = -1; + } + return 0; // Error +} + +int Kleo::GnuPGProcessBase::commSetupDoneP() { + if ( d->useStatusFD ) { + ::close( d->statusFD[1] ); // close the input end of the pipe, we're the reader + d->statnot = new QSocketNotifier( d->statusFD[0], QSocketNotifier::Read, this ); + connect( d->statnot, SIGNAL(activated(int)), SLOT(slotChildStatus(int)) ); + } + return KProcess::commSetupDoneP(); +} + +int Kleo::GnuPGProcessBase::commSetupDoneC() { + if ( d->useStatusFD ) + ::fcntl( d->statusFD[1], F_SETFD, 0 ); + return KProcess::commSetupDoneC(); +} + +void Kleo::GnuPGProcessBase::slotChildStatus( int fd ) { + if ( !childStatus(fd) ) + closeStatus(); +} + +bool Kleo::GnuPGProcessBase::closeStatus() { + if ( !d->useStatusFD ) + return false; + d->useStatusFD = false; + delete d->statnot; d->statnot = 0; + ::close( d->statusFD[0] ); d->statusFD[0] = -1; + return true; +} + +int Kleo::GnuPGProcessBase::childStatus( int fd ) { + char buf[1024]; + const int len = ::read( fd, buf, sizeof(buf)-1 ); + if ( len > 0 ) { + buf[len] = 0; + d->statusBuffer += buf; + parseStatusOutput(); + } + return len; +} + +static QString fromHexEscapedUtf8( const QCString & str ) { + return KURL::decode_string( str.data(), 106 /* utf-8 */ ); +} + +void Kleo::GnuPGProcessBase::parseStatusOutput() { + static const char startToken[] = "[GNUPG:] "; + static const int startTokenLen = sizeof startToken / sizeof *startToken - 1; + + int lineStart = 0; + for ( int lineEnd = d->statusBuffer.find( '\n' ) ; lineEnd >= 0 ; lineEnd = d->statusBuffer.find( '\n', lineStart = lineEnd+1 ) ) { + // get next line: + const QCString line = d->statusBuffer.mid( lineStart, lineEnd - lineStart ).stripWhiteSpace(); + if ( line.isEmpty() ) + continue; + // check status token + if ( line.left( startTokenLen ) != startToken ) { + kdDebug( 5150 ) << "Kleo::GnuPGProcessBase::childStatus: status-fd protocol error: line doesn't begin with \"" + << startToken << "\"" << endl; + continue; + } + // remove status token: + const QCString command = line.mid( startTokenLen ).simplifyWhiteSpace() + ' '; + if ( command == " " ) { + kdDebug( 5150 ) << "Kleo::GnuPGProcessBase::childStatus: status-fd protocol error: line without content." << endl; + continue; + } + // split into base and args + QString cmd; + QStringList args; + int tagStart = 0; + for ( int tagEnd = command.find( ' ' ) ; tagEnd >= 0 ; tagEnd = command.find( ' ', tagStart = tagEnd+1 ) ) { + const QCString tag = command.mid( tagStart, tagEnd - tagStart ); + if ( cmd.isNull() ) + cmd = fromHexEscapedUtf8( tag ); + else + args.push_back( fromHexEscapedUtf8( tag ) ); + } + emit status( this, cmd, args ); + } + d->statusBuffer = d->statusBuffer.mid( lineStart ); +} + +void Kleo::GnuPGProcessBase::virtual_hook( int id, void * data ) { + KProcess::virtual_hook( id, data ); +} + +#include "gnupgprocessbase.moc" diff --git a/certmanager/lib/backends/qgpgme/gnupgprocessbase.h b/certmanager/lib/backends/qgpgme/gnupgprocessbase.h new file mode 100644 index 000000000..73e31e295 --- /dev/null +++ b/certmanager/lib/backends/qgpgme/gnupgprocessbase.h @@ -0,0 +1,91 @@ +/* + gnupgprocessbase.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_GNUPGPROCESSBASE_H__ +#define __KLEO_GNUPGPROCESSBASE_H__ + +#include <kprocess.h> + +namespace Kleo { + + /** + * @short a base class for GPG and GPGSM processes. + * + * This KProcess subclass implements the status-fd handling common + * to GPG and GPGSM. + * + * @author Marc Mutz <mutz@kde.org> + */ + class GnuPGProcessBase : public KProcess { + Q_OBJECT + public: + GnuPGProcessBase( QObject * parent=0, const char * name=0 ); + ~GnuPGProcessBase(); + + void setUseStatusFD( bool use ); + + /*! reimplementation */ + bool start( RunMode runmode, Communication comm ); + + bool closeStatus(); + + signals: + void status( Kleo::GnuPGProcessBase * proc, const QString & type, const QStringList & args ); + + protected: + /*! reimplementation */ + int setupCommunication( Communication comm ); + /*! reimplementation */ + int commSetupDoneP(); + /*! reimplementation */ + int commSetupDoneC(); + + int childStatus( int fd ); + + + private slots: + void slotChildStatus( int fd ); + + private: + void parseStatusOutput(); + + private: + class Private; + Private * d; + protected: + /*! reimplementation */ + void virtual_hook( int id, void * data ); + }; + +} + +#endif // __KLEO_GNUPGPROCESSBASE_H__ diff --git a/certmanager/lib/backends/qgpgme/qgpgmebackend.cpp b/certmanager/lib/backends/qgpgme/qgpgmebackend.cpp new file mode 100644 index 000000000..8256522ae --- /dev/null +++ b/certmanager/lib/backends/qgpgme/qgpgmebackend.cpp @@ -0,0 +1,153 @@ +/* -*- mode: C++; c-file-style: "gnu" -*- + qgpgmebackend.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004,2005 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "qgpgmebackend.h" + +#include "qgpgmecryptoconfig.h" +#include "cryptplugwrapper.h" + +#include <gpgmepp/context.h> +#include <gpgmepp/engineinfo.h> + +#include <klocale.h> +#include <kstandarddirs.h> + +#include <qfile.h> +#include <qstring.h> + +Kleo::QGpgMEBackend::QGpgMEBackend() + : Kleo::CryptoBackend(), + mCryptoConfig( 0 ), + mOpenPGPProtocol( 0 ), + mSMIMEProtocol( 0 ) +{ + GpgME::initializeLibrary(); +} + +Kleo::QGpgMEBackend::~QGpgMEBackend() { + delete mCryptoConfig; mCryptoConfig = 0; + delete mOpenPGPProtocol; mOpenPGPProtocol = 0; + delete mSMIMEProtocol; mSMIMEProtocol = 0; +} + +QString Kleo::QGpgMEBackend::name() const { + return "gpgme"; +} + +QString Kleo::QGpgMEBackend::displayName() const { + return i18n( "GpgME" ); +} + +Kleo::CryptoConfig * Kleo::QGpgMEBackend::config() const { + if ( !mCryptoConfig ) { + static bool hasGpgConf = !KStandardDirs::findExe( "gpgconf" ).isEmpty(); + if ( hasGpgConf ) + mCryptoConfig = new QGpgMECryptoConfig(); + } + return mCryptoConfig; +} + +static bool check( GpgME::Context::Protocol proto, QString * reason ) { + if ( !GpgME::checkEngine( proto ) ) + return true; + if ( !reason ) + return false; + // error, check why: + const GpgME::EngineInfo ei = GpgME::engineInfo( proto ); + if ( ei.isNull() ) + *reason = i18n("GPGME was compiled without support for %1.").arg( proto == GpgME::Context::CMS ? "S/MIME" : "OpenPGP" ); + else if ( ei.fileName() && !ei.version() ) + *reason = i18n("Engine %1 is not installed properly.").arg( QFile::decodeName( ei.fileName() ) ); + else if ( ei.fileName() && ei.version() && ei.requiredVersion() ) + *reason = i18n("Engine %1 version %2 installed, " + "but at least version %3 is required.") + .arg( QFile::decodeName( ei.fileName() ), ei.version(), ei.requiredVersion() ); + else + *reason = i18n("Unknown problem with engine for protocol %1.").arg( proto == GpgME::Context::CMS ? "S/MIME" : "OpenPGP" ); + return false; +} + +bool Kleo::QGpgMEBackend::checkForOpenPGP( QString * reason ) const { + return check( GpgME::Context::OpenPGP, reason ); +} + +bool Kleo::QGpgMEBackend::checkForSMIME( QString * reason ) const { + return check( GpgME::Context::CMS, reason ); +} + +bool Kleo::QGpgMEBackend::checkForProtocol( const char * name, QString * reason ) const { + if ( qstricmp( name, OpenPGP ) == 0 ) + return check( GpgME::Context::OpenPGP, reason ); + if ( qstricmp( name, SMIME ) == 0 ) + return check( GpgME::Context::CMS, reason ); + if ( reason ) + *reason = i18n( "Unsupported protocol \"%1\"" ).arg( name ); + return false; +} + +Kleo::CryptoBackend::Protocol * Kleo::QGpgMEBackend::openpgp() const { + if ( !mOpenPGPProtocol ) + if ( checkForOpenPGP() ) + mOpenPGPProtocol = new CryptPlugWrapper( "gpg", "openpgp" ); + return mOpenPGPProtocol; +} + +Kleo::CryptoBackend::Protocol * Kleo::QGpgMEBackend::smime() const { + if ( !mSMIMEProtocol ) + if ( checkForSMIME() ) + mSMIMEProtocol = new CryptPlugWrapper( "gpgsm", "smime" ); + return mSMIMEProtocol; +} + +Kleo::CryptoBackend::Protocol * Kleo::QGpgMEBackend::protocol( const char * name ) const { + if ( qstricmp( name, OpenPGP ) == 0 ) + return openpgp(); + if ( qstricmp( name, SMIME ) == 0 ) + return smime(); + return 0; +} + +bool Kleo::QGpgMEBackend::supportsProtocol( const char * name ) const { + return qstricmp( name, OpenPGP ) == 0 || qstricmp( name, SMIME ) == 0; +} + +const char * Kleo::QGpgMEBackend::enumerateProtocols( int i ) const { + switch ( i ) { + case 0: return OpenPGP; + case 1: return SMIME; + default: return 0; + } +} diff --git a/certmanager/lib/backends/qgpgme/qgpgmebackend.h b/certmanager/lib/backends/qgpgme/qgpgmebackend.h new file mode 100644 index 000000000..fae2dd68e --- /dev/null +++ b/certmanager/lib/backends/qgpgme/qgpgmebackend.h @@ -0,0 +1,82 @@ +/* -*- mode: C++; c-file-style: "gnu" -*- + qgpgmebackend.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004,2005 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + + +#ifndef __KLEO_QGPGMEBACKEND_H__ +#define __KLEO_QGPGMEBACKEND_H__ + +#include "kleo/cryptobackend.h" + +class CryptPlugWrapper; + +namespace Kleo { + class CryptoConfig; +} +class QGpgMECryptoConfig; +class QString; + +namespace Kleo { + + class QGpgMEBackend : public Kleo::CryptoBackend { + public: + QGpgMEBackend(); + ~QGpgMEBackend(); + + QString name() const; + QString displayName() const; + + CryptoConfig * config() const; + + Protocol * openpgp() const; + Protocol * smime() const; + Protocol * protocol( const char * name ) const; + + bool checkForOpenPGP( QString * reason=0 ) const; + bool checkForSMIME( QString * reason=0 ) const; + bool checkForProtocol( const char * name, QString * reason ) const; + + bool supportsOpenPGP() const { return true; } + bool supportsSMIME() const { return true; } + bool supportsProtocol( const char * name ) const; + + const char * enumerateProtocols( int i ) const; + + private: + mutable QGpgMECryptoConfig * mCryptoConfig; + mutable CryptPlugWrapper * mOpenPGPProtocol; + mutable CryptPlugWrapper * mSMIMEProtocol; + }; + +} + + +#endif // __KLEO_QGPGMEBACKEND_H__ diff --git a/certmanager/lib/backends/qgpgme/qgpgmecryptoconfig.cpp b/certmanager/lib/backends/qgpgme/qgpgmecryptoconfig.cpp new file mode 100644 index 000000000..86eab99b4 --- /dev/null +++ b/certmanager/lib/backends/qgpgme/qgpgmecryptoconfig.cpp @@ -0,0 +1,837 @@ +/* + qgpgmecryptoconfig.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "qgpgmecryptoconfig.h" +#include <kdebug.h> +#include <kprocio.h> +#include <errno.h> +#include <kmessagebox.h> +#include <klocale.h> + +#include <assert.h> +#include <ktempfile.h> +#include <qfile.h> +#include <stdlib.h> +#include <qtextcodec.h> + +// Just for the Q_ASSERT in the dtor. Not thread-safe, but who would +// have 2 threads talking to gpgconf anyway? :) +static bool s_duringClear = false; + +static const int GPGCONF_FLAG_GROUP = 1; +static const int GPGCONF_FLAG_OPTIONAL = 2; +static const int GPGCONF_FLAG_LIST = 4; +static const int GPGCONF_FLAG_RUNTIME = 8; +static const int GPGCONF_FLAG_DEFAULT = 16; // fixed default value available +static const int GPGCONF_FLAG_DEFAULT_DESC = 32; // runtime default value available +static const int GPGCONF_FLAG_NOARG_DESC = 64; // option with optional arg; special meaning if no arg set +static const int GPGCONF_FLAG_NO_CHANGE = 128; // readonly +// Change size of mFlags bitfield if adding new values here + +QGpgMECryptoConfig::QGpgMECryptoConfig() + : mComponents( 7 ), mParsed( false ) +{ + mComponents.setAutoDelete( true ); +} + +QGpgMECryptoConfig::~QGpgMECryptoConfig() +{ +} + +void QGpgMECryptoConfig::runGpgConf( bool showErrors ) +{ + // Run gpgconf --list-components to make the list of components + + KProcIO proc( QTextCodec::codecForName( "utf8" ) ); + proc << "gpgconf"; // must be in the PATH + proc << "--list-components"; + + QObject::connect( &proc, SIGNAL( readReady(KProcIO*) ), + this, SLOT( slotCollectStdOut(KProcIO*) ) ); + + // run the process: + int rc = 0; + if ( !proc.start( KProcess::Block ) ) + rc = -1; + else + rc = ( proc.normalExit() ) ? proc.exitStatus() : -2 ; + + // handle errors, if any (and if requested) + if ( showErrors && rc != 0 ) { + QString wmsg = i18n("<qt>Failed to execute gpgconf:<br>%1</qt>"); + if ( rc == -1 ) + wmsg = wmsg.arg( i18n( "program not found" ) ); + else if ( rc == -2 ) + wmsg = wmsg.arg( i18n( "program cannot be executed" ) ); + else + wmsg = wmsg.arg( strerror(rc) ); + kdWarning(5150) << wmsg << endl; // to see it from test_cryptoconfig.cpp + KMessageBox::error(0, wmsg); + } + mParsed = true; +} + +void QGpgMECryptoConfig::slotCollectStdOut( KProcIO* proc ) +{ + QString line; + int result; + while( ( result = proc->readln(line) ) != -1 ) { + //kdDebug(5150) << "GOT LINE:" << line << endl; + // Format: NAME:DESCRIPTION + QStringList lst = QStringList::split( ':', line, true ); + if ( lst.count() >= 2 ) { + mComponents.insert( lst[0], new QGpgMECryptoConfigComponent( this, lst[0], lst[1] ) ); + } else { + kdWarning(5150) << "Parse error on gpgconf --list-components output: " << line << endl; + } + } +} + +QStringList QGpgMECryptoConfig::componentList() const +{ + if ( !mParsed ) + const_cast<QGpgMECryptoConfig*>( this )->runGpgConf( true ); + QDictIterator<QGpgMECryptoConfigComponent> it( mComponents ); + QStringList names; + for( ; it.current(); ++it ) + names.push_back( it.currentKey() ); + return names; +} + +Kleo::CryptoConfigComponent* QGpgMECryptoConfig::component( const QString& name ) const +{ + if ( !mParsed ) + const_cast<QGpgMECryptoConfig*>( this )->runGpgConf( false ); + return mComponents.find( name ); +} + +void QGpgMECryptoConfig::sync( bool runtime ) +{ + QDictIterator<QGpgMECryptoConfigComponent> it( mComponents ); + for( ; it.current(); ++it ) + it.current()->sync( runtime ); +} + +void QGpgMECryptoConfig::clear() +{ + s_duringClear = true; + mComponents.clear(); + s_duringClear = false; + mParsed = false; // next call to componentList/component will need to run gpgconf again +} + +//// + +QGpgMECryptoConfigComponent::QGpgMECryptoConfigComponent( QGpgMECryptoConfig*, const QString& name, const QString& description ) + : mGroups( 7 ), mName( name ), mDescription( description ) +{ + mGroups.setAutoDelete( true ); + runGpgConf(); +} + +QGpgMECryptoConfigComponent::~QGpgMECryptoConfigComponent() +{ +} + +void QGpgMECryptoConfigComponent::runGpgConf() +{ + // Run gpgconf --list-options <component>, and create all groups and entries for that component + + KProcIO proc( QTextCodec::codecForName( "utf8" ) ); + proc << "gpgconf"; // must be in the PATH + proc << "--list-options"; + proc << mName; + + //kdDebug(5150) << "Running gpgconf --list-options " << mName << endl; + + QObject::connect( &proc, SIGNAL( readReady(KProcIO*) ), + this, SLOT( slotCollectStdOut(KProcIO*) ) ); + mCurrentGroup = 0; + + // run the process: + int rc = 0; + if ( !proc.start( KProcess::Block ) ) + rc = -1; + else + rc = ( proc.normalExit() ) ? proc.exitStatus() : -1 ; + + if( rc != 0 ) // can happen when using the wrong version of gpg... + kdWarning(5150) << "Running 'gpgconf --list-options " << mName << "' failed. " << strerror( rc ) << ", but try that command to see the real output" << endl; + else { + if ( mCurrentGroup && !mCurrentGroup->mEntries.isEmpty() ) // only add non-empty groups + mGroups.insert( mCurrentGroupName, mCurrentGroup ); + } +} + +void QGpgMECryptoConfigComponent::slotCollectStdOut( KProcIO* proc ) +{ + QString line; + int result; + while( ( result = proc->readln(line) ) != -1 ) { + //kdDebug(5150) << "GOT LINE:" << line << endl; + // Format: NAME:FLAGS:LEVEL:DESCRIPTION:TYPE:ALT-TYPE:ARGNAME:DEFAULT:ARGDEF:VALUE + const QStringList lst = QStringList::split( ':', line, true ); + if ( lst.count() >= 10 ) { + const int flags = lst[1].toInt(); + const int level = lst[2].toInt(); + if ( level > 2 ) // invisible or internal -> skip it; + continue; + if ( flags & GPGCONF_FLAG_GROUP ) { + if ( mCurrentGroup && !mCurrentGroup->mEntries.isEmpty() ) // only add non-empty groups + mGroups.insert( mCurrentGroupName, mCurrentGroup ); + //else + // kdDebug(5150) << "Discarding empty group " << mCurrentGroupName << endl; + mCurrentGroup = new QGpgMECryptoConfigGroup( lst[0], lst[3], level ); + mCurrentGroupName = lst[0]; + } else { + // normal entry + if ( !mCurrentGroup ) { // first toplevel entry -> create toplevel group + mCurrentGroup = new QGpgMECryptoConfigGroup( "<nogroup>", QString::null, 0 ); + mCurrentGroupName = "<nogroup>"; + } + mCurrentGroup->mEntries.insert( lst[0], new QGpgMECryptoConfigEntry( lst ) ); + } + } else { + // This happens on lines like + // dirmngr[31465]: error opening `/home/dfaure/.gnupg/dirmngr_ldapservers.conf': No such file or directory + // so let's not bother the user with it. + //kdWarning(5150) << "Parse error on gpgconf --list-options output: " << line << endl; + } + } +} + +QStringList QGpgMECryptoConfigComponent::groupList() const +{ + QDictIterator<QGpgMECryptoConfigGroup> it( mGroups ); + QStringList names; + for( ; it.current(); ++it ) + names.push_back( it.currentKey() ); + return names; +} + +Kleo::CryptoConfigGroup* QGpgMECryptoConfigComponent::group(const QString& name ) const +{ + return mGroups.find( name ); +} + +void QGpgMECryptoConfigComponent::sync( bool runtime ) +{ + KTempFile tmpFile; + tmpFile.setAutoDelete( true ); + + QValueList<QGpgMECryptoConfigEntry *> dirtyEntries; + + // Collect all dirty entries + QDictIterator<QGpgMECryptoConfigGroup> groupit( mGroups ); + for( ; groupit.current(); ++groupit ) { + QDictIterator<QGpgMECryptoConfigEntry> it( groupit.current()->mEntries ); + for( ; it.current(); ++it ) { + if ( it.current()->isDirty() ) { + // OK, we can set it.currentKey() to it.current()->outputString() + QString line = it.currentKey(); + if ( it.current()->isSet() ) { // set option + line += ":0:"; + line += it.current()->outputString(); + } else { // unset option + line += ":16:"; + } + line += '\n'; + QCString line8bit = line.utf8(); // encode with utf8, and KProcIO uses utf8 when reading. + tmpFile.file()->writeBlock( line8bit.data(), line8bit.size()-1 /*no 0*/ ); + dirtyEntries.append( it.current() ); + } + } + } + tmpFile.close(); + if ( dirtyEntries.isEmpty() ) + return; + + // Call gpgconf --change-options <component> + QString commandLine = "gpgconf"; + if ( runtime ) + commandLine += " --runtime"; + commandLine += " --change-options "; + commandLine += KProcess::quote( mName ); + commandLine += " < "; + commandLine += KProcess::quote( tmpFile.name() ); + + //kdDebug(5150) << commandLine << endl; + //system( QCString( "cat " ) + tmpFile.name().latin1() ); // DEBUG + + KProcess proc; + proc.setUseShell( true ); + proc << commandLine; + + // run the process: + int rc = 0; + if ( !proc.start( KProcess::Block ) ) + rc = -1; + else + rc = ( proc.normalExit() ) ? proc.exitStatus() : -1 ; + + if ( rc == -1 ) + { + QString wmsg = i18n( "Could not start gpgconf\nCheck that gpgconf is in the PATH and that it can be started" ); + kdWarning(5150) << wmsg << endl; + KMessageBox::error(0, wmsg); + } + else if( rc != 0 ) // Happens due to bugs in gpgconf (e.g. issues 104/115) + { + QString wmsg = i18n( "Error from gpgconf while saving configuration: %1" ).arg( QString::fromLocal8Bit( strerror( rc ) ) ); + kdWarning(5150) << k_funcinfo << ":" << strerror( rc ) << endl; + KMessageBox::error(0, wmsg); + } + else + { + QValueList<QGpgMECryptoConfigEntry *>::Iterator it = dirtyEntries.begin(); + for( ; it != dirtyEntries.end(); ++it ) { + (*it)->setDirty( false ); + } + } +} + +//// + +QGpgMECryptoConfigGroup::QGpgMECryptoConfigGroup( const QString & name, const QString& description, int level ) + : mEntries( 29 ), + mName( name ), + mDescription( description ), + mLevel( static_cast<Kleo::CryptoConfigEntry::Level>( level ) ) +{ + mEntries.setAutoDelete( true ); +} + +QStringList QGpgMECryptoConfigGroup::entryList() const +{ + QDictIterator<QGpgMECryptoConfigEntry> it( mEntries ); + QStringList names; + for( ; it.current(); ++it ) + names.push_back( it.currentKey() ); + return names; +} + +Kleo::CryptoConfigEntry* QGpgMECryptoConfigGroup::entry( const QString& name ) const +{ + return mEntries.find( name ); +} + +//// + +static QString gpgconf_unescape( const QString& str ) +{ + // Looks like it's the same rules as KURL. + return KURL::decode_string( str, 106 ); +} + +static QString gpgconf_escape( const QString& str ) +{ + // Escape special chars (including ':' and '%') + QString enc = KURL::encode_string( str, 106 ); // and convert to utf8 first (to get %12%34 for one special char) + // Also encode commas, for lists. + enc.replace( ',', "%2c" ); + return enc; +} + +static QString urlpart_encode( const QString& str ) +{ + QString enc( str ); + enc.replace( '%', "%25" ); // first! + enc.replace( ':', "%3a" ); + //kdDebug() << " urlpart_encode: " << str << " -> " << enc << endl; + return enc; +} + +static QString urlpart_decode( const QString& str ) +{ + return KURL::decode_string( str ); +} + +// gpgconf arg type number -> CryptoConfigEntry arg type enum mapping +static Kleo::CryptoConfigEntry::ArgType knownArgType( int argType, bool& ok ) { + ok = true; + switch( argType ) { + case 0: // none + return Kleo::CryptoConfigEntry::ArgType_None; + case 1: // string + return Kleo::CryptoConfigEntry::ArgType_String; + case 2: // int32 + return Kleo::CryptoConfigEntry::ArgType_Int; + case 3: // uint32 + return Kleo::CryptoConfigEntry::ArgType_UInt; + case 32: // pathname + return Kleo::CryptoConfigEntry::ArgType_Path; + case 33: // ldap server + return Kleo::CryptoConfigEntry::ArgType_LDAPURL; + default: + ok = false; + return Kleo::CryptoConfigEntry::ArgType_None; + } +} + +QGpgMECryptoConfigEntry::QGpgMECryptoConfigEntry( const QStringList& parsedLine ) +{ + // Format: NAME:FLAGS:LEVEL:DESCRIPTION:TYPE:ALT-TYPE:ARGNAME:DEFAULT:ARGDEF:VALUE + assert( parsedLine.count() >= 10 ); // called checked for it already + QStringList::const_iterator it = parsedLine.begin(); + mName = *it++; + mFlags = (*it++).toInt(); + mLevel = (*it++).toInt(); + mDescription = *it++; + bool ok; + // we keep the real (int) arg type, since it influences the parsing (e.g. for ldap urls) + mRealArgType = (*it++).toInt(); + mArgType = knownArgType( mRealArgType, ok ); + if ( !ok && !(*it).isEmpty() ) { + // use ALT-TYPE + mRealArgType = (*it).toInt(); + mArgType = knownArgType( mRealArgType, ok ); + } + if ( !ok ) + kdWarning(5150) << "Unsupported datatype: " << parsedLine[4] << " : " << *it << " for " << parsedLine[0] << endl; + ++it; // done with alt-type + ++it; // skip argname (not useful in GUIs) + + mSet = false; + QString value; + if ( mFlags & GPGCONF_FLAG_DEFAULT ) { + value = *it; // get default value + mDefaultValue = stringToValue( value, true ); + } + ++it; // done with DEFAULT + ++it; // ### skip ARGDEF for now. It's only for options with an "optional arg" + //kdDebug(5150) << "Entry " << parsedLine[0] << " val=" << *it << endl; + + if ( !(*it).isEmpty() ) { // a real value was set + mSet = true; + value = *it; + mValue = stringToValue( value, true ); + } + else { + mValue = mDefaultValue; + } + + mDirty = false; +} + +QVariant QGpgMECryptoConfigEntry::stringToValue( const QString& str, bool unescape ) const +{ + bool isString = isStringType(); + + if ( isList() ) { + QValueList<QVariant> lst; + QStringList items = QStringList::split( ',', str ); + for( QStringList::const_iterator valit = items.begin(); valit != items.end(); ++valit ) { + QString val = *valit; + if ( isString ) { + if ( val.isEmpty() ) { + lst << QString::null; + continue; + } + else if ( unescape ) { + if( val[0] != '"' ) // see README.gpgconf + kdWarning(5150) << "String value should start with '\"' : " << val << endl; + val = val.mid( 1 ); + } + } + lst << QVariant( unescape ? gpgconf_unescape( val ) : val ); + } + return lst; + } else { // not a list + QString val( str ); + if ( isString ) { + if ( val.isEmpty() ) + return QVariant( QString::null ); // not set [ok with lists too?] + else if ( unescape ) { + Q_ASSERT( val[0] == '"' ); // see README.gpgconf + val = val.mid( 1 ); + } + } + return QVariant( unescape ? gpgconf_unescape( val ) : val ); + } +} + +QGpgMECryptoConfigEntry::~QGpgMECryptoConfigEntry() +{ +#ifndef NDEBUG + if ( !s_duringClear && mDirty ) + kdWarning(5150) << "Deleting a QGpgMECryptoConfigEntry that was modified (" << mDescription << ")\n" + << "You forgot to call sync() (to commit) or clear() (to discard)" << endl; +#endif +} + +bool QGpgMECryptoConfigEntry::isOptional() const +{ + return mFlags & GPGCONF_FLAG_OPTIONAL; +} + +bool QGpgMECryptoConfigEntry::isReadOnly() const +{ + return mFlags & GPGCONF_FLAG_NO_CHANGE; +} + +bool QGpgMECryptoConfigEntry::isList() const +{ + return mFlags & GPGCONF_FLAG_LIST; +} + +bool QGpgMECryptoConfigEntry::isRuntime() const +{ + return mFlags & GPGCONF_FLAG_RUNTIME; +} + +bool QGpgMECryptoConfigEntry::isSet() const +{ + return mSet; +} + +bool QGpgMECryptoConfigEntry::boolValue() const +{ + Q_ASSERT( mArgType == ArgType_None ); + Q_ASSERT( !isList() ); + return mValue.toBool(); +} + +QString QGpgMECryptoConfigEntry::stringValue() const +{ + return toString( false ); +} + +int QGpgMECryptoConfigEntry::intValue() const +{ + Q_ASSERT( mArgType == ArgType_Int ); + Q_ASSERT( !isList() ); + return mValue.toInt(); +} + +unsigned int QGpgMECryptoConfigEntry::uintValue() const +{ + Q_ASSERT( mArgType == ArgType_UInt ); + Q_ASSERT( !isList() ); + return mValue.toUInt(); +} + +static KURL parseURL( int mRealArgType, const QString& str ) +{ + if ( mRealArgType == 33 ) { // LDAP server + // The format is HOSTNAME:PORT:USERNAME:PASSWORD:BASE_DN + QStringList items = QStringList::split( ':', str, true ); + if ( items.count() == 5 ) { + QStringList::const_iterator it = items.begin(); + KURL url; + url.setProtocol( "ldap" ); + url.setHost( urlpart_decode( *it++ ) ); + url.setPort( (*it++).toInt() ); + url.setPath( "/" ); // workaround KURL parsing bug + url.setUser( urlpart_decode( *it++ ) ); + url.setPass( urlpart_decode( *it++ ) ); + url.setQuery( urlpart_decode( *it ) ); + return url; + } else + kdWarning(5150) << "parseURL: malformed LDAP server: " << str << endl; + } + // other URLs : assume wellformed URL syntax. + return KURL( str ); +} + +// The opposite of parseURL +static QString splitURL( int mRealArgType, const KURL& url ) +{ + if ( mRealArgType == 33 ) { // LDAP server + // The format is HOSTNAME:PORT:USERNAME:PASSWORD:BASE_DN + Q_ASSERT( url.protocol() == "ldap" ); + return urlpart_encode( url.host() ) + ":" + + QString::number( url.port() ) + ":" + + urlpart_encode( url.user() ) + ":" + + urlpart_encode( url.pass() ) + ":" + + // KURL automatically encoded the query (e.g. for spaces inside it), + // so decode it before writing it out to gpgconf (issue119) + urlpart_encode( KURL::decode_string( url.query().mid(1) ) ); + } + return url.path(); +} + +KURL QGpgMECryptoConfigEntry::urlValue() const +{ + Q_ASSERT( mArgType == ArgType_Path || mArgType == ArgType_URL || mArgType == ArgType_LDAPURL ); + Q_ASSERT( !isList() ); + QString str = mValue.toString(); + if ( mArgType == ArgType_Path ) + { + KURL url; + url.setPath( str ); + return url; + } + return parseURL( mRealArgType, str ); +} + +unsigned int QGpgMECryptoConfigEntry::numberOfTimesSet() const +{ + Q_ASSERT( mArgType == ArgType_None ); + Q_ASSERT( isList() ); + return mValue.toUInt(); +} + +QStringList QGpgMECryptoConfigEntry::stringValueList() const +{ + Q_ASSERT( isStringType() ); + Q_ASSERT( isList() ); + return mValue.toStringList(); +} + +QValueList<int> QGpgMECryptoConfigEntry::intValueList() const +{ + Q_ASSERT( mArgType == ArgType_Int ); + Q_ASSERT( isList() ); + QValueList<int> ret; + QValueList<QVariant> lst = mValue.toList(); + for( QValueList<QVariant>::const_iterator it = lst.begin(); it != lst.end(); ++it ) { + ret.append( (*it).toInt() ); + } + return ret; +} + +QValueList<unsigned int> QGpgMECryptoConfigEntry::uintValueList() const +{ + Q_ASSERT( mArgType == ArgType_UInt ); + Q_ASSERT( isList() ); + QValueList<unsigned int> ret; + QValueList<QVariant> lst = mValue.toList(); + for( QValueList<QVariant>::const_iterator it = lst.begin(); it != lst.end(); ++it ) { + ret.append( (*it).toUInt() ); + } + return ret; +} + +KURL::List QGpgMECryptoConfigEntry::urlValueList() const +{ + Q_ASSERT( mArgType == ArgType_Path || mArgType == ArgType_URL || mArgType == ArgType_LDAPURL ); + Q_ASSERT( isList() ); + QStringList lst = mValue.toStringList(); + + KURL::List ret; + for( QStringList::const_iterator it = lst.begin(); it != lst.end(); ++it ) { + if ( mArgType == ArgType_Path ) { + KURL url; + url.setPath( *it ); + ret << url; + } else { + ret << parseURL( mRealArgType, *it ); + } + } + return ret; +} + +void QGpgMECryptoConfigEntry::resetToDefault() +{ + mSet = false; + mDirty = true; + if ( mFlags & GPGCONF_FLAG_DEFAULT ) + mValue = mDefaultValue; + else if ( mArgType == ArgType_None ) + mValue = false; +} + +void QGpgMECryptoConfigEntry::setBoolValue( bool b ) +{ + Q_ASSERT( mArgType == ArgType_None ); + Q_ASSERT( !isList() ); + // A "no arg" option is either set or not set. + // Being set means mSet==true + mValue==true, being unset means resetToDefault(), i.e. both false + mValue = b; + mSet = b; + mDirty = true; +} + +void QGpgMECryptoConfigEntry::setStringValue( const QString& str ) +{ + mValue = stringToValue( str, false ); + // When setting a string to empty (and there's no default), we need to act like resetToDefault + // Otherwise we try e.g. "ocsp-responder:0:" and gpgconf answers: + // "gpgconf: argument required for option ocsp-responder" + if ( str.isEmpty() && !isOptional() ) + mSet = false; + else + mSet = true; + mDirty = true; +} + +void QGpgMECryptoConfigEntry::setIntValue( int i ) +{ + Q_ASSERT( mArgType == ArgType_Int ); + Q_ASSERT( !isList() ); + mValue = i; + mSet = true; + mDirty = true; +} + +void QGpgMECryptoConfigEntry::setUIntValue( unsigned int i ) +{ + mValue = i; + mSet = true; + mDirty = true; +} + +void QGpgMECryptoConfigEntry::setURLValue( const KURL& url ) +{ + QString str = splitURL( mRealArgType, url ); + if ( str.isEmpty() && !isOptional() ) + mSet = false; + else + mSet = true; + mValue = str; + mDirty = true; +} + +void QGpgMECryptoConfigEntry::setNumberOfTimesSet( unsigned int i ) +{ + Q_ASSERT( mArgType == ArgType_None ); + Q_ASSERT( isList() ); + setUIntValue( i ); +} + +void QGpgMECryptoConfigEntry::setStringValueList( const QStringList& lst ) +{ + mValue = lst; + if ( lst.isEmpty() && !isOptional() ) + mSet = false; + else + mSet = true; + mDirty = true; +} + +void QGpgMECryptoConfigEntry::setIntValueList( const QValueList<int>& lst ) +{ + QValueList<QVariant> ret; + for( QValueList<int>::const_iterator it = lst.begin(); it != lst.end(); ++it ) { + ret << QVariant( *it ); + } + mValue = ret; + if ( ret.isEmpty() && !isOptional() ) + mSet = false; + else + mSet = true; + mDirty = true; +} + +void QGpgMECryptoConfigEntry::setUIntValueList( const QValueList<unsigned int>& lst ) +{ + QValueList<QVariant> ret; + for( QValueList<unsigned int>::const_iterator it = lst.begin(); it != lst.end(); ++it ) { + ret << QVariant( *it ); + } + if ( ret.isEmpty() && !isOptional() ) + mSet = false; + else + mSet = true; + mValue = ret; + mDirty = true; +} + +void QGpgMECryptoConfigEntry::setURLValueList( const KURL::List& urls ) +{ + QStringList lst; + for( KURL::List::const_iterator it = urls.begin(); it != urls.end(); ++it ) { + lst << splitURL( mRealArgType, *it ); + } + mValue = lst; + if ( lst.isEmpty() && !isOptional() ) + mSet = false; + else + mSet = true; + mDirty = true; +} + +QString QGpgMECryptoConfigEntry::toString( bool escape ) const +{ + // Basically the opposite of stringToValue + if ( isStringType() ) { + if ( mValue.isNull() ) + return QString::null; + else if ( isList() ) { // string list + QStringList lst = mValue.toStringList(); + if ( escape ) { + for( QStringList::iterator it = lst.begin(); it != lst.end(); ++it ) { + if ( !(*it).isNull() ) + *it = gpgconf_escape( *it ).prepend( "\"" ); + } + } + QString res = lst.join( "," ); + kdDebug(5150) << "toString: " << res << endl; + return res; + } else { // normal string + QString res = mValue.toString(); + if ( escape ) + res = gpgconf_escape( res ).prepend( "\"" ); + return res; + } + } + if ( !isList() ) // non-list non-string + { + if ( mArgType == ArgType_None ) { + return mValue.toBool() ? QString::fromLatin1( "1" ) : QString::null; + } else { // some int + Q_ASSERT( mArgType == ArgType_Int || mArgType == ArgType_UInt ); + return mValue.toString(); // int to string conversion + } + } + + // Lists (of other types than strings) + if ( mArgType == ArgType_None ) + return QString::number( numberOfTimesSet() ); + QStringList ret; + QValueList<QVariant> lst = mValue.toList(); + for( QValueList<QVariant>::const_iterator it = lst.begin(); it != lst.end(); ++it ) { + ret << (*it).toString(); // QVariant does the conversion + } + return ret.join( "," ); +} + +QString QGpgMECryptoConfigEntry::outputString() const +{ + Q_ASSERT( mSet ); + return toString( true ); +} + +bool QGpgMECryptoConfigEntry::isStringType() const +{ + return ( mArgType == Kleo::CryptoConfigEntry::ArgType_String + || mArgType == Kleo::CryptoConfigEntry::ArgType_Path + || mArgType == Kleo::CryptoConfigEntry::ArgType_URL + || mArgType == Kleo::CryptoConfigEntry::ArgType_LDAPURL ); +} + +void QGpgMECryptoConfigEntry::setDirty( bool b ) +{ + mDirty = b; +} + +#include "qgpgmecryptoconfig.moc" diff --git a/certmanager/lib/backends/qgpgme/qgpgmecryptoconfig.h b/certmanager/lib/backends/qgpgme/qgpgmecryptoconfig.h new file mode 100644 index 000000000..bfcb8e5ca --- /dev/null +++ b/certmanager/lib/backends/qgpgme/qgpgmecryptoconfig.h @@ -0,0 +1,186 @@ +/* + qgpgmecryptoconfig.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef KLEO_QGPGMECRYPTOCONFIG_H +#define KLEO_QGPGMECRYPTOCONFIG_H + +#include <kleo/cryptoconfig.h> +#include <qdict.h> +#include <qstringlist.h> +#include <qobject.h> +#include <qvariant.h> +class KProcIO; + +class QGpgMECryptoConfigComponent; +class QGpgMECryptoConfigEntry; +/** + * CryptoConfig implementation around the gpgconf command-line tool + * For method docu, see kleo/cryptoconfig.h + */ +class QGpgMECryptoConfig : public QObject, public Kleo::CryptoConfig { + + Q_OBJECT +public: + /** + * Constructor + */ + QGpgMECryptoConfig(); + virtual ~QGpgMECryptoConfig(); + + virtual QStringList componentList() const; + + virtual Kleo::CryptoConfigComponent* component( const QString& name ) const; + + virtual void clear(); + virtual void sync( bool runtime ); + +private slots: + void slotCollectStdOut( KProcIO* proc ); +private: + /// @param showErrors if true, a messagebox will be shown if e.g. gpgconf wasn't found + void runGpgConf( bool showErrors ); + +private: + QDict<QGpgMECryptoConfigComponent> mComponents; + bool mParsed; +}; + +class QGpgMECryptoConfigGroup; + +/// For docu, see kleo/cryptoconfig.h +class QGpgMECryptoConfigComponent : public QObject, public Kleo::CryptoConfigComponent { + + Q_OBJECT +public: + QGpgMECryptoConfigComponent( QGpgMECryptoConfig*, const QString& name, const QString& description ); + ~QGpgMECryptoConfigComponent(); + + QString name() const { return mName; } + QString iconName() const { return mName; } + QString description() const { return mDescription; } + QStringList groupList() const; + Kleo::CryptoConfigGroup* group( const QString& name ) const; + + void sync( bool runtime ); + +private slots: + void slotCollectStdOut( KProcIO* proc ); +private: + void runGpgConf(); + +private: + QDict<QGpgMECryptoConfigGroup> mGroups; + QString mName; + QString mDescription; + QGpgMECryptoConfigGroup* mCurrentGroup; // during parsing + QString mCurrentGroupName; // during parsing +}; + +class QGpgMECryptoConfigGroup : public Kleo::CryptoConfigGroup { + +public: + QGpgMECryptoConfigGroup( const QString & name, const QString& description, int level ); + ~QGpgMECryptoConfigGroup() {} + + QString name() const { return mName; } + QString iconName() const { return QString::null; } + QString description() const { return mDescription; } + Kleo::CryptoConfigEntry::Level level() const { return mLevel; } + QStringList entryList() const; + Kleo::CryptoConfigEntry* entry( const QString& name ) const; + +private: + friend class QGpgMECryptoConfigComponent; // it adds the entries + QDict<QGpgMECryptoConfigEntry> mEntries; + QString mName; + QString mDescription; + Kleo::CryptoConfigEntry::Level mLevel; +}; + +class QGpgMECryptoConfigEntry : public Kleo::CryptoConfigEntry { +public: + QGpgMECryptoConfigEntry( const QStringList& parsedLine ); + ~QGpgMECryptoConfigEntry(); + + QString name() const { return mName; } + QString description() const { return mDescription; } + bool isOptional() const; + bool isReadOnly() const; + bool isList() const; + bool isRuntime() const; + Level level() const { return static_cast<Level>( mLevel ); } + ArgType argType() const { return static_cast<ArgType>( mArgType ); } + bool isSet() const; + bool boolValue() const; + QString stringValue() const; + int intValue() const; + unsigned int uintValue() const; + KURL urlValue() const; + unsigned int numberOfTimesSet() const; + QStringList stringValueList() const; + QValueList<int> intValueList() const; + QValueList<unsigned int> uintValueList() const; + KURL::List urlValueList() const; + void resetToDefault(); + void setBoolValue( bool ); + void setStringValue( const QString& ); + void setIntValue( int ); + void setUIntValue( unsigned int ); + void setURLValue( const KURL& ); + void setNumberOfTimesSet( unsigned int ); + void setStringValueList( const QStringList& ); + void setIntValueList( const QValueList<int>& ); + void setUIntValueList( const QValueList<unsigned int>& ); + void setURLValueList( const KURL::List& ); + bool isDirty() const { return mDirty; } + + void setDirty( bool b ); + QString outputString() const; + +protected: + bool isStringType() const; + QVariant stringToValue( const QString& value, bool unescape ) const; + QString toString( bool escape ) const; +private: + QString mName; + QString mDescription; + QVariant mDefaultValue; + QVariant mValue; + uint mFlags : 8; // bitfield with 8 bits + uint mLevel : 3; // max is 4 (2, in fact) -> 3 bits + uint mRealArgType : 6; // max is 33 -> 6 bits + uint mArgType : 3; // max is 6 (ArgType enum) -> 3 bits; + uint mDirty : 1; + uint mSet : 1; +}; + +#endif /* KLEO_QGPGMECRYPTOCONFIG_H */ diff --git a/certmanager/lib/backends/qgpgme/qgpgmedecryptjob.cpp b/certmanager/lib/backends/qgpgme/qgpgmedecryptjob.cpp new file mode 100644 index 000000000..17905555e --- /dev/null +++ b/certmanager/lib/backends/qgpgme/qgpgmedecryptjob.cpp @@ -0,0 +1,91 @@ +/* + qgpgmedecryptjob.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "qgpgmedecryptjob.h" + +#include <qgpgme/eventloopinteractor.h> +#include <qgpgme/dataprovider.h> + +#include <gpgmepp/context.h> +#include <gpgmepp/decryptionresult.h> +#include <gpgmepp/data.h> + +#include <assert.h> + +Kleo::QGpgMEDecryptJob::QGpgMEDecryptJob( GpgME::Context * context ) + : DecryptJob( QGpgME::EventLoopInteractor::instance(), "Kleo::QGpgMEDecryptJob" ), + QGpgMEJob( this, context ) +{ + assert( context ); +} + +Kleo::QGpgMEDecryptJob::~QGpgMEDecryptJob() { +} + +void Kleo::QGpgMEDecryptJob::setup( const QByteArray & cipherText ) { + assert( !mInData ); + assert( !mOutData ); + + createInData( cipherText ); + createOutData(); +} + +GpgME::Error Kleo::QGpgMEDecryptJob::start( const QByteArray & cipherText ) { + setup( cipherText ); + + hookupContextToEventLoopInteractor(); + + const GpgME::Error err = mCtx->startDecryption( *mInData, *mOutData ); + + if ( err ) + deleteLater(); + return err; +} + +GpgME::DecryptionResult Kleo::QGpgMEDecryptJob::exec( const QByteArray & cipherText, + QByteArray & plainText ) { + setup( cipherText ); + const GpgME::DecryptionResult result = mCtx->decrypt( *mInData, *mOutData ); + plainText = mOutDataDataProvider->data(); + getAuditLog(); + return result; +} + +void Kleo::QGpgMEDecryptJob::doOperationDoneEvent( const GpgME::Error & ) { + emit result( mCtx->decryptionResult(), mOutDataDataProvider->data() ); +} + +#include "qgpgmedecryptjob.moc" diff --git a/certmanager/lib/backends/qgpgme/qgpgmedecryptjob.h b/certmanager/lib/backends/qgpgme/qgpgmedecryptjob.h new file mode 100644 index 000000000..7fc89dff2 --- /dev/null +++ b/certmanager/lib/backends/qgpgme/qgpgmedecryptjob.h @@ -0,0 +1,74 @@ +/* + qgpgmedecryptjob.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_QGPGMEDECRYPTJOB_H__ +#define __KLEO_QGPGMEDECRYPTJOB_H__ + +#include <kleo/decryptjob.h> + +#include "qgpgmejob.h" + +#include <qcstring.h> + +namespace GpgME { + class Error; + class Context; +} + +namespace Kleo { + + class QGpgMEDecryptJob : public DecryptJob, private QGpgMEJob { + Q_OBJECT QGPGME_JOB + public: + QGpgMEDecryptJob( GpgME::Context * context ); + ~QGpgMEDecryptJob(); + + /*! \reimp from DecryptJob */ + GpgME::Error start( const QByteArray & cipherText ); + + /*! \reimp from DecryptJob */ + GpgME::DecryptionResult exec( const QByteArray & cipherText, + QByteArray & plainText ); + + private slots: + void slotOperationDoneEvent( GpgME::Context * context, const GpgME::Error & e ) { + QGpgMEJob::doSlotOperationDoneEvent( context, e ); + } + + private: + void doOperationDoneEvent( const GpgME::Error & e ); + void setup( const QByteArray & cipherText ); + }; + +} + +#endif // __KLEO_QGPGMEDECRYPTJOB_H__ diff --git a/certmanager/lib/backends/qgpgme/qgpgmedecryptverifyjob.cpp b/certmanager/lib/backends/qgpgme/qgpgmedecryptverifyjob.cpp new file mode 100644 index 000000000..02cf1ef28 --- /dev/null +++ b/certmanager/lib/backends/qgpgme/qgpgmedecryptverifyjob.cpp @@ -0,0 +1,95 @@ +/* + qgpgmedecryptverifyjob.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "qgpgmedecryptverifyjob.h" + +#include <qgpgme/eventloopinteractor.h> +#include <qgpgme/dataprovider.h> + +#include <gpgmepp/context.h> +#include <gpgmepp/decryptionresult.h> +#include <gpgmepp/verificationresult.h> +#include <gpgmepp/data.h> + +#include <assert.h> + +Kleo::QGpgMEDecryptVerifyJob::QGpgMEDecryptVerifyJob( GpgME::Context * context ) + : DecryptVerifyJob( QGpgME::EventLoopInteractor::instance(), "Kleo::QGpgMEDecryptVerifyJob" ), + QGpgMEJob( this, context ) +{ + assert( context ); +} + +Kleo::QGpgMEDecryptVerifyJob::~QGpgMEDecryptVerifyJob() { +} + +void Kleo::QGpgMEDecryptVerifyJob::setup( const QByteArray & cipherText ) { + assert( !mInData ); + assert( !mOutData ); + + createInData( cipherText ); + createOutData(); +} + +GpgME::Error Kleo::QGpgMEDecryptVerifyJob::start( const QByteArray & cipherText ) { + setup( cipherText ); + + hookupContextToEventLoopInteractor(); + + const GpgME::Error err = mCtx->startCombinedDecryptionAndVerification( *mInData, *mOutData ); + + if ( err ) + deleteLater(); + return err; +} + +std::pair<GpgME::DecryptionResult,GpgME::VerificationResult> +Kleo::QGpgMEDecryptVerifyJob::exec( const QByteArray & cipherText, QByteArray & plainText ) { + setup( cipherText ); + const std::pair<GpgME::DecryptionResult,GpgME::VerificationResult> result = + mCtx->decryptAndVerify( *mInData, *mOutData ); + plainText = mOutDataDataProvider->data(); + getAuditLog(); + return result; +} + +void Kleo::QGpgMEDecryptVerifyJob::doOperationDoneEvent( const GpgME::Error & ) { + emit result( mCtx->decryptionResult(), + mCtx->verificationResult(), + mOutDataDataProvider->data() ); +} + +#include "qgpgmedecryptverifyjob.moc" diff --git a/certmanager/lib/backends/qgpgme/qgpgmedecryptverifyjob.h b/certmanager/lib/backends/qgpgme/qgpgmedecryptverifyjob.h new file mode 100644 index 000000000..a39188746 --- /dev/null +++ b/certmanager/lib/backends/qgpgme/qgpgmedecryptverifyjob.h @@ -0,0 +1,75 @@ +/* + qgpgmedecryptverifyjob.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_QGPGMEDECRYPTVERIFYJOB_H__ +#define __KLEO_QGPGMEDECRYPTVERIFYJOB_H__ + +#include <kleo/decryptverifyjob.h> + +#include "qgpgmejob.h" + +#include <qcstring.h> +#include <kdepimmacros.h> + +namespace GpgME { + class Error; + class Context; +} + +namespace Kleo { + + class KDE_EXPORT QGpgMEDecryptVerifyJob : public DecryptVerifyJob, private QGpgMEJob { + Q_OBJECT QGPGME_JOB + public: + QGpgMEDecryptVerifyJob( GpgME::Context * context ); + ~QGpgMEDecryptVerifyJob(); + + /*! \reimp from DecryptVerifyJob */ + GpgME::Error start( const QByteArray & cipherText ); + + /*! \reimp from DecryptVerifyJob */ + std::pair<GpgME::DecryptionResult,GpgME::VerificationResult> + exec( const QByteArray & cipherText, QByteArray & plainText ); + + private slots: + void slotOperationDoneEvent( GpgME::Context * context, const GpgME::Error & e ) { + QGpgMEJob::doSlotOperationDoneEvent( context, e ); + } + + private: + void doOperationDoneEvent( const GpgME::Error & e ); + void setup( const QByteArray & ); + }; + +} + +#endif // __KLEO_QGPGMEDECRYPTVERIFYJOB_H__ diff --git a/certmanager/lib/backends/qgpgme/qgpgmedeletejob.cpp b/certmanager/lib/backends/qgpgme/qgpgmedeletejob.cpp new file mode 100644 index 000000000..c06907eea --- /dev/null +++ b/certmanager/lib/backends/qgpgme/qgpgmedeletejob.cpp @@ -0,0 +1,70 @@ +/* + qgpgmedeletejob.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "qgpgmedeletejob.h" + +#include <qgpgme/eventloopinteractor.h> + +#include <gpgmepp/context.h> + +#include <assert.h> + +Kleo::QGpgMEDeleteJob::QGpgMEDeleteJob( GpgME::Context * context ) + : DeleteJob( QGpgME::EventLoopInteractor::instance(), "Kleo::QGpgMEDeleteJob" ), + QGpgMEJob( this, context ) +{ + assert( context ); +} + +Kleo::QGpgMEDeleteJob::~QGpgMEDeleteJob() { +} + +GpgME::Error Kleo::QGpgMEDeleteJob::start( const GpgME::Key & key, bool allowSecretKeyDeletion ) { + + hookupContextToEventLoopInteractor(); + + const GpgME::Error err = mCtx->startKeyDeletion( key, allowSecretKeyDeletion ); + + if ( err ) + deleteLater(); + return err; +} + +void Kleo::QGpgMEDeleteJob::doOperationDoneEvent( const GpgME::Error & error ) { + emit result( error ); +} + +#include "qgpgmedeletejob.moc" diff --git a/certmanager/lib/backends/qgpgme/qgpgmedeletejob.h b/certmanager/lib/backends/qgpgme/qgpgmedeletejob.h new file mode 100644 index 000000000..9dec128f7 --- /dev/null +++ b/certmanager/lib/backends/qgpgme/qgpgmedeletejob.h @@ -0,0 +1,68 @@ +/* + qgpgmedeletejob.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_QGPGMEDELETEJOB_H__ +#define __KLEO_QGPGMEDELETEJOB_H__ + +#include <kleo/deletejob.h> + +#include "qgpgmejob.h" + +namespace GpgME { + class Error; + class Context; + class Key; +} + +namespace Kleo { + + class QGpgMEDeleteJob : public DeleteJob, private QGpgMEJob { + Q_OBJECT QGPGME_JOB + public: + QGpgMEDeleteJob( GpgME::Context * context ); + ~QGpgMEDeleteJob(); + + /*! \reimp from DeleteJob */ + GpgME::Error start( const GpgME::Key & key, bool allowSecretKeyDeletion ); + + private slots: + void slotOperationDoneEvent( GpgME::Context * context, const GpgME::Error & e ) { + QGpgMEJob::doSlotOperationDoneEvent( context, e ); + } + + private: + void doOperationDoneEvent( const GpgME::Error & e ); + }; + +} + +#endif // __KLEO_QGPGMEDELETEJOB_H__ diff --git a/certmanager/lib/backends/qgpgme/qgpgmedownloadjob.cpp b/certmanager/lib/backends/qgpgme/qgpgmedownloadjob.cpp new file mode 100644 index 000000000..6ee771a04 --- /dev/null +++ b/certmanager/lib/backends/qgpgme/qgpgmedownloadjob.cpp @@ -0,0 +1,78 @@ +/* + qgpgmedownloadjob.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "qgpgmedownloadjob.h" + +#include <qgpgme/eventloopinteractor.h> +#include <qgpgme/dataprovider.h> + +#include <gpgmepp/context.h> +#include <gpgmepp/data.h> + +#include <qstringlist.h> + +#include <assert.h> + +Kleo::QGpgMEDownloadJob::QGpgMEDownloadJob( GpgME::Context * context ) + : DownloadJob( QGpgME::EventLoopInteractor::instance(), "Kleo::QGpgMEDownloadJob" ), + QGpgMEJob( this, context ) +{ + assert( context ); +} + +Kleo::QGpgMEDownloadJob::~QGpgMEDownloadJob() { +} + +GpgME::Error Kleo::QGpgMEDownloadJob::start( const QStringList & pats ) { + assert( !patterns() ); + assert( !mOutData ); + + createOutData(); + setPatterns( pats ); + hookupContextToEventLoopInteractor(); + + const GpgME::Error err = mCtx->startPublicKeyExport( patterns(), *mOutData ); + + if ( err ) + deleteLater(); + return err; +} + +void Kleo::QGpgMEDownloadJob::doOperationDoneEvent( const GpgME::Error & error ) { + emit result( error, mOutDataDataProvider->data() ); +} + +#include "qgpgmedownloadjob.moc" diff --git a/certmanager/lib/backends/qgpgme/qgpgmedownloadjob.h b/certmanager/lib/backends/qgpgme/qgpgmedownloadjob.h new file mode 100644 index 000000000..1402b127c --- /dev/null +++ b/certmanager/lib/backends/qgpgme/qgpgmedownloadjob.h @@ -0,0 +1,67 @@ +/* + qgpgmedownloadjob.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_QGPGMEDOWNLOADJOB_H__ +#define __KLEO_QGPGMEDOWNLOADJOB_H__ + +#include <kleo/downloadjob.h> + +#include "qgpgmejob.h" + +namespace GpgME { + class Error; + class Context; +} + +namespace Kleo { + + class QGpgMEDownloadJob : public DownloadJob, private QGpgMEJob { + Q_OBJECT QGPGME_JOB + public: + QGpgMEDownloadJob( GpgME::Context * context ); + ~QGpgMEDownloadJob(); + + /*! \reimp from DownloadJob */ + GpgME::Error start( const QStringList & fingerprints ); + + private: + void doOperationDoneEvent( const GpgME::Error & e ); + + private slots: + void slotOperationDoneEvent( GpgME::Context * context, const GpgME::Error & e ) { + QGpgMEJob::doSlotOperationDoneEvent( context, e ); + } + }; + +} + +#endif // __KLEO_QGPGMEDOWNLOADJOB_H__ diff --git a/certmanager/lib/backends/qgpgme/qgpgmeencryptjob.cpp b/certmanager/lib/backends/qgpgme/qgpgmeencryptjob.cpp new file mode 100644 index 000000000..3f223fc56 --- /dev/null +++ b/certmanager/lib/backends/qgpgme/qgpgmeencryptjob.cpp @@ -0,0 +1,108 @@ +/* + qgpgmeencryptjob.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "qgpgmeencryptjob.h" + +#include "ui/messagebox.h" + +#include <qgpgme/eventloopinteractor.h> +#include <qgpgme/dataprovider.h> + +#include <gpgmepp/context.h> +#include <gpgmepp/encryptionresult.h> +#include <gpgmepp/data.h> + +#include <klocale.h> + +#include <assert.h> + +Kleo::QGpgMEEncryptJob::QGpgMEEncryptJob( GpgME::Context * context ) + : EncryptJob( QGpgME::EventLoopInteractor::instance(), "Kleo::QGpgMEEncryptJob" ), + QGpgMEJob( this, context ) +{ + assert( context ); +} + +Kleo::QGpgMEEncryptJob::~QGpgMEEncryptJob() { +} + +void Kleo::QGpgMEEncryptJob::setup( const QByteArray & plainText ) { + assert( !mInData ); + assert( !mOutData ); + + createInData( plainText ); + createOutData(); +} + +GpgME::Error Kleo::QGpgMEEncryptJob::start( const std::vector<GpgME::Key> & recipients, + const QByteArray & plainText, bool alwaysTrust ) { + setup( plainText ); + + hookupContextToEventLoopInteractor(); + + const GpgME::Context::EncryptionFlags flags = + alwaysTrust ? GpgME::Context::AlwaysTrust : GpgME::Context::None; + const GpgME::Error err = mCtx->startEncryption( recipients, *mInData, *mOutData, flags ); + + if ( err ) + deleteLater(); + mResult = GpgME::EncryptionResult( err ); + return err; +} + +GpgME::EncryptionResult Kleo::QGpgMEEncryptJob::exec( const std::vector<GpgME::Key> & recipients, + const QByteArray & plainText, + bool alwaysTrust, + QByteArray & ciphertext ) { + setup( plainText ); + const GpgME::Context::EncryptionFlags flags = + alwaysTrust ? GpgME::Context::AlwaysTrust : GpgME::Context::None; + mResult = mCtx->encrypt( recipients, *mInData, *mOutData, flags ); + ciphertext = mOutDataDataProvider->data(); + getAuditLog(); + return mResult; +} + +void Kleo::QGpgMEEncryptJob::doOperationDoneEvent( const GpgME::Error & ) { + emit result( mResult = mCtx->encryptionResult(), mOutDataDataProvider->data() ); +} + +void Kleo::QGpgMEEncryptJob::showErrorDialog( QWidget * parent, const QString & caption ) const { + if ( mResult.error() && !mResult.error().isCanceled() ) + Kleo::MessageBox::error( parent, mResult, this, caption ); +} + +#include "qgpgmeencryptjob.moc" diff --git a/certmanager/lib/backends/qgpgme/qgpgmeencryptjob.h b/certmanager/lib/backends/qgpgme/qgpgmeencryptjob.h new file mode 100644 index 000000000..362fb4e06 --- /dev/null +++ b/certmanager/lib/backends/qgpgme/qgpgmeencryptjob.h @@ -0,0 +1,86 @@ +/* + qgpgmeencryptjob.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_QGPGMEENCRYPTJOB_H__ +#define __KLEO_QGPGMEENCRYPTJOB_H__ + +#include <kleo/encryptjob.h> + +#include "qgpgmejob.h" + +#include <gpgmepp/encryptionresult.h> + +#include <qcstring.h> + +namespace GpgME { + class Error; + class Context; + class Key; +} + +namespace Kleo { + + class QGpgMEEncryptJob : public EncryptJob, private QGpgMEJob { + Q_OBJECT QGPGME_JOB + public: + QGpgMEEncryptJob( GpgME::Context * context ); + ~QGpgMEEncryptJob(); + + /*! \reimp from EncryptJob */ + GpgME::Error start( const std::vector<GpgME::Key> & recipients, + const QByteArray & plainText, bool alwaysTrust ); + + /*! \reimp from EncryptJob */ + GpgME::EncryptionResult exec( const std::vector<GpgME::Key> & recipients, + const QByteArray & plainText, bool alwaysTrust, + QByteArray & cipherText ); + + /*! \reimp from Job */ + void showErrorDialog( QWidget * parent, const QString & caption ) const; + + private slots: + void slotOperationDoneEvent( GpgME::Context * context, const GpgME::Error & e ) { + QGpgMEJob::doSlotOperationDoneEvent( context, e ); + } + + + private: + void doOperationDoneEvent( const GpgME::Error & e ); + void setup( const QByteArray & ); + + private: + GpgME::EncryptionResult mResult; + }; + +} + +#endif // __KLEO_QGPGMEENCRYPTJOB_H__ diff --git a/certmanager/lib/backends/qgpgme/qgpgmeexportjob.cpp b/certmanager/lib/backends/qgpgme/qgpgmeexportjob.cpp new file mode 100644 index 000000000..c9274f3b7 --- /dev/null +++ b/certmanager/lib/backends/qgpgme/qgpgmeexportjob.cpp @@ -0,0 +1,78 @@ +/* + qgpgmeexportjob.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "qgpgmeexportjob.h" + +#include <qgpgme/eventloopinteractor.h> +#include <qgpgme/dataprovider.h> + +#include <gpgmepp/context.h> +#include <gpgmepp/data.h> + +#include <qstringlist.h> + +#include <assert.h> + +Kleo::QGpgMEExportJob::QGpgMEExportJob( GpgME::Context * context ) + : ExportJob( QGpgME::EventLoopInteractor::instance(), "Kleo::QGpgMEExportJob" ), + QGpgMEJob( this, context ) +{ + assert( context ); +} + +Kleo::QGpgMEExportJob::~QGpgMEExportJob() { +} + +GpgME::Error Kleo::QGpgMEExportJob::start( const QStringList & pats ) { + assert( !patterns() ); + assert( !mOutData ); + + createOutData(); + setPatterns( pats ); + hookupContextToEventLoopInteractor(); + + const GpgME::Error err = mCtx->startPublicKeyExport( patterns(), *mOutData ); + + if ( err ) + deleteLater(); + return err; +} + +void Kleo::QGpgMEExportJob::doOperationDoneEvent( const GpgME::Error & error ) { + emit result( error, mOutDataDataProvider->data() ); +} + +#include "qgpgmeexportjob.moc" diff --git a/certmanager/lib/backends/qgpgme/qgpgmeexportjob.h b/certmanager/lib/backends/qgpgme/qgpgmeexportjob.h new file mode 100644 index 000000000..8b799b583 --- /dev/null +++ b/certmanager/lib/backends/qgpgme/qgpgmeexportjob.h @@ -0,0 +1,69 @@ +/* + qgpgmeexportjob.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_QGPGMEEXPORTJOB_H__ +#define __KLEO_QGPGMEEXPORTJOB_H__ + +#include <kleo/exportjob.h> + +#include "qgpgmejob.h" + +#include <qcstring.h> + +namespace GpgME { + class Error; + class Context; +} + +namespace Kleo { + + class QGpgMEExportJob : public ExportJob, private QGpgMEJob { + Q_OBJECT QGPGME_JOB + public: + QGpgMEExportJob( GpgME::Context * context ); + ~QGpgMEExportJob(); + + /*! \reimp from ExportJob */ + GpgME::Error start( const QStringList & patterns ); + + private slots: + void slotOperationDoneEvent( GpgME::Context * context, const GpgME::Error & e ) { + QGpgMEJob::doSlotOperationDoneEvent( context, e ); + } + + private: + void doOperationDoneEvent( const GpgME::Error & e ); + }; + +} + +#endif // __KLEO_QGPGMEEXPORTJOB_H__ diff --git a/certmanager/lib/backends/qgpgme/qgpgmeimportjob.cpp b/certmanager/lib/backends/qgpgme/qgpgmeimportjob.cpp new file mode 100644 index 000000000..fd1251b65 --- /dev/null +++ b/certmanager/lib/backends/qgpgme/qgpgmeimportjob.cpp @@ -0,0 +1,86 @@ +/* + qgpgmeimportjob.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "qgpgmeimportjob.h" + +#include <qgpgme/eventloopinteractor.h> +#include <qgpgme/dataprovider.h> + +#include <gpgmepp/context.h> +#include <gpgmepp/importresult.h> +#include <gpgmepp/data.h> + +#include <assert.h> + +Kleo::QGpgMEImportJob::QGpgMEImportJob( GpgME::Context * context ) + : ImportJob( QGpgME::EventLoopInteractor::instance(), "Kleo::QGpgMEImportJob" ), + QGpgMEJob( this, context ) +{ + assert( context ); +} + +Kleo::QGpgMEImportJob::~QGpgMEImportJob() { +} + +void Kleo::QGpgMEImportJob::setup( const QByteArray & keyData ) { + assert( !mInData ); + + createInData( keyData ); +} + +GpgME::Error Kleo::QGpgMEImportJob::start( const QByteArray & keyData ) { + setup( keyData ); + + hookupContextToEventLoopInteractor(); + + const GpgME::Error err = mCtx->startKeyImport( *mInData ); + + if ( err ) + deleteLater(); + return err; +} + +GpgME::ImportResult Kleo::QGpgMEImportJob::exec( const QByteArray & keyData ) { + setup( keyData ); + return mCtx->importKeys( *mInData ); +} + +void Kleo::QGpgMEImportJob::doOperationDoneEvent( const GpgME::Error & ) { + emit result( mCtx->importResult() ); +} + + +#include "qgpgmeimportjob.moc" diff --git a/certmanager/lib/backends/qgpgme/qgpgmeimportjob.h b/certmanager/lib/backends/qgpgme/qgpgmeimportjob.h new file mode 100644 index 000000000..8c2ee1ad4 --- /dev/null +++ b/certmanager/lib/backends/qgpgme/qgpgmeimportjob.h @@ -0,0 +1,73 @@ +/* + qgpgmeimportjob.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_QGPGMEIMPORTJOB_H__ +#define __KLEO_QGPGMEIMPORTJOB_H__ + +#include <kleo/importjob.h> + +#include "qgpgmejob.h" + +#include <qcstring.h> + +namespace GpgME { + class Error; + class Context; +} + +namespace Kleo { + + class QGpgMEImportJob : public ImportJob, private QGpgMEJob { + Q_OBJECT QGPGME_JOB + public: + QGpgMEImportJob( GpgME::Context * context ); + ~QGpgMEImportJob(); + + /*! \reimp from ImportJob */ + GpgME::Error start( const QByteArray & keyData ); + + /*! \reimp from ImportJob */ + GpgME::ImportResult exec( const QByteArray & keyData ); + + private slots: + void slotOperationDoneEvent( GpgME::Context * context, const GpgME::Error & e ) { + QGpgMEJob::doSlotOperationDoneEvent( context, e ); + } + + private: + void doOperationDoneEvent( const GpgME::Error & e ); + void setup( const QByteArray & ); + }; + +} + +#endif // __KLEO_QGPGMEIMPORTJOB_H__ diff --git a/certmanager/lib/backends/qgpgme/qgpgmejob.cpp b/certmanager/lib/backends/qgpgme/qgpgmejob.cpp new file mode 100644 index 000000000..897e5ff7c --- /dev/null +++ b/certmanager/lib/backends/qgpgme/qgpgmejob.cpp @@ -0,0 +1,304 @@ +/* + qgpgmejob.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "qgpgmejob.h" +#include "qgpgmeprogresstokenmapper.h" + +#include <kleo/job.h> +#include <ui/passphrasedialog.h> + +#include <qgpgme/eventloopinteractor.h> +#include <qgpgme/dataprovider.h> + +#include <gpgmepp/context.h> +#include <gpgmepp/data.h> + +#include <klocale.h> +#include <kstandarddirs.h> + +#include <qstring.h> +#include <qstringlist.h> + +#include <algorithm> + +#include <assert.h> +#include <string.h> + +namespace { + class InvarianceChecker { + public: +#ifdef NDEBUG + InvarianceChecker( const Kleo::QGpgMEJob * ) {} +#else + InvarianceChecker( const Kleo::QGpgMEJob * job ) + : _this( job ) + { + assert( _this ); + _this->checkInvariants(); + } + ~InvarianceChecker() { + _this->checkInvariants(); + } + private: + const Kleo::QGpgMEJob * _this; +#endif + }; +} + +Kleo::QGpgMEJob::QGpgMEJob( Kleo::Job * _this, GpgME::Context * context ) + : GpgME::ProgressProvider(), + GpgME::PassphraseProvider(), + mThis( _this ), + mCtx( context ), + mInData( 0 ), + mInDataDataProvider( 0 ), + mOutData( 0 ), + mOutDataDataProvider( 0 ), + mPatterns( 0 ), + mReplacedPattern( 0 ), + mNumPatterns( 0 ), + mChunkSize( 1024 ), + mPatternStartIndex( 0 ), mPatternEndIndex( 0 ) +{ + InvarianceChecker check( this ); + assert( context ); + QObject::connect( QGpgME::EventLoopInteractor::instance(), SIGNAL(aboutToDestroy()), + _this, SLOT(slotCancel()) ); + context->setProgressProvider( this ); + // (mmutz) work around a gpgme bug in versions at least <= 0.9.0. + // These versions will return GPG_ERR_NOT_IMPLEMENTED from + // a CMS sign operation when a passphrase callback is set. + if ( context->protocol() == GpgME::Context::OpenPGP ) + context->setPassphraseProvider( this ); +} + +void Kleo::QGpgMEJob::checkInvariants() const { +#ifndef NDEBUG + if ( mPatterns ) { + assert( mPatterns[mNumPatterns] == 0 ); + if ( mPatternEndIndex > 0 ) { + assert( mPatternEndIndex > mPatternStartIndex ); + assert( mPatternEndIndex - mPatternStartIndex == mChunkSize ); + } else { + assert( mPatternEndIndex == mPatternStartIndex ); + } + if ( mPatternEndIndex < mNumPatterns ) { + assert( mPatterns[mPatternEndIndex] == 0 ); + assert( mReplacedPattern != 0 ); + } else { + assert( mReplacedPattern == 0 ); + } + } else { + assert( mNumPatterns == 0 ); + assert( mPatternStartIndex == 0 ); + assert( mPatternEndIndex == 0 ); + assert( mReplacedPattern == 0 ); + } +#endif +} + +Kleo::QGpgMEJob::~QGpgMEJob() { + InvarianceChecker check( this ); + delete mCtx; mCtx = 0; + delete mInData; mInData = 0; + delete mInDataDataProvider; mInDataDataProvider = 0; + delete mOutData; mOutData = 0; + delete mOutDataDataProvider; mOutDataDataProvider = 0; + deleteAllPatterns(); +} + +void Kleo::QGpgMEJob::deleteAllPatterns() { + if ( mPatterns ) + for ( unsigned int i = 0 ; i < mNumPatterns ; ++i ) + free( (void*)mPatterns[i] ); + free( (void*)mReplacedPattern ); mReplacedPattern = 0; + delete[] mPatterns; mPatterns = 0; + mPatternEndIndex = mPatternStartIndex = mNumPatterns = 0; +} + +void Kleo::QGpgMEJob::hookupContextToEventLoopInteractor() { + mCtx->setManagedByEventLoopInteractor( true ); + QObject::connect( QGpgME::EventLoopInteractor::instance(), + SIGNAL(operationDoneEventSignal(GpgME::Context*,const GpgME::Error&)), + mThis, SLOT(slotOperationDoneEvent(GpgME::Context*,const GpgME::Error&)) ); +} + +void Kleo::QGpgMEJob::setPatterns( const QStringList & sl, bool allowEmpty ) { + InvarianceChecker check( this ); + deleteAllPatterns(); + // create a new null-terminated C array of char* from patterns: + mPatterns = new const char*[ sl.size() + 1 ]; + const char* * pat_it = mPatterns; + mNumPatterns = 0; + for ( QStringList::const_iterator it = sl.begin() ; it != sl.end() ; ++it ) { + if ( (*it).isNull() ) + continue; + if ( (*it).isEmpty() && !allowEmpty ) + continue; + *pat_it++ = strdup( (*it).utf8().data() ); + ++mNumPatterns; + } + *pat_it++ = 0; + mReplacedPattern = 0; + mPatternEndIndex = mChunkSize = mNumPatterns; +} + +void Kleo::QGpgMEJob::setChunkSize( unsigned int chunksize ) { + InvarianceChecker check( this ); + if ( mReplacedPattern ) { + mPatterns[mPatternEndIndex] = mReplacedPattern; + mReplacedPattern = 0; + } + mChunkSize = std::min( chunksize, mNumPatterns ); + mPatternStartIndex = 0; + mPatternEndIndex = mChunkSize; + mReplacedPattern = mPatterns[mPatternEndIndex]; + mPatterns[mPatternEndIndex] = 0; +} + +const char* * Kleo::QGpgMEJob::nextChunk() { + InvarianceChecker check( this ); + if ( mReplacedPattern ) { + mPatterns[mPatternEndIndex] = mReplacedPattern; + mReplacedPattern = 0; + } + mPatternStartIndex += mChunkSize; + mPatternEndIndex += mChunkSize; + if ( mPatternEndIndex < mNumPatterns ) { // could safely be <=, but the last entry is NULL anyway + mReplacedPattern = mPatterns[mPatternEndIndex]; + mPatterns[mPatternEndIndex] = 0; + } + return patterns(); +} + +const char* * Kleo::QGpgMEJob::patterns() const { + InvarianceChecker check( this ); + if ( mPatternStartIndex < mNumPatterns ) + return mPatterns + mPatternStartIndex; + return 0; +} + +GpgME::Error Kleo::QGpgMEJob::setSigningKeys( const std::vector<GpgME::Key> & signers ) { + mCtx->clearSigningKeys(); + for ( std::vector<GpgME::Key>::const_iterator it = signers.begin() ; it != signers.end() ; ++it ) { + if ( (*it).isNull() ) + continue; + if ( const GpgME::Error err = mCtx->addSigningKey( *it ) ) + return err; + } + return 0; +} + +void Kleo::QGpgMEJob::createInData( const QByteArray & in ) { + mInDataDataProvider = new QGpgME::QByteArrayDataProvider( in ); + mInData = new GpgME::Data( mInDataDataProvider ); + assert( !mInData->isNull() ); +} + +void Kleo::QGpgMEJob::createOutData() { + mOutDataDataProvider = new QGpgME::QByteArrayDataProvider(); + mOutData = new GpgME::Data( mOutDataDataProvider ); + assert( !mOutData->isNull() ); +} + +static const unsigned int GetAuditLogFlags = GpgME::Context::AuditLogWithHelp|GpgME::Context::HtmlAuditLog; + +static QString audit_log_as_html( GpgME::Context * ctx ) { + if ( !ctx ) + return QString(); + QGpgME::QByteArrayDataProvider dp; + GpgME::Data data( &dp ); + assert( !data.isNull() ); + if ( const GpgME::Error err = ctx->getAuditLog( data, GetAuditLogFlags ) ) + return QString(); + else + return QString::fromUtf8( dp.data().data() ); +} + +void Kleo::QGpgMEJob::doSlotOperationDoneEvent( GpgME::Context * context, const GpgME::Error & e ) { + if ( context == mCtx ) { + getAuditLog(); + doEmitDoneSignal(); + doOperationDoneEvent( e ); + mThis->deleteLater(); + } +} + +void Kleo::QGpgMEJob::getAuditLog() { + mAuditLogAsHtml = audit_log_as_html( mCtx ); +} + +void Kleo::QGpgMEJob::doSlotCancel() { + mCtx->cancelPendingOperation(); +} + +void Kleo::QGpgMEJob::showProgress( const char * what, int type, int current, int total ) { + doEmitProgressSignal( QGpgMEProgressTokenMapper::instance()->map( what, type, current, total ), current, total ); +} + +char * Kleo::QGpgMEJob::getPassphrase( const char * useridHint, const char * /*description*/, + bool previousWasBad, bool & canceled ) { + // DF: here, description is the key fingerprint, twice, then "17 0". Not really descriptive. + // So I'm ignoring QString::fromLocal8Bit( description ) ) + QString msg = previousWasBad ? + i18n( "You need a passphrase to unlock the secret key for user:<br/> %1 (retry)" ) : + i18n( "You need a passphrase to unlock the secret key for user:<br/> %1" ); + msg = msg.arg( QString::fromUtf8( useridHint ) ) + "<br/><br/>"; + msg.prepend( "<qt>" ); + msg += i18n( "This dialog will reappear every time the passphrase is needed. For a more secure solution that also allows caching the passphrase, use gpg-agent." ) + "<br/>"; + const QString gpgAgent = KStandardDirs::findExe( "gpg-agent" ); + if ( !gpgAgent.isEmpty() ) { + msg += i18n( "gpg-agent was found in %1, but does not appear to be running." ) + .arg( gpgAgent ); + } else { + msg += i18n( "gpg-agent is part of gnupg-%1, which you can download from %2" ) + .arg( "1.9" ) + .arg( "http://www.gnupg.org/download" ); // add #gnupg2 if you can make this a real link + } + msg += "<br/>"; + msg += i18n( "For information on how to set up gpg-agent, see %1" ) + .arg( "http://kmail.kde.org/kmail-pgpmime-howto.html" ); + msg += "<br/><br/>"; + msg += i18n( "Enter passphrase:" ); + Kleo::PassphraseDialog dlg( msg, i18n("Passphrase Dialog") ); + if ( dlg.exec() != QDialog::Accepted ) { + canceled = true; + return 0; + } + canceled = false; + // gpgme++ free()s it, and we need to copy as long as dlg isn't deleted :o + return strdup( dlg.passphrase() ); +} diff --git a/certmanager/lib/backends/qgpgme/qgpgmejob.h b/certmanager/lib/backends/qgpgme/qgpgmejob.h new file mode 100644 index 000000000..da7acf1c9 --- /dev/null +++ b/certmanager/lib/backends/qgpgme/qgpgmejob.h @@ -0,0 +1,160 @@ +/* + qgpgmejob.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_QGPGMEJOB_H__ +#define __KLEO_QGPGMEJOB_H__ + +#include <gpgmepp/interfaces/progressprovider.h> +#include <gpgmepp/interfaces/passphraseprovider.h> + +#include <gpgmepp/key.h> + +#include <qcstring.h> +#include <qstring.h> + +#include <vector> +#include <kdepimmacros.h> + +namespace GpgME { + class Error; + class Context; + class Data; +} + +namespace Kleo { + class Job; +} + +namespace QGpgME { + class QByteArrayDataProvider; +} + +class QString; +class QStringList; + +namespace Kleo { + + /** This is a hackish helper class to avoid code duplication in this + backend's Kleo::Job subclasses. It contains several workarounds + for moc/signal/slot shortcomings, most of which the author of + this thinks are Qt bugs (lazy implementations), first and + foremost the inability of moc to handle inheritance from + multiple QObject-derived subclasses. + + To use it, inherit from the Job-subclass, then from this class, + add QGPGME_JOB to just after Q OBJECT and implement + doOperationDoneEvent() by emitting your variant of the result() + signal there. Pass "this" as the first argument this QGpgMEJOb's + ctor. The rest is dealt with automatically. + */ + class KDE_EXPORT QGpgMEJob : public GpgME::ProgressProvider, public GpgME::PassphraseProvider { + public: + QGpgMEJob( Kleo::Job * _this, GpgME::Context * context ); + ~QGpgMEJob(); + + protected: + /*! Called on operation-done events, between emitting done() and + calling deleteLater(). You should emit your result signal here. */ + virtual void doOperationDoneEvent( const GpgME::Error & e ) = 0; + /*! Hooks up mCtx to be managed by the event loop interactor */ + void hookupContextToEventLoopInteractor(); + /*! Fills mPatterns from the stringlist, resets chunking to the full list */ + void setPatterns( const QStringList & sl, bool allowEmpty=false ); + /*! Returnes the number of patterns set */ + unsigned int numPatterns() const { return mNumPatterns; } + /*! Skips to the next chunk of patterns. @return patterns() */ + const char* * nextChunk(); + /*! @return patterns, offset by the current chunk */ + const char* * patterns() const; + /*! Set the current pattern chunksize to size and reset the chunk index to zero */ + void setChunkSize( unsigned int size ); + /*! @return current chunksize */ + unsigned int chunkSize() const { return mChunkSize; } + /*! Creates an empty GpgME::Data/QGpgME::QByteArrayDataProvider pair */ + void createOutData(); + /*! Creates a GpgME::Data/QGpgME::QByteArrayDataProvider pair, + filled with the contents of \a in */ + void createInData( const QByteArray & in ); + /*! Sets the list of signing keys */ + GpgME::Error setSigningKeys( const std::vector<GpgME::Key> & signers ); + /*! Call this to implement a slotOperationDoneEvent() */ + void doSlotOperationDoneEvent( GpgME::Context * context, const GpgME::Error & e ); + /*! Call this to extract the audit log from mCtx */ + void getAuditLog(); + + // + // only boring stuff below this line... + // + + protected: + virtual void doEmitProgressSignal( const QString & what, int current, int total ) = 0; + virtual void doEmitDoneSignal() = 0; + void doSlotCancel(); + QString auditLogAsHtml() const { return mAuditLogAsHtml; } + + private: + /*! \reimp from GpgME::ProgressProvider */ + void showProgress( const char * what, int type, int current, int total ); + char * getPassphrase( const char * useridHint, const char * description, + bool previousWasBad, bool & canceled ); + void deleteAllPatterns(); + + public: + void checkInvariants() const; + + protected: + Kleo::Job * mThis; + GpgME::Context * mCtx; + GpgME::Data * mInData; + QGpgME::QByteArrayDataProvider * mInDataDataProvider; + GpgME::Data * mOutData; + QGpgME::QByteArrayDataProvider * mOutDataDataProvider; + private: + const char* * mPatterns; + // holds the entry - if any - in mPattern that was replaced with + // NULL to create a temporary end-of-array marker for gpgme: + const char * mReplacedPattern; + unsigned int mNumPatterns; + unsigned int mChunkSize; + unsigned int mPatternStartIndex, mPatternEndIndex; + QString mAuditLogAsHtml; + }; + +} + +#define make_slot_cancel private: void slotCancel() { QGpgMEJob::doSlotCancel(); } +#define make_progress_emitter private: void doEmitProgressSignal( const QString & what, int cur, int tot ) { emit progress( what, cur, tot ); } +#define make_done_emitter private: void doEmitDoneSignal() { emit done(); } +#define make_auditLogAsHtml private: QString auditLogAsHtml() const { return QGpgMEJob::auditLogAsHtml(); } +#define QGPGME_JOB make_slot_cancel make_progress_emitter make_done_emitter make_auditLogAsHtml + +#endif // __KLEO_QGPGMEJOB_H__ diff --git a/certmanager/lib/backends/qgpgme/qgpgmekeygenerationjob.cpp b/certmanager/lib/backends/qgpgme/qgpgmekeygenerationjob.cpp new file mode 100644 index 000000000..a0ab78f23 --- /dev/null +++ b/certmanager/lib/backends/qgpgme/qgpgmekeygenerationjob.cpp @@ -0,0 +1,86 @@ +/* + qgpgmekeygenerationjob.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "qgpgmekeygenerationjob.h" + +#include <qgpgme/dataprovider.h> +#include <qgpgme/eventloopinteractor.h> + +#include <gpgmepp/context.h> +#include <gpgmepp/keygenerationresult.h> +#include <gpgmepp/data.h> + +#include <assert.h> + +Kleo::QGpgMEKeyGenerationJob::QGpgMEKeyGenerationJob( GpgME::Context * context ) + : KeyGenerationJob( QGpgME::EventLoopInteractor::instance(), "Kleo::QGpgMEKeyGenerationJob" ), + QGpgMEJob( this, context ), + mPubKeyDataProvider( 0 ), + mPubKey( 0 ) +{ + assert( context ); +} + +Kleo::QGpgMEKeyGenerationJob::~QGpgMEKeyGenerationJob() { + delete mPubKey; mPubKey = 0; + delete mPubKeyDataProvider; mPubKeyDataProvider = 0; +} + +GpgME::Error Kleo::QGpgMEKeyGenerationJob::start( const QString & parameters ) { + assert( !mPubKey ); + + // set up empty data object for the public key data + if ( mCtx->protocol() == GpgME::Context::CMS ) { + mPubKeyDataProvider = new QGpgME::QByteArrayDataProvider(); + mPubKey = new GpgME::Data( mPubKeyDataProvider ); + assert( !mPubKey->isNull() ); + } + + hookupContextToEventLoopInteractor(); + + const GpgME::Error err = + mCtx->startKeyGeneration( parameters.utf8().data(), mPubKey ? *mPubKey : GpgME::Data::null ); + + if ( err ) + deleteLater(); + return err; +} + +void Kleo::QGpgMEKeyGenerationJob::doOperationDoneEvent( const GpgME::Error & ) { + emit result( mCtx->keyGenerationResult(), mPubKeyDataProvider ? mPubKeyDataProvider->data() : QByteArray() ); +} + +#include "qgpgmekeygenerationjob.moc" diff --git a/certmanager/lib/backends/qgpgme/qgpgmekeygenerationjob.h b/certmanager/lib/backends/qgpgme/qgpgmekeygenerationjob.h new file mode 100644 index 000000000..973aeb12d --- /dev/null +++ b/certmanager/lib/backends/qgpgme/qgpgmekeygenerationjob.h @@ -0,0 +1,78 @@ +/* + qgpgmekeygenerationjob.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_QGPGMEKEYGENERATIONJOB_H__ +#define __KLEO_QGPGMEKEYGENERATIONJOB_H__ + +#include <kleo/keygenerationjob.h> + +#include "qgpgmejob.h" +#include <kdepimmacros.h> + +namespace GpgME { + class Error; + class Context; + class Key; + class Data; +} + +namespace QGpgME { + class QByteArrayDataProvider; +} + +namespace Kleo { + + class KDE_EXPORT QGpgMEKeyGenerationJob : public KeyGenerationJob, private QGpgMEJob { + Q_OBJECT QGPGME_JOB + public: + QGpgMEKeyGenerationJob( GpgME::Context * context ); + ~QGpgMEKeyGenerationJob(); + + /*! \reimp from KeygenerationJob */ + GpgME::Error start( const QString & parameters ); + + private slots: + void slotOperationDoneEvent( GpgME::Context * context, const GpgME::Error & error ) { + QGpgMEJob::doSlotOperationDoneEvent( context, error ); + } + + private: + void doOperationDoneEvent( const GpgME::Error & e ); + + private: + QGpgME::QByteArrayDataProvider * mPubKeyDataProvider; + GpgME::Data * mPubKey; + }; + +} + +#endif // __KLEO_QGPGMEKEYGENERATIONJOB_H__ diff --git a/certmanager/lib/backends/qgpgme/qgpgmekeylistjob.cpp b/certmanager/lib/backends/qgpgme/qgpgmekeylistjob.cpp new file mode 100644 index 000000000..9c87e3ef6 --- /dev/null +++ b/certmanager/lib/backends/qgpgme/qgpgmekeylistjob.cpp @@ -0,0 +1,187 @@ +/* + qgpgmekeylistjob.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "qgpgmekeylistjob.h" + +#include <qgpgme/eventloopinteractor.h> + +#include <gpgmepp/key.h> +#include <gpgmepp/context.h> +#include <gpgmepp/keylistresult.h> +#include <gpg-error.h> + +#include <kmessagebox.h> +#include <klocale.h> +#include <kdebug.h> + +#include <qstringlist.h> + +#include <algorithm> + +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +Kleo::QGpgMEKeyListJob::QGpgMEKeyListJob( GpgME::Context * context ) + : KeyListJob( QGpgME::EventLoopInteractor::instance(), "Kleo::QGpgMEKeyListJob" ), + QGpgMEJob( this, context ), + mResult(), mSecretOnly( false ) +{ + assert( context ); +} + +Kleo::QGpgMEKeyListJob::~QGpgMEKeyListJob() { +} + +void Kleo::QGpgMEKeyListJob::setup( const QStringList & pats, bool secretOnly ) { + assert( !patterns() ); + + mSecretOnly = secretOnly; + setPatterns( pats ); +} + +GpgME::Error Kleo::QGpgMEKeyListJob::start( const QStringList & pats, bool secretOnly ) { + setup( pats, secretOnly ); + + hookupContextToEventLoopInteractor(); + connect( QGpgME::EventLoopInteractor::instance(), + SIGNAL(nextKeyEventSignal(GpgME::Context*,const GpgME::Key&)), + SLOT(slotNextKeyEvent(GpgME::Context*,const GpgME::Key&)) ); + + // The communication channel between gpgme and gpgsm is limited in + // the number of patterns that can be transported, but they won't + // say to how much, so we need to find out ourselves if we get a + // LINE_TOO_LONG error back... + + // We could of course just feed them single patterns, and that would + // probably be easier, but the performance penalty would currently + // be noticable. + + while ( const GpgME::Error err = mCtx->startKeyListing( patterns(), mSecretOnly ) ) { + if ( err.code() == GPG_ERR_LINE_TOO_LONG ) { + setChunkSize( chunkSize()/2 ); + if ( chunkSize() >= 1 ) { + kdDebug(5150) << "QGpgMEKeyListJob::start(): retrying keylisting with chunksize " << chunkSize() << endl; + continue; + } + } + deleteLater(); + mResult = GpgME::KeyListResult( 0, err ); + return err; + } + mResult = GpgME::KeyListResult( 0, 0 ); + return 0; +} + +GpgME::KeyListResult Kleo::QGpgMEKeyListJob::exec( const QStringList & pats, bool secretOnly, std::vector<GpgME::Key> & keys ) { + setup( pats, secretOnly ); + + // The communication channel between gpgme and gpgsm is limited in + // the number of patterns that can be transported, but they won't + // say to how much, so we need to find out ourselves if we get a + // LINE_TOO_LONG error back... + + // We could of course just feed them single patterns, and that would + // probably be easier, but the performance penalty would currently + // be noticable. + + for (;;) { + keys.clear(); + mResult = attemptSyncKeyListing( keys ); + if ( !mResult.error() || mResult.error().code() != GPG_ERR_LINE_TOO_LONG ) + return mResult; + // got LINE_TOO_LONG, try a smaller chunksize: + setChunkSize( chunkSize()/2 ); + if ( chunkSize() < 1 ) + // chunks smaller than one can't be -> return the error. + return mResult; + kdDebug(5150) << "QGpgMEKeyListJob::exec(): retrying keylisting with chunksize " << chunkSize() << endl; + } + kdFatal(5150) << "QGpgMEKeyListJob::exec(): Oops, this is not supposed to happen!" << endl; + return GpgME::KeyListResult(); +} + +GpgME::KeyListResult Kleo::QGpgMEKeyListJob::attemptSyncKeyListing( std::vector<GpgME::Key> & keys ) { + GpgME::KeyListResult result; + for ( const char* * chunk = patterns() ; chunk ; chunk = nextChunk() ) { + + if ( const GpgME::Error err = mCtx->startKeyListing( chunk, mSecretOnly ) ) + return GpgME::KeyListResult( 0, err ); + + GpgME::Error err; + do + keys.push_back( mCtx->nextKey( err ) ); + while ( !err ); + keys.pop_back(); + result.mergeWith( mCtx->endKeyListing() ); + if ( result.error() ) + break; + } + return result; +} + +void Kleo::QGpgMEKeyListJob::slotNextKeyEvent( GpgME::Context * context, const GpgME::Key & key ) { + if ( context == mCtx ) + emit nextKey( key ); +} + +void Kleo::QGpgMEKeyListJob::slotOperationDoneEvent( GpgME::Context * context, const GpgME::Error & ) { + if ( context != mCtx ) + return; + mResult.mergeWith( mCtx->keyListResult() ); + if ( !mResult.error() ) + if ( const char* * chunk = nextChunk() ) { + if ( const GpgME::Error err = mCtx->startKeyListing( chunk, mSecretOnly ) ) + mResult.mergeWith( GpgME::KeyListResult( 0, err ) ); + else + return; + } + emit done(); + emit result( mResult ); + deleteLater(); +} + +void Kleo::QGpgMEKeyListJob::showErrorDialog( QWidget * parent, const QString & caption ) const { + if ( !mResult.error() || mResult.error().isCanceled() ) + return; + const QString msg = i18n( "<qt><p>An error occurred while fetching " + "the keys from the backend:</p>" + "<p><b>%1</b></p></qt>" ) + .arg( QString::fromLocal8Bit( mResult.error().asString() ) ); + KMessageBox::error( parent, msg, caption ); +} + +#include "qgpgmekeylistjob.moc" diff --git a/certmanager/lib/backends/qgpgme/qgpgmekeylistjob.h b/certmanager/lib/backends/qgpgme/qgpgmekeylistjob.h new file mode 100644 index 000000000..8320e0134 --- /dev/null +++ b/certmanager/lib/backends/qgpgme/qgpgmekeylistjob.h @@ -0,0 +1,81 @@ +/* + qgpgmekeylistjob.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_QGPGMEKEYLISTJOB_H__ +#define __KLEO_QGPGMEKEYLISTJOB_H__ + +#include <kleo/keylistjob.h> + +#include <gpgmepp/keylistresult.h> + +#include "qgpgmejob.h" + +namespace GpgME { + class Error; + class Context; + class Key; +} + +namespace Kleo { + + class QGpgMEKeyListJob : public KeyListJob, private QGpgMEJob { + Q_OBJECT QGPGME_JOB + public: + QGpgMEKeyListJob( GpgME::Context * context ); + ~QGpgMEKeyListJob(); + + /*! \reimp from KeyListJob */ + GpgME::Error start( const QStringList & patterns, bool secretOnly ); + + /*! \reimp from KeyListJob */ + GpgME::KeyListResult exec( const QStringList & patterns, bool secretOnly, std::vector<GpgME::Key> & keys ); + + /*! \reimp from Job */ + void showErrorDialog( QWidget * parent, const QString & caption ) const; + + private slots: + void slotNextKeyEvent( GpgME::Context * context, const GpgME::Key & key ); + void slotOperationDoneEvent( GpgME::Context * context, const GpgME::Error & e ); + + private: + void doOperationDoneEvent( const GpgME::Error &) {} // unused, we implement slotOperationDoneEvent ourselves. + void setup( const QStringList &, bool ); + GpgME::KeyListResult attemptSyncKeyListing( std::vector<GpgME::Key> & ); + + private: + GpgME::KeyListResult mResult; + bool mSecretOnly; + }; + +} + +#endif // __KLEO_QGPGMEKEYLISTJOB_H__ diff --git a/certmanager/lib/backends/qgpgme/qgpgmeprogresstokenmapper.cpp b/certmanager/lib/backends/qgpgme/qgpgmeprogresstokenmapper.cpp new file mode 100644 index 000000000..3b6ae35eb --- /dev/null +++ b/certmanager/lib/backends/qgpgme/qgpgmeprogresstokenmapper.cpp @@ -0,0 +1,159 @@ +/* -*- mode: C++; c-file-style: "gnu" -*- + qgpgmeprogresstokenmapper.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "qgpgmeprogresstokenmapper.h" + +#include <klocale.h> + +#include <qstring.h> + +#include <assert.h> +#include <map> + +struct Desc { + int type; // 0 == fallback + const char * display; // add %1 for useCur ^ useTot and %1 %2 for useCur == useTot == true + bool useCur : 1; + bool useTot : 1; +}; + +static const struct Desc pk_dsa[] = { + { 0, I18N_NOOP("Generating DSA key..."), false, false } +}; + +static const struct Desc pk_elg[] = { + { 0, I18N_NOOP("Generating ElGamal key..."), false, false } +}; + +static const struct Desc primegen[] = { + // FIXME: add all type's? + { 0, I18N_NOOP("Searching for a large prime number..."), false, false } +}; + +static const struct Desc need_entropy[] = { + { 0, I18N_NOOP("Waiting for new entropy from random number generator (you might want to exercise the harddisks or move the mouse)..."), false, false } +}; + +static const struct Desc tick[] = { + { 0, I18N_NOOP("Please wait..."), false, false } +}; + +static const struct Desc starting_agent[] = { + { 0, I18N_NOOP("Starting gpg-agent (you should consider starting a global instance instead)..."), false, false } +}; + +static const struct { + const char * token; + const Desc * desc; + unsigned int numDesc; +} tokens[] = { +#define make_token(x) { #x, x, sizeof(x) / sizeof(*x) } + make_token(pk_dsa), + make_token(pk_elg), + make_token(primegen), + make_token(need_entropy), + make_token(tick), + make_token(starting_agent) +#undef make_token +}; + + + +Kleo::QGpgMEProgressTokenMapper * Kleo::QGpgMEProgressTokenMapper::mSelf = 0; + +const Kleo::QGpgMEProgressTokenMapper * Kleo::QGpgMEProgressTokenMapper::instance() { + if ( !mSelf ) + (void) new QGpgMEProgressTokenMapper(); + return mSelf; +} + +Kleo::QGpgMEProgressTokenMapper::QGpgMEProgressTokenMapper() { + mSelf = this; +} + +Kleo::QGpgMEProgressTokenMapper::~QGpgMEProgressTokenMapper() { + mSelf = 0; +} + +typedef std::map< QString, std::map<int,Desc> > Map; + +static const Map & makeMap() { // return a reference to a static to avoid copying + static Map map; + for ( unsigned int i = 0 ; i < sizeof tokens / sizeof *tokens ; ++i ) { + assert( tokens[i].token ); + const QString token = QString::fromLatin1( tokens[i].token ).lower(); + for ( unsigned int j = 0 ; j < tokens[i].numDesc ; ++j ) { + const Desc & desc = tokens[i].desc[j]; + assert( desc.display ); + map[ token ][ desc.type ] = desc; + } + } + return map; +} + +QString Kleo::QGpgMEProgressTokenMapper::map( const char * tokenUtf8, int subtoken, int cur, int tot ) const { + if ( !tokenUtf8 || !*tokenUtf8 ) + return QString::null; + + if ( qstrcmp( tokenUtf8, "file:" ) == 0 ) + return QString::null; // gpgme's job + + return map( QString::fromUtf8( tokenUtf8 ), subtoken, cur, tot ); +} + +QString Kleo::QGpgMEProgressTokenMapper::map( const QString & token, int subtoken, int cur, int tot ) const { + if ( token.startsWith( "file:" ) ) + return QString::null; // gpgme's job + + static const Map & tokenMap = makeMap(); + + const Map::const_iterator it1 = tokenMap.find( token.lower() ); + if ( it1 == tokenMap.end() ) + return token; + std::map<int,Desc>::const_iterator it2 = it1->second.find( subtoken ); + if ( it2 == it1->second.end() ) + it2 = it1->second.find( 0 ); + if ( it2 == it1->second.end() ) + return token; + const Desc & desc = it2->second; + QString result = i18n( desc.display ); + if ( desc.useCur ) + result = result.arg( cur ); + if ( desc.useTot ) + result = result.arg( tot ); + return result; +} + diff --git a/certmanager/lib/backends/qgpgme/qgpgmeprogresstokenmapper.h b/certmanager/lib/backends/qgpgme/qgpgmeprogresstokenmapper.h new file mode 100644 index 000000000..d0a8da6c3 --- /dev/null +++ b/certmanager/lib/backends/qgpgme/qgpgmeprogresstokenmapper.h @@ -0,0 +1,58 @@ +/* + qgpgmeprogresstokenmapper.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + + +#ifndef __KLEO_QGPGMEPROGRESSTOKENMAPPER_H__ +#define __KLEO_QGPGMEPROGRESSTOKENMAPPER_H__ + + +class QString; + +namespace Kleo { + + class QGpgMEProgressTokenMapper { + QGpgMEProgressTokenMapper(); + ~QGpgMEProgressTokenMapper(); + public: + static const QGpgMEProgressTokenMapper * instance(); + + QString map( const char * token, int subtoken, int current, int total ) const; + QString map( const QString & token, int subtoken, int current, int total ) const; + + private: + static QGpgMEProgressTokenMapper * mSelf; + }; + +} + + +#endif // __KLEO_QGPGMEPROGRESSTOKENMAPPER_H__ diff --git a/certmanager/lib/backends/qgpgme/qgpgmerefreshkeysjob.cpp b/certmanager/lib/backends/qgpgme/qgpgmerefreshkeysjob.cpp new file mode 100644 index 000000000..325306e8c --- /dev/null +++ b/certmanager/lib/backends/qgpgme/qgpgmerefreshkeysjob.cpp @@ -0,0 +1,207 @@ +/* + qgpgmerefreshkeysjob.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "qgpgmerefreshkeysjob.h" + +#include "gnupgprocessbase.h" +#include "qgpgmeprogresstokenmapper.h" + +#include <kdebug.h> + +#include <gpgmepp/context.h> + +#include <qgpgme/eventloopinteractor.h> + +#include <qstringlist.h> + +#include <gpg-error.h> + +#include <assert.h> + +Kleo::QGpgMERefreshKeysJob::QGpgMERefreshKeysJob() + : RefreshKeysJob( QGpgME::EventLoopInteractor::instance(), "Kleo::QGpgMERefreshKeysJob" ), + mProcess( 0 ), + mError( 0 ) +{ + +} + +Kleo::QGpgMERefreshKeysJob::~QGpgMERefreshKeysJob() { + +} + +GpgME::Error Kleo::QGpgMERefreshKeysJob::start( const QStringList & patterns ) { + assert( mPatternsToDo.empty() ); + + mPatternsToDo = patterns; + if ( mPatternsToDo.empty() ) + mPatternsToDo.push_back( " " ); // empty list means all -> mae + // sure to fail the first + // startAProcess() guard clause + + return startAProcess(); +} + +#if MAX_CMD_LENGTH < 65 + 128 +#error MAX_CMD_LENGTH is too low +#endif + +GpgME::Error Kleo::QGpgMERefreshKeysJob::startAProcess() { + if ( mPatternsToDo.empty() ) + return 0; + // create and start gpgsm process: + mProcess = new GnuPGProcessBase( this, "gpgsm -k --with-validation --force-crl-refresh --enable-crl-checks" ); + + // FIXME: obbtain the path to gpgsm from gpgme, so we use the same instance. + *mProcess << "gpgsm" << "-k" << "--with-validation" << "--force-crl-refresh" + << "--enable-crl-checks"; + unsigned int commandLineLength = MAX_CMD_LENGTH; + commandLineLength -= + strlen("gpgsm") + 1 + strlen("-k") + 1 + + strlen("--with-validation") + 1 + strlen("--force-crl-refresh") + 1 + + strlen("--enable-crl-checks") + 1; + while ( !mPatternsToDo.empty() ) { + const QCString pat = mPatternsToDo.front().utf8().stripWhiteSpace(); + const unsigned int patLength = pat.length(); + if ( patLength >= commandLineLength ) + break; + mPatternsToDo.pop_front(); + if ( pat.isEmpty() ) + continue; + *mProcess << pat; + commandLineLength -= patLength + 1; + } + + mProcess->setUseStatusFD( true ); + + connect( mProcess, SIGNAL(processExited(KProcess*)), + SLOT(slotProcessExited(KProcess*)) ); + connect( mProcess, SIGNAL(receivedStderr(KProcess*,char*,int)), + SLOT(slotStderr(KProcess*,char*,int)) ); + connect( mProcess, SIGNAL(status(Kleo::GnuPGProcessBase*,const QString&,const QStringList&)), + SLOT(slotStatus(Kleo::GnuPGProcessBase*,const QString&,const QStringList&)) ); + + if ( !mProcess->start( KProcess::NotifyOnExit, KProcess::Stderr ) ) { + mError = gpg_err_make( GPG_ERR_SOURCE_GPGSM, GPG_ERR_ENOENT ); // what else? + deleteLater(); + return mError; + } else + return 0; +} + +void Kleo::QGpgMERefreshKeysJob::slotCancel() { + if ( mProcess ) + mProcess->kill(); + mProcess = 0; + mError = gpg_err_make( GPG_ERR_SOURCE_GPGSM, GPG_ERR_CANCELED ); +} + +void Kleo::QGpgMERefreshKeysJob::slotStatus( GnuPGProcessBase * proc, const QString & type, const QStringList & args ) { + if ( proc != mProcess ) + return; + QStringList::const_iterator it = args.begin(); + bool ok = false; + + if ( type == "ERROR" ) { + + + if ( args.size() < 2 ) { + kdDebug( 5150 ) << "Kleo::QGpgMERefreshKeysJob::slotStatus() not recognising ERROR with < 2 args!" << endl; + return; + } + const int source = (*++it).toInt( &ok ); + if ( !ok ) { + kdDebug( 5150 ) << "Kleo::QGpgMERefreshKeysJob::slotStatus() expected number for first ERROR arg, got something else" << endl; + return; + } + ok = false; + const int code = (*++it).toInt( &ok ); + if ( !ok ) { + kdDebug( 5150 ) << "Kleo::QGpgMERefreshKeysJob::slotStatus() expected number for second ERROR arg, got something else" << endl; + return; + } + mError = gpg_err_make( (gpg_err_source_t)source, (gpg_err_code_t)code ); + + + } else if ( type == "PROGRESS" ) { + + + if ( args.size() < 4 ) { + kdDebug( 5150 ) << "Kleo::QGpgMERefreshKeysJob::slotStatus() not recognising PROGRESS with < 4 args!" << endl; + return; + } + const QString what = *++it; + ++it; // don't use "type"... + const int cur = (*++it).toInt( &ok ); + if ( !ok ) { + kdDebug( 5150 ) << "Kleo::QGpgMERefreshKeysJob::slotStatus() expected number for \"cur\", got something else" << endl; + return; + } + ok = false; + const int total = (*++it).toInt( &ok ); + if ( !ok ) { + kdDebug( 5150 ) << "Kleo::QGpgMERefreshKeysJob::slotStatus() expected number for \"total\", got something else" << endl; + return; + } + emit progress( QGpgMEProgressTokenMapper::instance()->map( what, 0, cur, total ), cur, total ); + + + } +} + +void Kleo::QGpgMERefreshKeysJob::slotStderr( KProcess *, char *, int ) { + // implement? or not? +} + +void Kleo::QGpgMERefreshKeysJob::slotProcessExited( KProcess * proc ) { + if ( proc != mProcess ) + return; + + if ( !mError && !mPatternsToDo.empty() ) + if ( const GpgME::Error err = startAProcess() ) + mError = err; + else + return; + + emit done(); + if ( !mError && + ( !mProcess->normalExit() || mProcess->exitStatus() != 0 ) ) + mError = gpg_err_make( GPG_ERR_SOURCE_GPGSM, GPG_ERR_GENERAL ); + emit result( mError ); + deleteLater(); +} + +#include "qgpgmerefreshkeysjob.moc" diff --git a/certmanager/lib/backends/qgpgme/qgpgmerefreshkeysjob.h b/certmanager/lib/backends/qgpgme/qgpgmerefreshkeysjob.h new file mode 100644 index 000000000..a0132f223 --- /dev/null +++ b/certmanager/lib/backends/qgpgme/qgpgmerefreshkeysjob.h @@ -0,0 +1,80 @@ +/* + qgpgmerefreshkeysjob.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_QGPGMEREFRESHKEYSJOB_H__ +#define __KLEO_QGPGMEREFRESHKEYSJOB_H__ + +#include <kleo/refreshkeysjob.h> + +#include <qstringlist.h> + +namespace Kleo { + class GnuPGProcessBase; +} + +namespace GpgME { + class Error; +} + +class KProcess; + +namespace Kleo { + + class QGpgMERefreshKeysJob : public RefreshKeysJob { + Q_OBJECT + public: + QGpgMERefreshKeysJob(); + ~QGpgMERefreshKeysJob(); + + /*! \reimp from RefreshKeysJob */ + GpgME::Error start( const QStringList & patterns ); + + private slots: + /*! \reimp from Job */ + void slotCancel(); + + void slotStatus( Kleo::GnuPGProcessBase *, const QString &, const QStringList & ); + void slotStderr( KProcess *, char *, int ); + void slotProcessExited( KProcess * ); + + private: + GpgME::Error startAProcess(); + + private: + GnuPGProcessBase * mProcess; + int mError; + QStringList mPatternsToDo; + }; + +} + +#endif // __KLEO_QGPGMEREFRESHKEYSJOB_H__ diff --git a/certmanager/lib/backends/qgpgme/qgpgmesecretkeyexportjob.cpp b/certmanager/lib/backends/qgpgme/qgpgmesecretkeyexportjob.cpp new file mode 100644 index 000000000..0ce543cf9 --- /dev/null +++ b/certmanager/lib/backends/qgpgme/qgpgmesecretkeyexportjob.cpp @@ -0,0 +1,196 @@ +/* + qgpgmesecretexportjob.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "qgpgmesecretkeyexportjob.h" + +#include "gnupgprocessbase.h" +#include "qgpgmeprogresstokenmapper.h" + +#include <kdebug.h> + +#include <gpgmepp/context.h> +#include <gpgmepp/data.h> + +#include <qgpgme/eventloopinteractor.h> + +#include <qstringlist.h> + +#include <gpg-error.h> + +#include <string.h> +#include <assert.h> + +Kleo::QGpgMESecretKeyExportJob::QGpgMESecretKeyExportJob( bool armour, const QString& charset ) + : ExportJob( QGpgME::EventLoopInteractor::instance(), "Kleo::QGpgMESecretKeyExportJob" ), + mProcess( 0 ), + mError( 0 ), + mArmour( armour ), + mCharset( charset ) +{ + +} + +Kleo::QGpgMESecretKeyExportJob::~QGpgMESecretKeyExportJob() { + +} + +GpgME::Error Kleo::QGpgMESecretKeyExportJob::start( const QStringList & patterns ) { + assert( mKeyData.isEmpty() ); + + if ( patterns.size() != 1 || patterns.front().isEmpty() ) { + deleteLater(); + return mError = gpg_err_make( GPG_ERR_SOURCE_GPGSM, GPG_ERR_INV_VALUE ); + } + + // create and start gpgsm process: + mProcess = new GnuPGProcessBase( this, "gpgsm --export-secret-key-p12" ); + + // FIXME: obtain the path to gpgsm from gpgme, so we use the same instance. + *mProcess << "gpgsm" << "--export-secret-key-p12"; + if ( mArmour ) + *mProcess << "--armor"; + if ( !mCharset.isEmpty() ) + *mProcess << "--p12-charset" << mCharset; + *mProcess << patterns.front().utf8(); + + mProcess->setUseStatusFD( true ); + + connect( mProcess, SIGNAL(processExited(KProcess*)), + SLOT(slotProcessExited(KProcess*)) ); + connect( mProcess, SIGNAL(receivedStdout(KProcess*,char*,int)), + SLOT(slotStdout(KProcess*,char*,int)) ); + connect( mProcess, SIGNAL(receivedStderr(KProcess*,char*,int)), + SLOT(slotStderr(KProcess*,char*,int)) ); + connect( mProcess, SIGNAL(status(Kleo::GnuPGProcessBase*,const QString&,const QStringList&)), + SLOT(slotStatus(Kleo::GnuPGProcessBase*,const QString&,const QStringList&)) ); + + if ( !mProcess->start( KProcess::NotifyOnExit, KProcess::AllOutput ) ) { + mError = gpg_err_make( GPG_ERR_SOURCE_GPGSM, GPG_ERR_ENOENT ); // what else? + deleteLater(); + return mError; + } else + return 0; +} + +void Kleo::QGpgMESecretKeyExportJob::slotCancel() { + if ( mProcess ) + mProcess->kill(); + mProcess = 0; + mError = gpg_err_make( GPG_ERR_SOURCE_GPGSM, GPG_ERR_CANCELED ); +} + +void Kleo::QGpgMESecretKeyExportJob::slotStatus( GnuPGProcessBase * proc, const QString & type, const QStringList & args ) { + if ( proc != mProcess ) + return; + QStringList::const_iterator it = args.begin(); + bool ok = false; + + if ( type == "ERROR" ) { + + + if ( args.size() < 2 ) { + kdDebug( 5150 ) << "Kleo::QGpgMESecretKeyExportJob::slotStatus() not recognising ERROR with < 2 args!" << endl; + return; + } + const int source = (*++it).toInt( &ok ); + if ( !ok ) { + kdDebug( 5150 ) << "Kleo::QGpgMESecretKeyExportJob::slotStatus() expected number for first ERROR arg, got something else" << endl; + return; + } + ok = false; + const int code = (*++it).toInt( &ok ); + if ( !ok ) { + kdDebug( 5150 ) << "Kleo::QGpgMESecretKeyExportJob::slotStatus() expected number for second ERROR arg, got something else" << endl; + return; + } + mError = gpg_err_make( (gpg_err_source_t)source, (gpg_err_code_t)code ); + + + } else if ( type == "PROGRESS" ) { + + + if ( args.size() < 4 ) { + kdDebug( 5150 ) << "Kleo::QGpgMESecretKeyExportJob::slotStatus() not recognising PROGRESS with < 4 args!" << endl; + return; + } + const QString what = *++it; + ++it; // don't use "type"... + const int cur = (*++it).toInt( &ok ); + if ( !ok ) { + kdDebug( 5150 ) << "Kleo::QGpgMESecretKeyExportJob::slotStatus() expected number for \"cur\", got something else" << endl; + return; + } + ok = false; + const int total = (*++it).toInt( &ok ); + if ( !ok ) { + kdDebug( 5150 ) << "Kleo::QGpgMESecretKeyExportJob::slotStatus() expected number for \"total\", got something else" << endl; + return; + } + emit progress( QGpgMEProgressTokenMapper::instance()->map( what, 0, cur, total ), cur, total ); + + + } +} + +void Kleo::QGpgMESecretKeyExportJob::slotStdout( KProcess * proc, char * buf, int buflen ) { + if ( proc != mProcess ) + return; + if ( buflen <= 0 ) + return; + if ( !buf ) + return; + const unsigned int oldlen = mKeyData.size(); + mKeyData.resize( oldlen + buflen ); + memcpy( mKeyData.data() + oldlen, buf, buflen ); +} + +void Kleo::QGpgMESecretKeyExportJob::slotStderr( KProcess *, char *, int ) { + // implement? or not? +} + +void Kleo::QGpgMESecretKeyExportJob::slotProcessExited( KProcess * proc ) { + if ( proc != mProcess ) + return; + + emit done(); + if ( !mError && + ( !mProcess->normalExit() || mProcess->exitStatus() != 0 ) ) + mError = gpg_err_make( GPG_ERR_SOURCE_GPGSM, GPG_ERR_GENERAL ); + emit result( mError, mKeyData ); + deleteLater(); +} + +#include "qgpgmesecretkeyexportjob.moc" diff --git a/certmanager/lib/backends/qgpgme/qgpgmesecretkeyexportjob.h b/certmanager/lib/backends/qgpgme/qgpgmesecretkeyexportjob.h new file mode 100644 index 000000000..5f5e3b69c --- /dev/null +++ b/certmanager/lib/backends/qgpgme/qgpgmesecretkeyexportjob.h @@ -0,0 +1,85 @@ +/* + qgpgmesecretkeyexportjob.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_QGPGMESECRETKEYEXPORTJOB_H__ +#define __KLEO_QGPGMESECRETKEYEXPORTJOB_H__ + +#include <kleo/exportjob.h> + +#include <qcstring.h> + +namespace Kleo { + class GnuPGProcessBase; +} + +namespace GpgME { + class Error; + class Data; +} + +namespace QGpgME { + class QByteArrayDataProvider; +} + +class KProcess; + +namespace Kleo { + + class QGpgMESecretKeyExportJob : public ExportJob { + Q_OBJECT + public: + QGpgMESecretKeyExportJob( bool armour, const QString& charset ); + ~QGpgMESecretKeyExportJob(); + + /*! \reimp from ExportJob */ + GpgME::Error start( const QStringList & patterns ); + + private slots: + /*! \reimp from Job */ + void slotCancel(); + + void slotStatus( Kleo::GnuPGProcessBase *, const QString &, const QStringList & ); + void slotStdout( KProcess *, char *, int ); + void slotStderr( KProcess *, char *, int ); + void slotProcessExited( KProcess * ); + + private: + GnuPGProcessBase * mProcess; + QByteArray mKeyData; + int mError; + bool mArmour; + QString mCharset; + }; + +} + +#endif // __KLEO_QGPGMESECRETKEYEXPORTJOB_H__ diff --git a/certmanager/lib/backends/qgpgme/qgpgmesignencryptjob.cpp b/certmanager/lib/backends/qgpgme/qgpgmesignencryptjob.cpp new file mode 100644 index 000000000..fae748478 --- /dev/null +++ b/certmanager/lib/backends/qgpgme/qgpgmesignencryptjob.cpp @@ -0,0 +1,121 @@ +/* + qgpgmesignencryptjob.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "qgpgmesignencryptjob.h" + +#include "ui/messagebox.h" + +#include <qgpgme/eventloopinteractor.h> +#include <qgpgme/dataprovider.h> + +#include <gpgmepp/context.h> +#include <gpgmepp/data.h> +#include <gpgmepp/key.h> + +#include <klocale.h> + +#include <assert.h> + +Kleo::QGpgMESignEncryptJob::QGpgMESignEncryptJob( GpgME::Context * context ) + : SignEncryptJob( QGpgME::EventLoopInteractor::instance(), "Kleo::QGpgMESignEncryptJob" ), + QGpgMEJob( this, context ) +{ + assert( context ); +} + +Kleo::QGpgMESignEncryptJob::~QGpgMESignEncryptJob() { +} + +GpgME::Error Kleo::QGpgMESignEncryptJob::setup( const std::vector<GpgME::Key> & signers, + const QByteArray & plainText ) { + assert( !mInData ); + assert( !mOutData ); + + createInData( plainText ); + createOutData(); + + return setSigningKeys( signers ); +} + +GpgME::Error Kleo::QGpgMESignEncryptJob::start( const std::vector<GpgME::Key> & signers, + const std::vector<GpgME::Key> & recipients, + const QByteArray & plainText, bool alwaysTrust ) { + if ( const GpgME::Error error = setup( signers, plainText ) ) { + deleteLater(); + return error; + } + + hookupContextToEventLoopInteractor(); + + const GpgME::Context::EncryptionFlags flags = + alwaysTrust ? GpgME::Context::AlwaysTrust : GpgME::Context::None ; + const GpgME::Error err = mCtx->startCombinedSigningAndEncryption( recipients, *mInData, *mOutData, flags ); + + if ( err ) + deleteLater(); + mResult.first = GpgME::SigningResult( err ); + mResult.second = GpgME::EncryptionResult( err ); + return err; +} + +std::pair<GpgME::SigningResult,GpgME::EncryptionResult> +Kleo::QGpgMESignEncryptJob::exec( const std::vector<GpgME::Key> & signers, + const std::vector<GpgME::Key> & recipients, + const QByteArray & plainText, bool alwaysTrust, + QByteArray & cipherText ) { + if ( GpgME::Error err = setup( signers, plainText ) ) + return std::make_pair( GpgME::SigningResult( 0, err ), GpgME::EncryptionResult() ); + const GpgME::Context::EncryptionFlags flags = + alwaysTrust ? GpgME::Context::AlwaysTrust : GpgME::Context::None ; + mResult = mCtx->signAndEncrypt( recipients, *mInData, *mOutData, flags ); + cipherText = mOutDataDataProvider->data(); + getAuditLog(); + return mResult; +} + +void Kleo::QGpgMESignEncryptJob::doOperationDoneEvent( const GpgME::Error & ) { + mResult.first = mCtx->signingResult(); + mResult.second = mCtx->encryptionResult(); + emit result( mResult.first, mResult.second, mOutDataDataProvider->data() ); +} + +void Kleo::QGpgMESignEncryptJob::showErrorDialog( QWidget * parent, const QString & caption ) const { + if ( mResult.first.error() && !mResult.first.error().isCanceled() || + mResult.second.error() && !mResult.second.error().isCanceled() ) + Kleo::MessageBox::error( parent, mResult.first, mResult.second, this, caption ); +} + +#include "qgpgmesignencryptjob.moc" diff --git a/certmanager/lib/backends/qgpgme/qgpgmesignencryptjob.h b/certmanager/lib/backends/qgpgme/qgpgmesignencryptjob.h new file mode 100644 index 000000000..a826edcbf --- /dev/null +++ b/certmanager/lib/backends/qgpgme/qgpgmesignencryptjob.h @@ -0,0 +1,91 @@ +/* + qgpgmesignencryptjob.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_QGPGMESIGNENCRYPTJOB_H__ +#define __KLEO_QGPGMESIGNENCRYPTJOB_H__ + +#include <kleo/signencryptjob.h> + +#include "qgpgmejob.h" + +#include <gpgmepp/signingresult.h> +#include <gpgmepp/encryptionresult.h> + +#include <qcstring.h> + +#include <utility> + +#include <kdepimmacros.h> +namespace GpgME { + class Error; + class Context; + class Key; +} + +namespace Kleo { + + class KDE_EXPORT QGpgMESignEncryptJob : public SignEncryptJob, private QGpgMEJob { + Q_OBJECT QGPGME_JOB + public: + QGpgMESignEncryptJob( GpgME::Context * context ); + ~QGpgMESignEncryptJob(); + + /*! \reimp from SignEncryptJob */ + GpgME::Error start( const std::vector<GpgME::Key> & signers, + const std::vector<GpgME::Key> & recipients, + const QByteArray & plainText, bool alwaysTrust ); + + std::pair<GpgME::SigningResult,GpgME::EncryptionResult> + exec( const std::vector<GpgME::Key> & signers, + const std::vector<GpgME::Key> & recipients, + const QByteArray & plainText, bool alwaysTrust, + QByteArray & cipherText ); + + /*! \reimp from Job */ + void showErrorDialog( QWidget * parent, const QString & caption ) const; + + private slots: + void slotOperationDoneEvent( GpgME::Context * context, const GpgME::Error & e ) { + QGpgMEJob::doSlotOperationDoneEvent( context, e ); + } + + private: + void doOperationDoneEvent( const GpgME::Error & e ); + GpgME::Error setup( const std::vector<GpgME::Key> &, + const QByteArray & ); + private: + std::pair<GpgME::SigningResult,GpgME::EncryptionResult> mResult; + }; + +} + +#endif // __KLEO_QGPGMESIGNENCRYPTJOB_H__ diff --git a/certmanager/lib/backends/qgpgme/qgpgmesignjob.cpp b/certmanager/lib/backends/qgpgme/qgpgmesignjob.cpp new file mode 100644 index 000000000..84485ad5b --- /dev/null +++ b/certmanager/lib/backends/qgpgme/qgpgmesignjob.cpp @@ -0,0 +1,113 @@ +/* + qgpgmesignjob.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "qgpgmesignjob.h" + +#include "ui/messagebox.h" + +#include <qgpgme/eventloopinteractor.h> +#include <qgpgme/dataprovider.h> + +#include <gpgmepp/context.h> +#include <gpgmepp/signingresult.h> +#include <gpgmepp/data.h> +#include <gpgmepp/key.h> + +#include <klocale.h> + +#include <assert.h> + +Kleo::QGpgMESignJob::QGpgMESignJob( GpgME::Context * context ) + : SignJob( QGpgME::EventLoopInteractor::instance(), "Kleo::QGpgMESignJob" ), + QGpgMEJob( this, context ) +{ + assert( context ); +} + +Kleo::QGpgMESignJob::~QGpgMESignJob() { +} + +GpgME::Error Kleo::QGpgMESignJob::setup( const std::vector<GpgME::Key> & signers, + const QByteArray & plainText ) { + assert( !mInData ); + assert( !mOutData ); + + createInData( plainText ); + createOutData(); + + return setSigningKeys( signers ); +} + +GpgME::Error Kleo::QGpgMESignJob::start( const std::vector<GpgME::Key> & signers, + const QByteArray & plainText, + GpgME::Context::SignatureMode mode ) { + if ( const GpgME::Error error = setup( signers, plainText ) ) { + deleteLater(); + return error; + } + + hookupContextToEventLoopInteractor(); + + const GpgME::Error err = mCtx->startSigning( *mInData, *mOutData, mode ); + + if ( err ) + deleteLater(); + mResult = GpgME::SigningResult( err ); + return err; +} + +GpgME::SigningResult Kleo::QGpgMESignJob::exec( const std::vector<GpgME::Key> & signers, + const QByteArray & plainText, + GpgME::Context::SignatureMode mode, + QByteArray & signature ) { + if ( const GpgME::Error err = setup( signers, plainText ) ) + return mResult = GpgME::SigningResult( 0, err ); + mResult = mCtx->sign( *mInData, *mOutData, mode ); + signature = mOutDataDataProvider->data(); + getAuditLog(); + return mResult; +} + +void Kleo::QGpgMESignJob::doOperationDoneEvent( const GpgME::Error & ) { + emit result( mResult = mCtx->signingResult(), mOutDataDataProvider->data() ); +} + +void Kleo::QGpgMESignJob::showErrorDialog( QWidget * parent, const QString & caption ) const { + if ( mResult.error() && !mResult.error().isCanceled() ) + Kleo::MessageBox::error( parent, mResult, this, caption ); +} + +#include "qgpgmesignjob.moc" diff --git a/certmanager/lib/backends/qgpgme/qgpgmesignjob.h b/certmanager/lib/backends/qgpgme/qgpgmesignjob.h new file mode 100644 index 000000000..c2589b477 --- /dev/null +++ b/certmanager/lib/backends/qgpgme/qgpgmesignjob.h @@ -0,0 +1,87 @@ +/* + qgpgmesignjob.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_QGPGMESIGNJOB_H__ +#define __KLEO_QGPGMESIGNJOB_H__ + +#include <kleo/signjob.h> + +#include "qgpgmejob.h" + +#include <gpgmepp/signingresult.h> + +#include <qcstring.h> + +namespace GpgME { + class Error; + class Context; + class Key; +} + +namespace Kleo { + + class QGpgMESignJob : public SignJob, private QGpgMEJob { + Q_OBJECT QGPGME_JOB + public: + QGpgMESignJob( GpgME::Context * context ); + ~QGpgMESignJob(); + + /*! \reimp from SignJob */ + GpgME::Error start( const std::vector<GpgME::Key> & signers, + const QByteArray & plainText, + GpgME::Context::SignatureMode mode ); + + /*! \reimp from SignJob */ + GpgME::SigningResult exec( const std::vector<GpgME::Key> & signers, + const QByteArray & plainText, + GpgME::Context::SignatureMode mode, + QByteArray & signature ); + + /*! \reimp from Job */ + void showErrorDialog( QWidget * parent, const QString & caption ) const; + + private slots: + void slotOperationDoneEvent( GpgME::Context * context, const GpgME::Error & e ) { + QGpgMEJob::doSlotOperationDoneEvent( context, e ); + } + + private: + void doOperationDoneEvent( const GpgME::Error & e ); + GpgME::Error setup( const std::vector<GpgME::Key> &, const QByteArray & ); + + private: + GpgME::SigningResult mResult; + }; + +} + +#endif // __KLEO_QGPGMESIGNJOB_H__ diff --git a/certmanager/lib/backends/qgpgme/qgpgmeverifydetachedjob.cpp b/certmanager/lib/backends/qgpgme/qgpgmeverifydetachedjob.cpp new file mode 100644 index 000000000..cc1186373 --- /dev/null +++ b/certmanager/lib/backends/qgpgme/qgpgmeverifydetachedjob.cpp @@ -0,0 +1,96 @@ +/* + qgpgmeverifydetachedjob.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "qgpgmeverifydetachedjob.h" + +#include <qgpgme/eventloopinteractor.h> +#include <qgpgme/dataprovider.h> + +#include <gpgmepp/context.h> +#include <gpgmepp/verificationresult.h> +#include <gpgmepp/data.h> + +#include <assert.h> + +Kleo::QGpgMEVerifyDetachedJob::QGpgMEVerifyDetachedJob( GpgME::Context * context ) + : VerifyDetachedJob( QGpgME::EventLoopInteractor::instance(), "Kleo::QGpgMEVerifyDetachedJob" ), + QGpgMEJob( this, context ) +{ + assert( context ); +} + +Kleo::QGpgMEVerifyDetachedJob::~QGpgMEVerifyDetachedJob() { +} + +void Kleo::QGpgMEVerifyDetachedJob::setup( const QByteArray & signature, const QByteArray & signedData ) { + assert( !mInData ); + assert( !mOutData ); + + createInData( signature ); + + // two "in" data objects - (mis|re)use the "out" data object for the second... + mOutDataDataProvider = new QGpgME::QByteArrayDataProvider( signedData ); + mOutData = new GpgME::Data( mOutDataDataProvider ); + assert( !mOutData->isNull() ); +} + +GpgME::Error Kleo::QGpgMEVerifyDetachedJob::start( const QByteArray & signature, + const QByteArray & signedData ) { + setup( signature, signedData ); + + hookupContextToEventLoopInteractor(); + + const GpgME::Error err = mCtx->startDetachedSignatureVerification( *mInData, *mOutData ); + + if ( err ) + deleteLater(); + return err; +} + +GpgME::VerificationResult Kleo::QGpgMEVerifyDetachedJob::exec( const QByteArray & signature, + const QByteArray & signedData ) { + setup( signature, signedData ); + const GpgME::VerificationResult r = mCtx->verifyDetachedSignature( *mInData, *mOutData ); + getAuditLog(); + return r; +} + +void Kleo::QGpgMEVerifyDetachedJob::doOperationDoneEvent( const GpgME::Error & ) { + emit result( mCtx->verificationResult() ); +} + + +#include "qgpgmeverifydetachedjob.moc" diff --git a/certmanager/lib/backends/qgpgme/qgpgmeverifydetachedjob.h b/certmanager/lib/backends/qgpgme/qgpgmeverifydetachedjob.h new file mode 100644 index 000000000..76141fb80 --- /dev/null +++ b/certmanager/lib/backends/qgpgme/qgpgmeverifydetachedjob.h @@ -0,0 +1,75 @@ +/* + qgpgmeverifydetachedjob.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_QGPGMEVERIFYDETACHEDJOB_H__ +#define __KLEO_QGPGMEVERIFYDETACHEDJOB_H__ + +#include <kleo/verifydetachedjob.h> + +#include "qgpgmejob.h" + +#include <qcstring.h> + +namespace GpgME { + class Error; + class Context; +} + +namespace Kleo { + + class QGpgMEVerifyDetachedJob : public VerifyDetachedJob, private QGpgMEJob { + Q_OBJECT QGPGME_JOB + public: + QGpgMEVerifyDetachedJob( GpgME::Context * context ); + ~QGpgMEVerifyDetachedJob(); + + /*! \reimp from VerifyDetachedJob */ + GpgME::Error start( const QByteArray & signature, + const QByteArray & signedData ); + + /*! \reimp from VerifyDetachedJob */ + GpgME::VerificationResult exec( const QByteArray & signature, + const QByteArray & signedData ); + + private slots: + void slotOperationDoneEvent( GpgME::Context * context, const GpgME::Error & e ) { + QGpgMEJob::doSlotOperationDoneEvent( context, e ); + } + + private: + void doOperationDoneEvent( const GpgME::Error & e ); + void setup( const QByteArray &, const QByteArray & ); + }; + +} + +#endif // __KLEO_QGPGMEVERIFYDETACHEDJOB_H__ diff --git a/certmanager/lib/backends/qgpgme/qgpgmeverifyopaquejob.cpp b/certmanager/lib/backends/qgpgme/qgpgmeverifyopaquejob.cpp new file mode 100644 index 000000000..15f075963 --- /dev/null +++ b/certmanager/lib/backends/qgpgme/qgpgmeverifyopaquejob.cpp @@ -0,0 +1,91 @@ +/* + qgpgmeverifyopaquejob.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "qgpgmeverifyopaquejob.h" + +#include <qgpgme/eventloopinteractor.h> +#include <qgpgme/dataprovider.h> + +#include <gpgmepp/context.h> +#include <gpgmepp/verificationresult.h> +#include <gpgmepp/data.h> + +#include <assert.h> + +Kleo::QGpgMEVerifyOpaqueJob::QGpgMEVerifyOpaqueJob( GpgME::Context * context ) + : VerifyOpaqueJob( QGpgME::EventLoopInteractor::instance(), "Kleo::QGpgMEVerifyOpaqueJob" ), + QGpgMEJob( this, context ) +{ + assert( context ); +} + +Kleo::QGpgMEVerifyOpaqueJob::~QGpgMEVerifyOpaqueJob() { +} + +void Kleo::QGpgMEVerifyOpaqueJob::setup( const QByteArray & signedData ) { + assert( !mInData ); + assert( !mOutData ); + + createInData( signedData ); + createOutData(); +} + +GpgME::Error Kleo::QGpgMEVerifyOpaqueJob::start( const QByteArray & signedData ) { + setup( signedData ); + + hookupContextToEventLoopInteractor(); + + const GpgME::Error err = mCtx->startOpaqueSignatureVerification( *mInData, *mOutData ); + + if ( err ) + deleteLater(); + return err; +} + +GpgME::VerificationResult Kleo::QGpgMEVerifyOpaqueJob::exec( const QByteArray & signedData, QByteArray & plainText ) { + setup( signedData ); + const GpgME::VerificationResult res = mCtx->verifyOpaqueSignature( *mInData, *mOutData ); + plainText = mOutDataDataProvider->data(); + getAuditLog(); + return res; +} + +void Kleo::QGpgMEVerifyOpaqueJob::doOperationDoneEvent( const GpgME::Error & ) { + emit result( mCtx->verificationResult(), mOutDataDataProvider->data() ); +} + + +#include "qgpgmeverifyopaquejob.moc" diff --git a/certmanager/lib/backends/qgpgme/qgpgmeverifyopaquejob.h b/certmanager/lib/backends/qgpgme/qgpgmeverifyopaquejob.h new file mode 100644 index 000000000..2c167fb1d --- /dev/null +++ b/certmanager/lib/backends/qgpgme/qgpgmeverifyopaquejob.h @@ -0,0 +1,73 @@ +/* + qgpgmeverifyopaquejob.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_QGPGMEVERIFYOPAQUEJOB_H__ +#define __KLEO_QGPGMEVERIFYOPAQUEJOB_H__ + +#include <kleo/verifyopaquejob.h> + +#include "qgpgmejob.h" + +#include <qcstring.h> + +namespace GpgME { + class Error; + class Context; +} + +namespace Kleo { + + class QGpgMEVerifyOpaqueJob : public VerifyOpaqueJob, private QGpgMEJob { + Q_OBJECT QGPGME_JOB + public: + QGpgMEVerifyOpaqueJob( GpgME::Context * context ); + ~QGpgMEVerifyOpaqueJob(); + + /*! \reimp from VerifyOpaqueJob */ + GpgME::Error start( const QByteArray & signedData ); + + /*! \reimp form VerifyOpaqueJob */ + GpgME::VerificationResult exec( const QByteArray & signedData, QByteArray & plainData ); + + private slots: + void slotOperationDoneEvent( GpgME::Context * context, const GpgME::Error & e ) { + QGpgMEJob::doSlotOperationDoneEvent( context, e ); + } + + private: + void doOperationDoneEvent( const GpgME::Error & e ); + void setup( const QByteArray & ); + }; + +} + +#endif // __KLEO_QGPGMEVERIFYOPAQUEJOB_H__ diff --git a/certmanager/lib/cryptplug.cpp b/certmanager/lib/cryptplug.cpp new file mode 100644 index 000000000..f9d1aa632 --- /dev/null +++ b/certmanager/lib/cryptplug.cpp @@ -0,0 +1,1123 @@ +/* -*- Mode: C++ -*- + + this is a C++-ification of: + GPGMEPLUG - an GPGME based cryptography plug-in following + the common CRYPTPLUG specification. + + Copyright (C) 2001 by Klarälvdalens Datakonsult AB + Copyright (C) 2002 g10 Code GmbH + Copyright (C) 2004 Klarälvdalens Datakonsult AB + + GPGMEPLUG is free software; you can redistribute it and/or modify + it under the terms of GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + GPGMEPLUG is distributed in the hope that it will be useful, + it under the terms of GNU General Public License as published by + the Free Software Foundation; version 2 of the License + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "kleo/oidmap.h" + +#include <gpgmepp/context.h> +#include <gpgmepp/data.h> +#include <gpgmepp/importresult.h> + +/*! \file gpgmeplug.c + \brief GPGME implementation of CRYPTPLUG following the + specification located in common API header cryptplug.h. + + CRYPTPLUG is an independent cryptography plug-in API + developed for Sphinx-enabeling KMail and Mutt. + + CRYPTPLUG was designed for the Aegypten project, but it may + be used by 3rd party developers as well to design pluggable + crypto backends for the above mentioned MUAs. + + \note All string parameters appearing in this API are to be + interpreted as UTF-8 encoded. + + \see cryptplug.h +*/ + +#include <qstring.h> + +#include <string> +#include <vector> +#include <algorithm> +#include <iostream> +#include <memory> + +#include <stdio.h> +#include <string.h> +#include <strings.h> +#include <assert.h> +#include <errno.h> +#include <time.h> +#include <ctype.h> +#include <locale.h> + +#define __GPGMEPLUG_ERROR_CLEARTEXT_IS_ZERO "Error: Cannot run checkMessageSignature() with cleartext == 0" + +/* Note: The following specification will result in + function encryptAndSignMessage() producing + _empty_ mails. + This must be changed as soon as our plugin + is supporting the encryptAndSignMessage() function. */ +#ifndef GPGMEPLUG_ENCSIGN_MAKE_MIME_OBJECT +#define GPGMEPLUG_ENCSIGN_INCLUDE_CLEARTEXT false +#define GPGMEPLUG_ENCSIGN_MAKE_MIME_OBJECT false +#define GPGMEPLUG_ENCSIGN_MAKE_MULTI_MIME false +#define GPGMEPLUG_ENCSIGN_CTYPE_MAIN "" +#define GPGMEPLUG_ENCSIGN_CDISP_MAIN "" +#define GPGMEPLUG_ENCSIGN_CTENC_MAIN "" +#define GPGMEPLUG_ENCSIGN_CTYPE_VERSION "" +#define GPGMEPLUG_ENCSIGN_CDISP_VERSION "" +#define GPGMEPLUG_ENCSIGN_CTENC_VERSION "" +#define GPGMEPLUG_ENCSIGN_BTEXT_VERSION "" +#define GPGMEPLUG_ENCSIGN_CTYPE_CODE "" +#define GPGMEPLUG_ENCSIGN_CDISP_CODE "" +#define GPGMEPLUG_ENCSIGN_CTENC_CODE "" +#define GPGMEPLUG_ENCSIGN_FLAT_PREFIX "" +#define GPGMEPLUG_ENCSIGN_FLAT_SEPARATOR "" +#define GPGMEPLUG_ENCSIGN_FLAT_POSTFIX "" +#endif + +#include "cryptplug.h" +#include <kdebug.h> + +SMIMECryptPlug::SMIMECryptPlug() : CryptPlug() { + GPGMEPLUG_PROTOCOL = GPGME_PROTOCOL_CMS; + mProtocol = GpgME::Context::CMS; + + /* definitions for signing */ + // 1. opaque signatures (only used for S/MIME) + GPGMEPLUG_OPA_SIGN_INCLUDE_CLEARTEXT = false; + GPGMEPLUG_OPA_SIGN_MAKE_MIME_OBJECT = true; + GPGMEPLUG_OPA_SIGN_MAKE_MULTI_MIME = false; + GPGMEPLUG_OPA_SIGN_CTYPE_MAIN = "application/pkcs7-mime; smime-type=signed-data; name=\"smime.p7m\""; + GPGMEPLUG_OPA_SIGN_CDISP_MAIN = "attachment; filename=\"smime.p7m\""; + GPGMEPLUG_OPA_SIGN_CTENC_MAIN = "base64"; + GPGMEPLUG_OPA_SIGN_CTYPE_VERSION = ""; + GPGMEPLUG_OPA_SIGN_CDISP_VERSION = ""; + GPGMEPLUG_OPA_SIGN_CTENC_VERSION = ""; + GPGMEPLUG_OPA_SIGN_BTEXT_VERSION = ""; + GPGMEPLUG_OPA_SIGN_CTYPE_CODE = ""; + GPGMEPLUG_OPA_SIGN_CDISP_CODE = ""; + GPGMEPLUG_OPA_SIGN_CTENC_CODE = ""; + GPGMEPLUG_OPA_SIGN_FLAT_PREFIX = ""; + GPGMEPLUG_OPA_SIGN_FLAT_SEPARATOR = ""; + GPGMEPLUG_OPA_SIGN_FLAT_POSTFIX = ""; + // 2. detached signatures (used for S/MIME and for OpenPGP) + GPGMEPLUG_DET_SIGN_INCLUDE_CLEARTEXT = true; + GPGMEPLUG_DET_SIGN_MAKE_MIME_OBJECT = true; + GPGMEPLUG_DET_SIGN_MAKE_MULTI_MIME = true; + GPGMEPLUG_DET_SIGN_CTYPE_MAIN = "multipart/signed; protocol=\"application/pkcs7-signature\"; micalg=sha1"; + GPGMEPLUG_DET_SIGN_CDISP_MAIN = ""; + GPGMEPLUG_DET_SIGN_CTENC_MAIN = ""; + GPGMEPLUG_DET_SIGN_CTYPE_VERSION = ""; + GPGMEPLUG_DET_SIGN_CDISP_VERSION = ""; + GPGMEPLUG_DET_SIGN_CTENC_VERSION = ""; + GPGMEPLUG_DET_SIGN_BTEXT_VERSION = ""; + GPGMEPLUG_DET_SIGN_CTYPE_CODE = "application/pkcs7-signature; name=\"smime.p7s\""; + GPGMEPLUG_DET_SIGN_CDISP_CODE = "attachment; filename=\"smime.p7s\""; + GPGMEPLUG_DET_SIGN_CTENC_CODE = "base64"; + GPGMEPLUG_DET_SIGN_FLAT_PREFIX = ""; + GPGMEPLUG_DET_SIGN_FLAT_SEPARATOR = ""; + GPGMEPLUG_DET_SIGN_FLAT_POSTFIX = ""; + // 3. common definitions for opaque and detached signing + __GPGMEPLUG_SIGNATURE_CODE_IS_BINARY = true; + + /* definitions for encoding */ + GPGMEPLUG_ENC_INCLUDE_CLEARTEXT = false; + GPGMEPLUG_ENC_MAKE_MIME_OBJECT = true; + GPGMEPLUG_ENC_MAKE_MULTI_MIME = false; + GPGMEPLUG_ENC_CTYPE_MAIN = "application/pkcs7-mime; smime-type=enveloped-data; name=\"smime.p7m\""; + GPGMEPLUG_ENC_CDISP_MAIN = "attachment; filename=\"smime.p7m\""; + GPGMEPLUG_ENC_CTENC_MAIN = "base64"; + GPGMEPLUG_ENC_CTYPE_VERSION = ""; + GPGMEPLUG_ENC_CDISP_VERSION = ""; + GPGMEPLUG_ENC_CTENC_VERSION = ""; + GPGMEPLUG_ENC_BTEXT_VERSION = ""; + GPGMEPLUG_ENC_CTYPE_CODE = ""; + GPGMEPLUG_ENC_CDISP_CODE = ""; + GPGMEPLUG_ENC_CTENC_CODE = ""; + GPGMEPLUG_ENC_FLAT_PREFIX = ""; + GPGMEPLUG_ENC_FLAT_SEPARATOR = ""; + GPGMEPLUG_ENC_FLAT_POSTFIX = ""; + __GPGMEPLUG_ENCRYPTED_CODE_IS_BINARY = true; +} + +OpenPGPCryptPlug::OpenPGPCryptPlug() : CryptPlug() { + GPGMEPLUG_PROTOCOL = GPGME_PROTOCOL_OpenPGP; + mProtocol = GpgME::Context::OpenPGP; + + /* definitions for signing */ + // 1. opaque signatures (only used for S/MIME) + GPGMEPLUG_OPA_SIGN_INCLUDE_CLEARTEXT = false; + GPGMEPLUG_OPA_SIGN_MAKE_MIME_OBJECT = false; + GPGMEPLUG_OPA_SIGN_MAKE_MULTI_MIME = false; + GPGMEPLUG_OPA_SIGN_CTYPE_MAIN = ""; + GPGMEPLUG_OPA_SIGN_CDISP_MAIN = ""; + GPGMEPLUG_OPA_SIGN_CTENC_MAIN = ""; + GPGMEPLUG_OPA_SIGN_CTYPE_VERSION = ""; + GPGMEPLUG_OPA_SIGN_CDISP_VERSION = ""; + GPGMEPLUG_OPA_SIGN_CTENC_VERSION = ""; + GPGMEPLUG_OPA_SIGN_BTEXT_VERSION = ""; + GPGMEPLUG_OPA_SIGN_CTYPE_CODE = ""; + GPGMEPLUG_OPA_SIGN_CDISP_CODE = ""; + GPGMEPLUG_OPA_SIGN_CTENC_CODE = ""; + GPGMEPLUG_OPA_SIGN_FLAT_PREFIX = ""; + GPGMEPLUG_OPA_SIGN_FLAT_SEPARATOR = ""; + GPGMEPLUG_OPA_SIGN_FLAT_POSTFIX = ""; + // 2. detached signatures (used for S/MIME and for OpenPGP) + GPGMEPLUG_DET_SIGN_INCLUDE_CLEARTEXT = true; + GPGMEPLUG_DET_SIGN_MAKE_MIME_OBJECT = true; + GPGMEPLUG_DET_SIGN_MAKE_MULTI_MIME = true; + GPGMEPLUG_DET_SIGN_CTYPE_MAIN = "multipart/signed; protocol=\"application/pgp-signature\"; micalg=pgp-sha1"; + GPGMEPLUG_DET_SIGN_CDISP_MAIN = ""; + GPGMEPLUG_DET_SIGN_CTENC_MAIN = ""; + GPGMEPLUG_DET_SIGN_CTYPE_VERSION = ""; + GPGMEPLUG_DET_SIGN_CDISP_VERSION = ""; + GPGMEPLUG_DET_SIGN_CTENC_VERSION = ""; + GPGMEPLUG_DET_SIGN_BTEXT_VERSION = ""; + GPGMEPLUG_DET_SIGN_CTYPE_CODE = "application/pgp-signature"; + GPGMEPLUG_DET_SIGN_CDISP_CODE = ""; + GPGMEPLUG_DET_SIGN_CTENC_CODE = ""; + GPGMEPLUG_DET_SIGN_FLAT_PREFIX = ""; + GPGMEPLUG_DET_SIGN_FLAT_SEPARATOR = ""; + GPGMEPLUG_DET_SIGN_FLAT_POSTFIX = ""; + // 3. common definitions for opaque and detached signing + __GPGMEPLUG_SIGNATURE_CODE_IS_BINARY = false; + + /* definitions for encoding */ + GPGMEPLUG_ENC_INCLUDE_CLEARTEXT = false; + GPGMEPLUG_ENC_MAKE_MIME_OBJECT = true; + GPGMEPLUG_ENC_MAKE_MULTI_MIME = true; + GPGMEPLUG_ENC_CTYPE_MAIN = "multipart/encrypted; protocol=\"application/pgp-encrypted\""; + GPGMEPLUG_ENC_CDISP_MAIN = ""; + GPGMEPLUG_ENC_CTENC_MAIN = ""; + GPGMEPLUG_ENC_CTYPE_VERSION = "application/pgp-encrypted"; + GPGMEPLUG_ENC_CDISP_VERSION = "attachment"; + GPGMEPLUG_ENC_CTENC_VERSION = ""; + GPGMEPLUG_ENC_BTEXT_VERSION = "Version: 1"; + GPGMEPLUG_ENC_CTYPE_CODE = "application/octet-stream"; + GPGMEPLUG_ENC_CDISP_CODE = "inline; filename=\"msg.asc\""; + GPGMEPLUG_ENC_CTENC_CODE = ""; + GPGMEPLUG_ENC_FLAT_PREFIX = ""; + GPGMEPLUG_ENC_FLAT_SEPARATOR = ""; + GPGMEPLUG_ENC_FLAT_POSTFIX = ""; + __GPGMEPLUG_ENCRYPTED_CODE_IS_BINARY = false; +} + +#define days_from_seconds(x) ((x)/86400) + +/* Max number of parts in a DN */ +#define MAX_GPGME_IDX 20 + +/* some macros to replace ctype ones and avoid locale problems */ +#define spacep(p) (*(p) == ' ' || *(p) == '\t') +#define digitp(p) (*(p) >= '0' && *(p) <= '9') +#define hexdigitp(a) (digitp (a) \ + || (*(a) >= 'A' && *(a) <= 'F') \ + || (*(a) >= 'a' && *(a) <= 'f')) +/* the atoi macros assume that the buffer has only valid digits */ +#define atoi_1(p) (*(p) - '0' ) +#define atoi_2(p) ((atoi_1(p) * 10) + atoi_1((p)+1)) +#define atoi_4(p) ((atoi_2(p) * 100) + atoi_2((p)+2)) +#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \ + *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10)) +#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1)) + +static void * +xmalloc (size_t n) +{ + void *p = malloc (n); + if (!p) + { + fputs ("\nfatal: out of core\n", stderr); + exit (4); + } + return p; +} + +/* Please: Don't call an allocation function xfoo when it may return NULL. */ +/* Wrong: #define xstrdup( x ) (x)?strdup(x):0 */ +/* Right: */ +static char * +xstrdup (const char *string) +{ + char *p = (char*)xmalloc (strlen (string)+1); + strcpy (p, string); + return p; +} + + +CryptPlug::CryptPlug() { +} + +CryptPlug::~CryptPlug() { +} + +bool CryptPlug::initialize() { + GpgME::setDefaultLocale( LC_CTYPE, setlocale( LC_CTYPE, 0 ) ); + GpgME::setDefaultLocale( LC_MESSAGES, setlocale( LC_MESSAGES, 0 ) ); + return (gpgme_engine_check_version (GPGMEPLUG_PROTOCOL) == GPG_ERR_NO_ERROR); +} + + +bool CryptPlug::hasFeature( Feature flag ) +{ + /* our own plugins are supposed to support everything */ + switch ( flag ) { + case Feature_SignMessages: + case Feature_VerifySignatures: + case Feature_EncryptMessages: + case Feature_DecryptMessages: + case Feature_SendCertificates: + case Feature_PinEntrySettings: + case Feature_StoreMessagesWithSigs: + case Feature_EncryptionCRLs: + case Feature_StoreMessagesEncrypted: + case Feature_CheckCertificatePath: + return true; + case Feature_WarnSignCertificateExpiry: + case Feature_WarnSignEmailNotInCertificate: + case Feature_WarnEncryptCertificateExpiry: + case Feature_WarnEncryptEmailNotInCertificate: + return GPGMEPLUG_PROTOCOL == GPGME_PROTOCOL_CMS; + /* undefined or not yet implemented: */ + case Feature_CRLDirectoryService: + case Feature_CertificateDirectoryService: + case Feature_undef: + default: + return false; + } +} + + +static +void storeNewCharPtr( char** dest, const char* src ) +{ + int sLen = strlen( src ); + *dest = (char*)xmalloc( sLen + 1 ); + strcpy( *dest, src ); +} + +bool CryptPlug::decryptMessage( const char* ciphertext, + bool cipherIsBinary, + int cipherLen, + const char** cleartext, + const char* /*certificate*/, + int* errId, + char** errTxt ) +{ + gpgme_ctx_t ctx; + gpgme_error_t err; + gpgme_data_t gCiphertext, gPlaintext; + size_t rCLen = 0; + char* rCiph = 0; + bool bOk = false; + + if( !ciphertext ) + return false; + + err = gpgme_new (&ctx); + gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL); + + gpgme_set_armor (ctx, cipherIsBinary ? 0 : 1); + /* gpgme_set_textmode (ctx, cipherIsBinary ? 0 : 1); */ + + /* + gpgme_data_new_from_mem( &gCiphertext, ciphertext, + 1+strlen( ciphertext ), 1 ); */ + gpgme_data_new_from_mem( &gCiphertext, + ciphertext, + cipherIsBinary + ? cipherLen + : strlen( ciphertext ), + 1 ); + + gpgme_data_new( &gPlaintext ); + + err = gpgme_op_decrypt( ctx, gCiphertext, gPlaintext ); + if( err ) { + fprintf( stderr, "\ngpgme_op_decrypt() returned this error code: %i\n\n", err ); + if( errId ) + *errId = err; + if( errTxt ) { + const char* _errTxt = gpgme_strerror( err ); + *errTxt = (char*)malloc( strlen( _errTxt ) + 1 ); + if( *errTxt ) + strcpy(*errTxt, _errTxt ); + } + } + + gpgme_data_release( gCiphertext ); + + rCiph = gpgme_data_release_and_get_mem( gPlaintext, &rCLen ); + + *cleartext = (char*)malloc( rCLen + 1 ); + if( *cleartext ) { + if( rCLen ) { + bOk = true; + strncpy((char*)*cleartext, rCiph, rCLen ); + } + ((char*)(*cleartext))[rCLen] = 0; + } + + free( rCiph ); + gpgme_release( ctx ); + return bOk; +} + + +static char * +trim_trailing_spaces( char *string ) +{ + char *p, *mark; + + for( mark = NULL, p = string; *p; p++ ) { + if( isspace( *p ) ) { + if( !mark ) + mark = p; + } + else + mark = NULL; + } + if( mark ) + *mark = '\0' ; + + return string ; +} + +/* Parse a DN and return an array-ized one. This is not a validating + parser and it does not support any old-stylish syntax; gpgme is + expected to return only rfc2253 compatible strings. */ +static const unsigned char * +parse_dn_part (CryptPlug::DnPair *array, const unsigned char *string) +{ + const unsigned char *s, *s1; + size_t n; + char *p; + + /* parse attributeType */ + for (s = string+1; *s && *s != '='; s++) + ; + if (!*s) + return NULL; /* error */ + n = s - string; + if (!n) + return NULL; /* empty key */ + p = (char*)xmalloc (n+1); + + + memcpy (p, string, n); + p[n] = 0; + trim_trailing_spaces ((char*)p); + // map OIDs to their names: + for ( unsigned int i = 0 ; i < numOidMaps ; ++i ) + if ( !strcasecmp ((char*)p, oidmap[i].oid) ) { + free( p ); + p = xstrdup (oidmap[i].name); + break; + } + array->key = p; + string = s + 1; + + if (*string == '#') + { /* hexstring */ + string++; + for (s=string; hexdigitp (s); s++) + s++; + n = s - string; + if (!n || (n & 1)) + return NULL; /* empty or odd number of digits */ + n /= 2; + array->value = p = (char*)xmalloc (n+1); + + + for (s1=string; n; s1 += 2, n--) + *p++ = xtoi_2 (s1); + *p = 0; + } + else + { /* regular v3 quoted string */ + for (n=0, s=string; *s; s++) + { + if (*s == '\\') + { /* pair */ + s++; + if (*s == ',' || *s == '=' || *s == '+' + || *s == '<' || *s == '>' || *s == '#' || *s == ';' + || *s == '\\' || *s == '\"' || *s == ' ') + n++; + else if (hexdigitp (s) && hexdigitp (s+1)) + { + s++; + n++; + } + else + return NULL; /* invalid escape sequence */ + } + else if (*s == '\"') + return NULL; /* invalid encoding */ + else if (*s == ',' || *s == '=' || *s == '+' + || *s == '<' || *s == '>' || *s == '#' || *s == ';' ) + break; + else + n++; + } + + array->value = p = (char*)xmalloc (n+1); + + + for (s=string; n; s++, n--) + { + if (*s == '\\') + { + s++; + if (hexdigitp (s)) + { + *p++ = xtoi_2 (s); + s++; + } + else + *p++ = *s; + } + else + *p++ = *s; + } + *p = 0; + } + return s; +} + + +/* Parse a DN and return an array-ized one. This is not a validating + parser and it does not support any old-stylish syntax; gpgme is + expected to return only rfc2253 compatible strings. */ +static CryptPlug::DnPair * +parse_dn (const unsigned char *string) +{ + struct CryptPlug::DnPair *array; + size_t arrayidx, arraysize; + + if( !string ) + return NULL; + + arraysize = 7; /* C,ST,L,O,OU,CN,email */ + arrayidx = 0; + array = (CryptPlug::DnPair*)xmalloc ((arraysize+1) * sizeof *array); + + + while (*string) + { + while (*string == ' ') + string++; + if (!*string) + break; /* ready */ + if (arrayidx >= arraysize) + { /* mutt lacks a real safe_realoc - so we need to copy */ + struct CryptPlug::DnPair *a2; + + arraysize += 5; + a2 = (CryptPlug::DnPair*)xmalloc ((arraysize+1) * sizeof *array); + for (unsigned int i=0; i < arrayidx; i++) + { + a2[i].key = array[i].key; + a2[i].value = array[i].value; + } + free (array); + array = a2; + } + array[arrayidx].key = NULL; + array[arrayidx].value = NULL; + string = parse_dn_part (array+arrayidx, string); + arrayidx++; + if (!string) + goto failure; + while (*string == ' ') + string++; + if (*string && *string != ',' && *string != ';' && *string != '+') + goto failure; /* invalid delimiter */ + if (*string) + string++; + } + array[arrayidx].key = NULL; + array[arrayidx].value = NULL; + return array; + + failure: + for (unsigned i=0; i < arrayidx; i++) + { + free (array[i].key); + free (array[i].value); + } + free (array); + return NULL; +} + +static void +add_dn_part( QCString& result, struct CryptPlug::DnPair& dnPair ) +{ + /* email hack */ + QCString mappedPart( dnPair.key ); + for ( unsigned int i = 0 ; i < numOidMaps ; ++i ){ + if( !strcasecmp( dnPair.key, oidmap[i].oid ) ) { + mappedPart = oidmap[i].name; + break; + } + } + result.append( mappedPart ); + result.append( "=" ); + result.append( dnPair.value ); +} + +static int +add_dn_parts( QCString& result, struct CryptPlug::DnPair* dn, const char* part ) +{ + int any = 0; + + if( dn ) { + for(; dn->key; ++dn ) { + if( !strcmp( dn->key, part ) ) { + if( any ) + result.append( "," ); + add_dn_part( result, *dn ); + any = 1; + } + } + } + return any; +} + +static char* +reorder_dn( struct CryptPlug::DnPair *dn, + char** attrOrder = 0, + const char* unknownAttrsHandling = 0 ) +{ + struct CryptPlug::DnPair *dnOrg = dn; + + /* note: The must parts are: CN, L, OU, O, C */ + const char* defaultpart[] = { + "CN", "S", "SN", "GN", "T", "UID", + "MAIL", "EMAIL", "MOBILE", "TEL", "FAX", "STREET", + "L", "PC", "SP", "ST", + "OU", + "O", + "C", + NULL + }; + const char** stdpart = attrOrder ? ((const char**)attrOrder) : defaultpart; + int any=0, any2=0, found_X_=0, i; + QCString result; + QCString resultUnknowns; + + /* find and save the non-standard parts in their original order */ + if( dn ){ + for(; dn->key; ++dn ) { + for( i = 0; stdpart[i]; ++i ) { + if( !strcmp( dn->key, stdpart[i] ) ) { + break; + } + } + if( !stdpart[i] ) { + if( any2 ) + resultUnknowns.append( "," ); + add_dn_part( resultUnknowns, *dn ); + any2 = 1; + } + } + dn = dnOrg; + } + + /* prepend the unknown attrs if desired */ + if( unknownAttrsHandling && + !strcmp(unknownAttrsHandling, "PREFIX") + && *resultUnknowns ){ + result.append( resultUnknowns ); + any = 1; + }else{ + any = 0; + } + + /* add standard parts */ + for( i = 0; stdpart[i]; ++i ) { + dn = dnOrg; + if( any ) { + result.append( "," ); + } + if( any2 && + !strcmp(stdpart[i], "_X_") && + unknownAttrsHandling && + !strcmp(unknownAttrsHandling, "INFIX") ){ + if ( !resultUnknowns.isEmpty() ) { + result.append( resultUnknowns ); + any = 1; + } + found_X_ = 1; + }else{ + any = add_dn_parts( result, dn, stdpart[i] ); + } + } + + /* append the unknown attrs if desired */ + if( !unknownAttrsHandling || + !strcmp(unknownAttrsHandling, "POSTFIX") || + ( !strcmp(unknownAttrsHandling, "INFIX") && !found_X_ ) ){ + if( !resultUnknowns.isEmpty() ) { + if( any ){ + result.append( "," ); + } + result.append( resultUnknowns ); + } + } + + char* cResult = (char*)xmalloc( (result.length()+1)*sizeof(char) ); + if( result.isEmpty() ) + *cResult = 0; + else + strcpy( cResult, result ); + return cResult; +} + +GpgME::ImportResult CryptPlug::importCertificateFromMem( const char* data, size_t length ) +{ + using namespace GpgME; + + std::auto_ptr<Context> context( Context::createForProtocol( mProtocol ) ); + if ( !context.get() ) + return ImportResult(); + + Data keydata( data, length, false ); + if ( keydata.isNull() ) + return ImportResult(); + + return context->importKeys( keydata ); +} + + +/* == == == == == == == == == == == == == == == == == == == == == == == == == + == == + == Continuation of CryptPlug code == + == == +== == == == == == == == == == == == == == == == == == == == == == == == == */ + +// these are from gpgme-0.4.3: +static gpgme_sig_stat_t +sig_stat_from_status( gpgme_error_t err ) +{ + switch ( gpg_err_code(err) ) { + case GPG_ERR_NO_ERROR: + return GPGME_SIG_STAT_GOOD; + case GPG_ERR_BAD_SIGNATURE: + return GPGME_SIG_STAT_BAD; + case GPG_ERR_NO_PUBKEY: + return GPGME_SIG_STAT_NOKEY; + case GPG_ERR_NO_DATA: + return GPGME_SIG_STAT_NOSIG; + case GPG_ERR_SIG_EXPIRED: + return GPGME_SIG_STAT_GOOD_EXP; + case GPG_ERR_KEY_EXPIRED: + return GPGME_SIG_STAT_GOOD_EXPKEY; + default: + return GPGME_SIG_STAT_ERROR; + } +} + + +static gpgme_sig_stat_t +intersect_stati( gpgme_signature_t first ) +{ + if ( !first ) + return GPGME_SIG_STAT_NONE; + gpgme_sig_stat_t result = sig_stat_from_status( first->status ); + for ( gpgme_signature_t sig = first->next ; sig ; sig = sig->next ) + if ( sig_stat_from_status( sig->status ) != result ) + return GPGME_SIG_STAT_DIFF; + return result; +} + +static const char* +sig_status_to_string( gpgme_sig_stat_t status ) +{ + const char *result; + + switch (status) { + case GPGME_SIG_STAT_NONE: + result = "Oops: Signature not verified"; + break; + case GPGME_SIG_STAT_NOSIG: + result = "No signature found"; + break; + case GPGME_SIG_STAT_GOOD: + result = "Good signature"; + break; + case GPGME_SIG_STAT_BAD: + result = "BAD signature"; + break; + case GPGME_SIG_STAT_NOKEY: + result = "No public key to verify the signature"; + break; + case GPGME_SIG_STAT_ERROR: + result = "Error verifying the signature"; + break; + case GPGME_SIG_STAT_DIFF: + result = "Different results for signatures"; + break; + default: + result = "Error: Unknown status"; + break; + } + + return result; +} + +// WARNING: if you fix a bug here, you have to likely fix it in the +// gpgme 0.3 version below, too! +static +void obtain_signature_information( gpgme_ctx_t ctx, + gpgme_sig_stat_t & overallStatus, + struct CryptPlug::SignatureMetaData* sigmeta, + char** attrOrder, + const char* unknownAttrsHandling, + bool * signatureFound=0 ) +{ + gpgme_error_t err; + unsigned long sumGPGME; + SigStatusFlags sumPlug; + struct CryptPlug::DnPair* a; + int sig_idx=0; + + assert( ctx ); + assert( sigmeta ); + + sigmeta->extended_info = 0; + gpgme_verify_result_t result = gpgme_op_verify_result( ctx ); + if ( !result ) + return; + for ( gpgme_signature_t signature = result->signatures ; signature ; signature = signature->next, ++sig_idx ) { + void* alloc_return = realloc( sigmeta->extended_info, + sizeof( CryptPlug::SignatureMetaDataExtendedInfo ) + * ( sig_idx + 1 ) ); + if ( !alloc_return ) + break; + sigmeta->extended_info = (CryptPlug::SignatureMetaDataExtendedInfo*)alloc_return; + + /* shorthand notation :) */ + CryptPlug::SignatureMetaDataExtendedInfo & this_info = sigmeta->extended_info[sig_idx]; + + /* clear the data area */ + memset( &this_info, 0, sizeof (CryptPlug::SignatureMetaDataExtendedInfo) ); + + /* the creation time */ + if ( signature->timestamp ) { + this_info.creation_time = (tm*)malloc( sizeof( struct tm ) ); + if ( this_info.creation_time ) { + struct tm * ctime_val = localtime( (time_t*)&signature->timestamp ); + memcpy( this_info.creation_time, + ctime_val, sizeof( struct tm ) ); + } + } + + /* the extended signature verification status */ + sumGPGME = signature->summary; + fprintf( stderr, "gpgmeplug checkMessageSignature status flags: %lX\n", sumGPGME ); + /* translate GPGME status flags to common CryptPlug status flags */ + sumPlug = 0; +#define convert(X) if ( sumGPGME & GPGME_SIGSUM_##X ) sumPlug |= SigStat_##X + convert(VALID); + convert(GREEN); + convert(RED); + convert(KEY_REVOKED); + convert(KEY_EXPIRED); + convert(SIG_EXPIRED); + convert(KEY_MISSING); + convert(CRL_MISSING); + convert(CRL_TOO_OLD); + convert(BAD_POLICY); + convert(SYS_ERROR); +#undef convert + if( sumGPGME && !sumPlug ) + sumPlug = SigStat_NUMERICAL_CODE | sumGPGME; + this_info.sigStatusFlags = sumPlug; + + /* extract finger print */ + if ( signature->fpr ) + storeNewCharPtr( &this_info.fingerprint, signature->fpr ); + + /* validity */ + this_info.validity = GPGME_VALIDITY_UNKNOWN; + + /* sig key data */ + gpgme_key_t key = 0; + // PENDING(marc) if this is deprecated, how shall we get at all + // the infos below? + err = gpgme_get_sig_key (ctx, sig_idx, &key); + + if ( !err && key ) { + const char* attr_string; + unsigned long attr_ulong; + + /* extract key identidy */ + attr_string = key->subkeys ? key->subkeys->keyid : 0 ; + if ( attr_string ) + storeNewCharPtr( &this_info.keyid, attr_string ); + + /* pubkey algorithm */ + attr_string = key->subkeys ? gpgme_pubkey_algo_name( key->subkeys->pubkey_algo ) : 0 ; + if (attr_string != 0) + storeNewCharPtr( &this_info.algo, attr_string ); + attr_ulong = key->subkeys ? key->subkeys->pubkey_algo : 0 ; + this_info.algo_num = attr_ulong; + + /* extract key validity */ + attr_ulong = key->uids ? key->uids->validity : 0 ; + this_info.validity = attr_ulong; + + /* extract user id, according to the documentation it's representable + * as a number, but it seems that it also has a string representation + */ + attr_string = key->uids ? key->uids->uid : 0 ; + if (attr_string != 0) { + a = parse_dn( (const unsigned char*)attr_string ); + this_info.userid = reorder_dn( a, attrOrder, unknownAttrsHandling ); + } + + attr_ulong = 0; + this_info.userid_num = attr_ulong; + + /* extract the length */ + this_info.keylen = key->subkeys ? key->subkeys->length : 0 ; + + /* extract the creation time of the key */ + attr_ulong = key->subkeys ? key->subkeys->timestamp : 0 ; + this_info.key_created = attr_ulong; + + /* extract the expiration time of the key */ + attr_ulong = key->subkeys ? key->subkeys->expires : 0 ; + this_info.key_expires = attr_ulong; + + /* extract user name */ + attr_string = key->uids ? key->uids->name : 0 ; + if (attr_string != 0) { + a = parse_dn( (const unsigned char*)attr_string ); + this_info.name = reorder_dn( a, attrOrder, unknownAttrsHandling ); + } + + /* extract email(s) */ + this_info.emailCount = 0; + this_info.emailList = 0; + for ( gpgme_user_id_t uid = key->uids ; uid ; uid = uid->next ) { + attr_string = uid->email; + if ( attr_string && *attr_string) { + fprintf( stderr, "gpgmeplug checkMessageSignature found email: %s\n", attr_string ); + if( !this_info.emailCount ) + alloc_return = malloc( sizeof( char*) ); + else + alloc_return = realloc( this_info.emailList, + sizeof( char*) + * (this_info.emailCount + 1) ); + if( alloc_return ) { + this_info.emailList = (char**)alloc_return; + storeNewCharPtr( &( this_info.emailList[ this_info.emailCount ] ), + attr_string ); + ++this_info.emailCount; + } + } + } + if( !this_info.emailCount ) + fprintf( stderr, "gpgmeplug checkMessageSignature found NO EMAIL\n" ); + + /* extract the comment */ + attr_string = key->uids ? key->uids->comment : 0 ; + if (attr_string != 0) + storeNewCharPtr( &this_info.comment, attr_string ); + } + + gpgme_sig_stat_t status = sig_stat_from_status( signature->status ); + const char* sig_status = sig_status_to_string( status ); + storeNewCharPtr( &this_info.status_text, sig_status ); + } + sigmeta->extended_info_count = sig_idx; + overallStatus = intersect_stati( result->signatures ); + sigmeta->status_code = overallStatus; + storeNewCharPtr( &sigmeta->status, sig_status_to_string( overallStatus ) ); + if ( signatureFound ) + *signatureFound = ( overallStatus != GPGME_SIG_STAT_NONE ); +} + +bool CryptPlug::checkMessageSignature( char** cleartext, + const char* signaturetext, + bool signatureIsBinary, + int signatureLen, + struct CryptPlug::SignatureMetaData* sigmeta, + char** attrOrder, + const char* unknownAttrsHandling ) +{ + gpgme_ctx_t ctx; + gpgme_sig_stat_t status = GPGME_SIG_STAT_NONE; + gpgme_data_t datapart, sigpart; + char* rClear = 0; + size_t clearLen; + bool isOpaqueSigned; + + if( !cleartext ) { + if( sigmeta ) + storeNewCharPtr( &sigmeta->status, + __GPGMEPLUG_ERROR_CLEARTEXT_IS_ZERO ); + + return false; + } + + isOpaqueSigned = !*cleartext; + + gpgme_new( &ctx ); + gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL); + gpgme_set_armor (ctx, signatureIsBinary ? 0 : 1); + /* gpgme_set_textmode (ctx, signatureIsBinary ? 0 : 1); */ + + if( isOpaqueSigned ) + gpgme_data_new( &datapart ); + else + gpgme_data_new_from_mem( &datapart, *cleartext, + strlen( *cleartext ), 1 ); + + gpgme_data_new_from_mem( &sigpart, + signaturetext, + signatureIsBinary + ? signatureLen + : strlen( signaturetext ), + 1 ); + + if ( isOpaqueSigned ) + gpgme_op_verify( ctx, sigpart, 0, datapart ); + else + gpgme_op_verify( ctx, sigpart, datapart, 0 ); + + if( isOpaqueSigned ) { + rClear = gpgme_data_release_and_get_mem( datapart, &clearLen ); + *cleartext = (char*)malloc( clearLen + 1 ); + if( *cleartext ) { + if( clearLen ) + strncpy(*cleartext, rClear, clearLen ); + (*cleartext)[clearLen] = '\0'; + } + free( rClear ); + } + else + gpgme_data_release( datapart ); + + gpgme_data_release( sigpart ); + + obtain_signature_information( ctx, status, sigmeta, + attrOrder, unknownAttrsHandling ); + + gpgme_release( ctx ); + return ( status == GPGME_SIG_STAT_GOOD ); +} + +bool CryptPlug::decryptAndCheckMessage( const char* ciphertext, + bool cipherIsBinary, + int cipherLen, + const char** cleartext, + const char* /*certificate*/, + bool* signatureFound, + struct CryptPlug::SignatureMetaData* sigmeta, + int* errId, + char** errTxt, + char** attrOrder, + const char* unknownAttrsHandling ) +{ + gpgme_ctx_t ctx; + gpgme_error_t err; + gpgme_decrypt_result_t decryptresult; + gpgme_data_t gCiphertext, gPlaintext; + gpgme_sig_stat_t sigstatus = GPGME_SIG_STAT_NONE; + size_t rCLen = 0; + char* rCiph = 0; + bool bOk = false; + + if( !ciphertext ) + return false; + + err = gpgme_new (&ctx); + gpgme_set_protocol (ctx, GPGMEPLUG_PROTOCOL); + + gpgme_set_armor (ctx, cipherIsBinary ? 0 : 1); + /* gpgme_set_textmode (ctx, cipherIsBinary ? 0 : 1); */ + + /* + gpgme_data_new_from_mem( &gCiphertext, ciphertext, + 1+strlen( ciphertext ), 1 ); */ + gpgme_data_new_from_mem( &gCiphertext, + ciphertext, + cipherIsBinary + ? cipherLen + : strlen( ciphertext ), + 1 ); + + gpgme_data_new( &gPlaintext ); + + err = gpgme_op_decrypt_verify( ctx, gCiphertext, gPlaintext ); + gpgme_data_release( gCiphertext ); + + if( err ) { + fprintf( stderr, "\ngpgme_op_decrypt_verify() returned this error code: %i\n\n", err ); + if( errId ) + *errId = err; + if( errTxt ) { + const char* _errTxt = gpgme_strerror( err ); + *errTxt = (char*)malloc( strlen( _errTxt ) + 1 ); + if( *errTxt ) + strcpy(*errTxt, _errTxt ); + } + gpgme_data_release( gPlaintext ); + gpgme_release( ctx ); + return bOk; + } + decryptresult = gpgme_op_decrypt_result( ctx ); + + bool bWrongKeyUsage = false; +#ifdef HAVE_GPGME_WRONG_KEY_USAGE + if( decryptresult && decryptresult->wrong_key_usage ) + bWrongKeyUsage = true; +#endif + + if( bWrongKeyUsage ) { + if( errId ) + *errId = CRYPTPLUG_ERR_WRONG_KEY_USAGE; // report the wrong key usage + } + + rCiph = gpgme_data_release_and_get_mem( gPlaintext, &rCLen ); + + *cleartext = (char*)malloc( rCLen + 1 ); + if( *cleartext ) { + if( rCLen ) { + bOk = true; + strncpy((char*)*cleartext, rCiph, rCLen ); + } + ((char*)(*cleartext))[rCLen] = 0; + } + free( rCiph ); + + obtain_signature_information( ctx, sigstatus, sigmeta, + attrOrder, unknownAttrsHandling, + signatureFound ); + + gpgme_release( ctx ); + return bOk; +} + diff --git a/certmanager/lib/cryptplug.h b/certmanager/lib/cryptplug.h new file mode 100644 index 000000000..081702a7a --- /dev/null +++ b/certmanager/lib/cryptplug.h @@ -0,0 +1,954 @@ +/* -*- Mode: C++ -*- + + this is a C++-ification of: + CRYPTPLUG - an independent cryptography plug-in API + + Copyright (C) 2001,2004 Klarälvdalens Datakonsult AB + + CRYPTPLUG is free software; you can redistribute it and/or modify + it under the terms of GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + CRYPTPLUG is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +*/ + +#ifndef CRYPTPLUG_H +#define CRYPTPLUG_H + +#include <stdlib.h> + +#include <gpgmepp/context.h> +#include <gpgme.h> // need it for gpgme_protocol_t :( +#include <kdepimmacros.h> + +namespace GpgME { + class ImportResult; +} + +/*! \file cryptplug.h + \brief Common API header for CRYPTPLUG. + + CRYPTPLUG is an independent cryptography plug-in API + developed for Sphinx-enabeling KMail and Mutt. + + CRYPTPLUG was designed for the Aegypten project, but it may + be used by 3rd party developers as well to design pluggable + crypto backends for the above mentioned MUAs. + + \note All string parameters appearing in this API are to be + interpreted as UTF-8 encoded. + + \see pgpplugin.c + \see gpgplugin.c +*/ + +/*! \defgroup groupGeneral Loading and Unloading the Plugin, General Functionality + + The functions in this section are used for loading and + unloading plugins. Note that the actual locating of the plugin + and the loading and unloading of the dynamic library is not + covered here; this is MUA-specific code for which support code + might already exist in the programming environments. +*/ + +/*! \defgroup groupDisplay Graphical Display Functionality + + The functions in this section return stationery that the + MUAs can use in order to display security functionality + graphically. This can be toolbar icons, shortcuts, tooltips, + etc. Not all MUAs will use all this functionality. +*/ + +/*! \defgroup groupConfig Configuration Support + + The functions in this section provide the necessary + functionality to configure the security functionality as well + as to query configuration settings. Since all configuration + settings will not be saved with the plugin, but rather with + the MUA, there are also functions to set configuration + settings programmatically; these will be used on startup of + the plugin when the MUA transfers the configuration values it + has read into the plugin. Usually, the functions to query and + set the configuration values are not needed for anything but + saving to and restoring from configuration files. +*/ + + +/*! \defgroup groupConfigSign Signature Configuration + \ingroup groupConfig + + The functions in this section provide the functionality + to configure signature handling and set and query the + signature configuration. +*/ + +/*! \defgroup groupConfigCrypt Encryption Configuration + \ingroup groupConfig + + The functions in this section provide the functionality + to configure encryption handling and set and query the + encryption configuration. + + \note Whenever the term <b> encryption</b> is used here, + it is supposed to mean both encryption and decryption, + unless otherwise specified. +*/ + +/*! \defgroup groupConfigDir Directory Service Configuration + \ingroup groupConfig + + This section contains messages for configuring the + directory service. +*/ + + +/*! \defgroup groupCertHand Certificate Handling + + The following methods are used to maintain and query certificates. +*/ + + +/*! \defgroup groupSignCryptAct Signing and Encrypting Actions + + This section describes methods and structures + used for signing and/or encrypting your mails. +*/ + + +/*! \defgroup groupSignAct Signature Actions + \ingroup groupSignCryptAct + + This section describes methods that are used for working + with signatures. +*/ + +/*! \defgroup groupCryptAct Encryption and Decryption + \ingroup groupSignCryptAct + + The following methods are used to encrypt and decrypt + email messages. +*/ + +/*! \defgroup groupCertAct Certificate Handling Actions + + The functions in this section provide local certificate management. +*/ + +/*! \defgroup groupCRLAct CRL Handling Actions + + This section describes functions for managing CRLs. +*/ + +/*! \defgroup groupAdUsoInterno Important functions to be used by plugin implementors ONLY. + + This section describes functions that have to be used by + plugin implementors but should not be used by plugin users + directly. + + If you are not planning to write your own cryptography + plugin <b>you should ignore this</b> section! +*/ + +/*! \defgroup certList Certificate Info listing functions + */ + +typedef enum { + Feature_undef = 0, + + Feature_SignMessages = 1, + Feature_VerifySignatures = 2, + Feature_EncryptMessages = 3, + Feature_DecryptMessages = 4, + Feature_SendCertificates = 5, + Feature_WarnSignCertificateExpiry = 6, + Feature_WarnSignEmailNotInCertificate = 7, + Feature_PinEntrySettings = 8, + Feature_StoreMessagesWithSigs = 9, + Feature_EncryptionCRLs = 10, + Feature_WarnEncryptCertificateExpiry = 11, + Feature_WarnEncryptEmailNotInCertificate = 12, + Feature_StoreMessagesEncrypted = 13, + Feature_CheckCertificatePath = 14, + Feature_CertificateDirectoryService = 15, + Feature_CRLDirectoryService = 16, + Feature_CertificateInfo = 17 +} Feature; + +/* dummy values */ +typedef enum { + PinRequest_undef = 0, + + PinRequest_Always = 1, + PinRequest_WhenAddingCerts = 2, + PinRequest_AlwaysWhenSigning = 3, + PinRequest_OncePerSession = 4, + PinRequest_AfterMinutes = 5 +} PinRequests; + + +typedef enum { + SignatureCompoundMode_undef = 0, + + SignatureCompoundMode_Opaque = 1, + SignatureCompoundMode_Detached = 2 +} SignatureCompoundMode; + + +typedef enum { + SendCert_undef = 0, + + SendCert_DontSend = 1, + SendCert_SendOwn = 2, + SendCert_SendChainWithoutRoot = 3, + SendCert_SendChainWithRoot = 4 +} SendCertificates; + + +typedef enum { + SignAlg_undef = 0, + + SignAlg_SHA1 = 1 +} SignatureAlgorithm; + + + +typedef enum { + EncryptAlg_undef = 0, + + EncryptAlg_RSA = 1, + EncryptAlg_SHA1 = 2, + EncryptAlg_TripleDES = 3 +} EncryptionAlgorithm; + +typedef enum { + SignEmail_undef = 0, + + SignEmail_SignAll = 1, + SignEmail_Ask = 2, + SignEmail_DontSign = 3 +} SignEmail; + +typedef enum { + EncryptEmail_undef = 0, + + EncryptEmail_EncryptAll = 1, + EncryptEmail_Ask = 2, + EncryptEmail_DontEncrypt = 3 +} EncryptEmail; + +typedef enum { + CertSrc_undef = 0, + + CertSrc_Server = 1, + CertSrc_Local = 2, + CertSrc_ServerLocal = CertSrc_Server | CertSrc_Local +} CertificateSource; + + +/*! \ingroup groupSignAct + \brief Flags used to compose the SigStatusFlags value. + + This status flags are used to compose the SigStatusFlags value + returned in \c SignatureMetaDataExtendedInfo after trying to + verify a signed message part's signature status. + + The normal flags may <b>not</b> be used together with the + special SigStat_NUMERICAL_CODE flag. When finding the special + SigStat_NUMERICAL_CODE flag in a SigStatusFlags value you + can obtain the respective error code number by substracting + the SigStatusFlags value by SigStat_NUMERICAL_CODE: this is + used to transport special status information NOT matching + any of the normal predefined status codes. + + \note to PlugIn developers: Implementations of the CryptPlug API + should try to express their signature states by bit-wise OR'ing + the normal SigStatusFlags values. Using the SigStat_NUMERICAL_CODE + flag should only be used as for exceptional situations where no + other flag(s) could be used. By using the normal status flags your + PlugIn's users will be told an understandable description of the + status - when using (SigStat_NUMERICAL_CODE + internalCode) they + will only be shown the respective code number and have to look + into your PlugIn's manual to learn about it's meaning... +*/ +enum { + SigStat_VALID = 0x0001, /* The signature is fully valid */ + SigStat_GREEN = 0x0002, /* The signature is good. */ + SigStat_RED = 0x0004, /* The signature is bad. */ + SigStat_KEY_REVOKED = 0x0010, /* One key has been revoked. */ + SigStat_KEY_EXPIRED = 0x0020, /* One key has expired. */ + SigStat_SIG_EXPIRED = 0x0040, /* The signature has expired. */ + SigStat_KEY_MISSING = 0x0080, /* Can't verify: key missing. */ + SigStat_CRL_MISSING = 0x0100, /* CRL not available. */ + SigStat_CRL_TOO_OLD = 0x0200, /* Available CRL is too old. */ + SigStat_BAD_POLICY = 0x0400, /* A policy was not met. */ + SigStat_SYS_ERROR = 0x0800, /* A system error occurred. */ + + SigStat_NUMERICAL_CODE = 0x8000 /* An other error occurred. */ +}; +typedef unsigned long SigStatusFlags; + +class CryptPlugWrapper; + +class KDE_EXPORT CryptPlug { + friend class CryptPlugWrapper; +protected: + CryptPlug(); + virtual ~CryptPlug(); + + // these must be set by subclasses: + gpgme_protocol_t GPGMEPLUG_PROTOCOL; + GpgME::Context::Protocol mProtocol; + + /* definitions for signing */ + // 1. opaque signatures (only used for S/MIME) + int GPGMEPLUG_OPA_SIGN_INCLUDE_CLEARTEXT; + int GPGMEPLUG_OPA_SIGN_MAKE_MIME_OBJECT; + int GPGMEPLUG_OPA_SIGN_MAKE_MULTI_MIME; + const char * GPGMEPLUG_OPA_SIGN_CTYPE_MAIN; + const char * GPGMEPLUG_OPA_SIGN_CDISP_MAIN; + const char * GPGMEPLUG_OPA_SIGN_CTENC_MAIN; + const char * GPGMEPLUG_OPA_SIGN_CTYPE_VERSION; + const char * GPGMEPLUG_OPA_SIGN_CDISP_VERSION; + const char * GPGMEPLUG_OPA_SIGN_CTENC_VERSION; + const char * GPGMEPLUG_OPA_SIGN_BTEXT_VERSION; + const char * GPGMEPLUG_OPA_SIGN_CTYPE_CODE; + const char * GPGMEPLUG_OPA_SIGN_CDISP_CODE; + const char * GPGMEPLUG_OPA_SIGN_CTENC_CODE; + const char * GPGMEPLUG_OPA_SIGN_FLAT_PREFIX; + const char * GPGMEPLUG_OPA_SIGN_FLAT_SEPARATOR; + const char * GPGMEPLUG_OPA_SIGN_FLAT_POSTFIX; + // 2. detached signatures (used for S/MIME and for OpenPGP) + int GPGMEPLUG_DET_SIGN_INCLUDE_CLEARTEXT; + int GPGMEPLUG_DET_SIGN_MAKE_MIME_OBJECT; + int GPGMEPLUG_DET_SIGN_MAKE_MULTI_MIME; + const char * GPGMEPLUG_DET_SIGN_CTYPE_MAIN; + const char * GPGMEPLUG_DET_SIGN_CDISP_MAIN; + const char * GPGMEPLUG_DET_SIGN_CTENC_MAIN; + const char * GPGMEPLUG_DET_SIGN_CTYPE_VERSION; + const char * GPGMEPLUG_DET_SIGN_CDISP_VERSION; + const char * GPGMEPLUG_DET_SIGN_CTENC_VERSION; + const char * GPGMEPLUG_DET_SIGN_BTEXT_VERSION; + const char * GPGMEPLUG_DET_SIGN_CTYPE_CODE; + const char * GPGMEPLUG_DET_SIGN_CDISP_CODE; + const char * GPGMEPLUG_DET_SIGN_CTENC_CODE; + const char * GPGMEPLUG_DET_SIGN_FLAT_PREFIX; + const char * GPGMEPLUG_DET_SIGN_FLAT_SEPARATOR; + const char * GPGMEPLUG_DET_SIGN_FLAT_POSTFIX; + // 3. common definitions for opaque and detached signing + int __GPGMEPLUG_SIGNATURE_CODE_IS_BINARY; + + /* definitions for encoding */ + int GPGMEPLUG_ENC_INCLUDE_CLEARTEXT; + int GPGMEPLUG_ENC_MAKE_MIME_OBJECT; + int GPGMEPLUG_ENC_MAKE_MULTI_MIME; + const char * GPGMEPLUG_ENC_CTYPE_MAIN; + const char * GPGMEPLUG_ENC_CDISP_MAIN; + const char * GPGMEPLUG_ENC_CTENC_MAIN; + const char * GPGMEPLUG_ENC_CTYPE_VERSION; + const char * GPGMEPLUG_ENC_CDISP_VERSION; + const char * GPGMEPLUG_ENC_CTENC_VERSION; + const char * GPGMEPLUG_ENC_BTEXT_VERSION; + const char * GPGMEPLUG_ENC_CTYPE_CODE; + const char * GPGMEPLUG_ENC_CDISP_CODE; + const char * GPGMEPLUG_ENC_CTENC_CODE; + const char * GPGMEPLUG_ENC_FLAT_PREFIX; + const char * GPGMEPLUG_ENC_FLAT_SEPARATOR; + const char * GPGMEPLUG_ENC_FLAT_POSTFIX; + int __GPGMEPLUG_ENCRYPTED_CODE_IS_BINARY; + // end-of(these must be set by subclasses) + +public: + +#define CRYPTPLUG_CERT_DOES_NEVER_EXPIRE 365000 +#define CRYPTPLUG_ERR_WRONG_KEY_USAGE 0x7070 + +/*! \ingroup groupGeneral + \brief This function sets up all internal structures. + + Plugins that need no initialization should provide an empty + implementation. The method returns \c true if the initialization was + successful and \c false otherwise. Before this function is called, + no other plugin functions should be called; the behavior is + undefined in this case. + + \note This function <b>must</b> be implemented by each plug-in using + this API specification. +*/ +bool initialize( void ); + +/*! \ingroup groupGeneral + \brief This function frees all internal structures. + + Plugins that do not keep any internal structures should provide an + empty implementation. After this function has been called, + no other plugin functions should be called; the behavior is + undefined in this case. + + \note This function <b>must</b> be implemented by each plug-in using + this API specification. +*/ +//void deinitialize( void ); + +/*! \ingroup groupGeneral + \brief This function returns \c true if the + specified feature is available in the plugin, and + \c false otherwise. + + Not all plugins will support all features; a complete Sphinx + implementation will support all features contained in the enum, + however. + + \note This function <b>must</b> be implemented by each plug-in using + this API specification. +*/ +bool hasFeature( ::Feature ); + +/*! \ingroup groupSignCryptAct + \brief Information record returned by signing and by encrypting + functions - this record should be used together with a + corresponding \c free_StructuringInfo() function call. + + Use this information to compose a MIME object containing signed + and/or encrypted content (or to build a text frame around your + flat non-MIME message body, resp.) + + <b>If</b> value returned in \c makeMimeObject is <b>TRUE</b> the + text strings returned in \c contentTypeMain and \c contentDispMain + and \c contentTEncMain (and, if required, \c content[..]Version and + \c bodyTextVersion and \c content[..]Sig) should be used to compose + a respective MIME object.<br> + If <b>FALSE</b> the texts returned in \c flatTextPrefix and + \c flatTextSeparator and \c flatTextPostfix are to be used instead.<br> + Allways <b>either</b> the \c content[..] and \c bodyTextVersion + parameters <b>or</b> the \c flatText[..] parameters are holding + valid data - never both of them may be used simultaneously + as plugins will just ignore the parameters not matching their + \c makeMimeObject setting. + + When creating your MIME object please observe these common rules: + \li Parameters named \c contentType[..] and \c contentDisp[..] and + \c contentTEnc[..] will return the values for the respective MIME + headers 'Content-Type' and 'Content-Disposition' and + 'Content-Transfer-Encoding'. The following applies to these parameters: + \li The relevant MIME part may <b>only</b> be created if the respective + \c contentType[..] parameter is holding a non-zero-length string. If the + \c contentType[..] parameter value is invalid or holding an empty string + the respective \c contentDisp[..] and \c contentTEnc[..] parameters + should be ignored. + \li If the respective \c contentDisp[..] or \c contentTEnc[..] parameter + is NULL or holding a zero-length string it is up to you whether you want + to add the relevant MIME header yourself, but since it in in the + responsibility of the plugin implementors to provide you with all + neccessary 'Content-[..]' header information you should <b>not need</b> + to define them if they are not returned by the signing or encrypting + function - otherwise this may be considered as a bug in the plugin and + you could report the missing MIME header information to the address + returned by the \c bugURL() function. + + If \c makeMultiMime returns FALSE the \c contentTypeMain returned must + not be altered but used to specify a single part mime object holding the + code bloc, e.g. this is used for 'enveloped-data' single part MIME + objects. In this case you should ignore both the \c content[..]Version + and \c content[..]Code parameters. + + If \c makeMultiMime returns TRUE also the following rules apply: + \li If \c includeCleartext is TRUE you should include the cleartext + as first part of our multipart MIME object, typically this is TRUE + when signing mails but FALSE when encrypting. + \li The \c contentTypeMain returned typically starts with + "multipart/" while providing a "protocol" and a "micalg" parameter: just + add an appropriate \c "; boundary=[your \c boundary \c string]" to get + the complete Content-Type value to be used for the MIME object embedding + both the signed part and the signature part (or - in case of + encrypting - the version part and the code part, resp.). + \li If \c contentTypeVersion is holding a non-zero-length string an + additional MIME part must added immediately before the code part, this + version part's MIME headers must have the unaltered values of + \c contentTypeVersion and (if they are holding non-zero-length strings) + \c contentDispVersion and \c contentTEncVersion, the unaltered contents + of \c bodyTextVersion must be it's body. + \li The value returned in \c contentTypeCode is specifying the complete + Content-Type to be used for this multipart MIME object's signature part + (or - in case of encrypting - for the code part following after the + version part, resp.), you should not add/change/remove anything here + but just use it's unaltered value for specifying the Content-Type header + of the respective MIME part. + \li The same applies to the \c contentDispCode value: just use it's + unaltered value to specify the Content-Disposition header entry of + the respective MIME part. + \li The same applies to the \c contentTEncCode value: just use it's + unaltered value to specify the Content-Transfer-Encoding header of + the respective MIME part. + + <b>If</b> value returned in \c makeMimeObject is <b>FALSE</b> the + text strings returned in \c flatTextPrefix and \c flatTextPostfix + should be used to build a frame around the cleartext and the code + bloc holding the signature (or - in case of encrypting - the encoded + data bloc, resp.).<br> + If \c includeCleartext is TRUE this frame should also include the + cleartext as first bloc, this bloc should be divided from the code bloc + by the contents of \c flatTextSeparator - typically this is used for + signing but not when encrypting.<br> + If \c includeCleartext is FALSE you should ignore both the cleartext + and the \c flatTextSeparator parameter. + + <b>How to use StructuringInfo data in your program:</b> + \li To compose a signed message please act as described below. + \li For constructing an encrypted message just replace the + \c signMessage() call by the respective \c encryptMessage() call + and then proceed exactly the same way. + \li In any case make <b>sure</b> to free your \c ciphertext <b>and</b> + to call \c free_StructuringInfo() when you are done with processing + the data returned by the signing (or encrypting, resp.) function. + +\verbatim + + char* ciphertext; + StructuringInfo structInf; + + if( ! signMessage( cleartext, &ciphertext, certificate, + &structuring ) ) { + + myErrorDialog( "Error: could not sign the message!" ); + + } else { + if( structInf.makeMimeObject ) { + + // Build the main MIME object. + // This is done by + // using the header values returned in + // structInf.contentTypeMain and in + // structInf.contentDispMain and in + // structInf.contentTEncMain. + .. + + if( ! structInf.makeMultiMime ) { + + // Build the main MIME object's body. + // This is done by + // using the code bloc returned in + // ciphertext. + .. + + } else { + + // Build the encapsulated MIME parts. + if( structInf.includeCleartext ) { + + // Build a MIME part holding the cleartext. + // This is done by + // using the original cleartext's headers and by + // taking it's original body text. + .. + + } + if( structInf.contentTypeVersion + && 0 < strlen( structInf.contentTypeVersion ) ) { + + // Build a MIME part holding the version information. + // This is done by + // using the header values returned in + // structInf.contentTypeVersion and + // structInf.contentDispVersion and + // structInf.contentTEncVersion and by + // taking the body contents returned in + // structInf.bodyTextVersion. + .. + + } + if( structInf.contentTypeCode + && 0 < strlen( structInf.contentTypeCode ) ) { + + // Build a MIME part holding the code information. + // This is done by + // using the header values returned in + // structInf.contentTypeCode and + // structInf.contentDispCode and + // structInf.contentTEncCode and by + // taking the body contents returned in + // ciphertext. + .. + + } else { + + // Plugin error! + myErrorDialog( "Error: Cryptography plugin returned a main" + "Content-Type=Multipart/.. but did not " + "specify the code bloc's Content-Type header." + "\nYou may report this bug:" + "\n" + cryptplug.bugURL() ); + } + } + } else { + + // Build a plain message body + // based on the values returned in structInf. + // Note: We do _not_ insert line breaks between the parts since + // it is the plugin job to provide us with ready-to-use + // texts containing all neccessary line breaks. + strcpy( myMessageBody, structInf.plainTextPrefix ); + if( structInf.includeCleartext ) { + strcat( myMessageBody, cleartext ); + strcat( myMessageBody, structInf.plainTextSeparator ); + } + strcat( myMessageBody, *ciphertext ); + strcat( myMessageBody, structInf.plainTextPostfix ); + } + + // free the memory that was allocated + // for the ciphertext + free( ciphertext ); + + // free the memory that was allocated + // for our StructuringInfo's char* members + free_StructuringInfo( &structuring ); + } + +\endverbatim + + \note Make sure to call \c free_StructuringInfo() when you are done + with processing the StructuringInfo data! + + \see free_StructuringInfo + \see signMessage, encryptMessage, encryptAndSignMessage +*/ +struct StructuringInfo { + bool includeCleartext; /*!< specifies whether we should include the + cleartext as first part of our multipart + MIME object (or - for non-MIME + messages - as flat text to be set before + the ciphertext, resp.), typically this + is TRUE when signing mails but FALSE + when encrypting<br> + (this parameter is relevant no matter + whether \c makeMimeObject is TRUE or + FALSE) */ + bool makeMimeObject; /*!< specifies whether we should create a MIME + object or a flat text message body */ + /* the following are used for MIME messages only */ + bool makeMultiMime; /*!< specifies whether we should create a + 'Multipart' MIME object or a single part + object, if FALSE only \c contentTypeMain, + \c contentDispMain and \c contentTEncMain + may be used and all other parameters have + to be ignored<br> + (ignore this parameter if \c makeMimeObject + is FALSE) */ + char* contentTypeMain; /*!< value of the main 'Content-Type' + header<br> + (ignore this parameter if \c makeMimeObject + is FALSE) */ + char* contentDispMain; /*!< value of the main 'Content-Disposition' + header<br> + (ignore this parameter if \c makeMimeObject + is FALSE) */ + char* contentTEncMain; /*!< value of the main + 'Content-TransferEncoding' header<br> + (ignore this parameter if \c makeMimeObject + is FALSE) */ + char* contentTypeVersion; /*!< 'Content-Type' of the additional version + part that might preceed the code part - + if NULL or zero length no version part + must be created<br> + (ignore this parameter if either + \c makeMimeObject or \c makeMultiMime + is FALSE) */ + char* contentDispVersion; /*!< 'Content-Disposition' of the additional + preceeding the code part (only valid if + \c contentTypeVersion holds a + non-zero-length string)<br> + (ignore this parameter if either + \c makeMimeObject or \c makeMultiMime + is FALSE or if \c contentTypeVersion does + not return a non-zero-length string) */ + char* contentTEncVersion; /*!< 'Content-Transfer-Encoding' of the + additional version part (only valid if + \c contentTypeVersion holds a + non-zero-length string)<br> + (ignore this parameter if either + \c makeMimeObject or \c makeMultiMime + is FALSE or if \c contentTypeVersion does + not return a non-zero-length string) */ + char* bodyTextVersion; /*!< body text of the additional version part + (only valid if \c contentTypeVersion + holds a non-zero-length string)<br> + (ignore this parameter if either + \c makeMimeObject or \c makeMultiMime + is FALSE or if \c contentTypeVersion does + not return a non-zero-length string) */ + char* contentTypeCode; /*!< 'Content-Type' of the code part holding + the signature code (or the encrypted + data, resp.)<br> + (ignore this parameter if either + \c makeMimeObject or \c makeMultiMime + is FALSE) */ + char* contentDispCode; /*!< 'Content-Disposition' of the code part<br> + (ignore this parameter if either + \c makeMimeObject or \c makeMultiMime + is FALSE or if \c contentTypeCode does + not return a non-zero-length string) */ + char* contentTEncCode; /*!< 'Content-Type' of the code part<br> + (ignore this parameter if either + \c makeMimeObject or \c makeMultiMime + is FALSE or if \c contentTypeCode does + not return a non-zero-length string) */ + /* the following are used for flat non-MIME messages only */ + char* flatTextPrefix; /*!< text to preceed the main text (or the + code bloc containing the encrypted main + text, resp.)<br> + (ignore this parameter if + \c makeMimeObject is TRUE) */ + char* flatTextSeparator; /*!< text to be put between the main text and + the signature code bloc (not used when + encrypting)<br> + (ignore this parameter if + \c makeMimeObject is TRUE or if + \c includeCleartext is FALSE) */ + char* flatTextPostfix; /*!< text to follow the signature code bloc + (or the encrypted data bloc, resp.)<br> + (ignore this parameter if + \c makeMimeObject is TRUE) */ +}; + + +/*! \ingroup groupAdUsoInterno + \brief If you are not planning to write your own cryptography + plugin <b>you should ignore this</b> function! + + Usage of this function is depreciated for plugin users but highly + recommended for plugin implementors since this is an internal + function for initializing all char* members of a \c StructuringInfo + struct.<br> + This function <b>must</b> be called in <b>any</b> plugin's + implementations of the following functions: + + \c signMessage() <br> + \c encryptMessage() <br> + \c encryptAndSignMessage() + + Calling this function makes sure the corresponding + \c free_StructuringInfo() calls which will be embedded by + your plugin's users into their code will be able to + determine which of the char* members belonging to the + respective's StructuringInfo had been allocated memory + for during previous signing or encrypting actions. + + \see free_StructuringInfo, StructuringInfo + \see signMessage, encryptMessage, encryptAndSignMessage +*/ + inline void init_StructuringInfo( struct StructuringInfo* s ) + { + if( ! s ) return; + + s->includeCleartext = false; + + s->makeMimeObject = false; + s->makeMultiMime = false; + + s->contentTypeMain = 0; + s->contentDispMain = 0; + s->contentTEncMain = 0; + + s->contentTypeVersion = 0; + s->contentDispVersion = 0; + s->contentTEncVersion = 0; + s->bodyTextVersion = 0; + + s->contentTypeCode = 0; + s->contentDispCode = 0; + s->contentTEncCode = 0; + + s->flatTextPrefix = 0; + s->flatTextSeparator = 0; + s->flatTextPostfix = 0; + } + +/*! \ingroup groupSignCryptAct + \brief Important method for freeing all memory that was allocated + for the char* members of a \c StructuringInfo struct - use + this function after <b>each</b> signing or encrypting function + call. + + \note Even when intending to call \c encryptMessage() immediately + after having called \c signMessage() you first <b>must</b> call + the \c free_StructuringInfo() function to make sure all memory is + set free that was allocated for your StructuringInfo's char* members + by the \c signMessage() function! + + \see StructuringInfo +*/ + inline void free_StructuringInfo( struct StructuringInfo* s ) + { + if( ! s ) return; + if( s->contentTypeMain ) free( s->contentTypeMain ); + if( s->contentDispMain ) free( s->contentDispMain ); + if( s->contentTEncMain ) free( s->contentTEncMain ); + if( s->contentTypeVersion ) free( s->contentTypeVersion ); + if( s->contentDispVersion ) free( s->contentDispVersion ); + if( s->contentTEncVersion ) free( s->contentTEncVersion ); + if( s->bodyTextVersion ) free( s->bodyTextVersion ); + if( s->contentTypeCode ) free( s->contentTypeCode ); + if( s->contentDispCode ) free( s->contentDispCode ); + if( s->contentTEncCode ) free( s->contentTEncCode ); + if( s->flatTextPrefix ) free( s->flatTextPrefix ); + if( s->flatTextSeparator ) free( s->flatTextSeparator ); + if( s->flatTextPostfix ) free( s->flatTextPostfix ); + } + + +/*! \ingroup groupSignAct + */ +struct SignatureMetaDataExtendedInfo +{ + struct tm* creation_time; + SigStatusFlags sigStatusFlags; + char* status_text; + char* keyid; + char* fingerprint; + char* algo; + char* userid; + char* name; + char* comment; + char** emailList; + int emailCount; + unsigned long algo_num; + unsigned long validity; + unsigned long userid_num; + unsigned long keylen; + unsigned long key_created; + unsigned long key_expires; +}; + +/*! \ingroup groupSignAct +*/ +struct SignatureMetaData { + char* status; + struct SignatureMetaDataExtendedInfo* extended_info; + int extended_info_count; + int status_code; +}; + +/*! \ingroup groupSignAct + \brief Checks whether the signature of a message is + valid. + + \c cleartext must never be 0 but be a valid pointer. + + If \c *cleartext > 0 then **cleartext specifies the message text + that was signed and \c signaturetext is the signature itself. + + If \c *cleartext == 0 is an empty string then \c signaturetext is + supposed to contain an opaque signed message part. After checking the + data and verifying the signature the cleartext of the message will be + returned in \c cleartext. The user must free the respective memory + ocupied by *cleartext. + + Depending on the configuration, MUAs might not need to use this. + If \c sigmeta is non-null, the + \c SignatureMetaData object pointed to will + contain meta information about the signature after the + function call. +*/ +bool checkMessageSignature( char** cleartext, + const char* signaturetext, + bool signatureIsBinary, + int signatureLen, + struct SignatureMetaData* sigmeta, + char** attrOrder, + const char* unknownAttrsHandling ); + + +/*! \ingroup groupCryptAct + \brief Tries to decrypt an email message + \c ciphertext and returns the decrypted + message in \c cleartext. + + The \c certificate is used for decryption. If + the message could be decrypted, the function returns + \c true, otherwise + \c false. +*/ +bool decryptMessage( const char* ciphertext, + bool cipherIsBinary, + int cipherLen, + const char** cleartext, + const char* certificate, + int* errId, + char** errTxt ); + +/*! \ingroup groupCryptAct + \brief Combines the functionality of + \c checkMessageSignature() and + \c decryptMessage(). + + If \c certificate is \c NULL, + the default certificate will be used. + If \c sigmeta is non-null, the \c SignatureMetaData + object pointed to will contain meta information about + the signature after the function call. +*/ +bool decryptAndCheckMessage( const char* ciphertext, + bool cipherIsBinary, + int cipherLen, + const char** cleartext, + const char* certificate, + bool* signatureFound, + struct SignatureMetaData* sigmeta, + int* errId, + char** errTxt, + char** attrOrder, + const char* unknownAttrsHandling ); + +struct DnPair { + char *key; + char *value; +}; + +struct CertificateInfo { + char** userid; + char* userid_0_org; + char* serial; + char* fingerprint; + + char* issuer_org; + char* issuer_reord; + char* chainid; + + char* caps; + + unsigned long created; + unsigned long expire; + + int secret : 1; + int invalid : 1; + int expired : 1; + int disabled : 1; + + struct DnPair *dnarray; /* parsed values from userid[0] */ +}; + + /*! + Import a certificate from memory. + */ + GpgME::ImportResult importCertificateFromMem( const char* data, size_t length ); +}; // class CryptPlug + +class SMIMECryptPlug : public CryptPlug { +public: + SMIMECryptPlug(); +}; + +class OpenPGPCryptPlug : public CryptPlug { +public: + OpenPGPCryptPlug(); +}; + +#endif /*CRYPTPLUG_H*/ + diff --git a/certmanager/lib/cryptplugfactory.cpp b/certmanager/lib/cryptplugfactory.cpp new file mode 100644 index 000000000..7000d9a90 --- /dev/null +++ b/certmanager/lib/cryptplugfactory.cpp @@ -0,0 +1,119 @@ +/* + cryptplugfactory.cpp + + This file is part of libkleopatra, the KDE key management library + Copyright (c) 2001,2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "cryptplugfactory.h" +#include "cryptplugwrapperlist.h" + +#include <kconfig.h> +#include <klocale.h> +#include <kdebug.h> +#include <kmessagebox.h> +#include <kapplication.h> + +#include <assert.h> + +KMail::CryptPlugFactory * KMail::CryptPlugFactory::mSelf = 0; + +// +// +// KMail::CryptPlugFactory: backwards compat stuff (ugly) +// +// + + +KMail::CryptPlugFactory::CryptPlugFactory() + : Kleo::CryptoBackendFactory(), + mCryptPlugWrapperList( 0 ) +{ + mSelf = this; + + mCryptPlugWrapperList = new CryptPlugWrapperList(); + mCryptPlugWrapperList->setAutoDelete( false ); + updateCryptPlugWrapperList(); +} + +KMail::CryptPlugFactory::~CryptPlugFactory() { + mSelf = 0; + delete mCryptPlugWrapperList; mCryptPlugWrapperList = 0; +} + +KMail::CryptPlugFactory * KMail::CryptPlugFactory::instance() { + if ( !mSelf ) + mSelf = new CryptPlugFactory(); + return mSelf; +} + +CryptPlugWrapper * KMail::CryptPlugFactory::active() const { + if ( smime() && smime()->active() ) + return smime(); + if ( openpgp() && openpgp()->active() ) + return openpgp(); + return 0; +} + +CryptPlugWrapper * KMail::CryptPlugFactory::createForProtocol( const QString & proto ) const { + QString p = proto.lower(); + if ( p == "application/pkcs7-signature" || p == "application/x-pkcs7-signature" ) + return smime(); + if ( p == "application/pgp-signature" || p == "application/x-pgp-signature" ) + return openpgp(); + return 0; +} + +CryptPlugWrapper * KMail::CryptPlugFactory::smime() const { + return mCryptPlugWrapperList->findForLibName( "smime" ); +} + +CryptPlugWrapper * KMail::CryptPlugFactory::openpgp() const { + return mCryptPlugWrapperList->findForLibName( "openpgp" ); +} + +void KMail::CryptPlugFactory::scanForBackends( QStringList * reason ) { + Kleo::CryptoBackendFactory::scanForBackends( reason ); + updateCryptPlugWrapperList(); +} + +void KMail::CryptPlugFactory::updateCryptPlugWrapperList() { + mCryptPlugWrapperList->clear(); + for ( std::vector<Kleo::CryptoBackend*>::const_iterator it = mBackendList.begin() ; it != mBackendList.end() ; ++it ) { + if ( CryptPlugWrapper * w = dynamic_cast<CryptPlugWrapper*>( (*it)->openpgp() ) ) + mCryptPlugWrapperList->append( w ); + if ( CryptPlugWrapper * w = dynamic_cast<CryptPlugWrapper*>( (*it)->smime() ) ) + mCryptPlugWrapperList->append( w ); + } +} + +#include "cryptplugfactory.moc" diff --git a/certmanager/lib/cryptplugfactory.h b/certmanager/lib/cryptplugfactory.h new file mode 100644 index 000000000..a50c3909c --- /dev/null +++ b/certmanager/lib/cryptplugfactory.h @@ -0,0 +1,83 @@ +/* + cryptplugfactory.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_CRYPTPLUGFACTORY_H__ +#define __KLEO_CRYPTPLUGFACTORY_H__ + +#include "kleo/cryptobackendfactory.h" + +#include <kdepimmacros.h> + +#ifndef LIBKLEOPATRA_NO_COMPAT +namespace Kleo { + //typedef CryptoBackendFactory CryptPlugFactory KDE_DEPRECATED; +} + +class CryptPlugWrapper; +class CryptPlugWrapperList; + +namespace KMail { + + class KDE_EXPORT CryptPlugFactory : public Kleo::CryptoBackendFactory { + Q_OBJECT + protected: + CryptPlugFactory(); + ~CryptPlugFactory(); + + public: + static CryptPlugFactory * instance(); + + CryptPlugWrapper * active() const; + CryptPlugWrapper * smime() const; + CryptPlugWrapper * openpgp() const; + + CryptPlugWrapperList & list() const { return *mCryptPlugWrapperList; } + + CryptPlugWrapper * createForProtocol( const QString & proto ) const; + + void scanForBackends( QStringList * reason ); + + private: + void updateCryptPlugWrapperList(); + + private: + CryptPlugFactory( const CryptPlugFactory & ); + void operator=( const CryptPlugFactory & ); + CryptPlugWrapperList * mCryptPlugWrapperList; + + static CryptPlugFactory * mSelf; + }; + +} +#endif + +#endif // __KLEO_CRYPTPLUGFACTORY_H__ diff --git a/certmanager/lib/cryptplugwrapper.cpp b/certmanager/lib/cryptplugwrapper.cpp new file mode 100644 index 000000000..ce883d79f --- /dev/null +++ b/certmanager/lib/cryptplugwrapper.cpp @@ -0,0 +1,850 @@ +/** + * cryptplugwrapper.cpp + * + * Copyright (c) 2001 Karl-Heinz Zimmer, Klaraelvdalens Datakonsult AB + * + * This CRYPTPLUG wrapper implementation is based on cryptplug.h by + * Karl-Heinz Zimmer which is based on 'The Aegypten Plugin API' as + * specified by Matthias Kalle Dalheimer, Klaraelvdalens Datakonsult AB, + * see file mua-integration.sgml located on Aegypten CVS: + * http://www.gnupg.org/aegypten/development.en.html + * + * purpose: Wrap up all Aegypten Plugin API functions in one C++ class + * for usage by KDE programs, e.g. KMail (or KMime, resp.) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "cryptplugwrapper.h" +#include "cryptplug.h" + +#include <backends/qgpgme/qgpgmekeylistjob.h> +#include <backends/qgpgme/qgpgmeencryptjob.h> +#include <backends/qgpgme/qgpgmedecryptjob.h> +#include <backends/qgpgme/qgpgmesignjob.h> +#include <backends/qgpgme/qgpgmeverifydetachedjob.h> +#include <backends/qgpgme/qgpgmeverifyopaquejob.h> +#include <backends/qgpgme/qgpgmekeygenerationjob.h> +#include <backends/qgpgme/qgpgmeimportjob.h> +#include <backends/qgpgme/qgpgmeexportjob.h> +#include <backends/qgpgme/qgpgmesecretkeyexportjob.h> +#include <backends/qgpgme/qgpgmedownloadjob.h> +#include <backends/qgpgme/qgpgmedeletejob.h> +#include <backends/qgpgme/qgpgmesignencryptjob.h> +#include <backends/qgpgme/qgpgmedecryptverifyjob.h> +#include <backends/qgpgme/qgpgmecryptoconfig.h> +#include <backends/qgpgme/qgpgmerefreshkeysjob.h> + +// qgpgme +#include <qgpgme/dataprovider.h> + +// gpgme++ +#include <gpgmepp/data.h> +#include <gpgmepp/importresult.h> +#include <gpgmepp/keygenerationresult.h> + +// kde +#include <kdebug.h> +#include <kapplication.h> +#include <klocale.h> +#include <kglobal.h> +#include <kconfig.h> + +// other +#include <memory> + +#include <assert.h> +#include <stdlib.h> +#include <stdio.h> + + + + +/* + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This file's source comments - as well as those in interface file * + * cryptplugwrapper.h - are optimized for processing by Doxygen. * + * * + * To obtain best results please get an updated version of Doxygen, * + * for sources and binaries goto http://www.doxygen.org/index.html * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + */ + + + +/*! \file cryptplugwrapper.cpp + \brief C++ wrapper for the CRYPTPLUG library API. + + This CRYPTPLUG wrapper implementation is based on cryptplug.h by + Karl-Heinz Zimmer which is based on 'The Aegypten Plugin API' as + specified by Matthias Kalle Dalheimer, Klaraelvdalens Datakonsult AB, + see file mua-integration.sgml located on Aegypten CVS: + http://www.gnupg.org/aegypten/development.en.html + + purpose: Wrap up all Aegypten Plugin API functions in one C++ class + for usage by KDE programs, e.g. KMail (or KMime, resp.) + + CRYPTPLUG is an independent cryptography plug-in API + developed for Sphinx-enabeling KMail and Mutt. + + CRYPTPLUG was designed for the Aegypten project, but it may + be used by 3rd party developers as well to design pluggable + crypto backends for the above mentioned MUAs. + + \note All string parameters appearing in this API are to be + interpreted as UTF-8 encoded. + + \see cryptplugwrapper.h +*/ + + +// a little helper class for reordering of DN attributes +class DNBeautifier { +public: + enum UnknownAttrsHandling { unknownAttrsHide, + unknownAttrsPrefix, + unknownAttrsPostfix, + unknownAttrsInfix }; + // infix: at the position of "_X_", if any, else Postfix + + DNBeautifier() + { + // the attrOrder is defaulted to an empty string automatically + _unknownAttrsHandling = unknownAttrsInfix; + _unknownAttrsHandlingChar = "INFIX"; + } + DNBeautifier( KConfig* config, + const QString& cfgGroup, + const QString& cfgAttributeOrderEntry, + const QString& cfgUnknownAttrsEntry, + const QStringList& fallbackAttrOrder = QStringList(), + UnknownAttrsHandling fallbackUnknowAttrsHandling = unknownAttrsInfix ) + { + _unknownAttrsHandling = unknownAttrsInfix; + _unknownAttrsHandlingChar = "INFIX"; + if( config ){ + const QString oldGroup( config->group() ); + config->setGroup( cfgGroup ); // e.g. "General" + _attrOrder = + config->readListEntry( cfgAttributeOrderEntry ); // e.g. "DNAttributeOrder" + _unknownAttrsHandlingChar = + config->readEntry( cfgUnknownAttrsEntry ).upper().latin1(); // e.g. "DNUnknownAttributes" + config->setGroup( oldGroup ); + if( _unknownAttrsHandlingChar == "HIDE" ) + _unknownAttrsHandling = unknownAttrsHide; + else if( _unknownAttrsHandlingChar == "PREFIX" ) + _unknownAttrsHandling = unknownAttrsPrefix; + else if( _unknownAttrsHandlingChar == "POSTFIX" ) + _unknownAttrsHandling = unknownAttrsPostfix; + else if( _unknownAttrsHandlingChar == "INFIX" ) + _unknownAttrsHandling = unknownAttrsInfix; + else + _unknownAttrsHandlingChar = "INFIX"; + } + if( _attrOrder.isEmpty() && ! fallbackAttrOrder.isEmpty() ) + _attrOrder = fallbackAttrOrder; + + if( _attrOrder.isEmpty() ){ + _attrOrderChar = 0; + }else{ + _attrOrderChar = new char*[ _attrOrder.count()+1 ]; + int i=0; + for( QStringList::ConstIterator itOrder = _attrOrder.begin(); + itOrder != _attrOrder.end(); + ++itOrder ){ + _attrOrderChar[ i ] = (char*)malloc( ((*itOrder).length()+1)*sizeof(char) ); + strcpy( _attrOrderChar[ i ], (*itOrder).latin1() ); + ++i; + } + _attrOrderChar[ i ] = NULL; + } + } + ~DNBeautifier() + { + int i=0; + for( QStringList::ConstIterator itOrder = _attrOrder.begin(); + itOrder != _attrOrder.end(); + ++itOrder ){ + free( _attrOrderChar[ i ] ); + ++i; + } + delete[] _attrOrderChar; + } + + QStringList attrOrder() const + { + return _attrOrder; + } + char** attrOrderChar() + { + return _attrOrderChar; + } + + UnknownAttrsHandling unknownAttrsHandling() const + { + return _unknownAttrsHandling; + } + const char* unknownAttrsHandlingChar() const + { + return _unknownAttrsHandlingChar; + } + + QValueList< QPair<QString,QString> > reorder( const QValueList< QPair<QString,QString> > & dn ) const + { + return reorder( dn, _attrOrder, _unknownAttrsHandling ); + } + + + static QValueList< QPair<QString,QString> > reorder( + const QValueList< QPair<QString,QString> > & dn, + QStringList attrOrder, + UnknownAttrsHandling unknownAttrsHandling ) + { + if( !attrOrder.isEmpty() ){ + QPtrList< QPair<QString,QString> > unknownEntries; + QValueList< QPair<QString,QString> > dnNew; + + QPair<QString,QString>* unknownEntry; + QStringList::ConstIterator itOrder; + QValueList< QPair<QString,QString> >::ConstIterator itDN; + bool bFound; + + if( unknownAttrsHandling != unknownAttrsHide ){ + // find all unknown entries in their order of appearance + for( itDN = dn.begin(); itDN != dn.end(); ++itDN ){ + bFound = false; + for( itOrder = attrOrder.begin(); itOrder != attrOrder.end(); ++itOrder ){ + if( (*itOrder) == (*itDN).first ){ + bFound = true; + break; + } + } + if( !bFound ) + unknownEntries.append( &(*itDN) ); + } + } + + // prepend the unknown attrs (if desired) + if( unknownAttrsHandling == unknownAttrsPrefix ){ + for( unknownEntry = unknownEntries.first(); unknownEntry; unknownEntry = unknownEntries.next() ){ + dnNew << *unknownEntry; + } + } + + // process the known attrs in the desired order + bool b_X_declared = false; + for( itOrder = attrOrder.begin(); itOrder != attrOrder.end(); ++itOrder ){ + if( (*itOrder) == "_X_" ){ + b_X_declared = true; + // insert the unknown attrs (if desired) + if( unknownAttrsHandling == unknownAttrsInfix ){ + for( unknownEntry = unknownEntries.first(); unknownEntry; unknownEntry = unknownEntries.next() ){ + dnNew << *unknownEntry; + } + } + }else{ + for( itDN = dn.begin(); itDN != dn.end(); ++itDN ){ + if( (*itOrder) == (*itDN).first ){ + dnNew << *itDN; + //kdDebug(5150) << QString((*itDN).first) <<" = " << QString((*itDN).second) << endl;; + } + } + } + } + + // append the unknown attrs (if desired) + if( unknownAttrsHandling == unknownAttrsPostfix || + ( unknownAttrsHandling == unknownAttrsInfix && ! b_X_declared ) ){ + for( unknownEntry = unknownEntries.first(); unknownEntry; unknownEntry = unknownEntries.next() ){ + dnNew << *unknownEntry; + } + } + + return dnNew; + } + return dn; + } + +private: + QStringList _attrOrder; + char** _attrOrderChar; + UnknownAttrsHandling _unknownAttrsHandling; + QCString _unknownAttrsHandlingChar; +}; + + + +/* special helper class to be used by signing/encrypting functions *******/ + + + +StructuringInfoWrapper::StructuringInfoWrapper( CryptPlugWrapper* wrapper ) + : _initDone( false ), _wrapper( wrapper ) +{ + initMe(); +} +StructuringInfoWrapper::~StructuringInfoWrapper() +{ + freeMe(); +} +void StructuringInfoWrapper::reset() +{ + freeMe(); + initMe(); +} +void StructuringInfoWrapper::initMe() +{ + if ( _wrapper && _wrapper->cryptPlug() ) { + _wrapper->cryptPlug()->init_StructuringInfo( &data ); + _initDone = true; + } +} +void StructuringInfoWrapper::freeMe() +{ + if( _wrapper && _wrapper->cryptPlug() && _initDone ) { + _wrapper->cryptPlug()->free_StructuringInfo( &data ); + _initDone = false; + } +} + +class CryptPlugWrapper::Config { +public: + Config( gpgme_protocol_t proto ); + ~Config(); + + const char* signatureKeyCertificate; + SignatureAlgorithm signatureAlgorithm; + SignatureCompoundMode signatureCompoundMode; + SendCertificates sendCertificates; + bool saveSentSignatures; + bool warnNoCertificate; + bool signatureUseCRLs; + EncryptionAlgorithm encryptionAlgorithm; + EncryptEmail encryptEmail; + bool saveMessagesEncrypted; + bool encryptionUseCRLs; + bool encryptionCRLExpiryNearWarning; + int encryptionCRLNearExpiryInterval; + CertificateSource certificateSource; + bool warnSendUnsigned; + bool signatureCertificateExpiryNearWarning; + int signatureCertificateExpiryNearInterval; + bool cACertificateExpiryNearWarning; + int cACertificateExpiryNearInterval; + bool rootCertificateExpiryNearWarning; + int rootCertificateExpiryNearInterval; + bool warnSendUnencrypted; + bool checkCertificatePath; + bool receiverCertificateExpiryNearWarning; + int receiverCertificateExpiryNearWarningInterval; + bool certificateInChainExpiryNearWarning; + int certificateInChainExpiryNearWarningInterval; + bool receiverEmailAddressNotInCertificateWarning; + const char* libVersion; /* a statically allocated string with the GPGME Version used */ +}; + +static const int NEAR_EXPIRY = 14; + +CryptPlugWrapper::Config::Config( gpgme_protocol_t proto ) +{ + signatureAlgorithm = SignAlg_SHA1; + if ( proto == GPGME_PROTOCOL_CMS ) + signatureCompoundMode = SignatureCompoundMode_Opaque; + else + signatureCompoundMode = SignatureCompoundMode_Detached; + sendCertificates = SendCert_SendChainWithRoot; + saveSentSignatures = true; + warnNoCertificate = true; + signatureUseCRLs = true; + encryptionAlgorithm = EncryptAlg_RSA; + encryptEmail = EncryptEmail_Ask; + saveMessagesEncrypted = true; + encryptionUseCRLs = true; + encryptionCRLExpiryNearWarning = false; + encryptionCRLNearExpiryInterval = NEAR_EXPIRY; + certificateSource = CertSrc_Server; + warnSendUnsigned = true; + signatureCertificateExpiryNearWarning = true; + signatureCertificateExpiryNearInterval = NEAR_EXPIRY; + cACertificateExpiryNearWarning = true; + cACertificateExpiryNearInterval = NEAR_EXPIRY; + rootCertificateExpiryNearWarning = true; + rootCertificateExpiryNearInterval = NEAR_EXPIRY; + warnSendUnencrypted = false; + checkCertificatePath = true; + receiverCertificateExpiryNearWarning = true; + receiverCertificateExpiryNearWarningInterval = NEAR_EXPIRY; + certificateInChainExpiryNearWarning = true; + certificateInChainExpiryNearWarningInterval = NEAR_EXPIRY; + receiverEmailAddressNotInCertificateWarning = true; + libVersion = gpgme_check_version (NULL); +} + +CryptPlugWrapper::Config::~Config() { +} + +/* Some multi purpose functions ******************************************/ + +QString CryptPlugWrapper::errorIdToText( int errId, bool & isPassphraseError ) { + const GpgME::Error err( errId ); + isPassphraseError = err.isCanceled() + || gpgme_err_code( errId ) == GPG_ERR_NO_SECKEY ; // FIXME: more? + return QString::fromLocal8Bit( err.asString() ); +} + +/* some special functions ************************************************/ + + +CryptPlugWrapper::CryptPlugWrapper( const QString& name, + const QString& libName, + const QString& update, + bool active ) + : Kleo::CryptoBackend::Protocol(), + _name( name ), + _libName( libName ), + _updateURL( update ), + _active( active ), + _initStatus( InitStatus_undef ), + _cp( 0 ), + _config( 0 ), + _cryptoConfig( 0 ) +{ + const bool ok = initialize( 0, 0 ); + assert( ok ); +} + + +CryptPlugWrapper::~CryptPlugWrapper() +{ + deinitialize(); +} + + +void CryptPlugWrapper::setActive( bool active ) +{ + _active = active; +} + + +bool CryptPlugWrapper::active() const +{ + return _active; +} + + + +bool CryptPlugWrapper::setLibName( const QString& libName ) +{ + bool bOk = ! _cp; // Changing the lib name is only allowed + if( bOk ) // when either no initialization took + _libName = libName; // place or 'deinitialize()' has been + return bOk; // called afterwards. +} + +QString CryptPlugWrapper::libName() const +{ + return _libName; +} + +QString CryptPlugWrapper::protocol() const +{ + if ( _libName.contains( "smime" ) ) + return "SMIME"; + if ( _libName.contains( "openpgp" ) ) + return "OpenPGP"; + return QString::null; +} + +void CryptPlugWrapper::setDisplayName( const QString& name ) +{ + _name = name; +} + + +QString CryptPlugWrapper::displayName() const +{ + if ( !_name.isEmpty() ) + return _name; + if ( _libName.contains( "smime" ) ) + return "gpgsm"; + if ( _libName.contains( "openpgp" ) ) + return "gpg"; + return i18n("(Unknown Protocol)"); +} + +bool CryptPlugWrapper::initialize( InitStatus* initStatus, QString* errorMsg ) +{ + if ( _cp ) + return true; + + _initStatus = InitStatus_undef; + /* make sure we have a lib name */ + if ( _libName.isEmpty() ) { + _initStatus = InitStatus_NoLibName; + kdDebug(5150) << "No library name was given.\n" << endl; + } else { + if ( _libName.contains( "smime" ) ) { + _cp = new SMIMECryptPlug(); + _config = new Config( GPGME_PROTOCOL_CMS ); + } else if ( _libName.contains( "openpgp" ) ) { + _cp = new OpenPGPCryptPlug(); + _config = new Config( GPGME_PROTOCOL_OpenPGP ); + } else { + _cp = 0; + _config = 0; + } + + if ( !_cp ) { + _initStatus = InitStatus_LoadError; + kdDebug(5150) << "Couldn't create '" << _libName.latin1() << "'" << endl; + } else { + /* now call the init function */ + if( !_cp->initialize() ) { + _initStatus = InitStatus_InitError; + kdDebug(5150) << "Error while executing function 'initialize' on plugin " << _libName << endl; + _lastError = i18n("Error while initializing plugin \"%1\"").arg( _libName ); + if ( errorMsg ) + *errorMsg = _lastError; + delete _cp; _cp = 0; + delete _config; _config = 0; + } else { + _initStatus = InitStatus_Ok; + } + } + } + if( initStatus ) + *initStatus = _initStatus; + return _initStatus == InitStatus_Ok; +} + + + +void CryptPlugWrapper::deinitialize() +{ + delete _cp; _cp = 0; + delete _config; _config = 0; + delete _cryptoConfig; _cryptoConfig = 0; +} + + +CryptPlugWrapper::InitStatus CryptPlugWrapper::initStatus( QString* errorMsg ) const +{ + if( errorMsg ) + *errorMsg = _lastError; + return _initStatus; +} + + +bool CryptPlugWrapper::hasFeature( Feature flag ) +{ + return _cp && _cp->hasFeature( flag ); +} + + +/* normal functions ******************************************************/ + +bool CryptPlugWrapper::checkMessageSignature( char** cleartext, + const char* signaturetext, + bool signatureIsBinary, + int signatureLen, + CryptPlug::SignatureMetaData* sigmeta ) +{ + DNBeautifier dnBeautifier( kapp->config(), + "DN", + "AttributeOrder", + "UnknownAttributes" ); + return _cp && _cp->checkMessageSignature( cleartext, + signaturetext, + signatureIsBinary, + signatureLen, + sigmeta, + dnBeautifier.attrOrderChar(), + dnBeautifier.unknownAttrsHandlingChar() ); +} + + +bool CryptPlugWrapper::decryptMessage( const char* ciphertext, + bool cipherIsBinary, + int cipherLen, + char** cleartext, + const char* certificate, + int* errId, + char** errTxt ) +{ + return _cp && _cp->decryptMessage( ciphertext, cipherIsBinary, cipherLen, + (const char**)cleartext, certificate, errId, errTxt ); +} + + +bool CryptPlugWrapper::decryptAndCheckMessage( + const char* ciphertext, + bool cipherIsBinary, + int cipherLen, + char** cleartext, + const char* certificate, + bool* signatureFound, + CryptPlug::SignatureMetaData* sigmeta, + int* errId, + char** errTxt ) +{ + DNBeautifier dnBeautifier( kapp->config(), + "DN", + "AttributeOrder", + "UnknownAttributes" ); + return _cp && _cp->decryptAndCheckMessage( ciphertext, + cipherIsBinary, + cipherLen, + (const char**)cleartext, + certificate, + signatureFound, + sigmeta, + errId, + errTxt, + dnBeautifier.attrOrderChar(), + dnBeautifier.unknownAttrsHandlingChar() ); +} + + + + +void CryptPlugWrapper::freeSignatureMetaData( CryptPlug::SignatureMetaData* sigmeta ) +{ + if ( !sigmeta ) + return; + free( sigmeta->status ); + for( int i = 0; i < sigmeta->extended_info_count; ++i ) { + free( sigmeta->extended_info[i].creation_time ); + free( (void*)sigmeta->extended_info[i].status_text ); + free( (void*)sigmeta->extended_info[i].keyid ); + free( (void*)sigmeta->extended_info[i].fingerprint ); + free( (void*)sigmeta->extended_info[i].algo ); + free( (void*)sigmeta->extended_info[i].userid ); + free( (void*)sigmeta->extended_info[i].name ); + free( (void*)sigmeta->extended_info[i].comment ); + if( sigmeta->extended_info[i].emailCount ){ + for( int j=0; j < sigmeta->extended_info[i].emailCount; ++j) + if( sigmeta->extended_info[i].emailList[j] ) + free( (void*)sigmeta->extended_info[i].emailList[j] ); + free( (void*)sigmeta->extended_info[i].emailList ); + } + } + free( sigmeta->extended_info ); +} + +GpgME::ImportResult CryptPlugWrapper::importCertificate( const char* data, size_t length ) +{ + if ( !_cp ) + return GpgME::ImportResult(); + + + return _cp->importCertificateFromMem( data, length ); +} + +Kleo::KeyListJob * CryptPlugWrapper::keyListJob( bool remote, bool includeSigs, bool validate ) const { + if ( !_cp ) + return 0; + + GpgME::Context * context = GpgME::Context::createForProtocol( _cp->mProtocol ); + if ( !context ) + return 0; + + unsigned int mode = context->keyListMode(); + if ( remote ) { + mode |= GpgME::Context::Extern; + mode &= ~GpgME::Context::Local; + } else { + mode |= GpgME::Context::Local; + mode &= ~GpgME::Context::Extern; + } + if ( includeSigs ) mode |= GpgME::Context::Signatures; + if ( validate ) mode |= GpgME::Context::Validate; + context->setKeyListMode( mode ); + return new Kleo::QGpgMEKeyListJob( context ); +} + +Kleo::EncryptJob * CryptPlugWrapper::encryptJob( bool armor, bool textmode ) const { + if ( !_cp ) + return 0; + + GpgME::Context * context = GpgME::Context::createForProtocol( _cp->mProtocol ); + if ( !context ) + return 0; + + context->setArmor( armor ); + context->setTextMode( textmode ); + return new Kleo::QGpgMEEncryptJob( context ); +} + +Kleo::DecryptJob * CryptPlugWrapper::decryptJob() const { + if ( !_cp ) + return 0; + + GpgME::Context * context = GpgME::Context::createForProtocol( _cp->mProtocol ); + if ( !context ) + return 0; + + return new Kleo::QGpgMEDecryptJob( context ); +} + +Kleo::SignJob * CryptPlugWrapper::signJob( bool armor, bool textMode ) const { + if ( !_cp ) + return 0; + + GpgME::Context * context = GpgME::Context::createForProtocol( _cp->mProtocol ); + if ( !context ) + return 0; + + context->setArmor( armor ); + context->setTextMode( textMode ); + + return new Kleo::QGpgMESignJob( context ); +} + +Kleo::VerifyDetachedJob * CryptPlugWrapper::verifyDetachedJob( bool textMode ) const { + if ( !_cp ) + return 0; + + GpgME::Context * context = GpgME::Context::createForProtocol( _cp->mProtocol ); + if ( !context ) + return 0; + + context->setTextMode( textMode ); + + return new Kleo::QGpgMEVerifyDetachedJob( context ); +} + +Kleo::VerifyOpaqueJob * CryptPlugWrapper::verifyOpaqueJob( bool textMode ) const { + if ( !_cp ) + return 0; + + GpgME::Context * context = GpgME::Context::createForProtocol( _cp->mProtocol ); + if ( !context ) + return 0; + + context->setTextMode( textMode ); + + return new Kleo::QGpgMEVerifyOpaqueJob( context ); +} + +Kleo::KeyGenerationJob * CryptPlugWrapper::keyGenerationJob() const { + if ( !_cp ) + return 0; + + GpgME::Context * context = GpgME::Context::createForProtocol( _cp->mProtocol ); + if ( !context ) + return 0; + + return new Kleo::QGpgMEKeyGenerationJob( context ); +} + +Kleo::ImportJob * CryptPlugWrapper::importJob() const { + if ( !_cp ) + return 0; + + GpgME::Context * context = GpgME::Context::createForProtocol( _cp->mProtocol ); + if ( !context ) + return 0; + + return new Kleo::QGpgMEImportJob( context ); +} + +Kleo::ExportJob * CryptPlugWrapper::publicKeyExportJob( bool armor ) const { + if ( !_cp ) + return 0; + + GpgME::Context * context = GpgME::Context::createForProtocol( _cp->mProtocol ); + if ( !context ) + return 0; + + context->setArmor( armor ); + return new Kleo::QGpgMEExportJob( context ); +} + +Kleo::ExportJob * CryptPlugWrapper::secretKeyExportJob( bool armor, const QString& charset ) const { + if ( !_cp || _cp->mProtocol != GpgME::Context::CMS ) // fixme: add support for gpg, too + return 0; + + // this operation is not supported by gpgme, so we have to call gpgsm ourselves: + return new Kleo::QGpgMESecretKeyExportJob( armor, charset ); +} + +Kleo::RefreshKeysJob * CryptPlugWrapper::refreshKeysJob() const { + if ( !_cp || _cp->mProtocol != GpgME::Context::CMS ) // fixme: add support for gpg, too + return 0; + + // this operation is not supported by gpgme, so we have to call gpgsm ourselves: + return new Kleo::QGpgMERefreshKeysJob(); +} + +Kleo::DownloadJob * CryptPlugWrapper::downloadJob( bool armor ) const { + if ( !_cp ) + return 0; + + GpgME::Context * context = GpgME::Context::createForProtocol( _cp->mProtocol ); + if ( !context ) + return 0; + + context->setArmor( armor ); + // this is the hackish interface for downloading from keyserers currently: + context->setKeyListMode( GpgME::Context::Extern ); + + return new Kleo::QGpgMEDownloadJob( context ); +} + +Kleo::DeleteJob * CryptPlugWrapper::deleteJob() const { + if ( !_cp ) + return 0; + + GpgME::Context * context = GpgME::Context::createForProtocol( _cp->mProtocol ); + if ( !context ) + return 0; + + return new Kleo::QGpgMEDeleteJob( context ); +} + +Kleo::SignEncryptJob * CryptPlugWrapper::signEncryptJob( bool armor, bool textMode ) const { + if ( !_cp ) + return 0; + + GpgME::Context * context = GpgME::Context::createForProtocol( _cp->mProtocol ); + if ( !context ) + return 0; + + context->setArmor( armor ); + context->setTextMode( textMode ); + + return new Kleo::QGpgMESignEncryptJob( context ); +} + +Kleo::DecryptVerifyJob * CryptPlugWrapper::decryptVerifyJob( bool textMode ) const { + if ( !_cp ) + return 0; + + GpgME::Context * context = GpgME::Context::createForProtocol( _cp->mProtocol ); + if ( !context ) + return 0; + + context->setTextMode( textMode ); + + return new Kleo::QGpgMEDecryptVerifyJob( context ); +} diff --git a/certmanager/lib/cryptplugwrapper.h b/certmanager/lib/cryptplugwrapper.h new file mode 100644 index 000000000..91cec75df --- /dev/null +++ b/certmanager/lib/cryptplugwrapper.h @@ -0,0 +1,839 @@ +/** + * cryptplugwrapper.h + * + * Copyright (c) 2001 Karl-Heinz Zimmer, Klaraelvdalens Datakonsult AB + * + * This CRYPTPLUG wrapper interface is based on cryptplug.h by + * Karl-Heinz Zimmer which is based on 'The Aegypten Plugin API' as + * specified by Matthias Kalle Dalheimer, Klaraelvdalens Datakonsult AB, + * see file mua-integration.sgml located on Aegypten CVS: + * http://www.gnupg.org/aegypten/development.en.html + * + * purpose: Wrap up all Aegypten Plugin API functions in one C++ class + * for usage by KDE programs, e.g. KMail (or KMime, resp.) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef cryptplugwrapper_h +#define cryptplugwrapper_h + +#include "cryptplug.h" + +#ifndef LIBKLEOPATRA_NO_COMPAT + +/* + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * * + * This file's source comments are optimized for processing by Doxygen. * + * * + * To obtain best results please get an updated version of Doxygen, * + * for sources and binaries goto http://www.doxygen.org/index.html * + * * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + + * + */ +#include "kleo/cryptobackend.h" + +#include <qdatetime.h> + +#include <qvaluelist.h> +#include <qpair.h> +#include <qstringlist.h> +#include <qstring.h> +#include <kdepimmacros.h> + + +class KConfigBase; +class QGpgMECryptoConfig; + +namespace GpgME { + class ImportResult; + class KeyGenerationResult; +} + +namespace Kleo { + class KeyListJob; + class EncryptJob; + class DecryptJob; + class SignJob; + class VerifyDetachedJob; + class VerifyOpaqueJob; + class KeyGenerationJob; + class ImportJob; + class ExportJob; + class DownloadJob; + class DeleteJob; + class SignEncryptJob; + class DecryptVerifyJob; + class CryptoConfig; + class RefreshKeysJob; + class SpecialJob; +} + +/*! \file cryptplugwrapper.h + \brief C++ wrapper for the CRYPTPLUG library API. + + This CRYPTPLUG wrapper interface is based on cryptplug.h by + Karl-Heinz Zimmer which is based on 'The Aegypten Plugin API' as + specified by Matthias Kalle Dalheimer, Klaraelvdalens Datakonsult AB, + see file mua-integration.sgml located on Aegypten CVS: + http://www.gnupg.org/aegypten/development.en.html + + purpose: Wrap up all Aegypten Plugin API functions in one C++ class + for usage by KDE programs, e.g. KMail (or KMime, resp.) + + CRYPTPLUG is an independent cryptography plug-in API + developed for Sphinx-enabeling KMail and Mutt. + + CRYPTPLUG was designed for the Aegypten project, but it may + be used by 3rd party developers as well to design pluggable + crypto backends for the above mentioned MUAs. + + \note All string parameters appearing in this API are to be + interpreted as UTF-8 encoded. + + \see cryptplugwrapper.cpp +*/ + +/*! \defgroup groupAdmin Constructor, destructor and setting of 'active' flag + + The functions in this section are used for general administration of + this CRYPTPLUG wrapper class and for maintaining a separate \c active flag + for environments using more than one CRYPTPLUG library simultaneously. +*/ + +/*! \defgroup groupGeneral Loading and Unloading the Plugin, General Functionality + + The functions in this section are used for loading and + unloading the respective CRYPTPLUG library, for (re)setting + it's internal data structures and for retrieving information + on the implementation state of all functions covered by the CRYPTPLUG API. +*/ + +/*! \defgroup groupDisplay Graphical Display Functionality + + The functions in this section return stationery that the + MUAs can use in order to display security functionality + graphically. This can be toolbar icons, shortcuts, tooltips, + etc. Not all MUAs will use all this functionality. +*/ + +/*! \defgroup groupConfig Configuration Support + + The functions in this section provide the necessary + functionality to configure the security functionality as well + as to query configuration settings. Since all configuration + settings will not be saved with the plugin, but rather with + the MUA, there are also functions to set configuration + settings programmatically; these will be used on startup of + the plugin when the MUA transfers the configuration values it + has read into the plugin. Usually, the functions to query and + set the configuration values are not needed for anything but + saving to and restoring from configuration files. +*/ + + +/*! \defgroup groupConfigSign Signature Configuration + \ingroup groupConfig + + The functions in this section provide the functionality + to configure signature handling and set and query the + signature configuration. +*/ + +/*! \defgroup groupConfigCrypt Encryption Configuration + \ingroup groupConfig + + The functions in this section provide the functionality + to configure encryption handling and set and query the + encryption configuration. + + \note Whenever the term <b> encryption</b> is used here, + it is supposed to mean both encryption and decryption, + unless otherwise specified. +*/ + +/*! \defgroup groupConfigDir Directory Service Configuration + \ingroup groupConfig + + This section contains messages for configuring the + directory service. +*/ + + +/*! \defgroup groupCertHand Certificate Handling + + The following methods are used to maintain and query certificates. +*/ + + +/*! \defgroup groupSignCryptAct Signing and Encrypting Actions + + This section describes methods and structures + used for signing and/or encrypting your mails. +*/ + + +/*! \defgroup groupSignAct Signature Actions + \ingroup groupSignCryptAct + + This section describes methods that are used for working + with signatures. +*/ + +/*! \defgroup groupCryptAct Encryption and Decryption + \ingroup groupSignCryptAct + + The following methods are used to encrypt and decrypt + email messages. +*/ + +/*! \defgroup groupCertAct Certificate Handling Actions + + The functions in this section provide local certificate management. +*/ + +/*! \defgroup groupCRLAct CRL Handling Actions + + This section describes functions for managing CRLs. +*/ + +/*! \defgroup groupAdUsoInterno Important functions to be used by plugin implementors ONLY. + + This section describes functions that have to be used by + plugin implementors but should not be used by plugin users + directly. + + If you are not planning to write your own cryptography + plugin <b>you should ignore this</b> section! +*/ + + + +class CryptPlugWrapper; +/*! \ingroup groupSignCryptAct + \brief This class provides C++ access to the StructuringInfo helper + struct that is specified in cryptplug.h to hold information + returned by signing and by encrypting functions. + + Use this information to compose a MIME object containing signed + and/or encrypted content (or to build a text frame around your + flat non-MIME message body, resp.) + + \note This class is different from the respective cryptplug.h class + because this one takes care for freeing the char** members' memory + automatically. You must <b>not</b> call the \c free function for + any of it's members - just ignore the advise given in the + cryptplug.h documentation! + + <b>If</b> value returned in \c makeMimeObject is <b>TRUE</b> the + text strings returned in \c contentTypeMain and \c contentDispMain + and \c contentTEncMain (and, if required, \c content[..]Version and + \c bodyTextVersion and \c content[..]Sig) should be used to compose + a respective MIME object.<br> + If <b>FALSE</b> the texts returned in \c flatTextPrefix and + \c flatTextSeparator and \c flatTextPostfix are to be used instead.<br> + Always <b>either</b> the \c content[..] and \c bodyTextVersion + parameters <b>or</b> the \c flatText[..] parameters are holding + valid data - never both of them may be used simultaneously + as plugins will just ignore the parameters not matching their + \c makeMimeObject setting. + + When creating your MIME object please observe these common rules: + \li Parameters named \c contentType[..] and \c contentDisp[..] and + \c contentTEnc[..] will return the values for the respective MIME + headers 'Content-Type' and 'Content-Disposition' and + 'Content-Transfer-Encoding'. The following applies to these parameters: + \li The relevant MIME part may <b>only</b> be created if the respective + \c contentType[..] parameter is holding a non-zero-length string. If the + \c contentType[..] parameter value is invalid or holding an empty string + the respective \c contentDisp[..] and \c contentTEnc[..] parameters + should be ignored. + \li If the respective \c contentDisp[..] or \c contentTEnc[..] parameter + is NULL or holding a zero-length string it is up to you whether you want + to add the relevant MIME header yourself, but since it in in the + responsibility of the plugin implementors to provide you with all + necessary 'Content-[..]' header information you should <b>not need</b> + to define them if they are not returned by the signing or encrypting + function - otherwise this may be considered as a bug in the plugin and + you could report the missing MIME header information to the address + returned by the \c bugURL() function. + + If \c makeMultiMime returns FALSE the \c contentTypeMain returned must + not be altered but used to specify a single part mime object holding the + code bloc, e.g. this is used for 'enveloped-data' single part MIME + objects. In this case you should ignore both the \c content[..]Version + and \c content[..]Code parameters. + + If \c makeMultiMime returns TRUE also the following rules apply: + \li If \c includeCleartext is TRUE you should include the cleartext + as first part of our multipart MIME object, typically this is TRUE + when signing mails but FALSE when encrypting. + \li The \c contentTypeMain returned typically starts with + "multipart/" while providing a "protocol" and a "micalg" parameter: just + add an appropriate \c "; boundary=[your \c boundary \c string]" to get + the complete Content-Type value to be used for the MIME object embedding + both the signed part and the signature part (or - in case of + encrypting - the version part and the code part, resp.). + \li If \c contentTypeVersion is holding a non-zero-length string an + additional MIME part must added immediately before the code part, this + version part's MIME headers must have the unaltered values of + \c contentTypeVersion and (if they are holding non-zero-length strings) + \c contentDispVersion and \c contentTEncVersion, the unaltered contents + of \c bodyTextVersion must be it's body. + \li The value returned in \c contentTypeCode is specifying the complete + Content-Type to be used for this multipart MIME object's signature part + (or - in case of encrypting - for the code part following after the + version part, resp.), you should not add/change/remove anything here + but just use it's unaltered value for specifying the Content-Type header + of the respective MIME part. + \li The same applies to the \c contentDispCode value: just use it's + unaltered value to specify the Content-Disposition header entry of + the respective MIME part. + \li The same applies to the \c contentTEncCode value: just use it's + unaltered value to specify the Content-Transfer-Encoding header of + the respective MIME part. + + <b>If</b> value returned in \c makeMimeObject is <b>FALSE</b> the + text strings returned in \c flatTextPrefix and \c flatTextPostfix + should be used to build a frame around the cleartext and the code + bloc holding the signature (or - in case of encrypting - the encoded + data bloc, resp.).<br> + If \c includeCleartext is TRUE this frame should also include the + cleartext as first bloc, this bloc should be divided from the code bloc + by the contents of \c flatTextSeparator - typically this is used for + signing but not when encrypting.<br> + If \c includeCleartext is FALSE you should ignore both the cleartext + and the \c flatTextSeparator parameter. + + <b>How to use StructuringInfoWrapper data in your program:</b> + \li To compose a signed message please act as described below. + \li For constructing an encrypted message just replace the + \c signMessage() call by the respective \c encryptMessage() call + and then proceed exactly the same way. + \li In any case make <b>sure</b> to free your \c ciphertext when + you are done with processing the data returned by the signing + (or encrypting, resp.) function. + +\verbatim + + char* ciphertext; + StructuringInfoWrapper structInf; + + if( ! signMessage( cleartext, &ciphertext, certificate, + structInf ) ) { + + myErrorDialog( "Error: could not sign the message!" ); + + } else { + if( structInf.data.makeMimeObject ) { + + // Build the main MIME object. + // This is done by + // using the header values returned in + // structInf.data.contentTypeMain and in + // structInf.data.contentDispMain and in + // structInf.data.contentTEncMain. + .. + + if( ! structInf.data.makeMultiMime ) { + + // Build the main MIME object's body. + // This is done by + // using the code bloc returned in + // ciphertext. + .. + + } else { + + // Build the encapsulated MIME parts. + if( structInf.data.includeCleartext ) { + + // Build a MIME part holding the cleartext. + // This is done by + // using the original cleartext's headers and by + // taking it's original body text. + .. + + } + if( structInf.data.contentTypeVersion + && 0 < strlen( structInf.data.contentTypeVersion ) ) { + + // Build a MIME part holding the version information. + // This is done by + // using the header values returned in + // structInf.data.contentTypeVersion and + // structInf.data.contentDispVersion and + // structInf.data.contentTEncVersion and by + // taking the body contents returned in + // structInf.data.bodyTextVersion. + .. + + } + if( structInf.data.contentTypeCode + && 0 < strlen( structInf.data.contentTypeCode ) ) { + + // Build a MIME part holding the code information. + // This is done by + // using the header values returned in + // structInf.data.contentTypeCode and + // structInf.data.contentDispCode and + // structInf.data.contentTEncCode and by + // taking the body contents returned in + // ciphertext. + .. + + } else { + + // Plugin error! + myErrorDialog( "Error: Cryptography plugin returned a main" + "Content-Type=Multipart/.. but did not " + "specify the code bloc's Content-Type header." + "\nYou may report this bug:" + "\n" + cryptplug.bugURL() ); + } + } + } else { + + // Build a plain message body + // based on the values returned in structInf. + // Note: We do _not_ insert line breaks between the parts since + // it is the plugin job to provide us with ready-to-use + // texts containing all necessary line breaks. + strcpy( myMessageBody, structInf.data.plainTextPrefix ); + if( structInf.data.includeCleartext ) { + strcat( myMessageBody, cleartext ); + strcat( myMessageBody, structInf.data.plainTextSeparator ); + } + strcat( myMessageBody, *ciphertext ); + strcat( myMessageBody, structInf.data.plainTextPostfix ); + } + + // free the memory that was allocated + // for the ciphertext + free( ciphertext ); + } + +\endverbatim + + \see signMessage, encryptMessage, encryptAndSignMessage +*/ +class StructuringInfoWrapper { +public: + StructuringInfoWrapper( CryptPlugWrapper* wrapper ); + ~StructuringInfoWrapper(); + void reset(); + CryptPlug::StructuringInfo data; +private: + void initMe(); + void freeMe(); + bool _initDone; + CryptPlugWrapper* _wrapper; +}; + + + +/*! + \brief This class provides C++ access to the CRYPTPLUG API. +*/ +class KDE_EXPORT CryptPlugWrapper : public Kleo::CryptoBackend::Protocol { +public: + static QString errorIdToText( int errId, bool & isPassphraseError ); + + /*! \ingroup groupGeneral + + \brief Current initialization state. + + This flag holding status of previous call of initialize function. + If initialize was not called before return value will be + \c CryptPlugInit_undef. + + \sa initStatus, initialize + */ + typedef enum { + InitStatus_undef = 0, + + InitStatus_Ok = 1, + InitStatus_NoLibName = 2, + InitStatus_LoadError = 0x1000, + InitStatus_InitError = 0x2000 + } InitStatus; + + /*! \ingroup groupSignAct + \brief Flags used to compose the SigStatusFlags value. + + This status flags are used to compose the SigStatusFlags value + returned in \c SignatureMetaDataExtendedInfo after trying to + verify a signed message part's signature status. + + The normal flags may <b>not</b> be used together with the + special SigStatus_NUMERICAL_CODE flag. When finding the special + SigStatus_NUMERICAL_CODE flag in a SigStatusFlags value you + can obtain the respective error code number by substracting + the SigStatusFlags value by SigStatus_NUMERICAL_CODE: this is + used to transport special status information NOT matching + any of the normal predefined status codes. + + \note to PlugIn developers: Implementations of the CryptPlug API + should try to express their signature states by bit-wise OR'ing + the normal SigStatusFlags values. Using the SigStatus_NUMERICAL_CODE + flag should only be used as for exceptional situations where no + other flag(s) could be used. By using the normal status flags your + PlugIn's users will be told an understandable description of the + status - when using (SigStatus_NUMERICAL_CODE + internalCode) they + will only be shown the respective code number and have to look + into your PlugIn's manual to learn about it's meaning... + */ + enum { + SigStatus_UNKNOWN = 0x0000, + SigStatus_VALID = SigStat_VALID, + SigStatus_GREEN = SigStat_GREEN, + SigStatus_RED = SigStat_RED, + SigStatus_KEY_REVOKED = SigStat_KEY_REVOKED, + SigStatus_KEY_EXPIRED = SigStat_KEY_EXPIRED, + SigStatus_SIG_EXPIRED = SigStat_SIG_EXPIRED, + SigStatus_KEY_MISSING = SigStat_KEY_MISSING, + SigStatus_CRL_MISSING = SigStat_CRL_MISSING, + SigStatus_CRL_TOO_OLD = SigStat_CRL_TOO_OLD, + SigStatus_BAD_POLICY = SigStat_BAD_POLICY, + SigStatus_SYS_ERROR = SigStat_SYS_ERROR, + + SigStatus_NUMERICAL_CODE = 0x8000 /* An other error occurred. */ + }; + typedef unsigned long SigStatusFlags; + + + enum { + CertStatus_EXPIRES_NEVER = CRYPTPLUG_CERT_DOES_NEVER_EXPIRE + }; + + + /*! \ingroup groupAdmin + \brief Constructor of CRYPTPLUG wrapper class. + + This constructor does <b>not</b> call the initialize() method + but just stores some information for later use. + + \note Since more than one crypto plug-in might be specified (using + multiple instances of the warpper class) it is necessary to + set \c active at least one them. Only wrappers that have been + activated may be initialized or configured or used to perform + crypto actions. + + \param name The external name that is visible in lists, messages, + etc. + \param libName Complete path+name of CRYPTPLUG library that is to + be used by this instance of CryptPlugWrapper. + \param update the URL from where updates can be downloaded + \param active Specify whether the relative library is to be used + or not. + + \sa ~CryptPlugWrapper, setActive, active, initialize, deinitialize + \sa initStatus + */ + CryptPlugWrapper( const QString& name=QString::null, + const QString& libName=QString::null, + const QString& update=QString::null, + bool active = false ); + + /*! \ingroup groupAdmin + \brief Destructor of CRYPTPLUG wrapper class. + + This destructor <b>does</b> call the deinitialize() method in case + this was not done by explicitly calling it before. + + \sa deinitialize, initialize, CryptPlugWrapper(), setActive, active + \sa + */ + ~CryptPlugWrapper(); + + QString protocol() const; + + QString name() const { + return protocol(); + } + + /*! \ingroup groupAdmin + \brief Set this CRYPTPLUG wrapper's internal \c active flag. + + Since more than one crypto plug-in might be specified (using + multiple instances of the warpper class) it is necessary to + set \c active at least one them. Only wrappers that have been + activated may be initialized or configured or used to perform + crypto actions. + + This flag may be set in the constructor or by calling setActive(). + + \note Deactivating does <b>not</b> mean resetting the internal + structures - if just prevents the normal functions from + being called erroneously. When deactivated only the following + functions are operational: constructor , destructor , + setActive , active, setLibName , libName , initStatus; + calling other functions will be ignored and their return + values will be undefined. + + \param active Specify whether the relative library is to be used + or not. + + \sa active, CryptPlugWrapper(), ~CryptPlugWrapper + \sa deinitialize, initialize, initStatus + */ + void setActive( bool active ); + + /*! \ingroup groupAdmin + \brief Returns this CRYPTPLUG wrapper's internal \c active flag. + + \return whether the relative library is to be used or not. + + \sa setActive + */ + bool active() const; + + + /*! \ingroup groupAdmin + \brief Set the CRYPTPLUG library name. + + Complete path+name of CRYPTPLUG library that is to + be used by this instance of CryptPlugWrapper. + + This name may be set in the constructor or by calling setLibName(). + + \note Setting/changing the library name may only be done when + the initStatus() is <b>not</b> \c InitStatus_Ok. + If you want to change the name of the library after + successfully having called initialize() please make + sure to unload it by calling the deinitialize() function. + + \param libName libName Complete path+name of CRYPTPLUG library + that is to be used by this CryptPlugWrapper. + + \return whether the library name could be changed; library name + can only be changed when library is not initialized - see + above 'note'. + + \sa libName, CryptPlugWrapper(), ~CryptPlugWrapper + \sa deinitialize, initialize, initStatus + */ + bool setLibName( const QString& libName ); + + /*! \ingroup groupAdmin + \brief Returns the CRYPTPLUG library name. + + \return the complete path+name of CRYPTPLUG library that is to + be used by this instance of CryptPlugWrapper. + + \sa setLibName + */ + QString libName() const; + + + /*! \ingroup groupAdmin + \brief Specifies the external name that is visible in lists, + messages, etc. + */ + void setDisplayName( const QString& name ); + + + /*! \ingroup groupAdmin + \brief Returns the external name. + \return the external name used for display purposes + */ + QString displayName() const; + +private: + /*! \ingroup groupGeneral + \brief This function does two things: (a) load the lib and (b) set up all internal structures. + + The method tries to load the CRYPTPLUG library specified + in the constructor and returns \c true if the both <b>loading + and initializing</b> the internal data structures was successful + and \c false otherwise. Before this function is called, + no other plugin functions should be called; the behavior is + undefined in this case, this rule does not apply to the functions + \c setActive() and \c setLibName(). + + \param initStatus will receive the resulting InitStatus if not NULL + \param errorMsg will receive the system error message if not NULL + + \sa initStatus, deinitialize, CryptPlugWrapper(), ~CryptPlugWrapper + \sa setActive, active + */ + bool initialize( InitStatus* initStatus, QString* errorMsg ); + +public: + /*! \ingroup groupGeneral + \brief This function unloads the lib and frees all internal structures. + + After this function has been called, no other plugin functions + should be called; the behavior is undefined in this case. + + \note Deinitializing sets the internal initStatus value back + to \c InitStatus_undef. + + \sa initStatus, initialize, CryptPlugWrapper, ~CryptPlugWrapper + \sa setActive, active + */ + void deinitialize(); + + /*! \ingroup groupGeneral + \brief Returns this CRYPTPLUG wrapper's initialization state. + + \param errorMsg receives the last system error message, this value + should be ignored if InitStatus value equals \c InitStatus_Ok. + + \return whether the relative library was loaded and initialized + correctly + + \sa initialize, deinitialize, CryptPlugWrapper(), ~CryptPlugWrapper + \sa setActive, active + */ + InitStatus initStatus( QString* errorMsg ) const; + + + /*! \ingroup groupGeneral + \brief This function returns \c true if the + specified feature is available in the plugin, and + \c false otherwise. + + Not all plugins will support all features; a complete Sphinx + implementation will support all features contained in the enum, + however. + + \note In case this function cannot be executed the system's error + message may be retrieved by calling initStatus( QString* ). + + \return whether the relative feature is implemented or not + */ + bool hasFeature( ::Feature ); + + + /* \ingroup groupSignAct + * Frees the members of a signature meta data struct, but not the + * signature meta data struct itself as this could be allocated on + * the stack. + */ + void freeSignatureMetaData( CryptPlug::SignatureMetaData* ); + + /*! \ingroup groupSignAct + \brief Checks whether the signature of a message is + valid. + + \c cleartext must never be 0 but be a valid pointer. + + If \c *cleartext > 0 then **cleartext specifies the message text + that was signed and \c signaturetext is the signature itself. + + If \c *cleartext == 0 is an empty string then \c signaturetext is + supposed to contain an opaque signed message part. After checking the + data and verifying the signature the cleartext of the message will be + returned in \c cleartext. The user must free the respective memory + occupied by *cleartext. + + Depending on the configuration, MUAs might not need to use this. + If \c sigmeta is non-null, the + \c SignatureMetaData object pointed to will + contain meta information about the signature after the + function call. + */ + bool checkMessageSignature( char** cleartext, + const char* signaturetext, + bool signatureIsBinary, + int signatureLen, + CryptPlug::SignatureMetaData* sigmeta ); + + /*! \ingroup groupCryptAct + \brief Tries to decrypt an email message + \c ciphertext and returns the decrypted + message in \c cleartext. + + The \c certificate is used for decryption. If + the message could be decrypted, the function returns + \c true, otherwise + \c false. + */ + bool decryptMessage( const char* ciphertext, + bool cipherIsBinary, + int cipherLen, + char** cleartext, + const char* certificate, + int* errId, + char** errTxt ); + + /*! \ingroup groupCryptAct + \brief Combines the functionality of + \c checkMessageSignature() and + \c decryptMessage(). + + If \c certificate is \c NULL, + the default certificate will be used. If + \c sigmeta is non-null, the + \c SignatureMetaData object pointed to will + contain meta information about the signature after the + function call. + */ + bool decryptAndCheckMessage( const char* ciphertext, + bool cipherIsBinary, + int cipherLen, + char** cleartext, + const char* certificate, + bool* signatureFound, + CryptPlug::SignatureMetaData* sigmeta, + int* errId, + char** errTxt ); + + Kleo::KeyListJob * keyListJob( bool remote=false, bool includeSigs=false, bool validate=true ) const; + Kleo::EncryptJob * encryptJob( bool armor=false, bool textmode=false ) const; + Kleo::DecryptJob * decryptJob() const; + Kleo::SignJob * signJob( bool armor=false, bool textMode=false ) const; + Kleo::VerifyDetachedJob * verifyDetachedJob( bool textmode=false) const; + Kleo::VerifyOpaqueJob * verifyOpaqueJob( bool textmode=false ) const; + Kleo::KeyGenerationJob * keyGenerationJob() const; + + Kleo::ImportJob * importJob() const; + Kleo::ExportJob * publicKeyExportJob( bool armor=false ) const; + Kleo::ExportJob * secretKeyExportJob( bool armor=false, const QString& charset = QString::null ) const; + Kleo::DownloadJob * downloadJob( bool armor=false ) const; + Kleo::DeleteJob * deleteJob() const; + + Kleo::SignEncryptJob * signEncryptJob( bool armor=false, bool textmode=false ) const; + Kleo::DecryptVerifyJob * decryptVerifyJob( bool textmode=false ) const; + Kleo::RefreshKeysJob * refreshKeysJob() const; + + Kleo::SpecialJob * specialJob( const char *, const QMap<QString,QVariant> & ) const { return 0; } + + GpgME::ImportResult importCertificate( const char* data, size_t length ); + + CryptPlug * cryptPlug() const { return _cp; } + +private: + QString _name; + QString _libName; + QString _updateURL; + bool _active; + InitStatus _initStatus; + QString _lastError; + CryptPlug* _cp; + // local parameters without representation in cryptplug.h + bool mAlwaysEncryptToSelf; + class Config; + Config * _config; + QGpgMECryptoConfig * _cryptoConfig; +}; + +#endif // !LIBKLEOPATRA_NO_COMPAT + +#endif // cryptplugwrapper_h diff --git a/certmanager/lib/cryptplugwrapperlist.cpp b/certmanager/lib/cryptplugwrapperlist.cpp new file mode 100644 index 000000000..3ff38ddd8 --- /dev/null +++ b/certmanager/lib/cryptplugwrapperlist.cpp @@ -0,0 +1,34 @@ +/* -*- c++ -*- + + CRYPTPLUG - an independent cryptography plug-in + API. CryptPlugWrapperList holds any number of crypto plug-ins. + + Copyright (C) 2001 by Klarälvdalens Datakonsult AB + + CRYPTPLUG is free software; you can redistribute it and/or modify + it under the terms of GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + CRYPTPLUG is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "cryptplugwrapperlist.h" + +CryptPlugWrapper * CryptPlugWrapperList::findForLibName( const QString & libName ) const +{ + for ( QPtrListIterator<CryptPlugWrapper> it( *this ) ; it.current() ; ++it ) + if ( (*it)->libName().find( libName, 0, false ) >= 0 ) + return *it; + return 0; +} diff --git a/certmanager/lib/cryptplugwrapperlist.h b/certmanager/lib/cryptplugwrapperlist.h new file mode 100644 index 000000000..3fab5799c --- /dev/null +++ b/certmanager/lib/cryptplugwrapperlist.h @@ -0,0 +1,37 @@ +/* -*- Mode: C++ -*- + + CRYPTPLUG - an independent cryptography plug-in + API. CryptPlugWrapperList holds any number of crypto plug-ins. + + Copyright (C) 2001,2004 by Klarälvdalens Datakonsult AB + + CRYPTPLUG is free software; you can redistribute it and/or modify + it under the terms of GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + CRYPTPLUG is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +*/ + +#ifndef __CRYPTPLUGWRAPPERLIST_H__ +#define __CRYPTPLUGWRAPPERLIST_H__ + +#include "cryptplugwrapper.h" + +#include <qptrlist.h> + +class CryptPlugWrapperList : public QPtrList<CryptPlugWrapper> +{ +public: + CryptPlugWrapper * findForLibName( const QString & libName ) const; +}; + +typedef QPtrListIterator<CryptPlugWrapper> CryptPlugWrapperListIterator; + +#endif diff --git a/certmanager/lib/kleo/Makefile.am b/certmanager/lib/kleo/Makefile.am new file mode 100644 index 000000000..0465bb2da --- /dev/null +++ b/certmanager/lib/kleo/Makefile.am @@ -0,0 +1,37 @@ +INCLUDES = -I$(top_srcdir)/libkdenetwork \ + -I$(top_srcdir)/certmanager/lib \ + $(GPGME_CFLAGS) $(all_includes) + +noinst_LTLIBRARIES = libkleopatra_core.la + +libkleopatra_core_la_SOURCES = \ + cryptobackend.cpp \ + cryptobackendfactory.cpp \ + enum.cpp \ + dn.cpp \ + job.cpp \ + \ + multideletejob.cpp \ + hierarchicalkeylistjob.cpp \ + \ + kconfigbasedkeyfilter.cpp \ + keyfiltermanager.cpp + +kleodir = $(includedir)/kleo +kleo_HEADERS = \ + enum.h \ + cryptobackend.h \ + cryptobackendfactory.h \ + cryptoconfig.h \ + dn.h \ + job.h \ + keylistjob.h keygenerationjob.h importjob.h exportjob.h downloadjob.h deletejob.h \ + encryptjob.h decryptjob.h signjob.h verifydetachedjob.h verifyopaquejob.h \ + decryptverifyjob.h signencryptjob.h refreshkeysjob.h \ + multideletejob.h \ + hierarchicalkeylistjob.h \ + \ + keyfilter.h \ + keyfiltermanager.h + +METASOURCES = AUTO diff --git a/certmanager/lib/kleo/cryptobackend.cpp b/certmanager/lib/kleo/cryptobackend.cpp new file mode 100644 index 000000000..7a779c8ed --- /dev/null +++ b/certmanager/lib/kleo/cryptobackend.cpp @@ -0,0 +1,36 @@ +/* + kleo/cryptobackend.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2005 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "cryptobackend.h" + +const char Kleo::CryptoBackend::OpenPGP[] = "OpenPGP"; +const char Kleo::CryptoBackend::SMIME[] = "SMIME"; diff --git a/certmanager/lib/kleo/cryptobackend.h b/certmanager/lib/kleo/cryptobackend.h new file mode 100644 index 000000000..a94e1ae3a --- /dev/null +++ b/certmanager/lib/kleo/cryptobackend.h @@ -0,0 +1,122 @@ +/* + kleo/cryptobackend.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004,2005 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_CRYPTOBACKEND_H__ +#define __KLEO_CRYPTOBACKEND_H__ + +#include <qstring.h> + +namespace Kleo { + class CryptoConfig; + class KeyListJob; + class KeyGenerationJob; + class ImportJob; + class ExportJob; + class DownloadJob; + class DeleteJob; + class EncryptJob; + class DecryptJob; + class SignJob; + class VerifyDetachedJob; + class VerifyOpaqueJob; + class SignEncryptJob; + class DecryptVerifyJob; + class RefreshKeysJob; + class SpecialJob; +} + +class QString; +class QVariant; +template <typename T_Key, typename T_Value> class QMap; + +namespace Kleo { + + class CryptoBackend { + public: + class Protocol; + + static const char OpenPGP[]; + static const char SMIME[]; + + virtual ~CryptoBackend() {} + + virtual QString name() const = 0; + virtual QString displayName() const = 0; + + virtual bool checkForOpenPGP( QString * reason=0 ) const = 0; + virtual bool checkForSMIME( QString * reason=0 ) const = 0; + virtual bool checkForProtocol( const char * name, QString * reason=0 ) const = 0; + + virtual bool supportsOpenPGP() const = 0; + virtual bool supportsSMIME() const = 0; + virtual bool supportsProtocol( const char * name ) const = 0; + + virtual CryptoConfig * config() const = 0; + + virtual Protocol * openpgp() const = 0; + virtual Protocol * smime() const = 0; + virtual Protocol * protocol( const char * name ) const = 0; + + virtual const char * enumerateProtocols( int i ) const = 0; + }; + + class CryptoBackend::Protocol { + public: + virtual ~Protocol() {} + + virtual QString name() const = 0; + + virtual QString displayName() const = 0; + + virtual KeyListJob * keyListJob( bool remote=false, bool includeSigs=false, bool validate=false ) const = 0; + virtual EncryptJob * encryptJob( bool armor=false, bool textmode=false ) const = 0; + virtual DecryptJob * decryptJob() const = 0; + virtual SignJob * signJob( bool armor=false, bool textMode=false ) const = 0; + virtual VerifyDetachedJob * verifyDetachedJob( bool textmode=false) const = 0; + virtual VerifyOpaqueJob * verifyOpaqueJob( bool textmode=false ) const = 0; + virtual KeyGenerationJob * keyGenerationJob() const = 0; + virtual ImportJob * importJob() const = 0; + virtual ExportJob * publicKeyExportJob( bool armor=false ) const = 0; + // @param charset the encoding of the passphrase in the exported file + virtual ExportJob * secretKeyExportJob( bool armor=false, const QString& charset = QString::null ) const = 0; + virtual DownloadJob * downloadJob( bool armor=false ) const = 0; + virtual DeleteJob * deleteJob() const = 0; + virtual SignEncryptJob * signEncryptJob( bool armor=false, bool textMode=false ) const = 0; + virtual DecryptVerifyJob * decryptVerifyJob( bool textmode=false ) const = 0; + virtual RefreshKeysJob * refreshKeysJob() const = 0; + + virtual SpecialJob * specialJob( const char * type, const QMap<QString,QVariant> & args ) const = 0; + }; + +} + +#endif // __KLEO_CRYPTOBACKEND_H__ diff --git a/certmanager/lib/kleo/cryptobackendfactory.cpp b/certmanager/lib/kleo/cryptobackendfactory.cpp new file mode 100644 index 000000000..c56a7096f --- /dev/null +++ b/certmanager/lib/kleo/cryptobackendfactory.cpp @@ -0,0 +1,275 @@ +/* + cryptobackendfactory.cpp + + This file is part of libkleopatra, the KDE key management library + Copyright (c) 2001,2004,2005 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "cryptobackendfactory.h" + +#include <backends/qgpgme/qgpgmebackend.h> +#if 0 // disabled for kde-3.3 +#include <backends/kpgp/pgp2backend.h> +#include <backends/kpgp/pgp5backend.h> +#include <backends/kpgp/pgp6backend.h> +#include <backends/kpgp/gpg1backend.h> +#endif +#include <backends/chiasmus/chiasmusbackend.h> +#include <ui/backendconfigwidget.h> + +#include <kconfig.h> +#include <klocale.h> +#include <kdebug.h> +#include <kmessagebox.h> +#include <kapplication.h> + +#include <iterator> +#include <algorithm> + +#include <cassert> + +Kleo::CryptoBackendFactory * Kleo::CryptoBackendFactory::mSelf = 0; + +static const char * availableProtocols[] = { + "Chiasmus", + "OpenPGP", "SMIME", +}; +static const unsigned int numAvailableProtocols = sizeof availableProtocols / sizeof *availableProtocols; + +Kleo::CryptoBackendFactory::CryptoBackendFactory() + : QObject( qApp, "CryptoBackendFactory::instance()" ), + mConfigObject( 0 ), + mAvailableProtocols( availableProtocols, availableProtocols + numAvailableProtocols ) +{ + mBackendList.push_back( new QGpgMEBackend() ); +#if 0 // disabled for kde-3.3 + mBackendList.push_back( new PGP2Backend() ); + mBackendList.push_back( new PGP5Backend() ); + mBackendList.push_back( new PGP6Backend() ); + mBackendList.push_back( new GPG1Backend() ); +#endif + mBackendList.push_back( new ChiasmusBackend() ); + scanForBackends(); + readConfig(); + + mSelf = this; // last! +} + +Kleo::CryptoBackendFactory::~CryptoBackendFactory() { + mSelf = 0; // first! + + for ( std::vector<CryptoBackend*>::iterator it = mBackendList.begin() ; it != mBackendList.end() ; ++it ) { + delete *it; + *it = 0; + } + delete mConfigObject; + mConfigObject = 0; +} + +Kleo::CryptoBackendFactory * Kleo::CryptoBackendFactory::instance() { + if ( !mSelf ) + mSelf = new CryptoBackendFactory(); + return mSelf; +} + + +// const Kleo::CryptoBackend* Kleo::CryptoBackendFactory::smimeBackend() const { +// return mSMIMEBackend; +// } + +// const Kleo::CryptoBackend* Kleo::CryptoBackendFactory::openpgpBackend() const { +// return mOpenPGPBackend; +// } + +const Kleo::CryptoBackend::Protocol * Kleo::CryptoBackendFactory::smime() const { + const BackendMap::const_iterator it = mBackends.find( "SMIME" ); + if ( it == mBackends.end() ) + return 0; + if ( !it->second ) + return 0; + return it->second->smime(); +} + +const Kleo::CryptoBackend::Protocol * Kleo::CryptoBackendFactory::openpgp() const { + const BackendMap::const_iterator it = mBackends.find( "OpenPGP" ); + if ( it == mBackends.end() ) + return 0; + if ( !it->second ) + return 0; + return it->second->openpgp(); +} + +const Kleo::CryptoBackend::Protocol * Kleo::CryptoBackendFactory::protocol( const char * name ) const { + const BackendMap::const_iterator it = mBackends.find( name ); + if ( it == mBackends.end() ) + return 0; + if ( !it->second ) + return 0; + return it->second->protocol( name ); +} + +Kleo::CryptoConfig * Kleo::CryptoBackendFactory::config() const { + // ## should we use mSMIMEBackend? mOpenPGPBackend? backend(0) i.e. always qgpgme? + return backend( 0 ) ? backend( 0 )->config() : 0; +} + +bool Kleo::CryptoBackendFactory::hasBackends() const { + return !mBackendList.empty(); +} + +void Kleo::CryptoBackendFactory::scanForBackends( QStringList * reasons ) { + for ( std::vector<CryptoBackend*>::const_iterator it = mBackendList.begin() ; it != mBackendList.end() ; ++it ) { + assert( *it ); + for ( int i = 0 ; const char * protocol = (*it)->enumerateProtocols( i ) ; ++i ) { + QString reason; + if ( (*it)->supportsProtocol( protocol ) && !(*it)->checkForProtocol( protocol, &reason ) ) { + if ( reasons ) { + reasons->push_back( i18n("While scanning for %1 support in backend %2:") + .arg( protocol, (*it)->displayName() ) ); + reasons->push_back( " " + reason ); + } + } + } + } +} + +const Kleo::CryptoBackend * Kleo::CryptoBackendFactory::backend( unsigned int idx ) const { + return ( idx < mBackendList.size() ) ? mBackendList[idx] : 0 ; +} + +const Kleo::CryptoBackend * Kleo::CryptoBackendFactory::backendByName( const QString& name ) const { + for ( std::vector<CryptoBackend*>::const_iterator it = mBackendList.begin() ; it != mBackendList.end() ; ++it ) { + if ( (*it)->name() == name ) + return *it; + } + return 0; +} + +Kleo::BackendConfigWidget * Kleo::CryptoBackendFactory::configWidget( QWidget * parent, const char * name ) const { + return new Kleo::BackendConfigWidget( mSelf, parent, name ); +} + +KConfig* Kleo::CryptoBackendFactory::configObject() const { + if ( !mConfigObject ) + // this is unsafe. We're a lib, used by concurrent apps. + mConfigObject = new KConfig( "libkleopatrarc" ); + return mConfigObject; +} + +void Kleo::CryptoBackendFactory::setSMIMEBackend( const CryptoBackend* backend ) { + setProtocolBackend( "SMIME", backend ); +} + +void Kleo::CryptoBackendFactory::setOpenPGPBackend( const CryptoBackend* backend ) { + setProtocolBackend( "OpenPGP", backend ); +} + +void Kleo::CryptoBackendFactory::setProtocolBackend( const char * protocol, const CryptoBackend * backend ) { + const QString name = backend ? backend->name() : QString::null ; + KConfigGroup group( configObject(), "Backends" ); + group.writeEntry( protocol, name ); + configObject()->sync(); + mBackends[protocol] = backend; +} + +static const char * defaultBackend( const char * proto ) { + static const struct { + const char * proto; + const char * backend; + } defaults[] = { + { "OpenPGP", "gpgme" }, + { "SMIME", "gpgme" }, + { "Chiasmus", "chiasmus" }, + }; + for ( unsigned int i = 0 ; i < sizeof defaults / sizeof *defaults ; ++i ) + if ( qstricmp( proto, defaults[i].proto ) == 0 ) + return defaults[i].backend; + return 0; +} + +void Kleo::CryptoBackendFactory::readConfig() { + mBackends.clear(); + const KConfigGroup group( configObject(), "Backends" ); + for ( ProtocolSet::const_iterator it = mAvailableProtocols.begin(), end = mAvailableProtocols.end() ; it != end ; ++it ) { + const QString backend = group.readEntry( *it, defaultBackend( *it ) ); + mBackends[*it] = backendByName( backend ); + } +} + +const char * Kleo::CryptoBackendFactory::enumerateProtocols( int i ) const { + if ( i < 0 || static_cast<unsigned int>( i ) >= mAvailableProtocols.size() ) + return 0; + return mAvailableProtocols[i]; +} + +namespace { + class CaseInsensitiveString { + const char * m; + public: + CaseInsensitiveString( const char * s ) : m( s ) {} +#define make_operator( op ) \ + bool operator op( const CaseInsensitiveString & other ) const { \ + return qstricmp( m, other.m ) op 0; \ + } \ + bool operator op( const char * other ) const { \ + return qstricmp( m, other ) op 0; \ + } + make_operator( == ) + make_operator( != ) + make_operator( < ) + make_operator( > ) + make_operator( <= ) + make_operator( >= ) +#undef make_operator + operator const char *() const { return m; } + }; +#define make_ext_operator( op, inv_op ) \ + inline bool operator op( const char * lhs, const CaseInsensitiveString & rhs ) { \ + return rhs.operator inv_op( lhs ); \ + } + make_ext_operator( ==, == ) + make_ext_operator( !=, != ) + make_ext_operator( <, > ) + make_ext_operator( >, < ) + make_ext_operator( <=, >= ) + make_ext_operator( >=, <= ) +#undef make_ext_operator + +} + +bool Kleo::CryptoBackendFactory::knowsAboutProtocol( const char * name ) const { + return std::find( mAvailableProtocols.begin(), mAvailableProtocols.end(), + CaseInsensitiveString( name ) ) != mAvailableProtocols.end(); +} + +#include "cryptobackendfactory.moc" + diff --git a/certmanager/lib/kleo/cryptobackendfactory.h b/certmanager/lib/kleo/cryptobackendfactory.h new file mode 100644 index 000000000..7a54e9fd1 --- /dev/null +++ b/certmanager/lib/kleo/cryptobackendfactory.h @@ -0,0 +1,117 @@ +/* + kleo/cryptobackendfactory.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004,2005 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_CRYPTOBACKENDFACTORY_H__ +#define __KLEO_CRYPTOBACKENDFACTORY_H__ + +#include <qobject.h> + +#include "cryptobackend.h" +#include <kdepimmacros.h> + +#include <vector> +#include <map> + +namespace Kleo { + class BackendConfigWidget; +} + +class QString; +class KConfig; + +namespace Kleo { + + struct lt_i_str { + bool operator()( const char * one, const char * two ) const { + return qstricmp( one, two ) < 0; + } + }; + + class KDE_EXPORT CryptoBackendFactory : public QObject { + Q_OBJECT + protected: + CryptoBackendFactory(); + ~CryptoBackendFactory(); + public: + static CryptoBackendFactory * instance(); + + const CryptoBackend::Protocol * smime() const; + const CryptoBackend::Protocol * openpgp() const; + const CryptoBackend::Protocol * protocol( const char * name ) const; + CryptoConfig * config() const; + + const CryptoBackend * backend( unsigned int idx ) const; + + bool hasBackends() const; + + Kleo::BackendConfigWidget * configWidget( QWidget * parent=0, const char * name=0 ) const; + + KConfig* configObject() const; + + // The preferred backend for smime (can be 0) - currently unused + //const CryptoBackend* smimeBackend() const; + // The preferred backend for openpgp (can be 0) - currently unused + //const CryptoBackend* openpgpBackend() const; + + // For BackendConfigWidget to save the configuration + // 0 means no backend selected. + void setSMIMEBackend( const CryptoBackend* backend ); + void setOpenPGPBackend( const CryptoBackend* backend ); + void setProtocolBackend( const char * name, const CryptoBackend * backend ); + + void scanForBackends( QStringList * reasons=0 ); + + const char * enumerateProtocols( int i ) const; + + bool knowsAboutProtocol( const char * name ) const; + + protected: + std::vector<CryptoBackend*> mBackendList; + mutable KConfig* mConfigObject; + typedef std::map<const char *, const CryptoBackend*, lt_i_str> BackendMap; + BackendMap mBackends; + typedef std::vector<const char *> ProtocolSet; + ProtocolSet mAvailableProtocols; + + private: + const CryptoBackend * backendByName( const QString& name ) const; + void readConfig(); + CryptoBackendFactory( const CryptoBackendFactory & ); + void operator=( const CryptoBackendFactory & ); + + static CryptoBackendFactory * mSelf; + }; + + +} + +#endif // __KLEO_CRYPTOBACKENDFACTORY_H__ diff --git a/certmanager/lib/kleo/cryptoconfig.h b/certmanager/lib/kleo/cryptoconfig.h new file mode 100644 index 000000000..da16ca5b5 --- /dev/null +++ b/certmanager/lib/kleo/cryptoconfig.h @@ -0,0 +1,387 @@ +/* + cryptoconfig.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef CRYPTOCONFIG_H +#define CRYPTOCONFIG_H + +#ifdef __cplusplus +/* we read this file from a C compiler, and are only interested in the + * enums... */ + +#include <kurl.h> + +/* Start reading this file from the bottom up :) */ + +namespace Kleo { + + /** + * Description of a single option + */ + class CryptoConfigEntry { + + public: +#endif /* __cplusplus */ + /** + @li basic This option should always be offered to the user. + @li advanced This option may be offered to advanced users. + @li expert This option should only be offered to expert users. + */ + enum Level { Level_Basic = 0, + Level_Advanced = 1, + Level_Expert = 2 }; + + /** + Type of the argument + @li ArgType_None The option is set or not set, but no argument. + @li ArgType_String An unformatted string. + @li ArgType_Int A signed integer number. + @li ArgType_UInt An unsigned integer number. + @li ArgType_Path A string that describes the pathname of a file. + The file does not necessarily need to exist. + Separated from string so that e.g. a KURLRequester can be used. + @li ArgType_DirPath A string that describes the pathname of a directory. + The directory does not necessarily need to exist. + Separated from path so that e.g. a KURLRequester can be used which only + allows directories to be selected. + @li ArgType_URL A URL + @li ArgType_LDAPURL A LDAP URL + Separated from URL so that a more specific widget can be shown, hiding the url syntax + */ + enum ArgType { ArgType_None = 0, + ArgType_String = 1, + ArgType_Int = 2, + ArgType_UInt = 3, + ArgType_Path = 4, + ArgType_URL = 5, + ArgType_LDAPURL = 6, + ArgType_DirPath = 7 }; + +#ifdef __cplusplus + virtual ~CryptoConfigEntry() {} + + /** + * Return the internal name of this entry + */ + virtual QString name() const = 0; + + /** + * @return user-visible description of this entry + */ + virtual QString description() const = 0; + + /** + * @return true if the argument is optional + */ + virtual bool isOptional() const = 0; + + /** + * @return true if the entry is readonly + */ + virtual bool isReadOnly() const = 0; + + /** + * @return true if the argument can be given multiple times + */ + virtual bool isList() const = 0; + + /** + * @return true if the argument can be changed at runtime + */ + virtual bool isRuntime() const = 0; + + /** + * User level + */ + virtual Level level() const = 0; + + /** + * Argument type + */ + virtual ArgType argType() const = 0; + + /** + * Return true if the option is set, i.e. different from default + */ + virtual bool isSet() const = 0; + + /** + * Return value as a bool (only allowed for ArgType_None) + */ + virtual bool boolValue() const = 0; + + /** + * Return value as a string (available for all argtypes) + * The returned string can be empty (explicitely set to empty) or null (not set). + */ + virtual QString stringValue() const = 0; + + /** + * Return value as a signed int + */ + virtual int intValue() const = 0; + + /** + * Return value as an unsigned int + */ + virtual unsigned int uintValue() const = 0; + + /** + * Return value as a URL (only meaningful for Path and URL argtypes) + */ + virtual KURL urlValue() const = 0; + + /** + * Return number of times the option is set (only valid for ArgType_None, if isList()) + */ + virtual unsigned int numberOfTimesSet() const = 0; + + /** + * Return value as a list of strings (mostly meaningful for String, Path and URL argtypes, if isList()) + */ + virtual QStringList stringValueList() const = 0; + + /** + * Return value as a list of signed ints + */ + virtual QValueList<int> intValueList() const = 0; + + /** + * Return value as a list of unsigned ints + */ + virtual QValueList<unsigned int> uintValueList() const = 0; + + /** + * Return value as a list of URLs (only meaningful for Path and URL argtypes, if isList()) + */ + virtual KURL::List urlValueList() const = 0; + + /** + * Reset an option to its default value + */ + virtual void resetToDefault() = 0; + + /** + * Define whether the option is set or not (only allowed for ArgType_None) + * #### TODO: and for options with optional args + */ + virtual void setBoolValue( bool ) = 0; + + /** + * Set string value (allowed for all argtypes) + */ + virtual void setStringValue( const QString& ) = 0; + + /** + * Set a new signed int value + */ + virtual void setIntValue( int ) = 0; + + /** + * Set a new unsigned int value + */ + virtual void setUIntValue( unsigned int ) = 0; + + /** + * Set value as a URL (only meaningful for Path (if local) and URL argtypes) + */ + virtual void setURLValue( const KURL& ) = 0; + + /** + * Set the number of times the option is set (only valid for ArgType_None, if isList()) + */ + virtual void setNumberOfTimesSet( unsigned int ) = 0; + + /** + * Set a new string-list value (only allowed for String, Path and URL argtypes, if isList()) + */ + virtual void setStringValueList( const QStringList& ) = 0; + + /** + * Set a new list of signed int values + */ + virtual void setIntValueList( const QValueList<int>& ) = 0; + + /** + * Set a new list of unsigned int values + */ + virtual void setUIntValueList( const QValueList<unsigned int>& ) = 0; + + /** + * Set value as a URL list (only meaningful for Path (if all URLs are local) and URL argtypes, if isList()) + */ + virtual void setURLValueList( const KURL::List& ) = 0; + + /** + * @return true if the value was changed + */ + virtual bool isDirty() const = 0; + }; + + /** + * Group containing a set of config options + */ + class CryptoConfigGroup { + + public: + virtual ~CryptoConfigGroup() {} + + /** + * Return the internal name of this group + */ + virtual QString name() const = 0; + + /** + * Return the name of the icon for this group + */ + virtual QString iconName() const = 0; + + /** + * @return user-visible description of this group + */ + virtual QString description() const = 0; + + /** + * User level + */ + virtual CryptoConfigEntry::Level level() const = 0; + + /** + * Returns the list of entries that are known by this group. + * + * @return list of group entry names. + **/ + virtual QStringList entryList() const = 0; + + /** + * @return the configuration object for a given entry in this group + * The object is owned by CryptoConfigGroup, don't delete it. + * Groups cannot be nested, so all entries returned here are pure entries, no groups. + */ + virtual CryptoConfigEntry* entry( const QString& name ) const = 0; + }; + + /** + * Crypto config for one component (e.g. gpg-agent, dirmngr etc.) + */ + class CryptoConfigComponent { + + public: + virtual ~CryptoConfigComponent() {} + + /** + * Return the internal name of this component + */ + virtual QString name() const = 0; + + /** + * Return the name of the icon for this component + */ + virtual QString iconName() const = 0; + + /** + * Return user-visible description of this component + */ + virtual QString description() const = 0; + + /** + * Returns the list of groups that are known about. + * + * @return list of group names. One of them can be "<nogroup>", which is the group where all + * "toplevel" options (belonging to no group) are. + */ + virtual QStringList groupList() const = 0; + + /** + * @return the configuration object for a given group + * The object is owned by CryptoConfigComponent, don't delete it. + */ + virtual CryptoConfigGroup* group( const QString& name ) const = 0; + + }; + + /** + * Main interface to crypto configuration. + */ + class CryptoConfig { + + public: + virtual ~CryptoConfig() {} + + /** + * Returns the list of known components (e.g. "gpg-agent", "dirmngr" etc.). + * Use @ref component() to retrieve more information about each one. + * @return list of component names. + **/ + virtual QStringList componentList() const = 0; + + /** + * @return the configuration object for a given component + * The object is owned by CryptoConfig, don't delete it. + */ + virtual CryptoConfigComponent* component( const QString& name ) const = 0; + + /** + * Convenience method to get hold of a single configuration entry when + * its component, group and name are known. This can be used to read + * the value and/or to set a value to it. + * + * @return the configuration object for a single configuration entry, 0 if not found. + * The object is owned by CryptoConfig, don't delete it. + */ + CryptoConfigEntry* entry( const QString& componentName, const QString& groupName, const QString& entryName ) const { + const Kleo::CryptoConfigComponent* comp = component( componentName ); + const Kleo::CryptoConfigGroup* group = comp ? comp->group( groupName ) : 0; + return group ? group->entry( entryName ) : 0; + } + + /** + * Write back changes + * + * @param runtime If this option is set, the changes will take effect at run-time, as + * far as this is possible. Otherwise, they will take effect at the next + * start of the respective backend programs. + */ + virtual void sync( bool runtime ) = 0; + + /** + * Tells the CryptoConfig to discard any cached information, including + * all components, groups and entries. + * Call this to free some memory when you won't be using the object + * for some time. + * DON'T call this if you're holding pointers to components, groups or entries. + */ + virtual void clear() = 0; + }; + +} +#endif /* __cplusplus */ +#endif /* CRYPTOCONFIG_H */ diff --git a/certmanager/lib/kleo/decryptjob.h b/certmanager/lib/kleo/decryptjob.h new file mode 100644 index 000000000..e882152a0 --- /dev/null +++ b/certmanager/lib/kleo/decryptjob.h @@ -0,0 +1,84 @@ +/* + decryptjob.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_DECRYPTJOB_H__ +#define __KLEO_DECRYPTJOB_H__ + +#include "job.h" + +#include <qcstring.h> + +namespace GpgME { + class Error; + class Key; + class DecryptionResult; +} + + +namespace Kleo { + + /** + @short An abstract base class for asynchronous decrypters + + To use a DecryptJob, first obtain an instance from the + CryptoBackend implementation, connect the progress() and result() + signals to suitable slots and then start the decryption with a + call to start(). This call might fail, in which case the + DecryptJob instance will have scheduled it's own destruction with + a call to QObject::deleteLater(). + + After result() is emitted, the DecryptJob will schedule it's own + destruction by calling QObject::deleteLater(). + */ + class DecryptJob : public Job { + Q_OBJECT + protected: + DecryptJob( QObject * parent, const char * name ); + public: + ~DecryptJob(); + + /** + Starts the decryption operation. \a cipherText is the data to + decrypt. + */ + virtual GpgME::Error start( const QByteArray & cipherText ) = 0; + + virtual GpgME::DecryptionResult exec( const QByteArray & cipherText, + QByteArray & plainText ) = 0; + + signals: + void result( const GpgME::DecryptionResult & result, const QByteArray & plainText ); + }; + +} + +#endif // __KLEO_DECRYPTJOB_H__ diff --git a/certmanager/lib/kleo/decryptverifyjob.h b/certmanager/lib/kleo/decryptverifyjob.h new file mode 100644 index 000000000..f7cdb81a1 --- /dev/null +++ b/certmanager/lib/kleo/decryptverifyjob.h @@ -0,0 +1,90 @@ +/* + decryptverifyjob.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_DECRYPTVERIFYJOB_H__ +#define __KLEO_DECRYPTVERIFYJOB_H__ + +#include "job.h" + +#include <qcstring.h> + +#include <utility> + +namespace GpgME { + class Error; + class Key; + class DecryptionResult; + class VerificationResult; +} + + +namespace Kleo { + + /** + @short An abstract base class for asynchronous combined decrypters and verifiers + + To use a DecryptVerifyJob, first obtain an instance from the + CryptoBackend implementation, connect the progress() and result() + signals to suitable slots and then start the operation with a + call to start(). This call might fail, in which case the + DecryptVerifyJob instance will have scheduled it's own destruction with + a call to QObject::deleteLater(). + + After result() is emitted, the DecryptVerifyJob will schedule it's own + destruction by calling QObject::deleteLater(). + */ + class DecryptVerifyJob : public Job { + Q_OBJECT + protected: + DecryptVerifyJob( QObject * parent, const char * name ); + public: + ~DecryptVerifyJob(); + + /** + Starts the combined decryption and verification operation. + \a cipherText is the data to decrypt and later verify. + */ + virtual GpgME::Error start( const QByteArray & cipherText ) = 0; + + /** Synchronous equivalent of start() */ + virtual std::pair<GpgME::DecryptionResult,GpgME::VerificationResult> + exec( const QByteArray & cipherText, QByteArray & plainText ) = 0; + + signals: + void result( const GpgME::DecryptionResult & decryptionresult, + const GpgME::VerificationResult & verificationresult, + const QByteArray & plainText ); + }; + +} + +#endif // __KLEO_DECRYPTVERIFYJOB_H__ diff --git a/certmanager/lib/kleo/deletejob.h b/certmanager/lib/kleo/deletejob.h new file mode 100644 index 000000000..fd70ec513 --- /dev/null +++ b/certmanager/lib/kleo/deletejob.h @@ -0,0 +1,78 @@ +/* + deletejob.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_DELETEJOB_H__ +#define __KLEO_DELETEJOB_H__ + +#include "job.h" + +namespace GpgME { + class Error; + class Key; +} + +namespace Kleo { + + /** + @short An abstract base class for asynchronous deleters + + To use a DeleteJob, first obtain an instance from the + CryptoBackend implementation, connect the progress() and result() + signals to suitable slots and then start the delete with a call + to start(). This call might fail, in which case the DeleteJob + instance will have scheduled it's own destruction with a call to + QObject::deleteLater(). + + After result() is emitted, the DeleteJob will schedule it's own + destruction by calling QObject::deleteLater(). + */ + class DeleteJob : public Job { + Q_OBJECT + protected: + DeleteJob( QObject * parent, const char * name ); + public: + ~DeleteJob(); + + /** + Starts the delete operation. \a key represents the key to + delete, \a allowSecretKeyDeletion specifies if a key may also + be deleted if the secret key part is available, too. + */ + virtual GpgME::Error start( const GpgME::Key & key, bool allowSecretKeyDeletion=false ) = 0; + + signals: + void result( const GpgME::Error & result ); + }; + +} + +#endif // __KLEO_DELETEJOB_H__ diff --git a/certmanager/lib/kleo/dn.cpp b/certmanager/lib/kleo/dn.cpp new file mode 100644 index 000000000..9ba2209fb --- /dev/null +++ b/certmanager/lib/kleo/dn.cpp @@ -0,0 +1,538 @@ +/* + dn.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + DN parsing: + Copyright (c) 2002 g10 Code GmbH + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "dn.h" + +#include "oidmap.h" +#include "ui/dnattributeorderconfigwidget.h" + +#include <kapplication.h> +#include <kconfig.h> +#include <klocale.h> + +#include <qstringlist.h> +#include <qvaluevector.h> + +#include <iostream> +#include <iterator> +#include <algorithm> +#include <map> + +#include <string.h> +#include <ctype.h> +#include <stdlib.h> + +struct Kleo::DN::Private { + Private() : mRefCount( 0 ) {} + Private( const Private & other ) + : attributes( other.attributes ), + reorderedAttributes( other.reorderedAttributes ), + mRefCount( 0 ) + { + + } + + int ref() { + return ++mRefCount; + } + + int unref() { + if ( --mRefCount <= 0 ) { + delete this; + return 0; + } else + return mRefCount; + } + + int refCount() const { return mRefCount; } + + DN::Attribute::List attributes; + DN::Attribute::List reorderedAttributes; +private: + int mRefCount; +}; + +namespace { + struct DnPair { + char * key; + char * value; + }; +} + +// copied from CryptPlug and adapted to work on DN::Attribute::List: + +#define digitp(p) (*(p) >= '0' && *(p) <= '9') +#define hexdigitp(a) (digitp (a) \ + || (*(a) >= 'A' && *(a) <= 'F') \ + || (*(a) >= 'a' && *(a) <= 'f')) +#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \ + *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10)) +#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1)) + +static char * +trim_trailing_spaces( char *string ) +{ + char *p, *mark; + + for( mark = NULL, p = string; *p; p++ ) { + if( isspace( *p ) ) { + if( !mark ) + mark = p; + } + else + mark = NULL; + } + if( mark ) + *mark = '\0' ; + + return string ; +} + +/* Parse a DN and return an array-ized one. This is not a validating + parser and it does not support any old-stylish syntax; gpgme is + expected to return only rfc2253 compatible strings. */ +static const unsigned char * +parse_dn_part (DnPair *array, const unsigned char *string) +{ + const unsigned char *s, *s1; + size_t n; + char *p; + + /* parse attributeType */ + for (s = string+1; *s && *s != '='; s++) + ; + if (!*s) + return NULL; /* error */ + n = s - string; + if (!n) + return NULL; /* empty key */ + p = (char*)malloc (n+1); + + + memcpy (p, string, n); + p[n] = 0; + trim_trailing_spaces ((char*)p); + // map OIDs to their names: + for ( unsigned int i = 0 ; i < numOidMaps ; ++i ) + if ( !strcasecmp ((char*)p, oidmap[i].oid) ) { + free( p ); + p = strdup( oidmap[i].name ); + break; + } + array->key = p; + string = s + 1; + + if (*string == '#') + { /* hexstring */ + string++; + for (s=string; hexdigitp (s); s++) + s++; + n = s - string; + if (!n || (n & 1)) + return NULL; /* empty or odd number of digits */ + n /= 2; + array->value = p = (char*)malloc (n+1); + + + for (s1=string; n; s1 += 2, n--) + *p++ = xtoi_2 (s1); + *p = 0; + } + else + { /* regular v3 quoted string */ + for (n=0, s=string; *s; s++) + { + if (*s == '\\') + { /* pair */ + s++; + if (*s == ',' || *s == '=' || *s == '+' + || *s == '<' || *s == '>' || *s == '#' || *s == ';' + || *s == '\\' || *s == '\"' || *s == ' ') + n++; + else if (hexdigitp (s) && hexdigitp (s+1)) + { + s++; + n++; + } + else + return NULL; /* invalid escape sequence */ + } + else if (*s == '\"') + return NULL; /* invalid encoding */ + else if (*s == ',' || *s == '=' || *s == '+' + || *s == '<' || *s == '>' || *s == '#' || *s == ';' ) + break; + else + n++; + } + + array->value = p = (char*)malloc (n+1); + + + for (s=string; n; s++, n--) + { + if (*s == '\\') + { + s++; + if (hexdigitp (s)) + { + *p++ = xtoi_2 (s); + s++; + } + else + *p++ = *s; + } + else + *p++ = *s; + } + *p = 0; + } + return s; +} + + +/* Parse a DN and return an array-ized one. This is not a validating + parser and it does not support any old-stylish syntax; gpgme is + expected to return only rfc2253 compatible strings. */ +static Kleo::DN::Attribute::List +parse_dn( const unsigned char * string ) { + if ( !string ) + return QValueVector<Kleo::DN::Attribute>(); + + QValueVector<Kleo::DN::Attribute> result; + while (*string) + { + while (*string == ' ') + string++; + if (!*string) + break; /* ready */ + + DnPair pair = { 0, 0 }; + string = parse_dn_part (&pair, string); + if (!string) + goto failure; + if ( pair.key && pair.value ) + result.push_back( Kleo::DN::Attribute( QString::fromUtf8( pair.key ), + QString::fromUtf8( pair.value ) ) ); + free( pair.key ); + free( pair.value ); + + while (*string == ' ') + string++; + if (*string && *string != ',' && *string != ';' && *string != '+') + goto failure; /* invalid delimiter */ + if (*string) + string++; + } + return result; + +failure: + return QValueVector<Kleo::DN::Attribute>(); +} + +static QValueVector<Kleo::DN::Attribute> +parse_dn( const QString & dn ) { + return parse_dn( (const unsigned char*)dn.utf8().data() ); +} + +static QString dn_escape( const QString & s ) { + QString result; + for ( unsigned int i = 0, end = s.length() ; i != end ; ++i ) { + const QChar ch = s[i]; + switch ( ch.unicode() ) { + case ',': + case '+': + case '"': + case '\\': + case '<': + case '>': + case ';': + result += '\\'; + // fall through + default: + result += ch; + } + } + return result; +} + +static QString +serialise( const QValueVector<Kleo::DN::Attribute> & dn ) { + QStringList result; + for ( QValueVector<Kleo::DN::Attribute>::const_iterator it = dn.begin() ; it != dn.end() ; ++it ) + if ( !(*it).name().isEmpty() && !(*it).value().isEmpty() ) + result.push_back( (*it).name().stripWhiteSpace() + '=' + dn_escape( (*it).value().stripWhiteSpace() ) ); + return result.join( "," ); +} + +static Kleo::DN::Attribute::List +reorder_dn( const Kleo::DN::Attribute::List & dn ) { + const QStringList & attrOrder = Kleo::DNAttributeMapper::instance()->attributeOrder(); + + Kleo::DN::Attribute::List unknownEntries; + Kleo::DN::Attribute::List result; + unknownEntries.reserve( dn.size() ); + result.reserve( dn.size() ); + + // find all unknown entries in their order of appearance + for ( Kleo::DN::const_iterator it = dn.begin(); it != dn.end(); ++it ) + if ( attrOrder.find( (*it).name() ) == attrOrder.end() ) + unknownEntries.push_back( *it ); + + // process the known attrs in the desired order + for ( QStringList::const_iterator oit = attrOrder.begin() ; oit != attrOrder.end() ; ++oit ) + if ( *oit == "_X_" ) { + // insert the unknown attrs + std::copy( unknownEntries.begin(), unknownEntries.end(), + std::back_inserter( result ) ); + unknownEntries.clear(); // don't produce dup's + } else { + for ( Kleo::DN::const_iterator dnit = dn.begin() ; dnit != dn.end() ; ++dnit ) + if ( (*dnit).name() == *oit ) + result.push_back( *dnit ); + } + + return result; +} + +// +// +// class DN +// +// + +Kleo::DN::DN() { + d = new Private(); + d->ref(); +} + +Kleo::DN::DN( const QString & dn ) { + d = new Private(); + d->ref(); + d->attributes = parse_dn( dn ); +} + +Kleo::DN::DN( const char * utf8DN ) { + d = new Private(); + d->ref(); + if ( utf8DN ) + d->attributes = parse_dn( (const unsigned char*)utf8DN ); +} + +Kleo::DN::DN( const DN & other ) + : d( other.d ) +{ + if ( d ) d->ref(); +} + +Kleo::DN::~DN() { + if ( d ) d->unref(); +} + +const Kleo::DN & Kleo::DN::operator=( const DN & that ) { + if ( this->d == that.d ) + return *this; + + if ( that.d ) + that.d->ref(); + if ( this->d ) + this->d->unref(); + + this->d = that.d; + + return *this; +} + +QString Kleo::DN::prettyDN() const { + if ( !d ) + return QString::null; + if ( d->reorderedAttributes.empty() ) + d->reorderedAttributes = reorder_dn( d->attributes ); + return serialise( d->reorderedAttributes ); +} + +QString Kleo::DN::dn() const { + return d ? serialise( d->attributes ) : QString::null ; +} + +// static +QString Kleo::DN::escape( const QString & value ) { + return dn_escape( value ); +} + +void Kleo::DN::detach() { + if ( !d ) { + d = new Kleo::DN::Private(); + d->ref(); + } else if ( d->refCount() > 1 ) { + Kleo::DN::Private * d_save = d; + d = new Kleo::DN::Private( *d ); + d->ref(); + d_save->unref(); + } +} + +void Kleo::DN::append( const Attribute & attr ) { + detach(); + d->attributes.push_back( attr ); + d->reorderedAttributes.clear(); +} + +QString Kleo::DN::operator[]( const QString & attr ) const { + if ( !d ) + return QString::null; + const QString attrUpper = attr.upper(); + for ( QValueVector<Attribute>::const_iterator it = d->attributes.begin() ; + it != d->attributes.end() ; ++it ) + if ( (*it).name() == attrUpper ) + return (*it).value(); + return QString::null; +} + +static QValueVector<Kleo::DN::Attribute> empty; + +Kleo::DN::const_iterator Kleo::DN::begin() const { + return d ? d->attributes.begin() : empty.begin() ; +} + +Kleo::DN::const_iterator Kleo::DN::end() const { + return d ? d->attributes.end() : empty.end() ; +} + + +///////////////////// + +namespace { + struct ltstr { + bool operator()( const char * s1, const char * s2 ) const { + return qstrcmp( s1, s2 ) < 0 ; + } + }; +} + +static const char * defaultOrder[] = { + "CN", "L", "_X_", "OU", "O", "C" +}; + +std::pair<const char*,const char*> attributeLabels[] = { +#define MAKE_PAIR(x,y) std::pair<const char*,const char*>( x, y ) + MAKE_PAIR( "CN", I18N_NOOP("Common name") ), + MAKE_PAIR( "SN", I18N_NOOP("Surname") ), + MAKE_PAIR( "GN", I18N_NOOP("Given name") ), + MAKE_PAIR( "L", I18N_NOOP("Location") ), + MAKE_PAIR( "T", I18N_NOOP("Title") ), + MAKE_PAIR( "OU", I18N_NOOP("Organizational unit") ), + MAKE_PAIR( "O", I18N_NOOP("Organization") ), + MAKE_PAIR( "PC", I18N_NOOP("Postal code") ), + MAKE_PAIR( "C", I18N_NOOP("Country code") ), + MAKE_PAIR( "SP", I18N_NOOP("State or province") ), + MAKE_PAIR( "DC", I18N_NOOP("Domain component") ), + MAKE_PAIR( "BC", I18N_NOOP("Business category") ), + MAKE_PAIR( "EMAIL", I18N_NOOP("Email address") ), + MAKE_PAIR( "MAIL", I18N_NOOP("Mail address") ), + MAKE_PAIR( "MOBILE", I18N_NOOP("Mobile phone number") ), + MAKE_PAIR( "TEL", I18N_NOOP("Telephone number") ), + MAKE_PAIR( "FAX", I18N_NOOP("Fax number") ), + MAKE_PAIR( "STREET", I18N_NOOP("Street address") ), + MAKE_PAIR( "UID", I18N_NOOP("Unique ID") ) +#undef MAKE_PAIR +}; +static const unsigned int numAttributeLabels = sizeof attributeLabels / sizeof *attributeLabels ; + +class Kleo::DNAttributeMapper::Private { +public: + Private(); + std::map<const char*,const char*,ltstr> map; + QStringList attributeOrder; +}; + +Kleo::DNAttributeMapper::Private::Private() + : map( attributeLabels, attributeLabels + numAttributeLabels ) {} + +Kleo::DNAttributeMapper::DNAttributeMapper() { + d = new Private(); + const KConfigGroup config( kapp->config(), "DN" ); + d->attributeOrder = config.readListEntry( "AttributeOrder" ); + if ( d->attributeOrder.empty() ) + std::copy( defaultOrder, defaultOrder + sizeof defaultOrder / sizeof *defaultOrder, + std::back_inserter( d->attributeOrder ) ); + mSelf = this; +} + +Kleo::DNAttributeMapper::~DNAttributeMapper() { + mSelf = 0; + delete d; d = 0; +} + +Kleo::DNAttributeMapper * Kleo::DNAttributeMapper::mSelf = 0; + +const Kleo::DNAttributeMapper * Kleo::DNAttributeMapper::instance() { + if ( !mSelf ) + (void)new DNAttributeMapper(); + return mSelf; +} + +QString Kleo::DNAttributeMapper::name2label( const QString & s ) const { + const std::map<const char*,const char*,ltstr>::const_iterator it + = d->map.find( s.stripWhiteSpace().upper().latin1() ); + if ( it == d->map.end() ) + return QString::null; + return i18n( it->second ); +} + +QStringList Kleo::DNAttributeMapper::names() const { + QStringList result; + for ( std::map<const char*,const char*,ltstr>::const_iterator it = d->map.begin() ; it != d->map.end() ; ++it ) + result.push_back( it->first ); + return result; +} + +const QStringList & Kleo::DNAttributeMapper::attributeOrder() const { + return d->attributeOrder; +} + +void Kleo::DNAttributeMapper::setAttributeOrder( const QStringList & order ) { + d->attributeOrder = order; + if ( order.empty() ) + std::copy( defaultOrder, defaultOrder + sizeof defaultOrder / sizeof *defaultOrder, + std::back_inserter( d->attributeOrder ) ); + KConfigGroup config( kapp->config(), "DN" ); + config.writeEntry( "AttributeOrder", order ); +} + +Kleo::DNAttributeOrderConfigWidget * Kleo::DNAttributeMapper::configWidget( QWidget * parent, const char * name ) const { + return new DNAttributeOrderConfigWidget( mSelf, parent, name ); +} diff --git a/certmanager/lib/kleo/dn.h b/certmanager/lib/kleo/dn.h new file mode 100644 index 000000000..12bf9dc03 --- /dev/null +++ b/certmanager/lib/kleo/dn.h @@ -0,0 +1,142 @@ +/* + dn.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_DN_H__ +#define __KLEO_DN_H__ + +#include <qstring.h> +#include <qvaluevector.h> +#include <kdepimmacros.h> + +class QStringList; +class QWidget; + +namespace Kleo { + class DNAttributeOrderConfigWidget; +} + +namespace Kleo { + + /** + @short DN Attribute mapper + */ + class KDE_EXPORT DNAttributeMapper { + DNAttributeMapper(); + ~DNAttributeMapper(); + public: + static const DNAttributeMapper * instance(); + + QString name2label( const QString & s ) const; + QStringList names() const; + + const QStringList & attributeOrder() const; + + void setAttributeOrder( const QStringList & order ); + + DNAttributeOrderConfigWidget * configWidget( QWidget * parent=0, const char * name=0 ) const; + + private: + class Private; + Private * d; + static DNAttributeMapper * mSelf; + }; + + /** + @short DN parser and reorderer + */ + class KDE_EXPORT DN { + public: + class Attribute; + typedef QValueVector<Attribute> AttributeList; + typedef AttributeList::const_iterator const_iterator; + + DN(); + DN( const QString & dn ); + DN( const char * utf8DN ); + DN( const DN & other ); + ~DN(); + + const DN & operator=( const DN & other ); + + /** @return the value in rfc-2253-escaped form */ + static QString escape( const QString & value ); + + /** @return the DN in a reordered form, according to the settings in + the [DN] group of the application's config file */ + QString prettyDN() const; + /** @return the DN in the original form */ + QString dn() const; + + QString operator[]( const QString & attr ) const; + + void append( const Attribute & attr ); + + const_iterator begin() const; + const_iterator end() const; + + private: + void detach(); + private: + class Private; + Private * d; + }; + + class KDE_EXPORT DN::Attribute { + public: + typedef DN::AttributeList List; + + Attribute( const QString & name=QString::null, const QString & value=QString::null ) + : mName( name.upper() ), mValue( value ) {} + Attribute( const Attribute & other ) + : mName( other.name() ), mValue( other.value() ) {} + + const Attribute & operator=( const Attribute & other ) { + if ( this != &other ) { + mName = other.name(); + mValue = other.value(); + } + return *this; + } + + const QString & name() const { return mName; } + const QString & value() const { return mValue; } + + void setValue( const QString & value ) { mValue = value; } + + private: + QString mName; + QString mValue; + }; + +} + +#endif // __KLEO_DN_H__ diff --git a/certmanager/lib/kleo/downloadjob.h b/certmanager/lib/kleo/downloadjob.h new file mode 100644 index 000000000..006ab8ebd --- /dev/null +++ b/certmanager/lib/kleo/downloadjob.h @@ -0,0 +1,83 @@ +/* + downloadjob.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_DOWNLOADJOB_H__ +#define __KLEO_DOWNLOADJOB_H__ + +#include "job.h" + +#include <qcstring.h> + +namespace GpgME { + class Error; +} + +class QStringList; + +namespace Kleo { + + /** + @short An abstract base class for asynchronous downloaders + + To use a DownloadJob, first obtain an instance from the + CryptoBackend implementation, connect the progress() and result() + signals to suitable slots and then start the download with a call + to start(). This call might fail, in which case the DownloadJob + instance will have scheduled it's own destruction with a call to + QObject::deleteLater(). + + After result() is emitted, the DownloadJob will schedule it's own + destruction by calling QObject::deleteLater(). + */ + class DownloadJob : public Job { + Q_OBJECT + protected: + DownloadJob( QObject * parent, const char * name ); + public: + ~DownloadJob(); + + /** + Starts the download operation. \a fingerprints is a list of + fingerprints used to specify the list of keys downloaded. Empty + patterns are ignored. If \a fingerprints is empty, contains + only empty strings or anything other than fingerprints, the + result is undefined. + */ + virtual GpgME::Error start( const QStringList & fingerprints ) = 0; + + signals: + void result( const GpgME::Error & result, const QByteArray & keyData ); + }; + +} + +#endif // __KLEO_DOWNLOADJOB_H__ diff --git a/certmanager/lib/kleo/encryptjob.h b/certmanager/lib/kleo/encryptjob.h new file mode 100644 index 000000000..02144656f --- /dev/null +++ b/certmanager/lib/kleo/encryptjob.h @@ -0,0 +1,92 @@ +/* + encryptjob.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_ENCRYPTJOB_H__ +#define __KLEO_ENCRYPTJOB_H__ + +#include "job.h" + +#include <qcstring.h> + +#include <vector> + +namespace GpgME { + class Error; + class Key; + class EncryptionResult; +} + + +namespace Kleo { + + /** + @short An abstract base class for asynchronous encrypters + + To use a EncryptJob, first obtain an instance from the + CryptoBackend implementation, connect the progress() and result() + signals to suitable slots and then start the encryption with a + call to start(). This call might fail, in which case the + EncryptJob instance will have scheduled it's own destruction with + a call to QObject::deleteLater(). + + After result() is emitted, the EncryptJob will schedule it's own + destruction by calling QObject::deleteLater(). + */ + class EncryptJob : public Job { + Q_OBJECT + protected: + EncryptJob( QObject * parent, const char * name ); + public: + ~EncryptJob(); + + /** + Starts the encryption operation. \a recipients is the a list of + keys to encrypt \a plainText to. Empty (null) keys are ignored. + + If \a alwaysTrust is true, validity checking for the keys will + not be performed, but full validity assumed for all keys + without further checks. + */ + virtual GpgME::Error start( const std::vector<GpgME::Key> & recipients, + const QByteArray & plainText, bool alwaysTrust=false ) = 0; + + virtual GpgME::EncryptionResult exec( const std::vector<GpgME::Key> & recipients, + const QByteArray & plainText, + bool alwaysTrust, QByteArray & cipherText ) = 0; + + signals: + void result( const GpgME::EncryptionResult & result, const QByteArray & cipherText ); + }; + +} + +#endif // __KLEO_ENCRYPTJOB_H__ diff --git a/certmanager/lib/kleo/enum.cpp b/certmanager/lib/kleo/enum.cpp new file mode 100644 index 000000000..efa4cfaa3 --- /dev/null +++ b/certmanager/lib/kleo/enum.cpp @@ -0,0 +1,206 @@ +/* + kleo/enum.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "enum.h" + +#include <klocale.h> + +#include <qstring.h> +#include <qstringlist.h> + +static const struct { + Kleo::CryptoMessageFormat format; + const char * displayName; + const char * configName; +} cryptoMessageFormats[] = { + { Kleo::InlineOpenPGPFormat, + I18N_NOOP("Inline OpenPGP (deprecated)"), + "inline openpgp" }, + { Kleo::OpenPGPMIMEFormat, + I18N_NOOP("OpenPGP/MIME"), + "openpgp/mime" }, + { Kleo::SMIMEFormat, + I18N_NOOP("S/MIME"), + "s/mime" }, + { Kleo::SMIMEOpaqueFormat, + I18N_NOOP("S/MIME Opaque"), + "s/mime opaque" }, +}; +static const unsigned int numCryptoMessageFormats + = sizeof cryptoMessageFormats / sizeof *cryptoMessageFormats ; + +const char * Kleo::cryptoMessageFormatToString( Kleo::CryptoMessageFormat f ) { + if ( f == AutoFormat ) + return "auto"; + for ( unsigned int i = 0 ; i < numCryptoMessageFormats ; ++i ) + if ( f == cryptoMessageFormats[i].format ) + return cryptoMessageFormats[i].configName; + return 0; +} + +QStringList Kleo::cryptoMessageFormatsToStringList( unsigned int f ) { + QStringList result; + for ( unsigned int i = 0 ; i < numCryptoMessageFormats ; ++i ) + if ( f & cryptoMessageFormats[i].format ) + result.push_back( cryptoMessageFormats[i].configName ); + return result; +} + +QString Kleo::cryptoMessageFormatToLabel( Kleo::CryptoMessageFormat f ) { + if ( f == AutoFormat ) + return i18n("Any"); + for ( unsigned int i = 0 ; i < numCryptoMessageFormats ; ++i ) + if ( f == cryptoMessageFormats[i].format ) + return i18n( cryptoMessageFormats[i].displayName ); + return QString::null; +} + +Kleo::CryptoMessageFormat Kleo::stringToCryptoMessageFormat( const QString & s ) { + const QString t = s.lower(); + for ( unsigned int i = 0 ; i < numCryptoMessageFormats ; ++i ) + if ( t == cryptoMessageFormats[i].configName ) + return cryptoMessageFormats[i].format; + return AutoFormat; +} + +unsigned int Kleo::stringListToCryptoMessageFormats( const QStringList & sl ) { + unsigned int result = 0; + for ( QStringList::const_iterator it = sl.begin() ; it != sl.end() ; ++it ) + result |= stringToCryptoMessageFormat( *it ); + return result; +} + +// For the config values used below, see also kaddressbook/editors/cryptowidget.cpp + +const char* Kleo::encryptionPreferenceToString( EncryptionPreference pref ) +{ + switch( pref ) { + case UnknownPreference: + return 0; + case NeverEncrypt: + return "never"; + case AlwaysEncrypt: + return "always"; + case AlwaysEncryptIfPossible: + return "alwaysIfPossible"; + case AlwaysAskForEncryption: + return "askAlways"; + case AskWheneverPossible: + return "askWhenPossible"; + } + return 0; // keep the compiler happy +} + +Kleo::EncryptionPreference Kleo::stringToEncryptionPreference( const QString& str ) +{ + if ( str == "never" ) + return NeverEncrypt; + if ( str == "always" ) + return AlwaysEncrypt; + if ( str == "alwaysIfPossible" ) + return AlwaysEncryptIfPossible; + if ( str == "askAlways" ) + return AlwaysAskForEncryption; + if ( str == "askWhenPossible" ) + return AskWheneverPossible; + return UnknownPreference; +} + +QString Kleo::encryptionPreferenceToLabel( EncryptionPreference pref ) +{ + switch( pref ) { + case NeverEncrypt: + return i18n( "Never Encrypt" ); + case AlwaysEncrypt: + return i18n( "Always Encrypt" ); + case AlwaysEncryptIfPossible: + return i18n( "Always Encrypt If Possible" ); + case AlwaysAskForEncryption: + return i18n( "Ask" ); + case AskWheneverPossible: + return i18n( "Ask Whenever Possible" ); + default: + return i18n( "no specific preference", "<none>" ); + } +} + +const char* Kleo::signingPreferenceToString( SigningPreference pref ) +{ + switch( pref ) { + case UnknownSigningPreference: + return 0; + case NeverSign: + return "never"; + case AlwaysSign: + return "always"; + case AlwaysSignIfPossible: + return "alwaysIfPossible"; + case AlwaysAskForSigning: + return "askAlways"; + case AskSigningWheneverPossible: + return "askWhenPossible"; + } + return 0; // keep the compiler happy +} + +Kleo::SigningPreference Kleo::stringToSigningPreference( const QString& str ) +{ + if ( str == "never" ) + return NeverSign; + if ( str == "always" ) + return AlwaysSign; + if ( str == "alwaysIfPossible" ) + return AlwaysSignIfPossible; + if ( str == "askAlways" ) + return AlwaysAskForSigning; + if ( str == "askWhenPossible" ) + return AskSigningWheneverPossible; + return UnknownSigningPreference; +} + +QString Kleo::signingPreferenceToLabel( SigningPreference pref ) +{ + switch( pref ) { + case NeverSign: + return i18n( "Never Sign" ); + case AlwaysSign: + return i18n( "Always Sign" ); + case AlwaysSignIfPossible: + return i18n( "Always Sign If Possible" ); + case AlwaysAskForSigning: + return i18n( "Ask" ); + case AskSigningWheneverPossible: + return i18n( "Ask Whenever Possible" ); + default: + return i18n( "no specific preference", "<none>" ); + } +} diff --git a/certmanager/lib/kleo/enum.h b/certmanager/lib/kleo/enum.h new file mode 100644 index 000000000..29f8e2a66 --- /dev/null +++ b/certmanager/lib/kleo/enum.h @@ -0,0 +1,93 @@ +/* + kleo/enum.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_ENUM_H__ +#define __KLEO_ENUM_H__ + +#include <kdepimmacros.h> + +class QString; +class QStringList; + +namespace Kleo { + + enum CryptoMessageFormat { + InlineOpenPGPFormat = 1, + OpenPGPMIMEFormat = 2, + SMIMEFormat = 4, + SMIMEOpaqueFormat = 8, + AnyOpenPGP = InlineOpenPGPFormat|OpenPGPMIMEFormat, + AnySMIME = SMIMEOpaqueFormat|SMIMEFormat, + AutoFormat = AnyOpenPGP|AnySMIME + }; + + KDE_EXPORT QString cryptoMessageFormatToLabel( CryptoMessageFormat f ); + + KDE_EXPORT const char * cryptoMessageFormatToString( CryptoMessageFormat f ); + KDE_EXPORT QStringList cryptoMessageFormatsToStringList( unsigned int f ); + KDE_EXPORT CryptoMessageFormat stringToCryptoMessageFormat( const QString & s ); + KDE_EXPORT unsigned int stringListToCryptoMessageFormats( const QStringList & sl ); + + enum Action { + Conflict, DoIt, DontDoIt, Ask, AskOpportunistic, Impossible + }; + + enum EncryptionPreference { + UnknownPreference = 0, + NeverEncrypt = 1, + AlwaysEncrypt = 2, + AlwaysEncryptIfPossible = 3, + AlwaysAskForEncryption = 4, + AskWheneverPossible = 5, + MaxEncryptionPreference = AskWheneverPossible + }; + + KDE_EXPORT QString encryptionPreferenceToLabel( EncryptionPreference pref ); + KDE_EXPORT const char* encryptionPreferenceToString( EncryptionPreference pref ); + KDE_EXPORT EncryptionPreference stringToEncryptionPreference( const QString& str ); + + enum SigningPreference { + UnknownSigningPreference = 0, + NeverSign = 1, + AlwaysSign = 2, + AlwaysSignIfPossible = 3, + AlwaysAskForSigning = 4, + AskSigningWheneverPossible = 5, + MaxSigningPreference = AskSigningWheneverPossible + }; + + KDE_EXPORT QString signingPreferenceToLabel( SigningPreference pref ) KDE_EXPORT; + KDE_EXPORT const char* signingPreferenceToString( SigningPreference pref ) KDE_EXPORT; + KDE_EXPORT SigningPreference stringToSigningPreference( const QString& str ); +} + +#endif // __KLEO_CRYPTOBACKEND_H__ diff --git a/certmanager/lib/kleo/exportjob.h b/certmanager/lib/kleo/exportjob.h new file mode 100644 index 000000000..d6a0db185 --- /dev/null +++ b/certmanager/lib/kleo/exportjob.h @@ -0,0 +1,82 @@ +/* + exportjob.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_EXPORTJOB_H__ +#define __KLEO_EXPORTJOB_H__ + +#include "job.h" + +#include <qcstring.h> + +namespace GpgME { + class Error; +} + +class QStringList; + +namespace Kleo { + + /** + @short An abstract base class for asynchronous exporters + + To use a ExportJob, first obtain an instance from the + CryptoBackend implementation, connect the progress() and result() + signals to suitable slots and then start the export with a call + to start(). This call might fail, in which case the ExportJob + instance will have scheduled it's own destruction with a call to + QObject::deleteLater(). + + After result() is emitted, the ExportJob will schedule it's own + destruction by calling QObject::deleteLater(). + */ + class ExportJob : public Job { + Q_OBJECT + protected: + ExportJob( QObject * parent, const char * name ); + public: + ~ExportJob(); + + /** + Starts the export operation. \a patterns is a list of patterns + used to restrict the list of keys exported. Empty patterns are + ignored. If \a patterns is empty or contains only empty + strings, all available keys are exported. + */ + virtual GpgME::Error start( const QStringList & patterns ) = 0; + + signals: + void result( const GpgME::Error & result, const QByteArray & keyData ); + }; + +} + +#endif // __KLEO_EXPORTJOB_H__ diff --git a/certmanager/lib/kleo/hierarchicalkeylistjob.cpp b/certmanager/lib/kleo/hierarchicalkeylistjob.cpp new file mode 100644 index 000000000..a7a66b2fe --- /dev/null +++ b/certmanager/lib/kleo/hierarchicalkeylistjob.cpp @@ -0,0 +1,158 @@ +/* + hierarchicalkeylistjob.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "hierarchicalkeylistjob.h" +#include "cryptobackend.h" +#include "keylistjob.h" + +#include <klocale.h> + +#include <qstringlist.h> +#include <qtl.h> + +#include <gpgmepp/key.h> +#include <gpgmepp/context.h> +#include <gpgmepp/data.h> + +#include <gpg-error.h> + +#include <iterator> +#include <algorithm> + +#include <assert.h> + +Kleo::HierarchicalKeyListJob::HierarchicalKeyListJob( const CryptoBackend::Protocol * protocol, + bool remote, bool includeSigs, bool validating ) + : KeyListJob( 0, "Kleo::HierarchicalKeyListJob" ), + mProtocol( protocol ), + mRemote( remote ), + mIncludeSigs( includeSigs ), + mValidating( validating ), + mTruncated( false ), + mIntermediateResult(), + mJob( 0 ) +{ + assert( protocol ); +} + +Kleo::HierarchicalKeyListJob::~HierarchicalKeyListJob() { + +} + +GpgME::Error Kleo::HierarchicalKeyListJob::start( const QStringList & patterns, bool secretOnly ) { + if ( secretOnly || patterns.empty() ) + return gpg_err_make( GPG_ERR_SOURCE_GPGME, GPG_ERR_UNSUPPORTED_OPERATION ); + qCopy( patterns.begin(), patterns.end(), + std::inserter( mNextSet, mNextSet.begin() ) ); + const GpgME::Error err = startAJob(); + if ( err ) + deleteLater(); + return err; +} + +GpgME::KeyListResult Kleo::HierarchicalKeyListJob::exec( const QStringList &, bool, + std::vector<GpgME::Key> & keys ) { + keys.clear(); + return GpgME::KeyListResult( gpg_err_make( GPG_ERR_SOURCE_GPGME, GPG_ERR_UNSUPPORTED_OPERATION ) ); +} + +void Kleo::HierarchicalKeyListJob::slotNextKey( const GpgME::Key & key ) { + if ( const char * chain_id = key.chainID() ) + mNextSet.insert( chain_id ); + if ( const char * fpr = key.primaryFingerprint() ) + if ( mSentSet.find( fpr ) == mSentSet.end() ) { + mSentSet.insert( fpr ); + emit nextKey( key ); + } +} + +void Kleo::HierarchicalKeyListJob::slotCancel() { + if ( mJob ) mJob->slotCancel(); + mNextSet.clear(); +} + +void Kleo::HierarchicalKeyListJob::slotResult( const GpgME::KeyListResult & res ) { + mJob = 0; + mIntermediateResult.mergeWith( res ); + std::set<QString> tmp; + std::set_difference( mNextSet.begin(), mNextSet.end(), + mScheduledSet.begin(), mScheduledSet.end(), + std::inserter( tmp, tmp.begin() ) ); + mNextSet.clear(); + std::set_difference( tmp.begin(), tmp.end(), + mSentSet.begin(), mSentSet.end(), + std::inserter( mNextSet, mNextSet.begin() ) ); + if ( mIntermediateResult.error() || mNextSet.empty() ) { + emit done(); + emit result( mIntermediateResult ); + deleteLater(); + return; + } + if ( const GpgME::Error error = startAJob() ) { // error starting the job for next keys + mIntermediateResult.mergeWith( GpgME::KeyListResult( error ) ); + emit done(); + emit result( mIntermediateResult ); + deleteLater(); + return; + } +#if 0 // FIXME + const int current = mIt - mKeys.begin(); + const int total = mKeys.size(); + emit progress( i18n("progress info: \"%1 of %2\"","%1/%2").arg( current ).arg( total ), current, total ); +#endif +} + +GpgME::Error Kleo::HierarchicalKeyListJob::startAJob() { + if ( mNextSet.empty() ) + return 0; + mJob = mProtocol->keyListJob( mRemote, mIncludeSigs, mValidating ); + assert( mJob ); // FIXME: we need a way to generate errors ourselves, + // but I don't like the dependency on gpg-error :/ + + connect( mJob, SIGNAL(nextKey(const GpgME::Key&)), SLOT(slotNextKey(const GpgME::Key&)) ); + connect( mJob, SIGNAL(result(const GpgME::KeyListResult&)), SLOT(slotResult(const GpgME::KeyListResult&)) ); + + QStringList patterns; + for ( std::set<QString>::const_iterator it = mNextSet.begin() ; it != mNextSet.end() ; ++it ) + patterns.push_back( *it ); + + mScheduledSet.insert( mNextSet.begin(), mNextSet.end() ); + mNextSet.clear(); + + return mJob->start( patterns, false ); +} + +#include "hierarchicalkeylistjob.moc" diff --git a/certmanager/lib/kleo/hierarchicalkeylistjob.h b/certmanager/lib/kleo/hierarchicalkeylistjob.h new file mode 100644 index 000000000..a91ff6dc0 --- /dev/null +++ b/certmanager/lib/kleo/hierarchicalkeylistjob.h @@ -0,0 +1,116 @@ +/* + hierarchicalkeylistjob.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_HIERARCHICALKEYLISTJOB_H__ +#define __KLEO_HIERARCHICALKEYLISTJOB_H__ + +#include <kleo/keylistjob.h> +#include <kleo/cryptobackend.h> +#include <kdepimmacros.h> + +#include <gpgmepp/keylistresult.h> + +#include <qcstring.h> +#include <qguardedptr.h> + +#include <set> + +namespace GpgME { + class Error; + class Key; +} + +namespace Kleo { + class KeyListJob; +} + +namespace Kleo { + + /** + @short A convenience job that additionally fetches all available issuers. + + To use a HierarchicalKeyListJob, pass it a CryptoBackend + implementation, connect the progress() and result() signals to + suitable slots and then start the keylisting with a call to + start(). This call might fail, in which case the + HierarchicalKeyListJob instance will have scheduled it's own + destruction with a call to QObject::deleteLater(). + + After result() is emitted, the HierarchicalKeyListJob will + schedule its own destruction by calling QObject::deleteLater(). + */ + class KDE_EXPORT HierarchicalKeyListJob : public KeyListJob { + Q_OBJECT + public: + HierarchicalKeyListJob( const CryptoBackend::Protocol * protocol, + bool remote=false, bool includeSigs=false, bool validating=false ); + ~HierarchicalKeyListJob(); + + /** + Starts the keylist operation. \a patterns is a list of patterns + used to restrict the list of keys returned. Empty patterns are + ignored. \a patterns must not be empty or contain only empty + patterns; use the normal KeyListJob for a full listing. + + The \a secretOnly parameter is ignored by + HierarchicalKeyListJob and must be set to false. + */ + GpgME::Error start( const QStringList & patterns, bool secretOnly=false ); + + GpgME::KeyListResult exec( const QStringList & patterns, bool secretOnly, + std::vector<GpgME::Key> & keys ); + + private slots: + void slotResult( const GpgME::KeyListResult & ); + void slotNextKey( const GpgME::Key & key ); + /*! \reimp from Job */ + void slotCancel(); + + private: + GpgME::Error startAJob(); + + private: + const CryptoBackend::Protocol * const mProtocol; + const bool mRemote; + const bool mIncludeSigs; + const bool mValidating; + bool mTruncated; + std::set<QString> mSentSet; // keys already sent (prevent duplicates even if the backend should return them) + std::set<QString> mScheduledSet; // keys already scheduled (by starting a job for them) + std::set<QString> mNextSet; // keys to schedule for the next iteraton + GpgME::KeyListResult mIntermediateResult; + QGuardedPtr<KeyListJob> mJob; + }; + +} + +#endif // __KLEO_HIERARCHICALKEYLISTJOB_H__ diff --git a/certmanager/lib/kleo/importjob.h b/certmanager/lib/kleo/importjob.h new file mode 100644 index 000000000..10aa90383 --- /dev/null +++ b/certmanager/lib/kleo/importjob.h @@ -0,0 +1,83 @@ +/* + importjob.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_IMPORTJOB_H__ +#define __KLEO_IMPORTJOB_H__ + +#include "job.h" + +#include <qcstring.h> + +namespace GpgME { + class Error; + class Key; + class ImportResult; +} + + +namespace Kleo { + + /** + @short An abstract base class for asynchronous importers + + To use a ImportJob, first obtain an instance from the + CryptoBackend implementation, connect the progress() and result() + signals to suitable slots and then start the import with a call + to start(). This call might fail, in which case the ImportJob + instance will have scheduled it's own destruction with a call to + QObject::deleteLater(). + + After result() is emitted, the ImportJob will schedule it's own + destruction by calling QObject::deleteLater(). + */ + class ImportJob : public Job { + Q_OBJECT + protected: + ImportJob( QObject * parent, const char * name ); + public: + ~ImportJob(); + + /** + Starts the importing operation. \a keyData contains the data to + import from. + */ + virtual GpgME::Error start( const QByteArray & keyData ) = 0; + + virtual GpgME::ImportResult exec( const QByteArray & keyData ) = 0; + + signals: + void result( const GpgME::ImportResult & result ); + }; + +} + +#endif // __KLEO_IMPORTJOB_H__ diff --git a/certmanager/lib/kleo/job.cpp b/certmanager/lib/kleo/job.cpp new file mode 100644 index 000000000..77881d737 --- /dev/null +++ b/certmanager/lib/kleo/job.cpp @@ -0,0 +1,116 @@ +/* + job.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004,2005 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "job.h" + +#include "keylistjob.h" +#include "encryptjob.h" +#include "decryptjob.h" +#include "decryptverifyjob.h" +#include "signjob.h" +#include "signencryptjob.h" +#include "verifydetachedjob.h" +#include "verifyopaquejob.h" +#include "keygenerationjob.h" +#include "importjob.h" +#include "exportjob.h" +#include "downloadjob.h" +#include "deletejob.h" +#include "refreshkeysjob.h" +#include "specialjob.h" + +#include <qapplication.h> +#include <kdebug.h> + +Kleo::Job::Job( QObject * parent, const char * name ) + : QObject( parent, name ) +{ + if ( qApp ) + connect( qApp, SIGNAL(aboutToQuit()), SLOT(slotCancel()) ); +} + +Kleo::Job::~Job() { + +} + +void Kleo::Job::showErrorDialog( QWidget *, const QString & ) const { + kdDebug() << "Kleo::Job::showErrorDialog() should be reimplemented in Kleo::Job subclasses!" << endl; +} + +QString Kleo::Job::auditLogAsHtml() const { + kdDebug() << "Kleo::Job::auditLogAsHtml() should be reimplemented in Kleo::Job subclasses!" << endl; + return QString(); +} + +#define make_job_subclass(x) \ + Kleo::x::x( QObject * parent, const char * name ) : Job( parent, name ) {} \ + Kleo::x::~x() {} + +make_job_subclass(KeyListJob) +make_job_subclass(EncryptJob) +make_job_subclass(DecryptJob) +make_job_subclass(DecryptVerifyJob) +make_job_subclass(SignJob) +make_job_subclass(SignEncryptJob) +make_job_subclass(VerifyDetachedJob) +make_job_subclass(VerifyOpaqueJob) +make_job_subclass(KeyGenerationJob) +make_job_subclass(ImportJob) +make_job_subclass(ExportJob) +make_job_subclass(DownloadJob) +make_job_subclass(DeleteJob) +make_job_subclass(RefreshKeysJob) +make_job_subclass(SpecialJob) + +#undef make_job_subclass + +#include "job.moc" + +#include "keylistjob.moc" +#include "encryptjob.moc" +#include "decryptjob.moc" +#include "decryptverifyjob.moc" +#include "signjob.moc" +#include "signencryptjob.moc" +#include "verifydetachedjob.moc" +#include "verifyopaquejob.moc" +#include "keygenerationjob.moc" +#include "importjob.moc" +#include "exportjob.moc" +#include "downloadjob.moc" +#include "deletejob.moc" +#include "refreshkeysjob.moc" +#include "specialjob.moc" diff --git a/certmanager/lib/kleo/job.h b/certmanager/lib/kleo/job.h new file mode 100644 index 000000000..ae65008b0 --- /dev/null +++ b/certmanager/lib/kleo/job.h @@ -0,0 +1,81 @@ +/* + job.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_JOB_H__ +#define __KLEO_JOB_H__ + +#include <qobject.h> +#include <qstring.h> + +class QWidget; + +namespace Kleo { + + /** + @short An abstract base class for asynchronous crypto operations + + During the operation, you might receive progress updates through + the progress() signal as they arrive, but an implementation is + free to not send progress information. You should show a busy + progressbar until the first progress() signal is received. + + The done() signal is emitted _before_ the result() signals of + subclasses and should be used to hide and/or reset progress bars, + not to learn of the end of the operation. Use the result() + signals for that. + + To cancel the operation, simply call slotCancel(). The result() + signal of subclasses will still be emitted, though, and will + carry the information that the operation was canceled. + */ + class Job : public QObject { + Q_OBJECT + protected: + Job( QObject * parent, const char * name ); + public: + ~Job(); + + virtual void showErrorDialog( QWidget * parent=0, const QString & caption=QString::null ) const; + + virtual QString auditLogAsHtml() const; + + public slots: + virtual void slotCancel() = 0; + + signals: + void progress( const QString & what, int current, int total ); + void done(); + }; + +} + +#endif // __KLEO_JOB_H__ diff --git a/certmanager/lib/kleo/kconfigbasedkeyfilter.cpp b/certmanager/lib/kleo/kconfigbasedkeyfilter.cpp new file mode 100644 index 000000000..89d18e799 --- /dev/null +++ b/certmanager/lib/kleo/kconfigbasedkeyfilter.cpp @@ -0,0 +1,251 @@ +/* + kconfigbasedkeyfilter.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "kconfigbasedkeyfilter.h" + +#include <kconfigbase.h> +#include <klocale.h> + +static const struct { + const char * name; + GpgME::Key::OwnerTrust trust; + GpgME::UserID::Validity validity; +} ownerTrustAndValidityMap[] = { + { "unknown", GpgME::Key::Unknown, GpgME::UserID::Unknown }, + { "undefined", GpgME::Key::Undefined, GpgME::UserID::Undefined }, + { "never", GpgME::Key::Never, GpgME::UserID::Never }, + { "marginal", GpgME::Key::Marginal, GpgME::UserID::Marginal }, + { "full", GpgME::Key::Full, GpgME::UserID::Full }, + { "ultimate", GpgME::Key::Ultimate, GpgME::UserID::Ultimate }, +}; + +static GpgME::Key::OwnerTrust map2OwnerTrust( const QString & s ) { + for ( unsigned int i = 0 ; i < sizeof ownerTrustAndValidityMap / sizeof *ownerTrustAndValidityMap ; ++i ) + if ( s.lower() == ownerTrustAndValidityMap[i].name ) + return ownerTrustAndValidityMap[i].trust; + return ownerTrustAndValidityMap[0].trust; +} + +static GpgME::UserID::Validity map2Validity( const QString & s ) { + for ( unsigned int i = 0 ; i < sizeof ownerTrustAndValidityMap / sizeof *ownerTrustAndValidityMap ; ++i ) + if ( s.lower() == ownerTrustAndValidityMap[i].name ) + return ownerTrustAndValidityMap[i].validity; + return ownerTrustAndValidityMap[0].validity; +} + + +Kleo::KConfigBasedKeyFilter::KConfigBasedKeyFilter( const KConfigBase & config ) + : KeyFilter(), + mSpecificity( 0 ), + mItalic( false ), + mBold( false ), + mStrikeOut( false ), + mUseFullFont( false ), + mRevoked( DoesNotMatter ), + mExpired( DoesNotMatter ), + mDisabled( DoesNotMatter ), + mRoot( DoesNotMatter ), + mCanEncrypt( DoesNotMatter ), + mCanSign( DoesNotMatter ), + mCanCertify( DoesNotMatter ), + mCanAuthenticate( DoesNotMatter ), + mHasSecret( DoesNotMatter ), + mIsOpenPGP( DoesNotMatter ), + mWasValidated( DoesNotMatter ), + mOwnerTrust( LevelDoesNotMatter ), + mOwnerTrustReferenceLevel( GpgME::Key::Unknown ), + mValidity( LevelDoesNotMatter ), + mValidityReferenceLevel( GpgME::UserID::Unknown ) +{ + mFgColor = config.readColorEntry( "foreground-color" ); + mBgColor = config.readColorEntry( "background-color" ); + mName = config.readEntry( "name", i18n("<unnamed>") ); + mIcon = config.readEntry( "icon" ); + if ( config.hasKey( "font" ) ) { + mUseFullFont = true; + mFont = config.readFontEntry( "font" ); + } else { + mItalic = config.readBoolEntry( "font-italic", false ); + mBold = config.readBoolEntry( "font-bold", false ); + } + mStrikeOut = config.readBoolEntry( "font-strikeout", false ); +#ifdef SET +#undef SET +#endif +#define SET(member,key) \ + if ( config.hasKey( key ) ) { \ + member = config.readBoolEntry( key ) ? Set : NotSet ; \ + ++mSpecificity; \ + } + SET( mRevoked, "is-revoked" ); + SET( mExpired, "is-expired" ); + SET( mDisabled, "is-disabled" ); + SET( mRoot, "is-root-certificate" ); + SET( mCanEncrypt, "can-encrypt" ); + SET( mCanSign, "can-sign" ); + SET( mCanCertify, "can-certify" ); + SET( mCanAuthenticate, "can-authenticate" ); + SET( mHasSecret, "has-secret-key" ); + SET( mIsOpenPGP, "is-openpgp-key" ); + SET( mWasValidated, "was-validated" ); +#undef SET + static const struct { + const char * prefix; + LevelState state; + } prefixMap[] = { + { "is-", Is }, + { "is-not-", IsNot }, + { "is-at-least-", IsAtLeast }, + { "is-at-most-", IsAtMost }, + }; + for ( unsigned int i = 0 ; i < sizeof prefixMap / sizeof *prefixMap ; ++i ) { + const QString key = QString( prefixMap[i].prefix ) + "ownertrust"; + if ( config.hasKey( key ) ) { + mOwnerTrust = prefixMap[i].state; + mOwnerTrustReferenceLevel = map2OwnerTrust( config.readEntry( key ) ); + ++mSpecificity; + break; + } + } + for ( unsigned int i = 0 ; i < sizeof prefixMap / sizeof *prefixMap ; ++i ) { + const QString key = QString( prefixMap[i].prefix ) + "validity"; + if ( config.hasKey( key ) ) { + mValidity = prefixMap[i].state; + mValidityReferenceLevel = map2Validity( config.readEntry( key ) ); + ++mSpecificity; + break; + } + } +} + +Kleo::KConfigBasedKeyFilter::~KConfigBasedKeyFilter() { + +} + +bool Kleo::KConfigBasedKeyFilter::matches( const GpgME::Key & key ) const { +#ifdef MATCH +#undef MATCH +#endif +#define MATCH(member,method) \ + if ( member != DoesNotMatter && key.method() != bool( member == Set ) ) \ + return false +#define IS_MATCH(what) MATCH( m##what, is##what ) +#define CAN_MATCH(what) MATCH( mCan##what, can##what ) + IS_MATCH( Revoked ); + IS_MATCH( Expired ); + IS_MATCH( Disabled ); + IS_MATCH( Root ); + CAN_MATCH( Encrypt ); + CAN_MATCH( Sign ); + CAN_MATCH( Certify ); + CAN_MATCH( Authenticate ); + MATCH( mHasSecret, isSecret ); +#undef MATCH + if ( mIsOpenPGP != DoesNotMatter && + bool( key.protocol() == GpgME::Context::OpenPGP ) != bool( mIsOpenPGP == Set ) ) + return false; + if ( mWasValidated != DoesNotMatter && + bool( key.keyListMode() & GpgME::Context::Validate ) != bool( mWasValidated == Set ) ) + return false; + switch ( mOwnerTrust ) { + default: + case LevelDoesNotMatter: + break; + case Is: + if ( key.ownerTrust() != mOwnerTrustReferenceLevel ) + return false; + break; + case IsNot: + if ( key.ownerTrust() == mOwnerTrustReferenceLevel ) + return false; + break; + case IsAtLeast: + if ( (int)key.ownerTrust() < (int)mOwnerTrustReferenceLevel ) + return false; + break; + case IsAtMost: + if ( (int)key.ownerTrust() > (int)mOwnerTrustReferenceLevel ) + return false; + break; + } + const GpgME::UserID uid = key.userID(0); + switch ( mValidity ) { + default: + case LevelDoesNotMatter: + break; + case Is: + if ( uid.validity() != mValidityReferenceLevel ) + return false; + break; + case IsNot: + if ( uid.validity() == mValidityReferenceLevel ) + return false; + break; + case IsAtLeast: + if ( (int)uid.validity() < (int)mValidityReferenceLevel ) + return false; + break; + case IsAtMost: + if ( (int)uid.validity() > (int)mValidityReferenceLevel ) + return false; + break; + } + return true; +} + +static inline QFont resizedFont( QFont font, int pointSize, bool strike ) { + font.setPointSize( pointSize ); + if ( strike ) + font.setStrikeOut( true ); + return font; +} + +static inline QFont adapt( QFont font, bool it, bool b, bool strike ) { + if ( it ) + font.setItalic( true ); + if ( b ) + font.setBold( true ); + if ( strike ) + font.setStrikeOut( true ); + return font; +} + +QFont Kleo::KConfigBasedKeyFilter::font( const QFont & f ) const { + if ( mUseFullFont ) + return resizedFont( mFont, f.pointSize(), mStrikeOut ); + else + return adapt( f, mItalic, mBold, mStrikeOut ); +} diff --git a/certmanager/lib/kleo/kconfigbasedkeyfilter.h b/certmanager/lib/kleo/kconfigbasedkeyfilter.h new file mode 100644 index 000000000..42c083080 --- /dev/null +++ b/certmanager/lib/kleo/kconfigbasedkeyfilter.h @@ -0,0 +1,104 @@ +/* + kconfigbasedkeyfilter.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_KCONFIGBASEDKEYFILTER_H__ +#define __KLEO_KCONFIGBASEDKEYFILTER_H__ + +#include "keyfilter.h" + +#include <qfont.h> +#include <qstring.h> +#include <qcolor.h> + +#include <gpgmepp/key.h> + +class KConfigBase; + +namespace Kleo { + + class KConfigBasedKeyFilter : public KeyFilter { + public: + explicit KConfigBasedKeyFilter( const KConfigBase & config ); + ~KConfigBasedKeyFilter(); + bool matches( const GpgME::Key & key ) const; + + unsigned int specificity() const { return mSpecificity; } + + QColor fgColor() const { return mFgColor; } + QColor bgColor() const { return mBgColor; } + QFont font( const QFont & ) const; + QString name() const { return mName; } + QString icon() const { return mIcon; } + + private: + QColor mFgColor, mBgColor; + QString mName; + QString mIcon; + unsigned int mSpecificity; + bool mItalic; + bool mBold; + bool mStrikeOut; + bool mUseFullFont; + QFont mFont; + + enum TriState { + DoesNotMatter = 0, + Set = 1, + NotSet = 2 + }; + TriState mRevoked; + TriState mExpired; + TriState mDisabled; + TriState mRoot; + TriState mCanEncrypt; + TriState mCanSign; + TriState mCanCertify; + TriState mCanAuthenticate; + TriState mHasSecret; + TriState mIsOpenPGP; + TriState mWasValidated; + enum LevelState { + LevelDoesNotMatter = 0, + Is = 1, + IsNot = 2, + IsAtLeast = 3, + IsAtMost = 4 + }; + LevelState mOwnerTrust; + GpgME::Key::OwnerTrust mOwnerTrustReferenceLevel; + LevelState mValidity; + GpgME::UserID::Validity mValidityReferenceLevel; + }; + +} + +#endif // __KLEO_KCONFIGBASEDKEYFILTER_H__ diff --git a/certmanager/lib/kleo/keyfilter.h b/certmanager/lib/kleo/keyfilter.h new file mode 100644 index 000000000..f10fba9bf --- /dev/null +++ b/certmanager/lib/kleo/keyfilter.h @@ -0,0 +1,68 @@ +/* + keyfilter.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_KEYFILTER_H__ +#define __KLEO_KEYFILTER_H__ + +namespace GpgME { + class Key; +} + +class QFont; +class QColor; +class QString; + +namespace Kleo { + + /** + @short An abstract base class key filters + + */ + class KeyFilter { + public: + virtual ~KeyFilter() {} + virtual bool matches( const GpgME::Key & key ) const = 0; + + virtual unsigned int specificity() const = 0; + + // not sure if we want these here, but for the time being, it's + // the easiest way: + virtual QColor fgColor() const = 0; + virtual QColor bgColor() const = 0; + virtual QFont font( const QFont & ) const = 0; + virtual QString name() const = 0; + virtual QString icon() const = 0; + }; + +} + +#endif // __KLEO_KEYFILTER_H__ diff --git a/certmanager/lib/kleo/keyfiltermanager.cpp b/certmanager/lib/kleo/keyfiltermanager.cpp new file mode 100644 index 000000000..14932801c --- /dev/null +++ b/certmanager/lib/kleo/keyfiltermanager.cpp @@ -0,0 +1,118 @@ +/* + keyfiltermanager.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "keyfiltermanager.h" +#include "kconfigbasedkeyfilter.h" + +#include "cryptobackendfactory.h" + +#include <kconfig.h> + +#include <qapplication.h> +#include <qregexp.h> +#include <qstringlist.h> +#include <qvaluevector.h> + +#include <algorithm> + +namespace { + template <typename T> + struct Delete { + void operator()( T * item ) { delete item; } + }; +} + +struct Kleo::KeyFilterManager::Private { + void clear() { + std::for_each( filters.begin(), filters.end(), Delete<KeyFilter>() ); + filters.clear(); + } + + QValueVector<KeyFilter*> filters; +}; + +Kleo::KeyFilterManager * Kleo::KeyFilterManager::mSelf = 0; + +Kleo::KeyFilterManager::KeyFilterManager( QObject * parent, const char * name ) + : QObject( parent, name ), d( 0 ) +{ + mSelf = this; + d = new Private(); + // ### DF: doesn't a KStaticDeleter work more reliably? + if ( qApp ) + connect( qApp, SIGNAL(aboutToQuit()), SLOT(deleteLater()) ); + reload(); +} + +Kleo::KeyFilterManager::~KeyFilterManager() { + mSelf = 0; + if ( d ) + d->clear(); + delete d; d = 0; +} + +Kleo::KeyFilterManager * Kleo::KeyFilterManager::instance() { + if ( !mSelf ) + mSelf = new Kleo::KeyFilterManager(); + return mSelf; +} + +const Kleo::KeyFilter * Kleo::KeyFilterManager::filterMatching( const GpgME::Key & key ) const { + for ( QValueVector<KeyFilter*>::const_iterator it = d->filters.begin() ; it != d->filters.end() ; ++it ) + if ( (*it)->matches( key ) ) + return *it; + return 0; +} + +static inline bool by_increasing_specificity( const Kleo::KeyFilter * left, const Kleo::KeyFilter * right ) { + return left->specificity() > right->specificity(); +} + +void Kleo::KeyFilterManager::reload() { + d->clear(); + + KConfig * config = Kleo::CryptoBackendFactory::instance()->configObject(); + if ( !config ) + return; + const QStringList groups = config->groupList().grep( QRegExp( "^Key Filter #\\d+$" ) ); + for ( QStringList::const_iterator it = groups.begin() ; it != groups.end() ; ++it ) { + const KConfigGroup cfg( config, *it ); + d->filters.push_back( new KConfigBasedKeyFilter( cfg ) ); + } + std::stable_sort( d->filters.begin(), d->filters.end(), by_increasing_specificity ); +} + +#include "keyfiltermanager.moc" diff --git a/certmanager/lib/kleo/keyfiltermanager.h b/certmanager/lib/kleo/keyfiltermanager.h new file mode 100644 index 000000000..25353d71a --- /dev/null +++ b/certmanager/lib/kleo/keyfiltermanager.h @@ -0,0 +1,69 @@ +/* + keyfiltermanager.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_KEYFILTERMANAGER_H__ +#define __KLEO_KEYFILTERMANAGER_H__ + +#include <qobject.h> +#include <kdepimmacros.h> +namespace GpgME { + class Key; +} + +namespace Kleo { + class KeyFilter; +} + +namespace Kleo { + + class KDE_EXPORT KeyFilterManager : public QObject { + Q_OBJECT + protected: + KeyFilterManager( QObject * parent=0, const char * name=0 ); + ~KeyFilterManager(); + + public: + static KeyFilterManager * instance(); + + const KeyFilter * filterMatching( const GpgME::Key & key ) const; + + void reload(); + + private: + class Private; + Private * d; + static KeyFilterManager * mSelf; + }; + +} + +#endif // __KLEO_KEYFILTERMANAGER_H__ diff --git a/certmanager/lib/kleo/keygenerationjob.h b/certmanager/lib/kleo/keygenerationjob.h new file mode 100644 index 000000000..f78152c5c --- /dev/null +++ b/certmanager/lib/kleo/keygenerationjob.h @@ -0,0 +1,81 @@ +/* + keygenerationjob.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_KEYGENERATIONJOB_H__ +#define __KLEO_KEYGENERATIONJOB_H__ + +#include "job.h" + +#include <qcstring.h> + +namespace GpgME { + class Error; + class KeyGenerationResult; +} + + +namespace Kleo { + + /** + @short An abstract base class for asynchronous key generation + + To use a KeyGenerationJob, first obtain an instance from the + CryptoBackend implementation, connect the progress() and result() + signals to suitable slots and then start the key generation with + a call to start(). This call might fail, in which case the + KeyGenerationJob instance will have scheduled it's own + destruction with a call to QObject::deleteLater(). + + After result() is emitted, the KeyGenerationJob will schedule it's own + destruction by calling QObject::deleteLater(). + */ + class KeyGenerationJob : public Job { + Q_OBJECT + protected: + KeyGenerationJob( QObject * parent, const char * name ); + public: + ~KeyGenerationJob(); + + /** + Starts the key generation operation. \a parameters is a + backend-specific string containing the paramaters of the key to + create (length, capabilities, etc). + */ + virtual GpgME::Error start( const QString & parameters ) = 0; + + signals: + void result( const GpgME::KeyGenerationResult & result, const QByteArray & pubKeyData ); + }; + +} + +#endif // __KLEO_KEYGENERATIONJOB_H__ diff --git a/certmanager/lib/kleo/keylistjob.h b/certmanager/lib/kleo/keylistjob.h new file mode 100644 index 000000000..c419ad47d --- /dev/null +++ b/certmanager/lib/kleo/keylistjob.h @@ -0,0 +1,96 @@ +/* + keylistjob.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_KEYLISTJOB_H__ +#define __KLEO_KEYLISTJOB_H__ + +#include "job.h" + +#include <vector> + +namespace GpgME { + class Error; + class Key; + class KeyListResult; +} + +class QStringList; + +namespace Kleo { + + /** + @short An abstract base class for asynchronous key listers + + To use a KeyListJob, first obtain an instance from the + CryptoBackend implementation, connect the nextKey(), progress() + and result() signals to suitable slots and then start the key + listing with a call to start(). This call might fail, in which + case the KeylistJob instance will have schedules it's own + destruction with a call to QObject::deleteLater(). + + During keylisting, you will receive new key objects through the + nextKey() signal as they arrive. After result() is emitted, the + KeyListJob will schedule it's own destruction by calling + QObject::deleteLater(). + */ + class KeyListJob : public Job { + Q_OBJECT + protected: + KeyListJob( QObject * parent, const char * name ); + + public: + ~KeyListJob(); + + /** + Starts the keylist operation. \a pattern is a list of patterns + used to restrict the list of keys returned. Empty patterns are + ignored. If \a pattern is empty or contains only empty strings, + all keys are returned (however, the backend is free to truncate + the result and should do so; when this happens, it will be + reported by the reult object). + + If \a secretOnly is true, only keys for which the secret key is + also available are returned. Use this if you need to select a + key for signing. + */ + virtual GpgME::Error start( const QStringList & patterns, bool secretOnly=false ) = 0; + + virtual GpgME::KeyListResult exec( const QStringList & patterns, bool secretOnly, std::vector<GpgME::Key> & keys ) = 0; + + signals: + void nextKey( const GpgME::Key & key ); + void result( const GpgME::KeyListResult & result ); + }; + +} + +#endif // __KLEO_KEYLISTJOB_H__ diff --git a/certmanager/lib/kleo/multideletejob.cpp b/certmanager/lib/kleo/multideletejob.cpp new file mode 100644 index 000000000..32596e78f --- /dev/null +++ b/certmanager/lib/kleo/multideletejob.cpp @@ -0,0 +1,110 @@ +/* + multideletejob.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "multideletejob.h" +#include "cryptobackend.h" +#include "deletejob.h" + +#include <klocale.h> + +#include <gpgmepp/key.h> +#include <gpgmepp/context.h> +#include <gpgmepp/data.h> + +#include <iterator> + +#include <assert.h> + +Kleo::MultiDeleteJob::MultiDeleteJob( const CryptoBackend::Protocol * protocol ) + : Job( 0, "Kleo::MultiDeleteJob" ), + mProtocol( protocol ), + mJob( 0 ) +{ + assert( protocol ); +} + +Kleo::MultiDeleteJob::~MultiDeleteJob() { + +} + +GpgME::Error Kleo::MultiDeleteJob::start( const std::vector<GpgME::Key> & keys, bool allowSecretKeyDeletion ) { + mKeys = keys; + mAllowSecretKeyDeletion = allowSecretKeyDeletion; + mIt = mKeys.begin(); + + const GpgME::Error err = startAJob(); + + if ( err ) + deleteLater(); + return err; +} + +void Kleo::MultiDeleteJob::slotCancel() { + if ( mJob ) mJob->slotCancel(); + mIt = mKeys.end(); +} + +void Kleo::MultiDeleteJob::slotResult( const GpgME::Error & err ) { + mJob = 0; + GpgME::Error error = err; + if ( error || // error in last op + mIt == mKeys.end() || // (shouldn't happen) + ++mIt == mKeys.end() || // was the last key + (error = startAJob()) ) { // error starting the job for the new key + emit done(); + emit result( error, error && mIt != mKeys.end() ? *mIt : GpgME::Key::null ); + deleteLater(); + return; + } + + const int current = mIt - mKeys.begin(); + const int total = mKeys.size(); + emit progress( i18n("progress info: \"%1 of %2\"","%1/%2").arg( current ).arg( total ), current, total ); +} + +GpgME::Error Kleo::MultiDeleteJob::startAJob() { + if ( mIt == mKeys.end() ) + return 0; + mJob = mProtocol->deleteJob(); + assert( mJob ); // FIXME: we need a way to generate errors ourselves, + // but I don't like the dependency on gpg-error :/ + + connect( mJob, SIGNAL(result(const GpgME::Error&)), SLOT(slotResult(const GpgME::Error&)) ); + + return mJob->start( *mIt, mAllowSecretKeyDeletion ); +} + +#include "multideletejob.moc" diff --git a/certmanager/lib/kleo/multideletejob.h b/certmanager/lib/kleo/multideletejob.h new file mode 100644 index 000000000..5b995adaf --- /dev/null +++ b/certmanager/lib/kleo/multideletejob.h @@ -0,0 +1,101 @@ +/* + multideletejob.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_MULTIDELETEJOB_H__ +#define __KLEO_MULTIDELETEJOB_H__ + +#include <kleo/job.h> +#include <kleo/cryptobackend.h> + +#include <kdepimmacros.h> +#include <qguardedptr.h> + +#include <vector> + +namespace GpgME { + class Error; + class Key; +} + +namespace Kleo { + class DeleteJob; +} + +namespace Kleo { + + /** + @short A convenience class bundling together multiple DeleteJobs. + + To use a MultiDeleteJob, pass it a CryptoBackend implementation, + connect the progress() and result() signals to suitable slots and + then start the delete with a call to start(). This call might + fail, in which case the MultiDeleteJob instance will have scheduled + it's own destruction with a call to QObject::deleteLater(). + + After result() is emitted, the MultiDeleteJob will schedule it's own + destruction by calling QObject::deleteLater(). + */ + class KDE_EXPORT MultiDeleteJob : public Job { + Q_OBJECT + public: + MultiDeleteJob( const CryptoBackend::Protocol * protocol ); + ~MultiDeleteJob(); + + /** + Starts the delete operation. \a keys is the list of keys to + delete, \a allowSecretKeyDeletion specifies if a key may also + be deleted if the secret key part is available, too. + */ + GpgME::Error start( const std::vector<GpgME::Key> & keys, bool allowSecretKeyDeletion=false ); + + signals: + void result( const GpgME::Error & result, const GpgME::Key & errorKey ); + + private slots: + void slotResult( const GpgME::Error & ); + /*! \reimp from Job */ + void slotCancel(); + + private: + GpgME::Error startAJob(); + + private: + const CryptoBackend::Protocol * mProtocol; + QGuardedPtr<DeleteJob> mJob; + std::vector<GpgME::Key> mKeys; + std::vector<GpgME::Key>::const_iterator mIt; + bool mAllowSecretKeyDeletion; + }; + +} + +#endif // __KLEO_MULTIDELETEJOB_H__ diff --git a/certmanager/lib/kleo/oidmap.h b/certmanager/lib/kleo/oidmap.h new file mode 100644 index 000000000..596296332 --- /dev/null +++ b/certmanager/lib/kleo/oidmap.h @@ -0,0 +1,57 @@ +/* + oidmap.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_OIDMAP_H__ +#define __KLEO_OIDMAP_H__ + +static struct { + const char * name; + const char * oid; +} oidmap[] = { + // keep them ordered by oid: + { "SP", "ST" }, // hack to show the Sphinx-required/desired SP for + // StateOrProvince, otherwise known as ST or even S + { "NameDistinguisher", "0.2.262.1.10.7.20" }, + { "EMAIL", "1.2.840.113549.1.9.1" }, + { "SN", "2.5.4.4" }, + { "SerialNumber", "2.5.4.5" }, + { "T", "2.5.4.12" }, + { "D", "2.5.4.13" }, + { "BC", "2.5.4.15" }, + { "ADDR", "2.5.4.16" }, + { "PC", "2.5.4.17" }, + { "GN", "2.5.4.42" }, + { "Pseudo", "2.5.4.65" }, +}; +static const unsigned int numOidMaps = sizeof oidmap / sizeof *oidmap; + +#endif // __KLEO_OIDMAP_H__ diff --git a/certmanager/lib/kleo/refreshkeysjob.h b/certmanager/lib/kleo/refreshkeysjob.h new file mode 100644 index 000000000..dcf9cd516 --- /dev/null +++ b/certmanager/lib/kleo/refreshkeysjob.h @@ -0,0 +1,90 @@ +/* + refreshkeysjob.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_REFRESHKEYSJOB_H__ +#define __KLEO_REFRESHKEYSJOB_H__ + +#include "job.h" + +#include <vector> + +namespace GpgME { + class Error; + class Key; +} + +class QStringList; + +namespace Kleo { + + /** + @short An abstract base class for asynchronous key refreshers. + + To use a RefreshKeysJob, first obtain an instance from the + CryptoBackend implementation, connect the progress() and result() + signals to suitable slots and then start the key refresh with a + call to start(). This call might fail, in which case the + RefreshKeysJob instance will have scheduled its own destruction + with a call to QObject::deleteLater(). + + After result() is emitted, the KeyListJob will schedule it's own + destruction by calling QObject::deleteLater(). + */ + class RefreshKeysJob : public Job { + Q_OBJECT + protected: + RefreshKeysJob( QObject * parent, const char * name ); + + public: + ~RefreshKeysJob(); + + /** + Starts the keylist operation. \a pattern is a list of patterns + used to restrict the list of keys returned. Empty patterns are + ignored. If \a pattern is empty or contains only empty strings, + all keys are returned (however, the backend is free to truncate + the result and should do so; when this happens, it will be + reported by the reult object). + + If \a secretOnly is true, only keys for which the secret key is + also available are returned. Use this if you need to select a + key for signing. + */ + virtual GpgME::Error start( const QStringList & patterns ) = 0; + + signals: + void result( const GpgME::Error & error ); + }; + +} + +#endif // __KLEO_REFRESHKEYSJOB_H__ diff --git a/certmanager/lib/kleo/signencryptjob.h b/certmanager/lib/kleo/signencryptjob.h new file mode 100644 index 000000000..42d3a179f --- /dev/null +++ b/certmanager/lib/kleo/signencryptjob.h @@ -0,0 +1,103 @@ +/* + signencryptjob.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_SIGNENCRYPTJOB_H__ +#define __KLEO_SIGNENCRYPTJOB_H__ + +#include <gpgmepp/context.h> // for Context::SignatureMode (or should + // we roll our own enum here?) +#include "job.h" +#include <qcstring.h> + +#include <vector> +#include <utility> + +namespace GpgME { + class Error; + class Key; + class SigningResult; + class EncryptionResult; +} + + +namespace Kleo { + + /** + @short An abstract base class for asynchronous combined signing and encrypting + + To use a SignEncryptJob, first obtain an instance from the + CryptoBackend implementation, connect the progress() and result() + signals to suitable slots and then start the operation with a + call to start(). This call might fail, in which case the + SignEncryptJob instance will have scheduled it's own destruction + with a call to QObject::deleteLater(). + + After result() is emitted, the SignEncryptJob will schedule it's + own destruction by calling QObject::deleteLater(). + */ + class SignEncryptJob : public Job { + Q_OBJECT + protected: + SignEncryptJob( QObject * parent, const char * name ); + public: + ~SignEncryptJob(); + + /** + Starts the combined signing and encrypting operation. \a signers + is the list of keys to sign \a plainText with. \a recipients is + a list of keys to encrypt the signed \a plainText to. In both + lists, empty (null) keys are ignored. + + If \a alwaysTrust is true, validity checking for the + \em recipient keys will not be performed, but full validity + assumed for all \em recipient keys without further checks. + */ + virtual GpgME::Error start( const std::vector<GpgME::Key> & signers, + const std::vector<GpgME::Key> & recipients, + const QByteArray & plainText, + bool alwaysTrust=false ) = 0; + + virtual std::pair<GpgME::SigningResult,GpgME::EncryptionResult> + exec( const std::vector<GpgME::Key> & signers, + const std::vector<GpgME::Key> & recipients, + const QByteArray & plainText, + bool alwaysTrust, QByteArray & cipherText ) = 0; + + signals: + void result( const GpgME::SigningResult & signingresult, + const GpgME::EncryptionResult & encryptionresult, + const QByteArray & cipherText ); + }; + +} + +#endif // __KLEO_SIGNENCRYPTJOB_H__ diff --git a/certmanager/lib/kleo/signjob.h b/certmanager/lib/kleo/signjob.h new file mode 100644 index 000000000..17ea3d947 --- /dev/null +++ b/certmanager/lib/kleo/signjob.h @@ -0,0 +1,90 @@ +/* + signjob.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_SIGNJOB_H__ +#define __KLEO_SIGNJOB_H__ + +#include <gpgmepp/context.h> // for Context::SignatureMode (or should + // we roll our own enum here?) +#include "job.h" +#include <qcstring.h> + +#include <vector> + +namespace GpgME { + class Error; + class Key; + class SigningResult; +} + + +namespace Kleo { + + /** + @short An abstract base class for asynchronous signing + + To use a SignJob, first obtain an instance from the CryptoBackend + implementation, connect the progress() and result() signals to + suitable slots and then start the signing with a call to + start(). This call might fail, in which case the SignJob instance + will have scheduled it's own destruction with a call to + QObject::deleteLater(). + + After result() is emitted, the SignJob will schedule it's own + destruction by calling QObject::deleteLater(). + */ + class SignJob : public Job { + Q_OBJECT + protected: + SignJob( QObject * parent, const char * name ); + public: + ~SignJob(); + + /** + Starts the signing operation. \a signers is the list of keys to + sign \a plainText with. Empty (null) keys are ignored. + */ + virtual GpgME::Error start( const std::vector<GpgME::Key> & signers, + const QByteArray & plainText, + GpgME::Context::SignatureMode mode ) = 0; + virtual GpgME::SigningResult exec( const std::vector<GpgME::Key> & signers, + const QByteArray & plainText, + GpgME::Context::SignatureMode mode, + QByteArray & signature ) = 0; + + signals: + void result( const GpgME::SigningResult & result, const QByteArray & signature ); + }; + +} + +#endif // __KLEO_SIGNJOB_H__ diff --git a/certmanager/lib/kleo/specialjob.h b/certmanager/lib/kleo/specialjob.h new file mode 100644 index 000000000..e7280b0a5 --- /dev/null +++ b/certmanager/lib/kleo/specialjob.h @@ -0,0 +1,86 @@ +/* + specialjob.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_SPECIALJOB_H__ +#define __KLEO_SPECIALJOB_H__ + +#include "job.h" + +namespace GpgME { + class Error; +} + +namespace Kleo { + + /** + @short An abstract base class for protocol-specific jobs + + To use a SpecialJob, first obtain an instance from the + CryptoBackend implementation, connect progress() and result() + signals to suitable slots and then start the job with a call to + start(). This call might fail, in which case the SpecialJob + instance will have schedules its own destruction with a call to + QObject::deleteLater(). + + After result() is emitted, the SpecialJob will schedule its own + destruction by calling QObject::deleteLater(). + + Parameters are set using the Qt property system. More general, or + constructor parameters are given in the call to + Kleo::CryptoBackend::Protocol::specialJob(). + + The result is made available through the result signal, and + through the read-only result property, the latter of which needs + to be defined in each SpecialJob subclass. + */ + class SpecialJob : public Job { + Q_OBJECT + protected: + SpecialJob( QObject * parent, const char * name ); + + public: + ~SpecialJob(); + + /** + Starts the special operation. + */ + virtual GpgME::Error start() = 0; + + virtual GpgME::Error exec() = 0; + + signals: + void result( const GpgME::Error & result, const QVariant & data ); + }; + +} + +#endif // __KLEO_SPECIALJOB_H__ diff --git a/certmanager/lib/kleo/verifydetachedjob.h b/certmanager/lib/kleo/verifydetachedjob.h new file mode 100644 index 000000000..f50fda546 --- /dev/null +++ b/certmanager/lib/kleo/verifydetachedjob.h @@ -0,0 +1,86 @@ +/* + verifydetachedjob.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_VERIFYDETACHEDJOB_H__ +#define __KLEO_VERIFYDETACHEDJOB_H__ + +#include "job.h" + +#include <qcstring.h> + +namespace GpgME { + class Error; + class Key; + class VerificationResult; +} + + +namespace Kleo { + + /** + @short An abstract base class for asynchronous verification of detached signatures + + To use a VerifyDetachedJob, first obtain an instance from the + CryptoBackend implementation, connect the progress() and result() + signals to suitable slots and then start the verification with a + call to start(). This call might fail, in which case the + VerifyDetachedJob instance will have scheduled it's own + destruction with a call to QObject::deleteLater(). + + After result() is emitted, the VerifyDetachedJob will schedule + it's own destruction by calling QObject::deleteLater(). + */ + class VerifyDetachedJob : public Job { + Q_OBJECT + protected: + VerifyDetachedJob( QObject * parent, const char * name ); + public: + ~VerifyDetachedJob(); + + /** + Starts the verification operation. \a signature contains the + signature data, while \a signedData contains the data over + which the signature was made. + */ + virtual GpgME::Error start( const QByteArray & signature, + const QByteArray & signedData ) = 0; + + virtual GpgME::VerificationResult exec( const QByteArray & signature, + const QByteArray & signedData ) = 0; + + signals: + void result( const GpgME::VerificationResult & result ); + }; + +} + +#endif // __KLEO_VERIFYDETACHEDJOB_H__ diff --git a/certmanager/lib/kleo/verifyopaquejob.h b/certmanager/lib/kleo/verifyopaquejob.h new file mode 100644 index 000000000..b38b18de1 --- /dev/null +++ b/certmanager/lib/kleo/verifyopaquejob.h @@ -0,0 +1,85 @@ +/* + verifyopaquejob.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_VERIFYOPAQUEJOB_H__ +#define __KLEO_VERIFYOPAQUEJOB_H__ + +#include "job.h" + +#include <qcstring.h> + +namespace GpgME { + class Error; + class Key; + class VerificationResult; +} + + +namespace Kleo { + + /** + @short An abstract base class for asynchronous verification of opaque signatures + + To use a VerifyOpaqueJob, first obtain an instance from the + CryptoBackend implementation, connect the progress() and result() + signals to suitable slots and then start the verification with a + call to start(). This call might fail, in which case the + VerifyOpaqueJob instance will have scheduled it's own + destruction with a call to QObject::deleteLater(). + + After result() is emitted, the VerifyOpaqueJob will schedule + it's own destruction by calling QObject::deleteLater(). + */ + class VerifyOpaqueJob : public Job { + Q_OBJECT + protected: + VerifyOpaqueJob( QObject * parent, const char * name ); + public: + ~VerifyOpaqueJob(); + + /** + Starts the verification operation. \a signature contains the + signature data, while \a signedData contains the data over + which the signature was made. + */ + virtual GpgME::Error start( const QByteArray & signedData ) = 0; + + /** Synchronous version of @ref start */ + virtual GpgME::VerificationResult exec( const QByteArray & signedData, QByteArray & plainText ) = 0; + + signals: + void result( const GpgME::VerificationResult & result, const QByteArray & plainText ); + }; + +} + +#endif // __KLEO_VERIFYOPAQUEJOB_H__ diff --git a/certmanager/lib/libkleopatrarc.desktop b/certmanager/lib/libkleopatrarc.desktop new file mode 100644 index 000000000..3af8feaf0 --- /dev/null +++ b/certmanager/lib/libkleopatrarc.desktop @@ -0,0 +1,323 @@ +[Key Filter #0] +was-validated=false +Name=Not Validated Key +Name[af]=Sleutel nie bevestig nie +Name[bg]=Ðепроверен ключ +Name[ca]=Clau no validada +Name[cs]=Nevalidovaný klÃÄ +Name[da]=Ikke godkendt nøgle +Name[de]=Ungeprüfter Schlüssel +Name[el]=Μη επικυÏωμÎνο κλειδί +Name[eo]=Åœlosilo Ne Validigita +Name[es]=Clave no validada +Name[et]=Võtme ehtsus kontrollimatu +Name[eu]=Balidatu gabeko gakoa +Name[fa]=کلید بدون اعتبار +Name[fi]=Varmistamaton avain +Name[fr]=Clé non validée +Name[fy]=Net falidearre kaai +Name[gl]=Non hai Chave Validada +Name[he]=מפתח ×œ× ×ž×•×•×“× +Name[hu]=Nem ellenÅ‘rzött kulcs +Name[is]=Ekki staðfestur lykill +Name[it]=Chiave non convalidata +Name[ja]=èªè¨¼ã•ã‚Œã¦ã„ãªã„éµ +Name[ka]=დáƒáƒ£áƒ›áƒáƒ¬áƒ›áƒ”ბელი გáƒáƒ¡áƒáƒ¦áƒ”ბი +Name[kk]=ТекÑерілмеген кілт +Name[km]=កូនសោ​គ្មាន​សុពលភាព +Name[ko]=ê²€ì¦ë˜ì§€ ì•Šì€ í‚¤ +Name[lt]=Nevaliduotas raktas +Name[ms]=Kekunci Tidak Disahkan +Name[nb]=Nøkkel ikke sjekket for gyldighet +Name[nds]=Nich pröövt Slötel +Name[ne]=पà¥à¤°à¤®à¤¾à¤£à¥€à¤¤ नगरिà¤à¤•à¥‹ कà¥à¤žà¥à¤œà¥€ +Name[nl]=Geen gevalideerde sleutel +Name[nn]=Ikkje-validert nøkkel +Name[pl]=Niesprawdzony klucz +Name[pt]=Chave Não Validada +Name[pt_BR]=Chave Não Validada +Name[ru]=Ðепроверенный ключ +Name[se]=Ii-validerejuvvon Äoavdda +Name[sk]=Neoverený kÄ¾ÃºÄ +Name[sl]=Nepreverjen kljuÄ +Name[sr]=Ðеоверени кључ +Name[sr@Latn]=Neovereni kljuÄ +Name[sv]=Nyckeln har inte validerats +Name[ta]=செலà¯à®²à¯à®ªà®Ÿà®¿à®¯à®¾à®•à®¾à®¤ விசை +Name[tr]=Geçerli Olmayan Anahtar +Name[uk]=Ðеперевірений ключ +Name[zh_CN]=æœªæ ¡éªŒçš„å¯†é’¥ +Name[zh_TW]=未確èªçš„金鑰 + +[Key Filter #1] +was-validated=true +is-expired=true +is-revoked=false +foreground-color=255,0,0 +Name=Expired Key +Name[af]=Sleutel het verval +Name[bg]=Изтекъл ключ +Name[br]=Alc'hwez kabac'het +Name[ca]=Clau expirada +Name[cs]=KlÃÅ¡ s proÅ¡lou platnostà +Name[da]=Udløbet nøgle +Name[de]=Abgelaufener Schlüssel +Name[el]=ΛηγμÎνο κλειδί +Name[eo]=Åœlosilo EksvalidiÄinta +Name[es]=Clave caducada +Name[et]=Aegunud võti +Name[eu]=Iraungitako gakoa +Name[fa]=کلید منقضی +Name[fi]=Vanhentunut avain +Name[fr]=Clé expirée +Name[fy]=Ferrûne kaai +Name[gl]=Chave caducada +Name[he]=מפתח ×œ× ×ª×§×£ +Name[hu]=Lejárt kulcs +Name[is]=Útrunninn lykill +Name[it]=Chiave scaduta +Name[ja]=期é™åˆ‡ã‚Œã®éµ +Name[ka]=ვáƒáƒ“áƒáƒ’áƒáƒ¡áƒ£áƒšáƒ˜ გáƒáƒ¡áƒáƒ¦áƒ”ბი +Name[kk]=ЕÑкірген кілт +Name[km]=កូនសោ​បាន​ផុážáž€áŸ†ážŽážáŸ‹ +Name[ko]=ë§Œë£Œëœ í‚¤ +Name[lt]=BaigÄ™s galioti raktas +Name[mk]=ИÑтечен клуч +Name[ms]=Kekunci Luput +Name[nb]=UtgÃ¥tt nøkkel +Name[nds]=Aflopen Slötel +Name[ne]=मà¥à¤¯à¤¾à¤¦ समापà¥à¤¤ à¤à¤à¤•à¥‹ कà¥à¤žà¥à¤œà¥€ +Name[nl]=Verlopen sleutel +Name[nn]=Forelda nøkkel +Name[pl]=Klucz, który straciÅ‚ ważność +Name[pt]=Chave Expirada +Name[pt_BR]=Chave Expirada +Name[ru]=УтерÑвший Ñилу ключ +Name[se]=Boarásmuvvan Äoavdda +Name[sk]=VyprÅ¡aný kÄ¾ÃºÄ +Name[sl]=PreteÄen kljuÄ +Name[sr]=ИÑтекли кључ +Name[sr@Latn]=Istekli kljuÄ +Name[sv]=UtgÃ¥ngen nyckel +Name[ta]=காலாவதியான விசை +Name[tr]=Süresi DolmuÅŸ Anahtar +Name[uk]=ЗаÑтарілий ключ +Name[zh_CN]=过期密钥 +Name[zh_TW]=å·²éŽæœŸçš„金鑰 + +[Key Filter #2] +was-validated=true +is-revoked=true +Name=Revoked Key +Name[af]=Sleutel was herroep +Name[bg]=Ðнулиран ключ +Name[ca]=Clau revocada +Name[cs]=Odvolaný klÃÄ +Name[da]=Fjernet nøgle +Name[de]=Widerrufener Schlüssel +Name[el]=ΑκυÏωμÎνο κλειδί +Name[eo]=Åœlosilo Revokita +Name[es]=Clave revocada +Name[et]=Tühistatud võti +Name[eu]=Errebokatutako gakoa +Name[fa]=کلید لغو‌شده +Name[fi]=Peruutettu avain +Name[fr]=Clé révoquée +Name[fy]=Ynlutsen kaai +Name[gl]=Chave revocada +Name[he]=מפתח ×œ× ×§×‘×™×œ +Name[hu]=Visszavont kulcs +Name[is]=Afturkallaður lykill +Name[it]=Chiave revocata +Name[ja]=ç ´æ£„ã•ã‚ŒãŸéµ +Name[ka]=áƒáƒœáƒ£áƒšáƒ˜áƒ ებული გáƒáƒ¡áƒáƒ¦áƒ”ბი +Name[kk]=Күші жойылған кілт +Name[km]=កូនសោ​ážáŸ’រូវ​បាន​ដកហូហ+Name[ko]=ê±°ë¶€ëœ í‚¤ +Name[lt]=AtÅ¡auktas raktas +Name[mk]=Отповикан клуч +Name[ms]=Kekunci Dibatalkan +Name[nb]=Tilbakekalt nøkkel +Name[nds]=Torüchropen Slötel +Name[ne]=रदà¥à¤¦ गरिà¤à¤•à¥‹ कà¥à¤žà¥à¤œà¥€ +Name[nl]=Ingetrokken sleutel +Name[nn]=Tilbakekalla nøkkel +Name[pl]=OdwoÅ‚any klucz +Name[pt]=Chave Revogada +Name[pt_BR]=Chave Revogada +Name[ru]=Отозванный ключ +Name[sk]=KÄ¾ÃºÄ so zruÅ¡enou platnosÅ¥ou +Name[sl]=Preklican kljuÄ +Name[sr]=Опозвани кључ +Name[sr@Latn]=Opozvani kljuÄ +Name[sv]=Ã…terkallad nyckel +Name[ta]=நீகà¯à®•à®¿à®¯ விசை +Name[tr]=Geri Alınmış Anahtar +Name[uk]=Ðнульований ключ +Name[zh_CN]=åŠé”€çš„密钥 +Name[zh_TW]=已廢棄的金鑰 + +[Key Filter #3] +was-validated=true +is-root-certificate=true +is-validity=ultimate +Name=Trusted Root Certificate +Name[af]=Vertroude 'Root' sertifikaat +Name[ar]=شهادة جذر موثوق بها +Name[bg]=Ðадеждно удоÑтоверение +Name[ca]=Certificat arrel de confiança +Name[cs]=DůvÄ›ryhodný koÅ™enový certifikát +Name[da]=Root-certifikat der stoles pÃ¥ +Name[de]=Vertrauenswürdiges Stammzertifikat +Name[el]=Έμπιστο βασικό πιστοποιητικό +Name[eo]=Fidinda Radika Certifikato +Name[es]=Certificado raÃz de confianza +Name[et]=Usaldusväärne juursertifikaat +Name[eu]=Konfidantzazko erro ziurtagiria +Name[fa]=گواهی‌نامۀ معتبر کاربر ارشد +Name[fi]=Luotettu juurivarmenne +Name[fr]=Certificat racine de confiance +Name[fy]=Fertroude haadsertifikaat +Name[gl]=Certificado raiz autentificado +Name[hu]=MegbÃzható gyökértanúsÃtvány +Name[is]=Treyst rótarskilrÃki +Name[it]=Certificato radice affidabile +Name[ja]=ä¿¡é ¼ã•ã‚ŒãŸãƒ«ãƒ¼ãƒˆè¨¼æ˜Žæ›¸ +Name[ka]= რუტის სáƒáƒœáƒ“რსერთიფიკáƒáƒ¢áƒ˜ +Name[kk]=Сенім артылған түбір куәлігі +Name[km]=វិញ្ញាបនបážáŸ’ážš Root ដែល​អាច​ជឿទុកចិážáŸ’áž +Name[lt]=Patikimas root sertifikatas +Name[mk]=Доверлив коренов Ñертификат +Name[ms]=Sijil Root Dipercaya +Name[nb]=Tiltrodd rot-sertifikat +Name[nds]=Vertroonswöördig Wörtelzertifikaat +Name[ne]=विशà¥à¤µà¤¾à¤¸ गरिà¤à¤•à¤¾ मूल पà¥à¤°à¤®à¤¾à¤£à¤ªà¤¤à¥à¤° +Name[nl]=Vertrouwd hoofdcertificaat +Name[nn]=Tiltrudd rotsertifikat +Name[pl]=Zaufany certyfikat bazowy +Name[pt]=Certificado Raiz de Confiança +Name[pt_BR]=Certificado Raiz Confiável +Name[ru]=ДоверÑемый корневой Ñертификат +Name[se]=Luohttehahtti ruohtassertifikáhta +Name[sk]=Dôveryhodný koreňový certifikát +Name[sl]=Zaupan korenski certifikat +Name[sr]=Корени Ñертификат од поверења +Name[sr@Latn]=Koreni sertifikat od poverenja +Name[sv]=PÃ¥litligt rotcertifikat +Name[ta]=நமà¯à®ªà®•à®®à®¾à®© மூல சானà¯à®±à®¿à®¤à®´à¯ +Name[tr]=Güvenilir Kök Sertifikası +Name[uk]=Кореневий Ñертифікат з довірою +Name[zh_CN]=å¯ä¿¡ä»»çš„æ ¹è¯ä¹¦ +Name[zh_TW]=å¯ä¿¡ä»»çš„æ ¹æ†‘è‰ + +[Key Filter #4] +was-validated=true +is-root-certificate=true +is-not-validity=ultimate +Name=Not Trusted Root Certificate +Name[af]=Nie vertroude 'root' sertifikaat +Name[ar]=شهادة جذر غير موثوق بها +Name[bg]=Ðенадеждно удоÑтоверение +Name[ca]=Certificat arrel sense confiança +Name[cs]=NedůvÄ›ryhodný koÅ™enový certifikát +Name[da]=Root-certifikat der ikke stoles pÃ¥ +Name[de]=Nicht vertrauenswürdiges Stammzertifikat +Name[el]=Μη Îμπιστο βασικό πιστοποιητικό +Name[eo]=Ne Fidinda Radika Certifikato +Name[es]=Certificado raÃz no de confianza +Name[et]=Ebausaldusväärne juursertifikaat +Name[eu]=Konfidantza gabeko erro ziurtagiria +Name[fa]=گواهی‌نامۀ بدون اعتبار کاربر ارشد +Name[fi]=Ei-luotettu juurivarmenne +Name[fr]=Certificat racine non fiable +Name[fy]=Net fertroude haadsertifikaat +Name[gl]=Certificado raiz non autentificado +Name[hu]=Nem megbÃzható gyökértanúsÃtvány +Name[is]=Ekki traust rótarskilrÃki +Name[it]=Certificato radice non affidabile +Name[ja]=ä¿¡é ¼ã•ã‚Œã¦ãªã„ルート証明書 +Name[ka]=რუტის áƒáƒ áƒáƒ¡áƒáƒœáƒ“რსერტიფიკáƒáƒ¢áƒ˜ +Name[kk]=Сенім артылмаған түбір куәлігі +Name[km]=វិញ្ញាបនបážáŸ’ážš Root ដែល​មិន​អាច​ជឿទុកចិážáŸ’áž +Name[lt]=Nepatikimas root sertifikatas +Name[mk]=Ðедоверлив коренов Ñертификат +Name[ms]=Sijil Root Tak Dipercaya +Name[nb]=Ikke tiltrodd rot-sertifikat +Name[nds]=Nich vertroonswöördig Wörtelzertifikaat +Name[ne]=विशà¥à¤µà¤¾à¤¸ नगरिà¤à¤•à¤¾ मूल पà¥à¤°à¤®à¤¾à¤£à¤ªà¤¤à¥à¤° +Name[nl]=Niet vertrouwd hoofdcertificaat +Name[nn]=Ikkje tiltrudd rotsertifikat +Name[pl]=Nie zaufany certyfikat bazowy +Name[pt]=Certificado Raiz Não de Confiança +Name[pt_BR]=Certificado Raiz Não-Confiável +Name[ru]=Ðе доверÑемый корневой Ñертификат +Name[se]=Ii luohttehahtti ruohtassertifikáhta +Name[sk]=Nedôveryhodný koreňový certifikát +Name[sl]=Nezaupan korenski certifikat +Name[sr]=Корени Ñертификат који није од поверења +Name[sr@Latn]=Koreni sertifikat koji nije od poverenja +Name[sv]=OpÃ¥litligt rotcertifikat +Name[ta]=நமà¯à®ªà®®à¯à®Ÿà®¿à®¯à®¾à®¤ மூல சானà¯à®±à®¿à®¤à®´à¯ +Name[tr]=Güvenilmeyen Kök Sertifikası +Name[uk]=Кореневий Ñертифікат без довіри +Name[zh_CN]=æœªä¿¡ä»»çš„æ ¹è¯ä¹¦ +Name[zh_TW]=ä¸å¯ä¿¡ä»»çš„æ ¹æ†‘è‰ + +[Key Filter #5] +was-validated=true +Name=Other Keys +Name[af]=Ander Sleutels +Name[ar]=Ù…ÙØ§ØªÙŠØ Ø¢Ø®Ø±Ù‰ +Name[bg]=Други ключове +Name[br]=Alc'hwezioù all +Name[ca]=Altres claus +Name[cs]=Ostatnà klÃÄe +Name[da]=Andre nøgler +Name[de]=Andere Schlüssel +Name[el]=Άλλα κλειδιά +Name[eo]=Aliaj Åœlosiloj +Name[es]=Otras claves +Name[et]=Muud võtmed +Name[eu]=Beste gakoak +Name[fa]=کلیدهای دیگر +Name[fi]=Muut avaimet +Name[fr]=Autres clés +Name[fy]=Oare kaaien +Name[ga]=Eochracha Eile +Name[gl]=Outras chaves +Name[he]=מפתחות ××—×¨×™× +Name[hu]=Egyéb kulcsok +Name[is]=Aðrir lyklar +Name[it]=Altre chiavi +Name[ja]=ä»–ã®éµ +Name[ka]=სხვრგáƒáƒ¡áƒáƒ¦áƒ”ბები +Name[kk]=БаÑқа кілттер +Name[km]=កូនសោ​ផ្សáŸáž„​ទៀហ+Name[ko]=기타 키 +Name[lt]=Kiti raktai +Name[mk]=Други клучеви +Name[ms]=Kekunci Lain +Name[nb]=Andre nøkler +Name[nds]=Anner Slötels +Name[ne]=अनà¥à¤¯ कà¥à¤žà¥à¤œà¥€ +Name[nl]=Andere sleutels +Name[nn]=Andre nøklar +Name[pa]=ਹੋਰ ਕà©à©°à¨œà©€à¨†à¨‚ +Name[pl]=Inne klucze +Name[pt]=Outras Chaves +Name[pt_BR]=Outras Chaves +Name[ru]=Другие ключи +Name[se]=Eará Äoavdagat +Name[sk]=Iné kľúÄe +Name[sl]=Drugi kljuÄi +Name[sr]=Други кључеви +Name[sr@Latn]=Drugi kljuÄevi +Name[sv]=Andra nycklar +Name[ta]=மறà¯à®± விசைகள௠+Name[tr]=DiÄŸer Anahtarlar +Name[uk]=Інші ключі +Name[uz]=Boshqa kalitlar +Name[uz@cyrillic]=Бошқа калитлар +Name[zh_CN]=其它密钥 +Name[zh_TW]=其他金鑰 + diff --git a/certmanager/lib/pics/Makefile.am b/certmanager/lib/pics/Makefile.am new file mode 100644 index 000000000..33704d1b2 --- /dev/null +++ b/certmanager/lib/pics/Makefile.am @@ -0,0 +1,4 @@ +picsdir = $(kde_datadir)/libkleopatra/pics +pics_DATA = key.png key_ok.png key_bad.png key_unknown.png chiasmus_chi.png + +KDE_ICON = gpg gpgsm diff --git a/certmanager/lib/pics/chiasmus_chi.png b/certmanager/lib/pics/chiasmus_chi.png Binary files differnew file mode 100644 index 000000000..cd1d17cd5 --- /dev/null +++ b/certmanager/lib/pics/chiasmus_chi.png diff --git a/certmanager/lib/pics/cr16-app-gpg.png b/certmanager/lib/pics/cr16-app-gpg.png Binary files differnew file mode 100644 index 000000000..04a05c1cb --- /dev/null +++ b/certmanager/lib/pics/cr16-app-gpg.png diff --git a/certmanager/lib/pics/cr16-app-gpgsm.png b/certmanager/lib/pics/cr16-app-gpgsm.png Binary files differnew file mode 100644 index 000000000..04a05c1cb --- /dev/null +++ b/certmanager/lib/pics/cr16-app-gpgsm.png diff --git a/certmanager/lib/pics/cr22-app-gpg.png b/certmanager/lib/pics/cr22-app-gpg.png Binary files differnew file mode 100644 index 000000000..351df8709 --- /dev/null +++ b/certmanager/lib/pics/cr22-app-gpg.png diff --git a/certmanager/lib/pics/cr22-app-gpgsm.png b/certmanager/lib/pics/cr22-app-gpgsm.png Binary files differnew file mode 100644 index 000000000..351df8709 --- /dev/null +++ b/certmanager/lib/pics/cr22-app-gpgsm.png diff --git a/certmanager/lib/pics/cr32-app-gpg.png b/certmanager/lib/pics/cr32-app-gpg.png Binary files differnew file mode 100644 index 000000000..f6db91460 --- /dev/null +++ b/certmanager/lib/pics/cr32-app-gpg.png diff --git a/certmanager/lib/pics/cr32-app-gpgsm.png b/certmanager/lib/pics/cr32-app-gpgsm.png Binary files differnew file mode 100644 index 000000000..f6db91460 --- /dev/null +++ b/certmanager/lib/pics/cr32-app-gpgsm.png diff --git a/certmanager/lib/pics/key.png b/certmanager/lib/pics/key.png Binary files differnew file mode 100644 index 000000000..2da8bd755 --- /dev/null +++ b/certmanager/lib/pics/key.png diff --git a/certmanager/lib/pics/key_bad.png b/certmanager/lib/pics/key_bad.png Binary files differnew file mode 100644 index 000000000..1e0f8ca18 --- /dev/null +++ b/certmanager/lib/pics/key_bad.png diff --git a/certmanager/lib/pics/key_ok.png b/certmanager/lib/pics/key_ok.png Binary files differnew file mode 100644 index 000000000..3fa7e6f0d --- /dev/null +++ b/certmanager/lib/pics/key_ok.png diff --git a/certmanager/lib/pics/key_unknown.png b/certmanager/lib/pics/key_unknown.png Binary files differnew file mode 100644 index 000000000..ee3f542e2 --- /dev/null +++ b/certmanager/lib/pics/key_unknown.png diff --git a/certmanager/lib/tests/Makefile.am b/certmanager/lib/tests/Makefile.am new file mode 100644 index 000000000..3fa819f76 --- /dev/null +++ b/certmanager/lib/tests/Makefile.am @@ -0,0 +1,20 @@ +AM_CPPFLAGS = -I$(top_srcdir)/certmanager/lib \ + -I$(top_srcdir)/libkdenetwork \ + $(GPGME_CFLAGS) $(all_includes) -DKDESRCDIR=\"$(srcdir)\" + +check_PROGRAMS = test_keylister test_keygen test_keyselectiondialog \ + test_cryptoconfig test_gnupgprocessbase test_jobs test_verify +TESTS = test_verify + +test_keylister_SOURCES = test_keylister.cpp +test_keygen_SOURCES = test_keygen.cpp +test_keyselectiondialog_SOURCES = test_keyselectiondialog.cpp +test_cryptoconfig_SOURCES = test_cryptoconfig.cpp +test_gnupgprocessbase_SOURCES = test_gnupgprocessbase.cpp +test_jobs_SOURCES = test_jobs.cpp +test_verify_SOURCES = test_verify.cpp + +LDADD = ../libkleopatra.la + +METASOURCES = AUTO + diff --git a/certmanager/lib/tests/gnupg_home/pubring.gpg b/certmanager/lib/tests/gnupg_home/pubring.gpg Binary files differnew file mode 100644 index 000000000..5b9b35b1b --- /dev/null +++ b/certmanager/lib/tests/gnupg_home/pubring.gpg diff --git a/certmanager/lib/tests/gnupg_home/secring.gpg b/certmanager/lib/tests/gnupg_home/secring.gpg Binary files differnew file mode 100644 index 000000000..1556bbdac --- /dev/null +++ b/certmanager/lib/tests/gnupg_home/secring.gpg diff --git a/certmanager/lib/tests/gnupg_home/trustdb.gpg b/certmanager/lib/tests/gnupg_home/trustdb.gpg Binary files differnew file mode 100644 index 000000000..37cc64fd9 --- /dev/null +++ b/certmanager/lib/tests/gnupg_home/trustdb.gpg diff --git a/certmanager/lib/tests/gnupgviewer.h b/certmanager/lib/tests/gnupgviewer.h new file mode 100644 index 000000000..efba1760b --- /dev/null +++ b/certmanager/lib/tests/gnupgviewer.h @@ -0,0 +1,64 @@ +/* + gnupgviewer.h + + This file is part of libkleopatra's test suite. + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_TESTS_GNUPGVIEWER_H__ +#define __KLEO_TESTS_GNUPGVIEWER_H__ + +#include <qtextedit.h> +#include <qstring.h> + +namespace Kleo { + class GnuPGProcessBase; +} +class KProcess; +class QStringList; + +class GnuPGViewer : public QTextEdit { + Q_OBJECT +public: + GnuPGViewer( QWidget * parent=0, const char * name=0 ); + ~GnuPGViewer(); + + void setProcess( Kleo::GnuPGProcessBase * process ); + +private slots: + void slotStdout( KProcess *, char *, int ); + void slotStderr( KProcess *, char *, int ); + void slotStatus( Kleo::GnuPGProcessBase *, const QString &, const QStringList & ); + void slotProcessExited( KProcess * ); + +private: + Kleo::GnuPGProcessBase * mProcess; + QString mLastStdout, mLastStderr, mLastStatus; +}; + +#endif // __KLEO_TESTS_GNUPGVIEWER_H__ diff --git a/certmanager/lib/tests/test.data b/certmanager/lib/tests/test.data new file mode 100644 index 000000000..b4bce1a93 --- /dev/null +++ b/certmanager/lib/tests/test.data @@ -0,0 +1,295 @@ +/* -*- mode: c++; c-basic-offset:4 -*- + tests/test_uiserver.cpp + + This file is part of Kleopatra, the KDE keymanager + Copyright (c) 2007 Klarälvdalens Datakonsult AB + + Kleopatra is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + Kleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +// +// Usage: test_uiserver <socket> --verify-detached <signed data> <signature> +// +#ifndef _ASSUAN_ONLY_GPG_ERRORS +#define _ASSUAN_ONLY_GPG_ERRORS +#endif +#include "../uiserver/kleo-assuan.h" +#include <gpg-error.h> + +#include <QtCore> + +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <errno.h> +#include <assert.h> + +#include <iostream> +#include <map> +#include <string> +#include <vector> + +using namespace Kleo; + +static std::vector<int> inFDs, outFDs, msgFDs; +static std::vector<std::string> inFiles, outFiles, msgFiles; +static std::map<std::string,std::string> inquireData; + +static std::string hexencode( const std::string & in ) { + std::string result; + result.reserve( 3 * in.size() ); + + static const char hex[] = "0123456789ABCDEF"; + + for ( std::string::const_iterator it = in.begin(), end = in.end() ; it != end ; ++it ) + switch ( const unsigned char ch = *it ) { + default: + if ( ch >= '!' && ch <= '~' || ch > 0xA0 ) { + result += ch; + break; + } + // else fall through + case ' ': + result += '+'; + break; + case '"': + case '#': + case '$': + case '%': + case '\'': + case '+': + case '=': + result += '%'; + result += hex[ (ch & 0xF0) >> 4 ]; + result += hex[ (ch & 0x0F) ]; + break; + } + + return result; +} + +static void usage( const std::string & msg=std::string() ) { + std::cerr << msg << std::endl << + "\n" + "Usage: test_uiserver <socket> [<io>] [<options>] [<inquire>] command [<args>]\n" + "where:\n" + " <io>: [--input[-fd] <file>] [--output[-fd] <file>] [--message[-fd] <file>]\n" + " <options>: *[--option name=value]\n" + " <inquire>: [--inquire keyword=<file>]\n"; + exit( 1 ); +} + +static int data( void * void_ctx, const void * buffer, size_t len ) { + (void)void_ctx; (void)buffer; (void)len; + return 0; // ### implement me +} + +static int status( void * void_ctx, const char * line ) { + (void)void_ctx; (void)line; + return 0; +} + +static int inquire( void * void_ctx, const char * keyword ) { + assuan_context_t ctx = (assuan_context_t)void_ctx; + assert( ctx ); + const std::map<std::string,std::string>::const_iterator it = inquireData.find( keyword ); + if ( it == inquireData.end() ) + return gpg_error( GPG_ERR_UNKNOWN_COMMAND ); + + if ( !it->second.empty() && it->second[0] == '@' ) + return gpg_error( GPG_ERR_NOT_IMPLEMENTED ); + + if ( const gpg_error_t err = assuan_send_data( ctx, it->second.c_str(), it->second.size() ) ) { + qDebug( "assuan_write_data: %s", gpg_strerror( err ) ); + return err; + } + + return 0; +} + +int main( int argc, char * argv[] ) { + + assuan_set_assuan_err_source( GPG_ERR_SOURCE_DEFAULT ); + + if ( argc < 3 ) + usage(); // need socket and command, at least + + const char * socket = argv[1]; + + std::vector<const char*> options; + + std::string command; + for ( int optind = 2 ; optind < argc ; ++optind ) { + const char * const arg = argv[optind]; + if ( qstrcmp( arg, "--input-fd" ) == 0 ) { + int inFD; + if ( (inFD = open( argv[++optind], O_RDONLY )) == -1 ) { + perror( "--input-fd open()" ); + return 1; + } + inFDs.push_back( inFD ); + } else if ( qstrcmp( arg, "--output-fd" ) == 0 ) { + int outFD; + if ( (outFD = open( argv[++optind], O_WRONLY|O_CREAT )) == -1 ) { + perror( "--output-fd open()" ); + return 1; + } + outFDs.push_back( outFD ); + } else if ( qstrcmp( arg, "--message-fd" ) == 0 ) { + int msgFD; + if ( (msgFD = open( argv[++optind], O_RDONLY )) == -1 ) { + perror( "--message-fd open()" ); + return 1; + } + msgFDs.push_back( msgFD ); + } else if ( qstrcmp( arg, "--input" ) == 0 ) { + const std::string file = argv[++optind]; + inFiles.push_back( file ); + } else if ( qstrcmp( arg, "--output" ) == 0 ) { + const std::string file = argv[++optind]; + outFiles.push_back( file ); + } else if ( qstrcmp( arg, "--message" ) == 0 ) { + const std::string file = argv[++optind]; + msgFiles.push_back( file ); + } else if ( qstrcmp( arg, "--option" ) == 0 ) { + options.push_back( argv[++optind] ); + } else if ( qstrcmp( arg, "--inquire" ) == 0 ) { + const std::string inqval = argv[++optind]; + const size_t pos = inqval.find( '=' ); + // ### implement indirection with "@file"... + inquireData[inqval.substr( 0, pos )] = inqval.substr( pos+1 ); + } else { + while ( optind < argc ) { + if ( !command.empty() ) + command += ' '; + command += argv[optind++]; + } + } + } + if ( command.empty() ) + usage( "Command expected, but only options found" ); + + assuan_context_t ctx = 0; + + if ( const gpg_error_t err = assuan_socket_connect_ext( &ctx, socket, -1, 1 ) ) { + qDebug( "%s", assuan_exception( err, "assuan_socket_connect_ext" ).what() ); + return 1; + } + + assuan_set_log_stream( ctx, stderr ); + + for ( std::vector<int>::const_iterator it = inFDs.begin(), end = inFDs.end() ; it != end ; ++it ) { + if ( const gpg_error_t err = assuan_sendfd( ctx, *it ) ) { + qDebug( "%s", assuan_exception( err, "assuan_sendfd( inFD )" ).what() ); + return 1; + } + + if ( const gpg_error_t err = assuan_transact( ctx, "INPUT FD", 0, 0, 0, 0, 0, 0 ) ) { + qDebug( "%s", assuan_exception( err, "INPUT FD" ).what() ); + return 1; + } + } + + + for ( std::vector<std::string>::const_iterator it = inFiles.begin(), end = inFiles.end() ; it != end ; ++it ) { + char buffer[1024]; + sprintf( buffer, "INPUT FILE=%s", hexencode( *it ).c_str() ); + + if ( const gpg_error_t err = assuan_transact( ctx, buffer, 0, 0, 0, 0, 0, 0 ) ) { + qDebug( "%s", assuan_exception( err, buffer ).what() ); + return 1; + } + } + + + for ( std::vector<int>::const_iterator it = msgFDs.begin(), end = msgFDs.end() ; it != end ; ++it ) { + if ( const gpg_error_t err = assuan_sendfd( ctx, *it ) ) { + qDebug( "%s", assuan_exception( err, "assuan_sendfd( msgFD )" ).what() ); + return 1; + } + + if ( const gpg_error_t err = assuan_transact( ctx, "MESSAGE FD", 0, 0, 0, 0, 0, 0 ) ) { + qDebug( "%s", assuan_exception( err, "MESSAGE FD" ).what() ); + return 1; + } + } + + + for ( std::vector<std::string>::const_iterator it = msgFiles.begin(), end = msgFiles.end() ; it != end ; ++it ) { + char buffer[1024]; + sprintf( buffer, "MESSAGE FILE=%s", hexencode( *it ).c_str() ); + + if ( const gpg_error_t err = assuan_transact( ctx, buffer, 0, 0, 0, 0, 0, 0 ) ) { + qDebug( "%s", assuan_exception( err, buffer ).what() ); + return 1; + } + } + + + for ( std::vector<int>::const_iterator it = outFDs.begin(), end = outFDs.end() ; it != end ; ++it ) { + if ( const gpg_error_t err = assuan_sendfd( ctx, *it ) ) { + qDebug( "%s", assuan_exception( err, "assuan_sendfd( outFD )" ).what() ); + return 1; + } + + if ( const gpg_error_t err = assuan_transact( ctx, "OUTPUT FD", 0, 0, 0, 0, 0, 0 ) ) { + qDebug( "%s", assuan_exception( err, "OUTPUT FD" ).what() ); + return 1; + } + } + + + for ( std::vector<std::string>::const_iterator it = outFiles.begin(), end = outFiles.end() ; it != end ; ++it ) { + char buffer[1024]; + sprintf( buffer, "OUTPUT FILE=%s", hexencode( *it ).c_str() ); + + if ( const gpg_error_t err = assuan_transact( ctx, buffer, 0, 0, 0, 0, 0, 0 ) ) { + qDebug( "%s", assuan_exception( err, buffer ).what() ); + return 1; + } + } + + + + Q_FOREACH( const char * opt, options ) { + std::string line = "OPTION "; + line += opt; + if ( const gpg_error_t err = assuan_transact( ctx, line.c_str(), 0, 0, 0, 0, 0, 0 ) ) { + qDebug( "%s", assuan_exception( err, line ).what() ); + return 1; + } + } + + if ( const gpg_error_t err = assuan_transact( ctx, command.c_str(), data, ctx, inquire, ctx, status, ctx ) ) { + qDebug( "%s", assuan_exception( err, command ).what() ); + return 1; + } + + assuan_disconnect( ctx ); + + return 0; +} diff --git a/certmanager/lib/tests/test.data.gpg b/certmanager/lib/tests/test.data.gpg Binary files differnew file mode 100644 index 000000000..2e1d7d161 --- /dev/null +++ b/certmanager/lib/tests/test.data.gpg diff --git a/certmanager/lib/tests/test.data.sig b/certmanager/lib/tests/test.data.sig Binary files differnew file mode 100644 index 000000000..4e2713752 --- /dev/null +++ b/certmanager/lib/tests/test.data.sig diff --git a/certmanager/lib/tests/test_cryptoconfig.cpp b/certmanager/lib/tests/test_cryptoconfig.cpp new file mode 100644 index 000000000..17d1b4471 --- /dev/null +++ b/certmanager/lib/tests/test_cryptoconfig.cpp @@ -0,0 +1,365 @@ +/* + test_cryptoconfig.cpp + + This file is part of libkleopatra's test suite. + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include <backends/qgpgme/qgpgmecryptoconfig.h> + +#include <kapplication.h> +#include <kaboutdata.h> +#include <kcmdlineargs.h> +#include <iostream> +using namespace std; + +#include <stdlib.h> +#include <assert.h> + +int main( int argc, char** argv ) { + + KAboutData aboutData( "test_cryptoconfig", "CryptoConfig Test", "0.1" ); + KCmdLineArgs::init( argc, argv, &aboutData ); + KApplication app( false, false ); + + Kleo::CryptoConfig * config = new QGpgMECryptoConfig(); + + // Dynamic querying of the options + cout << "Components:" << endl; + QStringList components = config->componentList(); + + for( QStringList::Iterator compit = components.begin(); compit != components.end(); ++compit ) { + cout << "Component " << (*compit).local8Bit() << ":" << endl; + const Kleo::CryptoConfigComponent* comp = config->component( *compit ); + assert( comp ); + QStringList groups = comp->groupList(); + for( QStringList::Iterator groupit = groups.begin(); groupit != groups.end(); ++groupit ) { + const Kleo::CryptoConfigGroup* group = comp->group( *groupit ); + assert( group ); + cout << " Group " << (*groupit).local8Bit() << ": descr=\"" << group->description().local8Bit() << "\"" + << " level=" << group->level() << endl; + QStringList entries = group->entryList(); + for( QStringList::Iterator entryit = entries.begin(); entryit != entries.end(); ++entryit ) { + const Kleo::CryptoConfigEntry* entry = group->entry( *entryit ); + assert( entry ); + cout << " Entry " << (*entryit).local8Bit() << ":" + << " descr=\"" << entry->description().local8Bit() << "\"" + << " " << ( entry->isSet() ? "is set" : "is not set" ); + if ( !entry->isList() ) + switch( entry->argType() ) { + case Kleo::CryptoConfigEntry::ArgType_None: + break; + case Kleo::CryptoConfigEntry::ArgType_Int: + cout << " int value=" << entry->intValue(); + break; + case Kleo::CryptoConfigEntry::ArgType_UInt: + cout << " uint value=" << entry->uintValue(); + break; + case Kleo::CryptoConfigEntry::ArgType_LDAPURL: + case Kleo::CryptoConfigEntry::ArgType_URL: + cout << " URL value=" << entry->urlValue().prettyURL().local8Bit(); + // fallthrough + case Kleo::CryptoConfigEntry::ArgType_Path: + // fallthrough + case Kleo::CryptoConfigEntry::ArgType_DirPath: + // fallthrough + case Kleo::CryptoConfigEntry::ArgType_String: + + cout << " string value=" << entry->stringValue().local8Bit(); + break; + } + else // lists + { + switch( entry->argType() ) { + case Kleo::CryptoConfigEntry::ArgType_None: { + cout << " set " << entry->numberOfTimesSet() << " times"; + break; + } + case Kleo::CryptoConfigEntry::ArgType_Int: { + assert( entry->isOptional() ); // empty lists must be allowed (see issue121) + QValueList<int> lst = entry->intValueList(); + QString str; + for( QValueList<int>::Iterator it = lst.begin(); it != lst.end(); ++it ) { + str += QString::number( *it ); + } + cout << " int values=" << str.local8Bit(); + break; + } + case Kleo::CryptoConfigEntry::ArgType_UInt: { + assert( entry->isOptional() ); // empty lists must be allowed (see issue121) + QValueList<uint> lst = entry->uintValueList(); + QString str; + for( QValueList<uint>::Iterator it = lst.begin(); it != lst.end(); ++it ) { + str += QString::number( *it ); + } + cout << " uint values=" << str.local8Bit(); + break; + } + case Kleo::CryptoConfigEntry::ArgType_LDAPURL: + case Kleo::CryptoConfigEntry::ArgType_URL: { + assert( entry->isOptional() ); // empty lists must be allowed (see issue121) + KURL::List urls = entry->urlValueList(); + cout << " url values=" << urls.toStringList().join(" ").local8Bit() << "\n "; + } + // fallthrough + case Kleo::CryptoConfigEntry::ArgType_Path: + // fallthrough + case Kleo::CryptoConfigEntry::ArgType_DirPath: + // fallthrough + case Kleo::CryptoConfigEntry::ArgType_String: { + assert( entry->isOptional() ); // empty lists must be allowed (see issue121) + QStringList lst = entry->stringValueList(); + cout << " string values=" << lst.join(" ").local8Bit(); + break; + } + } + } + cout << endl; + } + // ... + } + } + + { + // Static querying of a single boolean option + static const char* s_groupName = "Monitor"; + static const char* s_entryName = "quiet"; + Kleo::CryptoConfigEntry* entry = config->entry( "dirmngr", s_groupName, s_entryName ); + if ( entry ) { + assert( entry->argType() == Kleo::CryptoConfigEntry::ArgType_None ); + bool val = entry->boolValue(); + cout << "quiet option initially: " << ( val ? "is set" : "is not set" ) << endl; + + entry->setBoolValue( !val ); + assert( entry->isDirty() ); + config->sync( true ); + + // Clear cached values! + config->clear(); + + // Check new value + Kleo::CryptoConfigEntry* entry = config->entry( "dirmngr", s_groupName, s_entryName ); + assert( entry ); + assert( entry->argType() == Kleo::CryptoConfigEntry::ArgType_None ); + cout << "quiet option now: " << ( val ? "is set" : "is not set" ) << endl; + assert( entry->boolValue() == !val ); + + // Set to default + entry->resetToDefault(); + assert( entry->boolValue() == false ); // that's the default + assert( entry->isDirty() ); + assert( !entry->isSet() ); + config->sync( true ); + config->clear(); + + // Check value + entry = config->entry( "dirmngr", s_groupName, s_entryName ); + assert( !entry->isDirty() ); + assert( !entry->isSet() ); + cout << "quiet option reset to default: " << ( entry->boolValue() ? "is set" : "is not set" ) << endl; + assert( entry->boolValue() == false ); + + // Reset old value + entry->setBoolValue( val ); + assert( entry->isDirty() ); + config->sync( true ); + + cout << "quiet option reset to initial: " << ( val ? "is set" : "is not set" ) << endl; + } + else + cout << "Entry 'dirmngr/" << s_groupName << "/" << s_entryName << "' not found" << endl; + } + + { + // Static querying and setting of a single int option + static const char* s_groupName = "LDAP"; + static const char* s_entryName = "ldaptimeout"; + Kleo::CryptoConfigEntry* entry = config->entry( "dirmngr", s_groupName, s_entryName ); + if ( entry ) { + assert( entry->argType() == Kleo::CryptoConfigEntry::ArgType_UInt ); + uint val = entry->uintValue(); + cout << "LDAP timeout initially: " << val << " seconds." << endl; + + // Test setting the option directly, then querying again + //system( "echo 'ldaptimeout:0:101' | gpgconf --change-options dirmngr" ); + // Now let's do it with the C++ API instead + entry->setUIntValue( 101 ); + assert( entry->isDirty() ); + config->sync( true ); + + // Clear cached values! + config->clear(); + + // Check new value + Kleo::CryptoConfigEntry* entry = config->entry( "dirmngr", s_groupName, s_entryName ); + assert( entry ); + assert( entry->argType() == Kleo::CryptoConfigEntry::ArgType_UInt ); + cout << "LDAP timeout now: " << entry->uintValue() << " seconds." << endl; + assert( entry->uintValue() == 101 ); + + // Set to default + entry->resetToDefault(); + assert( entry->uintValue() == 100 ); + assert( entry->isDirty() ); + assert( !entry->isSet() ); + config->sync( true ); + config->clear(); + + // Check value + entry = config->entry( "dirmngr", s_groupName, s_entryName ); + assert( !entry->isDirty() ); + assert( !entry->isSet() ); + cout << "LDAP timeout reset to default, " << entry->uintValue() << " seconds." << endl; + assert( entry->uintValue() == 100 ); + + // Reset old value + entry->setUIntValue( val ); + assert( entry->isDirty() ); + config->sync( true ); + + cout << "LDAP timeout reset to initial " << val << " seconds." << endl; + } + else + cout << "Entry 'dirmngr/" << s_groupName << "/" << s_entryName << "' not found" << endl; + } + + { + // Static querying and setting of a single string option + static const char* s_groupName = "Debug"; + static const char* s_entryName = "log-file"; + Kleo::CryptoConfigEntry* entry = config->entry( "dirmngr", s_groupName, s_entryName ); + if ( entry ) { + assert( entry->argType() == Kleo::CryptoConfigEntry::ArgType_Path ); + QString val = entry->stringValue(); + cout << "Log-file initially: " << val.local8Bit() << endl; + + // Test setting the option, sync'ing, then querying again + entry->setStringValue( QString::fromUtf8( "/tmp/test:%e5ä" ) ); + assert( entry->isDirty() ); + config->sync( true ); + + // Let's see how it prints it + system( "gpgconf --list-options dirmngr | grep log-file" ); + + // Clear cached values! + config->clear(); + + // Check new value + Kleo::CryptoConfigEntry* entry = config->entry( "dirmngr", s_groupName, s_entryName ); + assert( entry ); + assert( entry->argType() == Kleo::CryptoConfigEntry::ArgType_Path ); + cout << "Log-file now: " << entry->stringValue().local8Bit() << endl; + assert( entry->stringValue() == QString::fromUtf8( "/tmp/test:%e5ä" ) ); // (or even with %e5 decoded) + + // Reset old value +#if 0 + QString arg( val ); + if ( !arg.isEmpty() ) + arg.prepend( '"' ); + QCString sys; + sys.sprintf( "echo 'log-file:%s' | gpgconf --change-options dirmngr", arg.local8Bit().data() ); + system( sys.data() ); +#endif + entry->setStringValue( val ); + assert( entry->isDirty() ); + config->sync( true ); + + cout << "Log-file reset to initial " << val.local8Bit() << endl; + } + else + cout << "Entry 'dirmngr/" << s_groupName << "/" << s_entryName << "' not found" << endl; + } + + { + // Static querying and setting of the LDAP URL list option + static const char* s_groupName = "LDAP"; + static const char* s_entryName = "LDAP Server"; + Kleo::CryptoConfigEntry* entry = config->entry( "dirmngr", s_groupName, s_entryName ); + if ( entry ) { + assert( entry->argType() == Kleo::CryptoConfigEntry::ArgType_LDAPURL ); + assert( entry->isList() ); + KURL::List val = entry->urlValueList(); + cout << "URL list initially: " << val.toStringList().join(", ").local8Bit() << endl; + + // Test setting the option, sync'ing, then querying again + KURL::List lst; + // We use non-empty paths to workaround a bug in KURL (kdelibs-3.2) + lst << KURL( "ldap://a:389/?b" ); + // Test with query containing a litteral ':' (KURL supports this) + // and a ' ' (KURL will escape it, see issue119) + lst << KURL( "ldap://foo:389/?a:b c" ); + lst << KURL( "ldap://server:389/?a%3db,c=DE" ); // the query contains a litteral ',' + //cout << " trying to set: " << lst.toStringList().join(", ").local8Bit() << endl; + assert( lst[0].query() == "?b" ); + assert( lst[1].query() == "?a:b%20c" ); // see, the space got escaped + entry->setURLValueList( lst ); + assert( entry->isDirty() ); + config->sync( true ); + + // Let's see how it prints it + system( "gpgconf --list-options dirmngr | grep 'LDAP Server'" ); + + // Clear cached values! + config->clear(); + + // Check new value + Kleo::CryptoConfigEntry* entry = config->entry( "dirmngr", s_groupName, s_entryName ); + assert( entry ); + assert( entry->argType() == Kleo::CryptoConfigEntry::ArgType_LDAPURL ); + assert( entry->isList() ); + // Get raw a:b:c:d:e form + QStringList asStringList = entry->stringValueList(); + assert( asStringList.count() == 3 ); + cout << "asStringList[0]=" << asStringList[0].local8Bit() << endl; + cout << "asStringList[1]=" << asStringList[1].local8Bit() << endl; + cout << "asStringList[2]=" << asStringList[2].local8Bit() << endl; + assert( asStringList[0] == "a:389:::b" ); + assert( asStringList[1] == "foo:389:::a%3ab c" ); // the space must be decoded (issue119) + assert( asStringList[2] == "server:389:::a=b,c=DE" ); // all decoded + // Get KURL form + KURL::List newlst = entry->urlValueList(); + cout << "URL list now: " << newlst.toStringList().join(", ").local8Bit() << endl; + assert( newlst.count() == 3 ); + //cout << "newlst[0]=" << newlst[0].url().local8Bit() << endl; + //cout << "lst[0]=" << lst[0].url().local8Bit() << endl; + assert( newlst[0] == lst[0] ); + assert( newlst[1] == lst[1] ); + assert( newlst[2].url() == "ldap://server:389/?a=b,c=DE" ); // != lst[2] due to the encoded = + + // Reset old value + entry->setURLValueList( val ); + assert( entry->isDirty() ); + config->sync( true ); + + cout << "URL list reset to initial: " << val.toStringList().join(", ").local8Bit() << endl; + } + else + cout << "Entry 'dirmngr/" << s_groupName << "/" << s_entryName << "' not found" << endl; + } + + cout << "Done." << endl; +} diff --git a/certmanager/lib/tests/test_gnupgprocessbase.cpp b/certmanager/lib/tests/test_gnupgprocessbase.cpp new file mode 100644 index 000000000..37e961801 --- /dev/null +++ b/certmanager/lib/tests/test_gnupgprocessbase.cpp @@ -0,0 +1,143 @@ +/* + gnupgviewer.cpp + + This file is part of libkleopatra's test suite. + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "gnupgviewer.h" + +#include <backends/qgpgme/gnupgprocessbase.h> + +#include <kapplication.h> +#include <kaboutdata.h> +#include <kcmdlineargs.h> +#include <kmessagebox.h> +#include <kdebug.h> + +#include <qstringlist.h> + +GnuPGViewer::GnuPGViewer( QWidget * parent, const char * name ) + : QTextEdit( parent, name ), mProcess( 0 ) +{ + setTextFormat( LogText ); + setMaxLogLines( 10000 ); +} + +GnuPGViewer::~GnuPGViewer() { + if ( mProcess ) + mProcess->kill(); +} + +void GnuPGViewer::setProcess( Kleo::GnuPGProcessBase * process ) { + if ( !process ) + return; + mProcess = process; + connect( mProcess, SIGNAL(processExited(KProcess*)), + SLOT(slotProcessExited(KProcess*)) ); + connect( mProcess, SIGNAL(receivedStdout(KProcess*,char*,int)), + SLOT(slotStdout(KProcess*,char*,int)) ); + connect( mProcess, SIGNAL(receivedStderr(KProcess*,char*,int)), + SLOT(slotStderr(KProcess*,char*,int)) ); + connect( mProcess, SIGNAL(status(Kleo::GnuPGProcessBase*,const QString&,const QStringList&)), + SLOT(slotStatus(Kleo::GnuPGProcessBase*,const QString&,const QStringList&)) ); +} + +static QStringList split( char * buffer, int buflen, QString & old ) { + // when done right, this would need to use QTextCodec... + const QString str = old + QString::fromLocal8Bit( buffer, buflen ); + QStringList l = QStringList::split( '\n', str, true ); + if ( l.empty() ) + return l; + if ( str.endsWith( "\n" ) ) { + old = QString::null; + } else { + old = l.back(); + l.pop_back(); + } + return l; +} + +static QString escape( QString str ) { + return str.replace( '&', "&" ).replace( '<', "<" ).replace( '>', ">" ); +} + +void GnuPGViewer::slotStdout( KProcess *, char * buffer, int buflen ) { + const QStringList l = split( buffer, buflen, mLastStdout ); + for ( QStringList::const_iterator it = l.begin() ; it != l.end() ; ++it ) + append( "stdout: " + escape( *it ) ); +} + +void GnuPGViewer::slotStderr( KProcess *, char * buffer, int buflen ) { + const QStringList l = split( buffer, buflen, mLastStderr ); + for ( QStringList::const_iterator it = l.begin() ; it != l.end() ; ++it ) + append( "<b>stderr: " + escape( *it ) + "</b>" ); +} +void GnuPGViewer::slotStatus( Kleo::GnuPGProcessBase *, const QString & type, const QStringList & args ) { + append( "<b><font color=\"red\">status: " + escape( type + ' ' + args.join( " " ) ) + "</font></b>" ); +} +void GnuPGViewer::slotProcessExited( KProcess * proc ) { + if ( !proc ) + return; + if ( proc->normalExit() ) + append( QString( "<b>Process exit: return code %1</b>" ).arg ( proc->exitStatus() ) ); + else + append( "<b>Process exit: killed</b>" ); +} + +int main( int argc, char** argv ) { + if ( argc < 3 ) { + kdDebug() << "Need at least two arguments" << endl; + return 1; + } + KAboutData aboutData( "test_gnupgprocessbase", "GnuPGProcessBase Test", "0.1" ); + KCmdLineArgs::init( &aboutData ); + KApplication app; + + Kleo::GnuPGProcessBase gpg; + for ( int i = 1 ; i < argc ; ++i ) + gpg << argv[i]; + + gpg.setUseStatusFD( true ); + + GnuPGViewer * gv = new GnuPGViewer(); + gv->setProcess( &gpg ); + + app.setMainWidget( gv ); + gv->show(); + + gpg.start( KProcess::NotifyOnExit, KProcess::AllOutput ); + + return app.exec(); +} + +#include "gnupgviewer.moc" diff --git a/certmanager/lib/tests/test_jobs.cpp b/certmanager/lib/tests/test_jobs.cpp new file mode 100644 index 000000000..22d9136d4 --- /dev/null +++ b/certmanager/lib/tests/test_jobs.cpp @@ -0,0 +1,108 @@ +/* + test_jobs.cpp + + This file is part of libkleopatra's test suite. + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <kleo/cryptobackendfactory.h> +#include <kleo/signjob.h> +#include <kleo/keylistjob.h> + +#include <gpgmepp/key.h> +#include <gpgmepp/signingresult.h> +#include <gpgmepp/keylistresult.h> + +#include <kdebug.h> +#include <assert.h> +#include <kaboutdata.h> +#include <kcmdlineargs.h> +#include <kapplication.h> + +#include <memory> + +static const char * protocol = 0; + +static void testSign() +{ + const Kleo::CryptoBackend::Protocol * proto = protocol == "openpgp" ? Kleo::CryptoBackendFactory::instance()->openpgp() : Kleo::CryptoBackendFactory::instance()->smime() ; + assert( proto ); + + kdDebug() << "Using protocol " << proto->name() << endl; + + + std::vector<GpgME::Key> signingKeys; + + std::auto_ptr<Kleo::KeyListJob> listJob( proto->keyListJob( false, false, true ) ); // use validating keylisting + if ( listJob.get() ) { + // ##### Adjust this to your own identity + listJob->exec( "faure@kde.org", true /*secret*/, signingKeys ); + assert( !signingKeys.empty() ); + } else { + assert( 0 ); // job failed + } + + Kleo::SignJob* job = proto->signJob( true, true ); + + QCString cText = "Hallo Leute\n"; // like gpgme's t-sign.c + QByteArray plainText; + plainText.duplicate( cText.data(), cText.length() ); // hrmpf... + kdDebug() << k_funcinfo << "plainText=" << cText.data() << endl; + + kdDebug() << k_funcinfo << " signing with " << signingKeys[0].primaryFingerprint() << endl; + + QByteArray signature; + const GpgME::SigningResult res = + job->exec( signingKeys, plainText, GpgME::Context::Clearsigned, signature ); + if ( res.error().isCanceled() ) { + kdDebug() << "signing was canceled by user" << endl; + return; + } + if ( res.error() ) { + kdDebug() << "signing failed: " << res.error().asString() << endl; + return; + } + kdDebug() << k_funcinfo << "signing resulted in signature=" + << QCString( signature.data(), signature.size() + 1 ) << endl; +} + +int main( int argc, char** argv ) { + protocol = "openpgp"; + if ( argc == 2 ) { + protocol = argv[1]; + argc = 1; // hide from KDE + } + KAboutData aboutData( "test_jobs", "Signing Job Test", "0.1" ); + KCmdLineArgs::init( argc, argv, &aboutData ); + KApplication app; + + testSign(); +} diff --git a/certmanager/lib/tests/test_keygen.cpp b/certmanager/lib/tests/test_keygen.cpp new file mode 100644 index 000000000..9303b331c --- /dev/null +++ b/certmanager/lib/tests/test_keygen.cpp @@ -0,0 +1,160 @@ +/* + test_keygen.cpp + + This file is part of libkleopatra's test suite. + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "test_keygen.h" + +#include <kleo/keylistjob.h> +#include <kleo/keygenerationjob.h> +#include <kleo/cryptobackendfactory.h> + +#include <ui/progressdialog.h> + +#include <gpgmepp/keygenerationresult.h> + +#include <kapplication.h> +#include <kaboutdata.h> +#include <kcmdlineargs.h> +#include <kmessagebox.h> +#include <kdebug.h> + +#include <qmessagebox.h> +#include <qstringlist.h> +#include <qtimer.h> +#include <qlayout.h> +#include <qlineedit.h> +#include <qlabel.h> + +#include <assert.h> + +static const char * keyParams[] = { + "Key-Type", "Key-Length", + "Subkey-Type", "Subkey-Length", + "Name-Real", "Name-Comment", "Name-Email", "Name-DN", + "Expire-Date", + "Passphrase" +}; +static const int numKeyParams = sizeof keyParams / sizeof *keyParams; + +static const char * protocol = 0; + +KeyGenerator::KeyGenerator( QWidget * parent, const char * name, WFlags ) + : KDialogBase( parent, name, true, "KeyGenerationJob test", + Close|User1, User1, true, KGuiItem( "Create" ) ) +{ + QWidget * w = new QWidget( this ); + setMainWidget( w ); + + QGridLayout * glay = new QGridLayout( w, numKeyParams+3, 2, marginHint(), spacingHint() ); + + int row = -1; + + ++row; + glay->addMultiCellWidget( new QLabel( "<GnupgKeyParms format=\"internal\">", w ), + row, row, 0, 1 ); + for ( int i = 0 ; i < numKeyParams ; ++i ) { + ++row; + glay->addWidget( new QLabel( keyParams[i], w ), row, 0 ); + glay->addWidget( mLineEdits[i] = new QLineEdit( w ), row, 1 ); + } + + ++row; + glay->addMultiCellWidget( new QLabel( "</GnupgKeyParms>", w ), + row, row, 0, 1 ); + ++row; + glay->setRowStretch( row, 1 ); + glay->setColStretch( 1, 1 ); + + connect( this, SIGNAL(user1Clicked()), SLOT(slotStartKeyGeneration()) ); +} + +KeyGenerator::~KeyGenerator() {} + +void KeyGenerator::slotStartKeyGeneration() { + QString params = "<GnupgKeyParms format=\"internal\">\n"; + for ( int i = 0 ; i < numKeyParams ; ++i ) + if ( mLineEdits[i] && !mLineEdits[i]->text().stripWhiteSpace().isEmpty() ) + params += keyParams[i] + ( ": " + mLineEdits[i]->text().stripWhiteSpace() ) + '\n'; + params += "</GnupgKeyParms>\n"; + + const Kleo::CryptoBackend::Protocol * proto = protocol == "openpgp" ? Kleo::CryptoBackendFactory::instance()->openpgp() : Kleo::CryptoBackendFactory::instance()->smime() ; + if ( !proto ) + proto = Kleo::CryptoBackendFactory::instance()->smime(); + assert( proto ); + + kdDebug() << "Using protocol " << proto->name() << endl; + + Kleo::KeyGenerationJob * job = proto->keyGenerationJob(); + assert( job ); + + connect( job, SIGNAL(result(const GpgME::KeyGenerationResult&,const QByteArray&)), + SLOT(slotResult(const GpgME::KeyGenerationResult&,const QByteArray&)) ); + + const GpgME::Error err = job->start( params ); + if ( err ) + showError( err ); + else + (void)new Kleo::ProgressDialog( job, "Generating key", this ); +} + +void KeyGenerator::showError( const GpgME::Error & err ) { + KMessageBox::error( this, "Could not start key generation: " + QString::fromLocal8Bit( err.asString() ), + "Key Generation Error" ); +} + +void KeyGenerator::slotResult( const GpgME::KeyGenerationResult & res, const QByteArray & keyData ) { + if ( res.error() ) + showError( res.error() ); + else + KMessageBox::information( this, QString("Key generated successfully, %1 bytes long").arg( keyData.size() ), + "Key Generation Finished" ); +} + +int main( int argc, char** argv ) { + if ( argc == 2 ) { + protocol = argv[1]; + argc = 1; // hide from KDE + } + KAboutData aboutData( "test_keygen", "KeyGenerationJob Test", "0.1" ); + KCmdLineArgs::init( argc, argv, &aboutData ); + KApplication app; + + KeyGenerator * keygen = new KeyGenerator( 0, "KeyGenerator top-level" ); + app.setMainWidget( keygen ); + keygen->show(); + + return app.exec(); +} + +#include "test_keygen.moc" diff --git a/certmanager/lib/tests/test_keygen.h b/certmanager/lib/tests/test_keygen.h new file mode 100644 index 000000000..0ba713823 --- /dev/null +++ b/certmanager/lib/tests/test_keygen.h @@ -0,0 +1,62 @@ +/* + test_keygen.h + + This file is part of libkleopatra's test suite. + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_TEST_KEYGEN_H__ +#define __KLEO_TEST_KEYGEN_H__ + +#include <kdialogbase.h> + +#include <qcstring.h> + +namespace GpgME { + class Error; + class KeyGenerationResult; +} + +class QLineEdit; + +class KeyGenerator : public KDialogBase { + Q_OBJECT +public: + KeyGenerator( QWidget * parent=0, const char * name=0, WFlags f=0 ); + ~KeyGenerator(); + +public slots: + void slotStartKeyGeneration(); + void slotResult( const GpgME::KeyGenerationResult & res, const QByteArray & keyData ); +private: + void showError( const GpgME::Error & err ); + +private: + QLineEdit * mLineEdits[20]; +}; + +#endif // __KLEO_TEST_KEYGEN_H__ diff --git a/certmanager/lib/tests/test_keylister.cpp b/certmanager/lib/tests/test_keylister.cpp new file mode 100644 index 000000000..9507221e7 --- /dev/null +++ b/certmanager/lib/tests/test_keylister.cpp @@ -0,0 +1,146 @@ +/* + test_keylister.cpp + + This file is part of libkleopatra's test suite. + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include <config.h> + +#include "test_keylister.h" + +#include <kleo/keylistjob.h> +#include <cryptplugwrapper.h> +#include <kleo/cryptobackendfactory.h> + +#include <gpgmepp/keylistresult.h> +#include <gpgmepp/key.h> + +#include <kapplication.h> +#include <kaboutdata.h> +#include <kcmdlineargs.h> +#include <kdebug.h> + +#include <qmessagebox.h> +#include <qstringlist.h> +#include <qtimer.h> + +#include <assert.h> + +namespace { + class TestColumnStrategy : public Kleo::KeyListView::ColumnStrategy { + public: + ~TestColumnStrategy() {} + QString title( int col ) const; + QString toolTip( const GpgME::Key & key, int col ) const; + QString text( const GpgME::Key & key, int col ) const; + }; + + QString TestColumnStrategy::title( int col ) const { + switch ( col ) { + case 0: return "Subject"; + case 1: return "EMail"; + case 2: return "Issuer"; + case 3: return "Serial"; + case 4: return "Protocol"; + case 5: return "Validity"; + default: return QString::null; + } + } + + QString TestColumnStrategy::toolTip( const GpgME::Key & key, int ) const { + return "Fingerprint: " + QString::fromUtf8( key.primaryFingerprint() ); + } + + QString TestColumnStrategy::text( const GpgME::Key & key, int col ) const { + if ( key.isNull() ) + return "<null>"; + switch ( col ) { + case 0: return QString::fromUtf8( key.userID(0).id() ); + case 1: return QString::fromUtf8( key.userID(0).email() ); + case 2: return QString::fromUtf8( key.issuerName() ); + case 3: return key.issuerSerial(); + case 4: return key.protocolAsString(); + case 5: return QChar( key.userID(0).validityAsString() ); + default: return QString::null; + } + } +} + +CertListView::CertListView( QWidget * parent, const char * name, WFlags f ) + : Kleo::KeyListView( new TestColumnStrategy(), 0, parent, name, f ) +{ + setHierarchical( true ); + setRootIsDecorated( true ); +} + +void CertListView::slotResult( const GpgME::KeyListResult & result ) { + kdDebug() << "CertListView::slotResult()" << endl; + if ( result.isNull() ) + QMessageBox::information( this, "Key Listing Result", "KeyListResult is null!" ); + else if ( result.error() ) + QMessageBox::critical( this, "Key Listing Result", + QString("KeyListResult Error: %1").arg( result.error().asString() ) ); + else if ( result.isTruncated() ) + QMessageBox::information( this, "Key Listing Result", "KeyListResult is truncated!" ); + else + QMessageBox::information( this, "Key Listing Result", "Key listing successful" ); +} + +void CertListView::slotStart() { + kdDebug() << "CertListView::slotStart()" << endl; + Kleo::KeyListJob * job = Kleo::CryptoBackendFactory::instance()->smime()->keyListJob( false ); + assert( job ); + QObject::connect( job, SIGNAL(nextKey(const GpgME::Key&)), + this, SLOT(slotAddKey(const GpgME::Key&)) ); + QObject::connect( job, SIGNAL(result(const GpgME::KeyListResult&)), + this, SLOT(slotResult(const GpgME::KeyListResult&)) ); +#if 0 + QStringList l; + l << "Marc"; + job->start( l, false ); +#else + job->start( QStringList(), false ); +#endif +} + +int main( int argc, char** argv ) { + + KAboutData aboutData( "test_keylister", "KeyLister Test", "0.1" ); + KCmdLineArgs::init( argc, argv, &aboutData ); + KApplication app; + + CertListView * clv = new CertListView( 0, "CertListView top-level" ); + app.setMainWidget( clv ); + clv->show(); + + QTimer::singleShot( 5000, clv, SLOT(slotStart()) ); + + return app.exec(); +} + +#include "test_keylister.moc" diff --git a/certmanager/lib/tests/test_keylister.h b/certmanager/lib/tests/test_keylister.h new file mode 100644 index 000000000..348ec262f --- /dev/null +++ b/certmanager/lib/tests/test_keylister.h @@ -0,0 +1,52 @@ +/* + test_keylister.h + + This file is part of libkleopatra's test suite. + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_TEST_KEYLISTER_H__ +#define __KLEO_TEST_KEYLISTER_H__ + +#include <ui/keylistview.h> + +namespace GpgME { + class Key; + class KeyListResult; +} + +class CertListView : public Kleo::KeyListView { + Q_OBJECT +public: + CertListView( QWidget * parent=0, const char * name=0, WFlags f=0 ); + +public slots: + void slotResult( const GpgME::KeyListResult & result ); + void slotStart(); +}; + +#endif // __KLEO_TEST_KEYLISTER_H__ diff --git a/certmanager/lib/tests/test_keyselectiondialog.cpp b/certmanager/lib/tests/test_keyselectiondialog.cpp new file mode 100644 index 000000000..e6c85fca0 --- /dev/null +++ b/certmanager/lib/tests/test_keyselectiondialog.cpp @@ -0,0 +1,67 @@ +/* + test_keygen.cpp + + This file is part of libkleopatra's test suite. + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include <config.h> + +#include <ui/keyselectiondialog.h> +#include <gpgmepp/key.h> + +#include <kapplication.h> +#include <kcmdlineargs.h> +#include <kaboutdata.h> +#include <kglobal.h> +#include <kiconloader.h> +#include <kdebug.h> + +#include <vector> + +int main( int argc, char ** argv ) { + KAboutData aboutData( "test_keyselectiondialog", "KeySelectionDialog Test", "0.1" ); + KCmdLineArgs::init( argc, argv, &aboutData ); + KApplication app; + + KGlobal::iconLoader()->addAppDir( "libkleopatra" ); + + Kleo::KeySelectionDialog dlg( "Kleo::KeySelectionDialog Test", + "Please select a key:", + std::vector<GpgME::Key>(), + Kleo::KeySelectionDialog::AllKeys, true, true ); + + if ( dlg.exec() == QDialog::Accepted ) { + kdDebug() << "accepted; selected key: " << (dlg.selectedKey().userID(0).id() ? dlg.selectedKey().userID(0).id() : "<null>") << "\nselected _keys_:" << endl; + for ( std::vector<GpgME::Key>::const_iterator it = dlg.selectedKeys().begin() ; it != dlg.selectedKeys().end() ; ++it ) + kdDebug() << (it->userID(0).id() ? it->userID(0).id() : "<null>") << endl; + } else { + kdDebug() << "rejected" << endl; + } + + return 0; +} diff --git a/certmanager/lib/tests/test_verify.cpp b/certmanager/lib/tests/test_verify.cpp new file mode 100644 index 000000000..a81e50466 --- /dev/null +++ b/certmanager/lib/tests/test_verify.cpp @@ -0,0 +1,99 @@ +/* + This file is part of Kleopatra's test suite. + Copyright (c) 2007 Klarälvdalens Datakonsult AB + + Kleopatra is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + Kleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include <config.h> + +#include <kleo/cryptobackendfactory.h> +#include <kleo/verifydetachedjob.h> +#include <kleo/verifyopaquejob.h> + +#include <gpgmepp/verificationresult.h> +#include <gpgmepp/key.h> + +#include <kaboutdata.h> +#include <kapplication.h> +#include <kcmdlineargs.h> + +#include <qdir.h> +#include <qfile.h> + +#include <assert.h> + +int main( int argc, char **argv ) +{ + setenv("GNUPGHOME", KDESRCDIR "/gnupg_home", 1 ); + setenv("LC_ALL", "C", 1); + setenv("KDEHOME", QFile::encodeName( QDir::homeDirPath() + "/.kde-unit-test" ), 1); + + KAboutData aboutData( "test_verify", "verify job test", "0.1" ); + KCmdLineArgs::init( argc, argv, &aboutData ); + KApplication app( false, false ); + + const QString sigFileName = KDESRCDIR "/test.data.sig"; + const QString dataFileName = KDESRCDIR "/test.data"; + + QFile sigFile( sigFileName ); + assert( sigFile.open( IO_ReadOnly ) ); + QFile dataFile( dataFileName ); + assert( dataFile.open( IO_ReadOnly ) ); + + const Kleo::CryptoBackend::Protocol * const backend = Kleo::CryptoBackendFactory::instance()->protocol( "openpgp" ); + + Kleo::VerifyDetachedJob *job = backend->verifyDetachedJob(); + GpgME::VerificationResult result = job->exec( sigFile.readAll(), dataFile.readAll() ); + assert( !result.error() ); + assert( result.signatures().size() == 1 ); + + GpgME::Signature sig = result.signature( 0 ); + assert( (sig.summary() & GpgME::Signature::KeyMissing) == 0 ); + assert( sig.creationTime() == 1189650248L ); + assert( sig.validity() == GpgME::Signature::Full ); + + const QString opaqueFileName = KDESRCDIR "/test.data.gpg"; + QFile opaqueFile( opaqueFileName ); + assert( opaqueFile.open( IO_ReadOnly ) ); + QByteArray clearText; + + Kleo::VerifyOpaqueJob *job2 = backend->verifyOpaqueJob(); + result = job2->exec( opaqueFile.readAll(), clearText ); + assert( !result.error() ); + assert( result.signatures().size() == 1 ); + + sig = result.signature( 0 ); + assert( (sig.summary() & GpgME::Signature::KeyMissing) == 0 ); + assert( (sig.summary() & GpgME::Signature::Green ) ); + assert( sig.creationTime() > 0 ); + assert( sig.validity() == GpgME::Signature::Full ); + + dataFile.reset(); + assert( clearText == dataFile.readAll() ); + + return 0; +} diff --git a/certmanager/lib/ui/Makefile.am b/certmanager/lib/ui/Makefile.am new file mode 100644 index 000000000..f381fb64d --- /dev/null +++ b/certmanager/lib/ui/Makefile.am @@ -0,0 +1,42 @@ + +INCLUDES = -I$(top_srcdir)/libkdenetwork \ + -I$(top_srcdir)/libkpgp \ + -I$(top_srcdir)/certmanager/lib \ + $(GPGME_CFLAGS) $(all_includes) + +noinst_LTLIBRARIES = libkleopatra_ui.la + +libkleopatra_ui_la_SOURCES = \ + kdhorizontalline.cpp \ + messagebox.cpp \ + progressbar.cpp \ + progressdialog.cpp \ + keylistview.cpp \ + keyselectiondialog.cpp \ + keyrequester.cpp \ + passphrasedialog.cpp \ + keyapprovaldialog.cpp \ + backendconfigwidget.cpp \ + dnattributeorderconfigwidget.cpp \ + cryptoconfigmodule.cpp \ + cryptoconfigdialog.cpp \ + directoryserviceswidgetbase.ui \ + directoryserviceswidget.cpp \ + adddirectoryservicedialog.ui \ + adddirectoryservicedialogimpl.cpp + +kleodir = $(includedir)/kleo +kleo_HEADERS = \ + kdhorizontalline.h \ + messagebox.h \ + progressbar.h \ + progressdialog.h \ + keylistview.h \ + keyselectiondialog.h \ + keyrequester.h \ + passphrasedialog.h \ + keyapprovaldialog.h \ + backendconfigwidget.h \ + dnattributeorderconfigwidget.h + +METASOURCES = AUTO diff --git a/certmanager/lib/ui/adddirectoryservicedialog.ui b/certmanager/lib/ui/adddirectoryservicedialog.ui new file mode 100644 index 000000000..98e171887 --- /dev/null +++ b/certmanager/lib/ui/adddirectoryservicedialog.ui @@ -0,0 +1,207 @@ +<!DOCTYPE UI><UI version="3.2" stdsetdef="1"> +<class>AddDirectoryServiceDialog</class> +<widget class="QDialog"> + <property name="name"> + <cstring>AddDirectoryServiceDialog</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>389</width> + <height>257</height> + </rect> + </property> + <property name="caption"> + <string>Add or Change Directory Service</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>serverNameLA</cstring> + </property> + <property name="text"> + <string>&Server name:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>serverNameED</cstring> + </property> + </widget> + <widget class="QLineEdit" row="2" column="1" rowspan="1" colspan="3"> + <property name="name"> + <cstring>descriptionED</cstring> + </property> + </widget> + <widget class="QLineEdit" row="1" column="1" rowspan="1" colspan="3"> + <property name="name"> + <cstring>portED</cstring> + </property> + <property name="text"> + <string>389</string> + </property> + </widget> + <widget class="QLineEdit" row="0" column="1" rowspan="1" colspan="3"> + <property name="name"> + <cstring>serverNameED</cstring> + </property> + </widget> + <widget class="QLabel" row="3" column="0"> + <property name="name"> + <cstring>usernameLA</cstring> + </property> + <property name="text"> + <string>&User name (optional):</string> + </property> + <property name="buddy" stdset="0"> + <cstring>usernameED</cstring> + </property> + </widget> + <spacer row="5" column="3"> + <property name="name"> + <cstring>spacer23</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>60</height> + </size> + </property> + </spacer> + <widget class="QLabel" row="4" column="0"> + <property name="name"> + <cstring>passwordLA</cstring> + </property> + <property name="text"> + <string>Pass&word (optional):</string> + </property> + <property name="buddy" stdset="0"> + <cstring>passwordED</cstring> + </property> + </widget> + <widget class="QPushButton" row="8" column="2"> + <property name="name"> + <cstring>PushButton3</cstring> + </property> + <property name="text"> + <string>&OK</string> + </property> + <property name="default"> + <bool>true</bool> + </property> + </widget> + <widget class="QPushButton" row="8" column="3"> + <property name="name"> + <cstring>PushButton4</cstring> + </property> + <property name="text"> + <string>&Cancel</string> + </property> + </widget> + <widget class="Line" row="6" column="0" rowspan="1" colspan="4"> + <property name="name"> + <cstring>line1</cstring> + </property> + <property name="frameShape"> + <enum>HLine</enum> + </property> + <property name="frameShadow"> + <enum>Sunken</enum> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + </widget> + <spacer row="7" column="0" rowspan="2" colspan="2"> + <property name="name"> + <cstring>spacer21</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>260</width> + <height>21</height> + </size> + </property> + </spacer> + <widget class="QLineEdit" row="3" column="1" rowspan="1" colspan="3"> + <property name="name"> + <cstring>usernameED</cstring> + </property> + </widget> + <widget class="QLineEdit" row="4" column="1" rowspan="1" colspan="3"> + <property name="name"> + <cstring>passwordED</cstring> + </property> + <property name="echoMode"> + <enum>Password</enum> + </property> + </widget> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>descriptionLA</cstring> + </property> + <property name="text"> + <string>&Base DN:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>descriptionED</cstring> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>portLA</cstring> + </property> + <property name="text"> + <string>&Port:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>portED</cstring> + </property> + </widget> + </grid> +</widget> +<connections> + <connection> + <sender>PushButton3</sender> + <signal>clicked()</signal> + <receiver>AddDirectoryServiceDialog</receiver> + <slot>accept()</slot> + </connection> + <connection> + <sender>PushButton4</sender> + <signal>clicked()</signal> + <receiver>AddDirectoryServiceDialog</receiver> + <slot>reject()</slot> + </connection> +</connections> +<tabstops> + <tabstop>serverNameED</tabstop> + <tabstop>portED</tabstop> + <tabstop>descriptionED</tabstop> + <tabstop>usernameED</tabstop> + <tabstop>passwordED</tabstop> + <tabstop>PushButton3</tabstop> + <tabstop>PushButton4</tabstop> +</tabstops> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/certmanager/lib/ui/adddirectoryservicedialogimpl.cpp b/certmanager/lib/ui/adddirectoryservicedialogimpl.cpp new file mode 100644 index 000000000..973266b16 --- /dev/null +++ b/certmanager/lib/ui/adddirectoryservicedialogimpl.cpp @@ -0,0 +1,63 @@ +/* + adddirectoryservicedialogimpl.cpp + + This file is part of Kleopatra, the KDE keymanager + Copyright (c) 2001,2002,2004 Klarälvdalens Datakonsult AB + + Kleopatra is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + Kleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "adddirectoryservicedialogimpl.h" + +#include <qvalidator.h> +#include <klineedit.h> + +/* + * Constructs a AddDirectoryServiceDialogImpl which is a child of 'parent', with the + * name 'name' and widget flags set to 'f' + * + * The dialog will by default be modeless, unless you set 'modal' to + * TRUE to construct a modal dialog. + */ +AddDirectoryServiceDialogImpl::AddDirectoryServiceDialogImpl( QWidget* parent, const char* name, bool modal, WFlags fl ) + : AddDirectoryServiceDialog( parent, name, modal, fl ) +{ + portED->setValidator( new QIntValidator( 0, 65535, portED ) ); +} + +/* + * Destroys the object and frees any allocated resources + */ +AddDirectoryServiceDialogImpl::~AddDirectoryServiceDialogImpl() +{ + // no need to delete child widgets, Qt does it all for us +} + +#include "adddirectoryservicedialogimpl.moc" diff --git a/certmanager/lib/ui/adddirectoryservicedialogimpl.h b/certmanager/lib/ui/adddirectoryservicedialogimpl.h new file mode 100644 index 000000000..deee06439 --- /dev/null +++ b/certmanager/lib/ui/adddirectoryservicedialogimpl.h @@ -0,0 +1,47 @@ +/* + adddirectoryservicedialogimpl.h + + This file is part of Kleopatra, the KDE keymanager + Copyright (c) 2001,2002,2004 Klarälvdalens Datakonsult AB + + Kleopatra is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + Kleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef ADDDIRECTORYSERVICEDIALOGIMPL_H +#define ADDDIRECTORYSERVICEDIALOGIMPL_H +#include "adddirectoryservicedialog.h" + +class AddDirectoryServiceDialogImpl : public AddDirectoryServiceDialog +{ + Q_OBJECT + +public: + AddDirectoryServiceDialogImpl( QWidget* parent = 0, const char* name = 0, bool modal = FALSE, WFlags fl = 0 ); + ~AddDirectoryServiceDialogImpl(); + +}; + +#endif // ADDDIRECTORYSERVICEDIALOGIMPL_H diff --git a/certmanager/lib/ui/backendconfigwidget.cpp b/certmanager/lib/ui/backendconfigwidget.cpp new file mode 100644 index 000000000..c40890a43 --- /dev/null +++ b/certmanager/lib/ui/backendconfigwidget.cpp @@ -0,0 +1,323 @@ +/* -*- c++ -*- + backendconfigwidget.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2002,2004,2005 Klarälvdalens Datakonsult AB + Copyright (c) 2002,2003 Marc Mutz <mutz@kde.org> + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "backendconfigwidget.h" +#include "cryptoconfigdialog.h" + +#include "kleo/cryptobackendfactory.h" +#include "ui/keylistview.h" // for lvi_cast<> + +#include <klistview.h> +#include <kdialog.h> +#include <klocale.h> +#include <kdebug.h> +#include <kmessagebox.h> +#include <kapplication.h> +#include <dcopclient.h> + +#include <qpushbutton.h> +#include <qlayout.h> +#include <qheader.h> +#include <qtimer.h> + +#include <assert.h> + +namespace Kleo { + class BackendListView; +} + +class Kleo::BackendConfigWidget::Private { +public: + Kleo::BackendListView * listView; + QPushButton * configureButton; + QPushButton * rescanButton; + Kleo::CryptoBackendFactory * backendFactory; +}; + +namespace Kleo { + class BackendListViewItem; + class ProtocolCheckListItem; +} + +class Kleo::BackendListView : public KListView +{ +public: + BackendListView( BackendConfigWidget* parent, const char* name = 0 ) + : KListView( parent, name ) {} + + /// return backend for currently selected (/current) item. Used by Configure button. + const Kleo::CryptoBackend* currentBackend() const; + + /// return which protocol implementation was chosen (checked) for each type (used when saving) + const Kleo::CryptoBackend* chosenBackend( const char * protocol ); + + /// deselect all except one for a given protocol type (radiobutton-like exclusivity) + void deselectAll( const char * protocol, QCheckListItem* except ); + + void emitChanged() { static_cast<BackendConfigWidget *>( parentWidget() )->emitChanged( true ); } +}; + +// Toplevel listviewitem for a given backend (e.g. "GpgME", "Kgpg/gpg v2") +class Kleo::BackendListViewItem : public QListViewItem +{ +public: + BackendListViewItem( KListView* lv, QListViewItem *prev, const CryptoBackend *cryptoBackend ) + : QListViewItem( lv, prev, cryptoBackend->displayName() ), mCryptoBackend( cryptoBackend ) + {} + + const CryptoBackend *cryptoBackend() const { return mCryptoBackend; } + enum { RTTI = 0x2EAE3BE0, RTTI_MASK = 0xFFFFFFFF }; + int rtti() const { return RTTI; } + +private: + const CryptoBackend *mCryptoBackend; +}; + + +// Checklist item under a BackendListViewItem +// (e.g. "GpgME supports protocol OpenPGP") +class Kleo::ProtocolCheckListItem : public QCheckListItem +{ +public: + ProtocolCheckListItem( BackendListViewItem* blvi, + QListViewItem* prev, const char * protocolName, + const CryptoBackend::Protocol* protocol ) // can be 0 + : QCheckListItem( blvi, prev, itemText( protocolName, protocol ), + QCheckListItem::CheckBox ), + mProtocol( protocol ), mProtocolName( protocolName ) + {} + + enum { RTTI = 0x2EAE3BE1, RTTI_MASK = 0xFFFFFFFF }; + virtual int rtti() const { return RTTI; } + + // can be 0 + const CryptoBackend::Protocol* protocol() const { return mProtocol; } + const char * protocolName() const { return mProtocolName; } + +protected: + virtual void stateChange( bool b ) { + BackendListView* lv = static_cast<BackendListView *>( listView() ); + // "radio-button-like" behavior for the protocol checkboxes + if ( b ) + lv->deselectAll( mProtocolName, this ); + lv->emitChanged(); + QCheckListItem::stateChange( b ); + } + +private: + // Helper for the constructor. + static QString itemText( const char * protocolName, const CryptoBackend::Protocol* protocol ) { + // First one is the generic name (find a nice one for OpenPGP, SMIME) + const QString protoName = qstricmp( protocolName, "openpgp" ) != 0 + ? qstricmp( protocolName, "smime" ) != 0 + ? QString::fromLatin1( protocolName ) + : i18n( "S/MIME" ) + : i18n( "OpenPGP" ); + // second one is implementation name (gpg, gpgsm...) + const QString impName = protocol ? protocol->displayName() : i18n( "failed" ); + return i18n( "Items in Kleo::BackendConfigWidget listview (1: protocol; 2: implementation name)", + "%1 (%2)" ).arg( protoName, impName ); + } + + const CryptoBackend::Protocol* mProtocol; // can be 0 + const char * mProtocolName; +}; + +const Kleo::CryptoBackend* Kleo::BackendListView::currentBackend() const { + const QListViewItem* curItem = currentItem(); + if ( !curItem ) // can't happen + return 0; + if ( lvi_cast<Kleo::ProtocolCheckListItem>( curItem ) ) + curItem = curItem->parent(); + if ( const Kleo::BackendListViewItem * blvi = lvi_cast<Kleo::BackendListViewItem>( curItem ) ) + return blvi->cryptoBackend(); + return 0; +} + +// can't be const method due to QListViewItemIterator (why?) +const Kleo::CryptoBackend* Kleo::BackendListView::chosenBackend( const char * protocolName ) +{ + for ( QListViewItemIterator it( this /*, QListViewItemIterator::Checked doesn't work*/ ) ; + it.current() ; ++it ) + if ( ProtocolCheckListItem * p = lvi_cast<ProtocolCheckListItem>( it.current() ) ) + if ( p->isOn() && qstricmp( p->protocolName(), protocolName ) == 0 ) { + // OK that's the one. Now go up to the parent backend + // (need to do that in the listview since Protocol doesn't know it) + if ( const BackendListViewItem * parItem = lvi_cast<BackendListViewItem>( it.current()->parent() ) ) + return parItem->cryptoBackend(); + } + return 0; +} + +void Kleo::BackendListView::deselectAll( const char * protocolName, QCheckListItem* except ) +{ + for ( QListViewItemIterator it( this /*, QListViewItemIterator::Checked doesn't work*/ ) ; + it.current() ; ++it ) { + if ( it.current() == except ) continue; + if ( ProtocolCheckListItem * p = lvi_cast<ProtocolCheckListItem>( it.current() ) ) + if ( p->isOn() && qstricmp( p->protocolName(), protocolName ) == 0 ) + p->setOn( false ); + } +} + +//// + +Kleo::BackendConfigWidget::BackendConfigWidget( CryptoBackendFactory * factory, QWidget * parent, const char * name, WFlags f ) + : QWidget( parent, name, f ), d( 0 ) +{ + assert( factory ); + d = new Private(); + d->backendFactory = factory; + + QHBoxLayout * hlay = + new QHBoxLayout( this, 0, KDialog::spacingHint() ); + + d->listView = new BackendListView( this, "d->listView" ); + d->listView->addColumn( i18n("Available Backends") ); + d->listView->setAllColumnsShowFocus( true ); + d->listView->setSorting( -1 ); + d->listView->header()->setClickEnabled( false ); + d->listView->setFullWidth( true ); + + hlay->addWidget( d->listView, 1 ); + + connect( d->listView, SIGNAL(selectionChanged(QListViewItem*)), + SLOT(slotSelectionChanged(QListViewItem*)) ); + + QVBoxLayout * vlay = new QVBoxLayout( hlay ); // inherits spacing + + d->configureButton = new QPushButton( i18n("Confi&gure..."), this ); + d->configureButton->setAutoDefault( false ); + vlay->addWidget( d->configureButton ); + + connect( d->configureButton, SIGNAL(clicked()), + SLOT(slotConfigureButtonClicked()) ); + + d->rescanButton = new QPushButton( i18n("Rescan"), this ); + d->rescanButton->setAutoDefault( false ); + vlay->addWidget( d->rescanButton ); + + connect( d->rescanButton, SIGNAL(clicked()), + SLOT(slotRescanButtonClicked()) ); + + vlay->addStretch( 1 ); +} + +Kleo::BackendConfigWidget::~BackendConfigWidget() { + delete d; d = 0; +} + +void Kleo::BackendConfigWidget::load() { + d->listView->clear(); + + unsigned int backendCount = 0; + + // populate the plugin list: + BackendListViewItem * top = 0; + for ( unsigned int i = 0 ; const CryptoBackend * b = d->backendFactory->backend( i ) ; ++i ) { + + top = new Kleo::BackendListViewItem( d->listView, top, b ); + + ProtocolCheckListItem * last = 0; + for ( int i = 0 ; const char * name = b->enumerateProtocols( i ) ; ++i ) { + const CryptoBackend::Protocol * protocol = b->protocol( name ); + + if ( protocol ) { + last = new ProtocolCheckListItem( top, last, name, protocol ); + last->setOn( protocol == d->backendFactory->protocol( name ) ); + } else if ( b->supportsProtocol( name ) ) { + last = new ProtocolCheckListItem( top, last, name, 0 ); + last->setOn( false ); + last->setEnabled( false ); + } + } + + top->setOpen( true ); + ++backendCount; + } + + if ( backendCount ) { + d->listView->setCurrentItem( d->listView->firstChild() ); + d->listView->setSelected( d->listView->firstChild(), true ); + } + + slotSelectionChanged( d->listView->firstChild() ); +} + +void Kleo::BackendConfigWidget::slotSelectionChanged( QListViewItem * ) { + const CryptoBackend* backend = d->listView->currentBackend(); + if ( backend && !backend->config() ) + kdDebug(5150) << "Backend w/o config object!" << endl; + d->configureButton->setEnabled( backend && backend->config() ); +} + + +void Kleo::BackendConfigWidget::slotRescanButtonClicked() { + QStringList reasons; + d->backendFactory->scanForBackends( &reasons ); + if ( !reasons.empty() ) + KMessageBox::informationList( this, + i18n("The following problems where encountered during scanning:"), + reasons, i18n("Scan Results") ); + load(); + emit changed( true ); +} + +void Kleo::BackendConfigWidget::slotConfigureButtonClicked() { + const CryptoBackend* backend = d->listView->currentBackend(); + if ( backend && backend->config() ) { + Kleo::CryptoConfigDialog dlg( backend->config(), this ); + int result = dlg.exec(); + if ( result == QDialog::Accepted ) { + // Tell other users of gpgconf (e.g. the s/mime page) that the gpgconf data might have changed + kapp->dcopClient()->emitDCOPSignal( "KPIM::CryptoConfig", "changed()", QByteArray() ); + // and schedule a rescan, in case the updates make a backend valid + QTimer::singleShot( 0, this, SLOT(slotRescanButtonClicked()) ); + } + } + else // shouldn't happen, button is disabled + kdWarning(5150) << "Can't configure backend, no config object available" << endl; +} + +void Kleo::BackendConfigWidget::save() const { + for ( int i = 0 ; const char * name = d->backendFactory->enumerateProtocols( i ) ; ++i ) + d->backendFactory->setProtocolBackend( name, d->listView->chosenBackend( name ) ); +} + +void Kleo::BackendConfigWidget::virtual_hook( int, void* ) {} + +#include "backendconfigwidget.moc" diff --git a/certmanager/lib/ui/backendconfigwidget.h b/certmanager/lib/ui/backendconfigwidget.h new file mode 100644 index 000000000..0e26655ce --- /dev/null +++ b/certmanager/lib/ui/backendconfigwidget.h @@ -0,0 +1,76 @@ +/* -*- c++ -*- + backendconfigwidget.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2002,2004 Klarälvdalens Datakonsult AB + Copyright (c) 2002,2003 Marc Mutz <mutz@kde.org> + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. + */ + +#ifndef __KLEO_UI_BACKENDCONFIGWIDGET_H__ +#define __KLEO_UI_BACKENDCONFIGWIDGET_H__ + +#include <qwidget.h> +#include <kdepimmacros.h> + +namespace Kleo { + class CryptoBackendFactory; +} + +class QListViewItem; + +namespace Kleo { + + class KDE_EXPORT BackendConfigWidget : public QWidget { + Q_OBJECT + public: + BackendConfigWidget( CryptoBackendFactory * factory, QWidget * parent=0, const char * name=0, WFlags f=0 ); + ~BackendConfigWidget(); + + void load(); + void save() const; + + void emitChanged( bool b ) { emit changed( b ); } + + signals: + void changed( bool ); + + private slots: + void slotSelectionChanged( QListViewItem * ); + void slotRescanButtonClicked(); + void slotConfigureButtonClicked(); + + private: + class Private; + Private * d; + protected: + virtual void virtual_hook( int, void* ); + }; + +} + +#endif // __KLEO_UI_BACKENDCONFIGWIDGET_H__ diff --git a/certmanager/lib/ui/cryptoconfigdialog.cpp b/certmanager/lib/ui/cryptoconfigdialog.cpp new file mode 100644 index 000000000..3fa0a97ca --- /dev/null +++ b/certmanager/lib/ui/cryptoconfigdialog.cpp @@ -0,0 +1,89 @@ +/* + cryptoconfigdialog.h + + This file is part of kgpgcertmanager + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "cryptoconfigdialog.h" +#include "cryptoconfigmodule.h" +#include <klocale.h> +#include <kaccelmanager.h> + +Kleo::CryptoConfigDialog::CryptoConfigDialog( Kleo::CryptoConfig* config, QWidget *parent, const char* name ) + : KDialogBase( Swallow, + // Remove the "whats's this" button since we have no support for it + WStyle_Customize | WStyle_DialogBorder | WStyle_Maximize | WStyle_Title | WStyle_SysMenu, + parent, name, true /*modal*/, + i18n( "Configure" ), Default|Cancel|Apply|Ok|User1, + Ok, true /*separator*/, KGuiItem( i18n( "&Reset" ), "undo" ) ) +{ + mMainWidget = new CryptoConfigModule( config, this ); + setMainWidget( mMainWidget ); + connect( mMainWidget, SIGNAL( changed() ), SLOT( slotChanged() ) ); + enableButton( Apply, false ); + + // Automatically assign accelerators + KAcceleratorManager::manage( this ); +} + +void Kleo::CryptoConfigDialog::slotOk() +{ + slotApply(); + accept(); +} + +void Kleo::CryptoConfigDialog::slotCancel() +{ + mMainWidget->cancel(); + reject(); +} + +void Kleo::CryptoConfigDialog::slotDefault() +{ + mMainWidget->defaults(); + slotChanged(); +} + +void Kleo::CryptoConfigDialog::slotApply() +{ + mMainWidget->save(); + enableButton( Apply, false ); +} + +void Kleo::CryptoConfigDialog::slotUser1() // reset +{ + mMainWidget->reset(); + enableButton( Apply, false ); +} + +void Kleo::CryptoConfigDialog::slotChanged() +{ + enableButton( Apply, true ); +} + +#include "cryptoconfigdialog.moc" diff --git a/certmanager/lib/ui/cryptoconfigdialog.h b/certmanager/lib/ui/cryptoconfigdialog.h new file mode 100644 index 000000000..484c55ea4 --- /dev/null +++ b/certmanager/lib/ui/cryptoconfigdialog.h @@ -0,0 +1,69 @@ +/* + cryptoconfigdialog.h + + This file is part of kgpgcertmanager + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef CRYPTOCONFIGDIALOG_H +#define CRYPTOCONFIGDIALOG_H + +#include <kdialogbase.h> +#include <kdepimmacros.h> + +namespace Kleo { + + class CryptoConfig; + class CryptoConfigModule; + + /** + * Simple KDialogBase wrapper around CryptoConfigModule + */ + class KDE_EXPORT CryptoConfigDialog : public KDialogBase + { + Q_OBJECT + public: + CryptoConfigDialog( Kleo::CryptoConfig* config, QWidget *parent = 0, const char* name = 0 ); + + protected: + virtual void slotOk(); + virtual void slotCancel(); + virtual void slotDefault(); + virtual void slotApply(); + virtual void slotUser1(); // reset + + public slots: + void slotChanged(); + + private: + CryptoConfigModule* mMainWidget; + }; + +} + +#endif /* CRYPTOCONFIGDIALOG_H */ + diff --git a/certmanager/lib/ui/cryptoconfigmodule.cpp b/certmanager/lib/ui/cryptoconfigmodule.cpp new file mode 100644 index 000000000..dbc8edc57 --- /dev/null +++ b/certmanager/lib/ui/cryptoconfigmodule.cpp @@ -0,0 +1,634 @@ +/* + cryptoconfigmodule.cpp + + This file is part of kgpgcertmanager + Copyright (c) 2004 Klar�vdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "cryptoconfigmodule.h" +#include "cryptoconfigmodule_p.h" +#include "directoryserviceswidget.h" +#include "kdhorizontalline.h" + +#include <kleo/cryptoconfig.h> + +#include <klineedit.h> +#include <klocale.h> +#include <kdialogbase.h> +#include <kdebug.h> +#include <knuminput.h> +#include <kiconloader.h> +#include <kglobal.h> +#include <kurlrequester.h> + +#include <qgrid.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qvbox.h> +#include <qhbox.h> +#include <qpushbutton.h> +#include <qregexp.h> +#include <qstyle.h> +#include <qapplication.h> + +using namespace Kleo; + +static inline QPixmap loadIcon( QString s ) { + return KGlobal::instance()->iconLoader() + ->loadIcon( s.replace( QRegExp( "[^a-zA-Z0-9_]" ), "_" ), KIcon::NoGroup, KIcon::SizeMedium ); +} + +static const KJanusWidget::Face determineJanusFace( const Kleo::CryptoConfig * config ) { + return config && config->componentList().size() < 2 + ? KJanusWidget::Plain + : KJanusWidget::IconList ; +} + +Kleo::CryptoConfigModule::CryptoConfigModule( Kleo::CryptoConfig* config, QWidget * parent, const char * name ) + : KJanusWidget( parent, name, determineJanusFace( config ) ), mConfig( config ) +{ + QWidget * vbox = 0; + if ( face() == Plain ) { + vbox = plainPage(); + QVBoxLayout * vlay = new QVBoxLayout( vbox, 0, KDialog::spacingHint() ); + vlay->setAutoAdd( true ); + } + + const QStringList components = config->componentList(); + for ( QStringList::const_iterator it = components.begin(); it != components.end(); ++it ) { + //kdDebug(5150) << "Component " << (*it).local8Bit() << ":" << endl; + Kleo::CryptoConfigComponent* comp = config->component( *it ); + Q_ASSERT( comp ); + if ( comp->groupList().empty() ) + continue; + if ( face() != Plain ) { + vbox = addVBoxPage( comp->description(), QString::null, loadIcon( comp->iconName() ) ); + } + + QScrollView * scrollView = new QScrollView( vbox ); + scrollView->setHScrollBarMode( QScrollView::AlwaysOff ); + scrollView->setResizePolicy( QScrollView::AutoOneFit ); + QVBox* boxInScrollView = new QVBox( scrollView->viewport() ); + boxInScrollView->setMargin( KDialog::marginHint() ); + scrollView->addChild( boxInScrollView ); + + CryptoConfigComponentGUI* compGUI = + new CryptoConfigComponentGUI( this, comp, boxInScrollView, (*it).local8Bit() ); + // KJanusWidget doesn't seem to have iterators, so we store a copy... + mComponentGUIs.append( compGUI ); + + // Set a nice startup size + const int deskHeight = QApplication::desktop()->height(); + int dialogHeight; + if (deskHeight > 1000) // very big desktop ? + dialogHeight = 800; + else if (deskHeight > 650) // big desktop ? + dialogHeight = 500; + else // small (800x600, 640x480) desktop + dialogHeight = 400; + QSize sz = scrollView->sizeHint(); + scrollView->setMinimumSize( sz.width() + + scrollView->style().pixelMetric(QStyle::PM_ScrollBarExtent), + QMIN( compGUI->sizeHint().height(), dialogHeight ) ); + } +} + +void Kleo::CryptoConfigModule::save() +{ + bool changed = false; + QValueList<CryptoConfigComponentGUI *>::Iterator it = mComponentGUIs.begin(); + for( ; it != mComponentGUIs.end(); ++it ) { + if ( (*it)->save() ) + changed = true; + } + if ( changed ) + mConfig->sync(true /*runtime*/); +} + +void Kleo::CryptoConfigModule::reset() +{ + QValueList<CryptoConfigComponentGUI *>::Iterator it = mComponentGUIs.begin(); + for( ; it != mComponentGUIs.end(); ++it ) { + (*it)->load(); + } +} + +void Kleo::CryptoConfigModule::defaults() +{ + QValueList<CryptoConfigComponentGUI *>::Iterator it = mComponentGUIs.begin(); + for( ; it != mComponentGUIs.end(); ++it ) { + (*it)->defaults(); + } +} + +void Kleo::CryptoConfigModule::cancel() +{ + mConfig->clear(); +} + +//// + +Kleo::CryptoConfigComponentGUI::CryptoConfigComponentGUI( + CryptoConfigModule* module, Kleo::CryptoConfigComponent* component, + QWidget* parent, const char* name ) + : QWidget( parent, name ), + mComponent( component ) +{ + QGridLayout * glay = new QGridLayout( this, 1, 3, 0, KDialog::spacingHint() ); + const QStringList groups = mComponent->groupList(); + if ( groups.size() > 1 ) { + glay->setColSpacing( 0, KDHorizontalLine::indentHint() ); + for ( QStringList::const_iterator it = groups.begin(), end = groups.end() ; it != end; ++it ) { + Kleo::CryptoConfigGroup* group = mComponent->group( *it ); + Q_ASSERT( group ); + if ( !group ) + continue; + KDHorizontalLine * hl = new KDHorizontalLine( group->description(), this ); + const int row = glay->numRows(); + glay->addMultiCellWidget( hl, row, row, 0, 2 ); + mGroupGUIs.append( new CryptoConfigGroupGUI( module, group, glay, this ) ); + } + } else if ( !groups.empty() ) { + mGroupGUIs.append( new CryptoConfigGroupGUI( module, mComponent->group( groups.front() ), glay, this ) ); + } + glay->setRowStretch( glay->numRows(), 1 ); +} + + +bool Kleo::CryptoConfigComponentGUI::save() +{ + bool changed = false; + QValueList<CryptoConfigGroupGUI *>::Iterator it = mGroupGUIs.begin(); + for( ; it != mGroupGUIs.end(); ++it ) { + if ( (*it)->save() ) + changed = true; + } + return changed; +} + +void Kleo::CryptoConfigComponentGUI::load() +{ + QValueList<CryptoConfigGroupGUI *>::Iterator it = mGroupGUIs.begin(); + for( ; it != mGroupGUIs.end(); ++it ) + (*it)->load(); +} + +void Kleo::CryptoConfigComponentGUI::defaults() +{ + QValueList<CryptoConfigGroupGUI *>::Iterator it = mGroupGUIs.begin(); + for( ; it != mGroupGUIs.end(); ++it ) + (*it)->defaults(); +} + +//// + +Kleo::CryptoConfigGroupGUI::CryptoConfigGroupGUI( + CryptoConfigModule* module, Kleo::CryptoConfigGroup* group, + QGridLayout * glay, QWidget* widget, const char* name ) + : QObject( module, name ), mGroup( group ) +{ + const int startRow = glay->numRows(); + const QStringList entries = mGroup->entryList(); + for( QStringList::const_iterator it = entries.begin(), end = entries.end() ; it != end; ++it ) { + Kleo::CryptoConfigEntry* entry = group->entry( *it ); + Q_ASSERT( entry ); + if ( entry->level() > CryptoConfigEntry::Level_Advanced ) continue; + CryptoConfigEntryGUI* entryGUI = + CryptoConfigEntryGUIFactory::createEntryGUI( module, entry, *it, glay, widget ); + if ( entryGUI ) { + mEntryGUIs.append( entryGUI ); + entryGUI->load(); + } + } + const int endRow = glay->numRows() - 1; + if ( endRow < startRow ) + return; + + const QString iconName = group->iconName(); + if ( iconName.isEmpty() ) + return; + + QLabel * l = new QLabel( widget ); + l->setPixmap( loadIcon( iconName ) ); + glay->addMultiCellWidget( l, startRow, endRow, 0, 0, Qt::AlignTop ); +} + +bool Kleo::CryptoConfigGroupGUI::save() +{ + bool changed = false; + QValueList<CryptoConfigEntryGUI *>::Iterator it = mEntryGUIs.begin(); + for( ; it != mEntryGUIs.end(); ++it ) { + if ( (*it)->isChanged() ) { + (*it)->save(); + changed = true; + } + } + return changed; +} + +void Kleo::CryptoConfigGroupGUI::load() +{ + QValueList<CryptoConfigEntryGUI *>::Iterator it = mEntryGUIs.begin(); + for( ; it != mEntryGUIs.end(); ++it ) + (*it)->load(); +} + +void Kleo::CryptoConfigGroupGUI::defaults() +{ + QValueList<CryptoConfigEntryGUI *>::Iterator it = mEntryGUIs.begin(); + for( ; it != mEntryGUIs.end(); ++it ) + (*it)->resetToDefault(); +} + +//// + +CryptoConfigEntryGUI* Kleo::CryptoConfigEntryGUIFactory::createEntryGUI( CryptoConfigModule* module, Kleo::CryptoConfigEntry* entry, const QString& entryName, QGridLayout * glay, QWidget* widget, const char* name ) +{ + if ( entry->isList() ) { + switch( entry->argType() ) { + case Kleo::CryptoConfigEntry::ArgType_None: + // A list of options with no arguments (e.g. -v -v -v) is shown as a spinbox + return new CryptoConfigEntrySpinBox( module, entry, entryName, glay, widget, name ); + case Kleo::CryptoConfigEntry::ArgType_Int: + case Kleo::CryptoConfigEntry::ArgType_UInt: + // Let people type list of numbers (1,2,3....). Untested. + return new CryptoConfigEntryLineEdit( module, entry, entryName, glay, widget, name ); + case Kleo::CryptoConfigEntry::ArgType_URL: + case Kleo::CryptoConfigEntry::ArgType_Path: + case Kleo::CryptoConfigEntry::ArgType_DirPath: + case Kleo::CryptoConfigEntry::ArgType_String: + kdWarning(5150) << "No widget implemented for list of type " << entry->argType() << endl; + return 0; // TODO when the need arises :) + case Kleo::CryptoConfigEntry::ArgType_LDAPURL: + return new CryptoConfigEntryLDAPURL( module, entry, entryName, glay, widget, name ); + } + kdWarning(5150) << "No widget implemented for list of (unknown) type " << entry->argType() << endl; + return 0; + } + + switch( entry->argType() ) { + case Kleo::CryptoConfigEntry::ArgType_None: + return new CryptoConfigEntryCheckBox( module, entry, entryName, glay, widget, name ); + case Kleo::CryptoConfigEntry::ArgType_Int: + case Kleo::CryptoConfigEntry::ArgType_UInt: + return new CryptoConfigEntrySpinBox( module, entry, entryName, glay, widget, name ); + case Kleo::CryptoConfigEntry::ArgType_URL: + return new CryptoConfigEntryURL( module, entry, entryName, glay, widget, name ); + case Kleo::CryptoConfigEntry::ArgType_Path: + return new CryptoConfigEntryPath( module, entry, entryName, glay, widget, name ); + case Kleo::CryptoConfigEntry::ArgType_DirPath: + return new CryptoConfigEntryDirPath( module, entry, entryName, glay, widget, name ); + case Kleo::CryptoConfigEntry::ArgType_LDAPURL: + kdWarning(5150) << "No widget implemented for type " << entry->argType() << endl; + return 0; // TODO when the need arises :) + case Kleo::CryptoConfigEntry::ArgType_String: + return new CryptoConfigEntryLineEdit( module, entry, entryName, glay, widget, name ); + } + kdWarning(5150) << "No widget implemented for (unknown) type " << entry->argType() << endl; + return 0; +} + +//// + +Kleo::CryptoConfigEntryGUI::CryptoConfigEntryGUI( + CryptoConfigModule* module, + Kleo::CryptoConfigEntry* entry, + const QString& entryName, + const char* name ) + : QObject( module, name ), mEntry( entry ), mName( entryName ), mChanged( false ) +{ + connect( this, SIGNAL( changed() ), module, SIGNAL( changed() ) ); +} + +QString Kleo::CryptoConfigEntryGUI::description() const +{ + QString descr = mEntry->description(); + if ( descr.isEmpty() ) // shouldn't happen + descr = QString( "<%1>" ).arg( mName ); + return descr; +} + +void Kleo::CryptoConfigEntryGUI::resetToDefault() +{ + mEntry->resetToDefault(); + load(); +} + +//// + +Kleo::CryptoConfigEntryLineEdit::CryptoConfigEntryLineEdit( + CryptoConfigModule* module, + Kleo::CryptoConfigEntry* entry, const QString& entryName, + QGridLayout * glay, QWidget* widget, const char* name ) + : CryptoConfigEntryGUI( module, entry, entryName, name ) +{ + const int row = glay->numRows(); + mLineEdit = new KLineEdit( widget ); + QLabel* label = new QLabel( mLineEdit, description(), widget ); + glay->addWidget( label, row, 1 ); + glay->addWidget( mLineEdit, row, 2 ); + if ( entry->isReadOnly() ) { + label->setEnabled( false ); + mLineEdit->setEnabled( false ); + } else { + connect( mLineEdit, SIGNAL( textChanged( const QString& ) ), SLOT( slotChanged() ) ); + } +} + +void Kleo::CryptoConfigEntryLineEdit::doSave() +{ + mEntry->setStringValue( mLineEdit->text() ); +} + +void Kleo::CryptoConfigEntryLineEdit::doLoad() +{ + mLineEdit->setText( mEntry->stringValue() ); +} + +//// + +Kleo::CryptoConfigEntryPath::CryptoConfigEntryPath( + CryptoConfigModule* module, + Kleo::CryptoConfigEntry* entry, const QString& entryName, + QGridLayout * glay, QWidget* widget, const char* name ) + : CryptoConfigEntryGUI( module, entry, entryName, name ) +{ + const int row = glay->numRows(); + mUrlRequester = new KURLRequester( widget ); + mUrlRequester->setMode( KFile::File | KFile::ExistingOnly | KFile::LocalOnly ); + QLabel* label = new QLabel( mUrlRequester, description(), widget ); + glay->addWidget( label, row, 1 ); + glay->addWidget( mUrlRequester, row, 2 ); + if ( entry->isReadOnly() ) { + label->setEnabled( false ); + mUrlRequester->setEnabled( false ); + } else { + connect( mUrlRequester, SIGNAL( textChanged( const QString& ) ), SLOT( slotChanged() ) ); + } +} + +void Kleo::CryptoConfigEntryPath::doSave() +{ + KURL url; + url.setPath( mUrlRequester->url() ); + mEntry->setURLValue( url ); +} + +void Kleo::CryptoConfigEntryPath::doLoad() +{ + mUrlRequester->setURL( mEntry->urlValue().path() ); +} + +//// + +Kleo::CryptoConfigEntryDirPath::CryptoConfigEntryDirPath( + CryptoConfigModule* module, + Kleo::CryptoConfigEntry* entry, const QString& entryName, + QGridLayout * glay, QWidget* widget, const char* name ) + : CryptoConfigEntryGUI( module, entry, entryName, name ) +{ + const int row = glay->numRows(); + mUrlRequester = new KURLRequester( widget ); + mUrlRequester->setMode( KFile::Directory | KFile::ExistingOnly | KFile::LocalOnly ); + QLabel* label = new QLabel( mUrlRequester, description(), widget ); + glay->addWidget( label, row, 1 ); + glay->addWidget( mUrlRequester, row, 2 ); + if ( entry->isReadOnly() ) { + label->setEnabled( false ); + mUrlRequester->setEnabled( false ); + } else { + connect( mUrlRequester, SIGNAL( textChanged( const QString& ) ), SLOT( slotChanged() ) ); + } +} + +void Kleo::CryptoConfigEntryDirPath::doSave() +{ + KURL url; + url.setPath( mUrlRequester->url() ); + mEntry->setURLValue( url ); + +} + +void Kleo::CryptoConfigEntryDirPath::doLoad() +{ + mUrlRequester->setURL( mEntry->urlValue().path() ); +} + +//// + +Kleo::CryptoConfigEntryURL::CryptoConfigEntryURL( + CryptoConfigModule* module, + Kleo::CryptoConfigEntry* entry, const QString& entryName, + QGridLayout * glay, QWidget* widget, const char* name ) + : CryptoConfigEntryGUI( module, entry, entryName, name ) +{ + const int row = glay->numRows(); + mUrlRequester = new KURLRequester( widget ); + mUrlRequester->setMode( KFile::File | KFile::ExistingOnly ); + QLabel* label = new QLabel( mUrlRequester, description(), widget ); + glay->addWidget( label, row, 1 ); + glay->addWidget( mUrlRequester, row, 2 ); + if ( entry->isReadOnly() ) { + label->setEnabled( false ); + mUrlRequester->setEnabled( false ); + } else { + connect( mUrlRequester, SIGNAL( textChanged( const QString& ) ), SLOT( slotChanged() ) ); + } +} + +void Kleo::CryptoConfigEntryURL::doSave() +{ + mEntry->setURLValue( mUrlRequester->url() ); +} + +void Kleo::CryptoConfigEntryURL::doLoad() +{ + mUrlRequester->setURL( mEntry->urlValue().url() ); +} + +//// + +Kleo::CryptoConfigEntrySpinBox::CryptoConfigEntrySpinBox( + CryptoConfigModule* module, + Kleo::CryptoConfigEntry* entry, const QString& entryName, + QGridLayout * glay, QWidget* widget, const char* name ) + : CryptoConfigEntryGUI( module, entry, entryName, name ) +{ + + if ( entry->argType() == Kleo::CryptoConfigEntry::ArgType_None && entry->isList() ) { + mKind = ListOfNone; + } else if ( entry->argType() == Kleo::CryptoConfigEntry::ArgType_UInt ) { + mKind = UInt; + } else { + Q_ASSERT( entry->argType() == Kleo::CryptoConfigEntry::ArgType_Int ); + mKind = Int; + } + + const int row = glay->numRows(); + mNumInput = new KIntNumInput( widget ); + QLabel* label = new QLabel( mNumInput, description(), widget ); + glay->addWidget( label, row, 1 ); + glay->addWidget( mNumInput, row, 2 ); + + if ( entry->isReadOnly() ) { + label->setEnabled( false ); + mNumInput->setEnabled( false ); + } else { + if ( mKind == UInt || mKind == ListOfNone ) + mNumInput->setMinValue( 0 ); + connect( mNumInput, SIGNAL( valueChanged(int) ), SLOT( slotChanged() ) ); + } +} + +void Kleo::CryptoConfigEntrySpinBox::doSave() +{ + int value = mNumInput->value(); + switch ( mKind ) { + case ListOfNone: + mEntry->setNumberOfTimesSet( value ); + break; + case UInt: + mEntry->setUIntValue( value ); + break; + case Int: + mEntry->setIntValue( value ); + break; + } +} + +void Kleo::CryptoConfigEntrySpinBox::doLoad() +{ + int value = 0; + switch ( mKind ) { + case ListOfNone: + value = mEntry->numberOfTimesSet(); + break; + case UInt: + value = mEntry->uintValue(); + break; + case Int: + value = mEntry->intValue(); + break; + } + mNumInput->setValue( value ); +} + +//// + +Kleo::CryptoConfigEntryCheckBox::CryptoConfigEntryCheckBox( + CryptoConfigModule* module, + Kleo::CryptoConfigEntry* entry, const QString& entryName, + QGridLayout * glay, QWidget* widget, const char* name ) + : CryptoConfigEntryGUI( module, entry, entryName, name ) +{ + const int row = glay->numRows(); + mCheckBox = new QCheckBox( widget ); + glay->addMultiCellWidget( mCheckBox, row, row, 1, 2 ); + mCheckBox->setText( description() ); + if ( entry->isReadOnly() ) { + mCheckBox->setEnabled( false ); + } else { + connect( mCheckBox, SIGNAL( toggled(bool) ), SLOT( slotChanged() ) ); + } +} + +void Kleo::CryptoConfigEntryCheckBox::doSave() +{ + mEntry->setBoolValue( mCheckBox->isChecked() ); +} + +void Kleo::CryptoConfigEntryCheckBox::doLoad() +{ + mCheckBox->setChecked( mEntry->boolValue() ); +} + +Kleo::CryptoConfigEntryLDAPURL::CryptoConfigEntryLDAPURL( + CryptoConfigModule* module, + Kleo::CryptoConfigEntry* entry, + const QString& entryName, + QGridLayout * glay, QWidget* widget, const char* name ) + : CryptoConfigEntryGUI( module, entry, entryName, name ) +{ + mLabel = new QLabel( widget ); + mPushButton = new QPushButton( i18n( "Edit..." ), widget ); + + const int row = glay->numRows(); + glay->addWidget( new QLabel( mPushButton, description(), widget ), row, 1 ); + QHBoxLayout * hlay = new QHBoxLayout; + glay->addLayout( hlay, row, 2 ); + hlay->addWidget( mLabel, 1 ); + hlay->addWidget( mPushButton ); + + if ( entry->isReadOnly() ) { + mLabel->setEnabled( false ); + mPushButton->hide(); + } else { + connect( mPushButton, SIGNAL( clicked() ), SLOT( slotOpenDialog() ) ); + } +} + +void Kleo::CryptoConfigEntryLDAPURL::doLoad() +{ + setURLList( mEntry->urlValueList() ); +} + +void Kleo::CryptoConfigEntryLDAPURL::doSave() +{ + mEntry->setURLValueList( mURLList ); +} + +void Kleo::CryptoConfigEntryLDAPURL::slotOpenDialog() +{ + // I'm a bad boy and I do it all on the stack. Enough classes already :) + // This is just a simple dialog around the directory-services-widget + KDialogBase dialog( mPushButton->parentWidget(), 0, true /*modal*/, + i18n( "Configure LDAP Servers" ), + KDialogBase::Default|KDialogBase::Cancel|KDialogBase::Ok, + KDialogBase::Ok, true /*separator*/ ); + DirectoryServicesWidget* dirserv = new DirectoryServicesWidget( mEntry, &dialog ); + dirserv->load(); + dialog.setMainWidget( dirserv ); + connect( &dialog, SIGNAL( defaultClicked() ), dirserv, SLOT( defaults() ) ); + if ( dialog.exec() ) { + // Note that we just grab the urls from the dialog, we don't call its save method, + // since the user hasn't confirmed the big config dialog yet. + setURLList( dirserv->urlList() ); + slotChanged(); + } +} + +void Kleo::CryptoConfigEntryLDAPURL::setURLList( const KURL::List& urlList ) +{ + mURLList = urlList; + if ( mURLList.isEmpty() ) + mLabel->setText( i18n( "No server configured yet" ) ); + else + mLabel->setText( i18n( "1 server configured", "%n servers configured", mURLList.count() ) ); +} + +#include "cryptoconfigmodule.moc" +#include "cryptoconfigmodule_p.moc" diff --git a/certmanager/lib/ui/cryptoconfigmodule.h b/certmanager/lib/ui/cryptoconfigmodule.h new file mode 100644 index 000000000..185814594 --- /dev/null +++ b/certmanager/lib/ui/cryptoconfigmodule.h @@ -0,0 +1,68 @@ +/* + cryptoconfigmodule.h + + This file is part of libkleopatra + Copyright (c) 2004,2005 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef CRYPTOCONFIGMODULE_H +#define CRYPTOCONFIGMODULE_H + +#include <kjanuswidget.h> + +#include <qvaluelist.h> + +namespace Kleo { + + class CryptoConfig; + class CryptoConfigComponentGUI; + + /** + * Crypto Config Module widget, dynamically generated from CryptoConfig + * It's a simple QWidget so that it can be embedded into a dialog or into a KCModule. + */ + class CryptoConfigModule : public KJanusWidget { + Q_OBJECT + public: + CryptoConfigModule( Kleo::CryptoConfig* config, QWidget * parent=0, const char * name=0 ); + + void save(); + void reset(); // i.e. reload current settings, discarding user input + void defaults(); + void cancel(); + + signals: + void changed(); + + private: + Kleo::CryptoConfig* mConfig; + QValueList<CryptoConfigComponentGUI *> mComponentGUIs; + }; + +} + +#endif diff --git a/certmanager/lib/ui/cryptoconfigmodule_p.h b/certmanager/lib/ui/cryptoconfigmodule_p.h new file mode 100644 index 000000000..22145f323 --- /dev/null +++ b/certmanager/lib/ui/cryptoconfigmodule_p.h @@ -0,0 +1,280 @@ +/* + cryptoconfigmodule_p.h + + This file is part of libkleopatra + Copyright (c) 2004,2005 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License, + version 2, as published by the Free Software Foundation. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef CRYPTOCONFIGMODULE_P_H +#define CRYPTOCONFIGMODULE_P_H + +#include <qtabwidget.h> +#include <qhbox.h> +#include <qcheckbox.h> +#include <kurl.h> + +class KLineEdit; +class KIntNumInput; +class KURLRequester; +class QPushButton; +class QGridLayout; + +namespace Kleo { + + class CryptoConfig; + class CryptoConfigComponent; + class CryptoConfigGroup; + class CryptoConfigEntry; + class CryptoConfigComponentGUI; + class CryptoConfigGroupGUI; + class CryptoConfigEntryGUI; + + /** + * A widget corresponding to a component in the crypto config + */ + class CryptoConfigComponentGUI : public QWidget { + Q_OBJECT + + public: + CryptoConfigComponentGUI( CryptoConfigModule* module, Kleo::CryptoConfigComponent* component, + QWidget* parent, const char* name = 0 ); + + bool save(); + void load(); + void defaults(); + + private: + Kleo::CryptoConfigComponent* mComponent; + QValueList<CryptoConfigGroupGUI *> mGroupGUIs; + }; + + /** + * A class managing widgets corresponding to a group in the crypto config + */ + class CryptoConfigGroupGUI : public QObject { + Q_OBJECT + + public: + CryptoConfigGroupGUI( CryptoConfigModule* module, Kleo::CryptoConfigGroup* group, + QGridLayout * layout, QWidget* parent, const char* name = 0 ); + + bool save(); + void load(); + void defaults(); + + private: + Kleo::CryptoConfigGroup* mGroup; + QValueList<CryptoConfigEntryGUI *> mEntryGUIs; + }; + + /** + * Factory for CryptoConfigEntryGUI instances + * Not a real factory, but can become one later. + */ + class CryptoConfigEntryGUIFactory { + public: + static CryptoConfigEntryGUI* createEntryGUI( + CryptoConfigModule* module, + Kleo::CryptoConfigEntry* entry, const QString& entryName, + QGridLayout * layout, QWidget* widget, const char* name = 0 ); + }; + + /** + * Base class for the widget managers tied to an entry in the crypto config + */ + class CryptoConfigEntryGUI : public QObject { + Q_OBJECT + public: + CryptoConfigEntryGUI( CryptoConfigModule* module, + Kleo::CryptoConfigEntry* entry, + const QString& entryName, + const char* name = 0 ); + virtual ~CryptoConfigEntryGUI() {} + + void load() { doLoad(); mChanged = false; } + void save() { Q_ASSERT( mChanged ); doSave(); mChanged = false; } + void resetToDefault(); + + QString description() const; + bool isChanged() const { return mChanged; } + + signals: + void changed(); + + protected slots: + void slotChanged() { + mChanged = true; + emit changed(); + } + + protected: + virtual void doSave() = 0; + virtual void doLoad() = 0; + + Kleo::CryptoConfigEntry* mEntry; + QString mName; + bool mChanged; + }; + + /** + * A widget manager for a string entry in the crypto config + */ + class CryptoConfigEntryLineEdit : public CryptoConfigEntryGUI { + Q_OBJECT + + public: + CryptoConfigEntryLineEdit( CryptoConfigModule* module, + Kleo::CryptoConfigEntry* entry, + const QString& entryName, + QGridLayout * layout, + QWidget* parent, const char* name = 0 ); + + virtual void doSave(); + virtual void doLoad(); + private: + KLineEdit* mLineEdit; + }; + + /** + * A widget manager for a path entry in the crypto config + */ + class CryptoConfigEntryPath : public CryptoConfigEntryGUI { + Q_OBJECT + + public: + CryptoConfigEntryPath( CryptoConfigModule* module, + Kleo::CryptoConfigEntry* entry, + const QString& entryName, + QGridLayout * layout, + QWidget* parent, const char* name = 0 ); + + virtual void doSave(); + virtual void doLoad(); + private: + KURLRequester* mUrlRequester; + }; + + /** + * A widget manager for a directory path entry in the crypto config + */ + class CryptoConfigEntryDirPath : public CryptoConfigEntryGUI { + Q_OBJECT + + public: + CryptoConfigEntryDirPath( CryptoConfigModule* module, + Kleo::CryptoConfigEntry* entry, + const QString& entryName, + QGridLayout * layout, + QWidget* parent, const char* name = 0 ); + + virtual void doSave(); + virtual void doLoad(); + private: + KURLRequester* mUrlRequester; + }; + + /** + * A widget manager for an URL entry in the crypto config + */ + class CryptoConfigEntryURL : public CryptoConfigEntryGUI { + Q_OBJECT + + public: + CryptoConfigEntryURL( CryptoConfigModule* module, + Kleo::CryptoConfigEntry* entry, + const QString& entryName, + QGridLayout * layout, + QWidget* parent, const char* name = 0 ); + + virtual void doSave(); + virtual void doLoad(); + private: + KURLRequester * mUrlRequester; + }; + + /** + * A widget manager for an int/uint entry in the crypto config + */ + class CryptoConfigEntrySpinBox : public CryptoConfigEntryGUI { + Q_OBJECT + + public: + CryptoConfigEntrySpinBox( CryptoConfigModule* module, + Kleo::CryptoConfigEntry* entry, + const QString& entryName, + QGridLayout * layout, + QWidget* parent, const char* name = 0 ); + virtual void doSave(); + virtual void doLoad(); + private: + enum { Int, UInt, ListOfNone } mKind; + KIntNumInput* mNumInput; + }; + + /** + * A widget manager for a bool entry in the crypto config + */ + class CryptoConfigEntryCheckBox : public CryptoConfigEntryGUI { + Q_OBJECT + + public: + CryptoConfigEntryCheckBox( CryptoConfigModule* module, + Kleo::CryptoConfigEntry* entry, + const QString& entryName, + QGridLayout * layout, + QWidget* parent, const char* name = 0 ); + virtual void doSave(); + virtual void doLoad(); + private: + QCheckBox* mCheckBox; + }; + + /** + * A widget manager for a bool entry in the crypto config + */ + class CryptoConfigEntryLDAPURL : public CryptoConfigEntryGUI { + Q_OBJECT + + public: + CryptoConfigEntryLDAPURL( CryptoConfigModule* module, + Kleo::CryptoConfigEntry* entry, + const QString& entryName, + QGridLayout * layout, + QWidget* parent, const char* name = 0 ); + virtual void doSave(); + virtual void doLoad(); + private slots: + void slotOpenDialog(); + private: + void setURLList( const KURL::List& urlList ); + QLabel* mLabel; + QPushButton* mPushButton; + KURL::List mURLList; + }; +} + +#endif // CRYPTOCONFIGMODULE_P_H diff --git a/certmanager/lib/ui/directoryserviceswidget.cpp b/certmanager/lib/ui/directoryserviceswidget.cpp new file mode 100644 index 000000000..76c1b3dda --- /dev/null +++ b/certmanager/lib/ui/directoryserviceswidget.cpp @@ -0,0 +1,308 @@ +/* + directoryserviceswidget.cpp + + This file is part of Kleopatra, the KDE keymanager + Copyright (c) 2001,2002,2004 Klar�vdalens Datakonsult AB + + Kleopatra is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + Kleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include <config.h> + +#include "directoryserviceswidget.h" +#include "adddirectoryservicedialogimpl.h" +#include "cryptplugwrapper.h" + +#include <klineedit.h> +#include <kleo/cryptoconfig.h> +#include <kiconloader.h> +#include <kdebug.h> + +#include <qbuttongroup.h> +#include <qtoolbutton.h> +#include <qlistview.h> +#include <qpushbutton.h> + +using namespace Kleo; + +class QX500ListViewItem : public QListViewItem +{ +public: + QX500ListViewItem( QListView* lv, QListViewItem* prev, + const QString& serverName, + const QString& portNumber, + const QString& dn, + const QString& username, + const QString& password ) + : QListViewItem( lv, prev, serverName, portNumber, dn, username ) { + setPassword( password ); + } + + void setPassword( const QString& pass ) { + mPassword = pass; + setText( 4, pass.isEmpty() ? QString::null : QString::fromLatin1( "******" ) ); + } + + const QString& password() const { return mPassword; } + + void setData( const QString& serverName, + const QString& portNumber, + const QString& dn, + const QString& username, + const QString& password ) { + setText( 0, serverName ); + setText( 1, portNumber ); + setText( 2, dn ); + setText( 3, username ); + setPassword( password ); + } + + void copyItem( QX500ListViewItem* item ) { + for ( unsigned int i = 0; i < 4 ; ++i ) + setText( i, item->text( i ) ); + setPassword( item->password() ); + } + +private: + QString mPassword; +}; + +Kleo::DirectoryServicesWidget::DirectoryServicesWidget( + Kleo::CryptoConfigEntry* configEntry, + QWidget* parent, const char* name, WFlags fl ) + : DirectoryServicesWidgetBase( parent, name, fl ), + mConfigEntry( configEntry ) +{ + x500LV->setSorting( -1 ); + + // taken from kmail's configuredialog.cpp + upButton->setIconSet( BarIconSet( "up", KIcon::SizeSmall ) ); + upButton->setEnabled( false ); // b/c no item is selected yet + + downButton->setIconSet( BarIconSet( "down", KIcon::SizeSmall ) ); + downButton->setEnabled( false ); // b/c no item is selected yet +} + + +/* + * Destroys the object and frees any allocated resources + */ +DirectoryServicesWidget::~DirectoryServicesWidget() +{ + // no need to delete child widgets, Qt does it all for us +} + + +/** + Enables or disables the widgets in this dialog according to the + capabilities of the current plugin passed as a parameter. +*/ +void DirectoryServicesWidget::enableDisable( CryptPlugWrapper* cryptPlug ) // unused? +{ + // disable the whole page if the plugin does not support the use + // of directory services + setEnabled( cryptPlug->hasFeature( Feature_CertificateDirectoryService ) || + cryptPlug->hasFeature( Feature_CRLDirectoryService ) ); +} + + +/* + * protected slot, connected to selectionChanged() + */ +void DirectoryServicesWidget::slotServiceChanged( QListViewItem* item ) +{ + if( item ) + removeServicePB->setEnabled( true ); + else + removeServicePB->setEnabled( false ); + downButton->setEnabled( item && item->itemBelow() ); + upButton->setEnabled( item && item->itemAbove() ); +} + + +/* + * protected slot, connected to returnPressed/doubleClicked + */ +void DirectoryServicesWidget::slotServiceSelected( QListViewItem* item ) +{ + AddDirectoryServiceDialogImpl* dlg = new AddDirectoryServiceDialogImpl( this ); + dlg->serverNameED->setText( item->text( 0 ) ); + dlg->portED->setText( item->text( 1 ) ); + dlg->descriptionED->setText( item->text( 2 ) ); + dlg->usernameED->setText( item->text( 3 ) ); + QString pass = static_cast<QX500ListViewItem *>( item )->password(); + dlg->passwordED->setText( pass ); + + if( dlg->exec() == QDialog::Accepted ) { + item->setText( 0, dlg->serverNameED->text() ); + item->setText( 1, dlg->portED->text() ); + item->setText( 2, dlg->descriptionED->text() ); + item->setText( 3, dlg->usernameED->text() ); + static_cast<QX500ListViewItem *>( item )->setPassword( dlg->passwordED->text() ); + emit changed(); + } + delete dlg; +} + + +/* + * protected slot + */ +void DirectoryServicesWidget::slotAddService() +{ + AddDirectoryServiceDialogImpl* dlg = new AddDirectoryServiceDialogImpl( this ); + if( dlg->exec() == QDialog::Accepted ) { + QX500ListViewItem *item = new QX500ListViewItem( x500LV, x500LV->lastItem(), + dlg->serverNameED->text(), + dlg->portED->text(), + dlg->descriptionED->text(), + dlg->usernameED->text(), + dlg->passwordED->text() ); + slotServiceChanged(item); + emit changed(); + } + delete dlg; +} + +/* + * protected slot + */ +void DirectoryServicesWidget::slotDeleteService() +{ + QListViewItem* item = x500LV->selectedItem(); + Q_ASSERT( item ); + if( !item ) + return; + else + delete item; + x500LV->triggerUpdate(); + item = x500LV->currentItem(); + x500LV->setCurrentItem( item ); // seems necessary... + x500LV->setSelected( item, true ); + emit changed(); +} + + +void DirectoryServicesWidget::setInitialServices( const KURL::List& urls ) +{ + x500LV->clear(); + for( KURL::List::const_iterator it = urls.begin(); it != urls.end(); ++it ) { + QString dn = KURL::decode_string( (*it).query().mid( 1 ) ); // decode query and skip leading '?' + (void)new QX500ListViewItem( x500LV, x500LV->lastItem(), + (*it).host(), + QString::number( (*it).port() ), + dn, + (*it).user(), + (*it).pass()); + } +} + +KURL::List DirectoryServicesWidget::urlList() const +{ + KURL::List lst; + QListViewItemIterator it( x500LV ); + for ( ; it.current() ; ++it ) { + QListViewItem* item = it.current(); + KURL url; + url.setProtocol( "ldap" ); + url.setHost( item->text( 0 ) ); + url.setPort( item->text( 1 ).toInt() ); + url.setPath( "/" ); // workaround KURL parsing bug + url.setQuery( item->text( 2 ) ); + url.setUser( item->text( 3 ) ); + url.setPass( static_cast<QX500ListViewItem *>( item )->password() ); + kdDebug() << url << endl; + lst << url; + } + return lst; +} + +void DirectoryServicesWidget::clear() +{ + x500LV->clear(); + emit changed(); +} + +void DirectoryServicesWidget::load() +{ + if ( mConfigEntry ) { + setInitialServices( mConfigEntry->urlValueList() ); + } +} + +void DirectoryServicesWidget::save() +{ + if ( mConfigEntry ) { + mConfigEntry->setURLValueList( urlList() ); + } +} + +void DirectoryServicesWidget::defaults() +{ + if ( mConfigEntry ) { + // resetToDefault doesn't work since gpgconf doesn't know any defaults for this entry. + //mConfigEntry->resetToDefault(); + //load(); + clear(); // the default is an empty list. + } +} + +static void swapItems( QX500ListViewItem *item, QX500ListViewItem *other ) +{ + QString serverName = item->text( 0 ); + QString portNumber = item->text( 1 ); + QString dn = item->text( 2 ); + QString username = item->text( 3 ); + QString password = item->password(); + item->copyItem( other ); + other->setData( serverName, portNumber, dn, username, password ); +} + +void Kleo::DirectoryServicesWidget::slotMoveUp() +{ + QX500ListViewItem *item = static_cast<QX500ListViewItem *>( x500LV->selectedItem() ); + if ( !item ) return; + QX500ListViewItem *above = static_cast<QX500ListViewItem *>( item->itemAbove() ); + if ( !above ) return; + swapItems( item, above ); + x500LV->setCurrentItem( above ); + x500LV->setSelected( above, true ); + emit changed(); +} + +void Kleo::DirectoryServicesWidget::slotMoveDown() +{ + QX500ListViewItem *item = static_cast<QX500ListViewItem *>( x500LV->selectedItem() ); + if ( !item ) return; + QX500ListViewItem *below = static_cast<QX500ListViewItem *>( item->itemBelow() ); + if ( !below ) return; + swapItems( item, below ); + x500LV->setCurrentItem( below ); + x500LV->setSelected( below, true ); + emit changed(); +} + +#include "directoryserviceswidget.moc" diff --git a/certmanager/lib/ui/directoryserviceswidget.h b/certmanager/lib/ui/directoryserviceswidget.h new file mode 100644 index 000000000..02e428c95 --- /dev/null +++ b/certmanager/lib/ui/directoryserviceswidget.h @@ -0,0 +1,82 @@ +/* + directoryserviceswidget.h + + This file is part of Kleopatra, the KDE keymanager + Copyright (c) 2001,2002,2004 Klarälvdalens Datakonsult AB + + Kleopatra is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + Kleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef DIRECTORYSERVICESWIDGET_H +#define DIRECTORYSERVICESWIDGET_H +#include "directoryserviceswidgetbase.h" +#include <kurl.h> +#include <kdepimmacros.h> + +class CryptPlugWrapper; +namespace Kleo { + +class CryptoConfigEntry; + +class KDE_EXPORT DirectoryServicesWidget : public DirectoryServicesWidgetBase +{ + Q_OBJECT + +public: + DirectoryServicesWidget( + Kleo::CryptoConfigEntry* configEntry, + QWidget* parent = 0, const char* name = 0, WFlags fl = 0 ); + ~DirectoryServicesWidget(); + + void load(); + void save(); + + void enableDisable( CryptPlugWrapper* wrapper ); // unused? + void setInitialServices( const KURL::List& urls ); + KURL::List urlList() const; + void clear(); + +public slots: + void defaults(); + +signals: + void changed(); + +protected slots: + void slotServiceChanged( QListViewItem* ); + void slotServiceSelected( QListViewItem* ); + void slotAddService(); + void slotDeleteService(); + void slotMoveUp(); + void slotMoveDown(); + +private: + Kleo::CryptoConfigEntry* mConfigEntry; +}; + +} + +#endif // DIRECTORYSERVICESWIDGET_H diff --git a/certmanager/lib/ui/directoryserviceswidgetbase.ui b/certmanager/lib/ui/directoryserviceswidgetbase.ui new file mode 100644 index 000000000..1dabbca51 --- /dev/null +++ b/certmanager/lib/ui/directoryserviceswidgetbase.ui @@ -0,0 +1,342 @@ +<!DOCTYPE UI><UI version="3.2" stdsetdef="1"> +<class>DirectoryServicesWidgetBase</class> +<widget class="QWidget"> + <property name="name"> + <cstring>DirectoryServicesWidgetBase</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>576</width> + <height>363</height> + </rect> + </property> + <property name="caption"> + <string>Directory Services Configuration</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>x500LA</cstring> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>Plain</enum> + </property> + <property name="text"> + <string>X.&500 directory services:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>x500LV</cstring> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout2</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QListView"> + <column> + <property name="text"> + <string>Server Name</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Port</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Base DN</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>User Name</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Password</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <property name="name"> + <cstring>x500LV</cstring> + </property> + <property name="allColumnsShowFocus"> + <bool>true</bool> + </property> + <property name="toolTip" stdset="0"> + <string>Select Directory Services to Use Here</string> + </property> + <property name="whatsThis" stdset="0"> + <string><qt> +<h1>X.500 Directory Services</h1> +You can use X.500 directory services to retrieve certificates and certificate revocation lists that are not saved locally. Ask your local administrator if you want to make use of this feature and are unsure which directory service you can use. +<p> +If you do not use a directory service, you can still use local certificates. +</qt></string> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout1</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QToolButton"> + <property name="name"> + <cstring>upButton</cstring> + </property> + <property name="text"> + <string></string> + </property> + </widget> + <widget class="QToolButton"> + <property name="name"> + <cstring>downButton</cstring> + </property> + <property name="text"> + <string></string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer5</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>51</height> + </size> + </property> + </spacer> + </vbox> + </widget> + </hbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout3</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer> + <property name="name"> + <cstring>Spacer10</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>47</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QPushButton"> + <property name="name"> + <cstring>addServicePB</cstring> + </property> + <property name="text"> + <string>&Add Service...</string> + </property> + <property name="toolTip" stdset="0"> + <string>Click to add a service</string> + </property> + <property name="whatsThis" stdset="0"> + <string><qt> +<h1>Add a Directory Service</h1> +By clicking this button, you can select a new directory service to be used for retrieving certificates and CRLs. You will be asked for the server name and an optional description. +</qt></string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>Spacer11</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>47</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QPushButton"> + <property name="name"> + <cstring>removeServicePB</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>&Remove Service</string> + </property> + <property name="toolTip" stdset="0"> + <string>Click to remove the currently selected service</string> + </property> + <property name="whatsThis" stdset="0"> + <string><qt> +<h1>Remove Directory Service</h1> +By clicking this button, you can remove the currently selected directory service in the list above. You will have a chance to rethink your decision before the entry is deleted from the list. +</qt></string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>Spacer12</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>47</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> + </widget> + <spacer> + <property name="name"> + <cstring>Spacer9</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>16</height> + </size> + </property> + </spacer> + </vbox> +</widget> +<connections> + <connection> + <sender>removeServicePB</sender> + <signal>clicked()</signal> + <receiver>DirectoryServicesWidgetBase</receiver> + <slot>slotDeleteService()</slot> + </connection> + <connection> + <sender>x500LV</sender> + <signal>returnPressed(QListViewItem*)</signal> + <receiver>DirectoryServicesWidgetBase</receiver> + <slot>slotServiceSelected(QListViewItem*)</slot> + </connection> + <connection> + <sender>x500LV</sender> + <signal>doubleClicked(QListViewItem*)</signal> + <receiver>DirectoryServicesWidgetBase</receiver> + <slot>slotServiceSelected(QListViewItem*)</slot> + </connection> + <connection> + <sender>x500LV</sender> + <signal>selectionChanged(QListViewItem*)</signal> + <receiver>DirectoryServicesWidgetBase</receiver> + <slot>slotServiceChanged(QListViewItem*)</slot> + </connection> + <connection> + <sender>addServicePB</sender> + <signal>clicked()</signal> + <receiver>DirectoryServicesWidgetBase</receiver> + <slot>slotAddService()</slot> + </connection> + <connection> + <sender>upButton</sender> + <signal>clicked()</signal> + <receiver>DirectoryServicesWidgetBase</receiver> + <slot>slotMoveUp()</slot> + </connection> + <connection> + <sender>downButton</sender> + <signal>clicked()</signal> + <receiver>DirectoryServicesWidgetBase</receiver> + <slot>slotMoveDown()</slot> + </connection> +</connections> +<slots> + <slot access="protected">slotAddService()</slot> + <slot access="protected">slotDeleteService()</slot> + <slot access="protected">slotServiceChanged( QListViewItem* )</slot> + <slot access="protected">slotServiceSelected( QListViewItem* )</slot> + <slot access="protected">slotMoveUp()</slot> + <slot access="protected">slotMoveDown()</slot> +</slots> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/certmanager/lib/ui/dnattributeorderconfigwidget.cpp b/certmanager/lib/ui/dnattributeorderconfigwidget.cpp new file mode 100644 index 000000000..54fe32af1 --- /dev/null +++ b/certmanager/lib/ui/dnattributeorderconfigwidget.cpp @@ -0,0 +1,309 @@ +/* -*- c++ -*- + dnattributeorderconfigwidget.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klar�vdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "dnattributeorderconfigwidget.h" + +#include "kleo/dn.h" + +#include <klocale.h> +#include <kdebug.h> +#include <kdialog.h> +#include <kiconloader.h> +#include <kconfig.h> +#include <kapplication.h> + +#include <qtoolbutton.h> +#include <qlayout.h> +#include <qheader.h> +#include <qlabel.h> +#include <qlistview.h> +#include <qtooltip.h> + +#include <assert.h> + +struct Kleo::DNAttributeOrderConfigWidget::Private { + enum { UUp=0, Up=1, Left=2, Right=3, Down=4, DDown=5 }; + + QListView * availableLV; + QListView * currentLV; + QToolButton * navTB[6]; + + QListViewItem * placeHolderItem; + + Kleo::DNAttributeMapper * mapper; +}; + +static void prepare( QListView * lv ) { + lv->setAllColumnsShowFocus( true ); + lv->setResizeMode( QListView::LastColumn ); + lv->header()->setClickEnabled( false ); + lv->addColumn( QString::null ); + lv->addColumn( i18n("Description") ); +} + +Kleo::DNAttributeOrderConfigWidget::DNAttributeOrderConfigWidget( DNAttributeMapper * mapper, QWidget * parent, const char * name, WFlags f ) + : QWidget( parent, name, f ), d( 0 ) +{ + assert( mapper ); + d = new Private(); + d->mapper = mapper; + + QGridLayout * glay = new QGridLayout( this, 2, 3, 0, KDialog::spacingHint() ); + glay->setColStretch( 0, 1 ); + glay->setColStretch( 2, 1 ); + + int row = -1; + + ++row; + glay->addWidget( new QLabel( i18n("Available attributes:"), this ), row, 0 ); + glay->addWidget( new QLabel( i18n("Current attribute order:"), this ), row, 2 ); + + + ++row; + glay->setRowStretch( row, 1 ); + + d->availableLV = new QListView( this ); + prepare( d->availableLV ); + d->availableLV->setSorting( 0 ); + glay->addWidget( d->availableLV, row, 0 ); + + d->currentLV = new QListView( this ); + prepare( d->currentLV ); + d->currentLV->setSorting( -1 ); + glay->addWidget( d->currentLV, row, 2 ); + + connect( d->availableLV, SIGNAL(clicked( QListViewItem * )), + SLOT(slotAvailableSelectionChanged(QListViewItem*)) ); + connect( d->currentLV, SIGNAL(clicked(QListViewItem*)), + SLOT(slotCurrentOrderSelectionChanged(QListViewItem*)) ); + + d->placeHolderItem = new QListViewItem( d->availableLV, "_X_", i18n("All others") ); + + // the up/down/left/right arrow cross: + + QGridLayout * xlay = new QGridLayout( 5, 3, 0, "xlay" ); + xlay->setAlignment( AlignCenter ); + + static const struct { + const char * icon; + int row, col; + const char * tooltip; + const char * slot; + } navButtons[] = { + { "2uparrow", 0, 1, I18N_NOOP( "Move to top" ), SLOT(slotDoubleUpButtonClicked()) }, + { "1uparrow", 1, 1, I18N_NOOP( "Move one up" ), SLOT(slotUpButtonClicked()) }, + { "1leftarrow", 2, 0, I18N_NOOP( "Remove from current attribute order" ), SLOT(slotLeftButtonClicked()) }, + { "1rightarrow", 2, 2, I18N_NOOP( "Add to current attribute order" ), SLOT(slotRightButtonClicked()) }, + { "1downarrow", 3, 1, I18N_NOOP( "Move one down" ), SLOT(slotDownButtonClicked()) }, + { "2downarrow", 4, 1, I18N_NOOP( "Move to bottom" ), SLOT(slotDoubleDownButtonClicked()) } + }; + + for ( unsigned int i = 0 ; i < sizeof navButtons / sizeof *navButtons ; ++i ) { + QToolButton * tb = d->navTB[i] = new QToolButton( this ); + tb->setIconSet( SmallIconSet( navButtons[i].icon ) ); + tb->setEnabled( false ); + QToolTip::add( tb, i18n( navButtons[i].tooltip ) ); + xlay->addWidget( tb, navButtons[i].row, navButtons[i].col ); + connect( tb, SIGNAL(clicked()), navButtons[i].slot ); + } + + glay->addLayout( xlay, row, 1 ); +} + +Kleo::DNAttributeOrderConfigWidget::~DNAttributeOrderConfigWidget() { + delete d; d = 0; +} + +void Kleo::DNAttributeOrderConfigWidget::load() { + // save the _X_ item: + takePlaceHolderItem(); + // clear the rest: + d->availableLV->clear(); + d->currentLV->clear(); + + const QStringList order = d->mapper->attributeOrder(); + + // fill the RHS listview: + QListViewItem * last = 0; + for ( QStringList::const_iterator it = order.begin() ; it != order.end() ; ++it ) { + const QString attr = (*it).upper(); + if ( attr == "_X_" ) { + takePlaceHolderItem(); + d->currentLV->insertItem( d->placeHolderItem ); + d->placeHolderItem->moveItem( last ); + last = d->placeHolderItem; + } else + last = new QListViewItem( d->currentLV, last, attr, d->mapper->name2label( attr ) ); + } + + // fill the LHS listview with what's left: + + const QStringList all = Kleo::DNAttributeMapper::instance()->names(); + for ( QStringList::const_iterator it = all.begin() ; it != all.end() ; ++it ) + if ( order.find( *it ) == order.end() ) + (void)new QListViewItem( d->availableLV, *it, d->mapper->name2label( *it ) ); + + if ( !d->placeHolderItem->listView() ) + d->availableLV->insertItem( d->placeHolderItem ); +} + +void Kleo::DNAttributeOrderConfigWidget::takePlaceHolderItem() { + if ( QListView * lv = d->placeHolderItem->listView() ) + lv->takeItem( d->placeHolderItem ); +} + +void Kleo::DNAttributeOrderConfigWidget::save() const { + QStringList order; + for ( QListViewItemIterator it( d->currentLV ) ; it.current() ; ++it ) + order.push_back( it.current()->text( 0 ) ); + + d->mapper->setAttributeOrder( order ); +} + +void Kleo::DNAttributeOrderConfigWidget::defaults() { + kdDebug() << "Sorry, not implemented: Kleo::DNAttributeOrderConfigWidget::defaults()" << endl; +} + + + +void Kleo::DNAttributeOrderConfigWidget::slotAvailableSelectionChanged( QListViewItem * item ) { + d->navTB[Private::Right]->setEnabled( item ); +} + +void Kleo::DNAttributeOrderConfigWidget::slotCurrentOrderSelectionChanged( QListViewItem * item ) { + enableDisableButtons( item ); +} + +void Kleo::DNAttributeOrderConfigWidget::enableDisableButtons( QListViewItem * item ) { + d->navTB[Private::UUp ]->setEnabled( item && item->itemAbove() ); + d->navTB[Private::Up ]->setEnabled( item && item->itemAbove() ); + d->navTB[Private::Left ]->setEnabled( item ); + d->navTB[Private::Down ]->setEnabled( item && item->itemBelow() ); + d->navTB[Private::DDown]->setEnabled( item && item->itemBelow() ); +} + +void Kleo::DNAttributeOrderConfigWidget::slotUpButtonClicked() { + QListViewItem * item = d->currentLV->selectedItem(); + if ( !item ) + return; + QListViewItem * above = item->itemAbove(); + if ( !above ) + return; + above->moveItem( item ); // moves "above" to after "item", ie. "item" one up + enableDisableButtons( item ); + emit changed(); +} + +void Kleo::DNAttributeOrderConfigWidget::slotDoubleUpButtonClicked() { + QListViewItem * item = d->currentLV->selectedItem(); + if ( !item ) + return; + if ( item == d->currentLV->firstChild() ) + return; + d->currentLV->takeItem( item ); + d->currentLV->insertItem( item ); + d->currentLV->setSelected( item, true ); + enableDisableButtons( item ); + emit changed(); +} + +void Kleo::DNAttributeOrderConfigWidget::slotDownButtonClicked() { + QListViewItem * item = d->currentLV->selectedItem(); + if ( !item ) + return; + QListViewItem * below = item->itemBelow(); + if ( !below ) + return; + item->moveItem( below ); // moves "item" to after "below", ie. "item" one down + enableDisableButtons( item ); + emit changed(); +} + +void Kleo::DNAttributeOrderConfigWidget::slotDoubleDownButtonClicked() { + QListViewItem * item = d->currentLV->selectedItem(); + if ( !item ) + return; + QListViewItem * last = d->currentLV->lastItem(); + assert( last ); + if ( item == last ) + return; + item->moveItem( last ); // moves "item" to after "last", ie. to the bottom + enableDisableButtons( item ); + emit changed(); +} + +void Kleo::DNAttributeOrderConfigWidget::slotLeftButtonClicked() { + QListViewItem * right = d->currentLV->selectedItem(); + if ( !right ) + return; + QListViewItem * next = right->itemBelow(); + if ( !next ) + next = right->itemAbove(); + d->currentLV->takeItem( right ); + d->availableLV->insertItem( right ); + if ( next ) + d->currentLV->setSelected( next, true ); + enableDisableButtons( next ); + emit changed(); +} + +void Kleo::DNAttributeOrderConfigWidget::slotRightButtonClicked() { + QListViewItem * left = d->availableLV->selectedItem(); + if ( !left ) + return; + QListViewItem * next = left->itemBelow(); + if ( !next ) + next = left->itemAbove(); + d->availableLV->takeItem( left ); + d->currentLV->insertItem( left ); + if ( QListViewItem * right = d->currentLV->selectedItem() ) { + if ( QListViewItem * above = right->itemAbove() ) + left->moveItem( above ); // move new item immediately before old selected + d->currentLV->setSelected( right, false ); + } + d->currentLV->setSelected( left, true ); + enableDisableButtons( left ); + d->navTB[Private::Right]->setEnabled( next ); + if ( next ) + d->availableLV->setSelected( next, true ); + emit changed(); +} + + + +void Kleo::DNAttributeOrderConfigWidget::virtual_hook( int, void* ) {} + +#include "dnattributeorderconfigwidget.moc" diff --git a/certmanager/lib/ui/dnattributeorderconfigwidget.h b/certmanager/lib/ui/dnattributeorderconfigwidget.h new file mode 100644 index 000000000..11299ab37 --- /dev/null +++ b/certmanager/lib/ui/dnattributeorderconfigwidget.h @@ -0,0 +1,87 @@ +/* -*- c++ -*- + dnattributeorderconfigwidget.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. + */ + +#ifndef __KLEO_UI_DNATTRIBUTEORDERCONFIGWIDGET_H__ +#define __KLEO_UI_DNATTRIBUTEORDERCONFIGWIDGET_H__ + +#include <qwidget.h> +#include <kdepimmacros.h> +namespace Kleo { + class DNAttributeMapper; +} + +class QListViewItem; + +namespace Kleo { + + class KDE_EXPORT DNAttributeOrderConfigWidget : public QWidget { + Q_OBJECT + public: + /*! Use Kleo::DNAttributeMapper::instance()->configWidget( parent, name ) instead. */ + DNAttributeOrderConfigWidget( DNAttributeMapper * mapper, QWidget * parent=0, const char * name=0, WFlags f=0 ); + ~DNAttributeOrderConfigWidget(); + + void load(); + void save() const; + void defaults(); + + signals: + void changed(); + + // + // only boring stuff below... + // + + private slots: + void slotAvailableSelectionChanged( QListViewItem * ); + void slotCurrentOrderSelectionChanged( QListViewItem * ); + void slotDoubleUpButtonClicked(); + void slotUpButtonClicked(); + void slotDownButtonClicked(); + void slotDoubleDownButtonClicked(); + void slotLeftButtonClicked(); + void slotRightButtonClicked(); + + private: + void takePlaceHolderItem(); + void enableDisableButtons( QListViewItem * ); + + private: + class Private; + Private * d; + protected: + virtual void virtual_hook( int, void* ); + }; + +} + +#endif // __KLEO_UI_DNATTRIBUTEORDERCONFIGWIDGET_H__ diff --git a/certmanager/lib/ui/kdhorizontalline.cpp b/certmanager/lib/ui/kdhorizontalline.cpp new file mode 100644 index 000000000..83b92a19b --- /dev/null +++ b/certmanager/lib/ui/kdhorizontalline.cpp @@ -0,0 +1,171 @@ +/* -*- Mode: C++ -*- + KD Tools - a set of useful widgets for Qt +*/ + +/**************************************************************************** +** Copyright (C) 2005 Klarälvdalens Datakonsult AB. All rights reserved. +** +** This file is part of the KD Tools library. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid commercial KD Tools licenses may use this file in +** accordance with the KD Tools Commercial License Agreement provided with +** the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.klaralvdalens-datakonsult.se/?page=products for +** information about KD Tools Commercial License Agreements. +** +** Contact info@klaralvdalens-datakonsult.se if any conditions of this +** licensing are not clear to you. +** +** In addition, as a special exception, the copyright holders give +** permission to link the code of this program with any edition of the +** Qt library by Trolltech AS, Norway (or with modified versions of Qt +** that use the same license as Qt), and distribute linked +** combinations including the two. You must obey the GNU General +** Public License in all respects for all of the code used other than +** Qt. If you modify this file, you may extend this exception to your +** version of the file, but you are not obligated to do so. If you do +** not wish to do so, delete this exception statement from your +** version. +** +**********************************************************************/ + +#include "kdhorizontalline.h" + +#include <qstyle.h> +#include <qpainter.h> +#ifdef QT_ACCESSIBILITY_SUPPORT +#include <qaccessible.h> +#endif +#include <qfontmetrics.h> +#include <qapplication.h> + +KDHorizontalLine::KDHorizontalLine( QWidget * parent, const char * name, WFlags f ) + : QFrame( parent, name, f ), + mAlign( Qt::AlignAuto ), + mLenVisible( 0 ) +{ + QFrame::setFrameStyle( HLine | Sunken ); +} + +KDHorizontalLine::KDHorizontalLine( const QString & title, QWidget * parent, const char * name, WFlags f ) + : QFrame( parent, name, f ), + mAlign( Qt::AlignAuto ), + mLenVisible( 0 ) +{ + QFrame::setFrameStyle( HLine | Sunken ); + setTitle( title ); +} + +KDHorizontalLine::~KDHorizontalLine() {} + +void KDHorizontalLine::setFrameStyle( int style ) { + QFrame::setFrameStyle( ( style & ~MShape ) | HLine ); // force HLine +} + +void KDHorizontalLine::setTitle( const QString & title ) { + if ( mTitle == title ) + return; + mTitle = title; + calculateFrame(); + update(); + updateGeometry(); +#ifdef QT_ACCESSIBILITY_SUPPORT + QAccessible::updateAccessibility( this, 0, QAccessible::NameChanged ); +#endif +} + +void KDHorizontalLine::calculateFrame() { + mLenVisible = mTitle.length(); +#if 0 + if ( mLenVisible ) { + const QFontMetrics fm = fontMetrics(); + while ( mLenVisible ) { + const int tw = fm.width( mTitle, mLenVisible ) + 4*fm.width(QChar(' ')); + if ( tw < width() ) + break; + mLenVisible--; + } + qDebug( "mLenVisible = %d (of %d)", mLenVisible, mTitle.length() ); + if ( mLenVisible ) { // but do we also have a visible label? + QRect r = rect(); + const int va = style().styleHint( QStyle::SH_GroupBox_TextLabelVerticalAlignment, this ); + if( va & AlignVCenter ) + r.setTop( fm.height() / 2 ); // frame rect should be + else if( va & AlignTop ) + r.setTop( fm.ascent() ); + setFrameRect( r ); // smaller than client rect + return; + } + } + // no visible label + setFrameRect( QRect(0,0,0,0) ); // then use client rect +#endif +} + +QSizePolicy KDHorizontalLine::sizePolicy() const { + return QSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed ); +} + +QSize KDHorizontalLine::sizeHint() const { + return minimumSizeHint(); +} + +QSize KDHorizontalLine::minimumSizeHint() const { + const int w = fontMetrics().width( mTitle, mLenVisible ) + + fontMetrics().width( QChar( ' ' ) ); + const int h = fontMetrics().height(); + return QSize( QMAX( w, indentHint() ), h ).expandedTo( qApp->globalStrut() ); +} + +void KDHorizontalLine::paintEvent( QPaintEvent * e ) { + QPainter paint( this ); + + if ( mLenVisible ) { // draw title + const QFontMetrics & fm = paint.fontMetrics(); + const int h = fm.height(); + const int tw = fm.width( mTitle, mLenVisible ) + fm.width(QChar(' ')); + int x; + if ( mAlign & AlignHCenter ) // center alignment + x = frameRect().width()/2 - tw/2; + else if ( mAlign & AlignRight ) // right alignment + x = frameRect().width() - tw; + else if ( mAlign & AlignLeft ) // left alignment + x = 0; + else { // auto align + if( QApplication::reverseLayout() ) + x = frameRect().width() - tw; + else + x = 0; + } + QRect r( x, 0, tw, h ); + int va = style().styleHint( QStyle::SH_GroupBox_TextLabelVerticalAlignment, this ); + if ( va & AlignTop ) + r.moveBy( 0, fm.descent() ); + const QColor pen( (QRgb) style().styleHint( QStyle::SH_GroupBox_TextLabelColor, this ) ); +#if QT_VERSION >= 0x030300 + if ( !style().styleHint( QStyle::SH_UnderlineAccelerator, this ) ) + va |= NoAccel; +#endif + style().drawItem( &paint, r, ShowPrefix | AlignHCenter | va, colorGroup(), + isEnabled(), 0, mTitle, -1, ownPalette() ? 0 : &pen ); + paint.setClipRegion( e->region().subtract( r ) ); // clip everything but title + } + drawFrame( &paint ); + drawContents( &paint ); +} + +// static +int KDHorizontalLine::indentHint() { + return 30; +} + +#include "kdhorizontalline.moc" diff --git a/certmanager/lib/ui/kdhorizontalline.h b/certmanager/lib/ui/kdhorizontalline.h new file mode 100644 index 000000000..a79682ebd --- /dev/null +++ b/certmanager/lib/ui/kdhorizontalline.h @@ -0,0 +1,82 @@ +/* -*- Mode: C++ -*- + KD Tools - a set of useful widgets for Qt +*/ + +/**************************************************************************** +** Copyright (C) 2005 Klarälvdalens Datakonsult AB. All rights reserved. +** +** This file is part of the KD Tools library. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid commercial KD Tools licenses may use this file in +** accordance with the KD Tools Commercial License Agreement provided with +** the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.klaralvdalens-datakonsult.se/?page=products for +** information about KD Tools Commercial License Agreements. +** +** Contact info@klaralvdalens-datakonsult.se if any conditions of this +** licensing are not clear to you. +** +** In addition, as a special exception, the copyright holders give +** permission to link the code of this program with any edition of the +** Qt library by Trolltech AS, Norway (or with modified versions of Qt +** that use the same license as Qt), and distribute linked +** combinations including the two. You must obey the GNU General +** Public License in all respects for all of the code used other than +** Qt. If you modify this file, you may extend this exception to your +** version of the file, but you are not obligated to do so. If you do +** not wish to do so, delete this exception statement from your +** version. +** +**********************************************************************/ + +#ifndef __KDTOOLS__KDHORIZONTALLINE_H__ +#define __KDTOOLS__KDHORIZONTALLINE_H__ + +#include <qframe.h> +#include <qstring.h> + +class KDHorizontalLine : public QFrame { + Q_OBJECT + Q_PROPERTY( QString title READ title WRITE setTitle ) +public: + KDHorizontalLine( QWidget * parent=0, const char * name=0, WFlags f=0 ); + KDHorizontalLine( const QString & title, QWidget * parent=0, const char * name=0, WFlags f=0 ); + ~KDHorizontalLine(); + + QString title() const { return mTitle; } + + /*! \reimp to hard-code the frame shape */ + void setFrameStyle( int style ); + + QSize sizeHint() const; + QSize minimumSizeHint() const; + QSizePolicy sizePolicy() const; + + static int indentHint(); + +public slots: + virtual void setTitle( const QString & title ); + +protected: + void paintEvent( QPaintEvent * ); + +private: + void calculateFrame(); + +private: + QString mTitle; + Qt::AlignmentFlags mAlign; + int mLenVisible; +}; + +#endif /* __KDTOOLS__KDHORIZONTALLINE_H__ */ + diff --git a/certmanager/lib/ui/keyapprovaldialog.cpp b/certmanager/lib/ui/keyapprovaldialog.cpp new file mode 100644 index 000000000..7af85a0bb --- /dev/null +++ b/certmanager/lib/ui/keyapprovaldialog.cpp @@ -0,0 +1,227 @@ +/* -*- c++ -*- + keyapprovaldialog.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Based on kpgpui.h + Copyright (C) 2001,2002 the KPGP authors + See file libkdenetwork/AUTHORS.kpgp for details + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "keyapprovaldialog.h" + +#include "keyrequester.h" + +#include <cryptplugfactory.h> +#include <kleo/cryptobackend.h> + +#include <klocale.h> +#include <kglobalsettings.h> +#include <kseparator.h> + +#include <qstringlist.h> +#include <qframe.h> +#include <qlayout.h> +#include <qlabel.h> +#include <qcombobox.h> +#include <qscrollview.h> +#include <qpushbutton.h> + +#include <gpgmepp/key.h> + +#include <assert.h> + +static Kleo::EncryptionPreference cb2pref( int i ) { + switch ( i ) { + default: + case 0: return Kleo::UnknownPreference; + case 1: return Kleo::NeverEncrypt; + case 2: return Kleo::AlwaysEncrypt; + case 3: return Kleo::AlwaysEncryptIfPossible; + case 4: return Kleo::AlwaysAskForEncryption; + case 5: return Kleo::AskWheneverPossible; + } +} + +static int pref2cb( Kleo::EncryptionPreference p ) { + switch ( p ) { + default: return 0; + case Kleo::NeverEncrypt: return 1; + case Kleo::AlwaysEncrypt: return 2; + case Kleo::AlwaysEncryptIfPossible: return 3; + case Kleo::AlwaysAskForEncryption: return 4; + case Kleo::AskWheneverPossible: return 5; + } +} + +static QStringList preferencesStrings() { + return QStringList() << i18n("<none>") + << i18n("Never Encrypt with This Key") + << i18n("Always Encrypt with This Key") + << i18n("Encrypt Whenever Encryption is Possible") + << i18n("Always Ask") + << i18n("Ask Whenever Encryption is Possible"); +} + + +struct Kleo::KeyApprovalDialog::Private { + Private() : selfRequester( 0 ), prefsChanged( false ) {} + + Kleo::KeyRequester * selfRequester; + QStringList addresses; + std::vector<Kleo::KeyRequester*> requesters; + std::vector<QComboBox*> preferences; + bool prefsChanged; +}; + +Kleo::KeyApprovalDialog::KeyApprovalDialog( const std::vector<Item> & recipients, + const std::vector<GpgME::Key> & sender, + QWidget * parent, const char * name, + bool modal ) + : KDialogBase( parent, name, modal, i18n("Encryption Key Approval"), Ok|Cancel, Ok ), + d( 0 ) +{ + assert( !recipients.empty() ); + + d = new Private(); + + QFrame *page = makeMainWidget(); + QVBoxLayout * vlay = new QVBoxLayout( page, 0, spacingHint() ); + + vlay->addWidget( new QLabel( i18n("The following keys will be used for encryption:"), page ) ); + + QScrollView * sv = new QScrollView( page ); + sv->setResizePolicy( QScrollView::AutoOneFit ); + vlay->addWidget( sv ); + + QWidget * view = new QWidget( sv->viewport() ); + + QGridLayout * glay = new QGridLayout( view, 3, 2, marginHint(), spacingHint() ); + glay->setColStretch( 1, 1 ); + sv->addChild( view ); + + int row = -1; + + if ( !sender.empty() ) { + ++row; + glay->addWidget( new QLabel( i18n("Your keys:"), view ), row, 0 ); + d->selfRequester = new EncryptionKeyRequester( true, EncryptionKeyRequester::AllProtocols, view ); + d->selfRequester->setKeys( sender ); + glay->addWidget( d->selfRequester, row, 1 ); + ++row; + glay->addMultiCellWidget( new KSeparator( Horizontal, view ), row, row, 0, 1 ); + } + + const QStringList prefs = preferencesStrings(); + + for ( std::vector<Item>::const_iterator it = recipients.begin() ; it != recipients.end() ; ++it ) { + ++row; + glay->addWidget( new QLabel( i18n("Recipient:"), view ), row, 0 ); + glay->addWidget( new QLabel( it->address, view ), row, 1 ); + d->addresses.push_back( it->address ); + + ++row; + glay->addWidget( new QLabel( i18n("Encryption keys:"), view ), row, 0 ); + KeyRequester * req = new EncryptionKeyRequester( true, EncryptionKeyRequester::AllProtocols, view ); + req->setKeys( it->keys ); + glay->addWidget( req, row, 1 ); + d->requesters.push_back( req ); + + ++row; + glay->addWidget( new QLabel( i18n("Encryption preference:"), view ), row, 0 ); + QComboBox * cb = new QComboBox( false, view ); + cb->insertStringList( prefs ); + glay->addWidget( cb, row, 1 ); + cb->setCurrentItem( pref2cb( it->pref ) ); + connect( cb, SIGNAL(activated(int)), SLOT(slotPrefsChanged()) ); + d->preferences.push_back( cb ); + } + + // calculate the optimal width for the dialog + const int dialogWidth = marginHint() + + sv->frameWidth() + + view->sizeHint().width() + + sv->verticalScrollBar()->sizeHint().width() + + sv->frameWidth() + + marginHint() + + 2; + // calculate the optimal height for the dialog + const int dialogHeight = marginHint() + + fontMetrics().height() + + spacingHint() + + sv->frameWidth() + + view->sizeHint().height() + + sv->horizontalScrollBar()->sizeHint().height() + + sv->frameWidth() + + spacingHint() + + actionButton( KDialogBase::Cancel )->sizeHint().height() + + marginHint() + + 2; + + // don't make the dialog too large + const QRect desk = KGlobalSettings::desktopGeometry( this ); + setInitialSize( QSize( kMin( dialogWidth, 3 * desk.width() / 4 ), + kMin( dialogHeight, 7 * desk.height() / 8 ) ) ); +} + +Kleo::KeyApprovalDialog::~KeyApprovalDialog() { + delete d; d = 0; +} + +std::vector<GpgME::Key> Kleo::KeyApprovalDialog::senderKeys() const { + return d->selfRequester ? d->selfRequester->keys() : std::vector<GpgME::Key>() ; +} + +std::vector<Kleo::KeyApprovalDialog::Item> Kleo::KeyApprovalDialog::items() const { + assert( d->requesters.size() == d->addresses.size() ); + assert( d->requesters.size() == d->preferences.size() ); + + std::vector<Item> result; + result.reserve( d->requesters.size() ); + QStringList::const_iterator ait = d->addresses.begin(); + std::vector<KeyRequester*>::const_iterator rit = d->requesters.begin(); + std::vector<QComboBox*>::const_iterator cit = d->preferences.begin(); + while ( ait != d->addresses.end() ) + result.push_back( Item( *ait++, (*rit++)->keys(), cb2pref( (*cit++)->currentItem() ) ) ); + return result; +} + +bool Kleo::KeyApprovalDialog::preferencesChanged() const { + return d->prefsChanged; +} + +void Kleo::KeyApprovalDialog::slotPrefsChanged() { + d->prefsChanged = true; +} + +#include "keyapprovaldialog.moc" diff --git a/certmanager/lib/ui/keyapprovaldialog.h b/certmanager/lib/ui/keyapprovaldialog.h new file mode 100644 index 000000000..224530a71 --- /dev/null +++ b/certmanager/lib/ui/keyapprovaldialog.h @@ -0,0 +1,92 @@ +/* -*- c++ -*- + keyselectiondialog.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Based on kpgpui.h + Copyright (C) 2001,2002 the KPGP authors + See file libkdenetwork/AUTHORS.kpgp for details + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_KEYAPPROVALDIALOG_H__ +#define __KLEO_KEYAPPROVALDIALOG_H__ + +#include <kleo/enum.h> + +#include <kdialogbase.h> +#include <kdepimmacros.h> + +#include <kpgpkey.h> // for EncryptPref +#include <gpgmepp/key.h> + +#include <vector> + +namespace GpgME { + class Key; +} + +class QStringList; + +namespace Kleo { + + class KDE_EXPORT KeyApprovalDialog : public KDialogBase { + Q_OBJECT + public: + struct Item { + Item() : pref( UnknownPreference ) {} + Item( const QString & a, const std::vector<GpgME::Key> & k, + EncryptionPreference p=UnknownPreference ) + : address( a ), keys( k ), pref( p ) {} + QString address; + std::vector<GpgME::Key> keys; + EncryptionPreference pref; + }; + + KeyApprovalDialog( const std::vector<Item> & recipients, + const std::vector<GpgME::Key> & sender, + QWidget * parent=0, const char * name=0, + bool modal=true ); + ~KeyApprovalDialog(); + + std::vector<Item> items() const; + std::vector<GpgME::Key> senderKeys() const; + + bool preferencesChanged() const; + + private slots: + void slotPrefsChanged(); + + private: + class Private; + Private * d; + }; + +} // namespace Kleo + +#endif // __KLEO_KEYAPPROVALDIALOG_H__ diff --git a/certmanager/lib/ui/keylistview.cpp b/certmanager/lib/ui/keylistview.cpp new file mode 100644 index 000000000..98534a4b7 --- /dev/null +++ b/certmanager/lib/ui/keylistview.cpp @@ -0,0 +1,869 @@ +/* + keylistview.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "keylistview.h" + +#include <kdebug.h> + +#include <qfontmetrics.h> +#include <qtooltip.h> +#include <qrect.h> +#include <qheader.h> +#include <qpoint.h> +#include <qptrlist.h> +#include <qpainter.h> +#include <qfont.h> +#include <qcolor.h> +#include <qtimer.h> +#include <qcstring.h> + +#include <gpgmepp/key.h> + +#include <vector> +#include <map> + +#include <assert.h> + +static const int updateDelayMilliSecs = 500; + +namespace { + + class ItemToolTip : public QToolTip { + public: + ItemToolTip( Kleo::KeyListView * parent ); + protected: + void maybeTip( const QPoint & p ); + private: + Kleo::KeyListView * mKeyListView; + }; + + ItemToolTip::ItemToolTip( Kleo::KeyListView * parent ) + : QToolTip( parent->viewport() ), mKeyListView( parent ) {} + + void ItemToolTip::maybeTip( const QPoint & p ) { + if ( !mKeyListView ) + return; + + const QListViewItem * item = mKeyListView->itemAt( p ); + if ( !item ) + return; + + const QRect itemRect = mKeyListView->itemRect( item ); + if ( !itemRect.isValid() ) + return; + + const int col = mKeyListView->header()->sectionAt( p.x() ); + if ( col == -1 ) + return; + + const QRect headerRect = mKeyListView->header()->sectionRect( col ); + if ( !headerRect.isValid() ) + return; + + const QRect cellRect( headerRect.left(), itemRect.top(), + headerRect.width(), itemRect.height() ); + + QString tipStr; + if ( const Kleo::KeyListViewItem * klvi = Kleo::lvi_cast<Kleo::KeyListViewItem>( item ) ) + tipStr = klvi->toolTip( col ); + else + tipStr = item->text( col ) ; + + if ( !tipStr.isEmpty() ) + tip( cellRect, tipStr ); + } + +} // anon namespace + +struct Kleo::KeyListView::Private { + Private() : updateTimer( 0 ), itemToolTip( 0 ) {} + + std::vector<GpgME::Key> keyBuffer; + QTimer * updateTimer; + QToolTip * itemToolTip; + std::map<QCString,KeyListViewItem*> itemMap; +}; + +// a list of signals where we want to replace QListViewItem with +// Kleo:KeyListViewItem: +static const struct { + const char * source; + const char * target; +} signalReplacements[] = { + { SIGNAL(doubleClicked(QListViewItem*,const QPoint&,int)), + SLOT(slotEmitDoubleClicked(QListViewItem*,const QPoint&,int)) }, + { SIGNAL(returnPressed(QListViewItem*)), + SLOT(slotEmitReturnPressed(QListViewItem*)) }, + { SIGNAL(selectionChanged(QListViewItem*)), + SLOT(slotEmitSelectionChanged(QListViewItem*)) }, + { SIGNAL(contextMenu(KListView*, QListViewItem*,const QPoint&)), + SLOT(slotEmitContextMenu(KListView*, QListViewItem*,const QPoint&)) }, +}; +static const int numSignalReplacements = sizeof signalReplacements / sizeof *signalReplacements; + + +Kleo::KeyListView::KeyListView( const ColumnStrategy * columnStrategy, const DisplayStrategy * displayStrategy, QWidget * parent, const char * name, WFlags f ) + : KListView( parent, name ), + mColumnStrategy( columnStrategy ), + mDisplayStrategy ( displayStrategy ), + mHierarchical( false ) +{ + setWFlags( f ); + + d = new Private(); + + d->updateTimer = new QTimer( this ); + connect( d->updateTimer, SIGNAL(timeout()), SLOT(slotUpdateTimeout()) ); + + if ( !columnStrategy ) { + kdWarning(5150) << "Kleo::KeyListView: need a column strategy to work with!" << endl; + return; + } + + const QFontMetrics fm = fontMetrics(); + + for ( int col = 0 ; !columnStrategy->title( col ).isEmpty() ; ++col ) { + addColumn( columnStrategy->title( col ), columnStrategy->width( col, fm ) ); + setColumnWidthMode( col, columnStrategy->widthMode( col ) ); + } + + setAllColumnsShowFocus( true ); + setShowToolTips( false ); // we do it instead... + + for ( int i = 0 ; i < numSignalReplacements ; ++i ) + connect( this, signalReplacements[i].source, signalReplacements[i].target ); + + QToolTip::remove( this ); + QToolTip::remove( viewport() ); // make double sure :) + d->itemToolTip = new ItemToolTip( this ); +} + +Kleo::KeyListView::~KeyListView() { + d->updateTimer->stop(); + // need to clear here, since in ~QListView, our children won't have + // a valid listView() pointing to us anymore, and their dtors try to + // unregister from us. + clear(); + assert( d->itemMap.size() == 0 ); + // need to delete the tooltip ourselves, as ~QToolTip isn't virtual :o + delete d->itemToolTip; d->itemToolTip = 0; + delete d; d = 0; + delete mColumnStrategy; mColumnStrategy = 0; + delete mDisplayStrategy; mDisplayStrategy = 0; +} + +void Kleo::KeyListView::insertItem( QListViewItem * qlvi ) { + //kdDebug() << "Kleo::KeyListView::insertItem( " << qlvi << " )" << endl; + KListView::insertItem( qlvi ); + if ( KeyListViewItem * item = lvi_cast<KeyListViewItem>( qlvi ) ) + registerItem( item ); +} + +void Kleo::KeyListView::takeItem( QListViewItem * qlvi ) { + //kdDebug() << "Kleo::KeyListView::takeItem( " << qlvi << " )" << endl; + if ( KeyListViewItem * item = lvi_cast<KeyListViewItem>( qlvi ) ) + deregisterItem( item ); + KListView::takeItem( qlvi ); +} + + +void Kleo::KeyListView::setHierarchical( bool hier ) { + if ( hier == mHierarchical ) + return; + mHierarchical = hier; + if ( hier ) + gatherScattered(); + else + scatterGathered( firstChild() ); +} + +void Kleo::KeyListView::slotAddKey( const GpgME::Key & key ) { + if ( key.isNull() ) + return; + + d->keyBuffer.push_back( key ); + if ( !d->updateTimer->isActive() ) + d->updateTimer->start( updateDelayMilliSecs, true /* single-shot */ ); +} + +void Kleo::KeyListView::slotUpdateTimeout() { + if ( d->keyBuffer.empty() ) + return; + + const bool wasUpdatesEnabled = viewport()->isUpdatesEnabled(); + if ( wasUpdatesEnabled ) + viewport()->setUpdatesEnabled( false ); + kdDebug( 5150 ) << "Kleo::KeyListView::slotUpdateTimeout(): processing " + << d->keyBuffer.size() << " items en block" << endl; + if ( hierarchical() ) { + for ( std::vector<GpgME::Key>::const_iterator it = d->keyBuffer.begin() ; it != d->keyBuffer.end() ; ++it ) + doHierarchicalInsert( *it ); + gatherScattered(); + } else { + for ( std::vector<GpgME::Key>::const_iterator it = d->keyBuffer.begin() ; it != d->keyBuffer.end() ; ++it ) + (void)new KeyListViewItem( this, *it ); + } + if ( wasUpdatesEnabled ) + viewport()->setUpdatesEnabled( true ); + d->keyBuffer.clear(); +} + +void Kleo::KeyListView::clear() { + d->updateTimer->stop(); + d->keyBuffer.clear(); + KListView::clear(); +} + +void Kleo::KeyListView::registerItem( KeyListViewItem * item ) { + //kdDebug() << "registerItem( " << item << " )" << endl; + if ( !item ) + return; + const QCString fpr = item->key().primaryFingerprint(); + if ( !fpr.isEmpty() ) + d->itemMap.insert( std::make_pair( fpr, item ) ); +} + +void Kleo::KeyListView::deregisterItem( const KeyListViewItem * item ) { + //kdDebug() << "deregisterItem( KeyLVI: " << item << " )" << endl; + if ( !item ) + return; + std::map<QCString,KeyListViewItem*>::iterator it + = d->itemMap.find( item->key().primaryFingerprint() ); + if ( it == d->itemMap.end() ) + return; + Q_ASSERT( it->second == item ); + if ( it->second != item ) + return; + d->itemMap.erase( it ); +} + +void Kleo::KeyListView::doHierarchicalInsert( const GpgME::Key & key ) { + const QCString fpr = key.primaryFingerprint(); + if ( fpr.isEmpty() ) + return; + KeyListViewItem * item = 0; + if ( !key.isRoot() ) + if ( KeyListViewItem * parent = itemByFingerprint( key.chainID() ) ) { + item = new KeyListViewItem( parent, key ); + parent->setOpen( true ); + } + if ( !item ) + item = new KeyListViewItem( this, key ); // top-level (for now) + + d->itemMap.insert( std::make_pair( fpr, item ) ); +} + +void Kleo::KeyListView::gatherScattered() { + KeyListViewItem * item = firstChild(); + while ( item ) { + KeyListViewItem * cur = item; + item = item->nextSibling(); + if ( cur->key().isRoot() ) + continue; + if ( KeyListViewItem * parent = itemByFingerprint( cur->key().chainID() ) ) { + // found a new parent... + // ### todo: optimize by suppressing removing/adding the item to the itemMap... + takeItem( cur ); + parent->insertItem( cur ); + parent->setOpen( true ); + } + } +} + +void Kleo::KeyListView::scatterGathered( QListViewItem * start ) { + QListViewItem * item = start; + while ( item ) { + QListViewItem * cur = item; + item = item->nextSibling(); + + scatterGathered( cur->firstChild() ); + assert( cur->childCount() == 0 ); + + // ### todo: optimize by suppressing removing/adding the item to the itemMap... + if ( cur->parent() ) + cur->parent()->takeItem( cur ); + else + takeItem( cur ); + insertItem( cur ); + } +} + +Kleo::KeyListViewItem * Kleo::KeyListView::itemByFingerprint( const QCString & s ) const { + if ( s.isEmpty() ) + return 0; + const std::map<QCString,KeyListViewItem*>::const_iterator it = d->itemMap.find( s ); + if ( it == d->itemMap.end() ) + return 0; + return it->second; +} + + +void Kleo::KeyListView::slotRefreshKey( const GpgME::Key & key ) { + const char * fpr = key.primaryFingerprint(); + if ( !fpr ) + return; + if ( KeyListViewItem * item = itemByFingerprint( fpr ) ) + item->setKey ( key ); + else + // none found -> add it + slotAddKey( key ); +} + +// slots for the emission of covariant signals: + +void Kleo::KeyListView::slotEmitDoubleClicked( QListViewItem * item, const QPoint & p, int col ) { + if ( !item || lvi_cast<KeyListViewItem>( item ) ) + emit doubleClicked( static_cast<KeyListViewItem*>( item ), p, col ); +} + +void Kleo::KeyListView::slotEmitReturnPressed( QListViewItem * item ) { + if ( !item || lvi_cast<KeyListViewItem>( item ) ) + emit returnPressed( static_cast<KeyListViewItem*>( item ) ); +} + +void Kleo::KeyListView::slotEmitSelectionChanged( QListViewItem * item ) { + if ( !item || lvi_cast<KeyListViewItem>( item ) ) + emit selectionChanged( static_cast<KeyListViewItem*>( item ) ); +} + +void Kleo::KeyListView::slotEmitContextMenu( KListView*, QListViewItem * item, const QPoint & p ) { + if ( !item || lvi_cast<KeyListViewItem>( item ) ) + emit contextMenu( static_cast<KeyListViewItem*>( item ), p ); +} + +// +// +// KeyListViewItem +// +// + +Kleo::KeyListViewItem::KeyListViewItem( KeyListView * parent, const GpgME::Key & key ) + : QListViewItem( parent ) +{ + setKey( key ); +} + +Kleo::KeyListViewItem::KeyListViewItem( KeyListView * parent, KeyListViewItem * after, const GpgME::Key & key ) + : QListViewItem( parent, after ) +{ + setKey( key ); +} + +Kleo::KeyListViewItem::KeyListViewItem( KeyListViewItem * parent, const GpgME::Key & key ) + : QListViewItem( parent ) +{ + setKey( key ); +} + +Kleo::KeyListViewItem::KeyListViewItem( KeyListViewItem * parent, KeyListViewItem * after, const GpgME::Key & key ) + : QListViewItem( parent, after ) +{ + setKey( key ); +} + +Kleo::KeyListViewItem::~KeyListViewItem() { + // delete the children first... When children are deleted in the + // QLVI dtor, they don't have listView() anymore, thus they don't + // call deregister( this ), leading to stale entries in the + // itemMap... + while ( QListViewItem * item = firstChild() ) + delete item; + // better do this here, too, since deletion is top-down and thus + // we're deleted when our parent item is no longer a + // KeyListViewItem, but a mere QListViewItem, so our takeItem() + // overload is gone by that time... + if ( KeyListView * lv = listView() ) + lv->deregisterItem( this ); +} + +void Kleo::KeyListViewItem::setKey( const GpgME::Key & key ) { + KeyListView * lv = listView(); + if ( lv ) + lv->deregisterItem( this ); + mKey = key; + if ( lv ) + lv->registerItem( this ); + + // the ColumnStrategy operations might be very slow, so cache their + // result here, where we're non-const :) + const Kleo::KeyListView::ColumnStrategy * cs = lv ? lv->columnStrategy() : 0 ; + if ( !cs ) + return; + const int numCols = lv ? lv->columns() : 0 ; + for ( int i = 0 ; i < numCols ; ++i ) { + setText( i, cs->text( key, i ) ); + if ( const QPixmap * pix = cs->pixmap( key, i ) ) + setPixmap( i, *pix ); + } + repaint(); +} + +QString Kleo::KeyListViewItem::toolTip( int col ) const { + return listView() && listView()->columnStrategy() + ? listView()->columnStrategy()->toolTip( key(), col ) + : QString::null ; +} + +int Kleo::KeyListViewItem::compare( QListViewItem * item, int col, bool ascending ) const { + if ( !item || item->rtti() != RTTI || !listView() || !listView()->columnStrategy() ) + return QListViewItem::compare( item, col, ascending ); + KeyListViewItem * that = static_cast<KeyListViewItem*>( item ); + return listView()->columnStrategy()->compare( this->key(), that->key(), col ); +} + +void Kleo::KeyListViewItem::paintCell( QPainter * p, const QColorGroup & cg, int column, int width, int alignment ) { + const KeyListView::DisplayStrategy * ds = listView() ? listView()->displayStrategy() : 0 ; + if ( !ds ) { + QListViewItem::paintCell( p, cg, column, width, alignment ); + return; + } + const QColor fg = ds->keyForeground( key(), cg.text() ); + const QColor bg = ds->keyBackground( key(), cg.base() ); + const QFont f = ds->keyFont( key(), p->font() ); + + QColorGroup _cg = cg; + p->setFont( f ); + _cg.setColor( QColorGroup::Text, fg ); + _cg.setColor( QColorGroup::Base, bg ); + + QListViewItem::paintCell( p, _cg, column, width, alignment ); +} + +void Kleo::KeyListViewItem::insertItem( QListViewItem * qlvi ) { + //kdDebug() << "Kleo::KeyListViewItem::insertItem( " << qlvi << " )" << endl; + QListViewItem::insertItem( qlvi ); + if ( KeyListViewItem * item = lvi_cast<KeyListViewItem>( qlvi ) ) + listView()->registerItem( item ); +} + +void Kleo::KeyListViewItem::takeItem( QListViewItem * qlvi ) { + //kdDebug() << "Kleo::KeyListViewItem::takeItem( " << qlvi << " )" << endl; + if ( KeyListViewItem * item = lvi_cast<KeyListViewItem>( qlvi ) ) + listView()->deregisterItem( item ); + QListViewItem::takeItem( qlvi ); +} + + +// +// +// SubkeyKeyListViewItem +// +// + +Kleo::SubkeyKeyListViewItem::SubkeyKeyListViewItem( KeyListView * parent, const GpgME::Subkey & subkey ) + : KeyListViewItem( parent, subkey.parent() ), mSubkey( subkey ) +{ + +} + +Kleo::SubkeyKeyListViewItem::SubkeyKeyListViewItem( KeyListView * parent, KeyListViewItem * after, const GpgME::Subkey & subkey ) + : KeyListViewItem( parent, after, subkey.parent() ), mSubkey( subkey ) +{ + +} + +Kleo::SubkeyKeyListViewItem::SubkeyKeyListViewItem( KeyListViewItem * parent, const GpgME::Subkey & subkey ) + : KeyListViewItem( parent, subkey.parent() ), mSubkey( subkey ) +{ + +} + +Kleo::SubkeyKeyListViewItem::SubkeyKeyListViewItem( KeyListViewItem * parent, KeyListViewItem * after, const GpgME::Subkey & subkey ) + : KeyListViewItem( parent, after, subkey.parent() ), mSubkey( subkey ) +{ + +} + +void Kleo::SubkeyKeyListViewItem::setSubkey( const GpgME::Subkey & subkey ) { + mSubkey = subkey; + setKey( subkey.parent() ); +} + +QString Kleo::SubkeyKeyListViewItem::text( int col ) const { + return listView() && listView()->columnStrategy() + ? listView()->columnStrategy()->subkeyText( subkey(), col ) + : QString::null ; +} + +QString Kleo::SubkeyKeyListViewItem::toolTip( int col ) const { + return listView() && listView()->columnStrategy() + ? listView()->columnStrategy()->subkeyToolTip( subkey(), col ) + : QString::null ; +} + +const QPixmap * Kleo::SubkeyKeyListViewItem::pixmap( int col ) const { + return listView() && listView()->columnStrategy() + ? listView()->columnStrategy()->subkeyPixmap( subkey(), col ) : 0 ; +} + +int Kleo::SubkeyKeyListViewItem::compare( QListViewItem * item, int col, bool ascending ) const { + if ( !item || item->rtti() != RTTI || !listView() || !listView()->columnStrategy() ) + return KeyListViewItem::compare( item, col, ascending ); + SubkeyKeyListViewItem * that = static_cast<SubkeyKeyListViewItem*>( item ); + return listView()->columnStrategy()->subkeyCompare( this->subkey(), that->subkey(), col ); +} + +void Kleo::SubkeyKeyListViewItem::paintCell( QPainter * p, const QColorGroup & cg, int column, int width, int alignment ) { + const KeyListView::DisplayStrategy * ds = listView() ? listView()->displayStrategy() : 0 ; + if ( !ds ) { + QListViewItem::paintCell( p, cg, column, width, alignment ); + return; + } + const QColor fg = ds->subkeyForeground( subkey(), cg.text() ); + const QColor bg = ds->subkeyBackground( subkey(), cg.base() ); + const QFont f = ds->subkeyFont( subkey(), p->font() ); + + QColorGroup _cg = cg; + p->setFont( f ); + _cg.setColor( QColorGroup::Text, fg ); + _cg.setColor( QColorGroup::Base, bg ); + + QListViewItem::paintCell( p, _cg, column, width, alignment ); +} + + +// +// +// UserIDKeyListViewItem +// +// + +Kleo::UserIDKeyListViewItem::UserIDKeyListViewItem( KeyListView * parent, const GpgME::UserID & userID ) + : KeyListViewItem( parent, userID.parent() ), mUserID( userID ) +{ + +} + +Kleo::UserIDKeyListViewItem::UserIDKeyListViewItem( KeyListView * parent, KeyListViewItem * after, const GpgME::UserID & userID ) + : KeyListViewItem( parent, after, userID.parent() ), mUserID( userID ) +{ + +} + +Kleo::UserIDKeyListViewItem::UserIDKeyListViewItem( KeyListViewItem * parent, const GpgME::UserID & userID ) + : KeyListViewItem( parent, userID.parent() ), mUserID( userID ) +{ + +} + +Kleo::UserIDKeyListViewItem::UserIDKeyListViewItem( KeyListViewItem * parent, KeyListViewItem * after, const GpgME::UserID & userID ) + : KeyListViewItem( parent, after, userID.parent() ), mUserID( userID ) +{ + +} + +void Kleo::UserIDKeyListViewItem::setUserID( const GpgME::UserID & userID ) { + mUserID = userID; + setKey( userID.parent() ); +} + +QString Kleo::UserIDKeyListViewItem::text( int col ) const { + return listView() && listView()->columnStrategy() + ? listView()->columnStrategy()->userIDText( userID(), col ) + : QString::null ; +} + +QString Kleo::UserIDKeyListViewItem::toolTip( int col ) const { + return listView() && listView()->columnStrategy() + ? listView()->columnStrategy()->userIDToolTip( userID(), col ) + : QString::null ; +} + +const QPixmap * Kleo::UserIDKeyListViewItem::pixmap( int col ) const { + return listView() && listView()->columnStrategy() + ? listView()->columnStrategy()->userIDPixmap( userID(), col ) : 0 ; +} + +int Kleo::UserIDKeyListViewItem::compare( QListViewItem * item, int col, bool ascending ) const { + if ( !item || item->rtti() != RTTI || !listView() || !listView()->columnStrategy() ) + return KeyListViewItem::compare( item, col, ascending ); + UserIDKeyListViewItem * that = static_cast<UserIDKeyListViewItem*>( item ); + return listView()->columnStrategy()->userIDCompare( this->userID(), that->userID(), col ); +} + + +void Kleo::UserIDKeyListViewItem::paintCell( QPainter * p, const QColorGroup & cg, int column, int width, int alignment ) { + const KeyListView::DisplayStrategy * ds = listView() ? listView()->displayStrategy() : 0 ; + if ( !ds ) { + QListViewItem::paintCell( p, cg, column, width, alignment ); + return; + } + const QColor fg = ds->useridForeground( userID(), cg.text() ); + const QColor bg = ds->useridBackground( userID(), cg.base() ); + const QFont f = ds->useridFont( userID(), p->font() ); + + QColorGroup _cg = cg; + p->setFont( f ); + _cg.setColor( QColorGroup::Text, fg ); + _cg.setColor( QColorGroup::Base, bg ); + + QListViewItem::paintCell( p, _cg, column, width, alignment ); +} + + +// +// +// SignatureKeyListViewItem +// +// + +Kleo::SignatureKeyListViewItem::SignatureKeyListViewItem( KeyListView * parent, const GpgME::UserID::Signature & signature ) + : KeyListViewItem( parent, signature.parent().parent() ), mSignature( signature ) +{ + +} + +Kleo::SignatureKeyListViewItem::SignatureKeyListViewItem( KeyListView * parent, KeyListViewItem * after, const GpgME::UserID::Signature & signature ) + : KeyListViewItem( parent, after, signature.parent().parent() ), mSignature( signature ) +{ + +} + +Kleo::SignatureKeyListViewItem::SignatureKeyListViewItem( KeyListViewItem * parent, const GpgME::UserID::Signature & signature ) + : KeyListViewItem( parent, signature.parent().parent() ), mSignature( signature ) +{ + +} + +Kleo::SignatureKeyListViewItem::SignatureKeyListViewItem( KeyListViewItem * parent, KeyListViewItem * after, const GpgME::UserID::Signature & signature ) + : KeyListViewItem( parent, after, signature.parent().parent() ), mSignature( signature ) +{ + +} + +void Kleo::SignatureKeyListViewItem::setSignature( const GpgME::UserID::Signature & signature ) { + mSignature = signature; + setKey( signature.parent().parent() ); +} + +QString Kleo::SignatureKeyListViewItem::text( int col ) const { + return listView() && listView()->columnStrategy() + ? listView()->columnStrategy()->signatureText( signature(), col ) + : QString::null ; +} + +QString Kleo::SignatureKeyListViewItem::toolTip( int col ) const { + return listView() && listView()->columnStrategy() + ? listView()->columnStrategy()->signatureToolTip( signature(), col ) + : QString::null ; +} + +const QPixmap * Kleo::SignatureKeyListViewItem::pixmap( int col ) const { + return listView() && listView()->columnStrategy() + ? listView()->columnStrategy()->signaturePixmap( signature(), col ) : 0 ; +} + +int Kleo::SignatureKeyListViewItem::compare( QListViewItem * item, int col, bool ascending ) const { + if ( !item || item->rtti() != RTTI || !listView() || !listView()->columnStrategy() ) + return KeyListViewItem::compare( item, col, ascending ); + SignatureKeyListViewItem * that = static_cast<SignatureKeyListViewItem*>( item ); + return listView()->columnStrategy()->signatureCompare( this->signature(), that->signature(), col ); +} + +void Kleo::SignatureKeyListViewItem::paintCell( QPainter * p, const QColorGroup & cg, int column, int width, int alignment ) { + const KeyListView::DisplayStrategy * ds = listView() ? listView()->displayStrategy() : 0 ; + if ( !ds ) { + QListViewItem::paintCell( p, cg, column, width, alignment ); + return; + } + const QColor fg = ds->signatureForeground( signature(), cg.text() ); + const QColor bg = ds->signatureBackground( signature(), cg.base() ); + const QFont f = ds->signatureFont( signature(), p->font() ); + + QColorGroup _cg = cg; + p->setFont( f ); + _cg.setColor( QColorGroup::Text, fg ); + _cg.setColor( QColorGroup::Base, bg ); + + QListViewItem::paintCell( p, _cg, column, width, alignment ); +} + + +// +// +// ColumnStrategy +// +// + +Kleo::KeyListView::ColumnStrategy::~ColumnStrategy() {} + +int Kleo::KeyListView::ColumnStrategy::compare( const GpgME::Key & key1, const GpgME::Key & key2, int col ) const { + return QString::localeAwareCompare( text( key1, col ), text( key2, col ) ); +} + +int Kleo::KeyListView::ColumnStrategy::width( int col, const QFontMetrics & fm ) const { + return fm.width( title( col ) ) * 2; +} + +int Kleo::KeyListView::ColumnStrategy::subkeyCompare( const GpgME::Subkey & sub1, const GpgME::Subkey & sub2, int col ) const { + return QString::localeAwareCompare( subkeyText( sub1, col ), subkeyText( sub2, col ) ); +} + +int Kleo::KeyListView::ColumnStrategy::userIDCompare( const GpgME::UserID & uid1, const GpgME::UserID & uid2, int col ) const { + return QString::localeAwareCompare( userIDText( uid1, col ), userIDText( uid2, col ) ); +} + +int Kleo::KeyListView::ColumnStrategy::signatureCompare( const GpgME::UserID::Signature & sig1, const GpgME::UserID::Signature & sig2, int col ) const { + return QString::localeAwareCompare( signatureText( sig1, col ), signatureText( sig2, col ) ); +} + +QString Kleo::KeyListView::ColumnStrategy::toolTip( const GpgME::Key & key, int col ) const { + return text( key, col ); +} + +QString Kleo::KeyListView::ColumnStrategy::subkeyToolTip( const GpgME::Subkey & sub, int col ) const { + return subkeyText( sub, col ); +} + +QString Kleo::KeyListView::ColumnStrategy::userIDToolTip( const GpgME::UserID & uid, int col ) const { + return userIDText( uid, col ); +} + +QString Kleo::KeyListView::ColumnStrategy::signatureToolTip( const GpgME::UserID::Signature & sig, int col ) const { + return signatureText( sig, col ); +} + +// +// +// DisplayStrategy +// +// + +Kleo::KeyListView::DisplayStrategy::~DisplayStrategy() {} + + +//font +QFont Kleo::KeyListView::DisplayStrategy::keyFont( const GpgME::Key &, const QFont & font ) const { + return font; +} + +QFont Kleo::KeyListView::DisplayStrategy::subkeyFont( const GpgME::Subkey &, const QFont & font ) const { + return font; +} + +QFont Kleo::KeyListView::DisplayStrategy::useridFont( const GpgME::UserID &, const QFont & font ) const { + return font; +} + +QFont Kleo::KeyListView::DisplayStrategy::signatureFont( const GpgME::UserID::Signature &, const QFont & font ) const { + return font; +} + +//foreground +QColor Kleo::KeyListView::DisplayStrategy::keyForeground( const GpgME::Key &, const QColor & fg )const { + return fg; +} + +QColor Kleo::KeyListView::DisplayStrategy::subkeyForeground( const GpgME::Subkey &, const QColor & fg ) const { + return fg; +} + +QColor Kleo::KeyListView::DisplayStrategy::useridForeground( const GpgME::UserID &, const QColor & fg ) const { + return fg; +} + +QColor Kleo::KeyListView::DisplayStrategy::signatureForeground( const GpgME::UserID::Signature &, const QColor & fg ) const { + return fg; +} + +//background +QColor Kleo::KeyListView::DisplayStrategy::keyBackground( const GpgME::Key &, const QColor & bg )const { + return bg; +} + +QColor Kleo::KeyListView::DisplayStrategy::subkeyBackground( const GpgME::Subkey &, const QColor & bg ) const { + return bg; +} + +QColor Kleo::KeyListView::DisplayStrategy::useridBackground( const GpgME::UserID &, const QColor & bg ) const { + return bg; +} + +QColor Kleo::KeyListView::DisplayStrategy::signatureBackground( const GpgME::UserID::Signature &, const QColor & bg ) const { + return bg; +} + + +// +// +// Collection of covariant return reimplementations of QListView(Item) +// members: +// +// + +Kleo::KeyListView * Kleo::KeyListViewItem::listView() const { + return static_cast<Kleo::KeyListView*>( QListViewItem::listView() ); +} + +Kleo::KeyListViewItem * Kleo::KeyListViewItem::nextSibling() const { + return static_cast<Kleo::KeyListViewItem*>( QListViewItem::nextSibling() ); +} + +Kleo::KeyListViewItem * Kleo::KeyListView::firstChild() const { + return static_cast<Kleo::KeyListViewItem*>( KListView::firstChild() ); +} + +Kleo::KeyListViewItem * Kleo::KeyListView::selectedItem() const { + return static_cast<Kleo::KeyListViewItem*>( KListView::selectedItem() ); +} + +static void selectedItems( QPtrList<Kleo::KeyListViewItem> & result, QListViewItem * start ) { + for ( QListViewItem * item = start ; item ; item = item->nextSibling() ) { + if ( item->isSelected() ) + if ( Kleo::KeyListViewItem * i = Kleo::lvi_cast<Kleo::KeyListViewItem>( item ) ) + result.append( i ); + selectedItems( result, item->firstChild() ); + } +} + +QPtrList<Kleo::KeyListViewItem> Kleo::KeyListView::selectedItems() const { + QPtrList<KeyListViewItem> result; + ::selectedItems( result, firstChild() ); + return result; +} + +static bool hasSelection( QListViewItem * start ) { + for ( QListViewItem * item = start ; item ; item = item->nextSibling() ) + if ( item->isSelected() || hasSelection( item->firstChild() ) ) + return true; + return false; +} + +bool Kleo::KeyListView::hasSelection() const { + return ::hasSelection( firstChild() ); +} + +#include "keylistview.moc" diff --git a/certmanager/lib/ui/keylistview.h b/certmanager/lib/ui/keylistview.h new file mode 100644 index 000000000..3ef708771 --- /dev/null +++ b/certmanager/lib/ui/keylistview.h @@ -0,0 +1,323 @@ +/* + keylistview.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_KEYLISTVIEW_H__ +#define __KLEO_KEYLISTVIEW_H__ + +#include <klistview.h> + +#include <gpgmepp/key.h> +#include <kdepimmacros.h> + +class QPainter; +class QColorGroup; +class QFont; +class QColor; + +namespace Kleo { + + // work around moc parser bug... +#define TEMPLATE_TYPENAME(T) template <typename T> + TEMPLATE_TYPENAME(T) + inline T * lvi_cast( QListViewItem * item ) { + return item && (item->rtti() & T::RTTI_MASK) == T::RTTI + ? static_cast<T*>( item ) : 0 ; + } + + TEMPLATE_TYPENAME(T) + inline const T * lvi_cast( const QListViewItem * item ) { + return item && (item->rtti() & T::RTTI_MASK) == T::RTTI + ? static_cast<const T*>( item ) : 0 ; + } +#undef TEMPLATE_TYPENAME + + class KeyListView; + + class KDE_EXPORT KeyListViewItem : public QListViewItem { + public: + KeyListViewItem( KeyListView * parent, const GpgME::Key & key ); + KeyListViewItem( KeyListView * parent, KeyListViewItem * after, const GpgME::Key & key ); + KeyListViewItem( KeyListViewItem * parent, const GpgME::Key & key ); + KeyListViewItem( KeyListViewItem * parent, KeyListViewItem * after, const GpgME::Key & key ); + ~KeyListViewItem(); + + void setKey( const GpgME::Key & key ); + const GpgME::Key & key() const { return mKey; } + + enum { RTTI_MASK = 0xFFFFFFF0, RTTI = 0x2C1362E0 }; + + // + // only boring stuff below: + // + virtual QString toolTip( int column ) const; + + /*! \reimp for covariant return */ + KeyListView * listView() const; + /*! \reimp for covariant return */ + KeyListViewItem * nextSibling() const; + /*! \reimp */ + int compare( QListViewItem * other, int col, bool ascending ) const; + /*! \reimp to allow for key() overload above */ + QString key( int col, bool ascending ) const { return QListViewItem::key( col, ascending ); } + /*! \reimp */ + int rtti() const { return RTTI; } + /*! \reimp */ + void paintCell( QPainter * p, const QColorGroup & cg, int column, int width, int alignment ); + /*! \reimp */ + void insertItem( QListViewItem * item ); + /*! \reimp */ + void takeItem( QListViewItem * item ); + + private: + GpgME::Key mKey; + }; + + class KDE_EXPORT SubkeyKeyListViewItem : public KeyListViewItem { + public: + SubkeyKeyListViewItem( KeyListView * parent, const GpgME::Subkey & subkey ); + SubkeyKeyListViewItem( KeyListView * parent, KeyListViewItem * after, const GpgME::Subkey & subkey ); + SubkeyKeyListViewItem( KeyListViewItem * parent, const GpgME::Subkey & subkey ); + SubkeyKeyListViewItem( KeyListViewItem * parent, KeyListViewItem * after, const GpgME::Subkey & subkey ); + + void setSubkey( const GpgME::Subkey & subkey ); + const GpgME::Subkey & subkey() const { return mSubkey; } + + enum { RTTI = KeyListViewItem::RTTI + 1 }; + + // + // only boring stuff below: + // + /*! \reimp */ + QString toolTip( int col ) const; + /*! \reimp */ + QString text( int col ) const; + /*! \reimp */ + const QPixmap * pixmap( int col ) const; + /*! \reimp */ + int compare( QListViewItem * other, int col, bool ascending ) const; + /*! \reimp */ + int rtti() const { return RTTI; } + /*! \reimp */ + void paintCell( QPainter * p, const QColorGroup & cg, int column, int width, int alignment ); + + private: + GpgME::Subkey mSubkey; + }; + + class KDE_EXPORT UserIDKeyListViewItem : public KeyListViewItem { + public: + UserIDKeyListViewItem( KeyListView * parent, const GpgME::UserID & userid ); + UserIDKeyListViewItem( KeyListView * parent, KeyListViewItem * after, const GpgME::UserID & userid ); + UserIDKeyListViewItem( KeyListViewItem * parent, const GpgME::UserID & userid ); + UserIDKeyListViewItem( KeyListViewItem * parent, KeyListViewItem * after, const GpgME::UserID & userid ); + + void setUserID( const GpgME::UserID & userid ); + const GpgME::UserID userID() const { return mUserID; } + + enum { RTTI = KeyListViewItem::RTTI + 2 }; + + // + // only boring stuff below: + // + /*! \reimp */ + QString toolTip( int col ) const; + /*! \reimp */ + QString text( int col ) const; + /*! \reimp */ + const QPixmap * pixmap( int col ) const; + /*! \reimp */ + int compare( QListViewItem * other, int col, bool ascending ) const; + /*! \reimp */ + int rtti() const { return RTTI; } + /*! \reimp */ + void paintCell( QPainter * p, const QColorGroup & cg, int column, int width, int alignment ); + + private: + GpgME::UserID mUserID; + }; + + class KDE_EXPORT SignatureKeyListViewItem : public KeyListViewItem { + public: + SignatureKeyListViewItem( KeyListView * parent, const GpgME::UserID::Signature & sig ); + SignatureKeyListViewItem( KeyListView * parent, KeyListViewItem * after, const GpgME::UserID::Signature & sig ); + SignatureKeyListViewItem( KeyListViewItem * parent, const GpgME::UserID::Signature & sig ); + SignatureKeyListViewItem( KeyListViewItem * parent, KeyListViewItem * after, const GpgME::UserID::Signature & sig ); + + void setSignature( const GpgME::UserID::Signature & sig ); + const GpgME::UserID::Signature & signature() const { return mSignature; } + + enum { RTTI = KeyListViewItem::RTTI + 3 }; + + // + // only boring stuff below: + // + /*! \reimp */ + QString toolTip( int col ) const; + /*! \reimp */ + QString text( int col ) const; + /*! \reimp */ + const QPixmap * pixmap( int col ) const; + /*! \reimp */ + int compare( QListViewItem * other, int col, bool ascending ) const; + /*! \reimp */ + int rtti() const { return RTTI; } + /*! \reimp */ + void paintCell( QPainter * p, const QColorGroup & cg, int column, int width, int alignment ); + + private: + GpgME::UserID::Signature mSignature; + }; + + + class KDE_EXPORT KeyListView : public KListView { + Q_OBJECT + friend class KeyListViewItem; + public: + + class KDE_EXPORT ColumnStrategy { + public: + virtual ~ColumnStrategy(); + virtual QString title( int column ) const = 0; + virtual int width( int column, const QFontMetrics & fm ) const; + virtual QListView::WidthMode widthMode( int ) const { return QListView::Manual; } + + virtual QString text( const GpgME::Key & key, int column ) const = 0; + virtual QString toolTip( const GpgME::Key & key, int column ) const; + virtual const QPixmap * pixmap( const GpgME::Key &, int ) const { return 0; } + virtual int compare( const GpgME::Key & key1, const GpgME::Key & key2, const int column ) const; + + virtual QString subkeyText( const GpgME::Subkey &, int ) const { return QString::null; } + virtual QString subkeyToolTip( const GpgME::Subkey & subkey, int column ) const; + virtual const QPixmap * subkeyPixmap( const GpgME::Subkey &, int ) const { return 0; } + virtual int subkeyCompare( const GpgME::Subkey & subkey1, const GpgME::Subkey & subkey2, const int column ) const; + + virtual QString userIDText( const GpgME::UserID &, int ) const { return QString::null; } + virtual QString userIDToolTip( const GpgME::UserID & userID, int column ) const; + virtual const QPixmap * userIDPixmap( const GpgME::UserID &, int ) const { return 0; } + virtual int userIDCompare( const GpgME::UserID & userID1, const GpgME::UserID & userID2, const int column ) const; + + virtual QString signatureText( const GpgME::UserID::Signature &, int ) const { return QString::null; } + virtual QString signatureToolTip( const GpgME::UserID::Signature & sig, int column ) const; + virtual const QPixmap * signaturePixmap( const GpgME::UserID::Signature &, int ) const { return 0; } + virtual int signatureCompare( const GpgME::UserID::Signature & sig1, const GpgME::UserID::Signature & sig2, const int column ) const; + }; + + class KDE_EXPORT DisplayStrategy { + public: + virtual ~DisplayStrategy(); + //font + virtual QFont keyFont( const GpgME::Key &, const QFont & ) const; + virtual QFont subkeyFont( const GpgME::Subkey &, const QFont & ) const; + virtual QFont useridFont( const GpgME::UserID &, const QFont & ) const; + virtual QFont signatureFont( const GpgME::UserID::Signature & , const QFont & ) const; + //foreground + virtual QColor keyForeground( const GpgME::Key & , const QColor & ) const; + virtual QColor subkeyForeground( const GpgME::Subkey &, const QColor & ) const; + virtual QColor useridForeground( const GpgME::UserID &, const QColor & ) const; + virtual QColor signatureForeground( const GpgME::UserID::Signature &, const QColor & ) const; + //background + virtual QColor keyBackground( const GpgME::Key &, const QColor & ) const; + virtual QColor subkeyBackground( const GpgME::Subkey &, const QColor & ) const; + virtual QColor useridBackground( const GpgME::UserID &, const QColor & ) const; + virtual QColor signatureBackground( const GpgME::UserID::Signature &, const QColor & ) const; + }; + + KeyListView( const ColumnStrategy * strategy, + const DisplayStrategy * display=0, + QWidget * parent=0, const char * name=0, WFlags f=0 ); + + ~KeyListView(); + + const ColumnStrategy * columnStrategy() const { return mColumnStrategy; } + const DisplayStrategy * displayStrategy() const { return mDisplayStrategy; } + + bool hierarchical() const { return mHierarchical; } + virtual void setHierarchical( bool hier ); + + void flushKeys() { slotUpdateTimeout(); } + + bool hasSelection() const; + + KeyListViewItem * itemByFingerprint( const QCString & ) const; + + signals: + void doubleClicked( Kleo::KeyListViewItem*, const QPoint&, int ); + void returnPressed( Kleo::KeyListViewItem* ); + void selectionChanged( Kleo::KeyListViewItem* ); + void contextMenu( Kleo::KeyListViewItem*, const QPoint& ); + + public slots: + virtual void slotAddKey( const GpgME::Key & key ); + virtual void slotRefreshKey( const GpgME::Key & key ); + + // + // Only boring stuff below: + // + private slots: + void slotEmitDoubleClicked( QListViewItem*, const QPoint&, int ); + void slotEmitReturnPressed( QListViewItem* ); + void slotEmitSelectionChanged( QListViewItem* ); + void slotEmitContextMenu( KListView*, QListViewItem*, const QPoint& ); + void slotUpdateTimeout(); + + public: + /*! \reimp for covariant return */ + KeyListViewItem * selectedItem() const; + /*! \reimp */ + QPtrList<KeyListViewItem> selectedItems() const; + /*! \reimp for covariant return */ + KeyListViewItem * firstChild() const; + /*! \reimp */ + void clear(); + /*! \reimp */ + void insertItem( QListViewItem * ); + /*! \reimp */ + void takeItem( QListViewItem * ); + + private: + void doHierarchicalInsert( const GpgME::Key & ); + void gatherScattered(); + void scatterGathered( QListViewItem * ); + void registerItem( KeyListViewItem * ); + void deregisterItem( const KeyListViewItem * ); + + private: + const ColumnStrategy * mColumnStrategy; + const DisplayStrategy * mDisplayStrategy; + bool mHierarchical; + + class Private; + Private * d; + }; +} + +#endif // __KLEO_KEYLISTVIEW_H__ diff --git a/certmanager/lib/ui/keyrequester.cpp b/certmanager/lib/ui/keyrequester.cpp new file mode 100644 index 000000000..d537affc5 --- /dev/null +++ b/certmanager/lib/ui/keyrequester.cpp @@ -0,0 +1,481 @@ +/* -*- c++ -*- + keyrequester.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klar�vdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. + + + Based on kpgpui.cpp + Copyright (C) 2001,2002 the KPGP authors + See file libkdenetwork/AUTHORS.kpgp for details + + This file is part of KPGP, the KDE PGP/GnuPG support library. + + KPGP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "keyrequester.h" + +#include "keyselectiondialog.h" + +#include <kleo/keylistjob.h> +#include <kleo/dn.h> +#include <kleo/cryptobackendfactory.h> + +// gpgme++ +#include <gpgmepp/key.h> +#include <gpgmepp/keylistresult.h> + +// KDE +#include <klocale.h> +#include <kiconloader.h> +#include <kdialog.h> +#include <kdebug.h> +#include <kmessagebox.h> +#include <kpushbutton.h> + +// Qt +#include <qapplication.h> +#include <qlayout.h> +#include <qtooltip.h> +#include <qstring.h> +#include <qstringlist.h> +#include <qlabel.h> +#include <qregexp.h> + +#include <assert.h> + +Kleo::KeyRequester::KeyRequester( unsigned int allowedKeys, bool multipleKeys, + QWidget * parent, const char * name ) + : QWidget( parent, name ), + mOpenPGPBackend( 0 ), + mSMIMEBackend( 0 ), + mMulti( multipleKeys ), + mKeyUsage( allowedKeys ), + mJobs( 0 ), + d( 0 ) +{ + init(); +} + +Kleo::KeyRequester::KeyRequester( QWidget * parent, const char * name ) + : QWidget( parent, name ), + mOpenPGPBackend( 0 ), + mSMIMEBackend( 0 ), + mMulti( false ), + mKeyUsage( 0 ), + mJobs( 0 ), + d( 0 ) +{ + init(); +} + +void Kleo::KeyRequester::init() +{ + QHBoxLayout * hlay = new QHBoxLayout( this, 0, KDialog::spacingHint() ); + + // the label where the key id is to be displayed: + mLabel = new QLabel( this ); + mLabel->setFrameStyle( QFrame::Panel | QFrame::Sunken ); + + // the button to unset any key: + mEraseButton = new KPushButton( this ); + mEraseButton->setAutoDefault( false ); + mEraseButton->setSizePolicy( QSizePolicy( QSizePolicy::Minimum, + QSizePolicy::Minimum ) ); + mEraseButton->setIconSet( SmallIconSet( QApplication::reverseLayout() ? "locationbar_erase" : "clear_left" ) ); + QToolTip::add( mEraseButton, i18n("Clear") ); + + // the button to call the KeySelectionDialog: + mDialogButton = new QPushButton( i18n("Change..."), this ); + mDialogButton->setAutoDefault( false ); + + hlay->addWidget( mLabel, 1 ); + hlay->addWidget( mEraseButton ); + hlay->addWidget( mDialogButton ); + + connect( mEraseButton, SIGNAL(clicked()), SLOT(slotEraseButtonClicked()) ); + connect( mDialogButton, SIGNAL(clicked()), SLOT(slotDialogButtonClicked()) ); + + setSizePolicy( QSizePolicy( QSizePolicy::MinimumExpanding, + QSizePolicy::Fixed ) ); + + setAllowedKeys( mKeyUsage ); +} + +Kleo::KeyRequester::~KeyRequester() { + +} + +const std::vector<GpgME::Key> & Kleo::KeyRequester::keys() const { + return mKeys; +} + +const GpgME::Key & Kleo::KeyRequester::key() const { + if ( mKeys.empty() ) + return GpgME::Key::null; + else + return mKeys.front(); +} + +void Kleo::KeyRequester::setKeys( const std::vector<GpgME::Key> & keys ) { + mKeys.clear(); + for ( std::vector<GpgME::Key>::const_iterator it = keys.begin() ; it != keys.end() ; ++it ) + if ( !it->isNull() ) + mKeys.push_back( *it ); + updateKeys(); +} + +void Kleo::KeyRequester::setKey( const GpgME::Key & key ) { + mKeys.clear(); + if ( !key.isNull() ) + mKeys.push_back( key ); + updateKeys(); +} + +QString Kleo::KeyRequester::fingerprint() const { + if ( mKeys.empty() ) + return QString::null; + else + return mKeys.front().primaryFingerprint(); +} + +QStringList Kleo::KeyRequester::fingerprints() const { + QStringList result; + for ( std::vector<GpgME::Key>::const_iterator it = mKeys.begin() ; it != mKeys.end() ; ++it ) + if ( !it->isNull() ) + if ( const char * fpr = it->primaryFingerprint() ) + result.push_back( fpr ); + return result; +} + +void Kleo::KeyRequester::setFingerprint( const QString & fingerprint ) { + startKeyListJob( fingerprint ); +} + +void Kleo::KeyRequester::setFingerprints( const QStringList & fingerprints ) { + startKeyListJob( fingerprints ); +} + +void Kleo::KeyRequester::updateKeys() { + if ( mKeys.empty() ) { + mLabel->clear(); + return; + } + if ( mKeys.size() > 1 ) + setMultipleKeysEnabled( true ); + + QStringList labelTexts; + QString toolTipText; + for ( std::vector<GpgME::Key>::const_iterator it = mKeys.begin() ; it != mKeys.end() ; ++it ) { + if ( it->isNull() ) + continue; + const QString fpr = it->primaryFingerprint(); + labelTexts.push_back( fpr.right(8) ); + toolTipText += fpr.right(8) + ": "; + if ( const char * uid = it->userID(0).id() ) + if ( it->protocol() == GpgME::Context::OpenPGP ) + toolTipText += QString::fromUtf8( uid ); + else + toolTipText += Kleo::DN( uid ).prettyDN(); + else + toolTipText += i18n("<unknown>"); + toolTipText += '\n'; + } + + mLabel->setText( labelTexts.join(", ") ); + QToolTip::remove( mLabel ); + QToolTip::add( mLabel, toolTipText ); +} + +#ifndef __KLEO_UI_SHOW_KEY_LIST_ERROR_H__ +#define __KLEO_UI_SHOW_KEY_LIST_ERROR_H__ +static void showKeyListError( QWidget * parent, const GpgME::Error & err ) { + assert( err ); + const QString msg = i18n( "<qt><p>An error occurred while fetching " + "the keys from the backend:</p>" + "<p><b>%1</b></p></qt>" ) + .arg( QString::fromLocal8Bit( err.asString() ) ); + + KMessageBox::error( parent, msg, i18n( "Key Listing Failed" ) ); +} +#endif // __KLEO_UI_SHOW_KEY_LIST_ERROR_H__ + +void Kleo::KeyRequester::startKeyListJob( const QStringList & fingerprints ) { + if ( !mSMIMEBackend && !mOpenPGPBackend ) + return; + + mTmpKeys.clear(); + mJobs = 0; + + unsigned int count = 0; + for ( QStringList::const_iterator it = fingerprints.begin() ; it != fingerprints.end() ; ++it ) + if ( !(*it).stripWhiteSpace().isEmpty() ) + ++count; + + if ( !count ) { + // don't fall into the trap that an empty pattern means + // "return all keys" :) + setKey( GpgME::Key::null ); + return; + } + + if ( mOpenPGPBackend ) { + KeyListJob * job = mOpenPGPBackend->keyListJob( false ); // local, no sigs + if ( !job ) { + KMessageBox::error( this, + i18n("The OpenPGP backend does not support listing keys. " + "Check your installation."), + i18n("Key Listing Failed") ); + } else { + connect( job, SIGNAL(result(const GpgME::KeyListResult&)), + SLOT(slotKeyListResult(const GpgME::KeyListResult&)) ); + connect( job, SIGNAL(nextKey(const GpgME::Key&)), + SLOT(slotNextKey(const GpgME::Key&)) ); + + const GpgME::Error err = job->start( fingerprints, + mKeyUsage & Kleo::KeySelectionDialog::SecretKeys && + !( mKeyUsage & Kleo::KeySelectionDialog::PublicKeys ) ); + + if ( err ) + showKeyListError( this, err ); + else + ++mJobs; + } + } + + if ( mSMIMEBackend ) { + KeyListJob * job = mSMIMEBackend->keyListJob( false ); // local, no sigs + if ( !job ) { + KMessageBox::error( this, + i18n("The S/MIME backend does not support listing keys. " + "Check your installation."), + i18n("Key Listing Failed") ); + } else { + connect( job, SIGNAL(result(const GpgME::KeyListResult&)), + SLOT(slotKeyListResult(const GpgME::KeyListResult&)) ); + connect( job, SIGNAL(nextKey(const GpgME::Key&)), + SLOT(slotNextKey(const GpgME::Key&)) ); + + const GpgME::Error err = job->start( fingerprints, + mKeyUsage & Kleo::KeySelectionDialog::SecretKeys && + !( mKeyUsage & Kleo::KeySelectionDialog::PublicKeys ) ); + + if ( err ) + showKeyListError( this, err ); + else + ++mJobs; + } + } + + if ( mJobs > 0 ) { + mEraseButton->setEnabled( false ); + mDialogButton->setEnabled( false ); + } +} + +void Kleo::KeyRequester::slotNextKey( const GpgME::Key & key ) { + if ( !key.isNull() ) + mTmpKeys.push_back( key ); +} + +void Kleo::KeyRequester::slotKeyListResult( const GpgME::KeyListResult & res ) { + if ( res.error() ) + showKeyListError( this, res.error() ); + + if ( --mJobs <= 0 ) { + mEraseButton->setEnabled( true ); + mDialogButton->setEnabled( true ); + + setKeys( mTmpKeys ); + mTmpKeys.clear(); + } +} + + +void Kleo::KeyRequester::slotDialogButtonClicked() { + KeySelectionDialog * dlg = mKeys.empty() + ? new KeySelectionDialog( mDialogCaption, mDialogMessage, mInitialQuery, mKeyUsage, mMulti, false, this ) + : new KeySelectionDialog( mDialogCaption, mDialogCaption, mKeys, mKeyUsage, mMulti, false, this ) ; + + if ( dlg->exec() == QDialog::Accepted ) { + if ( mMulti ) + setKeys( dlg->selectedKeys() ); + else + setKey( dlg->selectedKey() ); + emit changed(); + } + + delete dlg; +} + +void Kleo::KeyRequester::slotEraseButtonClicked() { + if ( !mKeys.empty() ) + emit changed(); + mKeys.clear(); + updateKeys(); +} + +void Kleo::KeyRequester::setDialogCaption( const QString & caption ) { + mDialogCaption = caption; +} + +void Kleo::KeyRequester::setDialogMessage( const QString & msg ) { + mDialogMessage = msg; +} + +bool Kleo::KeyRequester::isMultipleKeysEnabled() const { + return mMulti; +} + +void Kleo::KeyRequester::setMultipleKeysEnabled( bool multi ) { + if ( multi == mMulti ) return; + + if ( !multi && !mKeys.empty() ) + mKeys.erase( mKeys.begin() + 1, mKeys.end() ); + + mMulti = multi; + updateKeys(); +} + +unsigned int Kleo::KeyRequester::allowedKeys() const { + return mKeyUsage; +} + +void Kleo::KeyRequester::setAllowedKeys( unsigned int keyUsage ) { + mKeyUsage = keyUsage; + mOpenPGPBackend = 0; + mSMIMEBackend = 0; + + if ( mKeyUsage & KeySelectionDialog::OpenPGPKeys ) + mOpenPGPBackend = Kleo::CryptoBackendFactory::instance()->openpgp(); + if ( mKeyUsage & KeySelectionDialog::SMIMEKeys ) + mSMIMEBackend = Kleo::CryptoBackendFactory::instance()->smime(); + + if ( mOpenPGPBackend && !mSMIMEBackend ) { + mDialogCaption = i18n("OpenPGP Key Selection"); + mDialogMessage = i18n("Please select an OpenPGP key to use."); + } else if ( !mOpenPGPBackend && mSMIMEBackend ) { + mDialogCaption = i18n("S/MIME Key Selection"); + mDialogMessage = i18n("Please select an S/MIME key to use."); + } else { + mDialogCaption = i18n("Key Selection"); + mDialogMessage = i18n("Please select an (OpenPGP or S/MIME) key to use."); + } +} + +QPushButton * Kleo::KeyRequester::dialogButton() { + return mDialogButton; +} + +QPushButton * Kleo::KeyRequester::eraseButton() { + return mEraseButton; +} + +static inline unsigned int foo( bool openpgp, bool smime, bool trusted, bool valid ) { + unsigned int result = 0; + if ( openpgp ) + result |= Kleo::KeySelectionDialog::OpenPGPKeys; + if ( smime ) + result |= Kleo::KeySelectionDialog::SMIMEKeys; + if ( trusted ) + result |= Kleo::KeySelectionDialog::TrustedKeys; + if ( valid ) + result |= Kleo::KeySelectionDialog::ValidKeys; + return result; +} + +static inline unsigned int encryptionKeyUsage( bool openpgp, bool smime, bool trusted, bool valid ) { + return foo( openpgp, smime, trusted, valid ) | Kleo::KeySelectionDialog::EncryptionKeys | Kleo::KeySelectionDialog::PublicKeys; +} + +static inline unsigned int signingKeyUsage( bool openpgp, bool smime, bool trusted, bool valid ) { + return foo( openpgp, smime, trusted, valid ) | Kleo::KeySelectionDialog::SigningKeys | Kleo::KeySelectionDialog::SecretKeys; +} + +Kleo::EncryptionKeyRequester::EncryptionKeyRequester( bool multi, unsigned int proto, + QWidget * parent, const char * name, + bool onlyTrusted, bool onlyValid ) + : KeyRequester( encryptionKeyUsage( proto & OpenPGP, proto & SMIME, onlyTrusted, onlyValid ), multi, + parent, name ) +{ +} + +Kleo::EncryptionKeyRequester::EncryptionKeyRequester( QWidget * parent, const char * name ) + : KeyRequester( 0, false, parent, name ) +{ +} + +Kleo::EncryptionKeyRequester::~EncryptionKeyRequester() {} + + +void Kleo::EncryptionKeyRequester::setAllowedKeys( unsigned int proto, bool onlyTrusted, bool onlyValid ) +{ + KeyRequester::setAllowedKeys( encryptionKeyUsage( proto & OpenPGP, proto & SMIME, onlyTrusted, onlyValid ) ); +} + +Kleo::SigningKeyRequester::SigningKeyRequester( bool multi, unsigned int proto, + QWidget * parent, const char * name, + bool onlyTrusted, bool onlyValid ) + : KeyRequester( signingKeyUsage( proto & OpenPGP, proto & SMIME, onlyTrusted, onlyValid ), multi, + parent, name ) +{ +} + +Kleo::SigningKeyRequester::SigningKeyRequester( QWidget * parent, const char * name ) + : KeyRequester( 0, false, parent, name ) +{ +} + +Kleo::SigningKeyRequester::~SigningKeyRequester() {} + +void Kleo::SigningKeyRequester::setAllowedKeys( unsigned int proto, bool onlyTrusted, bool onlyValid ) +{ + KeyRequester::setAllowedKeys( signingKeyUsage( proto & OpenPGP, proto & SMIME, onlyTrusted, onlyValid ) ); +} + +void Kleo::KeyRequester::virtual_hook( int, void* ) {} +void Kleo::EncryptionKeyRequester::virtual_hook( int id, void * data ) { + KeyRequester::virtual_hook( id, data ); +} +void Kleo::SigningKeyRequester::virtual_hook( int id, void * data ) { + KeyRequester::virtual_hook( id, data ); +} + +#include "keyrequester.moc" diff --git a/certmanager/lib/ui/keyrequester.h b/certmanager/lib/ui/keyrequester.h new file mode 100644 index 000000000..3de9c508b --- /dev/null +++ b/certmanager/lib/ui/keyrequester.h @@ -0,0 +1,227 @@ +/* -*- c++ -*- + keyrequester.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. + + + Based on kpgpui.h + Copyright (C) 2001,2002 the KPGP authors + See file libkdenetwork/AUTHORS.kpgp for details + + This file is part of KPGP, the KDE PGP/GnuPG support library. + + KPGP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __KLEO_UI_KEYREQUESTER_H__ +#define __KLEO_UI_KEYREQUESTER_H__ + +#include <qwidget.h> +#include <kleo/cryptobackend.h> + +#include <vector> +#include <kdepimmacros.h> + +namespace Kleo { + class KeyListView; + class KeyListViewItem; +} + +namespace GpgME { + class Key; + class KeyListResult; +} + +class QStringList; +class QString; +class QPushButton; +class QLabel; + +namespace Kleo { + + /// Base class for SigningKeyRequester and EncryptionKeyRequester + class KDE_EXPORT KeyRequester : public QWidget { + Q_OBJECT + public: + KeyRequester( unsigned int allowedKeys, bool multipleKeys=false, + QWidget * parent=0, const char * name=0 ); + // Constructor for Qt Designer + KeyRequester( QWidget * parent=0, const char * name=0 ); + ~KeyRequester(); + + const GpgME::Key & key() const; + /** Preferred method to set a key for + non-multi-KeyRequesters. Doesn't start a backend + KeyListJob. + */ + void setKey( const GpgME::Key & key ); + + const std::vector<GpgME::Key> & keys() const; + /** Preferred method to set a key for multi-KeyRequesters. Doesn't + start a backend KeyListJob. + */ + void setKeys( const std::vector<GpgME::Key> & keys ); + + QString fingerprint() const; + /** Set the key by fingerprint. Starts a background KeyListJob to + retrive the complete GpgME::Key object + */ + void setFingerprint( const QString & fingerprint ); + + QStringList fingerprints() const; + /** Set the keys by fingerprint. Starts a background KeyListJob to + retrive the complete GpgME::Key objects + */ + void setFingerprints( const QStringList & fingerprints ); + + + QPushButton * eraseButton(); + QPushButton * dialogButton(); + + void setDialogCaption( const QString & caption ); + void setDialogMessage( const QString & message ); + + bool isMultipleKeysEnabled() const; + void setMultipleKeysEnabled( bool enable ); + + unsigned int allowedKeys() const; + void setAllowedKeys( unsigned int allowed ); + + void setInitialQuery( const QString & s ) { mInitialQuery = s; } + const QString & initialQuery() const { return mInitialQuery; } + + signals: + void changed(); + + private: + void init(); + void startKeyListJob( const QStringList & fingerprints ); + void updateKeys(); + + private slots: + void slotNextKey( const GpgME::Key & key ); + void slotKeyListResult( const GpgME::KeyListResult & result ); + void slotDialogButtonClicked(); + void slotEraseButtonClicked(); + + private: + const CryptoBackend::Protocol * mOpenPGPBackend; + const CryptoBackend::Protocol * mSMIMEBackend; + QLabel * mLabel; + QPushButton * mEraseButton; + QPushButton * mDialogButton; + QString mDialogCaption, mDialogMessage, mInitialQuery; + bool mMulti; + unsigned int mKeyUsage; + int mJobs; + std::vector<GpgME::Key> mKeys; + std::vector<GpgME::Key> mTmpKeys; + + private: + class Private; + Private * d; + protected: + virtual void virtual_hook( int, void* ); + }; + + + class KDE_EXPORT EncryptionKeyRequester : public KeyRequester { + Q_OBJECT + public: + enum { OpenPGP = 1, SMIME = 2, AllProtocols = OpenPGP|SMIME }; + + /** + * Preferred constructor + */ + EncryptionKeyRequester( bool multipleKeys=false, unsigned int proto=AllProtocols, + QWidget * parent=0, const char * name=0, + bool onlyTrusted=true, bool onlyValid=true ); + /** + * Constructor for Qt designer + */ + EncryptionKeyRequester( QWidget * parent=0, const char * name=0 ); + ~EncryptionKeyRequester(); + + void setAllowedKeys( unsigned int proto, bool onlyTrusted=true, bool onlyValid=true ); + + private: + class Private; + Private * d; + protected: + virtual void virtual_hook( int, void* ); + }; + + + class KDE_EXPORT SigningKeyRequester : public KeyRequester { + Q_OBJECT + public: + enum { OpenPGP = 1, SMIME = 2, AllProtocols = OpenPGP|SMIME }; + + /** + * Preferred constructor + * @param multipleKeys whether multiple keys can be selected + * + * @param proto the allowed protocols, OpenPGP and/or SMIME + * @param onlyTrusted only show trusted keys + * @param onlyValid only show valid keys + */ + SigningKeyRequester( bool multipleKeys=false, unsigned int proto=AllProtocols, + QWidget * parent=0, const char * name=0, + bool onlyTrusted=true, bool onlyValid=true ); + /** + * Constructor for Qt designer + */ + SigningKeyRequester( QWidget * parent=0, const char * name=0 ); + ~SigningKeyRequester(); + + /* + * Those parameters affect the parameters given to the key selection dialog. + * @param proto the allowed protocols, OpenPGP and/or SMIME + * @param onlyTrusted only show trusted keys + * @param onlyValid only show valid keys + */ + void setAllowedKeys( unsigned int proto, bool onlyTrusted=true, bool onlyValid=true ); + + private: + class Private; + Private * d; + protected: + virtual void virtual_hook( int, void* ); + }; + +} + +#endif // __KLEO_UI_KEYREQUESTER_H__ diff --git a/certmanager/lib/ui/keyselectiondialog.cpp b/certmanager/lib/ui/keyselectiondialog.cpp new file mode 100644 index 000000000..e21cb39d4 --- /dev/null +++ b/certmanager/lib/ui/keyselectiondialog.cpp @@ -0,0 +1,806 @@ +/* -*- c++ -*- + keyselectiondialog.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarävdalens Datakonsult AB + + Based on kpgpui.cpp + Copyright (C) 2001,2002 the KPGP authors + See file libkdenetwork/AUTHORS.kpgp for details + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "keyselectiondialog.h" + +#include "keylistview.h" +#include "progressdialog.h" + +#include <kleo/dn.h> +#include <kleo/keylistjob.h> +#include <kleo/cryptobackendfactory.h> + +// gpgme++ +#include <gpgmepp/key.h> +#include <gpgmepp/keylistresult.h> + +// KDE +#include <klocale.h> +#include <kapplication.h> +#include <kglobal.h> +#include <kiconloader.h> +#include <kdebug.h> +#include <kwin.h> +#include <kconfig.h> +#include <kmessagebox.h> +#include <kprocess.h> + +// Qt +#include <qcheckbox.h> +#include <qtoolbutton.h> +#include <qlabel.h> +#include <qpixmap.h> +#include <qtimer.h> +#include <qlayout.h> +#include <qlineedit.h> +#include <qwhatsthis.h> +#include <qpopupmenu.h> +#include <qregexp.h> +#include <qpushbutton.h> + +#include <algorithm> +#include <iterator> + +#include <string.h> +#include <assert.h> + +static bool checkKeyUsage( const GpgME::Key & key, unsigned int keyUsage ) { + + if ( keyUsage & Kleo::KeySelectionDialog::ValidKeys ) { + if ( key.isInvalid() ) + kdDebug() << "key is invalid - ignoring" << endl; + if ( key.isExpired() ) { + kdDebug() << "key is expired" << endl; + return false; + } else if ( key.isRevoked() ) { + kdDebug() << "key is revoked" << endl; + return false; + } else if ( key.isDisabled() ) { + kdDebug() << "key is disabled" << endl; + return false; + } + } + + if ( keyUsage & Kleo::KeySelectionDialog::EncryptionKeys && + !key.canEncrypt() ) { + kdDebug() << "key can't encrypt" << endl; + return false; + } + if ( keyUsage & Kleo::KeySelectionDialog::SigningKeys && + !key.canSign() ) { + kdDebug() << "key can't sign" << endl; + return false; + } + if ( keyUsage & Kleo::KeySelectionDialog::CertificationKeys && + !key.canCertify() ) { + kdDebug() << "key can't certify" << endl; + return false; + } + if ( keyUsage & Kleo::KeySelectionDialog::AuthenticationKeys && + !key.canAuthenticate() ) { + kdDebug() << "key can't authenticate" << endl; + return false; + } + + if ( keyUsage & Kleo::KeySelectionDialog::SecretKeys && + !( keyUsage & Kleo::KeySelectionDialog::PublicKeys ) && + !key.isSecret() ) { + kdDebug() << "key isn't secret" << endl; + return false; + } + + if ( keyUsage & Kleo::KeySelectionDialog::TrustedKeys && + key.protocol() == GpgME::Context::OpenPGP && + // only check this for secret keys for now. + // Seems validity isn't checked for secret keylistings... + !key.isSecret() ) { + std::vector<GpgME::UserID> uids = key.userIDs(); + for ( std::vector<GpgME::UserID>::const_iterator it = uids.begin() ; it != uids.end() ; ++it ) + if ( !it->isRevoked() && it->validity() >= GpgME::UserID::Marginal ) + return true; + kdDebug() << "key has no UIDs with validity >= Marginal" << endl; + return false; + } + // X.509 keys are always trusted, else they won't be the keybox. + // PENDING(marc) check that this ^ is correct + + return true; +} + +static bool checkKeyUsage( const std::vector<GpgME::Key> & keys, unsigned int keyUsage ) { + for ( std::vector<GpgME::Key>::const_iterator it = keys.begin() ; it != keys.end() ; ++it ) + if ( !checkKeyUsage( *it, keyUsage ) ) + return false; + return true; +} + +static inline QString time_t2string( time_t t ) { + QDateTime dt; + dt.setTime_t( t ); + return dt.toString(); +} + +namespace { + + class ColumnStrategy : public Kleo::KeyListView::ColumnStrategy { + public: + ColumnStrategy( unsigned int keyUsage ); + + QString title( int col ) const; + int width( int col, const QFontMetrics & fm ) const; + + QString text( const GpgME::Key & key, int col ) const; + QString toolTip( const GpgME::Key & key, int col ) const; + const QPixmap * pixmap( const GpgME::Key & key, int col ) const; + + private: + const QPixmap mKeyGoodPix, mKeyBadPix, mKeyUnknownPix, mKeyValidPix; + const unsigned int mKeyUsage; + }; + + ColumnStrategy::ColumnStrategy( unsigned int keyUsage ) + : Kleo::KeyListView::ColumnStrategy(), + mKeyGoodPix( UserIcon( "key_ok" ) ), + mKeyBadPix( UserIcon( "key_bad" ) ), + mKeyUnknownPix( UserIcon( "key_unknown" ) ), + mKeyValidPix( UserIcon( "key" ) ), + mKeyUsage( keyUsage ) + { + kdWarning( keyUsage == 0, 5150 ) + << "KeySelectionDialog: keyUsage == 0. You want to use AllKeys instead." << endl; + } + + QString ColumnStrategy::title( int col ) const { + switch ( col ) { + case 0: return i18n("Key ID"); + case 1: return i18n("User ID"); + default: return QString::null; + } + } + + int ColumnStrategy::width( int col, const QFontMetrics & fm ) const { + if ( col == 0 ) { + static const char hexchars[] = "0123456789ABCDEF"; + int maxWidth = 0; + for ( unsigned int i = 0 ; i < 16 ; ++i ) + maxWidth = kMax( fm.width( QChar( hexchars[i] ) ), maxWidth ); + return 8 * maxWidth + 2 * mKeyGoodPix.width(); + } + return Kleo::KeyListView::ColumnStrategy::width( col, fm ); + } + + QString ColumnStrategy::text( const GpgME::Key & key, int col ) const { + switch ( col ) { + case 0: + { + if ( key.shortKeyID() ) + return QString::fromUtf8( key.shortKeyID() ); + else + return i18n("<unknown>"); + } + break; + case 1: + { + const char * uid = key.userID(0).id(); + if ( key.protocol() == GpgME::Context::OpenPGP ) + return uid && *uid ? QString::fromUtf8( uid ) : QString::null ; + else // CMS + return Kleo::DN( uid ).prettyDN(); + } + break; + default: return QString::null; + } + } + + QString ColumnStrategy::toolTip( const GpgME::Key & key, int ) const { + const char * uid = key.userID(0).id(); + const char * fpr = key.primaryFingerprint(); + const char * issuer = key.issuerName(); + const GpgME::Subkey subkey = key.subkey(0); + const QString expiry = subkey.neverExpires() ? i18n("never") : time_t2string( subkey.expirationTime() ) ; + const QString creation = time_t2string( subkey.creationTime() ); + if ( key.protocol() == GpgME::Context::OpenPGP ) + return i18n( "OpenPGP key for %1\n" + "Created: %2\n" + "Expiry: %3\n" + "Fingerprint: %4" ) + .arg( uid ? QString::fromUtf8( uid ) : i18n("unknown"), + creation, expiry, + fpr ? QString::fromLatin1( fpr ) : i18n("unknown") ); + else + return i18n( "S/MIME key for %1\n" + "Created: %2\n" + "Expiry: %3\n" + "Fingerprint: %4\n" + "Issuer: %5" ) + .arg( uid ? Kleo::DN( uid ).prettyDN() : i18n("unknown"), + creation, expiry, + fpr ? QString::fromLatin1( fpr ) : i18n("unknown") ) + .arg( issuer ? Kleo::DN( issuer ).prettyDN() : i18n("unknown") ); + } + + const QPixmap * ColumnStrategy::pixmap( const GpgME::Key & key, int col ) const { + if ( col != 0 ) + return 0; + // this key did not undergo a validating keylisting yet: + if ( !( key.keyListMode() & GpgME::Context::Validate ) ) + return &mKeyUnknownPix; + + if ( !checkKeyUsage( key, mKeyUsage ) ) + return &mKeyBadPix; + + if ( key.protocol() == GpgME::Context::CMS ) + return &mKeyGoodPix; + + switch ( key.userID(0).validity() ) { + default: + case GpgME::UserID::Unknown: + case GpgME::UserID::Undefined: + return &mKeyUnknownPix; + case GpgME::UserID::Never: + return &mKeyValidPix; + case GpgME::UserID::Marginal: + case GpgME::UserID::Full: + case GpgME::UserID::Ultimate: + return &mKeyGoodPix; + } + } + +} + + +static const int sCheckSelectionDelay = 250; + +Kleo::KeySelectionDialog::KeySelectionDialog( const QString & title, + const QString & text, + const std::vector<GpgME::Key> & selectedKeys, + unsigned int keyUsage, + bool extendedSelection, + bool rememberChoice, + QWidget * parent, const char * name, + bool modal ) + : KDialogBase( parent, name, modal, title, Default|Ok|Cancel|Help, Ok ), + mOpenPGPBackend( 0 ), + mSMIMEBackend( 0 ), + mRememberCB( 0 ), + mSelectedKeys( selectedKeys ), + mKeyUsage( keyUsage ), + mCurrentContextMenuItem( 0 ) +{ + init( rememberChoice, extendedSelection, text, QString::null ); +} + +Kleo::KeySelectionDialog::KeySelectionDialog( const QString & title, + const QString & text, + const QString & initialQuery, + unsigned int keyUsage, + bool extendedSelection, + bool rememberChoice, + QWidget * parent, const char * name, + bool modal ) + : KDialogBase( parent, name, modal, title, Default|Ok|Cancel|Help, Ok ), + mOpenPGPBackend( 0 ), + mSMIMEBackend( 0 ), + mRememberCB( 0 ), + mKeyUsage( keyUsage ), + mSearchText( initialQuery ), + mCurrentContextMenuItem( 0 ) +{ + init( rememberChoice, extendedSelection, text, initialQuery ); +} + +void Kleo::KeySelectionDialog::init( bool rememberChoice, bool extendedSelection, + const QString & text, const QString & initialQuery ) { + if ( mKeyUsage & OpenPGPKeys ) + mOpenPGPBackend = Kleo::CryptoBackendFactory::instance()->openpgp(); + if ( mKeyUsage & SMIMEKeys ) + mSMIMEBackend = Kleo::CryptoBackendFactory::instance()->smime(); + + mCheckSelectionTimer = new QTimer( this ); + mStartSearchTimer = new QTimer( this ); + + QFrame *page = makeMainWidget(); + mTopLayout = new QVBoxLayout( page, 0, spacingHint() ); + + if ( !text.isEmpty() ) { + QLabel* textLabel = new QLabel( text, page ); + textLabel->setAlignment( textLabel->alignment() | Qt::WordBreak ); + mTopLayout->addWidget( textLabel ); + } + + QHBoxLayout * hlay = new QHBoxLayout( mTopLayout ); // inherits spacing + QLineEdit * le = new QLineEdit( page ); + le->setText( initialQuery ); + QToolButton *clearButton = new QToolButton( page ); + clearButton->setIconSet( KGlobal::iconLoader()->loadIconSet( + KApplication::reverseLayout() ? "clear_left":"locationbar_erase", KIcon::Small, 0 ) ); + hlay->addWidget( clearButton ); + hlay->addWidget( new QLabel( le, i18n("&Search for:"), page ) ); + hlay->addWidget( le, 1 ); + le->setFocus(); + + connect( clearButton, SIGNAL( clicked() ), le, SLOT( clear() ) ); + connect( le, SIGNAL(textChanged(const QString&)), + this, SLOT(slotSearch(const QString&)) ); + connect( mStartSearchTimer, SIGNAL(timeout()), SLOT(slotFilter()) ); + + mKeyListView = new KeyListView( new ColumnStrategy( mKeyUsage ), 0, page, "mKeyListView" ); + mKeyListView->setResizeMode( QListView::LastColumn ); + mKeyListView->setRootIsDecorated( true ); + mKeyListView->setShowSortIndicator( true ); + mKeyListView->setSorting( 1, true ); // sort by User ID + mKeyListView->setShowToolTips( true ); + if ( extendedSelection ) + mKeyListView->setSelectionMode( QListView::Extended ); + mTopLayout->addWidget( mKeyListView, 10 ); + + if ( rememberChoice ) { + mRememberCB = new QCheckBox( i18n("&Remember choice"), page ); + mTopLayout->addWidget( mRememberCB ); + QWhatsThis::add( mRememberCB, + i18n("<qt><p>If you check this box your choice will " + "be stored and you will not be asked again." + "</p></qt>") ); + } + + connect( mCheckSelectionTimer, SIGNAL(timeout()), + SLOT(slotCheckSelection()) ); + connectSignals(); + + connect( mKeyListView, + SIGNAL(doubleClicked(Kleo::KeyListViewItem*,const QPoint&,int)), + SLOT(slotTryOk()) ); + connect( mKeyListView, + SIGNAL(contextMenu(Kleo::KeyListViewItem*,const QPoint&)), + SLOT(slotRMB(Kleo::KeyListViewItem*,const QPoint&)) ); + + setButtonText( KDialogBase::Default, i18n("&Reread Keys") ); + setButtonGuiItem( KDialogBase::Help, i18n("&Start Certificate Manager") ); + connect( this, SIGNAL(defaultClicked()), this, SLOT(slotRereadKeys()) ); + connect( this, SIGNAL(helpClicked()), this, SLOT(slotStartCertificateManager()) ); + + slotRereadKeys(); + mTopLayout->activate(); + + if ( kapp ) { + KWin::setIcons( winId(), kapp->icon(), kapp->miniIcon() ); + QSize dialogSize( 500, 400 ); + + KConfigGroup dialogConfig( KGlobal::config(), "Key Selection Dialog" ); + dialogSize = dialogConfig.readSizeEntry( "Dialog size", &dialogSize ); + resize( dialogSize ); + } +} + +Kleo::KeySelectionDialog::~KeySelectionDialog() { + KConfigGroup dialogConfig( KGlobal::config(), "Key Selection Dialog" ); + dialogConfig.writeEntry( "Dialog size", size() ); + dialogConfig.sync(); +} + + +void Kleo::KeySelectionDialog::connectSignals() { + if ( mKeyListView->isMultiSelection() ) + connect( mKeyListView, SIGNAL(selectionChanged()), + SLOT(slotSelectionChanged()) ); + else + connect( mKeyListView, SIGNAL(selectionChanged(Kleo::KeyListViewItem*)), + SLOT(slotCheckSelection(Kleo::KeyListViewItem*)) ); +} + +void Kleo::KeySelectionDialog::disconnectSignals() { + if ( mKeyListView->isMultiSelection() ) + disconnect( mKeyListView, SIGNAL(selectionChanged()), + this, SLOT(slotSelectionChanged()) ); + else + disconnect( mKeyListView, SIGNAL(selectionChanged(Kleo::KeyListViewItem*)), + this, SLOT(slotCheckSelection(Kleo::KeyListViewItem*)) ); +} + +const GpgME::Key & Kleo::KeySelectionDialog::selectedKey() const { + if ( mKeyListView->isMultiSelection() || !mKeyListView->selectedItem() ) + return GpgME::Key::null; + return mKeyListView->selectedItem()->key(); +} + +QString Kleo::KeySelectionDialog::fingerprint() const { + return selectedKey().primaryFingerprint(); +} + +QStringList Kleo::KeySelectionDialog::fingerprints() const { + QStringList result; + for ( std::vector<GpgME::Key>::const_iterator it = mSelectedKeys.begin() ; it != mSelectedKeys.end() ; ++it ) + if ( const char * fpr = it->primaryFingerprint() ) + result.push_back( fpr ); + return result; +} + +QStringList Kleo::KeySelectionDialog::pgpKeyFingerprints() const { + QStringList result; + for ( std::vector<GpgME::Key>::const_iterator it = mSelectedKeys.begin() ; it != mSelectedKeys.end() ; ++it ) + if ( it->protocol() == GpgME::Context::OpenPGP ) + if ( const char * fpr = it->primaryFingerprint() ) + result.push_back( fpr ); + return result; +} + +QStringList Kleo::KeySelectionDialog::smimeFingerprints() const { + QStringList result; + for ( std::vector<GpgME::Key>::const_iterator it = mSelectedKeys.begin() ; it != mSelectedKeys.end() ; ++it ) + if ( it->protocol() == GpgME::Context::CMS ) + if ( const char * fpr = it->primaryFingerprint() ) + result.push_back( fpr ); + return result; +} + +void Kleo::KeySelectionDialog::slotRereadKeys() { + mKeyListView->clear(); + mListJobCount = 0; + mTruncated = 0; + mSavedOffsetY = mKeyListView->contentsY(); + + disconnectSignals(); + mKeyListView->setEnabled( false ); + + // FIXME: save current selection + if ( mOpenPGPBackend ) + startKeyListJobForBackend( mOpenPGPBackend, std::vector<GpgME::Key>(), false /*non-validating*/ ); + if ( mSMIMEBackend ) + startKeyListJobForBackend( mSMIMEBackend, std::vector<GpgME::Key>(), false /*non-validating*/ ); + + if ( mListJobCount == 0 ) { + mKeyListView->setEnabled( true ); + KMessageBox::information( this, + i18n("No backends found for listing keys. " + "Check your installation."), + i18n("Key Listing Failed") ); + connectSignals(); + } +} + +void Kleo::KeySelectionDialog::slotHelp() +{ + emit helpClicked(); +} + +void Kleo::KeySelectionDialog::slotStartCertificateManager() +{ + KProcess certManagerProc; + certManagerProc << "kleopatra"; + + if( !certManagerProc.start( KProcess::DontCare ) ) + KMessageBox::error( this, i18n( "Could not start certificate manager; " + "please check your installation." ), + i18n( "Certificate Manager Error" ) ); + else + kdDebug(5006) << "\nslotStartCertManager(): certificate manager started.\n" << endl; +} + +#ifndef __KLEO_UI_SHOW_KEY_LIST_ERROR_H__ +#define __KLEO_UI_SHOW_KEY_LIST_ERROR_H__ +static void showKeyListError( QWidget * parent, const GpgME::Error & err ) { + assert( err ); + const QString msg = i18n( "<qt><p>An error occurred while fetching " + "the keys from the backend:</p>" + "<p><b>%1</b></p></qt>" ) + .arg( QString::fromLocal8Bit( err.asString() ) ); + + KMessageBox::error( parent, msg, i18n( "Key Listing Failed" ) ); +} +#endif // __KLEO_UI_SHOW_KEY_LIST_ERROR_H__ + +namespace { + struct ExtractFingerprint { + QString operator()( const GpgME::Key & key ) { + return key.primaryFingerprint(); + } + }; +} + +void Kleo::KeySelectionDialog::startKeyListJobForBackend( const CryptoBackend::Protocol * backend, const std::vector<GpgME::Key> & keys, bool validate ) { + assert( backend ); + KeyListJob * job = backend->keyListJob( false, false, validate ); // local, w/o sigs, validation as givem + if ( !job ) + return; + + connect( job, SIGNAL(result(const GpgME::KeyListResult&)), + SLOT(slotKeyListResult(const GpgME::KeyListResult&)) ); + connect( job, SIGNAL(nextKey(const GpgME::Key&)), + mKeyListView, validate ? + SLOT(slotRefreshKey(const GpgME::Key&)) : + SLOT(slotAddKey(const GpgME::Key&)) ); + + QStringList fprs; + std::transform( keys.begin(), keys.end(), std::back_inserter( fprs ), ExtractFingerprint() ); + const GpgME::Error err = job->start( fprs, mKeyUsage & SecretKeys && !( mKeyUsage & PublicKeys ) ); + + if ( err ) + return showKeyListError( this, err ); + + // FIXME: create a MultiProgressDialog: + (void)new ProgressDialog( job, validate ? i18n( "Checking selected keys..." ) : i18n( "Fetching keys..." ), this ); + ++mListJobCount; +} + +static void selectKeys( Kleo::KeyListView * klv, const std::vector<GpgME::Key> & selectedKeys ) { + klv->clearSelection(); + if ( selectedKeys.empty() ) + return; + for ( std::vector<GpgME::Key>::const_iterator it = selectedKeys.begin() ; it != selectedKeys.end() ; ++it ) + if ( Kleo::KeyListViewItem * item = klv->itemByFingerprint( it->primaryFingerprint() ) ) + item->setSelected( true ); +} + +void Kleo::KeySelectionDialog::slotKeyListResult( const GpgME::KeyListResult & res ) { + if ( res.error() ) + showKeyListError( this, res.error() ); + else if ( res.isTruncated() ) + ++mTruncated; + + if ( --mListJobCount > 0 ) + return; // not yet finished... + + if ( mTruncated > 0 ) + KMessageBox::information( this, + i18n("<qt>One backend returned truncated output.<br>" + "Not all available keys are shown</qt>", + "<qt>%n backends returned truncated output.<br>" + "Not all available keys are shown</qt>", + mTruncated), + i18n("Key List Result") ); + + mKeyListView->flushKeys(); + + mKeyListView->setEnabled( true ); + mListJobCount = mTruncated = 0; + mKeysToCheck.clear(); + + selectKeys( mKeyListView, mSelectedKeys ); + + slotFilter(); + + connectSignals(); + + slotSelectionChanged(); + + // restore the saved position of the contents + mKeyListView->setContentsPos( 0, mSavedOffsetY ); mSavedOffsetY = 0; +} + +void Kleo::KeySelectionDialog::slotSelectionChanged() { + kdDebug(5150) << "KeySelectionDialog::slotSelectionChanged()" << endl; + + // (re)start the check selection timer. Checking the selection is delayed + // because else drag-selection doesn't work very good (checking key trust + // is slow). + mCheckSelectionTimer->start( sCheckSelectionDelay ); +} + +namespace { + struct AlreadyChecked { + bool operator()( const GpgME::Key & key ) const { + return key.keyListMode() & GpgME::Context::Validate ; + } + }; +} + +void Kleo::KeySelectionDialog::slotCheckSelection( KeyListViewItem * item ) { + kdDebug(5150) << "KeySelectionDialog::slotCheckSelection()\n"; + + mCheckSelectionTimer->stop(); + + mSelectedKeys.clear(); + + if ( !mKeyListView->isMultiSelection() ) { + if ( item ) + mSelectedKeys.push_back( item->key() ); + } + + for ( KeyListViewItem * it = mKeyListView->firstChild() ; it ; it = it->nextSibling() ) + if ( it->isSelected() ) + mSelectedKeys.push_back( it->key() ); + + mKeysToCheck.clear(); + std::remove_copy_if( mSelectedKeys.begin(), mSelectedKeys.end(), + std::back_inserter( mKeysToCheck ), + AlreadyChecked() ); + if ( mKeysToCheck.empty() ) { + enableButtonOK( !mSelectedKeys.empty() && + checkKeyUsage( mSelectedKeys, mKeyUsage ) ); + return; + } + + // performed all fast checks - now for validating key listing: + startValidatingKeyListing(); +} + +void Kleo::KeySelectionDialog::startValidatingKeyListing() { + if ( mKeysToCheck.empty() ) + return; + + mListJobCount = 0; + mTruncated = 0; + mSavedOffsetY = mKeyListView->contentsY(); + + disconnectSignals(); + mKeyListView->setEnabled( false ); + + std::vector<GpgME::Key> smime, openpgp; + for ( std::vector<GpgME::Key>::const_iterator it = mKeysToCheck.begin() ; it != mKeysToCheck.end() ; ++it ) + if ( it->protocol() == GpgME::Context::OpenPGP ) + openpgp.push_back( *it ); + else + smime.push_back( *it ); + + if ( !openpgp.empty() ) { + assert( mOpenPGPBackend ); + startKeyListJobForBackend( mOpenPGPBackend, openpgp, true /*validate*/ ); + } + if ( !smime.empty() ) { + assert( mSMIMEBackend ); + startKeyListJobForBackend( mSMIMEBackend, smime, true /*validate*/ ); + } + + assert( mListJobCount > 0 ); +} + +bool Kleo::KeySelectionDialog::rememberSelection() const { + return mRememberCB && mRememberCB->isChecked() ; +} + +void Kleo::KeySelectionDialog::slotRMB( Kleo::KeyListViewItem * item, const QPoint & p ) { + if ( !item ) return; + + mCurrentContextMenuItem = item; + + QPopupMenu menu; + menu.insertItem( i18n( "Recheck Key" ), this, SLOT(slotRecheckKey()) ); + menu.exec( p ); +} + +void Kleo::KeySelectionDialog::slotRecheckKey() { + if ( !mCurrentContextMenuItem || mCurrentContextMenuItem->key().isNull() ) + return; + + mKeysToCheck.clear(); + mKeysToCheck.push_back( mCurrentContextMenuItem->key() ); +} + +void Kleo::KeySelectionDialog::slotTryOk() { + if ( actionButton( Ok )->isEnabled() ) + slotOk(); +} + +void Kleo::KeySelectionDialog::slotOk() { + if ( mCheckSelectionTimer->isActive() ) + slotCheckSelection(); + // button could be disabled again after checking the selected key + if ( !actionButton( Ok )->isEnabled() ) + return; + mStartSearchTimer->stop(); + accept(); +} + + +void Kleo::KeySelectionDialog::slotCancel() { + mCheckSelectionTimer->stop(); + mStartSearchTimer->stop(); + reject(); +} + +void Kleo::KeySelectionDialog::slotSearch( const QString & text ) { + mSearchText = text.stripWhiteSpace().upper(); + slotSearch(); +} + +void Kleo::KeySelectionDialog::slotSearch() { + mStartSearchTimer->start( sCheckSelectionDelay, true /*single-shot*/ ); +} + +void Kleo::KeySelectionDialog::slotFilter() { + if ( mSearchText.isEmpty() ) { + showAllItems(); + return; + } + + // OK, so we need to filter: + QRegExp keyIdRegExp( "(?:0x)?[A-F0-9]{1,8}", false /*case-insens.*/ ); + if ( keyIdRegExp.exactMatch( mSearchText ) ) { + if ( mSearchText.startsWith( "0X" ) ) + // search for keyID only: + filterByKeyID( mSearchText.mid( 2 ) ); + else + // search for UID and keyID: + filterByKeyIDOrUID( mSearchText ); + } else { + // search in UID: + filterByUID( mSearchText ); + } +} + +void Kleo::KeySelectionDialog::filterByKeyID( const QString & keyID ) { + assert( keyID.length() <= 8 ); + assert( !keyID.isEmpty() ); // regexp in slotFilter should prevent these + if ( keyID.isEmpty() ) + showAllItems(); + else + for ( KeyListViewItem * item = mKeyListView->firstChild() ; item ; item = item->nextSibling() ) + item->setVisible( item->text( 0 ).upper().startsWith( keyID ) ); +} + +static bool anyUIDMatches( const Kleo::KeyListViewItem * item, QRegExp & rx ) { + if ( !item ) + return false; + + const std::vector<GpgME::UserID> uids = item->key().userIDs(); + for ( std::vector<GpgME::UserID>::const_iterator it = uids.begin() ; it != uids.end() ; ++it ) + if ( it->id() && rx.search( QString::fromUtf8( it->id() ) ) >= 0 ) + return true; + return false; +} + +void Kleo::KeySelectionDialog::filterByKeyIDOrUID( const QString & str ) { + assert( !str.isEmpty() ); + + // match beginnings of words: + QRegExp rx( "\\b" + QRegExp::escape( str ), false ); + + for ( KeyListViewItem * item = mKeyListView->firstChild() ; item ; item = item->nextSibling() ) + item->setVisible( item->text( 0 ).upper().startsWith( str ) || anyUIDMatches( item, rx ) ); + +} + +void Kleo::KeySelectionDialog::filterByUID( const QString & str ) { + assert( !str.isEmpty() ); + + // match beginnings of words: + QRegExp rx( "\\b" + QRegExp::escape( str ), false ); + + for ( KeyListViewItem * item = mKeyListView->firstChild() ; item ; item = item->nextSibling() ) + item->setVisible( anyUIDMatches( item, rx ) ); +} + + +void Kleo::KeySelectionDialog::showAllItems() { + for ( KeyListViewItem * item = mKeyListView->firstChild() ; item ; item = item->nextSibling() ) + item->setVisible( true ); +} + +#include "keyselectiondialog.moc" diff --git a/certmanager/lib/ui/keyselectiondialog.h b/certmanager/lib/ui/keyselectiondialog.h new file mode 100644 index 000000000..f274398b1 --- /dev/null +++ b/certmanager/lib/ui/keyselectiondialog.h @@ -0,0 +1,179 @@ +/* -*- c++ -*- + keyselectiondialog.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarävdalens Datakonsult AB + + Based on kpgpui.h + Copyright (C) 2001,2002 the KPGP authors + See file libkdenetwork/AUTHORS.kpgp for details + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_UI_KEYSELECTIONDIALOG_H__ +#define __KLEO_UI_KEYSELECTIONDIALOG_H__ + +#include <kdialogbase.h> + +#include <kleo/cryptobackend.h> +#include <gpgmepp/key.h> +#include <kdepimmacros.h> +#include <vector> + +class QVBoxLayout; +class QCheckBox; +class QPixmap; +class QTimer; +class QListViewItem; +class QRegExp; +class QPoint; + +namespace Kleo { + class KeyListView; + class KeyListViewItem; +} + +namespace GpgME { + class KeyListResult; +} + +namespace Kleo { + + class KDE_EXPORT KeySelectionDialog : public KDialogBase { + Q_OBJECT + public: + + enum KeyUsage { + PublicKeys = 1, + SecretKeys = 2, + EncryptionKeys = 4, + SigningKeys = 8, + ValidKeys = 16, + TrustedKeys = 32, + CertificationKeys = 64, + AuthenticationKeys = 128, + OpenPGPKeys = 256, + SMIMEKeys = 512, + AllKeys = PublicKeys | SecretKeys | OpenPGPKeys | SMIMEKeys, + ValidEncryptionKeys = AllKeys | EncryptionKeys | ValidKeys, + ValidTrustedEncryptionKeys = AllKeys | EncryptionKeys | ValidKeys | TrustedKeys + }; + + KeySelectionDialog( const QString & title, + const QString & text, + const std::vector<GpgME::Key> & selectedKeys=std::vector<GpgME::Key>(), + unsigned int keyUsage=AllKeys, + bool extendedSelection=false, + bool rememberChoice=false, + QWidget * parent=0, const char * name=0, + bool modal=true ); + KeySelectionDialog( const QString & title, + const QString & text, + const QString & initialPattern, + unsigned int keyUsage=AllKeys, + bool extendedSelection=false, + bool rememberChoice=false, + QWidget * parent=0, const char * name=0, + bool modal=true ); + ~KeySelectionDialog(); + + /** Returns the key ID of the selected key in single selection mode. + Otherwise it returns a null key. */ + const GpgME::Key & selectedKey() const; + + QString fingerprint() const; + + /** Returns a list of selected key IDs. */ + const std::vector<GpgME::Key> & selectedKeys() const { return mSelectedKeys; } + + /// Return all the selected fingerprints + QStringList fingerprints() const; + + /// Return the selected openpgp fingerprints + QStringList pgpKeyFingerprints() const; + /// Return the selected smime fingerprints + QStringList smimeFingerprints() const; + + bool rememberSelection() const; + protected slots: + // reimplemented to avoid popping up the help, since we + // override the button + void slotHelp(); + + // Could be used by derived classes to insert their own widget + QVBoxLayout* topLayout() const { return mTopLayout; } + + private slots: + void slotRereadKeys(); + void slotStartCertificateManager(); + void slotKeyListResult( const GpgME::KeyListResult & ); + void slotSelectionChanged(); + void slotCheckSelection() { slotCheckSelection( 0 ); } + void slotCheckSelection( Kleo::KeyListViewItem * ); + void slotRMB( Kleo::KeyListViewItem *, const QPoint & ); + void slotRecheckKey(); + void slotTryOk(); + void slotOk(); + void slotCancel(); + void slotSearch( const QString & text ); + void slotSearch(); + void slotFilter(); + + private: + void filterByKeyID( const QString & keyID ); + void filterByKeyIDOrUID( const QString & keyID ); + void filterByUID( const QString & uid ); + void showAllItems(); + bool anyChildMatches( const Kleo::KeyListViewItem * item, QRegExp & rx ) const; + + void connectSignals(); + void disconnectSignals(); + + void startKeyListJobForBackend( const Kleo::CryptoBackend::Protocol *, const std::vector<GpgME::Key> &, bool ); + void startValidatingKeyListing(); + + void init( bool, bool, const QString &, const QString & ); + + private: + QVBoxLayout* mTopLayout; + Kleo::KeyListView * mKeyListView; + const Kleo::CryptoBackend::Protocol * mOpenPGPBackend; + const Kleo::CryptoBackend::Protocol * mSMIMEBackend; + QCheckBox * mRememberCB; + std::vector<GpgME::Key> mSelectedKeys, mKeysToCheck; + unsigned int mKeyUsage; + QTimer * mCheckSelectionTimer; + QTimer * mStartSearchTimer; + // cross-eventloop temporaries: + QString mSearchText; + Kleo::KeyListViewItem * mCurrentContextMenuItem; + int mTruncated, mListJobCount, mSavedOffsetY; + }; + +} + +#endif // __KLEO_UI_KEYSELECTIONDIALOG_H__ diff --git a/certmanager/lib/ui/messagebox.cpp b/certmanager/lib/ui/messagebox.cpp new file mode 100644 index 000000000..283d33108 --- /dev/null +++ b/certmanager/lib/ui/messagebox.cpp @@ -0,0 +1,265 @@ +/* + messagebox.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "messagebox.h" + +#include "kleo/job.h" + +#include <gpgmepp/signingresult.h> +#include <gpgmepp/encryptionresult.h> + +#include <kfiledialog.h> +#include <kdialogbase.h> +#include <klocale.h> +#include <ksavefile.h> +#include <kguiitem.h> + +#include <qtextedit.h> +#include <qtextstream.h> +#include <qvbox.h> + +using namespace Kleo; +using namespace GpgME; + +namespace { + +static KGuiItem KGuiItem_save() { + return KGuiItem( i18n("&Save to Disk..."), "filesaveas" ); +} + +static KGuiItem KGuiItem_copy() { + return KGuiItem( i18n("&Copy to Clipboard"), "editcopy", i18n("Copy Audit Log to Clipboard") ); +} + +static KGuiItem KGuiItem_showAuditLog() { + return KGuiItem( i18n("&Show Audit Log") ); // "view_log"? +} + +class AuditLogViewer : public KDialogBase { + // Q_OBJECT +public: + explicit AuditLogViewer( const QString & log, QWidget * parent=0, const char * name=0, WFlags f=0 ) + : KDialogBase( parent, name, false, i18n("View GnuPG Audit Log"), + Close|User1|User2, Close, false, KGuiItem_save(), KGuiItem_copy() ), + m_textEdit( new QTextEdit( this, "m_textEdit" ) ) + { + setWFlags( f ); + setMainWidget( m_textEdit ); + m_textEdit->setTextFormat( QTextEdit::RichText ); + m_textEdit->setReadOnly( true ); + setAuditLog( log ); + } + ~AuditLogViewer() {} + + void setAuditLog( const QString & log ) { + m_textEdit->setText( log ); + } + +private: + void slotUser1() { + const QString fileName = KFileDialog::getSaveFileName( QString(), QString(), + this, i18n("Choose File to Save GnuPG Audit Log to") ); + if ( fileName.isEmpty() ) + return; + + KSaveFile file( fileName ); + + if ( QTextStream * const s = file.textStream() ) { + *s << m_textEdit->text() << endl; + file.close(); + } + + if ( const int err = file.status() ) + KMessageBox::error( this, i18n("Couldn't save to file \"%1\": %2") + .arg( file.name(), QString::fromLocal8Bit( strerror( err ) ) ), + i18n("File Save Error") ); + } + void slotUser2() { + m_textEdit->selectAll(); + m_textEdit->copy(); + m_textEdit->selectAll( false ); + } + +private: + QTextEdit * m_textEdit; +}; + +} // anon namespace + +// static +void MessageBox::auditLog( QWidget * parent, const Job * job, const QString & caption ) { + + if ( !job ) + return; + + if ( !GpgME::hasFeature( AuditLogFeature ) ) { + KMessageBox::information( parent, i18n("Your system does not have support for GnuPG Audit Logs"), + i18n("System Error") ); + return; + } + + const QString log = job->auditLogAsHtml(); + if ( log.isEmpty() ) { + KMessageBox::information( parent, i18n("No GnuPG Audit Log available for this operation."), + i18n("No GnuPG Audit Log") ); + return; + } + + auditLog( parent, log, caption ); +} + +// static +void MessageBox::auditLog( QWidget * parent, const QString & log, const QString & caption ) { + AuditLogViewer * const alv = new AuditLogViewer( "<qt>" + log + "</qt>", parent, "alv", Qt::WDestructiveClose ); + alv->setCaption( caption ); + alv->show(); +} + +// static +void MessageBox::auditLog( QWidget * parent, const Job * job ) { + auditLog( parent, job, i18n("GnuPG Audit Log Viewer") ); +} + +// static +void MessageBox::auditLog( QWidget * parent, const QString & log ) { + auditLog( parent, log, i18n("GnuPG Audit Log Viewer") ); +} + +static QString to_information_string( const SigningResult & result ) { + return result.error() + ? i18n("Signing failed: %1").arg( QString::fromLocal8Bit( result.error().asString() ) ) + : i18n("Signing successful") ; +} + +static QString to_error_string( const SigningResult & result ) { + return to_information_string( result ); +} + +static QString to_information_string( const EncryptionResult & result ) { + return result.error() + ? i18n("Encryption failed: %1").arg( QString::fromLocal8Bit( result.error().asString() ) ) + : i18n("Encryption successful") ; +} + +static QString to_error_string( const EncryptionResult & result ) { + return to_information_string( result ); +} + +static QString to_information_string( const SigningResult & sresult, const EncryptionResult & eresult ) { + return to_information_string( sresult ) + '\n' + to_information_string( eresult ); +} + +static QString to_error_string( const SigningResult & sresult, const EncryptionResult & eresult ) { + return to_information_string( sresult, eresult ); +} + +// static +void MessageBox::information( QWidget * parent, const SigningResult & result, const Job * job, int options ) { + information( parent, result, job, i18n("Signing Result"), options ); +} + +// static +void MessageBox::information( QWidget * parent, const SigningResult & result, const Job * job, const QString & caption, int options ) { + make( parent, QMessageBox::Information, to_information_string( result ), job, caption, options ); +} + +// static +void MessageBox::error( QWidget * parent, const SigningResult & result, const Job * job, int options ) { + error( parent, result, job, i18n("Signing Error"), options ); +} + +// static +void MessageBox::error( QWidget * parent, const SigningResult & result, const Job * job, const QString & caption, int options ) { + make( parent, QMessageBox::Critical, to_error_string( result ), job, caption, options ); +} + +// static +void MessageBox::information( QWidget * parent, const EncryptionResult & result, const Job * job, int options ) { + information( parent, result, job, i18n("Encryption Result"), options ); +} + +// static +void MessageBox::information( QWidget * parent, const EncryptionResult & result, const Job * job, const QString & caption, int options ) { + make( parent, QMessageBox::Information, to_information_string( result ), job, caption, options ); +} + +// static +void MessageBox::error( QWidget * parent, const EncryptionResult & result, const Job * job, int options ) { + error( parent, result, job, i18n("Encryption Error"), options ); +} + +// static +void MessageBox::error( QWidget * parent, const EncryptionResult & result, const Job * job, const QString & caption, int options ) { + make( parent, QMessageBox::Critical, to_error_string( result ), job, caption, options ); +} + +// static +void MessageBox::information( QWidget * parent, const SigningResult & sresult, const EncryptionResult & eresult, const Job * job, int options ) { + information( parent, sresult, eresult, job, i18n("Encryption Result"), options ); +} + +// static +void MessageBox::information( QWidget * parent, const SigningResult & sresult, const EncryptionResult & eresult, const Job * job, const QString & caption, int options ) { + make( parent, QMessageBox::Information, to_information_string( sresult, eresult ), job, caption, options ); +} + +// static +void MessageBox::error( QWidget * parent, const SigningResult & sresult, const EncryptionResult & eresult, const Job * job, int options ) { + error( parent, sresult, eresult, job, i18n("Encryption Error"), options ); +} + +// static +void MessageBox::error( QWidget * parent, const SigningResult & sresult, const EncryptionResult & eresult, const Job * job, const QString & caption, int options ) { + make( parent, QMessageBox::Critical, to_error_string( sresult, eresult ), job, caption, options ); +} + +// static +void MessageBox::make( QWidget * parent, QMessageBox::Icon icon, const QString & text, const Job * job, const QString & caption, int options ) { + KDialogBase * dialog = GpgME::hasFeature( GpgME::AuditLogFeature ) + ? new KDialogBase( caption, KDialogBase::Yes | KDialogBase::No, + KDialogBase::Yes, KDialogBase::Yes, + parent, "error", true, true, + KStdGuiItem::ok(), KGuiItem_showAuditLog() ) + : new KDialogBase( caption, KDialogBase::Yes, + KDialogBase::Yes, KDialogBase::Yes, + parent, "error", true, true, + KStdGuiItem::ok() ) ; + if ( options & KMessageBox::PlainCaption ) + dialog->setPlainCaption( caption ); + + if ( KDialogBase::No == KMessageBox::createKMessageBox( dialog, icon, text, QStringList(), QString::null, 0, options ) ) + auditLog( 0, job ); +} diff --git a/certmanager/lib/ui/messagebox.h b/certmanager/lib/ui/messagebox.h new file mode 100644 index 000000000..a84f86e11 --- /dev/null +++ b/certmanager/lib/ui/messagebox.h @@ -0,0 +1,83 @@ +/* + messagebox.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2007 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_UI_MESSAGEBOX_H__ +#define __KLEO_UI_MESSAGEBOX_H__ + +#include <kmessagebox.h> + +namespace GpgME { + class SigningResult; + class EncryptionResult; + class DecryptionResult; + class VerificationResult; +} + +namespace Kleo { + class Job; +} + +class QWidget; +class QString; + +namespace Kleo { + + class MessageBox { + public: + static void information( QWidget * parent, const GpgME::SigningResult & result, const Kleo::Job * job, const QString & caption, int options=KMessageBox::Notify ); + static void information( QWidget * parent, const GpgME::SigningResult & result, const Kleo::Job * job, int options=KMessageBox::Notify ); + static void error( QWidget * parent, const GpgME::SigningResult & result, const Kleo::Job * job, const QString & caption, int options=KMessageBox::Notify ); + static void error( QWidget * parent, const GpgME::SigningResult & result, const Kleo::Job * job, int options=KMessageBox::Notify ); + + static void information( QWidget * parent, const GpgME::EncryptionResult & result, const Kleo::Job * job, const QString & caption, int options=KMessageBox::Notify ); + static void information( QWidget * parent, const GpgME::EncryptionResult & result, const Kleo::Job * job, int options=KMessageBox::Notify ); + static void error( QWidget * parent, const GpgME::EncryptionResult & result, const Kleo::Job * job, const QString & caption, int options=KMessageBox::Notify ); + static void error( QWidget * parent, const GpgME::EncryptionResult & result, const Kleo::Job * job, int options=KMessageBox::Notify ); + + static void information( QWidget * parent, const GpgME::SigningResult & sresult, const GpgME::EncryptionResult & eresult, const Kleo::Job * job, const QString & caption, int options=KMessageBox::Notify ); + static void information( QWidget * parent, const GpgME::SigningResult & sresult, const GpgME::EncryptionResult & eresult, const Kleo::Job * job, int options=KMessageBox::Notify ); + static void error( QWidget * parent, const GpgME::SigningResult & sresult, const GpgME::EncryptionResult & eresult, const Kleo::Job * job, const QString & caption, int options=KMessageBox::Notify ); + static void error( QWidget * parent, const GpgME::SigningResult & sresult, const GpgME::EncryptionResult & eresult, const Kleo::Job * job, int options=KMessageBox::Notify ); + + static void auditLog( QWidget * parent, const Kleo::Job * job, const QString & caption ); + static void auditLog( QWidget * parent, const Kleo::Job * job ); + static void auditLog( QWidget * parent, const QString & log, const QString & caption ); + static void auditLog( QWidget * parent, const QString & log ); + + private: + static void make( QWidget * parent, QMessageBox::Icon icon, const QString & text, const Kleo::Job * job, const QString & caption, int options ); + }; + + +} + +#endif /* __KLEO_UI_MESSAGEBOX_H__ */ diff --git a/certmanager/lib/ui/passphrasedialog.cpp b/certmanager/lib/ui/passphrasedialog.cpp new file mode 100644 index 000000000..5915387f5 --- /dev/null +++ b/certmanager/lib/ui/passphrasedialog.cpp @@ -0,0 +1,123 @@ +/* -*- c++ -*- + passphrasedialog.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. + + + Based on kpgpui.cpp + Copyright (C) 2001,2002 the KPGP authors + See file libkdenetwork/AUTHORS.kpgp for details + + This file is part of KPGP, the KDE PGP/GnuPG support library. + + KPGP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +*/ + +#ifndef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "passphrasedialog.h" + +#include <kpassdlg.h> +#include <kiconloader.h> +#include <klocale.h> + +#include <qlabel.h> +#include <qlayout.h> +#include <qfontmetrics.h> + +struct Kleo::PassphraseDialog::Private { + KPasswordEdit * lineedit; +}; + + +Kleo::PassphraseDialog::PassphraseDialog( const QString & msg, const QString & caption, + QWidget * parent, const char * name, bool modal ) + : KDialogBase( parent, name, modal, caption, Ok|Cancel, Ok ), d( 0 ) +{ + d = new Private(); + + QWidget * w = new QWidget( this ); + setMainWidget( w ); + + QHBoxLayout * hlay = new QHBoxLayout( w, 0, spacingHint() ); + + QLabel * label = new QLabel( w ); + label->setPixmap( DesktopIcon( "pgp-keys", KIcon::SizeMedium ) ); + hlay->addWidget( label, 0, AlignTop ); + + QVBoxLayout * vlay = new QVBoxLayout( hlay ); // inherits spacing + + vlay->addWidget( new QLabel( msg.isEmpty() ? i18n("Please enter your passphrase:") : msg, w ) ); + + d->lineedit = new KPasswordEdit( KPasswordEdit::OneStar, w, "d->lineedit" ); + d->lineedit->setMinimumWidth( fontMetrics().width("*") * 20 ); + d->lineedit->setFocus(); + + vlay->addWidget( d->lineedit ); + + connect( d->lineedit, SIGNAL(returnPressed()), SLOT(slotOk()) ); + + disableResize(); +} + + +Kleo::PassphraseDialog::~PassphraseDialog() { + delete d; d = 0; +} + +const char * Kleo::PassphraseDialog::passphrase() const { + return d->lineedit->password(); +} + +void Kleo::PassphraseDialog::slotOk() { + const char * pass = passphrase(); + emit finished( pass ? pass : "" ); + KDialogBase::slotOk(); +} + +void Kleo::PassphraseDialog::slotCancel() { + emit canceled(); + KDialogBase::slotCancel(); +} + + +void Kleo::PassphraseDialog::virtual_hook( int id, void * data ) { + return KDialogBase::virtual_hook( id, data ); +} + +#include "passphrasedialog.moc" diff --git a/certmanager/lib/ui/passphrasedialog.h b/certmanager/lib/ui/passphrasedialog.h new file mode 100644 index 000000000..12a434e13 --- /dev/null +++ b/certmanager/lib/ui/passphrasedialog.h @@ -0,0 +1,91 @@ +/* -*- c++ -*- + passphrasedialog.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. + + + Based on kpgpui.h + Copyright (C) 2001,2002 the KPGP authors + See file libkdenetwork/AUTHORS.kpgp for details + + This file is part of KPGP, the KDE PGP/GnuPG support library. + + KPGP is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +*/ + +#ifndef __KLEO_UI_PASSPHRASEDIALOG_H__ +#define __KLEO_UI_PASSPHRASEDIALOG_H__ + +#include <kdialogbase.h> + +namespace Kleo { + + class PassphraseDialog : public KDialogBase { + Q_OBJECT + public: + PassphraseDialog( const QString & description, + const QString & caption=QString::null, + QWidget * parent=0, const char * name=0, + bool modal=true ); + ~PassphraseDialog(); + + const char * passphrase() const; + + signals: + /** emitted when the user clicks Ok. \a pass is never NULL. + \c pass only valid inside slots connected to this signal. + */ + void finished( const char * pass ); + /** emitted when the user clicks Cancel. */ + void canceled(); + + protected slots: + /*! \reimp */ + void slotOk(); + /*! \reimp */ + void slotCancel(); + + private: + class Private; + Private * d; + protected: + /*! \reimp */ + void virtual_hook( int, void* ); + }; + +} // namespace Kleo + +#endif // __KLEO_UI_PASSPHRASEDIALOG_H__ diff --git a/certmanager/lib/ui/progressbar.cpp b/certmanager/lib/ui/progressbar.cpp new file mode 100644 index 000000000..96f51fa8a --- /dev/null +++ b/certmanager/lib/ui/progressbar.cpp @@ -0,0 +1,111 @@ +/* + progressbar.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "config.h" +#include "progressbar.h" + +#include <qtimer.h> +#include <kdebug.h> + +static const int busyTimerTickInterval = 100; +static const int busyTimerTickIncrement = 5; + +Kleo::ProgressBar::ProgressBar( QWidget * parent, const char * name, WFlags f ) + : QProgressBar( 0, parent, name, f ), + mRealProgress( -1 ) +{ + mBusyTimer = new QTimer( this ); + connect( mBusyTimer, SIGNAL(timeout()), SLOT(slotBusyTimerTick()) ); + fixup( true ); +} + +void Kleo::ProgressBar::slotProgress( const QString &, int cur, int tot ) { + setProgress( cur, tot ); +} + +void Kleo::ProgressBar::slotProgress( const QString &, int, int cur, int tot ) { + setProgress( cur, tot ); +} + +void Kleo::ProgressBar::setTotalSteps( int total ) { + kdDebug() << "Kleo::ProgressBar::setTotalSteps( " << total << " )" << endl; + if ( total == totalSteps() ) + return; + QProgressBar::setTotalSteps( 0 ); + fixup( false ); +} + +void Kleo::ProgressBar::setProgress( int p ) { + kdDebug() << "Kleo::ProgressBar::setProgress( " << p << " )" << endl; + mRealProgress = p; + fixup( true ); +} + +void Kleo::ProgressBar::reset() { + mRealProgress = -1; + fixup( true ); +} + +void Kleo::ProgressBar::slotBusyTimerTick() { + fixup( false ); + if ( mBusyTimer->isActive() ) + QProgressBar::setProgress( QProgressBar::progress() + busyTimerTickIncrement ); +} + +void Kleo::ProgressBar::fixup( bool newValue ) { + const int cur = QProgressBar::progress(); + const int tot = QProgressBar::totalSteps(); + + kdDebug() << "Kleo::ProgressBar::startStopBusyTimer() cur = " << cur << "; tot = " << tot << "; real = " << mRealProgress << endl; + + if ( ( newValue && mRealProgress < 0 ) || ( !newValue && cur < 0 ) ) { + kdDebug() << "(new value) switch to reset" << endl; + mBusyTimer->stop(); + if ( newValue ) + QProgressBar::reset(); + mRealProgress = -1; + } else if ( tot == 0 ) { + kdDebug() << "(new value) switch or stay in busy" << endl; + if ( !mBusyTimer->isActive() ) { + mBusyTimer->start( busyTimerTickInterval ); + if ( newValue ) + QProgressBar::setProgress( mRealProgress ); + } + } else { + kdDebug() << "(new value) normal progress" << endl; + mBusyTimer->stop(); + if ( QProgressBar::progress() != mRealProgress ) + QProgressBar::setProgress( mRealProgress ); + } +} + +#include "progressbar.moc" diff --git a/certmanager/lib/ui/progressbar.h b/certmanager/lib/ui/progressbar.h new file mode 100644 index 000000000..41d96796d --- /dev/null +++ b/certmanager/lib/ui/progressbar.h @@ -0,0 +1,74 @@ +/* + progressbar.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_PROGRESSBAR_H__ +#define __KLEO_PROGRESSBAR_H__ + +#include <qprogressbar.h> +#include <kdepimmacros.h> +class QTimer; + +namespace Kleo { + + /** + @short A QProgressBar with self-powered busy indicator + */ + class KDE_EXPORT ProgressBar : public QProgressBar { + Q_OBJECT + public: + ProgressBar( QWidget * parent=0, const char * name=0, WFlags f=0 ); + + public slots: + void slotProgress( const QString & message, int type, int current, int total ); + void slotProgress( const QString & message, int current, int total ); + /*! reimplementation to support self-powered busy indicator */ + void setProgress( int progress ); + /*! reimplementation to support self-powered busy indicator */ + void setTotalSteps( int total ); + /*! reimplementation to support self-powered busy indicator */ + void reset(); + /*! reimplementation to preserve visibility */ + void setProgress( int cur, int tot ) { QProgressBar::setProgress( cur, tot ); } + + private slots: + void slotBusyTimerTick(); + + private: + void fixup( bool ); + + private: + QTimer * mBusyTimer; + int mRealProgress; + }; +} + +#endif // __KLEO_PROGRESSBAR_H__ diff --git a/certmanager/lib/ui/progressdialog.cpp b/certmanager/lib/ui/progressdialog.cpp new file mode 100644 index 000000000..bb66aca17 --- /dev/null +++ b/certmanager/lib/ui/progressdialog.cpp @@ -0,0 +1,98 @@ +/* + progressdialog.cpp + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#include "progressdialog.h" + +#include "progressbar.h" + +#include <kleo/job.h> + +#include <kdebug.h> +#include <klocale.h> + +#include <qtimer.h> + +#include <assert.h> + +Kleo::ProgressDialog::ProgressDialog( Job * job, const QString & baseText, + QWidget * creator, const char * name, WFlags f ) + : QProgressDialog( creator, name, false, f ), mBaseText( baseText ) +{ + assert( job ); + setBar( new ProgressBar( this, "replacement progressbar in Kleo::ProgressDialog" ) ); + + setMinimumDuration( 2000 /*ms*/ ); + setAutoReset( false ); + setAutoClose( false ); + setLabelText( baseText ); + setProgress( 0, 0 ); // activate busy indicator + + connect( job, SIGNAL(progress(const QString&,int,int)), + SLOT(slotProgress(const QString&,int,int)) ); + connect( job, SIGNAL(done()), SLOT(slotDone()) ); + connect( this, SIGNAL(canceled()), + job, SLOT(slotCancel()) ); + + QTimer::singleShot( minimumDuration(), this, SLOT(forceShow()) ); +} + +Kleo::ProgressDialog::~ProgressDialog() { + +} + +void Kleo::ProgressDialog::setMinimumDuration( int ms ) { + if ( 0 < ms && ms < minimumDuration() ) + QTimer::singleShot( ms, this, SLOT(forceShow()) ); + QProgressDialog::setMinimumDuration( ms ); +} + +void Kleo::ProgressDialog::slotProgress( const QString & what, int current, int total ) { + kdDebug(5150) << "Kleo::ProgressDialog::slotProgress( \"" << what << "\", " + << current << ", " << total << " )" << endl; + if ( mBaseText.isEmpty() ) + setLabelText( what ); + else if ( what.isEmpty() ) + setLabelText( mBaseText ); + else + setLabelText( i18n( "%1: %2" ).arg( mBaseText, what ) ); + setProgress( current, total ); +} + +void Kleo::ProgressDialog::slotDone() { + kdDebug(5150) << "Kleo::ProgressDialog::slotDone()" << endl; + hide(); + deleteLater(); +} + + +#include "progressdialog.moc" + diff --git a/certmanager/lib/ui/progressdialog.h b/certmanager/lib/ui/progressdialog.h new file mode 100644 index 000000000..0b419aabb --- /dev/null +++ b/certmanager/lib/ui/progressdialog.h @@ -0,0 +1,66 @@ +/* + progressdialog.h + + This file is part of libkleopatra, the KDE keymanagement library + Copyright (c) 2004 Klarälvdalens Datakonsult AB + + Libkleopatra is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + Libkleopatra is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + + In addition, as a special exception, the copyright holders give + permission to link the code of this program with any edition of + the Qt library by Trolltech AS, Norway (or with modified versions + of Qt that use the same license as Qt), and distribute linked + combinations including the two. You must obey the GNU General + Public License in all respects for all of the code used other than + Qt. If you modify this file, you may extend this exception to + your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from + your version. +*/ + +#ifndef __KLEO_PROGRESSDIALOG_H__ +#define __KLEO_PROGRESSDIALOG_H__ + +#include <qprogressdialog.h> +#include <qstring.h> +#include <kdepimmacros.h> +namespace Kleo { + + class Job; + + /** + @short A progress dialog for Kleo::Jobs + */ + class KDE_EXPORT ProgressDialog : public QProgressDialog { + Q_OBJECT + public: + ProgressDialog( Job * job, const QString & baseText, + QWidget * creator=0, const char * name=0, WFlags f=0 ); + ~ProgressDialog(); + + public slots: + /*! reimplementation */ + void setMinimumDuration( int ms ); + + private slots: + void slotProgress( const QString & what, int current, int total ); + void slotDone(); + private: + QString mBaseText; + }; + +} + +#endif // __KLEO_PROGRESSDIALOG_H__ |