summaryrefslogtreecommitdiffstats
path: root/certmanager/lib/backends/qgpgme/qgpgmekeylistjob.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'certmanager/lib/backends/qgpgme/qgpgmekeylistjob.cpp')
-rw-r--r--certmanager/lib/backends/qgpgme/qgpgmekeylistjob.cpp187
1 files changed, 187 insertions, 0 deletions
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"