00001
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 "qgpgmejob.h"
00038 #include "qgpgmeprogresstokenmapper.h"
00039
00040 #include <kleo/job.h>
00041 #include <ui/passphrasedialog.h>
00042
00043 #include <qgpgme/eventloopinteractor.h>
00044 #include <qgpgme/dataprovider.h>
00045
00046 #include <gpgmepp/context.h>
00047 #include <gpgmepp/data.h>
00048
00049 #include <tdelocale.h>
00050 #include <kstandarddirs.h>
00051
00052 #include <tqstring.h>
00053 #include <tqstringlist.h>
00054
00055 #include <algorithm>
00056
00057 #include <assert.h>
00058 #include <stdlib.h>
00059 #include <string.h>
00060
00061 namespace {
00062 class InvarianceChecker {
00063 public:
00064 #ifdef NDEBUG
00065 InvarianceChecker( const Kleo::QGpgMEJob * ) {}
00066 #else
00067 InvarianceChecker( const Kleo::QGpgMEJob * job )
00068 : _this( job )
00069 {
00070 assert( _this );
00071 _this->checkInvariants();
00072 }
00073 ~InvarianceChecker() {
00074 _this->checkInvariants();
00075 }
00076 private:
00077 const Kleo::QGpgMEJob * _this;
00078 #endif
00079 };
00080 }
00081
00082 Kleo::QGpgMEJob::QGpgMEJob( Kleo::Job * _this, GpgME::Context * context )
00083 : GpgME::ProgressProvider(),
00084 GpgME::PassphraseProvider(),
00085 mThis( _this ),
00086 mCtx( context ),
00087 mInData( 0 ),
00088 mInDataDataProvider( 0 ),
00089 mOutData( 0 ),
00090 mOutDataDataProvider( 0 ),
00091 mPatterns( 0 ),
00092 mReplacedPattern( 0 ),
00093 mNumPatterns( 0 ),
00094 mChunkSize( 1024 ),
00095 mPatternStartIndex( 0 ), mPatternEndIndex( 0 )
00096 {
00097 InvarianceChecker check( this );
00098 assert( context );
00099 TQObject::connect( QGpgME::EventLoopInteractor::instance(), TQT_SIGNAL(aboutToDestroy()),
00100 _this, TQT_SLOT(slotCancel()) );
00101 context->setProgressProvider( this );
00102
00103
00104
00105 if ( context->protocol() == GpgME::Context::OpenPGP )
00106 context->setPassphraseProvider( this );
00107 }
00108
00109 void Kleo::QGpgMEJob::checkInvariants() const {
00110 #ifndef NDEBUG
00111 if ( mPatterns ) {
00112 assert( mPatterns[mNumPatterns] == 0 );
00113 if ( mPatternEndIndex > 0 ) {
00114 assert( mPatternEndIndex > mPatternStartIndex );
00115 assert( mPatternEndIndex - mPatternStartIndex == mChunkSize );
00116 } else {
00117 assert( mPatternEndIndex == mPatternStartIndex );
00118 }
00119 if ( mPatternEndIndex < mNumPatterns ) {
00120 assert( mPatterns[mPatternEndIndex] == 0 );
00121 assert( mReplacedPattern != 0 );
00122 } else {
00123 assert( mReplacedPattern == 0 );
00124 }
00125 } else {
00126 assert( mNumPatterns == 0 );
00127 assert( mPatternStartIndex == 0 );
00128 assert( mPatternEndIndex == 0 );
00129 assert( mReplacedPattern == 0 );
00130 }
00131 #endif
00132 }
00133
00134 Kleo::QGpgMEJob::~QGpgMEJob() {
00135 InvarianceChecker check( this );
00136 delete mCtx; mCtx = 0;
00137 delete mInData; mInData = 0;
00138 delete mInDataDataProvider; mInDataDataProvider = 0;
00139 delete mOutData; mOutData = 0;
00140 delete mOutDataDataProvider; mOutDataDataProvider = 0;
00141 deleteAllPatterns();
00142 }
00143
00144 void Kleo::QGpgMEJob::deleteAllPatterns() {
00145 if ( mPatterns )
00146 for ( unsigned int i = 0 ; i < mNumPatterns ; ++i )
00147 free( (void*)mPatterns[i] );
00148 free( (void*)mReplacedPattern ); mReplacedPattern = 0;
00149 delete[] mPatterns; mPatterns = 0;
00150 mPatternEndIndex = mPatternStartIndex = mNumPatterns = 0;
00151 }
00152
00153 void Kleo::QGpgMEJob::hookupContextToEventLoopInteractor() {
00154 mCtx->setManagedByEventLoopInteractor( true );
00155 TQObject::connect( QGpgME::EventLoopInteractor::instance(),
00156 TQT_SIGNAL(operationDoneEventSignal(GpgME::Context*,const GpgME::Error&)),
00157 mThis, TQT_SLOT(slotOperationDoneEvent(GpgME::Context*,const GpgME::Error&)) );
00158 }
00159
00160 void Kleo::QGpgMEJob::setPatterns( const TQStringList & sl, bool allowEmpty ) {
00161 InvarianceChecker check( this );
00162 deleteAllPatterns();
00163
00164 mPatterns = new const char*[ sl.size() + 1 ];
00165 const char* * pat_it = mPatterns;
00166 mNumPatterns = 0;
00167 for ( TQStringList::const_iterator it = sl.begin() ; it != sl.end() ; ++it ) {
00168 if ( (*it).isNull() )
00169 continue;
00170 if ( (*it).isEmpty() && !allowEmpty )
00171 continue;
00172 *pat_it++ = strdup( (*it).utf8().data() );
00173 ++mNumPatterns;
00174 }
00175 *pat_it++ = 0;
00176 mReplacedPattern = 0;
00177 mPatternEndIndex = mChunkSize = mNumPatterns;
00178 }
00179
00180 void Kleo::QGpgMEJob::setChunkSize( unsigned int chunksize ) {
00181 InvarianceChecker check( this );
00182 if ( mReplacedPattern ) {
00183 mPatterns[mPatternEndIndex] = mReplacedPattern;
00184 mReplacedPattern = 0;
00185 }
00186 mChunkSize = std::min( chunksize, mNumPatterns );
00187 mPatternStartIndex = 0;
00188 mPatternEndIndex = mChunkSize;
00189 mReplacedPattern = mPatterns[mPatternEndIndex];
00190 mPatterns[mPatternEndIndex] = 0;
00191 }
00192
00193 const char* * Kleo::QGpgMEJob::nextChunk() {
00194 InvarianceChecker check( this );
00195 if ( mReplacedPattern ) {
00196 mPatterns[mPatternEndIndex] = mReplacedPattern;
00197 mReplacedPattern = 0;
00198 }
00199 mPatternStartIndex += mChunkSize;
00200 mPatternEndIndex += mChunkSize;
00201 if ( mPatternEndIndex < mNumPatterns ) {
00202 mReplacedPattern = mPatterns[mPatternEndIndex];
00203 mPatterns[mPatternEndIndex] = 0;
00204 }
00205 return patterns();
00206 }
00207
00208 const char* * Kleo::QGpgMEJob::patterns() const {
00209 InvarianceChecker check( this );
00210 if ( mPatternStartIndex < mNumPatterns )
00211 return mPatterns + mPatternStartIndex;
00212 return 0;
00213 }
00214
00215 GpgME::Error Kleo::QGpgMEJob::setSigningKeys( const std::vector<GpgME::Key> & signers ) {
00216 mCtx->clearSigningKeys();
00217 for ( std::vector<GpgME::Key>::const_iterator it = signers.begin() ; it != signers.end() ; ++it ) {
00218 if ( (*it).isNull() )
00219 continue;
00220 if ( const GpgME::Error err = mCtx->addSigningKey( *it ) )
00221 return err;
00222 }
00223 return 0;
00224 }
00225
00226 void Kleo::QGpgMEJob::createInData( const TQByteArray & in ) {
00227 mInDataDataProvider = new QGpgME::TQByteArrayDataProvider( in );
00228 mInData = new GpgME::Data( mInDataDataProvider );
00229 assert( !mInData->isNull() );
00230 }
00231
00232 void Kleo::QGpgMEJob::createOutData() {
00233 mOutDataDataProvider = new QGpgME::TQByteArrayDataProvider();
00234 mOutData = new GpgME::Data( mOutDataDataProvider );
00235 assert( !mOutData->isNull() );
00236 }
00237
00238 static const unsigned int GetAuditLogFlags = GpgME::Context::AuditLogWithHelp|GpgME::Context::HtmlAuditLog;
00239
00240 static TQString audit_log_as_html( GpgME::Context * ctx, GpgME::Error & err ) {
00241 assert( ctx );
00242 QGpgME::TQByteArrayDataProvider dp;
00243 GpgME::Data data( &dp );
00244 assert( !data.isNull() );
00245 if ( ( err = ctx->getAuditLog( data, GetAuditLogFlags ) ) )
00246 return TQString();
00247 const TQByteArray ba = dp.data();
00248 return TQString::fromUtf8( ba.data(), ba.size() );
00249 }
00250
00251 void Kleo::QGpgMEJob::doSlotOperationDoneEvent( GpgME::Context * context, const GpgME::Error & e ) {
00252 if ( context == mCtx ) {
00253 doEmitDoneSignal();
00254 doOperationDoneEvent( e );
00255 mThis->deleteLater();
00256 }
00257 }
00258
00259 void Kleo::QGpgMEJob::getAuditLog() {
00260 if ( !mCtx )
00261 return;
00262 mAuditLogAsHtml = audit_log_as_html( mCtx, mAuditLogError );
00263 }
00264
00265 void Kleo::QGpgMEJob::doSlotCancel() {
00266 mCtx->cancelPendingOperation();
00267 }
00268
00269 void Kleo::QGpgMEJob::showProgress( const char * what, int type, int current, int total ) {
00270 doEmitProgressSignal( QGpgMEProgressTokenMapper::instance()->map( what, type, current, total ), current, total );
00271 }
00272
00273 char * Kleo::QGpgMEJob::getPassphrase( const char * useridHint, const char * ,
00274 bool previousWasBad, bool & canceled ) {
00275
00276
00277 TQString msg = previousWasBad ?
00278 i18n( "You need a passphrase to unlock the secret key for user:<br/> %1 (retry)" ) :
00279 i18n( "You need a passphrase to unlock the secret key for user:<br/> %1" );
00280 msg = msg.arg( TQString::fromUtf8( useridHint ) ) + "<br/><br/>";
00281 msg.prepend( "<qt>" );
00282 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/>";
00283 const TQString gpgAgent = TDEStandardDirs::findExe( "gpg-agent" );
00284 if ( !gpgAgent.isEmpty() ) {
00285 msg += i18n( "gpg-agent was found in %1, but does not appear to be running." )
00286 .arg( gpgAgent );
00287 } else {
00288 msg += i18n( "gpg-agent is part of gnupg-%1, which you can download from %2" )
00289 .arg( "1.9" )
00290 .arg( "http://www.gnupg.org/download" );
00291 }
00292 msg += "<br/>";
00293 msg += i18n( "For information on how to set up gpg-agent, see %1" )
00294 .arg( "http://userbase.kde.org/KMail/PGP_MIME" );
00295 msg += "<br/><br/>";
00296 msg += i18n( "Enter passphrase:" );
00297 Kleo::PassphraseDialog dlg( msg, i18n("Passphrase Dialog") );
00298 if ( dlg.exec() != TQDialog::Accepted ) {
00299 canceled = true;
00300 return 0;
00301 }
00302 canceled = false;
00303
00304 return strdup( dlg.passphrase() );
00305 }