certmanager/lib
qgpgmekeylistjob.cpp00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
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 #include <qtimer.h>
00052
00053 #include <algorithm>
00054
00055 #include <stdlib.h>
00056 #include <string.h>
00057 #include <assert.h>
00058
00059 Kleo::QGpgMEKeyListJob::QGpgMEKeyListJob( GpgME::Context * context )
00060 : KeyListJob( QGpgME::EventLoopInteractor::instance(), "Kleo::QGpgMEKeyListJob" ),
00061 QGpgMEJob( this, context ),
00062 mResult(), mSecretOnly( false )
00063 {
00064 assert( context );
00065 }
00066
00067 Kleo::QGpgMEKeyListJob::~QGpgMEKeyListJob() {
00068 }
00069
00070 void Kleo::QGpgMEKeyListJob::setup( const QStringList & pats, bool secretOnly ) {
00071 assert( !patterns() );
00072
00073 mSecretOnly = secretOnly;
00074 setPatterns( pats );
00075 }
00076
00077 GpgME::Error Kleo::QGpgMEKeyListJob::start( const QStringList & pats, bool secretOnly ) {
00078 setup( pats, secretOnly );
00079
00080 hookupContextToEventLoopInteractor();
00081 connect( QGpgME::EventLoopInteractor::instance(),
00082 SIGNAL(nextKeyEventSignal(GpgME::Context*,const GpgME::Key&)),
00083 SLOT(slotNextKeyEvent(GpgME::Context*,const GpgME::Key&)) );
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094 while ( const GpgME::Error err = mCtx->startKeyListing( patterns(), mSecretOnly ) ) {
00095 if ( err.code() == GPG_ERR_LINE_TOO_LONG ) {
00096 setChunkSize( chunkSize()/2 );
00097 if ( chunkSize() >= 1 ) {
00098 kdDebug(5150) << "QGpgMEKeyListJob::start(): retrying keylisting with chunksize " << chunkSize() << endl;
00099 continue;
00100 }
00101 } else if ( err.code() == GPG_ERR_EOF ) {
00102 kdDebug(5150) << "QGpgMEKeyListJob::start(): early end of keylisting, trying to fake an empty result" << endl;
00103 QTimer::singleShot( 10, this, SLOT(slotFakeOperationDoneEvent()) );
00104 return GpgME::Error();
00105 }
00106 deleteLater();
00107 mResult = GpgME::KeyListResult( 0, err );
00108 return err;
00109 }
00110 mResult = GpgME::KeyListResult( 0, 0 );
00111 return 0;
00112 }
00113
00114 GpgME::KeyListResult Kleo::QGpgMEKeyListJob::exec( const QStringList & pats, bool secretOnly, std::vector<GpgME::Key> & keys ) {
00115 setup( pats, secretOnly );
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126 for (;;) {
00127 keys.clear();
00128 mResult = attemptSyncKeyListing( keys );
00129 if ( !mResult.error() || mResult.error().code() != GPG_ERR_LINE_TOO_LONG )
00130 return mResult;
00131
00132 setChunkSize( chunkSize()/2 );
00133 if ( chunkSize() < 1 )
00134
00135 return mResult;
00136 kdDebug(5150) << "QGpgMEKeyListJob::exec(): retrying keylisting with chunksize " << chunkSize() << endl;
00137 }
00138 kdFatal(5150) << "QGpgMEKeyListJob::exec(): Oops, this is not supposed to happen!" << endl;
00139 return GpgME::KeyListResult();
00140 }
00141
00142 GpgME::KeyListResult Kleo::QGpgMEKeyListJob::attemptSyncKeyListing( std::vector<GpgME::Key> & keys ) {
00143 GpgME::KeyListResult result;
00144 for ( const char* * chunk = patterns() ; chunk ; chunk = nextChunk() ) {
00145
00146 if ( const GpgME::Error err = mCtx->startKeyListing( chunk, mSecretOnly ) )
00147 return GpgME::KeyListResult( 0, err );
00148
00149 GpgME::Error err;
00150 do
00151 keys.push_back( mCtx->nextKey( err ) );
00152 while ( !err );
00153 keys.pop_back();
00154 result.mergeWith( mCtx->endKeyListing() );
00155 if ( result.error() )
00156 break;
00157 }
00158 return result;
00159 }
00160
00161 void Kleo::QGpgMEKeyListJob::slotNextKeyEvent( GpgME::Context * context, const GpgME::Key & key ) {
00162 if ( context == mCtx )
00163 emit nextKey( key );
00164 }
00165
00166 void Kleo::QGpgMEKeyListJob::slotFakeOperationDoneEvent() {
00167 const GpgME::KeyListResult res = mCtx->keyListResult();
00168 if ( !res.error().code() == GPG_ERR_EOF )
00169 kdDebug(5150) << "QGpgMEKeyListJob::slotFakeOperationDoneEvent: expected EOF, got "
00170 << res.error().asString() << endl;
00171 mResult = GpgME::KeyListResult();
00172 emit done();
00173 emit result( mResult );
00174 deleteLater();
00175 }
00176
00177 void Kleo::QGpgMEKeyListJob::slotOperationDoneEvent( GpgME::Context * context, const GpgME::Error & ) {
00178 if ( context != mCtx )
00179 return;
00180 mResult.mergeWith( mCtx->keyListResult() );
00181 if ( !mResult.error() )
00182 if ( const char* * chunk = nextChunk() ) {
00183 if ( const GpgME::Error err = mCtx->startKeyListing( chunk, mSecretOnly ) )
00184 mResult.mergeWith( GpgME::KeyListResult( 0, err ) );
00185 else
00186 return;
00187 }
00188 emit done();
00189 emit result( mResult );
00190 deleteLater();
00191 }
00192
00193 void Kleo::QGpgMEKeyListJob::showErrorDialog( QWidget * parent, const QString & caption ) const {
00194 if ( !mResult.error() || mResult.error().isCanceled() )
00195 return;
00196 const QString msg = i18n( "<qt><p>An error occurred while fetching "
00197 "the keys from the backend:</p>"
00198 "<p><b>%1</b></p></qt>" )
00199 .arg( QString::fromLocal8Bit( mResult.error().asString() ) );
00200 KMessageBox::error( parent, msg, caption );
00201 }
00202
00203 #include "qgpgmekeylistjob.moc"
|