From ff7704ff0b607a280a966f5a8f97931b85487261 Mon Sep 17 00:00:00 2001 From: Christian Hohnstaedt Date: Fri, 9 Apr 2021 15:54:32 +0200 Subject: [PATCH] Add context sensitive documentation All dialogs get the "Qt::WindowModal" modality to operate the Help window in parallel while also blocking the dialog parent windows. The manageRevocations() moved from model to view The Details dialogs become more self-sufficient. There is a statc start method that shows the dialog and updates name and comment after accept(). This allows recursive starts of certificate details and independence of mainwin. It is necessary to set the current toplevel widget as parent for the next dialog to not block the application. --- doc/rst/certificate-input.rst | 12 +++ doc/rst/certificates.rst | 5 ++ doc/rst/common-actions.rst | 52 +++++++++---- doc/rst/index.rst | 3 +- doc/rst/options.rst | 1 + doc/rst/privatekey.rst | 33 ++++++--- doc/rst/requests.rst | 5 ++ doc/rst/revocationlist.rst | 60 +++++++++++++++ doc/rst/{template-crl.rst => template.rst} | 24 ------ lib/database_model.cpp | 11 ++- lib/database_model.h | 23 +++++- lib/db_base.cpp | 4 +- lib/db_crl.cpp | 6 +- lib/db_key.cpp | 4 +- lib/db_temp.cpp | 1 - lib/db_x509.cpp | 30 ++------ lib/db_x509.h | 1 - lib/db_x509req.cpp | 4 +- ui/Help.ui | 14 +++- widgets/CertDetail.cpp | 85 +++++++++++++++------- widgets/CertDetail.h | 8 +- widgets/CertTreeView.cpp | 17 ++++- widgets/CrlDetail.cpp | 45 ++++++++++-- widgets/CrlDetail.h | 9 ++- widgets/CrlTreeView.cpp | 34 +-------- widgets/CrlTreeView.h | 2 +- widgets/ExportDialog.cpp | 12 ++- widgets/ExportDialog.h | 5 +- widgets/Help.cpp | 47 ++++++++++-- widgets/Help.h | 3 + widgets/ImportMulti.cpp | 28 +------ widgets/KeyDetail.cpp | 37 +++++++++- widgets/KeyDetail.h | 11 ++- widgets/KeyTreeView.cpp | 16 +--- widgets/KeyTreeView.h | 2 +- widgets/MainWindow.cpp | 2 + widgets/MainWindow.h | 4 +- widgets/NewCrl.cpp | 23 +++++- widgets/NewCrl.h | 3 +- widgets/NewKey.cpp | 4 +- widgets/NewX509.cpp | 11 ++- widgets/NewX509.h | 2 +- widgets/Options.cpp | 2 + widgets/RevocationList.cpp | 15 ++-- widgets/RevocationList.h | 7 +- widgets/TempTreeView.cpp | 10 +-- widgets/TempTreeView.h | 6 +- widgets/X509SuperTreeView.cpp | 25 +------ widgets/X509SuperTreeView.h | 2 +- widgets/XcaDialog.h | 8 +- widgets/XcaTreeView.h | 2 +- 51 files changed, 500 insertions(+), 280 deletions(-) create mode 100644 doc/rst/revocationlist.rst rename doc/rst/{template-crl.rst => template.rst} (54%) diff --git a/doc/rst/certificate-input.rst b/doc/rst/certificate-input.rst index 3643dfba..8c3c935b 100644 --- a/doc/rst/certificate-input.rst +++ b/doc/rst/certificate-input.rst @@ -1,4 +1,6 @@ +.. index:: wizard (wizard) + .. _wizard: Certificate Input Dialog @@ -8,6 +10,8 @@ This input dialog is the central part for collecting all data regarding certific requests and templates. It will be invoked whenever such an item is going to be created or, in case of a template, is altered. +.. index:: wizard_src (wizard_src) + Source ------ @@ -45,6 +49,8 @@ Templates can be mixed by applying the subject of one template and then applying the extensions of an other by using the buttons *Apply subject* and *Apply extensions* +.. index:: wizard_subject (wizard_subject) + Personal Settings ----------------- @@ -97,6 +103,10 @@ Select "Modify subject of the request", if you want to modify it anyway. The content of the subject Tab will then be preset with the content of the request. +.. index:: wizard_extensions (wizard_extensions) +.. index:: wizard_keyusage (wizard_keyusage) +.. index:: wizard_netcape (wizard_netcape) + X509v3 Extensions ----------------- @@ -134,6 +144,8 @@ template. Applying the time range means to set notBefore to "now" and notAfter to "now + time range". If the *midnight* button is set both dates will be rounded down and up to midnight. +.. index:: wizard_advanced (wizard_advanced) + Advanced ........ diff --git a/doc/rst/certificates.rst b/doc/rst/certificates.rst index 9b6f56b4..01ea00a0 100644 --- a/doc/rst/certificates.rst +++ b/doc/rst/certificates.rst @@ -1,4 +1,5 @@ +.. index:: certdetail (certdetail) .. _certificates: Certificates @@ -31,6 +32,8 @@ This usually happens if a CA certificate got renewed. In this case XCA selects the certificate with the later expiry date as anchor for the issued certificates. +.. index:: certgen (certgen) + Generating certificates ----------------------- @@ -60,6 +63,8 @@ If the certificate is revoked, the revocation date will be shown instead. On the *Subject* and *Issuer* tab the distinguished name is also displayed in a format defined in RFC2253 for copy&paste. +.. index:: certexport (certexport) + Certificate Export ------------------ diff --git a/doc/rst/common-actions.rst b/doc/rst/common-actions.rst index 73aa5c2b..1712c683 100644 --- a/doc/rst/common-actions.rst +++ b/doc/rst/common-actions.rst @@ -7,6 +7,9 @@ here once for all. The goal of this application is to provide an easy to use signing-tool and also a common place for all selected PKI items like requests or certificates. +.. _columns: +.. index:: columns (columns) + Column Handling --------------- @@ -39,19 +42,6 @@ It shows all available columns with check-boxes to show or hide them. - **Comment** A multi-line free text input, see :ref:`comment`. -- Private Key columns - - - **Type** - One of *RSA*, *DSA*, *EC*, *ED25519*. - - **Size** - Key size in bits. - - **EC Group** - Curve name of the EC key. - - **Use** - Number of certificates and requests using this key. - - **Password** - Protection of the key. See :ref:`keys` - - Certificate and request columns - **Subject** @@ -93,6 +83,8 @@ Columns can be resized and rearranged. This configuration is stored in the database and will be reassigned next time this database is opened. +.. index:: import (import) + Importing items --------------- @@ -163,6 +155,15 @@ The displayed list of items can be reduced by the search-input at the bottom right. It affects all tabs. It does not only search inside the displayed columns but the whole content of the items. It searches the internal name, issuer, subject, extensions, PKCS#10 attributes and token provider. +.. _internal_name: + +Internal name +------------- + +The internal name is only used inside the database and is intended +to uniquely identify the items. In earlier versions of XCA this name +had to be unique. This is not a requirement anymore. + .. _date_and_source: Date and source of appearance @@ -175,19 +176,27 @@ context menu of an item, or by enabling the *Source* or The source may be one of the following -- Imported +- Imported: + From a file or by pasting PEM data - Generated + Created by XCA - Transformed + Converted from an other item by the "transform" context menu - Token + The device has been initiall read from a hardware token - Legacy Database + The item was already present in a legacy XCA database that + did not track the Source information. The content of the date and source fields will never be part of an exported item. +.. index:: comment (comment) + .. _comment: -Comments --------- +Comment +------- XCA allows to insert multi-line comments for all items. They can be edited by the properties dialog. When showing the *Comment* @@ -200,6 +209,7 @@ to leave a note during important operations: - Generated keys during certificate or request generation - Signing date, time and internal name of the issuing CA when a request gets signed. +- File name when the item got imported from a file. The content of the comment field will never be part of an exported item. @@ -216,3 +226,13 @@ The internal name cannot be used, since it is not necessarily unique anymore. This ID will never be used outside the database. +.. index:: itemproperties (itemproperties) + +Item properties +--------------- + +Common properties can be displayed and edited for all items: + +- Internal name :ref:`internal_name` +- Comment :ref:`comment` +- Date and source :ref:`date_and_source` diff --git a/doc/rst/index.rst b/doc/rst/index.rst index 403af890..9d476bae 100644 --- a/doc/rst/index.rst +++ b/doc/rst/index.rst @@ -21,7 +21,8 @@ XCA - X Certificate and Key management privatekey requests certificates - template-crl + template + revocationlist options object-ids step-by-step diff --git a/doc/rst/options.rst b/doc/rst/options.rst index 8b072769..de801760 100644 --- a/doc/rst/options.rst +++ b/doc/rst/options.rst @@ -1,4 +1,5 @@ +.. index:: options (options) .. _options: Options diff --git a/doc/rst/privatekey.rst b/doc/rst/privatekey.rst index 9eb6a444..6e85d685 100644 --- a/doc/rst/privatekey.rst +++ b/doc/rst/privatekey.rst @@ -1,4 +1,6 @@ +.. index:: keydetail (keydetail) + .. _keys: RSA, DSA and EC Keys @@ -6,9 +8,11 @@ RSA, DSA and EC Keys For creating certificates, keys are needed. All keys are stored encrypted in the database using the PKCS#8 AES algorithm. -The password can be changed for each key. The password type means: +The password can be changed for each key. -.. index:: keytype (ktid) +.. index:: keytab (keytab) + +The password type means: common: The database password provided during database load. @@ -20,8 +24,6 @@ PIN: No password: Public keys don't need a password. -.. index:: usecounter (ucid) - All keys carry a use counter which counts the times it is used in requests or certificates. When creating new requests or certificates the list of available keys is reduced to the keys with a use counter of 0. @@ -31,6 +33,23 @@ Keys should *never* be used multiple times. When importing an EC key with explicit curve parameters, the corresponding curve OID is searched and set if found. +- Private Key columns + + - **Type** + One of *RSA*, *DSA*, *EC*, *ED25519*. + - **Size** + Key size in bits. + - **EC Group** + Curve name of the EC key. + - **Use** + Number of certificates and requests in the database using this key. + For new certificates and requests only unused or newly generated keys + should be used. + - **Password** + Protection of the key. See :ref:`keys` + +.. index:: keygen (keygen) + Generating Keys --------------- @@ -45,15 +64,11 @@ While searching for random prime numbers a progress bar is shown in the bottom of the base application. After the key generation is done the key will be stored in the database. -.. index:: keygen_default - When checking the *Remember as default* box, the settings (Key-type, key-size or EC curve) will be remembered and preset for the next key generation dialog. This option is not available when generating keys on 'ref'`token`. -.. index:: keygen_token - For every connected token providing the Key-Generate facility, an entry in the drop-down menu of the key-types will be shown. It contains the name of the token and the valid key-sizes. @@ -64,7 +79,7 @@ The token may support even less ECParameters / OIDs. When selecting an unsupported EC curve an error will occur. Please consult the documentation of the provider of the PKCS#11 library. -.. index:: key_export +.. index:: keyexport (keyexport) Key Export ---------- diff --git a/doc/rst/requests.rst b/doc/rst/requests.rst index a647d75b..8ced51c2 100644 --- a/doc/rst/requests.rst +++ b/doc/rst/requests.rst @@ -1,4 +1,5 @@ +.. index:: csrdetail (csrdetail) .. _csr: Certificate Signing Requests @@ -25,6 +26,8 @@ It does not depend on the certificate remaining in the XCA database. The *Certificate count* column on the other hand displays the number of currently available certificates with the same public key in the database. +.. index:: csrgen (csrgen) + Generating a new Request ------------------------ @@ -39,6 +42,8 @@ if the private key of the certificate is available. In this case all needed data is copied from the certificate and the Certificate dialog is not invoked. +.. index:: csrexport (csrexport) + Request Export -------------- diff --git a/doc/rst/revocationlist.rst b/doc/rst/revocationlist.rst new file mode 100644 index 00000000..b5a680d6 --- /dev/null +++ b/doc/rst/revocationlist.rst @@ -0,0 +1,60 @@ +.. index:: crldetail (crldetail) + +Certificate Revocation Lists +============================ + +All certificates are issued for a restricted period of time. +However it may happen that a certificate should not be used or becomes invalid +before the *not after* time in the certificate is reached. In this case +the issuing CA should revoke this certificate by putting it on the list of +revoked certificates, signing the list and publishing it. + +.. index:: crlgenerate (crlgenerate) + +Generation of CRLs +------------------ + +In XCA this can be done by the context-menu of the CA and the +*revoke* entry in the context-menu of the issued certificate. +First all invalid certificates must be marked as revoked and +then a Certificate Revocation List should be created and will be stored in the +database. + +The validity times define start and expiry date of the CRL. The default +interval can be configured in the :ref:`ca_properties` dialog. + +The options section allows to select, whether the Subject Alternative Name +and the Authority Key Identifier of the issuing CA should be placed into +the CRL. The CRL Number (https://tools.ietf.org/html/rfc5280#section-5.2.3) +will be tracked by XCA and updated on every use. + +There is also a commandline option to issue a CRL: + +.. code-block:: bash + + xca --crlgen="My Ca" --pem --print + +.. index:: crlmanage (crlmanage) + +Manage revocations +------------------ + +Revoked certificates may be managed without the revoked certificate +in the database. The revocations are stored inside the database for each CA +with revocation date, revocation reason and invalidation date. +They get automatically updated when importing a CRL of this CA +or by manually revoking an issued certificate. +The Manage revocations dialog is accessible by the CA submenu of the +ontext menu of the CA. +Entries can be added, deleted and modified. + +.. index:: crlrevocation (crlrevocation) + +Revocation properties +--------------------- + +The certificate revocation happens by the CA at the *revocation date* which +is the time when the revocation is performed. The *invalidity date* can be set +to an earlier time in this dialog. The *revocation reason* is explains why +the certificate has been revoked. +https://tools.ietf.org/html/rfc5280#section-5.3 diff --git a/doc/rst/template-crl.rst b/doc/rst/template.rst similarity index 54% rename from doc/rst/template-crl.rst rename to doc/rst/template.rst index fac3abec..1d6f258e 100644 --- a/doc/rst/template-crl.rst +++ b/doc/rst/template.rst @@ -20,27 +20,3 @@ An easy way to create templates is to export an existing certificate or PKCS#10 request to a template. Just select *Transform->Template* in the context-menu of the item. The private key of the Certificate or Request is not required for this operation. - -Certificate Revocation Lists -============================ - -All certificates are issued for a restricted period of time. -However it may happen that a certificate should not be used or becomes invalid -before the *not after* time in the certificate is reached. In this case -the issuing CA should revoke this certificate by putting it on the list of -revoked certificates, signing the list and publishing it. - -Generation of Certificate revocation lists ------------------------------------------- - -In XCA this can be done by the context-menu of the CA and the -*revoke* entry in the context-menu of the issued certificate. -First all invalid certificates must be marked as revoked and -then a Certificate Revocation List should be created and will be stored in the -database. - -There is also a commandline option to issue a CRL: - -.. code-block:: bash - - xca --crlgen="My Ca" --pem --print diff --git a/lib/database_model.cpp b/lib/database_model.cpp index dccd8469..ce9217fc 100644 --- a/lib/database_model.cpp +++ b/lib/database_model.cpp @@ -294,9 +294,11 @@ database_model::database_model(const QString &name, const Passwd &pass) models << new db_crl(); models << new db_temp(); - foreach(db_base *m, models) + foreach(db_base *m, models) { check_oom(m); - + connect(m, SIGNAL(pkiChanged(pki_base*)), + this, SLOT(pkiChangedSlot(pki_base*))); + } if (!oldDbFile.isEmpty()) importOldDatabase(oldDbFile); @@ -656,3 +658,8 @@ enum open_result database_model::initPass(const QString &dbName, const QString & pki_evp::passwd = ""; return pw_ok; } + +void database_model::pkiChangedSlot(pki_base *pki) +{ + emit pkiChanged(pki); +} diff --git a/lib/database_model.h b/lib/database_model.h index 507af683..abc3182a 100644 --- a/lib/database_model.h +++ b/lib/database_model.h @@ -38,7 +38,6 @@ class database_model: public QObject enum open_result initPass(const QString &dbName, const QString &passhash) const; void restart_timer(); - db_base *modelForPki(const pki_base *pki) const; static void openDatabase(const QString &descriptor, const Passwd &pass); static void openRemoteDatabase(const QString &connName, @@ -46,12 +45,15 @@ class database_model: public QObject const Passwd &pass); static void openLocalDatabase(const QString &connName, const QString &descriptor); + private slots: + void pkiChangedSlot(pki_base *pki); public: database_model(const QString &dbName, const Passwd &pass = Passwd()); ~database_model(); void timerEvent(QTimerEvent *event); + db_base *modelForPki(const pki_base *pki) const; QString dbname() const { @@ -76,14 +78,18 @@ class database_model: public QObject static DbMap splitRemoteDbName(const QString &db); static bool isRemoteDB(const QString &db); static void as_default_database(const QString &db); + + signals: + void pkiChanged(pki_base *pki) const; }; -class xca_db { - +class xca_db +{ private: database_model *db; public: + xca_db() : db(nullptr) { } ~xca_db() { close(); @@ -135,6 +141,17 @@ class xca_db { { return db ? db->insert(pki) : NULL; } + db_base *modelForPki(const pki_base *pki) const + { + return db ? db->modelForPki(pki) : NULL; + } + void connectToDbChangeEvt(QObject *o, const char *slot) + { + if (db) + QObject::connect( + db, SIGNAL(pkiChanged(pki_base*)), + o, slot); + } }; extern xca_db Database; diff --git a/lib/db_base.cpp b/lib/db_base.cpp index 764d83ef..e42e2516 100644 --- a/lib/db_base.cpp +++ b/lib/db_base.cpp @@ -637,8 +637,8 @@ void db_base::editComment(const QModelIndex &index) prop->name->setText(item->getIntName()); prop->source->setText(item->pki_source_name()); prop->insertionDate->setText(item->getInsertionDate().toPretty()); - XcaDialog *d = new XcaDialog(NULL, item->getType(), w, - tr("Item properties"), QString()); + XcaDialog *d = new XcaDialog(nullptr, item->getType(), w, + tr("Item properties"), QString(), "itemproperties"); if (d->exec()) updateItem(item, prop->name->text(), prop->comment->toPlainText()); delete d; diff --git a/lib/db_crl.cpp b/lib/db_crl.cpp index fa9b7a5d..e4b87474 100644 --- a/lib/db_crl.cpp +++ b/lib/db_crl.cpp @@ -7,17 +7,13 @@ #include "db_crl.h" +#include "db_x509.h" #include "main.h" #include "exception.h" #include "database_model.h" -#include "widgets/CrlDetail.h" -#include "widgets/NewCrl.h" #include #include -#include "widgets/XcaDialog.h" -#include "widgets/XcaWarning.h" #include "widgets/ItemCombo.h" -#include "ui_NewCrl.h" db_crl::db_crl() : db_x509name("crls") { diff --git a/lib/db_key.cpp b/lib/db_key.cpp index 084f5517..51811551 100644 --- a/lib/db_key.cpp +++ b/lib/db_key.cpp @@ -229,7 +229,7 @@ exportType::etype db_key::clipboardFormat(QModelIndexList indexes) const } ExportDialog *dlg = new ExportDialog(NULL, tr("Export keys to Clipboard"), QString(), NULL, - QPixmap(":keyImg"), types); + QPixmap(":keyImg"), types, "keyexport"); dlg->filename->setText(tr("Clipboard")); dlg->filename->setEnabled(false); @@ -304,7 +304,7 @@ void db_key::store(QModelIndex index) tr("Private Keys ( *.pem *.der *.pk8 );; " "SSH Public Keys ( *.pub )"), key, QPixmap(key->isToken() ? ":scardImg" : ":keyImg"), - types); + types, "keyexport"); if (!dlg->exec()) { delete dlg; diff --git a/lib/db_temp.cpp b/lib/db_temp.cpp index 4088c947..14a84270 100644 --- a/lib/db_temp.cpp +++ b/lib/db_temp.cpp @@ -10,7 +10,6 @@ #include "func.h" #include "widgets/XcaWarning.h" #include "widgets/NewX509.h" -#include "widgets/XcaDialog.h" #include #include #include diff --git a/lib/db_x509.cpp b/lib/db_x509.cpp index 1dc31e66..e9788950 100644 --- a/lib/db_x509.cpp +++ b/lib/db_x509.cpp @@ -375,7 +375,7 @@ void db_x509::markRequestSigned(pki_x509req *req, pki_x509 *cert) void db_x509::newItem() { - NewX509 *dlg = new NewX509(NULL); + NewX509 *dlg = new NewX509(); dlg->setCert(); pki_x509 *sigcert = get1SelectedCert(); dlg->defineSigner((pki_x509*)sigcert, true); @@ -387,7 +387,7 @@ void db_x509::newItem() void db_x509::newCert(pki_x509req *req) { - NewX509 *dlg = new NewX509(NULL); + NewX509 *dlg = new NewX509(); pki_x509 *sigcert = get1SelectedCert(); dlg->setCert(); dlg->defineRequest(req); @@ -400,7 +400,7 @@ void db_x509::newCert(pki_x509req *req) void db_x509::newCert(pki_temp *temp) { - NewX509 *dlg = new NewX509(NULL); + NewX509 *dlg = new NewX509(); dlg->setCert(); dlg->defineTemplate(temp); if (dlg->exec()) { @@ -411,7 +411,7 @@ void db_x509::newCert(pki_temp *temp) void db_x509::newCert(pki_x509 *cert) { - NewX509 *dlg = new NewX509(NULL); + NewX509 *dlg = new NewX509(); dlg->setCert(); dlg->fromX509super(cert, false); if (dlg->exec()) { @@ -628,7 +628,7 @@ void db_x509::store(QModelIndexList list) types = usual << exportType() << types; ExportDialog *dlg = new ExportDialog(NULL, tr("Certificate export"), tr("X509 Certificates ( *.pem *.cer *.crt *.p12 *.pfx *.p7b )"), crt, - QPixmap(":certImg"), types); + QPixmap(":certImg"), types, "certexport"); if (!dlg->exec()) { delete dlg; return; @@ -829,22 +829,6 @@ void db_x509::writePKCS7(pki_x509 *cert, XFile &file, exportType::etype type, delete p7; } -void db_x509::manageRevocations(QModelIndex idx) -{ - pki_x509 *cert = fromIndex(idx); - if (!cert) - return; - - RevocationList *dlg = new RevocationList(NULL); - dlg->setRevList(cert->getRevList(), cert); - connect(dlg, SIGNAL(genCRL(pki_x509*)), - mainwin->crlView, SLOT(newItem(pki_x509*))); - if (dlg->exec()) { - cert->setRevocations(dlg->getRevList()); - emit columnsContentChanged(); - } -} - void db_x509::certRenewal(QModelIndexList indexes) { pki_x509 *oldcert = NULL, *signer = NULL, *newcert =NULL; @@ -874,7 +858,7 @@ void db_x509::certRenewal(QModelIndexList indexes) return; } if (dlg->revoke->isChecked() && !renew_myself) { - Revocation *revoke = new Revocation(NULL, indexes); + Revocation *revoke = new Revocation(indexes); doRevoke = revoke->exec(); r = revoke->getRevocation(); delete revoke; @@ -921,7 +905,7 @@ void db_x509::revoke(QModelIndexList indexes) { if (indexes.size() == 0) return; - Revocation *revoke = new Revocation(NULL, indexes); + Revocation *revoke = new Revocation(indexes); if (revoke->exec()) { do_revoke(indexes, revoke->getRevocation()); } diff --git a/lib/db_x509.h b/lib/db_x509.h index fb741d16..0272f1cf 100644 --- a/lib/db_x509.h +++ b/lib/db_x509.h @@ -58,7 +58,6 @@ class db_x509: public db_x509super void load(); void caProperties(QModelIndex idx); void toCertificate(QModelIndex index); - void manageRevocations(QModelIndex idx); void certRenewal(QModelIndexList indexes); void revoke(QModelIndexList indexes); void do_revoke(QModelIndexList indexes, const x509rev &r); diff --git a/lib/db_x509req.cpp b/lib/db_x509req.cpp index 1a56a7ff..8c6e69a2 100644 --- a/lib/db_x509req.cpp +++ b/lib/db_x509req.cpp @@ -65,7 +65,7 @@ void db_x509req::newItem() void db_x509req::newItem(pki_temp *temp, pki_x509req *orig) { pki_x509req *req = NULL; - NewX509 *dlg = new NewX509(NULL); + NewX509 *dlg = new NewX509(); if (temp) { dlg->defineTemplate(temp); @@ -118,7 +118,7 @@ void db_x509req::store(QModelIndex index) ExportDialog *dlg = new ExportDialog(NULL, tr("Certificate request export"), tr("Certificate request ( *.pem *.der *.csr )"), req, - QPixmap(":csrImg"), types); + QPixmap(":csrImg"), types, "csrexport"); if (!dlg->exec()) { delete dlg; return; diff --git a/ui/Help.ui b/ui/Help.ui index ae446cf6..029f1637 100644 --- a/ui/Help.ui +++ b/ui/Help.ui @@ -92,7 +92,7 @@ buttonOk clicked() Help - accept() + hide() 668 @@ -136,5 +136,17 @@ + + textbox + backwardAvailable(bool) + back + setEnabled(bool) + + + textbox + forwardAvailable(bool) + forward + setEnabled(bool) + diff --git a/widgets/CertDetail.cpp b/widgets/CertDetail.cpp index 8c9e5b04..906c1967 100644 --- a/widgets/CertDetail.cpp +++ b/widgets/CertDetail.cpp @@ -12,6 +12,7 @@ #include "distname.h" #include "clicklabel.h" #include "XcaWarning.h" +#include "Help.h" #include "OidResolver.h" #include "lib/func.h" #include @@ -19,15 +20,16 @@ #include #include -CertDetail::CertDetail(QWidget *parent) - :QDialog(parent) +CertDetail::CertDetail(QWidget *w) + : QDialog(w ?: mainwin), keySqlId(), issuerSqlId(), thisSqlId() { setupUi(this); setWindowTitle(XCA_TITLE); showConf = false; - keySqlId = QVariant(); - issuerSqlId = QVariant(); myPubKey = NULL; + tmpPubKey = NULL; + + Database.connectToDbChangeEvt(this, SLOT(itemChanged(pki_base*))); } void CertDetail::on_showExt_clicked() @@ -47,31 +49,35 @@ void CertDetail::on_showExt_clicked() void CertDetail::setX509super(pki_x509super *x) { descr->setText(x->getIntName()); + thisSqlId = x->getSqlItemId(); // examine the key - pki_key *key= x->getRefKey(); - myPubKey = x->getPubKey(); - if (key) { - privKey->setText(key->getIntName()); - privKey->setClickText(key->getSqlItemId().toString()); - if (key->isPrivKey()) { + myPubKey = x->getRefKey(); + if (myPubKey) { + privKey->setText(myPubKey->getIntName()); + privKey->setClickText(myPubKey->getSqlItemId().toString()); + if (myPubKey->isPrivKey()) { privKey->setGreen(); } else { privKey->setRed(); } - keySqlId = key->getSqlItemId(); - } else if (myPubKey) { + } else { + tmpPubKey = myPubKey = x->getPubKey(); privKey->setText(tr("Show public key")); privKey->setRed(); - connect(privKey, SIGNAL(doubleClicked(QString)), - this, SLOT(showPubKey())); myPubKey->setIntName(x->getIntName()); myPubKey->setComment(tr("This key is not in the database.")); - } else { + } + + if (!myPubKey) { privKey->setText(tr("Not available")); privKey->setDisabled(true); privKey->disableToolTip(); + } else { + keySqlId = myPubKey->getSqlItemId(); } + connect(privKey, SIGNAL(doubleClicked(QString)), + this, SLOT(showPubKey())); // details of the subject subject->setX509name(x->getSubject()); @@ -104,6 +110,7 @@ void CertDetail::setCert(pki_x509 *cert) return; image->setPixmap(QPixmap(":certImg")); headerLabel->setText(tr("Details of the Certificate")); + mainwin->helpdlg->register_ctxhelp_button(this, "certdetail"); try { // No attributes tabwidget->removeTab(3); @@ -123,6 +130,9 @@ void CertDetail::setCert(pki_x509 *cert) signature->setClickText(issuer->getSqlItemId().toString()); signature->setGreen(); issuerSqlId = issuer->getSqlItemId(); + + connect(signature, SIGNAL(doubleClicked(QString)), + this, SLOT(showIssuer())); } // the serial @@ -172,6 +182,7 @@ void CertDetail::setReq(pki_x509req *req) return; image->setPixmap(QPixmap(":csrImg")); headerLabel->setText(tr("Details of the certificate signing request")); + mainwin->helpdlg->register_ctxhelp_button(this, "csrdetail"); try { // No issuer tabwidget->removeTab(2); @@ -252,28 +263,48 @@ QLabel *CertDetail::labelFromAsn1String(ASN1_STRING *s) void CertDetail::itemChanged(pki_base *pki) { - if (pki->getSqlItemId() == keySqlId) - privKey->setText(pki->getIntName()); + QVariant pkiSqlId = pki->getSqlItemId(); - if (pki->getSqlItemId() == issuerSqlId) + if (pkiSqlId == keySqlId) + privKey->setText(pki->getIntName()); + if (pkiSqlId == issuerSqlId) signature->setText(pki->getIntName()); + if (pkiSqlId == thisSqlId) + descr->setText(pki->getIntName()); } void CertDetail::showPubKey() { - if (!myPubKey) + KeyDetail::showKey(this, myPubKey); +} + +void CertDetail::showIssuer() +{ + showCert(this, Store.lookupPki(issuerSqlId)); +} + +void CertDetail::showCert(QWidget *parent, pki_x509super *x) +{ + if (!x) return; - KeyDetail *dlg = new KeyDetail(this); + CertDetail *dlg = new CertDetail(parent); if (!dlg) - return; - dlg->setKey(myPubKey); - dlg->keyDesc->setReadOnly(true); - dlg->comment->setReadOnly(true); - dlg->exec(); - delete dlg; + return; + dlg->setX509super(x); + if (dlg->exec()) { + db_base *db = Database.modelForPki(x); + if (!db) { + x->setIntName(dlg->descr->text()); + x->setComment(dlg->comment->toPlainText()); + } else { + db->updateItem(x, dlg->descr->text(), + dlg->comment->toPlainText()); + } + } + delete dlg; } CertDetail::~CertDetail() { - delete myPubKey; + delete tmpPubKey; } diff --git a/widgets/CertDetail.h b/widgets/CertDetail.h index 7071fb61..ecb9760d 100644 --- a/widgets/CertDetail.h +++ b/widgets/CertDetail.h @@ -19,22 +19,24 @@ class CertDetail: public QDialog, public Ui::CertDetail Q_OBJECT bool showConf; - QVariant keySqlId, issuerSqlId; + QVariant keySqlId, issuerSqlId, thisSqlId; QString conf, exts; QLabel *labelFromAsn1String(ASN1_STRING *s); - pki_key *myPubKey; + pki_key *myPubKey, *tmpPubKey; void setCert(pki_x509 *cert); void setReq(pki_x509req *req); public: - CertDetail(QWidget *parent); + CertDetail(QWidget *w = nullptr); ~CertDetail(); void setX509super(pki_x509super *x); + static void showCert(QWidget *parent, pki_x509super *x); private slots: void on_showExt_clicked(); void itemChanged(pki_base *pki); void showPubKey(); + void showIssuer(); }; #endif diff --git a/widgets/CertTreeView.cpp b/widgets/CertTreeView.cpp index 9d8321a2..6103cc95 100644 --- a/widgets/CertTreeView.cpp +++ b/widgets/CertTreeView.cpp @@ -8,6 +8,8 @@ #include "CertTreeView.h" #include "XcaWarning.h" #include "MainWindow.h" +#include "RevocationList.h" +#include "NewCrl.h" #include "lib/database_model.h" #include "lib/db_crl.h" @@ -127,8 +129,7 @@ void CertTreeView::genCrl() { pki_x509 *ca = db_base::fromIndex(currentIndex()); - if (mainwin && ca) - mainwin->crlView->newItem(ca); + NewCrl::newCrl(this, ca); } void CertTreeView::toCertificate() @@ -158,8 +159,16 @@ void CertTreeView::changeView() void CertTreeView::manageRevocations() { - if (basemodel) - certs()->manageRevocations(currentIndex()); + pki_x509 *cert = db_base::fromIndex(currentIndex()); + if (!cert) + return; + + RevocationList *dlg = new RevocationList(); + dlg->setRevList(cert->getRevList(), cert); + if (dlg->exec()) { + cert->setRevocations(dlg->getRevList()); + columnsChanged(); + } } void CertTreeView::caProperties() diff --git a/widgets/CrlDetail.cpp b/widgets/CrlDetail.cpp index cebc128b..ed6127f7 100644 --- a/widgets/CrlDetail.cpp +++ b/widgets/CrlDetail.cpp @@ -7,7 +7,9 @@ #include "CrlDetail.h" +#include "CertDetail.h" #include "MainWindow.h" +#include "Help.h" #include "distname.h" #include "clicklabel.h" #include "RevocationList.h" @@ -18,15 +20,15 @@ #include #include -CrlDetail::CrlDetail(MainWindow *mainwin) - :QDialog(mainwin) +CrlDetail::CrlDetail(QWidget *w) + : QDialog(w ?: mainwin), issuerSqlId(), crlSqlId() { - mw = mainwin; setupUi(this); setWindowTitle(XCA_TITLE); + mainwin->helpdlg->register_ctxhelp_button(this, "crldetail"); image->setPixmap(QPixmap(":revImg")); - issuerSqlId = QVariant(); + Database.connectToDbChangeEvt(this, SLOT(itemChanged(pki_base*))); } void CrlDetail::setCrl(pki_crl *crl) @@ -35,6 +37,8 @@ void CrlDetail::setCrl(pki_crl *crl) x509v3ext e1, e2; iss = crl->getIssuer(); + crlSqlId = crl->getSqlItemId(); + signCheck->disableToolTip(); signCheck->setClickText(crl->getSigAlg()); if (iss != NULL) { @@ -59,6 +63,8 @@ void CrlDetail::setCrl(pki_crl *crl) connect(signCheck, SIGNAL(doubleClicked(QString)), MainWindow::getResolver(), SLOT(searchOid(QString))); + connect(issuerIntName, SIGNAL(doubleClicked(QString)), + this, SLOT(showIssuer())); descr->setText(crl->getIntName()); lUpdate->setText(crl->getLastUpdate().toPretty()); @@ -78,6 +84,35 @@ void CrlDetail::setCrl(pki_crl *crl) void CrlDetail::itemChanged(pki_base *pki) { - if (pki->getSqlItemId() == issuerSqlId) + QVariant pkiSqlId = pki->getSqlItemId(); + + if (pkiSqlId == issuerSqlId) issuerIntName->setText(pki->getIntName()); + if (pkiSqlId == crlSqlId) + descr->setText(pki->getIntName()); +} + +void CrlDetail::showIssuer() +{ + CertDetail::showCert(this, Store.lookupPki(issuerSqlId)); +} + +void CrlDetail::showCrl(QWidget *parent, pki_crl *crl) +{ + CrlDetail *dlg = new CrlDetail(parent); + if (!dlg) + return; + + dlg->setCrl(crl); + if (dlg->exec()) { + db_base *db = Database.modelForPki(crl); + if (!db) { + crl->setIntName(dlg->descr->text()); + crl->setComment(dlg->comment->toPlainText()); + } else { + db->updateItem(crl, dlg->descr->text(), + dlg->comment->toPlainText()); + } + } + delete dlg; } diff --git a/widgets/CrlDetail.h b/widgets/CrlDetail.h index b431f856..5d1801c3 100644 --- a/widgets/CrlDetail.h +++ b/widgets/CrlDetail.h @@ -12,18 +12,19 @@ class pki_crl; class pki_base; -class MainWindow; class CrlDetail: public QDialog, public Ui::CrlDetail { Q_OBJECT + private: - MainWindow *mw; - QVariant issuerSqlId; + QVariant issuerSqlId, crlSqlId; public: - CrlDetail(MainWindow *mainwin); + CrlDetail(QWidget *w = nullptr); void setCrl(pki_crl *crl); + static void showCrl(QWidget *parent, pki_crl *crl); public slots: void itemChanged(pki_base *pki); + void showIssuer(); }; #endif diff --git a/widgets/CrlTreeView.cpp b/widgets/CrlTreeView.cpp index 512382ae..8f03698a 100644 --- a/widgets/CrlTreeView.cpp +++ b/widgets/CrlTreeView.cpp @@ -16,40 +16,14 @@ #include "lib/pki_x509.h" #include "lib/database_model.h" -void CrlTreeView::showPki(pki_base *pki) const +void CrlTreeView::showPki(pki_base *pki) { - db_x509 *certs = Database.model(); - pki_crl *crl = dynamic_cast(pki); - - if (!crl || !basemodel || !certs) - return; - - CrlDetail *dlg = new CrlDetail(NULL); - if (!dlg) - return; - - dlg->setCrl(crl); - connect(dlg->issuerIntName, SIGNAL(doubleClicked(QString)), - mainwin->certView, SLOT(showItem(QString))); - connect(certs, SIGNAL(pkiChanged(pki_base*)), - dlg, SLOT(itemChanged(pki_base*))); - if (dlg->exec()) { - crls()->updateItem(pki, dlg->descr->text(), - dlg->comment->toPlainText()); - } - delete dlg; + CrlDetail::showCrl(this, dynamic_cast(pki)); } void CrlTreeView::newItem(pki_x509 *cert) { - crljob task(cert); - NewCrl *widget = new NewCrl(NULL, task); - XcaDialog *dlg = new XcaDialog(mainwin, revocation, widget, - tr("Create CRL"), QString()); - if (dlg->exec() && basemodel) { - crls()->newCrl(widget->getCrlJob()); - } - delete dlg; + NewCrl::newCrl(this, cert); } void CrlTreeView::newItem() @@ -67,7 +41,7 @@ void CrlTreeView::newItem() break; default: { itemComboCert *c = new itemComboCert(NULL); - XcaDialog *d = new XcaDialog(mainwin, revocation, c, + XcaDialog *d = new XcaDialog(this, revocation, c, tr("Select CA certificate"), QString()); c->insertPkiItems(cas); if (!d->exec()) { diff --git a/widgets/CrlTreeView.h b/widgets/CrlTreeView.h index 83fe5dc6..b36ee818 100644 --- a/widgets/CrlTreeView.h +++ b/widgets/CrlTreeView.h @@ -24,7 +24,7 @@ class CrlTreeView: public XcaTreeView public: CrlTreeView(QWidget *parent) : XcaTreeView(parent) { } - void showPki(pki_base *pki) const; + void showPki(pki_base *pki); public slots: void newItem(pki_x509 *cert); diff --git a/widgets/ExportDialog.cpp b/widgets/ExportDialog.cpp index 144e96a4..24f2c0c9 100644 --- a/widgets/ExportDialog.cpp +++ b/widgets/ExportDialog.cpp @@ -8,6 +8,7 @@ #include "ExportDialog.h" #include "MainWindow.h" +#include "Help.h" #include "XcaWarning.h" #include "lib/base.h" @@ -18,9 +19,10 @@ #include #include -ExportDialog::ExportDialog(QWidget *w, const QString &title, const QString &filt, - pki_base *pki, const QPixmap &img, QList types) - : QDialog(w) +ExportDialog::ExportDialog(QWidget *w, const QString &title, + const QString &filt, pki_base *pki, const QPixmap &img, + QList types, const QString &help_ctx) + : QDialog(w ?: mainwin) { setupUi(this); setWindowTitle(XCA_TITLE); @@ -28,7 +30,9 @@ ExportDialog::ExportDialog(QWidget *w, const QString &title, const QString &filt descr->setText(pki->getIntName()); descr->setReadOnly(true); image->setPixmap(img); - label->setText(title); + label->setText(title); + mainwin->helpdlg->register_ctxhelp_button(this, help_ctx); + if (pki) { QString fn = Settings["workingdir"] + pki->getUnderlinedName() + "." + types[0].extension; diff --git a/widgets/ExportDialog.h b/widgets/ExportDialog.h index 603c1582..39e5c5ec 100644 --- a/widgets/ExportDialog.h +++ b/widgets/ExportDialog.h @@ -59,8 +59,9 @@ class ExportDialog: public QDialog, public Ui::ExportDialog QVector help; public: - ExportDialog(QWidget *mw, const QString &title, const QString &filt, - pki_base *pki, const QPixmap &img, QList types); + ExportDialog(QWidget *w, const QString &title, const QString &filt, + pki_base *pki, const QPixmap &img, QList types, + const QString &help_ctx = QString()); static bool mayWriteFile(const QString &fname); enum exportType::etype type(); diff --git a/widgets/Help.cpp b/widgets/Help.cpp index 674a5098..556e2ff3 100644 --- a/widgets/Help.cpp +++ b/widgets/Help.cpp @@ -9,14 +9,17 @@ #include "lib/func.h" #include +#include #include +#include Help::Help() : QWidget(NULL) { setupUi(this); setWindowTitle(XCA_TITLE); textbox->setSearchPaths(QStringList(getDocDir())); - + textbox->setOpenExternalLinks(true); + textbox->clearHistory(); helpengine = new QHelpEngineCore(getDocDir() + "/xca.qhc"); } @@ -27,10 +30,17 @@ Help::~Help() void Help::display(const QUrl &url) { - qDebug() << "URL:" << url.toString() << "Fragment:" << url.fragment(); - textbox->setHtml(QString::fromUtf8( helpengine->fileData(url))); +#if QT_VERSION < 0x050000 + QString path = url.path(); + int pos = path.lastIndexOf("/"); + if (pos != -1) + path = path.mid(pos+1); + textbox->setSource(QUrl(path)); +#else + textbox->setSource(QUrl(url.fileName())); +#endif textbox->scrollToAnchor(url.fragment()); - show(); + show(); } void Help::content() @@ -38,9 +48,14 @@ void Help::content() display(QUrl("qthelp://org.sphinx.xca/doc/index.html")); } +QMap Help::url_by_ctx(const QString &ctx) const +{ + return helpengine->linksForIdentifier(QString("%1.%1").arg(ctx)); +} + void Help::contexthelp(const QString &context) { - QMap helpctx(helpengine->linksForIdentifier(context)); + QMap helpctx = url_by_ctx(context); if (helpctx.count()) display(helpctx.constBegin().value()); @@ -54,6 +69,24 @@ void Help::contexthelp() QString ctx = o->property("help_ctx").toString(); if (ctx.isEmpty()) return; - qDebug() << "help_ctx" << ctx; - contexthelp(QString("%1.%1").arg(ctx)); + contexthelp(ctx); +} + +void Help::register_ctxhelp_button(QDialog *dlg, const QString &help_ctx) const +{ + QDialogButtonBox *buttonBox = + dlg->findChild("buttonBox"); + + if (!buttonBox || help_ctx.isEmpty()) + return; + + dlg->setWindowModality(Qt::WindowModal); + buttonBox->addButton(QDialogButtonBox::Help); + buttonBox->setProperty("help_ctx", QVariant(help_ctx)); + connect(buttonBox, SIGNAL(helpRequested()), this, SLOT(contexthelp())); + + if (url_by_ctx(help_ctx).count() == 0) { + qWarning() << "Unknown help context: " << help_ctx; + buttonBox->button(QDialogButtonBox::Help)->setEnabled(false); + } } diff --git a/widgets/Help.h b/widgets/Help.h index e8682c00..e99e93a3 100644 --- a/widgets/Help.h +++ b/widgets/Help.h @@ -24,6 +24,9 @@ class Help: public QWidget, public Ui::Help public: Help(); ~Help(); + void register_ctxhelp_button(QDialog *dlg, + const QString &help_ctx) const; + QMap url_by_ctx(const QString &ctx) const; public slots: void contexthelp(); diff --git a/widgets/ImportMulti.cpp b/widgets/ImportMulti.cpp index 283ba65e..7b123a51 100644 --- a/widgets/ImportMulti.cpp +++ b/widgets/ImportMulti.cpp @@ -251,8 +251,6 @@ void ImportMulti::on_butDetails_clicked() { QItemSelectionModel *selectionModel = listView->selectionModel(); QModelIndex index; - db_key *keys = Database.model(); - db_x509 *certs = Database.model(); if (!selectionModel->selectedIndexes().count()) return; @@ -265,37 +263,17 @@ void ImportMulti::on_butDetails_clicked() try { pki_x509super *pki_super = dynamic_cast(pki); if (pki_super) { - CertDetail *dlg = new CertDetail(NULL); - dlg->setX509super(pki_super); - connect(dlg->privKey, SIGNAL(doubleClicked(QString)), - keys, SLOT(showItem(QString))); - connect(dlg->signature, - SIGNAL(doubleClicked(QString)), - certs, SLOT(showItem(QString))); - if (dlg->exec()) - pki->setIntName(dlg->descr->text()); - delete dlg; + CertDetail::showCert(this, pki_super); return; } pki_key *key = dynamic_cast(pki); if (key) { - KeyDetail *dlg = new KeyDetail(NULL); - dlg->setKey(key); - if (dlg->exec()) - pki->setIntName(dlg->keyDesc->text()); - delete dlg; + KeyDetail::showKey(this, key); return; } pki_crl *crl = dynamic_cast(pki); if (crl) { - CrlDetail *dlg = new CrlDetail(NULL); - dlg->setCrl(crl); - connect(dlg->issuerIntName, - SIGNAL(doubleClicked(QString)), - certs, SLOT(showItem(QString))); - if (dlg->exec()) - pki->setIntName(dlg->descr->text()); - delete dlg; + CrlDetail::showCrl(this, crl); return; } pki_temp *temp = dynamic_cast(pki); diff --git a/widgets/KeyDetail.cpp b/widgets/KeyDetail.cpp index 3622f421..8a00f7fe 100644 --- a/widgets/KeyDetail.cpp +++ b/widgets/KeyDetail.cpp @@ -12,6 +12,7 @@ #include "KeyDetail.h" #include "MainWindow.h" +#include "Help.h" #include "distname.h" #include "clicklabel.h" #include "XcaApplication.h" @@ -21,14 +22,18 @@ #include #include -KeyDetail::KeyDetail(QWidget *parent) - :QDialog(parent) +KeyDetail::KeyDetail(QWidget *w) + : QDialog(w ?: mainwin) , keySqlId() { setupUi(this); setWindowTitle(XCA_TITLE); image->setPixmap(QPixmap(":keyImg")); + mainwin->helpdlg->register_ctxhelp_button(this, "keydetail"); + keyModulus->setFont(XcaApplication::tableFont); tabWidget->setCurrentIndex(0); + + Database.connectToDbChangeEvt(this, SLOT(itemChanged(pki_base*))); } #ifndef OPENSSL_NO_EC @@ -74,6 +79,7 @@ void KeyDetail::setupFingerprints(pki_key *key) void KeyDetail::setKey(pki_key *key) { + keySqlId = key->getSqlItemId(); keyDesc->setText(key->getIntName()); keyLength->setText(key->length()); @@ -142,3 +148,30 @@ void KeyDetail::setKey(pki_key *key) tlHeader->setText(tr("Unknown key")); } } + +void KeyDetail::itemChanged(pki_base *pki) +{ + if (pki->getSqlItemId() == keySqlId) + keyDesc->setText(pki->getIntName()); +} + +void KeyDetail::showKey(QWidget *parent, pki_key *key) +{ + if (!key) + return; + KeyDetail *dlg = new KeyDetail(parent); + if (!dlg) + return; + dlg->setKey(key); + if (dlg->exec()) { + db_base *db = Database.modelForPki(key); + if (!db) { + key->setIntName(dlg->keyDesc->text()); + key->setComment(dlg->comment->toPlainText()); + } else { + db->updateItem(key, dlg->keyDesc->text(), + dlg->comment->toPlainText()); + } + } + delete dlg; +} diff --git a/widgets/KeyDetail.h b/widgets/KeyDetail.h index 1bd219d8..ab73239c 100644 --- a/widgets/KeyDetail.h +++ b/widgets/KeyDetail.h @@ -11,16 +11,21 @@ #include "ui_KeyDetail.h" class pki_key; +class pki_base; class KeyDetail: public QDialog, public Ui::KeyDetail { Q_OBJECT - public: - KeyDetail(QWidget *parent); + QVariant keySqlId; + + public: + KeyDetail(QWidget *w = nullptr); void setKey(pki_key *key); void setupFingerprints(pki_key *key); + static void showKey(QWidget *parent, pki_key *key); - + public slots: + void itemChanged(pki_base *pki); }; #endif diff --git a/widgets/KeyTreeView.cpp b/widgets/KeyTreeView.cpp index bca7e4a8..0737ed93 100644 --- a/widgets/KeyTreeView.cpp +++ b/widgets/KeyTreeView.cpp @@ -165,22 +165,10 @@ void KeyTreeView::toToken() delete card; } -void KeyTreeView::showPki(pki_base *pki) const +void KeyTreeView::showPki(pki_base *pki) { pki_key *key = dynamic_cast(pki); - if (!key || !basemodel) - return; - - KeyDetail *dlg = new KeyDetail(mainwin); - if (!dlg) - return; - dlg->setKey(key); - - if (dlg->exec() && basemodel) { - keys()->updateItem(pki, dlg->keyDesc->text(), - dlg->comment->toPlainText()); - } - delete dlg; + KeyDetail::showKey(this, key); } void KeyTreeView::newItem() { diff --git a/widgets/KeyTreeView.h b/widgets/KeyTreeView.h index 9ee099cc..7114f911 100644 --- a/widgets/KeyTreeView.h +++ b/widgets/KeyTreeView.h @@ -24,7 +24,7 @@ class KeyTreeView: public XcaTreeView KeyTreeView(QWidget *parent) : XcaTreeView(parent) { } void fillContextMenu(QMenu *menu, QMenu *subExport, const QModelIndex &index, QModelIndexList indexes); - void showPki(pki_base *pki) const; + void showPki(pki_base *pki); public slots: void resetOwnPass(); diff --git a/widgets/MainWindow.cpp b/widgets/MainWindow.cpp index 30acba97..f0e941c0 100644 --- a/widgets/MainWindow.cpp +++ b/widgets/MainWindow.cpp @@ -437,6 +437,8 @@ void MainWindow::closeEvent(QCloseEvent *e) } delete resolver; resolver = NULL; + delete helpdlg; + helpdlg = NULL; close_database(); QMainWindow::closeEvent(e); } diff --git a/widgets/MainWindow.h b/widgets/MainWindow.h index 54524201..3107d6ab 100644 --- a/widgets/MainWindow.h +++ b/widgets/MainWindow.h @@ -9,7 +9,6 @@ #define __MAINWINDOW_H #include "ui_MainWindow.h" -#include "Help.h" #include "lib/oid.h" #include "lib/Passwd.h" @@ -27,6 +26,8 @@ class pki_multi; class NewX509; class OidResolver; class QProgressBar; +class DHgen; +class Help; class tipMenu : public QMenu { @@ -48,7 +49,6 @@ class tipMenu : public QMenu } }; -class DHgen; class MainWindow: public QMainWindow, public Ui::MainWindow { Q_OBJECT diff --git a/widgets/NewCrl.cpp b/widgets/NewCrl.cpp index 86d18c5a..73dd37d9 100644 --- a/widgets/NewCrl.cpp +++ b/widgets/NewCrl.cpp @@ -7,18 +7,19 @@ #include "NewCrl.h" +#include "XcaDialog.h" +#include "validity.h" +#include "MainWindow.h" #include "lib/base.h" #include "lib/func.h" -#include "widgets/validity.h" -#include "widgets/MainWindow.h" #include #include #include #include #include -NewCrl::NewCrl(QWidget *parent, const crljob &j) - :QWidget(parent), task(j) +NewCrl::NewCrl(const crljob &j, QWidget *w) + : QWidget(w ?: mainwin), task(j) { pki_x509 *issuer = task.issuer; pki_key *key = issuer->getRefKey(); @@ -67,3 +68,17 @@ NewCrl::~NewCrl() { qDebug() << "NewCrl::~NewCrl() -- DELETED"; } + +void NewCrl::newCrl(QWidget *parent, pki_x509 *issuer) +{ + crljob task(issuer); + NewCrl *widget = new NewCrl(task); + XcaDialog *dlg = new XcaDialog(parent, revocation, widget, + tr("Create CRL"), QString(), "crlgenerate"); + if (dlg->exec()) { + db_crl *db = Database.model(); + if (db) + db->newCrl(widget->getCrlJob()); + } + delete dlg; +} diff --git a/widgets/NewCrl.h b/widgets/NewCrl.h index 1fc17d76..8b7f1360 100644 --- a/widgets/NewCrl.h +++ b/widgets/NewCrl.h @@ -19,9 +19,10 @@ class NewCrl: public QWidget, public Ui::NewCrl crljob task; public: - NewCrl(QWidget *parent, const crljob &task); + NewCrl(const crljob &task, QWidget *w = nullptr); ~NewCrl(); crljob getCrlJob() const; + static void newCrl(QWidget *parent, pki_x509 *issuer); public slots: void on_applyTime_clicked(); diff --git a/widgets/NewKey.cpp b/widgets/NewKey.cpp index 3180f4e6..55f35c44 100644 --- a/widgets/NewKey.cpp +++ b/widgets/NewKey.cpp @@ -8,6 +8,7 @@ #include "NewKey.h" #include "MainWindow.h" +#include "Help.h" #include "lib/pki_evp.h" #include "lib/pkcs11.h" #include "distname.h" @@ -85,7 +86,7 @@ class keyListItem Q_DECLARE_METATYPE(keyListItem); NewKey::NewKey(QWidget *parent, const QString &name) - :QDialog(parent) + :QDialog(parent ?: mainwin) { static const QList sizeList = { 1024, 2048, 4096, 8192 }; slotidList p11_slots; @@ -94,6 +95,7 @@ NewKey::NewKey(QWidget *parent, const QString &name) setupUi(this); setWindowTitle(XCA_TITLE); image->setPixmap(QPixmap(":keyImg")); + mainwin->helpdlg->register_ctxhelp_button(this, "keygen"); if (!name.isEmpty()) keyDesc->setText(name); diff --git a/widgets/NewX509.cpp b/widgets/NewX509.cpp index cec1ef15..6edc8e04 100644 --- a/widgets/NewX509.cpp +++ b/widgets/NewX509.cpp @@ -23,6 +23,7 @@ #include "XcaWarning.h" #include "OidResolver.h" #include "MainWindow.h" +#include "Help.h" #include "v3ext.h" #include "lib/x509name.h" #include "lib/db_key.h" @@ -104,8 +105,7 @@ QList NewX509::setupExplicitInputs(NIDlist nid_list, return edits; } -NewX509::NewX509(QWidget *parent) - :QDialog(parent) +NewX509::NewX509(QWidget *w) : QDialog(w ?: mainwin) { int i; QStringList keys; @@ -115,6 +115,7 @@ NewX509::NewX509(QWidget *parent) attr_nid << NID_pkcs9_unstructuredName << NID_pkcs9_challengePassword; setupUi(this); + mainwin->helpdlg->register_ctxhelp_button(this, "wizard"); /* temporary storage for creating temporary X509V3_CTX */ ctx_cert = NULL; @@ -150,6 +151,7 @@ NewX509::NewX509(QWidget *parent) for (i=0; icount(); i++) { tabnames << tabWidget->tabText(i); + qDebug() << "TAB:" << i << " " << tabWidget->tabText(i); } nsImg->setPixmap(QPixmap(":nsImg")); @@ -1109,8 +1111,13 @@ void NewX509::on_editAuthInfAcc_clicked() void NewX509::on_tabWidget_currentChanged(int tab) { + QStringList helpctx({ + "wizard_src", "wizard_subject", "wizard_extensions", + "wizard_keyusage", "wizard_netscape", "wizard_advanced", + "comment"}); if (tabWidget->tabText(tab) == tabnames[5]) do_validateExtensions(); + buttonBox->setProperty("help_ctx", QVariant(helpctx[tab])); } QString NewX509::mandatoryDnRemain() diff --git a/widgets/NewX509.h b/widgets/NewX509.h index 573308e0..f50f458a 100644 --- a/widgets/NewX509.h +++ b/widgets/NewX509.h @@ -70,7 +70,7 @@ class NewX509: public QDialog, public Ui::NewX509 QWidget *parent, QWidget *old, int columns); public: - NewX509(QWidget *parent); + NewX509(QWidget *w = nullptr); virtual ~NewX509(); void initCtx(); void setRequest(); // reduce to request form diff --git a/widgets/Options.cpp b/widgets/Options.cpp index 48384f9b..b4876606 100644 --- a/widgets/Options.cpp +++ b/widgets/Options.cpp @@ -9,6 +9,7 @@ #include "Options.h" #include "SearchPkcs11.h" #include "XcaWarning.h" +#include "Help.h" #include "lib/pki_scard.h" #include "lib/oid.h" #include @@ -20,6 +21,7 @@ Options::Options(QWidget *parent) { setWindowTitle(XCA_TITLE); setupUi(this); + mainwin->helpdlg->register_ctxhelp_button(this, "options"); foreach(int nid, distname_nid) { QString n = OBJ_nid2ln(nid); diff --git a/widgets/RevocationList.cpp b/widgets/RevocationList.cpp index fc6d7cd8..f10eb540 100644 --- a/widgets/RevocationList.cpp +++ b/widgets/RevocationList.cpp @@ -7,6 +7,8 @@ #include "RevocationList.h" #include "MainWindow.h" +#include "NewCrl.h" +#include "Help.h" #include "lib/asn1int.h" #include "lib/pki_x509.h" @@ -91,12 +93,13 @@ void RevocationList::setupRevocationView(QTreeWidget *certList, certList->setSelectionMode(QAbstractItemView::ExtendedSelection); } -RevocationList::RevocationList(QWidget *w) : QDialog(w) +RevocationList::RevocationList(QWidget *w) : QDialog(w ?: mainwin) { QPushButton *genCrl; setupUi(this); setWindowTitle(XCA_TITLE); image->setPixmap(QPixmap(":revImg")); + mainwin->helpdlg->register_ctxhelp_button(this, "crlmanage"); genCrl = buttonBox->addButton(tr("Generate CRL"), QDialogButtonBox::ActionRole); @@ -107,7 +110,7 @@ RevocationList::RevocationList(QWidget *w) : QDialog(w) void RevocationList::gencrl() { issuer->setRevocations(getRevList()); - emit genCRL(issuer); + NewCrl::newCrl(this, issuer); } void RevocationList::setRevList(const x509revList &rl, pki_x509 *iss) @@ -124,7 +127,7 @@ const x509revList &RevocationList::getRevList() void RevocationList::on_addRev_clicked() { - Revocation *revoke = new Revocation(this, QModelIndexList()); + Revocation *revoke = new Revocation(QModelIndexList(), this); if (revoke->exec()) { x509rev revit = revoke->getRevocation(); revList << revit; @@ -168,7 +171,7 @@ void RevocationList::on_certList_itemDoubleClicked(QTreeWidgetItem *current) rev = revList[idx]; - Revocation *revoke = new Revocation(this, QModelIndexList()); + Revocation *revoke = new Revocation(QModelIndexList(), this); revoke->setRevocation(rev); if (revoke->exec()) { a1time a1 = rev.getDate(); @@ -180,10 +183,12 @@ void RevocationList::on_certList_itemDoubleClicked(QTreeWidgetItem *current) delete revoke; } -Revocation::Revocation(QWidget *w, QModelIndexList indexes) : QDialog(w) +Revocation::Revocation(QModelIndexList indexes, QWidget *w) : QDialog(w ?: mainwin) { setupUi(this); setWindowTitle(XCA_TITLE); + mainwin->helpdlg->register_ctxhelp_button(this, "crlrevocation"); + reason->addItems(x509rev::crlreasons()); invalid->setNow(); diff --git a/widgets/RevocationList.h b/widgets/RevocationList.h index 73646eed..fbd98d96 100644 --- a/widgets/RevocationList.h +++ b/widgets/RevocationList.h @@ -25,7 +25,7 @@ class RevocationList: public QDialog, public Ui::RevocationList public: static void setupRevocationView(QTreeWidget *certList, const x509revList &revList, const pki_x509 *iss); - RevocationList(QWidget *w); + RevocationList(QWidget *w = nullptr); void setRevList(const x509revList &rl, pki_x509 *issuer); const x509revList &getRevList(); @@ -35,9 +35,6 @@ class RevocationList: public QDialog, public Ui::RevocationList void on_editRev_clicked(); void gencrl(); void on_certList_itemDoubleClicked(QTreeWidgetItem *); - - signals: - void genCRL(pki_x509 *); }; class Revocation: public QDialog, public Ui::Revoke @@ -45,7 +42,7 @@ class Revocation: public QDialog, public Ui::Revoke Q_OBJECT public: - Revocation(QWidget *w, QModelIndexList indexes); + Revocation(QModelIndexList indexes, QWidget *w = nullptr); x509rev getRevocation(); void setRevocation(x509rev r); }; diff --git a/widgets/TempTreeView.cpp b/widgets/TempTreeView.cpp index a7da6e63..cc851d49 100644 --- a/widgets/TempTreeView.cpp +++ b/widgets/TempTreeView.cpp @@ -49,14 +49,14 @@ void TempTreeView::reqFromTemp() emit newReq(temp); } -void TempTreeView::showPki(pki_base *pki) const +void TempTreeView::showPki(pki_base *pki) { alterTemp(dynamic_cast(pki)); } -bool TempTreeView::runTempDlg(pki_temp *temp) const +bool TempTreeView::runTempDlg(pki_temp *temp) { - NewX509 *dlg = new NewX509(mainwin); + NewX509 *dlg = new NewX509(this); dlg->setTemp(temp); if (!dlg->exec()) { @@ -78,7 +78,7 @@ void TempTreeView::newItem() itemComboTemp *ic = new itemComboTemp(NULL); ic->insertPkiItems(temps()->getPredefs()); - XcaDialog *dlg = new XcaDialog(mainwin, tmpl, ic, + XcaDialog *dlg = new XcaDialog(this, tmpl, ic, tr("Preset Template values"), QString()); if (dlg->exec()) { temp = new pki_temp(ic->currentPkiItem()); @@ -95,7 +95,7 @@ void TempTreeView::newItem() delete dlg; } -bool TempTreeView::alterTemp(pki_temp *temp) const +bool TempTreeView::alterTemp(pki_temp *temp) { if (!basemodel || !temp) return false; diff --git a/widgets/TempTreeView.h b/widgets/TempTreeView.h index 40c8a72b..dd3f8733 100644 --- a/widgets/TempTreeView.h +++ b/widgets/TempTreeView.h @@ -20,14 +20,14 @@ class TempTreeView: public XcaTreeView return dynamic_cast(basemodel); } - bool runTempDlg(pki_temp *temp) const; + bool runTempDlg(pki_temp *temp); public: TempTreeView(QWidget *parent) : XcaTreeView(parent) { } void fillContextMenu(QMenu *menu, QMenu *subExport, const QModelIndex &index, QModelIndexList indexes); - void showPki(pki_base *pki) const; - bool alterTemp(pki_temp *temp) const; + void showPki(pki_base *pki); + bool alterTemp(pki_temp *temp); public slots: void certFromTemp(); diff --git a/widgets/X509SuperTreeView.cpp b/widgets/X509SuperTreeView.cpp index 3bb16c3e..9e0d53da 100644 --- a/widgets/X509SuperTreeView.cpp +++ b/widgets/X509SuperTreeView.cpp @@ -57,29 +57,8 @@ void X509SuperTreeView::toOpenssl() } -void X509SuperTreeView::showPki(pki_base *pki) const +void X509SuperTreeView::showPki(pki_base *pki) { pki_x509super *x = dynamic_cast(pki); - if (!x) - return; - CertDetail *dlg = new CertDetail(NULL); - if (!dlg) - return; - - dlg->setX509super(x); - - connect(dlg->privKey, SIGNAL(doubleClicked(QString)), - mainwin->keyView, SLOT(showItem(QString))); - connect(dlg->signature, SIGNAL(doubleClicked(QString)), - this, SLOT(showItem(QString))); - connect(basemodel, SIGNAL(pkiChanged(pki_base*)), - dlg, SLOT(itemChanged(pki_base*))); - connect(Database.model(), SIGNAL(pkiChanged(pki_base*)), - dlg, SLOT(itemChanged(pki_base*))); - - if (dlg->exec() && basemodel) { - x509super()->updateItem(pki, dlg->descr->text(), - dlg->comment->toPlainText()); - } - delete dlg; + CertDetail::showCert(this, x); } diff --git a/widgets/X509SuperTreeView.h b/widgets/X509SuperTreeView.h index edb6b134..dc7ce515 100644 --- a/widgets/X509SuperTreeView.h +++ b/widgets/X509SuperTreeView.h @@ -32,7 +32,7 @@ class X509SuperTreeView: public XcaTreeView const QModelIndex &index, QModelIndexList indexes); public slots: - void showPki(pki_base *pki) const; + void showPki(pki_base *pki); void extractPubkey(); void toTemplate(); void toOpenssl(); diff --git a/widgets/XcaDialog.h b/widgets/XcaDialog.h index c181aabd..ad69f81e 100644 --- a/widgets/XcaDialog.h +++ b/widgets/XcaDialog.h @@ -13,6 +13,7 @@ #include "ui_XcaDialog.h" #include "lib/db.h" #include "MainWindow.h" +#include "Help.h" // index = enum pki_type static const char * const PixmapMap[] = { @@ -23,13 +24,16 @@ class XcaDialog : public QDialog, public Ui::XcaDialog { QWidget *widg; public: - XcaDialog(QWidget *parent, enum pki_type type, QWidget *w, - QString t, QString desc) : QDialog(parent) + XcaDialog(QWidget *parent, enum pki_type type, QWidget *w, QString t, + QString desc, QString help_ctx = QString()) + : QDialog(parent ?: mainwin) { setupUi(this); setWindowTitle(XCA_TITLE); image->setPixmap(QPixmap(PixmapMap[type])); content->addWidget(w); + mainwin->helpdlg->register_ctxhelp_button(this, help_ctx); + widg = w; title->setText(t); if (desc.isEmpty()) { diff --git a/widgets/XcaTreeView.h b/widgets/XcaTreeView.h index 77e66975..291455c7 100644 --- a/widgets/XcaTreeView.h +++ b/widgets/XcaTreeView.h @@ -56,7 +56,7 @@ class XcaTreeView: public QTreeView void contextMenu(QContextMenuEvent *e, QMenu *parent = NULL, int sect = -1); void keyPressEvent(QKeyEvent *event); - virtual void showPki(pki_base *) const {}; + virtual void showPki(pki_base *) {}; public slots: void changeView();