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 "certmanager.h"
00038
00039
#include "certlistview.h"
00040
#include "certificatewizardimpl.h"
00041
#include "certificateinfowidgetimpl.h"
00042
#include "crlview.h"
00043
#include "customactions.h"
00044
#include "hierarchyanalyser.h"
00045
#include "storedtransferjob.h"
00046
#include "conf/configuredialog.h"
00047
00048
00049
#include <kleo/cryptobackendfactory.h>
00050
#include <kleo/downloadjob.h>
00051
#include <kleo/importjob.h>
00052
#include <kleo/exportjob.h>
00053
#include <kleo/multideletejob.h>
00054
#include <kleo/deletejob.h>
00055
#include <kleo/keylistjob.h>
00056
#include <kleo/dn.h>
00057
#include <kleo/keyfilter.h>
00058
#include <kleo/keyfiltermanager.h>
00059
#include <kleo/hierarchicalkeylistjob.h>
00060
#include <kleo/refreshkeysjob.h>
00061
00062
#include <ui/progressdialog.h>
00063
#include <ui/progressbar.h>
00064
#include <ui/keyselectiondialog.h>
00065
#include <ui/cryptoconfigdialog.h>
00066
00067
00068
#include <gpgmepp/importresult.h>
00069
#include <gpgmepp/keylistresult.h>
00070
#include <gpgmepp/key.h>
00071
00072
00073
#include <kfiledialog.h>
00074
#include <kprocess.h>
00075
#include <kaction.h>
00076
#include <kapplication.h>
00077
#include <klocale.h>
00078
#include <kmessagebox.h>
00079
#include <dcopclient.h>
00080
#include <ktoolbar.h>
00081
#include <kstatusbar.h>
00082
#include <kstandarddirs.h>
00083
#include <kdebug.h>
00084
#include <kdialogbase.h>
00085
#include <kkeydialog.h>
00086
#include <ktempfile.h>
00087
#include <kio/job.h>
00088
#include <kio/netaccess.h>
00089
#include <kstdaccel.h>
00090
00091
00092
#include <qfontmetrics.h>
00093
#include <qpopupmenu.h>
00094
00095
00096
#include <algorithm>
00097
#include <assert.h>
00098
00099
static const bool startWithHierarchicalKeyListing =
false;
00100
00101
namespace {
00102
00103
class DisplayStrategy :
public Kleo::KeyListView::DisplayStrategy{
00104
public:
00105 ~DisplayStrategy() {}
00106
00107
virtual QFont keyFont(
const GpgME::Key& key,
const QFont& font )
const {
00108
const Kleo::KeyFilter* filter = Kleo::KeyFilterManager::instance()->filterMatching( key );
00109
return filter ? filter->
font( font ) : font;
00110 }
00111
virtual QColor keyForeground(
const GpgME::Key& key,
const QColor& c )
const {
00112
const Kleo::KeyFilter* filter = Kleo::KeyFilterManager::instance()->filterMatching( key );
00113
if ( filter && filter->
fgColor().isValid() )
00114
return filter->
fgColor();
00115
return c;
00116 }
00117
virtual QColor keyBackground(
const GpgME::Key& key,
const QColor& c )
const {
00118
const Kleo::KeyFilter* filter = Kleo::KeyFilterManager::instance()->filterMatching( key );
00119
if ( filter && filter->
bgColor().isValid() )
00120
return filter->
bgColor();
00121
return c;
00122 }
00123 };
00124
00125
class ColumnStrategy :
public Kleo::KeyListView::ColumnStrategy {
00126
public:
00127 ~ColumnStrategy() {}
00128
00129
QString title(
int col )
const;
00130
QString text(
const GpgME::Key & key,
int col )
const;
00131
int width(
int col,
const QFontMetrics & fm )
const;
00132 };
00133
00134
QString ColumnStrategy::title(
int col )
const {
00135
switch ( col ) {
00136
case 0:
return i18n(
"Subject");
00137
case 1:
return i18n(
"Issuer");
00138
case 2:
return i18n(
"Serial");
00139
default:
return QString::null;
00140 }
00141 }
00142
00143
QString ColumnStrategy::text(
const GpgME::Key & key,
int col )
const {
00144
switch ( col ) {
00145
case 0:
return Kleo::DN( key.userID(0).id() ).prettyDN();
00146
case 1:
return Kleo::DN( key.issuerName() ).prettyDN();
00147
case 2:
return key.issuerSerial() ? QString::fromUtf8( key.issuerSerial() ) : QString::null ;
00148
default:
return QString::null;
00149 }
00150 }
00151
00152
int ColumnStrategy::width(
int col,
const QFontMetrics & fm )
const {
00153
int factor = -1;
00154
switch ( col ) {
00155
case 0: factor = 6;
break;
00156
case 1: factor = 4;
break;
00157
default:
return -1;
00158 }
00159
return fm.width( title( col ) ) * factor;
00160 }
00161 }
00162
00163 CertManager::CertManager(
bool remote,
const QString& query,
const QString &
import,
00164
QWidget* parent,
const char* name )
00165 : KMainWindow( parent, name ),
00166 mCrlView( 0 ),
00167 mDirmngrProc( 0 ),
00168 mHierarchyAnalyser( 0 ),
00169 mLineEditAction( 0 ),
00170 mComboAction( 0 ),
00171 mFindAction( 0 ),
00172 mImportCertFromFileAction( 0 ),
00173 mImportCRLFromFileAction( 0 ),
00174 mNextFindRemote( false ),
00175 mRemote( remote ),
00176 mDirMngrFound( false )
00177 {
00178 createStatusBar();
00179 createActions();
00180
00181 createGUI();
00182 setAutoSaveSettings();
00183
00184
00185 mKeyListView =
new CertKeyListView(
new ColumnStrategy(),
new DisplayStrategy(),
this,
"mKeyListView" );
00186 mKeyListView->setHierarchical( startWithHierarchicalKeyListing );
00187 mKeyListView->setRootIsDecorated( startWithHierarchicalKeyListing );
00188 mKeyListView->setSelectionMode( QListView::Extended );
00189 setCentralWidget( mKeyListView );
00190
00191 connect( mKeyListView, SIGNAL(doubleClicked(Kleo::KeyListViewItem*,
const QPoint&,
int)),
00192 SLOT(slotViewDetails(Kleo::KeyListViewItem*)) );
00193 connect( mKeyListView, SIGNAL(returnPressed(Kleo::KeyListViewItem*)),
00194 SLOT(slotViewDetails(Kleo::KeyListViewItem*)) );
00195 connect( mKeyListView, SIGNAL(selectionChanged()),
00196 SLOT(slotSelectionChanged()) );
00197 connect( mKeyListView, SIGNAL(contextMenu(Kleo::KeyListViewItem*,
const QPoint&)),
00198 SLOT(slotContextMenu(Kleo::KeyListViewItem*,
const QPoint&)) );
00199
00200 connect( mKeyListView, SIGNAL(dropped(
const KURL::List&) ),
00201 SLOT( slotDropped(
const KURL::List&) ) );
00202
00203 mLineEditAction->setText(query);
00204
if ( !mRemote || !query.isEmpty() )
00205 slotSearch();
00206
00207
if ( !
import.isEmpty() )
00208 slotImportCertFromFile( KURL(
import ) );
00209
00210 updateStatusBarLabels();
00211 slotSelectionChanged();
00212 }
00213
00214
void CertManager::createStatusBar() {
00215 KStatusBar * bar = statusBar();
00216 mProgressBar =
new Kleo::ProgressBar( bar,
"mProgressBar" );
00217 mProgressBar->reset();
00218 mProgressBar->setFixedSize(
QSize( 100, mProgressBar->height() * 3 / 5 ) );
00219 bar->addWidget( mProgressBar, 0,
true );
00220 mStatusLabel =
new QLabel( bar,
"mStatusLabel" );
00221 bar->addWidget( mStatusLabel, 1,
false );
00222 }
00223
00224
static inline void connectEnableOperationSignal(
QObject * s,
QObject * d ) {
00225 QObject::connect( s, SIGNAL(enableOperations(
bool)),
00226 d, SLOT(setEnabled(
bool)) );
00227 }
00228
00229
00230
void CertManager::createActions() {
00231 KAction * action = 0;
00232
00233 (
void)KStdAction::quit(
this, SLOT(close()), actionCollection() );
00234
00235 action = KStdAction::redisplay(
this, SLOT(slotRedisplay()), actionCollection() );
00236
00237 KShortcut reloadShortcut = KStdAccel::shortcut(KStdAccel::Reload);
00238 reloadShortcut.append(KKey(CTRL + Key_R));
00239 action->setShortcut( reloadShortcut );
00240
00241 connectEnableOperationSignal(
this, action );
00242
00243 action =
new KAction( i18n(
"Stop Operation"),
"stop", Key_Escape,
00244
this, SIGNAL(stopOperations()),
00245 actionCollection(),
"view_stop_operations" );
00246 action->setEnabled(
false );
00247
00248 (
void)
new KAction( i18n(
"New Key Pair..."),
"filenew", 0,
00249
this, SLOT(newCertificate()),
00250 actionCollection(),
"file_new_certificate" );
00251
00252 connect(
new KToggleAction( i18n(
"Hierarchical Key List"), 0,
00253 actionCollection(),
"view_hierarchical" ),
00254 SIGNAL(toggled(
bool)), SLOT(slotToggleHierarchicalView(
bool)) );
00255
00256 action =
new KAction( i18n(
"Expand All"), 0, CTRL+Key_Period,
00257
this, SLOT(slotExpandAll()),
00258 actionCollection(),
"view_expandall" );
00259 action->setEnabled( startWithHierarchicalKeyListing );
00260 action =
new KAction( i18n(
"Collapse All"), 0, CTRL+Key_Comma,
00261
this, SLOT(slotCollapseAll()),
00262 actionCollection(),
"view_collapseall" );
00263 action->setEnabled( startWithHierarchicalKeyListing );
00264
00265 (
void)
new KAction( i18n(
"Refresh CRLs"), 0, 0,
00266
this, SLOT(slotRefreshKeys()),
00267 actionCollection(),
"certificates_refresh_clr" );
00268
00269
#ifdef NOT_IMPLEMENTED_ANYWAY
00270
mRevokeCertificateAction =
new KAction( i18n(
"Revoke"), 0,
00271
this, SLOT(revokeCertificate()),
00272 actionCollection(),
"edit_revoke_certificate" );
00273 connectEnableOperationSignal(
this, mRevokeCertificateAction );
00274
00275 mExtendCertificateAction =
new KAction( i18n(
"Extend"), 0,
00276
this, SLOT(extendCertificate()),
00277 actionCollection(),
"edit_extend_certificate" );
00278 connectEnableOperationSignal(
this, mExtendCertificateAction );
00279
#endif
00280
00281 mDeleteCertificateAction =
new KAction( i18n(
"Delete"),
"editdelete", Key_Delete,
00282
this, SLOT(slotDeleteCertificate()),
00283 actionCollection(),
"edit_delete_certificate" );
00284 connectEnableOperationSignal(
this, mDeleteCertificateAction );
00285
00286 mValidateCertificateAction =
new KAction( i18n(
"Validate"),
"reload", SHIFT + Key_F5,
00287
this, SLOT(slotValidate()),
00288 actionCollection(),
"certificates_validate" );
00289 connectEnableOperationSignal(
this, mValidateCertificateAction );
00290
00291 mImportCertFromFileAction =
new KAction( i18n(
"Import Certificates..."), 0,
00292
this, SLOT(slotImportCertFromFile()),
00293 actionCollection(),
"file_import_certificates" );
00294 connectEnableOperationSignal(
this, mImportCertFromFileAction );
00295
00296 mImportCRLFromFileAction =
new KAction( i18n(
"Import CRLs..."), 0,
00297
this, SLOT(importCRLFromFile()),
00298 actionCollection(),
"file_import_crls" );
00299 connectEnableOperationSignal(
this, mImportCRLFromFileAction );
00300
00301 mExportCertificateAction =
new KAction( i18n(
"Export Certificates..."),
"export", 0,
00302
this, SLOT(slotExportCertificate()),
00303 actionCollection(),
"file_export_certificate" );
00304
00305 mExportSecretKeyAction =
new KAction( i18n(
"Export Secret Key..."),
"export", 0,
00306
this, SLOT(slotExportSecretKey()),
00307 actionCollection(),
"file_export_secret_keys" );
00308 connectEnableOperationSignal(
this, mExportSecretKeyAction );
00309
00310 mViewCertDetailsAction =
new KAction( i18n(
"Certificate Details..."), 0, 0,
00311
this, SLOT(slotViewDetails()), actionCollection(),
00312
"view_certificate_details" );
00313 mDownloadCertificateAction =
new KAction( i18n(
"Download"), 0, 0,
00314
this, SLOT(slotDownloadCertificate()), actionCollection(),
00315
"download_certificate" );
00316
00317
const QString dirmngr = KStandardDirs::findExe(
"gpgsm" );
00318 mDirMngrFound = !dirmngr.isEmpty();
00319
00320 action =
new KAction( i18n(
"Dump CRL Cache..."), 0,
00321
this, SLOT(slotViewCRLs()),
00322 actionCollection(),
"crl_dump_crl_cache" );
00323 action->setEnabled( mDirMngrFound );
00324
00325 action =
new KAction( i18n(
"Clear CRL Cache..."), 0,
00326
this, SLOT(slotClearCRLs()),
00327 actionCollection(),
"crl_clear_crl_cache" );
00328 action->setEnabled( mDirMngrFound );
00329
00330 action =
new KAction( i18n(
"GnuPG Log Viewer..."),
"pgp-keys", 0,
this,
00331 SLOT(slotStartWatchGnuPG()), actionCollection(),
"tools_start_kwatchgnupg");
00332
00333
if (KStandardDirs::findExe(
"kwatchgnupg").isEmpty()) action->setEnabled(
false);
00334
00335 (
void)
new LabelAction( i18n(
"Search:"), actionCollection(),
"label_action" );
00336
00337 mLineEditAction =
new LineEditAction( QString::null, actionCollection(),
this,
00338 SLOT(slotSearch()),
00339
"query_lineedit_action");
00340
00341
QStringList lst;
00342 lst << i18n(
"In Local Certificates") << i18n(
"In External Certificates");
00343 mComboAction =
new ComboAction( lst, actionCollection(),
this, SLOT( slotToggleRemote(
int) ),
00344
"location_combo_action");
00345
00346 mFindAction =
new KAction( i18n(
"Find"),
"find", 0,
this, SLOT(slotSearch()),
00347 actionCollection(),
"find" );
00348
00349 KStdAction::keyBindings(
this, SLOT(slotEditKeybindings()), actionCollection() );
00350 KStdAction::preferences(
this, SLOT(slotShowConfigurationDialog()), actionCollection() );
00351
00352
new KAction( i18n(
"Configure &GpgME Backend" ), 0, 0,
this, SLOT(slotConfigureGpgME()),
00353 actionCollection(),
"configure_gpgme" );
00354
00355 createStandardStatusBarAction();
00356 updateImportActions(
true );
00357 }
00358
00359
void CertManager::updateImportActions(
bool enable ) {
00360 mImportCRLFromFileAction->setEnabled( mDirMngrFound && enable );
00361 mImportCertFromFileAction->setEnabled( enable );
00362 }
00363
00364
void CertManager::slotEditKeybindings() {
00365 KKeyDialog::configure( actionCollection(),
true );
00366 }
00367
00368
void CertManager::slotShowConfigurationDialog() {
00369 ConfigureDialog dlg(
this );
00370 connect( &dlg, SIGNAL( configCommitted() ), SLOT( slotRepaint() ) );
00371 dlg.exec();
00372 }
00373
00374
void CertManager::slotConfigureGpgME() {
00375
Kleo::CryptoConfig* config = Kleo::CryptoBackendFactory::instance()->config();
00376
if ( config ) {
00377
Kleo::CryptoConfigDialog dlg( config );
00378 dlg.exec();
00379 }
00380 }
00381
00382
void CertManager::slotRepaint()
00383 {
00384 mKeyListView->repaintContents();
00385 }
00386
00387
void CertManager::slotToggleRemote(
int idx ) {
00388 mNextFindRemote = idx != 0;
00389 }
00390
00391
void CertManager::slotToggleHierarchicalView(
bool hier ) {
00392 mKeyListView->setHierarchical( hier );
00393 mKeyListView->setRootIsDecorated( hier );
00394
if ( KAction * act = action(
"view_expandall") )
00395 act->setEnabled( hier );
00396
if ( KAction * act = action(
"view_collapseall" ) )
00397 act->setEnabled( hier );
00398
if ( hier && !mCurrentQuery.isEmpty() )
00399 startRedisplay(
false );
00400 }
00401
00402
void CertManager::slotExpandAll() {
00403
for (
QListViewItemIterator it( mKeyListView ) ; it.current() ; ++it )
00404 it.current()->setOpen(
true );
00405 }
00406
00407
void CertManager::slotCollapseAll() {
00408
for (
QListViewItemIterator it( mKeyListView ) ; it.current() ; ++it )
00409 it.current()->setOpen(
false );
00410 }
00411
00412
void CertManager::connectJobToStatusBarProgress(
Kleo::Job * job,
const QString & initialText ) {
00413 assert( mProgressBar );
00414
if ( !job )
00415
return;
00416
if ( !initialText.isEmpty() )
00417 statusBar()->message( initialText );
00418 connect( job, SIGNAL(progress(
const QString&,
int,
int)),
00419 mProgressBar, SLOT(slotProgress(
const QString&,
int,
int)) );
00420 connect( job, SIGNAL(done()), mProgressBar, SLOT(reset()) );
00421 connect(
this, SIGNAL(stopOperations()), job, SLOT(slotCancel()) );
00422
00423 action(
"view_stop_operations")->setEnabled(
true );
00424 emit enableOperations(
false );
00425 }
00426
00427
void CertManager::disconnectJobFromStatusBarProgress(
const GpgME::Error & err ) {
00428 updateStatusBarLabels();
00429
const QString msg = err.isCanceled() ? i18n(
"Canceled.")
00430 : err ? i18n("Failed.")
00431 : i18n("Done.") ;
00432 statusBar()->message( msg, 4000 );
00433
00434 action(
"view_stop_operations")->setEnabled(
false );
00435 emit enableOperations(
true );
00436 slotSelectionChanged();
00437 }
00438
00439
void CertManager::updateStatusBarLabels() {
00440 mKeyListView->flushKeys();
00441
int total = 0;
00442
for (
QListViewItemIterator it( mKeyListView ) ; it.current() ; ++it )
00443 ++total;
00444 mStatusLabel->setText( i18n(
"%n Key.",
"%n Keys.", total ) );
00445 }
00446
00447
00448
00449
00450
00451
00452
00453
00454
static std::set<std::string> extractKeyFingerprints(
const QPtrList<Kleo::KeyListViewItem> & items ) {
00455 std::set<std::string> result;
00456
for (
QPtrListIterator<Kleo::KeyListViewItem> it( items ) ; it.current() ; ++it )
00457
if (
const char * fpr = it.current()->key().subkey(0).fingerprint() )
00458 result.insert( fpr );
00459
return result;
00460 }
00461
00462
static QStringList stringlistFromSet(
const std::set<std::string> & set ) {
00463
00464
QStringList sl;
00465
for ( std::set<std::string>::const_iterator it = set.begin() ; it != set.end() ; ++it )
00466
00467 sl.push_back( QString::fromLatin1( it->c_str() ) );
00468
return sl;
00469 }
00470
00471
void CertManager::slotRefreshKeys() {
00472
const QStringList keys = stringlistFromSet( extractKeyFingerprints( mKeyListView->selectedItems() ) );
00473
Kleo::RefreshKeysJob * job = Kleo::CryptoBackendFactory::instance()->smime()->refreshKeysJob();
00474 assert( job );
00475
00476 connect( job, SIGNAL(result(
const GpgME::Error&)),
00477
this, SLOT(slotRefreshKeysResult(
const GpgME::Error&)) );
00478
00479 connectJobToStatusBarProgress( job, i18n(
"Refreshing keys...") );
00480
if (
const GpgME::Error err = job->
start( keys ) )
00481 slotRefreshKeysResult( err );
00482 }
00483
00484
void CertManager::slotRefreshKeysResult(
const GpgME::Error & err ) {
00485 disconnectJobFromStatusBarProgress( err );
00486
if ( err.isCanceled() )
00487
return;
00488
if ( err )
00489 KMessageBox::error(
this, i18n(
"An error occurred while trying to refresh "
00490
"keys:\n%1").arg( QString::fromLocal8Bit( err.asString() ) ),
00491 i18n(
"Refreshing Keys Failed") );
00492 }
00493
00494
static void showKeyListError(
QWidget * parent,
const GpgME::Error & err ) {
00495 assert( err );
00496
const QString msg = i18n(
"<qt><p>An error occurred while fetching "
00497
"the certificates from the backend:</p>"
00498
"<p><b>%1</b></p></qt>" )
00499 .arg( QString::fromLocal8Bit( err.asString() ) );
00500
00501 KMessageBox::error( parent, msg, i18n(
"Certificate Listing Failed" ) );
00502 }
00503
00504
void CertManager::slotSearch() {
00505 mPreviouslySelectedFingerprints.clear();
00506
00507 mKeyListView->clear();
00508 mCurrentQuery = mLineEditAction->text();
00509 startKeyListing(
false,
false, mCurrentQuery );
00510 }
00511
00512
void CertManager::startRedisplay(
bool validate ) {
00513 mPreviouslySelectedFingerprints = extractKeyFingerprints( mKeyListView->selectedItems() );
00514
if ( mPreviouslySelectedFingerprints.empty() )
00515 startKeyListing( validate,
true, mCurrentQuery );
00516
else
00517 startKeyListing( validate,
true, mPreviouslySelectedFingerprints );
00518 }
00519
00520
void CertManager::startKeyListing(
bool validating,
bool refresh,
const std::set<std::string> & patterns ) {
00521 startKeyListing( validating, refresh, stringlistFromSet( patterns ) );
00522 }
00523
00524
void CertManager::startKeyListing(
bool validating,
bool refresh,
const QStringList & patterns ) {
00525 mRemote = mNextFindRemote;
00526 mLineEditAction->setEnabled(
false );
00527 mComboAction->setEnabled(
false );
00528 mFindAction->setEnabled(
false );
00529
00530
Kleo::KeyListJob * job = 0;
00531
if ( !validating && !refresh && mKeyListView->hierarchical() && !patterns.empty() )
00532 job =
new Kleo::HierarchicalKeyListJob( Kleo::CryptoBackendFactory::instance()->smime(),
00533 mRemote,
false, validating );
00534
else
00535 job = Kleo::CryptoBackendFactory::instance()->smime()->keyListJob( mRemote,
false, validating );
00536 assert( job );
00537
00538 connect( job, SIGNAL(nextKey(
const GpgME::Key&)),
00539 mKeyListView, refresh ? SLOT(slotRefreshKey(
const GpgME::Key&)) : SLOT(slotAddKey(
const GpgME::Key&)) );
00540 connect( job, SIGNAL(result(
const GpgME::KeyListResult&)),
00541
this, SLOT(slotKeyListResult(
const GpgME::KeyListResult&)) );
00542
00543 connectJobToStatusBarProgress( job, i18n(
"Fetching keys...") );
00544
00545
const GpgME::Error err = job->
start( patterns ) ;
00546
if ( err ) {
00547 showKeyListError(
this, err );
00548
return;
00549 }
00550 mProgressBar->setProgress( 0, 0 );
00551 }
00552
00553
static void selectKeys( Kleo::KeyListView * lv,
const std::set<std::string> & fprs ) {
00554
if ( !lv || fprs.empty() )
00555
return;
00556
for (
QListViewItemIterator it( lv ) ; it.current() ; ++it )
00557
if ( ( it.current()->rtti() & Kleo::KeyListViewItem::RTTI_MASK ) == Kleo::KeyListViewItem::RTTI ) {
00558 Kleo::KeyListViewItem * item = static_cast<Kleo::KeyListViewItem*>( it.current() );
00559
const char * fpr = item->key().subkey(0).fingerprint();
00560 item->setSelected( fpr && fprs.find( fpr ) != fprs.end() );
00561 }
00562 }
00563
00564
void CertManager::slotKeyListResult(
const GpgME::KeyListResult & res ) {
00565
if ( res.error() )
00566 showKeyListError(
this, res.error() );
00567
else if ( res.isTruncated() )
00568 KMessageBox::information(
this,
00569 i18n(
"The query result has been truncated.\n"
00570
"Either the local or a remote limit on "
00571
"the maximum number of returned hits has "
00572
"been exceeded.\n"
00573
"You can try to increase the local limit "
00574
"in the configuration dialog, but if one "
00575
"of the configured servers is the limiting "
00576
"factor, you have to refine your search.") );
00577
00578 mLineEditAction->setEnabled(
true );
00579 mComboAction->setEnabled(
true );
00580 mFindAction->setEnabled(
true );
00581
00582 mLineEditAction->focusAll();
00583 disconnectJobFromStatusBarProgress( res.error() );
00584 selectKeys( mKeyListView, mPreviouslySelectedFingerprints );
00585 }
00586
00587
void CertManager::slotContextMenu(Kleo::KeyListViewItem* item,
const QPoint& point) {
00588
if ( !item )
00589
return;
00590
if (
QPopupMenu * popup = static_cast<QPopupMenu*>(factory()->container(
"listview_popup",
this)) )
00591 popup->exec( point );
00592 }
00593
00597
void CertManager::newCertificate()
00598 {
00599 CertificateWizardImpl wizard(
this );
00600 wizard.exec();
00601 }
00602
00607
void CertManager::revokeCertificate()
00608 {
00609 qDebug(
"Not Yet Implemented");
00610 }
00611
00616
void CertManager::extendCertificate()
00617 {
00618 qDebug(
"Not Yet Implemented");
00619 }
00620
00621
00622
00623
00624
00625
00626
00627
00628
00632
void CertManager::slotImportCertFromFile()
00633 {
00634
const QString filter =
"application/x-x509-ca-cert application/x-pkcs12 application/pkcs7-mime";
00635
00636 slotImportCertFromFile( KFileDialog::getOpenURL( QString::null, filter,
this,
00637 i18n(
"Select Certificate File" ) ) );
00638 }
00639
00640
void CertManager::slotImportCertFromFile(
const KURL & certURL )
00641 {
00642
if ( !certURL.isValid() )
00643
return;
00644
00645 mPreviouslySelectedFingerprints.clear();
00646
00647
00648 updateImportActions(
false );
00649
00650
00651
KIOext::StoredTransferJob* importJob = KIOext::storedGet( certURL );
00652 importJob->setWindow(
this );
00653 connect( importJob, SIGNAL(result(KIO::Job*)), SLOT(slotImportResult(KIO::Job*)) );
00654 }
00655
00656
void CertManager::slotImportResult( KIO::Job* job )
00657 {
00658
if ( job->error() ) {
00659 job->showErrorDialog();
00660 }
else {
00661
KIOext::StoredTransferJob* trJob = static_cast<KIOext::StoredTransferJob *>( job );
00662 startCertificateImport( trJob->
data(), trJob->url().fileName() );
00663 }
00664
00665 updateImportActions(
true );
00666 }
00667
00668
static void showCertificateDownloadError(
QWidget * parent,
const GpgME::Error & err,
const QString& certDisplayName ) {
00669 assert( err );
00670
const QString msg = i18n(
"<qt><p>An error occurred while trying "
00671
"to download the certificate %1:</p>"
00672
"<p><b>%2</b></p></qt>" )
00673 .arg( certDisplayName )
00674 .arg( QString::fromLocal8Bit( err.asString() ) );
00675
00676 KMessageBox::error( parent, msg, i18n(
"Certificate Download Failed" ) );
00677 }
00678
00679
void CertManager::slotDownloadCertificate() {
00680 mPreviouslySelectedFingerprints.clear();
00681
QPtrList<Kleo::KeyListViewItem> items = mKeyListView->selectedItems();
00682
for (
QPtrListIterator<Kleo::KeyListViewItem> it( items ) ; it.current() ; ++it )
00683
if ( !it.current()->key().isNull() )
00684
if (
const char * fpr = it.current()->key().subkey(0).fingerprint() )
00685 slotStartCertificateDownload( fpr, it.current()->text(0) );
00686 }
00687
00688
00689
void CertManager::slotStartCertificateDownload(
const QString& fingerprint,
const QString& displayName ) {
00690
if ( fingerprint.isEmpty() )
00691
return;
00692
00693
Kleo::DownloadJob * job =
00694 Kleo::CryptoBackendFactory::instance()->smime()->downloadJob(
false );
00695 assert( job );
00696
00697 connect( job, SIGNAL(result(
const GpgME::Error&,
const QByteArray&)),
00698 SLOT(slotCertificateDownloadResult(
const GpgME::Error&,
const QByteArray&)) );
00699
00700 connectJobToStatusBarProgress( job, i18n(
"Fetching certificate from server...") );
00701
00702
const GpgME::Error err = job->
start( fingerprint );
00703
if ( err )
00704 showCertificateDownloadError(
this, err, displayName );
00705
else {
00706 mProgressBar->setProgress( 0, 0 );
00707 mJobsDisplayNameMap.insert( job, displayName );
00708 }
00709 }
00710
00711
QString CertManager::displayNameForJob(
const Kleo::Job *job )
00712 {
00713 JobsDisplayNameMap::iterator it = mJobsDisplayNameMap.find( job );
00714
QString displayName;
00715
if ( it != mJobsDisplayNameMap.end() ) {
00716 displayName = *it;
00717 mJobsDisplayNameMap.remove( it );
00718 }
else {
00719 kdWarning() <<
"Job not found in map: " << job << endl;
00720 }
00721
return displayName;
00722 }
00723
00724
00725
void CertManager::slotCertificateDownloadResult(
const GpgME::Error & err,
const QByteArray & keyData ) {
00726
00727
QString displayName = displayNameForJob( static_cast<const Kleo::Job *>( sender() ) );
00728
00729
if ( err )
00730 showCertificateDownloadError(
this, err, displayName );
00731
else
00732 startCertificateImport( keyData, displayName );
00733 disconnectJobFromStatusBarProgress( err );
00734 }
00735
00736
static void showCertificateImportError(
QWidget * parent,
const GpgME::Error & err,
const QString& certDisplayName ) {
00737 assert( err );
00738
const QString msg = i18n(
"<qt><p>An error occurred while trying "
00739
"to import the certificate %1:</p>"
00740
"<p><b>%2</b></p></qt>" )
00741 .arg( certDisplayName )
00742 .arg( QString::fromLocal8Bit( err.asString() ) );
00743 KMessageBox::error( parent, msg, i18n(
"Certificate Import Failed" ) );
00744 }
00745
00746
void CertManager::startCertificateImport(
const QByteArray & keyData,
const QString& certDisplayName ) {
00747
Kleo::ImportJob * job = Kleo::CryptoBackendFactory::instance()->smime()->importJob();
00748 assert( job );
00749
00750 connect( job, SIGNAL(result(
const GpgME::ImportResult&)),
00751 SLOT(slotCertificateImportResult(
const GpgME::ImportResult&)) );
00752
00753 connectJobToStatusBarProgress( job, i18n(
"Importing certificates...") );
00754
00755 kdDebug() <<
"Importing certificate. keyData size:" << keyData.size() << endl;
00756
const GpgME::Error err = job->
start( keyData );
00757
if ( err )
00758 showCertificateImportError(
this, err, certDisplayName );
00759
else {
00760 mProgressBar->setProgress( 0, 0 );
00761 mJobsDisplayNameMap.insert( job, certDisplayName );
00762 }
00763 }
00764
00765
void CertManager::slotCertificateImportResult(
const GpgME::ImportResult & res ) {
00766
QString displayName = displayNameForJob( static_cast<const Kleo::Job *>( sender() ) );
00767
00768
if ( res.error().isCanceled() ) {
00769
00770 }
else if ( res.error() ) {
00771 showCertificateImportError(
this, res.error(), displayName );
00772 }
else {
00773
00774
const QString normalLine = i18n(
"<tr><td align=\"right\">%1</td><td>%2</td></tr>");
00775
const QString boldLine = i18n(
"<tr><td align=\"right\"><b>%1</b></td><td>%2</td></tr>");
00776
00777
QStringList lines;
00778 lines.push_back( normalLine.arg( i18n(
"Total number processed:"),
00779 QString::number( res.numConsidered() ) ) );
00780 lines.push_back( normalLine.arg( i18n(
"Imported:"),
00781 QString::number( res.numImported() ) ) );
00782
if ( res.newSignatures() )
00783 lines.push_back( normalLine.arg( i18n(
"New signatures:"),
00784 QString::number( res.newSignatures() ) ) );
00785
if ( res.newUserIDs() )
00786 lines.push_back( normalLine.arg( i18n(
"New user IDs:"),
00787 QString::number( res.newUserIDs() ) ) );
00788
if ( res.numKeysWithoutUserID() )
00789 lines.push_back( normalLine.arg( i18n(
"Keys without user IDs:"),
00790 QString::number( res.numKeysWithoutUserID() ) ) );
00791
if ( res.newSubkeys() )
00792 lines.push_back( normalLine.arg( i18n(
"New subkeys:"),
00793 QString::number( res.newSubkeys() ) ) );
00794
if ( res.newRevocations() )
00795 lines.push_back( boldLine.arg( i18n(
"Newly revoked:"),
00796 QString::number( res.newRevocations() ) ) );
00797
if ( res.notImported() )
00798 lines.push_back( boldLine.arg( i18n(
"Not imported:"),
00799 QString::number( res.notImported() ) ) );
00800
if ( res.numUnchanged() )
00801 lines.push_back( normalLine.arg( i18n(
"Unchanged:"),
00802 QString::number( res.numUnchanged() ) ) );
00803
if ( res.numSecretKeysConsidered() )
00804 lines.push_back( normalLine.arg( i18n(
"Secret keys processed:"),
00805 QString::number( res.numSecretKeysConsidered() ) ) );
00806
if ( res.numSecretKeysImported() )
00807 lines.push_back( normalLine.arg( i18n(
"Secret keys imported:"),
00808 QString::number( res.numSecretKeysImported() ) ) );
00809
if ( res.numSecretKeysConsidered() - res.numSecretKeysImported() - res.numSecretKeysUnchanged() > 0 )
00810 lines.push_back( boldLine.arg( i18n(
"Secret keys <em>not</em> imported:"),
00811 QString::number( res.numSecretKeysConsidered()
00812 - res.numSecretKeysImported()
00813 - res.numSecretKeysUnchanged() ) ) );
00814
if ( res.numSecretKeysUnchanged() )
00815 lines.push_back( normalLine.arg( i18n(
"Secret keys unchanged:"),
00816 QString::number( res.numSecretKeysUnchanged() ) ) );
00817
00818 KMessageBox::information(
this,
00819 i18n(
"<qt><p>Detailed results of importing %1:</p>"
00820
"<table>%2</table></qt>" )
00821 .arg( displayName ).arg( lines.join( QString::null ) ),
00822 i18n(
"Certificate Import Result" ) );
00823
00824 disconnectJobFromStatusBarProgress( res.error() );
00825
00826
const std::vector<GpgME::Import> imports = res.imports();
00827
for ( std::vector<GpgME::Import>::const_iterator it = imports.begin() ; it != imports.end() ; ++it )
00828 mPreviouslySelectedFingerprints.insert( it->fingerprint() );
00829 }
00830 importNextURLOrRedisplay();
00831 }
00832
00833
00834
00839
void CertManager::slotDirmngrExited() {
00840
if ( !mDirmngrProc->normalExit() )
00841 KMessageBox::error(
this, i18n(
"The GpgSM process that tried to import the CRL file ended prematurely because of an unexpected error." ), i18n(
"Certificate Manager Error" ) );
00842
else if ( mDirmngrProc->exitStatus() )
00843 KMessageBox::error(
this, i18n(
"An error occurred when trying to import the CRL file. The output from GpgSM was:\n%1").arg( mErrorbuffer ), i18n(
"Certificate Manager Error" ) );
00844
else
00845 KMessageBox::information(
this, i18n(
"CRL file imported successfully." ), i18n(
"Certificate Manager Information" ) );
00846
00847
delete mDirmngrProc; mDirmngrProc = 0;
00848
if ( !mImportCRLTempFile.isEmpty() )
00849 QFile::remove( mImportCRLTempFile );
00850 updateImportActions(
true );
00851 }
00852
00856
void CertManager::importCRLFromFile() {
00857
QString filter =
QString(
"*.crl *.arl *-crl.der *-arl.der|") + i18n(
"Certificate Revocation List (*.crl *.arl *-crl.der *-arl.der)");
00858 KURL url = KFileDialog::getOpenURL( QString::null,
00859 filter,
00860
this,
00861 i18n(
"Select CRL File" ) );
00862
if ( url.isValid() ) {
00863 updateImportActions(
false );
00864
if ( url.isLocalFile() ) {
00865 startImportCRL( url.path(),
false );
00866 updateImportActions(
true );
00867 }
else {
00868 KTempFile tempFile;
00869 KURL destURL;
00870 destURL.setPath( tempFile.name() );
00871 KIO::Job* copyJob = KIO::file_copy( url, destURL, 0600,
true,
false );
00872 copyJob->setWindow(
this );
00873 connect( copyJob, SIGNAL( result( KIO::Job * ) ),
00874 SLOT( slotImportCRLJobFinished( KIO::Job * ) ) );
00875 }
00876 }
00877 }
00878
00879
void CertManager::slotImportCRLJobFinished( KIO::Job *job )
00880 {
00881 KIO::FileCopyJob* fcjob = static_cast<KIO::FileCopyJob*>( job );
00882 QString tempFilePath = fcjob->destURL().path();
00883
if ( job->error() ) {
00884 job->showErrorDialog();
00885 QFile::remove( tempFilePath );
00886 updateImportActions(
true );
00887
return;
00888 }
00889 startImportCRL( tempFilePath,
true );
00890 }
00891
00892
bool CertManager::connectAndStartDirmngr(
const char * slot,
const char * processname ) {
00893 assert( slot );
00894 assert( processname );
00895 assert( mDirmngrProc );
00896 mErrorbuffer = QString::null;
00897 connect( mDirmngrProc, SIGNAL(processExited(KProcess*)), slot );
00898 connect( mDirmngrProc, SIGNAL(receivedStderr(KProcess*,
char*,
int) ),
00899
this, SLOT(slotStderr(KProcess*,
char*,
int)) );
00900
if( !mDirmngrProc->start( KProcess::NotifyOnExit, KProcess::Stderr ) ) {
00901
delete mDirmngrProc; mDirmngrProc = 0;
00902 KMessageBox::error(
this, i18n(
"Unable to start %1 process. Please check your installation." ).arg( processname ), i18n(
"Certificate Manager Error" ) );
00903
return false;
00904 }
00905
return true;
00906 }
00907
00908
void CertManager::startImportCRL(
const QString& filename,
bool isTempFile )
00909 {
00910 assert( !mDirmngrProc );
00911 mImportCRLTempFile = isTempFile ? filename : QString::null;
00912 mDirmngrProc =
new KProcess();
00913 *mDirmngrProc <<
"gpgsm" <<
"--call-dirmngr" <<
"loadcrl" << filename;
00914
if ( !connectAndStartDirmngr( SLOT(slotDirmngrExited()),
"gpgsm" ) ) {
00915 updateImportActions(
true );
00916
if ( isTempFile )
00917 QFile::remove( mImportCRLTempFile );
00918 }
00919 }
00920
00921
void CertManager::startClearCRLs() {
00922 assert( !mDirmngrProc );
00923 mDirmngrProc =
new KProcess();
00924 *mDirmngrProc <<
"dirmngr" <<
"--flush";
00925
00926 connectAndStartDirmngr( SLOT(slotClearCRLsResult()),
"dirmngr" );
00927 }
00928
00929
void CertManager::slotStderr( KProcess*,
char* buf,
int len ) {
00930 mErrorbuffer += QString::fromLocal8Bit( buf, len );
00931 }
00932
00936
void CertManager::importCRLFromLDAP()
00937 {
00938 qDebug(
"Not Yet Implemented");
00939 }
00940
00941
void CertManager::slotViewCRLs() {
00942
if ( !mCrlView )
00943 mCrlView =
new CRLView(
this );
00944
00945 mCrlView->show();
00946 mCrlView->slotUpdateView();
00947 }
00948
00949
00950
void CertManager::slotClearCRLs() {
00951 startClearCRLs();
00952 }
00953
00954
void CertManager::slotClearCRLsResult() {
00955 assert( mDirmngrProc );
00956
if ( !mDirmngrProc->normalExit() )
00957 KMessageBox::error(
this, i18n(
"The DirMngr process that tried to clear the CRL cache ended prematurely because of an unexpected error." ), i18n(
"Certificate Manager Error" ) );
00958
else if ( mDirmngrProc->exitStatus() )
00959 KMessageBox::error(
this, i18n(
"An error occurred when trying to clear the CRL cache. The output from DirMngr was:\n%1").arg( mErrorbuffer ), i18n(
"Certificate Manager Error" ) );
00960
else
00961 KMessageBox::information(
this, i18n(
"CRL cache cleared successfully." ), i18n(
"Certificate Manager Information" ) );
00962
delete mDirmngrProc; mDirmngrProc = 0;
00963 }
00964
00965
static void showDeleteError(
QWidget * parent,
const GpgME::Error & err ) {
00966 assert( err );
00967
const QString msg = i18n(
"<qt><p>An error occurred while trying to delete "
00968
"the certificates:</p>"
00969
"<p><b>%1</b></p></qt>")
00970 .arg( QString::fromLocal8Bit( err.asString() ) );
00971 KMessageBox::error( parent, msg, i18n(
"Certificate Deletion Failed") );
00972 }
00973
00974
static bool ByFingerprint(
const GpgME::Key & left,
const GpgME::Key & right ) {
00975
return qstricmp( left.primaryFingerprint(), right.primaryFingerprint() ) < 0 ;
00976 }
00977
00978
static bool WithRespectToFingerprints(
const GpgME::Key & left,
const GpgME::Key & right ) {
00979
return qstricmp( left.primaryFingerprint(), right.primaryFingerprint() ) == 0;
00980 }
00981
00982
void CertManager::slotDeleteCertificate() {
00983 mItemsToDelete = mKeyListView->selectedItems();
00984
if ( mItemsToDelete.isEmpty() )
00985
return;
00986 std::vector<GpgME::Key> keys;
00987 keys.reserve( mItemsToDelete.count() );
00988
QStringList keyDisplayNames;
00989
for (
QPtrListIterator<Kleo::KeyListViewItem> it( mItemsToDelete ) ; it.current() ; ++it )
00990
if ( !it.current()->key().isNull() ) {
00991 keys.push_back( it.current()->key() );
00992 keyDisplayNames.push_back( it.current()->text( 0 ) );
00993 }
00994
if ( keys.empty() )
00995
return;
00996
00997
if ( !mHierarchyAnalyser ) {
00998 mHierarchyAnalyser =
new HierarchyAnalyser(
this,
"mHierarchyAnalyser" );
00999
Kleo::KeyListJob * job = Kleo::CryptoBackendFactory::instance()->smime()->keyListJob();
01000 assert( job );
01001 connect( job, SIGNAL(nextKey(
const GpgME::Key&)),
01002 mHierarchyAnalyser, SLOT(slotNextKey(
const GpgME::Key&)) );
01003 connect( job, SIGNAL(result(
const GpgME::KeyListResult&)),
01004
this, SLOT(slotDeleteCertificate()) );
01005 connectJobToStatusBarProgress( job, i18n(
"Checking key dependencies...") );
01006
if (
const GpgME::Error error = job->
start(
QStringList() ) ) {
01007 showKeyListError(
this, error );
01008
delete mHierarchyAnalyser; mHierarchyAnalyser = 0;
01009 }
01010
return;
01011 }
else
01012 disconnectJobFromStatusBarProgress( 0 );
01013
01014 std::vector<GpgME::Key> keysToDelete = keys;
01015
for ( std::vector<GpgME::Key>::const_iterator it = keys.begin() ; it != keys.end() ; ++it )
01016
if ( !it->isNull() ) {
01017
const std::vector<GpgME::Key> subjects
01018 = mHierarchyAnalyser->subjectsForIssuerRecursive( it->subkey(0).fingerprint() );
01019 keysToDelete.insert( keysToDelete.end(), subjects.begin(), subjects.end() );
01020 }
01021
01022 std::sort( keysToDelete.begin(), keysToDelete.end(), ByFingerprint );
01023 keysToDelete.erase( std::unique( keysToDelete.begin(), keysToDelete.end(),
01024 WithRespectToFingerprints ),
01025 keysToDelete.end() );
01026
01027
delete mHierarchyAnalyser; mHierarchyAnalyser = 0;
01028
01029
if ( keysToDelete.size() > keys.size() )
01030
if ( KMessageBox::warningContinueCancel(
this,
01031 i18n(
"Some or all of the selected "
01032
"certificates are issuers (CA certificates) "
01033
"for other, non-selected certificates.\n"
01034
"Deleting a CA certificate will also delete "
01035
"all certificates issued by it."),
01036 i18n(
"Deleting CA Certificates") )
01037 != KMessageBox::Continue )
01038
return;
01039
01040
const QString msg = keysToDelete.size() > keys.size()
01041 ? i18n(
"Do you really want to delete this certificate and the %1 certificates it certified?",
01042
"Do you really want to delete these %n certificates and the %1 certificates they certified?",
01043 keys.size() ).arg( keysToDelete.size() - keys.size() )
01044 : i18n(
"Do you really want to delete this certificate?",
01045
"Do you really want to delete these %n certificates?", keys.size() ) ;
01046
01047
if ( KMessageBox::warningContinueCancelList(
this, msg, keyDisplayNames,
01048 i18n(
"Delete Certificates" ),
01049 KGuiItem( i18n(
"Delete" ),
"editdelete" ),
01050
"ConfirmDeleteCert", KMessageBox::Dangerous )
01051 != KMessageBox::Continue )
01052
return;
01053
01054
if (
Kleo::DeleteJob * job = Kleo::CryptoBackendFactory::instance()->smime()->deleteJob() )
01055 job->
slotCancel();
01056
else {
01057 QString str = keys.size() == 1
01058 ? i18n(
"<qt><p>An error occurred while trying to delete "
01059
"the certificate:</p>"
01060
"<p><b>%1</b><p></qt>" )
01061 : i18n( "<qt><p>An error occurred while trying to delete "
01062 "the certificates:</p>"
01063 "<p><b>%1</b><p></qt>" );
01064 KMessageBox::error(
this,
01065 str.arg( i18n(
"Operation not supported by the backend.") ),
01066 i18n(
"Certificate Deletion Failed") );
01067 }
01068
Kleo::MultiDeleteJob * job =
new Kleo::MultiDeleteJob( Kleo::CryptoBackendFactory::instance()->smime() );
01069 assert( job );
01070
01071 connect( job, SIGNAL(result(
const GpgME::Error&,
const GpgME::Key&)),
01072 SLOT(slotDeleteResult(
const GpgME::Error&,
const GpgME::Key&)) );
01073
01074 connectJobToStatusBarProgress( job, i18n(
"Deleting keys...") );
01075
01076
const GpgME::Error err = job->
start( keys,
true );
01077
if ( err )
01078 showDeleteError(
this, err );
01079
else
01080 mProgressBar->setProgress( 0, 0 );
01081 }
01082
01083
void CertManager::slotDeleteResult(
const GpgME::Error & err,
const GpgME::Key & ) {
01084
if ( err )
01085 showDeleteError(
this, err );
01086
else {
01087 mItemsToDelete.setAutoDelete(
true );
01088 mItemsToDelete.clear();
01089 mItemsToDelete.setAutoDelete(
false );
01090 }
01091 disconnectJobFromStatusBarProgress( err );
01092 }
01093
01094
void CertManager::slotViewDetails( Kleo::KeyListViewItem * item ) {
01095
if ( !item || item->key().isNull() )
01096
return;
01097
01098
01099 KDialogBase * dialog =
new KDialogBase(
this,
"dialog",
false, i18n(
"Additional Information for Key"), KDialogBase::Close, KDialogBase::Close );
01100
01101 CertificateInfoWidgetImpl * top =
new CertificateInfoWidgetImpl( item->key(), isRemote(), dialog );
01102 dialog->setMainWidget( top );
01103
01104 connect( top, SIGNAL(requestCertificateDownload(
const QString&,
const QString&)),
01105 SLOT(slotStartCertificateDownload(
const QString&,
const QString&)) );
01106 dialog->show();
01107 }
01108
01109
void CertManager::slotViewDetails()
01110 {
01111
QPtrList<Kleo::KeyListViewItem> items = mKeyListView->selectedItems();
01112
if ( items.isEmpty() )
01113
return;
01114
01115
01116
01117 slotViewDetails( items.first() );
01118 }
01119
01120
void CertManager::slotSelectionChanged()
01121 {
01122 mKeyListView->flushKeys();
01123
bool b = mKeyListView->hasSelection();
01124 mExportCertificateAction->setEnabled( b );
01125 mViewCertDetailsAction->setEnabled( b );
01126 mDeleteCertificateAction->setEnabled( b );
01127
#ifdef NOT_IMPLEMENTED_ANYWAY
01128
mRevokeCertificateAction->setEnabled( b );
01129 mExtendCertificateAction->setEnabled( b );
01130
#endif
01131
mDownloadCertificateAction->setEnabled( b && mRemote );
01132 mValidateCertificateAction->setEnabled( !mRemote );
01133 }
01134
01135
void CertManager::slotExportCertificate() {
01136
QPtrList<Kleo::KeyListViewItem> items = mKeyListView->selectedItems();
01137
if ( items.isEmpty() )
01138
return;
01139
01140
QStringList fingerprints;
01141
for (
QPtrListIterator<Kleo::KeyListViewItem> it( items ) ; it.current() ; ++it )
01142
if ( !it.current()->key().isNull() )
01143
if (
const char * fpr = it.current()->key().subkey(0).fingerprint() )
01144 fingerprints.push_back( fpr );
01145
01146 startCertificateExport( fingerprints );
01147 }
01148
01149
static void showCertificateExportError(
QWidget * parent,
const GpgME::Error & err ) {
01150 assert( err );
01151
const QString msg = i18n(
"<qt><p>An error occurred while trying to export "
01152
"the certificate:</p>"
01153
"<p><b>%1</b></p></qt>")
01154 .arg( QString::fromLocal8Bit( err.asString() ) );
01155 KMessageBox::error( parent, msg, i18n(
"Certificate Export Failed") );
01156 }
01157
01158
void CertManager::startCertificateExport(
const QStringList & fingerprints ) {
01159
if ( fingerprints.empty() )
01160
return;
01161
01162
01163
01164
Kleo::ExportJob * job = Kleo::CryptoBackendFactory::instance()->smime()->publicKeyExportJob(
true );
01165 assert( job );
01166
01167 connect( job, SIGNAL(result(
const GpgME::Error&,
const QByteArray&)),
01168 SLOT(slotCertificateExportResult(
const GpgME::Error&,
const QByteArray&)) );
01169
01170 connectJobToStatusBarProgress( job, i18n(
"Exporting certificate...") );
01171
01172
const GpgME::Error err = job->
start( fingerprints );
01173
if ( err )
01174 showCertificateExportError(
this, err );
01175
else
01176 mProgressBar->setProgress( 0, 0 );
01177 }
01178
01179
01180
static bool checkOverwrite(
const KURL& url,
bool& overwrite,
QWidget* w )
01181 {
01182
if ( KIO::NetAccess::exists( url,
false , w ) ) {
01183
if ( KMessageBox::Cancel ==
01184 KMessageBox::warningContinueCancel(
01185 w,
01186 i18n(
"A file named \"%1\" already exists. "
01187
"Are you sure you want to overwrite it?" ).arg( url.prettyURL() ),
01188 i18n(
"Overwrite File?" ),
01189 i18n(
"&Overwrite" ) ) )
01190
return false;
01191 overwrite =
true;
01192 }
01193
return true;
01194 }
01195
01196
void CertManager::slotCertificateExportResult(
const GpgME::Error & err,
const QByteArray & data ) {
01197 disconnectJobFromStatusBarProgress( err );
01198
if ( err ) {
01199 showCertificateExportError(
this, err );
01200
return;
01201 }
01202
01203 kdDebug() <<
"CertManager::slotCertificateExportResult(): got " << data.size() <<
" bytes" << endl;
01204
01205
const QString filter = QString(
"*.pem|") + i18n(
"ASCII Armored Certificate Bundles (*.pem)");
01206
const KURL url = KFileDialog::getOpenURL( QString::null,
01207 filter,
01208
this,
01209 i18n(
"Save Certificate" ) );
01210
if ( !url.isValid() )
01211
return;
01212
01213
bool overwrite =
false;
01214
if ( !checkOverwrite( url, overwrite,
this ) )
01215
return;
01216
01217 KIO::Job* uploadJob = KIOext::put( data, url, -1, overwrite,
false );
01218 uploadJob->setWindow(
this );
01219 connect( uploadJob, SIGNAL( result( KIO::Job* ) ),
01220
this, SLOT( slotUploadResult( KIO::Job* ) ) );
01221 }
01222
01223
01224
void CertManager::slotExportSecretKey() {
01225 Kleo::KeySelectionDialog dlg( i18n(
"Secret Key Export"),
01226 i18n(
"Select the secret key to export "
01227
"(<b>Warning: The PKCS#12 format is insecure; "
01228
"exporting secret keys is discouraged</b>):"),
01229 std::vector<GpgME::Key>(),
01230 Kleo::KeySelectionDialog::SecretKeys|Kleo::KeySelectionDialog::SMIMEKeys,
01231
false ,
01232
false ,
01233
this,
"secret key export key selection dialog" );
01234
01235
01236
if ( dlg.exec() != QDialog::Accepted )
01237
return;
01238
01239 startSecretKeyExport( dlg.fingerprint() );
01240 }
01241
01242
static void showSecretKeyExportError(
QWidget * parent,
const GpgME::Error & err ) {
01243 assert( err );
01244
const QString msg = i18n(
"<qt><p>An error occurred while trying to export "
01245
"the secret key:</p>"
01246
"<p><b>%1</b></p></qt>")
01247 .arg( QString::fromLocal8Bit( err.asString() ) );
01248 KMessageBox::error( parent, msg, i18n(
"Secret-Key Export Failed") );
01249 }
01250
01251
void CertManager::startSecretKeyExport(
const QString & fingerprint ) {
01252
if ( fingerprint.isEmpty() )
01253
return;
01254
01255
01256
Kleo::ExportJob * job = Kleo::CryptoBackendFactory::instance()->smime()->secretKeyExportJob(
false );
01257 assert( job );
01258
01259 connect( job, SIGNAL(result(
const GpgME::Error&,
const QByteArray&)),
01260 SLOT(slotSecretKeyExportResult(
const GpgME::Error&,
const QByteArray&)) );
01261
01262 connectJobToStatusBarProgress( job, i18n(
"Exporting secret key...") );
01263
01264
const GpgME::Error err = job->
start( fingerprint );
01265
if ( err )
01266 showSecretKeyExportError(
this, err );
01267
else
01268 mProgressBar->setProgress( 0, 0 );
01269 }
01270
01271
void CertManager::slotSecretKeyExportResult(
const GpgME::Error & err,
const QByteArray & data ) {
01272 disconnectJobFromStatusBarProgress( err );
01273
if ( err ) {
01274 showSecretKeyExportError(
this, err );
01275
return;
01276 }
01277
01278 kdDebug() <<
"CertManager::slotSecretKeyExportResult(): got " << data.size() <<
" bytes" << endl;
01279 QString filter = QString(
"*.p12|") + i18n(
"PKCS#12 Key Bundle (*.p12)");
01280 KURL url = KFileDialog::getOpenURL( QString::null,
01281 filter,
01282
this,
01283 i18n(
"Save Certificate" ) );
01284
if ( !url.isValid() )
01285
return;
01286
01287
bool overwrite =
false;
01288
if ( !checkOverwrite( url, overwrite,
this ) )
01289
return;
01290
01291 KIO::Job* uploadJob = KIOext::put( data, url, -1, overwrite,
false );
01292 uploadJob->setWindow(
this );
01293 connect( uploadJob, SIGNAL( result( KIO::Job* ) ),
01294
this, SLOT( slotUploadResult( KIO::Job* ) ) );
01295 }
01296
01297
void CertManager::slotUploadResult( KIO::Job* job )
01298 {
01299
if ( job->error() )
01300 job->showErrorDialog();
01301 }
01302
01303
void CertManager::slotDropped(
const KURL::List& lst)
01304 {
01305 mURLsToImport = lst;
01306
if ( !lst.empty() )
01307 importNextURLOrRedisplay();
01308 }
01309
01310
void CertManager::importNextURLOrRedisplay()
01311 {
01312
if ( !mURLsToImport.empty() ) {
01313
01314 KURL url = mURLsToImport.front();
01315 mURLsToImport.pop_front();
01316 slotImportCertFromFile( url );
01317 }
else {
01318
if ( isRemote() )
01319
return;
01320 startKeyListing(
false,
true, mPreviouslySelectedFingerprints );
01321 }
01322 }
01323
01324
void CertManager::slotStartWatchGnuPG()
01325 {
01326 KProcess certManagerProc;
01327 certManagerProc <<
"kwatchgnupg";
01328
01329
if( !certManagerProc.start( KProcess::DontCare ) )
01330 KMessageBox::error(
this, i18n(
"Could not start GnuPG LogViewer (kwatchgnupg). "
01331
"Please check your installation!" ),
01332 i18n(
"Kleopatra Error" ) );
01333 }
01334
01335
#include "certmanager.moc"