• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdepim API Reference
  • KDE Home
  • Contact Us
 

kleopatra

  • sources
  • kde-4.14
  • kdepim
  • kleopatra
  • newcertificatewizard
newcertificatewizard.cpp
Go to the documentation of this file.
1 /* -*- mode: c++; c-basic-offset:4 -*-
2  newcertificatewizard/newcertificatewizard.cpp
3 
4  This file is part of Kleopatra, the KDE keymanager
5  Copyright (c) 2008 Klarälvdalens Datakonsult AB
6 
7  Kleopatra is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 2 of the License, or
10  (at your option) any later version.
11 
12  Kleopatra is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 
21  In addition, as a special exception, the copyright holders give
22  permission to link the code of this program with any edition of
23  the Qt library by Trolltech AS, Norway (or with modified versions
24  of Qt that use the same license as Qt), and distribute linked
25  combinations including the two. You must obey the GNU General
26  Public License in all respects for all of the code used other than
27  Qt. If you modify this file, you may extend this exception to
28  your version of the file, but you are not obligated to do so. If
29  you do not wish to do so, delete this exception statement from
30  your version.
31 */
32 
33 #include <config-kleopatra.h>
34 
35 #include "newcertificatewizard.h"
36 
37 #include "ui_chooseprotocolpage.h"
38 #include "ui_enterdetailspage.h"
39 #include "ui_overviewpage.h"
40 #include "ui_keycreationpage.h"
41 #include "ui_resultpage.h"
42 
43 #include "ui_advancedsettingsdialog.h"
44 
45 #include <models/keycache.h>
46 
47 #include <commands/exportsecretkeycommand.h>
48 #include <commands/exportopenpgpcertstoservercommand.h>
49 #include <commands/exportcertificatecommand.h>
50 
51 #include <utils/formatting.h>
52 #include <utils/validation.h>
53 #include <utils/filedialog.h>
54 
55 #include <kleo/stl_util.h>
56 #include <kleo/dn.h>
57 #include <kleo/oidmap.h>
58 #include <kleo/keygenerationjob.h>
59 #include <kleo/cryptobackendfactory.h>
60 #include <kleo/cryptobackend.h>
61 
62 #include <gpgme++/global.h>
63 #include <gpgme++/keygenerationresult.h>
64 #include <gpgme.h>
65 
66 #include <KConfigGroup>
67 #include <KGlobal>
68 #include <KLocalizedString>
69 #include <KDebug>
70 #include <KTempDir>
71 #include <KMessageBox>
72 
73 #include <QRegExpValidator>
74 #include <QLineEdit>
75 #include <QMetaProperty>
76 #include <QDir>
77 #include <QFile>
78 #include <QUrl>
79 #include <QDesktopServices>
80 
81 #ifndef Q_MOC_RUN
82 #include <boost/range.hpp>
83 #endif
84 
85 #include <algorithm>
86 
87 using namespace Kleo;
88 using namespace Kleo::NewCertificateUi;
89 using namespace Kleo::Commands;
90 using namespace GpgME;
91 using namespace boost;
92 
93 static const char RSA_KEYSIZES_ENTRY[] = "RSAKeySizes";
94 static const char DSA_KEYSIZES_ENTRY[] = "DSAKeySizes";
95 static const char ELG_KEYSIZES_ENTRY[] = "ELGKeySizes";
96 
97 static const char RSA_KEYSIZE_LABELS_ENTRY[] = "RSAKeySizeLabels";
98 static const char DSA_KEYSIZE_LABELS_ENTRY[] = "DSAKeySizeLabels";
99 static const char ELG_KEYSIZE_LABELS_ENTRY[] = "ELGKeySizeLabels";
100 
101 static const char PGP_KEY_TYPE_ENTRY[] = "PGPKeyType";
102 static const char CMS_KEY_TYPE_ENTRY[] = "CMSKeyType";
103 
104 static void set_tab_order( const QList<QWidget*> & wl ) {
105  kdtools::for_each_adjacent_pair( wl, &QWidget::setTabOrder );
106 }
107 
108 enum KeyAlgo { RSA, DSA, ELG };
109 
110 static bool is_algo( gpgme_pubkey_algo_t algo, KeyAlgo what ) {
111  switch ( algo ) {
112  case GPGME_PK_RSA:
113  case GPGME_PK_RSA_E:
114  case GPGME_PK_RSA_S:
115  return what == RSA;
116  case GPGME_PK_ELG_E:
117  case GPGME_PK_ELG:
118  return what == ELG;
119  case GPGME_PK_DSA:
120  return what == DSA;
121  default:
122  break;
123  }
124  return false;
125 }
126 
127 static bool is_rsa( unsigned int algo ) {
128  return is_algo( static_cast<gpgme_pubkey_algo_t>( algo ), RSA );
129 }
130 
131 static bool is_dsa( unsigned int algo ) {
132  return is_algo( static_cast<gpgme_pubkey_algo_t>( algo ), DSA );
133 }
134 
135 static bool is_elg( unsigned int algo ) {
136  return is_algo( static_cast<gpgme_pubkey_algo_t>( algo ), ELG );
137 }
138 
139 static void force_set_checked( QAbstractButton * b, bool on ) {
140  // work around Qt bug (tested: 4.1.4, 4.2.3, 4.3.4)
141  const bool autoExclusive = b->autoExclusive();
142  b->setAutoExclusive( false );
143  b->setChecked( b->isEnabled() && on );
144  b->setAutoExclusive( autoExclusive );
145 }
146 
147 static void set_keysize( QComboBox * cb, unsigned int strength ) {
148  if ( !cb )
149  return;
150  const int idx = cb->findData( static_cast<int>( strength ) );
151  if ( idx < 0 )
152  kWarning() << "keysize " << strength << " not allowed";
153  cb->setCurrentIndex( idx );
154 }
155 
156 static unsigned int get_keysize( const QComboBox * cb ) {
157  if ( !cb )
158  return 0;
159  const int idx = cb->currentIndex();
160  if ( idx < 0 )
161  return 0;
162  return cb->itemData( idx ).toInt();
163 }
164 
165 namespace Kleo {
166 namespace NewCertificateUi {
167  class WizardPage : public QWizardPage {
168  Q_OBJECT
169  protected:
170  explicit WizardPage( QWidget * parent=0 )
171  : QWizardPage( parent ) {}
172 
173  NewCertificateWizard * wizard() const {
174  assert( static_cast<NewCertificateWizard*>( QWizardPage::wizard() ) == qobject_cast<NewCertificateWizard*>( QWizardPage::wizard() ) );
175  return static_cast<NewCertificateWizard*>( QWizardPage::wizard() );
176  }
177 
178  QAbstractButton * button( QWizard::WizardButton button ) const {
179  return QWizardPage::wizard() ? QWizardPage::wizard()->button( button ) : 0 ;
180  }
181 
182  bool isButtonVisible( QWizard::WizardButton button ) const {
183  if ( const QAbstractButton * const b = this->button( button ) )
184  return b->isVisible();
185  else
186  return false;
187  }
188 
189  QDir tmpDir() const;
190 
191  protected Q_SLOTS:
192  void setButtonVisible( QWizard::WizardButton button, bool visible ) {
193  if ( QAbstractButton * const b = this->button( button ) )
194  b->setVisible( visible );
195  }
196 
197  protected:
198 #define FIELD(type, name) type name() const { return field( QLatin1String(#name) ).value<type>(); }
199  FIELD( bool, pgp )
200  FIELD( bool, signingAllowed )
201  FIELD( bool, encryptionAllowed )
202  FIELD( bool, certificationAllowed )
203  FIELD( bool, authenticationAllowed )
204 
205  FIELD( QString, name )
206  FIELD( QString, email )
207  FIELD( QString, comment )
208  FIELD( QString, dn )
209 
210  FIELD( int, keyType )
211  FIELD( int, keyStrength )
212 
213  FIELD( int, subkeyType )
214  FIELD( int, subkeyStrength )
215 
216  FIELD( QDate, expiryDate )
217 
218  FIELD( QStringList, additionalUserIDs )
219  FIELD( QStringList, additionalEMailAddresses )
220  FIELD( QStringList, dnsNames )
221  FIELD( QStringList, uris )
222 
223  FIELD( QString, url )
224  FIELD( QString, error )
225  FIELD( QString, result )
226  FIELD( QString, fingerprint )
227 #undef FIELD
228  };
229 } // namespace NewCertificateUi
230 } // namespace Kleo
231 
232 using namespace Kleo::NewCertificateUi;
233 
234 namespace {
235 
236  class AdvancedSettingsDialog : public QDialog {
237  Q_OBJECT
238  Q_PROPERTY( QStringList additionalUserIDs READ additionalUserIDs WRITE setAdditionalUserIDs )
239  Q_PROPERTY( QStringList additionalEMailAddresses READ additionalEMailAddresses WRITE setAdditionalEMailAddresses )
240  Q_PROPERTY( QStringList dnsNames READ dnsNames WRITE setDnsNames )
241  Q_PROPERTY( QStringList uris READ uris WRITE setUris )
242  Q_PROPERTY( uint keyStrength READ keyStrength WRITE setKeyStrength )
243  Q_PROPERTY( uint keyType READ keyType WRITE setKeyType )
244  Q_PROPERTY( uint subkeyStrength READ subkeyStrength WRITE setSubkeyStrength )
245  Q_PROPERTY( uint subkeyType READ subkeyType WRITE setSubkeyType )
246  Q_PROPERTY( bool signingAllowed READ signingAllowed WRITE setSigningAllowed )
247  Q_PROPERTY( bool encryptionAllowed READ encryptionAllowed WRITE setEncryptionAllowed )
248  Q_PROPERTY( bool certificationAllowed READ certificationAllowed WRITE setCertificationAllowed )
249  Q_PROPERTY( bool authenticationAllowed READ authenticationAllowed WRITE setAuthenticationAllowed )
250  Q_PROPERTY( QDate expiryDate READ expiryDate WRITE setExpiryDate )
251  public:
252  explicit AdvancedSettingsDialog( QWidget * parent=0 )
253  : QDialog( parent ),
254  protocol( UnknownProtocol ),
255  pgpDefaultAlgorithm( GPGME_PK_ELG_E ),
256  cmsDefaultAlgorithm( GPGME_PK_RSA ),
257  keyTypeImmutable( false ),
258  ui()
259  {
260  ui.setupUi( this );
261  const QDate today = QDate::currentDate();
262  ui.expiryDE->setMinimumDate( today );
263  ui.expiryDE->setDate( today.addYears( 2 ) );
264  ui.emailLW->setDefaultValue( i18n("new email") );
265  ui.dnsLW->setDefaultValue( i18n("new dns name") );
266  ui.uriLW->setDefaultValue( i18n("new uri") );
267 
268  fillKeySizeComboBoxen();
269  }
270 
271  void setProtocol( GpgME::Protocol proto ) {
272  if ( protocol == proto )
273  return;
274  protocol = proto;
275  loadDefaultKeyType();
276  }
277 
278  void setAdditionalUserIDs( const QStringList & items ) { ui.uidLW->setItems( items ); }
279  QStringList additionalUserIDs() const { return ui.uidLW->items(); }
280 
281  void setAdditionalEMailAddresses( const QStringList & items ) { ui.emailLW->setItems( items ); }
282  QStringList additionalEMailAddresses() const { return ui.emailLW->items(); }
283 
284  void setDnsNames( const QStringList & items ) { ui.dnsLW->setItems( items ); }
285  QStringList dnsNames() const { return ui.dnsLW->items(); }
286 
287  void setUris( const QStringList & items ) { ui.uriLW->setItems( items ); }
288  QStringList uris() const { return ui.uriLW->items(); }
289 
290 
291  void setKeyStrength( unsigned int strength ) {
292  set_keysize( ui.rsaKeyStrengthCB, strength );
293  set_keysize( ui.dsaKeyStrengthCB, strength );
294  }
295  unsigned int keyStrength() const {
296  return
297  ui.dsaRB->isChecked() ? get_keysize( ui.dsaKeyStrengthCB ) :
298  ui.rsaRB->isChecked() ? get_keysize( ui.rsaKeyStrengthCB ) : 0 ;
299  }
300 
301  void setKeyType( unsigned int algo ) {
302  QRadioButton * const rb =
303  is_rsa( algo ) ? ui.rsaRB :
304  is_dsa( algo ) ? ui.dsaRB : 0 ;
305  if ( rb )
306  rb->setChecked( true );
307  }
308  unsigned int keyType() const {
309  return
310  ui.dsaRB->isChecked() ? GPGME_PK_DSA :
311  ui.rsaRB->isChecked() ? GPGME_PK_RSA :
312  0 ;
313  }
314 
315  void setSubkeyType( unsigned int algo ) {
316  ui.elgCB->setChecked( is_elg( algo ) );
317  ui.rsaSubCB->setChecked( is_rsa( algo ) );
318  }
319  unsigned int subkeyType() const {
320  if ( ui.elgCB->isChecked() ) {
321  return GPGME_PK_ELG_E;
322  } else if ( ui.rsaSubCB->isChecked() ) {
323  return GPGME_PK_RSA;
324  }
325  return 0;
326  }
327 
328  void setSubkeyStrength( unsigned int strength ) {
329  if ( subkeyType() == GPGME_PK_RSA ) {
330  set_keysize( ui.rsaKeyStrengthSubCB, strength );
331  } else {
332  set_keysize( ui.elgKeyStrengthCB, strength );
333  }
334  }
335  unsigned int subkeyStrength() const {
336  if ( subkeyType() == GPGME_PK_RSA ) {
337  return get_keysize( ui.rsaKeyStrengthSubCB );
338  }
339  return get_keysize( ui.elgKeyStrengthCB );
340  }
341 
342  void setSigningAllowed( bool on ) { ui.signingCB->setChecked( on ); }
343  bool signingAllowed() const { return ui.signingCB->isChecked(); }
344 
345  void setEncryptionAllowed( bool on ) { ui.encryptionCB->setChecked( on ); }
346  bool encryptionAllowed() const { return ui.encryptionCB->isChecked(); }
347 
348  void setCertificationAllowed( bool on ) { ui.certificationCB->setChecked( on ); }
349  bool certificationAllowed() const { return ui.certificationCB->isChecked(); }
350 
351  void setAuthenticationAllowed( bool on ) { ui.authenticationCB->setChecked( on ); }
352  bool authenticationAllowed() const { return ui.authenticationCB->isChecked(); }
353 
354  void setExpiryDate( const QDate & date ) { if ( date.isValid() ) ui.expiryDE->setDate( date ); else ui.expiryCB->setChecked( false ); }
355  QDate expiryDate() const { return ui.expiryCB->isChecked() ? ui.expiryDE->date() : QDate() ; }
356 
357  Q_SIGNALS:
358  void changed();
359 
360  private Q_SLOTS:
361  void slotKeyMaterialSelectionChanged() {
362  const unsigned int algo = keyType();
363  const unsigned int sk_algo = subkeyType();
364  if ( protocol == OpenPGP ) {
365  if ( !keyTypeImmutable ) {
366  ui.elgCB->setEnabled( is_dsa( algo ) );
367  if ( sender() == ui.dsaRB || sender() == ui.rsaRB )
368  ui.elgCB->setChecked( is_dsa( algo ) );
369  }
370  if ( is_rsa( algo ) ) {
371  ui.encryptionCB->setEnabled( true );
372  ui.encryptionCB->setChecked( true );
373  ui.signingCB->setEnabled( true );
374  ui.signingCB->setChecked( true );
375  ui.authenticationCB->setEnabled( true );
376  if ( is_rsa( sk_algo ) ) {
377  ui.encryptionCB->setEnabled( false );
378  ui.encryptionCB->setChecked( true );
379  } else {
380  ui.encryptionCB->setEnabled( true );
381  }
382  } else if ( is_dsa( algo ) ) {
383  ui.encryptionCB->setEnabled( false );
384  if ( is_elg( sk_algo ) )
385  ui.encryptionCB->setChecked( true );
386  else
387  ui.encryptionCB->setChecked( false );
388  }
389  } else {
390  //assert( is_rsa( keyType() ) ); // it can happen through misconfiguration by the admin that no key type is selectable at all
391  }
392  }
393 
394  void slotSigningAllowedToggled( bool on ) {
395  if ( !on && protocol == CMS && !encryptionAllowed() )
396  setEncryptionAllowed( true );
397  }
398  void slotEncryptionAllowedToggled( bool on ) {
399  if ( !on && protocol == CMS && !signingAllowed() )
400  setSigningAllowed( true );
401  }
402 
403  private:
404  void fillKeySizeComboBoxen();
405  void loadDefaultKeyType();
406  void updateWidgetVisibility();
407 
408  private:
409  GpgME::Protocol protocol;
410  unsigned int pgpDefaultAlgorithm;
411  unsigned int cmsDefaultAlgorithm;
412  bool keyTypeImmutable;
413  Ui_AdvancedSettingsDialog ui;
414  };
415 
416  class ChooseProtocolPage : public WizardPage {
417  Q_OBJECT
418  public:
419  explicit ChooseProtocolPage( QWidget * p=0 )
420  : WizardPage( p ),
421  initialized( false ),
422  ui()
423  {
424  ui.setupUi( this );
425  registerField( QLatin1String("pgp"), ui.pgpCLB );
426  }
427 
428  void setProtocol( Protocol proto ) {
429  if ( proto == OpenPGP )
430  ui.pgpCLB->setChecked( true );
431  else if ( proto == CMS )
432  ui.x509CLB->setChecked( true );
433  else {
434  force_set_checked( ui.pgpCLB, false );
435  force_set_checked( ui.x509CLB, false );
436  }
437  }
438 
439  Protocol protocol() const {
440  return
441  ui.pgpCLB->isChecked() ? OpenPGP :
442  ui.x509CLB->isChecked() ? CMS : UnknownProtocol ;
443  }
444 
445  /* reimp */ void initializePage() {
446  if ( !initialized ) {
447  connect( ui.pgpCLB, SIGNAL(clicked()), wizard(), SLOT(next()), Qt::QueuedConnection );
448  connect( ui.x509CLB, SIGNAL(clicked()), wizard(), SLOT(next()), Qt::QueuedConnection );
449  }
450  initialized = true;
451  }
452 
453  /* reimp */ bool isComplete() const {
454  return protocol() != UnknownProtocol ;
455  }
456 
457  private:
458  bool initialized : 1;
459  Ui_ChooseProtocolPage ui;
460  };
461 
462  struct Line {
463  QString attr;
464  QString label;
465  QString regex;
466  QLineEdit * edit;
467  };
468 
469  class EnterDetailsPage : public WizardPage {
470  Q_OBJECT
471  public:
472  explicit EnterDetailsPage( QWidget * p=0 )
473  : WizardPage( p ), dialog( this ), ui()
474  {
475  ui.setupUi( this );
476 
477  // set errorLB to have a fixed height of two lines:
478  ui.errorLB->setText( QLatin1String("2<br>1") );
479  ui.errorLB->setFixedHeight( ui.errorLB->minimumSizeHint().height() );
480  ui.errorLB->clear();
481 
482  connect( ui.resultLE, SIGNAL(textChanged(QString)),
483  SIGNAL(completeChanged()) );
484  // The email doesn't necessarily show up in ui.resultLE:
485  connect( ui.emailLE, SIGNAL(textChanged(QString)),
486  SIGNAL(completeChanged()) );
487  connect( ui.addEmailToDnCB, SIGNAL(toggled(bool)),
488  SLOT(slotUpdateResultLabel()) );
489  registerDialogPropertiesAsFields();
490  registerField( QLatin1String("dn"), ui.resultLE );
491  registerField( QLatin1String("name"), ui.nameLE );
492  registerField( QLatin1String("email"), ui.emailLE );
493  registerField( QLatin1String("comment"), ui.commentLE );
494  updateForm();
495  }
496 
497  /* reimp */ bool isComplete() const;
498  /* reimp */ void initializePage() {
499  updateForm();
500  dialog.setProtocol( pgp() ? OpenPGP : CMS );
501  }
502  /* reimp */ void cleanupPage() {
503  saveValues();
504  }
505 
506  private:
507  void updateForm();
508  void clearForm();
509  void saveValues();
510  void registerDialogPropertiesAsFields();
511 
512  private:
513  QString pgpUserID() const;
514  QString cmsDN() const;
515 
516  private Q_SLOTS:
517  void slotAdvancedSettingsClicked();
518  void slotUpdateResultLabel() {
519  ui.resultLE->setText( pgp() ? pgpUserID() : cmsDN() );
520  }
521 
522  private:
523  QVector<Line> lineList;
524  QList<QWidget*> dynamicWidgets;
525  QMap<QString,QString> savedValues;
526  AdvancedSettingsDialog dialog;
527  Ui_EnterDetailsPage ui;
528  };
529 
530  class OverviewPage : public WizardPage {
531  Q_OBJECT
532  public:
533  explicit OverviewPage( QWidget * p=0 )
534  : WizardPage( p ), ui()
535  {
536  ui.setupUi( this );
537  setCommitPage( true );
538  setButtonText( QWizard::CommitButton, i18nc("@action", "Create Key") );
539  }
540 
541  /* reimp */ void initializePage() {
542  slotShowDetails();
543  }
544 
545  private Q_SLOTS:
546  void slotShowDetails() {
547  ui.textBrowser->setHtml( i18nFormatGnupgKeyParms( ui.showAllDetailsCB->isChecked() ) );
548  }
549 
550  private:
551  QStringList i18nKeyUsages() const;
552  QStringList i18nSubkeyUsages() const;
553  QStringList i18nCombinedKeyUsages() const;
554  QString i18nFormatGnupgKeyParms( bool details ) const;
555 
556  private:
557  Ui_OverviewPage ui;
558  };
559 
560  class KeyCreationPage : public WizardPage {
561  Q_OBJECT
562  public:
563  explicit KeyCreationPage( QWidget * p=0 )
564  : WizardPage( p ),
565  ui()
566  {
567  ui.setupUi( this );
568  }
569 
570  /* reimp */ bool isComplete() const {
571  return !job;
572  }
573 
574  /* reimp */ void initializePage() {
575  startJob();
576  }
577 
578  private:
579  void startJob() {
580  const CryptoBackend::Protocol * const proto = CryptoBackendFactory::instance()->protocol( pgp() ? OpenPGP : CMS );
581  if ( !proto )
582  return;
583  KeyGenerationJob * const j = proto->keyGenerationJob();
584  if ( !j )
585  return;
586  connect( j, SIGNAL(result(GpgME::KeyGenerationResult,QByteArray,QString)),
587  this, SLOT(slotResult(GpgME::KeyGenerationResult,QByteArray,QString)) );
588  if ( const Error err = j->start( createGnupgKeyParms() ) )
589  setField( QLatin1String("error"), i18n("Could not start certificate creation: %1",
590  QString::fromLocal8Bit( err.asString() ) ) );
591  else
592  job = j;
593  }
594  QStringList keyUsages() const;
595  QStringList subkeyUsages() const;
596  QString createGnupgKeyParms() const;
597 
598  private Q_SLOTS:
599  void slotResult( const GpgME::KeyGenerationResult & result, const QByteArray & request, const QString & auditLog )
600  {
601  Q_UNUSED( auditLog );
602  if ( result.error().code() ) {
603  setField( QLatin1String("error"), result.error().isCanceled()
604  ? i18n("Operation canceled.")
605  : i18n("Could not create certificate: %1",
606  QString::fromLocal8Bit( result.error().asString() ) ) );
607  setField( QLatin1String("url"), QString() );
608  setField( QLatin1String("result"), QString() );
609  } else if ( pgp() ) {
610  setField( QLatin1String("error"), QString() );
611  setField( QLatin1String("url"), QString() );
612  setField( QLatin1String("result"), i18n("Certificate created successfully.\n"
613  "Fingerprint: %1", QLatin1String(result.fingerprint()) ) );
614  } else {
615  QFile file( tmpDir().absoluteFilePath( QLatin1String("request.p10") ) );
616 
617  if ( !file.open( QIODevice::WriteOnly ) ) {
618  setField( QLatin1String("error"), i18n("Could not write output file %1: %2",
619  file.fileName(), file.errorString() ) );
620  setField( QLatin1String("url"), QString() );
621  setField( QLatin1String("result"), QString() );
622  } else {
623  file.write( request );
624  setField( QLatin1String("error"), QString() );
625  setField( QLatin1String("url"), QUrl::fromLocalFile( file.fileName() ).toString() );
626  setField( QLatin1String("result"), i18n("Certificate created successfully.") );
627  }
628  }
629  setField( QLatin1String("fingerprint"), QString::fromLatin1( result.fingerprint() ) );
630  job = 0;
631  emit completeChanged();
632  QMetaObject::invokeMethod( wizard(), "next", Qt::QueuedConnection );
633  }
634 
635  private:
636  QPointer<KeyGenerationJob> job;
637  Ui_KeyCreationPage ui;
638  };
639 
640  class ResultPage : public WizardPage {
641  Q_OBJECT
642  public:
643  explicit ResultPage( QWidget * p=0 )
644  : WizardPage( p ),
645  initialized( false ),
646  successfullyCreatedSigningCertificate( false ),
647  successfullyCreatedEncryptionCertificate( false ),
648  ui()
649  {
650  ui.setupUi( this );
651  ui.dragQueen->setPixmap( KIcon( QLatin1String("kleopatra") ).pixmap( 64, 64 ) );
652  registerField( QLatin1String("error"), ui.errorTB, "plainText" );
653  registerField( QLatin1String("result"), ui.resultTB, "plainText" );
654  registerField( QLatin1String("url"), ui.dragQueen, "url" );
655  // hidden field, since QWizard can't deal with non-widget-backed fields...
656  QLineEdit * le = new QLineEdit( this );
657  le->hide();
658  registerField( QLatin1String("fingerprint"), le );
659  }
660 
661  /* reimp */ void initializePage() {
662  const bool error = isError();
663 
664  if ( error ) {
665  setTitle( i18nc("@title","Key Creation Failed") );
666  setSubTitle( i18n("Key pair creation failed. Please find details about the failure below.") );
667  } else {
668  setTitle( i18nc("@title","Key Pair Successfully Created") );
669  setSubTitle( i18n("Your new key pair was created successfully. Please find details on the result and some suggested next steps below.") );
670  }
671 
672  ui.resultTB ->setVisible( !error );
673  ui.errorTB ->setVisible( error );
674  ui.dragQueen ->setVisible( !error && !pgp() );
675  ui.restartWizardPB ->setVisible( error );
676  ui.nextStepsGB ->setVisible( !error );
677  ui.saveRequestToFilePB ->setVisible( !pgp() );
678  ui.makeBackupPB ->setVisible( pgp() );
679  ui.createRevocationRequestPB->setVisible( pgp() && false ); // not implemented
680 
681 #ifdef KDEPIM_MOBILE_UI
682  ui.sendCertificateByEMailPB ->setVisible( false );
683  ui.sendRequestByEMailPB ->setVisible( false );
684  ui.uploadToKeyserverPB ->setVisible( false );
685 #else
686  ui.sendCertificateByEMailPB ->setVisible( pgp() );
687  ui.sendRequestByEMailPB ->setVisible( !pgp() );
688  ui.uploadToKeyserverPB ->setVisible( pgp() );
689 #endif
690 
691  if ( !error && !pgp() ) {
692  if ( signingAllowed() && !encryptionAllowed() )
693  successfullyCreatedSigningCertificate = true;
694  else if ( !signingAllowed() && encryptionAllowed() )
695  successfullyCreatedEncryptionCertificate = true;
696  else
697  successfullyCreatedEncryptionCertificate = successfullyCreatedSigningCertificate = true;
698  }
699 
700  ui.createSigningCertificatePB->setVisible( successfullyCreatedEncryptionCertificate && !successfullyCreatedSigningCertificate );
701  ui.createEncryptionCertificatePB->setVisible( successfullyCreatedSigningCertificate && !successfullyCreatedEncryptionCertificate );
702 
703  setButtonVisible( QWizard::CancelButton, error );
704 
705  if ( !initialized )
706  connect( ui.restartWizardPB, SIGNAL(clicked()),
707  wizard(), SLOT(restart()) );
708  initialized = true;
709  }
710 
711  /* reimp */ void cleanupPage() {
712  setButtonVisible( QWizard::CancelButton, true );
713  }
714 
715  bool isError() const {
716  return !ui.errorTB->toPlainText().isEmpty();
717  }
718 
719  /* reimp */ bool isComplete() const {
720  return !isError();
721  }
722 
723  private:
724  Key key() const {
725  return KeyCache::instance()->findByFingerprint( fingerprint().toLatin1().constData() );
726  }
727 
728  private Q_SLOTS:
729  void slotSaveRequestToFile() {
730  QString fileName = FileDialog::getSaveFileName( this, i18nc("@title", "Save Request"),
731  QLatin1String("imp"), i18n("PKCS#10 Requests (*.p10)") );
732  if ( fileName.isEmpty() )
733  return;
734  if ( !fileName.endsWith( QLatin1String( ".p10" ), Qt::CaseInsensitive ) )
735  fileName += QLatin1String(".p10");
736  QFile src( QUrl( url() ).toLocalFile() );
737  if ( !src.copy( fileName ) )
738  KMessageBox::error( this,
739  i18nc("@info",
740  "Could not copy temporary file <filename>%1</filename> "
741  "to file <filename>%2</filename>: <message>%3</message>",
742  src.fileName(), fileName, src.errorString() ),
743  i18nc("@title", "Error Saving Request") );
744  else
745  KMessageBox::information( this,
746  i18nc("@info",
747  "<para>Successfully wrote request to <filename>%1</filename>.</para>"
748  "<para>You should now send the request to the Certification Authority (CA).</para>",
749  fileName ),
750  i18nc("@title", "Request Saved" ) );
751  }
752 
753  void slotSendRequestByEMail() {
754  if ( pgp() )
755  return;
756  const KConfigGroup config( KGlobal::config(), "CertificateCreationWizard" );
757  invokeMailer( config.readEntry( "CAEmailAddress" ), // to
758  i18n("Please process this certificate."), // subject
759  i18n("Please process this certificate and inform the sender about the location to fetch the resulting certificate.\n\nThanks,\n"), // body
760  QUrl( url() ).toLocalFile() ); // attachment
761  }
762 
763  void slotSendCertificateByEMail() {
764  if ( !pgp() || exportCertificateCommand )
765  return;
766  ExportCertificateCommand * cmd = new ExportCertificateCommand( key() );
767  connect( cmd, SIGNAL(finished()), SLOT(slotSendCertificateByEMailContinuation()) );
768  cmd->setOpenPGPFileName( tmpDir().absoluteFilePath( fingerprint() + QLatin1String(".asc") ) );
769  cmd->start();
770  exportCertificateCommand = cmd;
771  }
772 
773  void slotSendCertificateByEMailContinuation() {
774  if ( !exportCertificateCommand )
775  return;
776  // ### better error handling?
777  const QString fileName = exportCertificateCommand->openPGPFileName();
778  kDebug() << "fileName" << fileName;
779  exportCertificateCommand = 0;
780  if ( fileName.isEmpty() )
781  return;
782  invokeMailer( QString(), // to
783  i18n("My new OpenPGP certificate"), // subject
784  i18n("Please find attached my new OpenPGP certificate."), // body
785  fileName );
786  }
787 
788  QByteArray ol_quote( QByteArray str ) {
789 #ifdef Q_OS_WIN
790  return "\"\"" + str.replace( '"', "\\\"" ) + "\"\"";
791  //return '"' + str.replace( '"', "\\\"" ) + '"';
792 #else
793  return str;
794 #endif
795  }
796 
797  void invokeMailer( const QString & to, const QString & subject, QString body, const QString & attachment ) {
798  kDebug() << "to:" << to << "subject:" << subject
799  << "body:" << body << "attachment:" << attachment;
800  // KToolInvocation::invokeMailer is broken on Windows, and openUrl works fine on Unix, too.
801 
802  // RFC 2368 says body's linebreaks need to be encoded as
803  // "%0D%0A", so normalize body to CRLF:
804  body.replace( QLatin1Char( '\n' ), QLatin1String( "\r\n" ) ).remove( QLatin1String( "\r\r" ) );
805 
806  QByteArray encoded = "mailto:?to=" + QUrl::toPercentEncoding( to )
807  + "&subject=" + QUrl::toPercentEncoding( subject )
808  + "&body=" + QUrl::toPercentEncoding( body ) ;
809  if ( !attachment.isEmpty() )
810  encoded += "&attach=" + ol_quote( QUrl::toPercentEncoding( QFileInfo( attachment ).absoluteFilePath() ) );
811  kDebug() << "openUrl" << QUrl::fromEncoded( encoded );
812  QDesktopServices::openUrl( QUrl::fromEncoded( encoded ) );
813  KMessageBox::information( this,
814  i18nc("@info",
815  "<para><application>Kleopatra</application> tried to send a mail via your default mail client.</para>"
816  "<para>Some mail clients are known not to support attachments when invoked this way.</para>"
817  "<para>If your mail client does not have an attachment, then drag the <application>Kleopatra</application> icon and drop it on the message compose window of your mail client.</para>"
818  "<para>If that does not work, either, save the request to a file, and then attach that.</para>"),
819  i18nc("@title", "Sending Mail"),
820  QLatin1String("newcertificatewizard-mailto-troubles") );
821  }
822 
823  void slotUploadCertificateToDirectoryServer() {
824  if ( pgp() )
825  ( new ExportOpenPGPCertsToServerCommand( key() ) )->start();
826  }
827 
828  void slotBackupCertificate() {
829  if ( pgp() )
830  ( new ExportSecretKeyCommand( key() ) )->start();
831  }
832 
833  void slotCreateRevocationRequest() {
834 
835  }
836 
837  void slotCreateSigningCertificate() {
838  if ( successfullyCreatedSigningCertificate )
839  return;
840  toggleSignEncryptAndRestart();
841  }
842 
843  void slotCreateEncryptionCertificate() {
844  if ( successfullyCreatedEncryptionCertificate )
845  return;
846  toggleSignEncryptAndRestart();
847  }
848 
849  private:
850  void toggleSignEncryptAndRestart() {
851  if ( !wizard() )
852  return;
853  if ( KMessageBox::warningContinueCancel(
854  this,
855  i18nc("@info",
856  "This operation will delete the certification request. "
857  "Please make sure that you have sent or saved it before proceeding." ),
858  i18nc("@title", "Certification Request About To Be Deleted") ) != KMessageBox::Continue )
859  return;
860  const bool sign = signingAllowed();
861  const bool encr = encryptionAllowed();
862  setField( QLatin1String("signingAllowed"), !sign );
863  setField( QLatin1String("encryptionAllowed"), !encr );
864  // restart and skip to Overview Page:
865  wizard()->restart();
866  for ( int i = wizard()->currentId() ; i < NewCertificateWizard::OverviewPageId ; ++i )
867  wizard()->next();
868  }
869 
870  private:
871  bool initialized : 1;
872  bool successfullyCreatedSigningCertificate : 1;
873  bool successfullyCreatedEncryptionCertificate : 1;
874  QPointer<ExportCertificateCommand> exportCertificateCommand;
875  Ui_ResultPage ui;
876  };
877 }
878 
879 class NewCertificateWizard::Private {
880  friend class ::Kleo::NewCertificateWizard;
881  friend class ::Kleo::NewCertificateUi::WizardPage;
882  NewCertificateWizard * const q;
883 public:
884  explicit Private( NewCertificateWizard * qq )
885  : q( qq ),
886  tmp( QDir::temp().absoluteFilePath( QLatin1String("kleo-") ) ),
887  ui( q )
888  {
889  q->setWindowTitle( i18nc("@title", "Certificate Creation Wizard") );
890  }
891 
892 private:
893  KTempDir tmp;
894  struct Ui {
895  ChooseProtocolPage chooseProtocolPage;
896  EnterDetailsPage enterDetailsPage;
897  OverviewPage overviewPage;
898  KeyCreationPage keyCreationPage;
899  ResultPage resultPage;
900 
901  explicit Ui( NewCertificateWizard * q )
902  : chooseProtocolPage( q ),
903  enterDetailsPage( q ),
904  overviewPage( q ),
905  keyCreationPage( q ),
906  resultPage( q )
907  {
908  KDAB_SET_OBJECT_NAME( chooseProtocolPage );
909  KDAB_SET_OBJECT_NAME( enterDetailsPage );
910  KDAB_SET_OBJECT_NAME( overviewPage );
911  KDAB_SET_OBJECT_NAME( keyCreationPage );
912  KDAB_SET_OBJECT_NAME( resultPage );
913 
914  q->setOptions( DisabledBackButtonOnLastPage );
915 
916  q->setPage( ChooseProtocolPageId, &chooseProtocolPage );
917  q->setPage( EnterDetailsPageId, &enterDetailsPage );
918  q->setPage( OverviewPageId, &overviewPage );
919  q->setPage( KeyCreationPageId, &keyCreationPage );
920  q->setPage( ResultPageId, &resultPage );
921 
922  q->setStartId( ChooseProtocolPageId );
923  }
924 
925  } ui;
926 
927 };
928 
929 NewCertificateWizard::NewCertificateWizard( QWidget * p )
930  : QWizard( p ), d( new Private( this ) )
931 {
932 
933 }
934 
935 NewCertificateWizard::~NewCertificateWizard() {}
936 
937 void NewCertificateWizard::setProtocol( Protocol proto ) {
938  d->ui.chooseProtocolPage.setProtocol( proto );
939  setStartId( proto == UnknownProtocol ? ChooseProtocolPageId : EnterDetailsPageId );
940 }
941 
942 Protocol NewCertificateWizard::protocol() const {
943  return d->ui.chooseProtocolPage.protocol();
944 }
945 
946 static QString pgpLabel( const QString & attr ) {
947  if ( attr == QLatin1String("NAME") )
948  return i18n("Name");
949  if ( attr == QLatin1String("COMMENT") )
950  return i18n("Comment");
951  if ( attr == QLatin1String("EMAIL") )
952  return i18n("EMail");
953  return QString();
954 }
955 
956 static QString attributeLabel( const QString & attr, bool pgp ) {
957  if ( attr.isEmpty() )
958  return QString();
959  const QString label = pgp ? pgpLabel( attr ) : Kleo::DNAttributeMapper::instance()->name2label( attr ) ;
960  if ( !label.isEmpty() )
961  if ( pgp )
962  return label;
963  else
964  return i18nc("Format string for the labels in the \"Your Personal Data\" page",
965  "%1 (%2)", label, attr );
966  else
967  return attr;
968 }
969 
970 #if 0
971 //Not used anywhere
972 static QString attributeLabelWithColor( const QString & attr, bool pgp ) {
973  const QString result = attributeLabel( attr, pgp );
974  if ( result.isEmpty() )
975  return QString();
976  else
977  return result + ':';
978 }
979 #endif
980 
981 static QString attributeFromKey( QString key ) {
982  return key.remove( QLatin1Char('!') );
983 }
984 
985 static const char * oidForAttributeName( const QString & attr ) {
986  QByteArray attrUtf8 = attr.toUtf8();
987  for ( unsigned int i = 0 ; i < numOidMaps ; ++i )
988  if ( qstricmp( attrUtf8, oidmap[i].name ) == 0 )
989  return oidmap[i].oid;
990  return 0;
991 }
992 
993 QDir WizardPage::tmpDir() const {
994  return wizard() ? QDir( wizard()->d->tmp.name() ) : QDir::home() ;
995 }
996 
997 void EnterDetailsPage::registerDialogPropertiesAsFields() {
998 
999  const QMetaObject * const mo = dialog.metaObject();
1000  for ( unsigned int i = mo->propertyOffset(), end = i + mo->propertyCount() ; i != end ; ++i ) {
1001  const QMetaProperty mp = mo->property( i );
1002  if ( mp.isValid() )
1003  registerField( QLatin1String(mp.name()), &dialog, mp.name(), SIGNAL(accepted()) );
1004  }
1005 
1006 }
1007 
1008 void EnterDetailsPage::saveValues() {
1009  Q_FOREACH( const Line & line, lineList )
1010  savedValues[ attributeFromKey( line.attr ) ] = line.edit->text().trimmed();
1011 }
1012 
1013 void EnterDetailsPage::clearForm() {
1014  qDeleteAll( dynamicWidgets );
1015  dynamicWidgets.clear();
1016  lineList.clear();
1017 
1018  ui.nameLE->hide();
1019  ui.nameLE->clear();
1020  ui.nameLB->hide();
1021  ui.nameRequiredLB->hide();
1022 
1023  ui.emailLE->hide();
1024  ui.emailLE->clear();
1025  ui.emailLB->hide();
1026  ui.emailRequiredLB->hide();
1027 
1028  ui.commentLE->hide();
1029  ui.commentLE->clear();
1030  ui.commentLB->hide();
1031  ui.commentRequiredLB->hide();
1032 
1033  ui.addEmailToDnCB->hide();
1034 }
1035 
1036 static int row_index_of( QWidget * w, QGridLayout * l ) {
1037  const int idx = l->indexOf( w );
1038  int r, c, rs, cs;
1039  l->getItemPosition( idx, &r, &c, &rs, &cs );
1040  return r;
1041 }
1042 
1043 static QLineEdit * adjust_row( QGridLayout * l, int row, const QString & label, const QString & preset, QValidator * validator, bool readonly, bool required ) {
1044  assert( l );
1045  assert( row >= 0 );
1046  assert( row < l->rowCount() );
1047 
1048  QLabel * lb = qobject_cast<QLabel*>( l->itemAtPosition( row, 0 )->widget() );
1049  assert( lb );
1050  QLineEdit * le = qobject_cast<QLineEdit*>( l->itemAtPosition( row, 1 )->widget() );
1051  assert( le );
1052  lb->setBuddy( le ); // For better accessibility
1053  QLabel * reqLB = qobject_cast<QLabel*>( l->itemAtPosition( row, 2 )->widget() );
1054  assert( reqLB );
1055 
1056  lb->setText( i18nc("interpunctation for labels", "%1:", label ) );
1057  le->setText( preset );
1058  reqLB->setText( required ? i18n("(required)") : i18n("(optional)") );
1059  delete le->validator();
1060  if ( validator ) {
1061  if ( !validator->parent() )
1062  validator->setParent( le );
1063  le->setValidator( validator );
1064  }
1065 
1066  le->setReadOnly( readonly && le->hasAcceptableInput() );
1067 
1068  lb->show();
1069  le->show();
1070  reqLB->show();
1071 
1072  return le;
1073 }
1074 
1075 static int add_row( QGridLayout * l, QList<QWidget*> * wl ) {
1076  assert( l );
1077  assert( wl );
1078  const int row = l->rowCount();
1079  QWidget *w1, *w2, *w3;
1080  l->addWidget( w1 = new QLabel( l->parentWidget() ), row, 0 );
1081  l->addWidget( w2 = new QLineEdit( l->parentWidget() ), row, 1 );
1082  l->addWidget( w3 = new QLabel( l->parentWidget() ), row, 2 );
1083  wl->push_back( w1 );
1084  wl->push_back( w2 );
1085  wl->push_back( w3 );
1086  return row;
1087 }
1088 
1089 void EnterDetailsPage::updateForm() {
1090 
1091  clearForm();
1092 
1093  const KConfigGroup config( KGlobal::config(), "CertificateCreationWizard" );
1094 
1095  QStringList attrOrder = config.readEntry( pgp() ? "OpenPGPAttributeOrder" : "DNAttributeOrder", QStringList() );
1096  if ( attrOrder.empty() ) {
1097  if ( pgp() )
1098  attrOrder << QLatin1String("NAME!") << QLatin1String("EMAIL!") << QLatin1String("COMMENT");
1099  else
1100  attrOrder << QLatin1String("CN!") << QLatin1String("L") << QLatin1String("OU") << QLatin1String("O!") << QLatin1String("C!") << QLatin1String("EMAIL!");
1101  }
1102 
1103  QList<QWidget*> widgets;
1104  widgets.push_back( ui.nameLE );
1105  widgets.push_back( ui.emailLE );
1106  widgets.push_back( ui.commentLE );
1107 
1108  QMap<int,Line> lines;
1109 
1110  Q_FOREACH( const QString & rawKey, attrOrder ) {
1111  const QString key = rawKey.trimmed().toUpper();
1112  const QString attr = attributeFromKey( key );
1113  if ( attr.isEmpty() )
1114  continue;
1115  const QString preset = savedValues.value( attr, config.readEntry( attr, QString() ) );
1116  const bool required = key.endsWith( QLatin1Char('!') );
1117  const bool readonly = config.isEntryImmutable( attr );
1118  const QString label = config.readEntry( attr + QLatin1String("_label"),
1119  attributeLabel( attr, pgp() ) );
1120  const QString regex = config.readEntry( attr + QLatin1String("_regex") );
1121 
1122  int row;
1123  bool known = true;
1124  QValidator * validator = 0;
1125  if ( attr == QLatin1String("EMAIL") ) {
1126  row = row_index_of( ui.emailLE, ui.gridLayout );
1127  validator = regex.isEmpty() ? Validation::email() : Validation::email( QRegExp( regex ) ) ;
1128  if ( !pgp() )
1129  ui.addEmailToDnCB->show();
1130  } else if ( attr == QLatin1String("NAME") || attr == QLatin1String("CN") ) {
1131  if ( ( pgp() && attr == QLatin1String("CN") ) || ( !pgp() && attr == QLatin1String("NAME") ) )
1132  continue;
1133  if ( pgp() )
1134  validator = regex.isEmpty() ? Validation::pgpName() : Validation::pgpName( QRegExp( regex ) ) ;
1135  row = row_index_of( ui.nameLE, ui.gridLayout );
1136  } else if ( attr == QLatin1String("COMMENT") ) {
1137  if ( !pgp() )
1138  continue;
1139  validator = regex.isEmpty() ? Validation::pgpComment() : Validation::pgpComment( QRegExp( regex ) ) ;
1140  row = row_index_of( ui.commentLE, ui.gridLayout );
1141  } else {
1142  known = false;
1143  row = add_row( ui.gridLayout, &dynamicWidgets );
1144  }
1145  if ( !validator && !regex.isEmpty() )
1146  validator = new QRegExpValidator( QRegExp( regex ), 0 );
1147 
1148  QLineEdit * le = adjust_row( ui.gridLayout, row, label, preset, validator, readonly, required );
1149 
1150  const Line line = { key, label, regex, le };
1151  lines[row] = line;
1152 
1153  if ( !known )
1154  widgets.push_back( le );
1155 
1156  // don't connect twice:
1157  disconnect( le, SIGNAL(textChanged(QString)),
1158  this, SLOT(slotUpdateResultLabel()) );
1159  connect( le, SIGNAL(textChanged(QString)),
1160  this, SLOT(slotUpdateResultLabel()) );
1161  }
1162 
1163  // create lineList in visual order, so requirementsAreMet()
1164  // complains from top to bottom:
1165  lineList = kdtools::copy< QVector<Line> >( lines );
1166 
1167  widgets.push_back( ui.resultLE );
1168  widgets.push_back( ui.addEmailToDnCB );
1169  widgets.push_back( ui.advancedPB );
1170 
1171  set_tab_order( widgets );
1172 }
1173 
1174 QString EnterDetailsPage::cmsDN() const {
1175  DN dn;
1176  for ( QVector<Line>::const_iterator it = lineList.begin(), end = lineList.end() ; it != end ; ++it ) {
1177  const QString text = it->edit->text().trimmed();
1178  if ( text.isEmpty() )
1179  continue;
1180  QString attr = attributeFromKey( it->attr );
1181  if ( attr == QLatin1String("EMAIL") && !ui.addEmailToDnCB->isChecked() )
1182  continue;
1183  if ( const char * const oid = oidForAttributeName( attr ) )
1184  attr = QString::fromUtf8( oid );
1185  dn.append( DN::Attribute( attr, text ) );
1186  }
1187  return dn.dn();
1188 }
1189 
1190 QString EnterDetailsPage::pgpUserID() const {
1191  return Formatting::prettyNameAndEMail( OpenPGP, QString(),
1192  ui.nameLE->text().trimmed(),
1193  ui.emailLE->text().trimmed(),
1194  ui.commentLE->text().trimmed() );
1195 }
1196 
1197 static bool has_intermediate_input( const QLineEdit * le ) {
1198  QString text = le->text();
1199  int pos = le->cursorPosition();
1200  const QValidator * const v = le->validator();
1201  return v && v->validate( text, pos ) == QValidator::Intermediate ;
1202 }
1203 
1204 static bool requirementsAreMet( const QVector<Line> & list, QString & error ) {
1205  Q_FOREACH( const Line & line, list ) {
1206  const QLineEdit * le = line.edit;
1207  if ( !le )
1208  continue;
1209  const QString key = line.attr;
1210  kDebug() << "requirementsAreMet(): checking \"" << key << "\" against \"" << le->text() << "\":";
1211  if ( le->text().trimmed().isEmpty() ) {
1212  if ( key.endsWith(QLatin1Char('!')) ) {
1213  if ( line.regex.isEmpty() )
1214  error = i18nc("@info","<interface>%1</interface> is required, but empty.", line.label );
1215  else
1216  error = i18nc("@info","<interface>%1</interface> is required, but empty.<nl/>"
1217  "Local Admin rule: <icode>%2</icode>", line.label, line.regex );
1218  return false;
1219  }
1220  } else if ( has_intermediate_input( le ) ) {
1221  if ( line.regex.isEmpty() )
1222  error = i18nc("@info","<interface>%1</interface> is incomplete.", line.label );
1223  else
1224  error = i18nc("@info","<interface>%1</interface> is incomplete.<nl/>"
1225  "Local Admin rule: <icode>%2</icode>", line.label, line.regex );
1226  return false;
1227  } else if ( !le->hasAcceptableInput() ) {
1228  if ( line.regex.isEmpty() )
1229  error = i18nc("@info","<interface>%1</interface> is invalid.", line.label );
1230  else
1231  error = i18nc("@info","<interface>%1</interface> is invalid.<nl/>"
1232  "Local Admin rule: <icode>%2</icode>", line.label, line.regex );
1233  return false;
1234  }
1235  kDebug() << "ok" << endl;
1236  }
1237  return true;
1238 }
1239 
1240 bool EnterDetailsPage::isComplete() const {
1241  QString error;
1242  const bool ok = requirementsAreMet( lineList, error );
1243  ui.errorLB->setText( error );
1244  return ok;
1245 }
1246 
1247 void EnterDetailsPage::slotAdvancedSettingsClicked() {
1248  dialog.exec();
1249 }
1250 
1251 QStringList KeyCreationPage::keyUsages() const {
1252  QStringList usages;
1253  if ( signingAllowed() )
1254  usages << QLatin1String("sign");
1255  if ( encryptionAllowed() && !is_dsa( keyType() ) && !is_rsa( subkeyType() ) )
1256  usages << QLatin1String("encrypt");
1257  if ( 0 ) // not needed in pgp (implied) and not supported in cms
1258  if ( certificationAllowed() )
1259  usages << QLatin1String("certify");
1260  if ( authenticationAllowed() )
1261  usages << QLatin1String("auth");
1262  return usages;
1263 }
1264 
1265 QStringList OverviewPage::i18nKeyUsages() const {
1266  QStringList usages;
1267  if ( signingAllowed() )
1268  usages << i18n("Sign");
1269  if ( encryptionAllowed() && !is_dsa( keyType() ) && !is_rsa( subkeyType() ) )
1270  usages << i18n("Encrypt");
1271  if ( 0 ) // not needed in pgp (implied) and not supported in cms
1272  if ( certificationAllowed() )
1273  usages << i18n("Certify");
1274  if ( authenticationAllowed() )
1275  usages << i18n("Authenticate");
1276  return usages;
1277 }
1278 
1279 QStringList KeyCreationPage::subkeyUsages() const {
1280  QStringList usages;
1281  if ( encryptionAllowed() && ( is_dsa( keyType() ) || is_rsa ( subkeyType() ) ) ) {
1282  assert( subkeyType() );
1283  usages << QLatin1String("encrypt");
1284  }
1285  return usages;
1286 }
1287 
1288 QStringList OverviewPage::i18nSubkeyUsages() const {
1289  QStringList usages;
1290  if ( encryptionAllowed() && ( is_dsa( keyType() ) || is_rsa ( subkeyType() ) ) ) {
1291  assert( subkeyType() );
1292  usages << i18n("Encrypt");
1293  }
1294  return usages;
1295 }
1296 
1297 QStringList OverviewPage::i18nCombinedKeyUsages() const {
1298  return i18nSubkeyUsages() + i18nKeyUsages();
1299 }
1300 
1301 namespace {
1302  template <typename T=QString>
1303  struct Row {
1304  QString key;
1305  T value;
1306 
1307  Row( const QString & k, const T & v ) : key( k ), value( v ) {}
1308  };
1309  template <typename T>
1310  QTextStream & operator<<( QTextStream & s, const Row<T> & row ) {
1311  if ( row.key.isEmpty() )
1312  return s;
1313  else
1314  return s << "<tr><td>" << row.key << "</td><td>" << row.value << "</td></tr>";
1315  }
1316 }
1317 
1318 QString OverviewPage::i18nFormatGnupgKeyParms( bool details ) const {
1319  QString result;
1320  QTextStream s( &result );
1321  s << "<table>";
1322  if ( pgp() )
1323  s << Row< >( i18n("Name:"), name() );
1324  s << Row< >( i18n("Email Address:"), email() );
1325  if ( pgp() ) {
1326  if ( !comment().isEmpty() )
1327  s << Row< >( i18n("Comment:"), comment() );
1328  } else {
1329  s << Row< >( i18n("Subject-DN:"), DN( dn() ).dn( QLatin1String(",<br>") ) );
1330  }
1331  if ( details ) {
1332  s << Row< >( i18n("Key Type:"), QLatin1String(gpgme_pubkey_algo_name( static_cast<gpgme_pubkey_algo_t>( keyType() ) )) );
1333  if ( const unsigned int strength = keyStrength() )
1334  s << Row< >( i18n("Key Strength:"), i18np("1 bit", "%1 bits", strength ) );
1335  else
1336  s << Row< >( i18n("Key Strength:"), i18n("default") );
1337  s << Row< >( i18n("Certificate Usage:"), i18nCombinedKeyUsages().join(i18nc("separator for key usages",",&nbsp;")) );
1338  if ( const unsigned int subkey = subkeyType() ) {
1339  s << Row< >( i18n("Subkey Type:"), QLatin1String(gpgme_pubkey_algo_name( static_cast<gpgme_pubkey_algo_t>( subkey ) )) );
1340  if ( const unsigned int strength = subkeyStrength() )
1341  s << Row< >( i18n("Subkey Strength:"), i18np("1 bit", "%1 bits", strength ) );
1342  else
1343  s << Row< >( i18n("Subkey Strength:"), i18n("default") );
1344  s << Row< >( i18n("Subkey Usage:"), i18nSubkeyUsages().join(i18nc("separator for key usages",",&nbsp;")) );
1345  }
1346  }
1347  if ( pgp() && details && expiryDate().isValid() )
1348  s << Row< >( i18n("Valid Until:"), KGlobal::locale()->formatDate( expiryDate() ) );
1349  if ( !pgp() && details ) {
1350  Q_FOREACH( const QString & email, additionalEMailAddresses() )
1351  s << Row< >( i18n("Add. Email Address:"),email );
1352  Q_FOREACH( const QString & dns, dnsNames() )
1353  s << Row< >( i18n("DNS Name:"), dns );
1354  Q_FOREACH( const QString & uri, uris() )
1355  s << Row< >( i18n("URI:"), uri );
1356  }
1357  return result;
1358 }
1359 
1360 static QString encode_dns( const QString & dns ) {
1361  return QString::fromLatin1( QUrl::toAce( dns ) );
1362 }
1363 
1364 static QString encode_email( const QString & email ) {
1365  const int at = email.lastIndexOf( QLatin1Char('@') );
1366  if ( at < 0 )
1367  return email;
1368  return email.left( at + 1 ) + encode_dns( email.mid( at + 1 ) );
1369 }
1370 
1371 QString KeyCreationPage::createGnupgKeyParms() const {
1372  QString result;
1373  QTextStream s( &result );
1374  s << "<GnupgKeyParms format=\"internal\">" << endl;
1375  if ( pgp() )
1376  s << "%ask-passphrase" << endl;
1377  s << "key-type: " << gpgme_pubkey_algo_name( static_cast<gpgme_pubkey_algo_t>( keyType() ) ) << endl;
1378  if ( const unsigned int strength = keyStrength() )
1379  s << "key-length: " << strength << endl;
1380  s << "key-usage: " << keyUsages().join(QLatin1String(" ")) << endl;
1381  if ( const unsigned int subkey = subkeyType() ) {
1382  s << "subkey-type: " << gpgme_pubkey_algo_name( static_cast<gpgme_pubkey_algo_t>( subkey ) ) << endl;
1383  if ( const unsigned int strength = subkeyStrength() )
1384  s << "subkey-length: " << strength << endl;
1385  s << "subkey-usage: " << subkeyUsages().join(QLatin1String(" ")) << endl;
1386  }
1387  if ( pgp() && expiryDate().isValid() )
1388  s << "expire-date: " << expiryDate().toString( Qt::ISODate ) << endl;
1389  s << "name-email: " << encode_email( email() ) << endl;
1390  if ( pgp() ) {
1391  s << "name-real: " << name() << endl;
1392  if ( !comment().isEmpty() )
1393  s << "name-comment: " << comment() << endl;
1394  } else {
1395  s << "name-dn: " << dn() << endl;
1396  Q_FOREACH( const QString & email, additionalEMailAddresses() )
1397  s << "name-email: " << encode_email( email )<< endl;
1398  Q_FOREACH( const QString & dns, dnsNames() )
1399  s << "name-dns: " << encode_dns( dns ) << endl;
1400  Q_FOREACH( const QString & uri, uris() )
1401  s << "name-uri: " << uri << endl;
1402  }
1403  s << "</GnupgKeyParms>" << endl;
1404  kDebug() << '\n' << result;
1405  return result;
1406 }
1407 
1408 static void fill_combobox( QComboBox & cb, const QList<int> & sizes, const QStringList & labels ) {
1409  cb.clear();
1410  for ( int i = 0, end = sizes.size() ; i != end ; ++i ) {
1411  cb.addItem( i < labels.size() && !labels[i].trimmed().isEmpty()
1412  ? sizes[i] < 0
1413  ? i18ncp( "%2: some admin-supplied text, %1: key size in bits", "%2 (1 bit; default)", "%2 (%1 bits; default)", -sizes[i], labels[i].trimmed() )
1414  : i18ncp( "%2: some admin-supplied text, %1: key size in bits", "%2 (1 bit)", "%2 (%1 bits)", sizes[i], labels[i].trimmed() )
1415  : sizes[i] < 0
1416  ? i18ncp( "%1: key size in bits", "1 bit (default)", "%1 bits (default)", -sizes[i] )
1417  : i18ncp( "%1: key size in bits", "1 bit", "%1 bits", sizes[i] ),
1418  std::abs( sizes[i] ) );
1419  if ( sizes[i] < 0 )
1420  cb.setCurrentIndex( cb.count() - 1 );
1421  }
1422 }
1423 
1424 void AdvancedSettingsDialog::fillKeySizeComboBoxen() {
1425 
1426  const KConfigGroup config( KGlobal::config(), "CertificateCreationWizard" );
1427 
1428  const QList<int> rsaKeySizes = config.readEntry( RSA_KEYSIZES_ENTRY, QList<int>() << 1536 << -2048 << 3072 << 4096 );
1429  const QList<int> dsaKeySizes = config.readEntry( DSA_KEYSIZES_ENTRY, QList<int>() << -2048 );
1430  const QList<int> elgKeySizes = config.readEntry( ELG_KEYSIZES_ENTRY, QList<int>() << 1536 << -2048 << 3072 << 4096 );
1431 
1432  const QStringList rsaKeySizeLabels = config.readEntry( RSA_KEYSIZE_LABELS_ENTRY, QStringList() );
1433  const QStringList dsaKeySizeLabels = config.readEntry( DSA_KEYSIZE_LABELS_ENTRY, QStringList() );
1434  const QStringList elgKeySizeLabels = config.readEntry( ELG_KEYSIZE_LABELS_ENTRY, QStringList() );
1435 
1436  fill_combobox( *ui.rsaKeyStrengthCB, rsaKeySizes, rsaKeySizeLabels );
1437  fill_combobox( *ui.rsaKeyStrengthSubCB, rsaKeySizes, rsaKeySizeLabels );
1438  fill_combobox( *ui.dsaKeyStrengthCB, dsaKeySizes, dsaKeySizeLabels );
1439  fill_combobox( *ui.elgKeyStrengthCB, elgKeySizes, elgKeySizeLabels );
1440 
1441 }
1442 
1443 void AdvancedSettingsDialog::loadDefaultKeyType() {
1444 
1445  if ( protocol != CMS && protocol != OpenPGP )
1446  return;
1447 
1448  const KConfigGroup config( KGlobal::config(), "CertificateCreationWizard" );
1449 
1450  const QString entry = protocol == CMS ? QLatin1String(CMS_KEY_TYPE_ENTRY) : QLatin1String(PGP_KEY_TYPE_ENTRY) ;
1451  const QString keyType = config.readEntry( entry ).trimmed().toUpper();
1452 
1453  if ( protocol == OpenPGP && keyType == QLatin1String("DSA") ) {
1454  setKeyType( GPGME_PK_DSA );
1455  setSubkeyType( 0 );
1456  } else if ( protocol == OpenPGP && keyType == QLatin1String("DSA+ELG") ) {
1457  setKeyType( GPGME_PK_DSA );
1458  setSubkeyType( GPGME_PK_ELG_E );
1459  } else {
1460  if ( !keyType.isEmpty() && keyType != QLatin1String("RSA") )
1461  kWarning() << "invalid value \"" << qPrintable( keyType )
1462  << "\" for entry \"[CertificateCreationWizard]"
1463  << qPrintable( entry ) << "\"";
1464  setKeyType( GPGME_PK_RSA );
1465  setSubkeyType( GPGME_PK_RSA );
1466  }
1467 
1468  keyTypeImmutable = config.isEntryImmutable( entry );
1469  updateWidgetVisibility();
1470 }
1471 
1472 void AdvancedSettingsDialog::updateWidgetVisibility() {
1473  // Personal Details Page
1474  if ( protocol == OpenPGP ) { // ### hide until multi-uid is implemented
1475  if ( ui.tabWidget->indexOf( ui.personalTab ) != -1 )
1476  ui.tabWidget->removeTab( ui.tabWidget->indexOf( ui.personalTab ) );
1477  } else {
1478  if ( ui.tabWidget->indexOf( ui.personalTab ) == -1 )
1479  ui.tabWidget->addTab( ui.personalTab, tr2i18n( "Personal Details", 0 ) );
1480  }
1481  ui.uidGB->setVisible( protocol == OpenPGP );
1482  ui.uidGB->setEnabled( false );
1483  ui.uidGB->setToolTip( i18nc("@info:tooltip","Adding more than one User ID is not yet implemented.") );
1484  ui.emailGB->setVisible( protocol == CMS );
1485  ui.dnsGB->setVisible( protocol == CMS );
1486  ui.uriGB->setVisible( protocol == CMS );
1487  // Technical Details Page
1488  if ( keyTypeImmutable ) {
1489  ui.rsaRB->setEnabled( false );
1490  ui.rsaSubCB->setEnabled( false );
1491  ui.dsaRB->setEnabled( false );
1492  ui.elgCB->setEnabled( false );
1493  } else {
1494  ui.rsaRB->setEnabled( true );
1495  ui.rsaSubCB->setEnabled( protocol == OpenPGP );
1496  ui.dsaRB->setEnabled( protocol == OpenPGP );
1497  ui.elgCB->setEnabled( protocol == OpenPGP );
1498  }
1499  ui.certificationCB->setVisible( protocol == OpenPGP ); // gpgsm limitation?
1500  ui.authenticationCB->setVisible( protocol == OpenPGP );
1501  if ( protocol == OpenPGP ) { // pgp keys must have certify capability
1502  ui.certificationCB->setChecked( true );
1503  ui.certificationCB->setEnabled( false );
1504  }
1505  if ( protocol == CMS ) {
1506  ui.encryptionCB->setEnabled( true );
1507  ui.rsaSubCB->setChecked( false );
1508  }
1509  ui.expiryDE->setVisible( protocol == OpenPGP );
1510  ui.expiryCB->setVisible( protocol == OpenPGP );
1511  slotKeyMaterialSelectionChanged();
1512 }
1513 
1514 #include "newcertificatewizard.moc"
CMS_KEY_TYPE_ENTRY
static const char CMS_KEY_TYPE_ENTRY[]
Definition: newcertificatewizard.cpp:102
QWidget
QString::append
QString & append(QChar ch)
QDate::addYears
QDate addYears(int nyears) const
Kleo::NewCertificateWizard::~NewCertificateWizard
~NewCertificateWizard()
Definition: newcertificatewizard.cpp:935
QWidget::setupUi
void setupUi(QWidget *widget)
QString::toUpper
QString toUpper() const
Kleo::Validation::email
QValidator * email(QObject *parent=0)
Definition: validation.cpp:129
set_tab_order
static void set_tab_order(const QList< QWidget * > &wl)
Definition: newcertificatewizard.cpp:104
QWizard::setPage
void setPage(int id, QWizardPage *page)
QRegExpValidator
set_keysize
static void set_keysize(QComboBox *cb, unsigned int strength)
Definition: newcertificatewizard.cpp:147
QGridLayout::getItemPosition
void getItemPosition(int index, int *row, int *column, int *rowSpan, int *columnSpan)
QMetaProperty::isValid
bool isValid() const
QGridLayout::addWidget
void addWidget(QWidget *widget, int row, int column, QFlags< Qt::AlignmentFlag > alignment)
QVector::begin
iterator begin()
QList::push_back
void push_back(const T &value)
QByteArray
QLineEdit::setText
void setText(const QString &)
QWizard::setOptions
void setOptions(QFlags< QWizard::WizardOption > options)
QAbstractButton::autoExclusive
autoExclusive
email
static std::string email(const UserID &uid)
Definition: keycache.cpp:594
PGP_KEY_TYPE_ENTRY
static const char PGP_KEY_TYPE_ENTRY[]
Definition: newcertificatewizard.cpp:101
QLayoutItem::widget
virtual QWidget * widget()
validation.h
QMap
Definition: signingcertificateselectiondialog.h:41
QPointer
ELG
Definition: newcertificatewizard.cpp:108
FIELD
#define FIELD(type, name)
Definition: newcertificatewizard.cpp:198
Kleo::NewCertificateWizard::ChooseProtocolPageId
Definition: newcertificatewizard.h:59
QWidget::isVisible
bool isVisible() const
formatting.h
Kleo::Command::start
void start()
Definition: commands/command.cpp:182
RSA
Definition: newcertificatewizard.cpp:108
ResultPageId
Definition: newsignencryptfileswizard.cpp:91
QGridLayout
DSA_KEYSIZE_LABELS_ENTRY
static const char DSA_KEYSIZE_LABELS_ENTRY[]
Definition: newcertificatewizard.cpp:98
add_row
static int add_row(QGridLayout *l, QList< QWidget * > *wl)
Definition: newcertificatewizard.cpp:1075
QString::remove
QString & remove(int position, int n)
oidForAttributeName
static const char * oidForAttributeName(const QString &attr)
Definition: newcertificatewizard.cpp:985
row_index_of
static int row_index_of(QWidget *w, QGridLayout *l)
Definition: newcertificatewizard.cpp:1036
QWizard::setStartId
void setStartId(int id)
Kleo::Commands::ExportSecretKeyCommand
Definition: exportsecretkeycommand.h:44
QFile
QTextStream
QString::lastIndexOf
int lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
Kleo::NewCertificateWizard::protocol
GpgME::Protocol protocol() const
Definition: newcertificatewizard.cpp:942
Kleo::NewCertificateWizard::NewCertificateWizard
NewCertificateWizard(QWidget *parent=0)
Definition: newcertificatewizard.cpp:929
QLayout::indexOf
virtual int indexOf(QWidget *widget) const
QLabel::setBuddy
void setBuddy(QWidget *buddy)
QLineEdit::setReadOnly
void setReadOnly(bool)
Kleo::NewCertificateWizard::OverviewPageId
Definition: newcertificatewizard.h:61
is_elg
static bool is_elg(unsigned int algo)
Definition: newcertificatewizard.cpp:135
QRegExp
QMetaObject::propertyCount
int propertyCount() const
QWidget::isEnabled
bool isEnabled() const
QString::fromLocal8Bit
QString fromLocal8Bit(const char *str, int size)
d
#define d
Definition: adduseridcommand.cpp:89
QString::fromUtf8
QString fromUtf8(const char *str, int size)
QMetaObject
is_dsa
static bool is_dsa(unsigned int algo)
Definition: newcertificatewizard.cpp:131
QList::empty
bool empty() const
QVariant::toInt
int toInt(bool *ok) const
DSA
Definition: newcertificatewizard.cpp:108
QUrl::toAce
QByteArray toAce(const QString &domain)
Kleo::Class::OpenPGP
Definition: classify.h:49
Kleo::NewCertificateWizard::setProtocol
void setProtocol(GpgME::Protocol protocol)
Definition: newcertificatewizard.cpp:937
exportsecretkeycommand.h
requirementsAreMet
static bool requirementsAreMet(const QVector< Line > &list, QString &error)
Definition: newcertificatewizard.cpp:1204
QWidget::setTabOrder
void setTabOrder(QWidget *first, QWidget *second)
QString::isEmpty
bool isEmpty() const
adjust_row
static QLineEdit * adjust_row(QGridLayout *l, int row, const QString &label, const QString &preset, QValidator *validator, bool readonly, bool required)
Definition: newcertificatewizard.cpp:1043
QString::trimmed
QString trimmed() const
QByteArray::replace
QByteArray & replace(int pos, int len, const char *after)
fill_combobox
static void fill_combobox(QComboBox &cb, const QList< int > &sizes, const QStringList &labels)
Definition: newcertificatewizard.cpp:1408
Kleo::Validation::pgpComment
QValidator * pgpComment(QObject *parent=0)
Definition: validation.cpp:145
KDAB_SET_OBJECT_NAME
#define KDAB_SET_OBJECT_NAME(x)
Definition: kdtoolsglobal.h:66
QDate::isValid
bool isValid() const
ELG_KEYSIZE_LABELS_ENTRY
static const char ELG_KEYSIZE_LABELS_ENTRY[]
Definition: newcertificatewizard.cpp:99
QLineEdit::validator
const QValidator * validator() const
QString::endsWith
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const
Kleo::Class::CMS
Definition: classify.h:48
QDate
QLabel::setText
void setText(const QString &)
QString
QList
Definition: commands/command.h:46
QWidget::hide
void hide()
KeyAlgo
KeyAlgo
Definition: newcertificatewizard.cpp:108
get_keysize
static unsigned int get_keysize(const QComboBox *cb)
Definition: newcertificatewizard.cpp:156
DSA_KEYSIZES_ENTRY
static const char DSA_KEYSIZES_ENTRY[]
Definition: newcertificatewizard.cpp:94
Kleo::ExportCertificateCommand
Definition: exportcertificatecommand.h:39
Kleo::Formatting::prettyNameAndEMail
QString prettyNameAndEMail(int proto, const char *id, const char *name, const char *email, const char *comment)
Definition: formatting.cpp:87
QStringList
exportopenpgpcertstoservercommand.h
QUrl::toLocalFile
QString toLocalFile() const
QComboBox::itemData
QVariant itemData(int index, int role) const
is_algo
static bool is_algo(gpgme_pubkey_algo_t algo, KeyAlgo what)
Definition: newcertificatewizard.cpp:110
QFileInfo
QValidator::validate
virtual State validate(QString &input, int &pos) const =0
QObject::setParent
void setParent(QObject *parent)
RSA_KEYSIZES_ENTRY
static const char RSA_KEYSIZES_ENTRY[]
Definition: newcertificatewizard.cpp:93
QUrl
Kleo::FileDialog::getSaveFileName
QString getSaveFileName(QWidget *parent=0, const QString &caption=QString(), const QString &dirID=QString(), const QString &filter=QString())
Definition: filedialog.cpp:127
QLatin1Char
newcertificatewizard.h
Kleo::ExportCertificateCommand::setOpenPGPFileName
void setOpenPGPFileName(const QString &fileName)
Definition: exportcertificatecommand.cpp:126
QMetaObject::invokeMethod
bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType type, QGenericReturnArgument ret, QGenericArgument val0, QGenericArgument val1, QGenericArgument val2, QGenericArgument val3, QGenericArgument val4, QGenericArgument val5, QGenericArgument val6, QGenericArgument val7, QGenericArgument val8, QGenericArgument val9)
encode_dns
static QString encode_dns(const QString &dns)
Definition: newcertificatewizard.cpp:1360
QMetaProperty::name
const char * name() const
QMetaObject::propertyOffset
int propertyOffset() const
QDir
QAbstractButton::setChecked
void setChecked(bool)
QString::replace
QString & replace(int position, int n, QChar after)
QAbstractButton
QGridLayout::rowCount
int rowCount() const
QWizard::button
QAbstractButton * button(WizardButton which) const
QString::mid
QString mid(int position, int n) const
QComboBox::findData
int findData(const QVariant &data, int role, QFlags< Qt::MatchFlag > flags) const
QVector< Line >
QTest::toString
char * toString(const T &value)
QLatin1String
QRadioButton
QWizardPage::wizard
QWizard * wizard() const
QDate::currentDate
QDate currentDate()
q
#define q
Definition: adduseridcommand.cpp:90
Kleo::NewCertificateWizard
Definition: newcertificatewizard.h:49
encode_email
static QString encode_email(const QString &email)
Definition: newcertificatewizard.cpp:1364
QUrl::toPercentEncoding
QByteArray toPercentEncoding(const QString &input, const QByteArray &exclude, const QByteArray &include)
QComboBox::setCurrentIndex
void setCurrentIndex(int index)
Kleo::KeyCache::instance
static boost::shared_ptr< const KeyCache > instance()
Definition: keycache.cpp:190
attributeFromKey
static QString attributeFromKey(QString key)
Definition: newcertificatewizard.cpp:981
exportcertificatecommand.h
Kleo::Validation::pgpName
QValidator * pgpName(QObject *parent=0)
Definition: validation.cpp:137
name
const char * name
Definition: uiserver/selectcertificatecommand.cpp:113
QString::left
QString left(int n) const
pgpLabel
static QString pgpLabel(const QString &attr)
Definition: newcertificatewizard.cpp:946
QDialog
QString::fromLatin1
QString fromLatin1(const char *str, int size)
Kleo::NewCertificateWizard::EnterDetailsPageId
Definition: newcertificatewizard.h:60
QLineEdit::hasAcceptableInput
bool hasAcceptableInput() const
QWidget::show
void show()
QLayout::parentWidget
QWidget * parentWidget() const
has_intermediate_input
static bool has_intermediate_input(const QLineEdit *le)
Definition: newcertificatewizard.cpp:1197
QLineEdit
QWizard
is_rsa
static bool is_rsa(unsigned int algo)
Definition: newcertificatewizard.cpp:127
QDesktopServices::openUrl
bool openUrl(const QUrl &url)
keycache.h
QLineEdit::cursorPosition
cursorPosition
QLabel
QObject::parent
QObject * parent() const
RSA_KEYSIZE_LABELS_ENTRY
static const char RSA_KEYSIZE_LABELS_ENTRY[]
Definition: newcertificatewizard.cpp:97
QGridLayout::itemAtPosition
QLayoutItem * itemAtPosition(int row, int column) const
QLineEdit::setValidator
void setValidator(const QValidator *v)
QDir::home
QDir home()
force_set_checked
static void force_set_checked(QAbstractButton *b, bool on)
Definition: newcertificatewizard.cpp:139
Kleo::Commands::ExportOpenPGPCertsToServerCommand
Definition: exportopenpgpcertstoservercommand.h:41
QUrl::fromEncoded
QUrl fromEncoded(const QByteArray &input)
QMetaProperty
QWizardPage
QUrl::fromLocalFile
QUrl fromLocalFile(const QString &localFile)
QValidator
QMetaObject::property
QMetaProperty property(int index) const
attributeLabel
static QString attributeLabel(const QString &attr, bool pgp)
Definition: newcertificatewizard.cpp:956
ELG_KEYSIZES_ENTRY
static const char ELG_KEYSIZES_ENTRY[]
Definition: newcertificatewizard.cpp:95
filedialog.h
QString::toUtf8
QByteArray toUtf8() const
QComboBox
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:33:11 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kleopatra

Skip menu "kleopatra"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

kdepim API Reference

Skip menu "kdepim API Reference"
  • akonadi_next
  • akregator
  • blogilo
  • calendarsupport
  • console
  •   kabcclient
  •   konsolekalendar
  • kaddressbook
  • kalarm
  •   lib
  • kdgantt2
  • kjots
  • kleopatra
  • kmail
  • knode
  • knotes
  • kontact
  • korgac
  • korganizer
  • ktimetracker
  • libkdepim
  • libkleo
  • libkpgp
  • mailcommon
  • messagelist
  • messageviewer
  • pimprint

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal