certmanager/lib

qgpgmekeylistjob.cpp

00001 /*
00002     qgpgmekeylistjob.cpp
00003 
00004     This file is part of libkleopatra, the KDE keymanagement library
00005     Copyright (c) 2004 Klarälvdalens Datakonsult AB
00006 
00007     Libkleopatra is free software; you can redistribute it and/or
00008     modify it under the terms of the GNU General Public License as
00009     published by the Free Software Foundation; either version 2 of the
00010     License, or (at your option) any later version.
00011 
00012     Libkleopatra is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015     General Public License for more details.
00016 
00017     You should have received a copy of the GNU General Public License
00018     along with this program; if not, write to the Free Software
00019     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00020 
00021     In addition, as a special exception, the copyright holders give
00022     permission to link the code of this program with any edition of
00023     the Qt library by Trolltech AS, Norway (or with modified versions
00024     of Qt that use the same license as Qt), and distribute linked
00025     combinations including the two.  You must obey the GNU General
00026     Public License in all respects for all of the code used other than
00027     Qt.  If you modify this file, you may extend this exception to
00028     your version of the file, but you are not obligated to do so.  If
00029     you do not wish to do so, delete this exception statement from
00030     your version.
00031 */
00032 
00033 #ifdef HAVE_CONFIG_H
00034 #include <config.h>
00035 #endif
00036 
00037 #include "qgpgmekeylistjob.h"
00038 
00039 #include <qgpgme/eventloopinteractor.h>
00040 
00041 #include <gpgmepp/key.h>
00042 #include <gpgmepp/context.h>
00043 #include <gpgmepp/keylistresult.h>
00044 #include <gpg-error.h>
00045 
00046 #include <kmessagebox.h>
00047 #include <klocale.h>
00048 #include <kdebug.h>
00049 
00050 #include <qstringlist.h>
00051 
00052 #include <algorithm>
00053 
00054 #include <stdlib.h>
00055 #include <string.h>
00056 #include <assert.h>
00057 
00058 Kleo::QGpgMEKeyListJob::QGpgMEKeyListJob( GpgME::Context * context )
00059   : KeyListJob( QGpgME::EventLoopInteractor::instance(), "Kleo::QGpgMEKeyListJob" ),
00060     QGpgMEJob( this, context ),
00061     mResult(), mSecretOnly( false )
00062 {
00063   assert( context );
00064 }
00065 
00066 Kleo::QGpgMEKeyListJob::~QGpgMEKeyListJob() {
00067 }
00068 
00069 void Kleo::QGpgMEKeyListJob::setup( const QStringList & pats, bool secretOnly ) {
00070   assert( !patterns() );
00071 
00072   mSecretOnly = secretOnly;
00073   setPatterns( pats );
00074 }
00075 
00076 GpgME::Error Kleo::QGpgMEKeyListJob::start( const QStringList & pats, bool secretOnly ) {
00077   setup( pats, secretOnly );
00078 
00079   hookupContextToEventLoopInteractor();
00080   connect( QGpgME::EventLoopInteractor::instance(),
00081        SIGNAL(nextKeyEventSignal(GpgME::Context*,const GpgME::Key&)),
00082        SLOT(slotNextKeyEvent(GpgME::Context*,const GpgME::Key&)) );
00083 
00084   // The communication channel between gpgme and gpgsm is limited in
00085   // the number of patterns that can be transported, but they won't
00086   // say to how much, so we need to find out ourselves if we get a
00087   // LINE_TOO_LONG error back...
00088 
00089   // We could of course just feed them single patterns, and that would
00090   // probably be easier, but the performance penalty would currently
00091   // be noticable.
00092 
00093   while ( const GpgME::Error err = mCtx->startKeyListing( patterns(), mSecretOnly ) ) {
00094     if ( err.code() == GPG_ERR_LINE_TOO_LONG ) {
00095       setChunkSize( chunkSize()/2 );
00096       if ( chunkSize() >= 1 ) {
00097     kdDebug(5150) << "QGpgMEKeyListJob::start(): retrying keylisting with chunksize " << chunkSize() << endl;
00098     continue;
00099       }
00100     }
00101     deleteLater();
00102     mResult = GpgME::KeyListResult( 0, err );
00103     return err;
00104   }
00105   mResult = GpgME::KeyListResult( 0, 0 );
00106   return 0;
00107 }
00108 
00109 GpgME::KeyListResult Kleo::QGpgMEKeyListJob::exec( const QStringList & pats, bool secretOnly, std::vector<GpgME::Key> & keys ) {
00110   setup( pats, secretOnly );
00111 
00112   // The communication channel between gpgme and gpgsm is limited in
00113   // the number of patterns that can be transported, but they won't
00114   // say to how much, so we need to find out ourselves if we get a
00115   // LINE_TOO_LONG error back...
00116 
00117   // We could of course just feed them single patterns, and that would
00118   // probably be easier, but the performance penalty would currently
00119   // be noticable.
00120 
00121   for (;;) {
00122     keys.clear();
00123     mResult = attemptSyncKeyListing( keys );
00124     if ( !mResult.error() || mResult.error().code() != GPG_ERR_LINE_TOO_LONG )
00125       return mResult;
00126     // got LINE_TOO_LONG, try a smaller chunksize:
00127     setChunkSize( chunkSize()/2 );
00128     if ( chunkSize() < 1 )
00129       // chunks smaller than one can't be -> return the error.
00130       return mResult;
00131     kdDebug(5150) << "QGpgMEKeyListJob::exec(): retrying keylisting with chunksize " << chunkSize() << endl;
00132   }
00133   kdFatal(5150) << "QGpgMEKeyListJob::exec(): Oops, this is not supposed to happen!" << endl;
00134   return GpgME::KeyListResult();
00135 }
00136 
00137 GpgME::KeyListResult Kleo::QGpgMEKeyListJob::attemptSyncKeyListing( std::vector<GpgME::Key> & keys ) {
00138   GpgME::KeyListResult result;
00139   for ( const char* * chunk = patterns() ; chunk ; chunk = nextChunk() ) {
00140 
00141     if ( const GpgME::Error err = mCtx->startKeyListing( chunk, mSecretOnly ) )
00142       return GpgME::KeyListResult( 0, err );
00143 
00144     GpgME::Error err;
00145     do
00146       keys.push_back( mCtx->nextKey( err ) );
00147     while ( !err );
00148     keys.pop_back();
00149     result.mergeWith( mCtx->endKeyListing() );
00150     if ( result.error() )
00151       break;
00152   }
00153   return result;
00154 }
00155 
00156 void Kleo::QGpgMEKeyListJob::slotNextKeyEvent( GpgME::Context * context, const GpgME::Key & key ) {
00157   if ( context == mCtx )
00158     emit nextKey( key );
00159 }
00160 
00161 void Kleo::QGpgMEKeyListJob::slotOperationDoneEvent( GpgME::Context * context, const GpgME::Error & ) {
00162   if ( context != mCtx )
00163     return;
00164   mResult.mergeWith( mCtx->keyListResult() );
00165   if ( !mResult.error() )
00166     if ( const char* * chunk = nextChunk() ) {
00167       if ( const GpgME::Error err = mCtx->startKeyListing( chunk, mSecretOnly ) )
00168     mResult.mergeWith( GpgME::KeyListResult( 0, err ) );
00169       else
00170     return;
00171     }
00172   emit done();
00173   emit result( mResult );
00174   deleteLater();
00175 }
00176 
00177 void Kleo::QGpgMEKeyListJob::showErrorDialog( QWidget * parent, const QString & caption ) const {
00178   if ( !mResult.error() || mResult.error().isCanceled() )
00179     return;
00180   const QString msg = i18n( "<qt><p>An error occurred while fetching "
00181                 "the keys from the backend:</p>"
00182                 "<p><b>%1</b></p></qt>" )
00183     .arg( QString::fromLocal8Bit( mResult.error().asString() ) );
00184   KMessageBox::error( parent, msg, caption );
00185 }
00186 
00187 #include "qgpgmekeylistjob.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys