From 6ea01e80f6640a6356d4fffe18ef393b15fbbf43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Hohnst=C3=A4dt?= Date: Sat, 30 Oct 2021 18:19:59 +0200 Subject: [PATCH] Refactor item export: separate GUI and database Collect all export formats in pki_export. Each export format has assigned acouple of flags, indicating, whether they are text, concatenateable, encrypted, usable for multiple selections or only for a single item. --- lib/db_base.cpp | 23 ++++- lib/db_base.h | 16 ++- lib/db_crl.cpp | 46 +++------ lib/db_crl.h | 3 +- lib/db_key.cpp | 88 ++++++---------- lib/db_key.h | 7 +- lib/db_temp.cpp | 31 +----- lib/db_temp.h | 3 +- lib/db_x509.cpp | 184 ++++++++++++++-------------------- lib/db_x509.h | 7 +- lib/db_x509req.cpp | 28 +----- lib/db_x509req.h | 3 +- lib/db_x509super.cpp | 19 +--- lib/db_x509super.h | 1 - lib/digest.cpp | 4 +- lib/pki_crl.h | 1 + lib/pki_evp.cpp | 2 +- lib/pki_export.cpp | 71 ++++++------- lib/pki_export.h | 6 +- lib/pki_key.cpp | 2 +- lib/pki_scard.cpp | 3 - lib/settings.cpp | 3 +- ui/MainWindow.ui | 12 +-- widgets/CertTreeView.cpp | 12 +++ widgets/CertTreeView.h | 1 + widgets/CrlTreeView.cpp | 10 ++ widgets/CrlTreeView.h | 1 + widgets/ExportDialog.cpp | 30 ++++-- widgets/ExportDialog.h | 4 +- widgets/KeyTreeView.cpp | 19 +++- widgets/KeyTreeView.h | 1 + widgets/MainWindow.cpp | 1 + widgets/Options.cpp | 1 + widgets/ReqTreeView.cpp | 12 +++ widgets/ReqTreeView.h | 1 + widgets/TempTreeView.cpp | 12 +++ widgets/TempTreeView.h | 1 + widgets/X509SuperTreeView.cpp | 16 ++- widgets/XcaDialog.h | 4 +- widgets/XcaTreeView.cpp | 82 +++++++-------- widgets/XcaTreeView.h | 6 +- widgets/hashBox.cpp | 6 +- 42 files changed, 378 insertions(+), 405 deletions(-) diff --git a/lib/db_base.cpp b/lib/db_base.cpp index c27dabcf..1fc445e6 100644 --- a/lib/db_base.cpp +++ b/lib/db_base.cpp @@ -10,13 +10,9 @@ #include "exception.h" #include "XcaWarningCore.h" -#include -#include -#include #include #include #include -#include #include void db_base::restart_timer() @@ -658,3 +654,22 @@ void db_base::writeVcalendar(XFile &file, QStringList vcal) const "END:VCALENDAR"; file.write(ics.join("\r\n").toUtf8()); } + +void db_base::exportItems(const QModelIndexList &indexes, + const pki_export *xport, XFile &file) const +{ + foreach(QModelIndex idx, indexes) + exportItem(idx, xport, file); +} + +int db_base::exportFlags(const QModelIndexList &indexes) const +{ + int disabled_flags = 0; + foreach(const QModelIndex &idx, indexes) + disabled_flags |= exportFlags(idx); + if (indexes.size() > 1) + disabled_flags |= F_SINGLE; + else + disabled_flags |= F_MULTI; + return disabled_flags; +} diff --git a/lib/db_base.h b/lib/db_base.h index a4e72c7f..8d95a567 100644 --- a/lib/db_base.h +++ b/lib/db_base.h @@ -10,7 +10,6 @@ #include #include "base.h" -#include "load_obj.h" #include "pki_base.h" #include "headerlist.h" @@ -64,10 +63,20 @@ class db_base: public QAbstractItemModel virtual void inToCont(pki_base *pki); virtual void remFromCont(const QModelIndex &idx); void changeView(); + int exportFlags(const QModelIndexList &indexes) const; + virtual int exportFlags(const QModelIndex &index) const + { + return 0; + } + virtual void exportItem(const QModelIndex &index, + const pki_export *xport, XFile &file) const { }; + virtual void exportItems(const QModelIndexList &indexes, + const pki_export *xport, XFile &file) const; void dump(const QString &dirname) const; - QModelIndex index(int row, int column, const QModelIndex &parent)const; - QModelIndex index(pki_base *pki)const; + QModelIndex index(int row, int column, + const QModelIndex &parent) const; + QModelIndex index(pki_base *pki) const; QModelIndex parent(const QModelIndex &index) const; int rowCount(const QModelIndex &parent) const; int allItemsCount() const @@ -112,7 +121,6 @@ class db_base: public QAbstractItemModel { colResizing--; } - virtual void store(QModelIndex index) { (void)index; }; dbheaderList getAllHeaders() { return allHeaders; } diff --git a/lib/db_crl.cpp b/lib/db_crl.cpp index 12f7face..3e507f91 100644 --- a/lib/db_crl.cpp +++ b/lib/db_crl.cpp @@ -12,10 +12,6 @@ #include "exception.h" #include "database_model.h" -#warning drop UI dependencies -#include "widgets/ExportDialog.h" -#include "ui_ExportDialog.h" - db_crl::db_crl() : db_x509name("crls") { sqlHashTable = "crls"; @@ -112,37 +108,21 @@ pki_base *db_crl::insert(pki_base *item) return crl; } -void db_crl::store(QModelIndex index) +void db_crl::exportItems(const QModelIndexList &indexes, + const pki_export *xport, XFile &file) const { - pki_crl *crl = fromIndex(index); - - if (!index.isValid() || !crl) - return; - - ExportDialog *dlg = new ExportDialog(NULL, - tr("Revocation list export"), - tr("CRL ( *.pem *.der *.crl )"), crl, QPixmap(":revImg"), - pki_export::select(revocation, 0)); - if (!dlg->exec()) { - delete dlg; - return; + QStringList vcal; + foreach(QModelIndex idx, indexes) { + pki_crl *crl = fromIndex(idx); + if (!crl) + continue; + if (xport->match_all(F_CAL)) + vcal << crl->icsVEVENT(); + else + crl->writeCrl(file, xport->match_all(F_PEM)); } - try { - const pki_export *xtype = dlg->export_type(); - XFile file(dlg->filename->text()); - pki_base::pem_comment = dlg->pemComment->isChecked(); - file.open_key(); - if (xtype->match_all(F_CAL)) { - writeVcalendar(file, crl->icsVEVENT()); - } else { - crl->writeCrl(file, xtype->match_all(F_PEM)); - } - } - catch (errorEx &err) { - XCA_ERROR(err); - } - pki_base::pem_comment = false; - delete dlg; + if (vcal.size() > 0) + writeVcalendar(file, vcal); } pki_crl *db_crl::newCrl(const crljob &task) diff --git a/lib/db_crl.h b/lib/db_crl.h index 4ef2fd3b..6b74b98a 100644 --- a/lib/db_crl.h +++ b/lib/db_crl.h @@ -23,8 +23,9 @@ class db_crl: public db_x509name void inToCont(pki_base *pki); pki_base *insert(pki_base *item); void removeSigner(pki_base *signer); - void store(QModelIndex index); void updateCertView(); pki_crl *newCrl(const crljob &crljob); + void exportItems(const QModelIndexList &indexes, + const pki_export *xport, XFile &file) const; }; #endif diff --git a/lib/db_key.cpp b/lib/db_key.cpp index 088f8b2d..92f4f548 100644 --- a/lib/db_key.cpp +++ b/lib/db_key.cpp @@ -19,10 +19,6 @@ #include "XcaWarningCore.h" #include "PwDialogCore.h" -#warning drop UI dependencies -#include "widgets/ExportDialog.h" -#include "ui_ExportDialog.h" - db_key::db_key() : db_base("keys") { sqlHashTable = "public_keys"; @@ -188,16 +184,14 @@ pki_key *db_key::newKey(const keyjob &task, const QString &name) return key; } -void db_key::store(QModelIndex index) +int db_key::exportFlags(const QModelIndex &index) const { - QString title = tr("Export public key [%1]"); int disable_flags = 0; pki_key *key = fromIndex(index); - pki_evp *privkey = dynamic_cast(key); if (!index.isValid() || !key) - return; + return 0; int keytype = key->getKeyType(); if (keytype != EVP_PKEY_RSA && keytype != EVP_PKEY_DSA) @@ -212,57 +206,41 @@ void db_key::store(QModelIndex index) if (key->isPubKey() || key->isToken()) disable_flags |= F_PRIVATE; - ExportDialog *dlg = new ExportDialog(NULL, - title.arg(key->getTypeString()), - tr("Private Keys ( *.pem *.der *.pk8 );; " - "SSH Public Keys ( *.pub )"), key, - QPixmap(key->isToken() ? ":scardImg" : ":keyImg"), - pki_export::select(asym_key, disable_flags), "keyexport"); + return disable_flags; +} - if (!dlg->exec()) { - delete dlg; - return; - } - try { - const pki_export *xport = dlg->export_type(); - pki_base::pem_comment = dlg->pemComment->isChecked(); - XFile file(dlg->filename->text()); - const EVP_CIPHER *algo = NULL; - int(*pwCallback)(char *, int, int, void *) = NULL; +void db_key::exportItem(const QModelIndex &index, const pki_export *xport, + XFile &file) const +{ + const EVP_CIPHER *algo = NULL; + pki_key *key = fromIndex(index); + pki_evp *privkey = dynamic_cast(key); - if (xport->match_all(F_CRYPT)) { - algo = EVP_aes_256_cbc(); - pwCallback = PwDialogCore::pwCallback; - } - if (xport->match_all(F_PRIVATE)) - file.open_write(); - else - file.open_key(); + int(*pwCallback)(char *, int, int, void *) = NULL; - if (xport->match_all(F_DER | F_PRIVATE)) - privkey->writeKey(file, NULL, NULL, false); - else if (xport->match_all(F_PEM | F_PRIVATE)) - privkey->writeKey(file, algo, pwCallback, true); - else if (xport->match_all(F_DER)) - key->writePublic(file, false); - else if (xport->match_all(F_PEM)) - key->writePublic(file, true); - else if (xport->match_all(F_PKCS8)) - privkey->writePKCS8(file, algo, pwCallback, true); - else if (xport->match_all(F_SSH2 | F_PRIVATE)) - key->writeSSH2private(file, pwCallback); - else if (xport->match_all(F_SSH2)) - key->writeSSH2public(file); - else if (xport->match_all(F_PVK)) - privkey->writePVKprivate(file, pwCallback); - else - throw errorEx(tr("Internal error")); + if (xport->match_all(F_CRYPT)) { + algo = EVP_aes_256_cbc(); + pwCallback = PwDialogCore::pwCallback; } - catch (errorEx &err) { - XCA_ERROR(err); - } - pki_base::pem_comment = false; - delete dlg; + + if (privkey && xport->match_all(F_DER | F_PRIVATE)) + privkey->writeKey(file, NULL, NULL, false); + else if (privkey && xport->match_all(F_PEM | F_PRIVATE)) + privkey->writeKey(file, algo, pwCallback, true); + else if (xport->match_all(F_DER)) + key->writePublic(file, false); + else if (xport->match_all(F_PEM)) + key->writePublic(file, true); + else if (privkey && xport->match_all(F_PKCS8)) + privkey->writePKCS8(file, algo, pwCallback, true); + else if (xport->match_all(F_SSH2 | F_PRIVATE)) + key->writeSSH2private(file, pwCallback); + else if (xport->match_all(F_SSH2)) + key->writeSSH2public(file); + else if (privkey && xport->match_all(F_PVK)) + privkey->writePVKprivate(file, pwCallback); + else + throw errorEx(tr("Internal error")); } void db_key::setOwnPass(QModelIndex idx, enum pki_key::passType x) diff --git a/lib/db_key.h b/lib/db_key.h index 8a2a1c48..b5d5f4a1 100644 --- a/lib/db_key.h +++ b/lib/db_key.h @@ -11,6 +11,7 @@ #include "pki_export.h" #include "db_base.h" #include "pki_key.h" +#include "xfile.h" class QModelIndex; class QContextMenuEvent; @@ -32,9 +33,9 @@ class db_key: public db_base void setOwnPass(QModelIndex idx, enum pki_key::passType); void loadContainer(); pki_key *newKey(const keyjob &task, const QString &name); - - public slots: - void store(QModelIndex index); + int exportFlags(const QModelIndex &index) const; + void exportItem(const QModelIndex &index, + const pki_export *xport, XFile &file) const; signals: void delKey(pki_key *delkey); diff --git a/lib/db_temp.cpp b/lib/db_temp.cpp index 9dafc84d..49dacce7 100644 --- a/lib/db_temp.cpp +++ b/lib/db_temp.cpp @@ -7,16 +7,13 @@ #include "db_temp.h" +#include "pki_temp.h" +#include "load_obj.h" #include "func.h" #include "XcaWarningCore.h" #include #include -#warning drop UI dependencies -#include "widgets/NewX509.h" -#include "ui_NewX509.h" -#include - db_temp::db_temp() : db_x509name("templates") { /* XCA loads templates from private space ($HOME/.local/) @@ -107,28 +104,10 @@ bool db_temp::alterTemp(pki_temp *temp) return true; } -void db_temp::store(QModelIndex index) +void db_temp::exportItem(const QModelIndex &index, + const pki_export *, XFile &file) const { pki_temp *temp = fromIndex(index); - - if (!index.isValid() || !temp) - return; - - QString fn = Settings["workingdir"] + - temp->getUnderlinedName() + ".xca"; - QString s = QFileDialog::getSaveFileName(NULL, - tr("Save template as"), fn, - tr("XCA templates ( *.xca );; All files ( * )")); - if (s.isEmpty()) - return; - - update_workingdir(s); - try { - XFile file(s); - file.open_key(); + if (temp) temp->writeTemp(file); - } - catch (errorEx &err) { - XCA_ERROR(err); - } } diff --git a/lib/db_temp.h b/lib/db_temp.h index ee5cef5c..1a53b246 100644 --- a/lib/db_temp.h +++ b/lib/db_temp.h @@ -25,7 +25,8 @@ class db_temp: public db_x509name pki_base *newPKI(enum pki_type type = none); void fillContextMenu(QMenu *menu, const QModelIndex &index); QList getPredefs() const; - void store(QModelIndex index); bool alterTemp(pki_temp *temp); + void exportItem(const QModelIndex &index, + const pki_export *, XFile &file) const; }; #endif diff --git a/lib/db_x509.cpp b/lib/db_x509.cpp index 3b7b2b25..1729c1e7 100644 --- a/lib/db_x509.cpp +++ b/lib/db_x509.cpp @@ -24,7 +24,6 @@ #warning drop UI dependencies #include "widgets/CertExtend.h" -#include "widgets/ExportDialog.h" #include "widgets/RevocationList.h" #include "widgets/NewX509.h" #include "widgets/MainWindow.h" @@ -542,122 +541,93 @@ pki_x509 *db_x509::newCert(NewX509 *dlg) return cert; } -void db_x509::store(QModelIndex idx) -{ - QModelIndexList l; - l << idx; - store(l); -} - -void db_x509::store(QModelIndexList list) +int db_x509::exportFlags(const QModelIndex &idx) const { QStringList filt; - bool single = list.size() == 1;; int disable_flags = 0; - if (list.size() == 0) - return; - - pki_x509 *oldcrt = nullptr, *crt = fromIndex(list[0]); + pki_x509 *crt = fromIndex(idx); if (!crt) - return; + return 0; pki_key *privkey = crt->getRefKey(); - pki_evp *pkey; - if (!single || !crt->getSigner() || crt->getSigner() == crt) + if (!crt->getSigner() || crt->getSigner() == crt) disable_flags |= F_CHAIN; if (!privkey || !privkey->isPrivKey() || privkey->isToken()) disable_flags |= F_PRIVATE; - if (single) - disable_flags |= F_SELECT; - - if (!single || !crt->isCA()) + if (!crt->isCA()) disable_flags |= F_CA; - ExportDialog *dlg = new ExportDialog(NULL, tr("Certificate export"), - tr("X509 Certificates ( *.pem *.cer *.crt *.p12 *.pfx *.p7b )"), crt, - QPixmap(":certImg"), pki_export::select(x509, disable_flags), - "certexport"); - if (!dlg->exec()) { - delete dlg; - return; - } - QStringList vcal; - QList certs; - QList items; - try { - const pki_export *xport = dlg->export_type(); - XFile file(dlg->filename->text()); - file.open_write(); - pki_base::pem_comment = dlg->pemComment->isChecked(); + return disable_flags; +} - if (xport->match_all(F_PEM | F_CHAIN)) { - while (crt && crt != oldcrt) { - crt->writeCert(file, true); - oldcrt = crt; - crt = crt->getSigner(); - } - } else if (xport->match_all(F_PEM | F_SELECT)) { - foreach(QModelIndex idx, list) { - crt = fromIndex(idx); - if (crt) - crt->writeCert(file, true); - } - } else if (xport->match_all(F_PEM | F_UNREVOKED)) { - foreach(pki_x509 *pki, Store.getAll()) - if (!pki->isRevoked()) - pki->writeCert(file, true); - } else if (xport->match_all(F_PEM | F_ALL)) { - foreach(pki_x509 *pki, Store.getAll()) - pki->writeCert(file, true); - } else if (xport->match_all(F_PEM | F_PRIVATE)) { - pkey = (pki_evp *)crt->getRefKey(); - if (!pkey || pkey->isPubKey()) - throw errorEx(tr("There was no key found for the Certificate: '%1'"). - arg(crt->getIntName())); - if (pkey->isToken()) - throw errorEx(tr("Not possible for a token key: '%1'"). - arg(crt->getIntName())); - if (xport->match_all(F_PKCS8)) { - pkey->writePKCS8(file, EVP_des_ede3_cbc(), - PwDialogCore::pwCallback, true); - } else { - pkey->writeKey(file, NULL, NULL, true); - } - crt->writeCert(file, true); - } else if (xport->match_all(F_PEM)) { - crt->writeCert(file, true); - } else if (xport->match_all(F_DER)) { - crt->writeCert(file, false); - } else if (xport->match_all(F_PKCS7)) { - writePKCS7(crt, file, xport->flags, list); - } else if (xport->match_all(F_PKCS12)) { - writePKCS12(crt, file, xport->match_all(F_CHAIN)); - } else if (xport->match_all(F_INDEX)) { - foreach(QModelIndex idx, list) { - crt = fromIndex(idx); - if (crt) - certs << crt; - } - writeIndex(file, certs); - } else if (xport->match_all(F_CAL)) { - foreach(QModelIndex idx, list) { - crt = fromIndex(idx); - if (!crt) - continue; - vcal += xport->match_all(F_CHAIN) ? - crt->icsVEVENT_ca() : crt->icsVEVENT(); - } - writeVcalendar(file, vcal); - } - } catch (errorEx &err) { - XCA_ERROR(err); +void db_x509::exportItems(const QModelIndexList &list, + const pki_export *xport, XFile &file) const +{ + if (list.empty()) + return; + + pki_x509 *oldcrt = nullptr, *crt = fromIndex(list[0]); + + QList certs; + foreach(QModelIndex idx, list) { + pki_x509 *x = fromIndex(idx); + if (x) + certs << x; + } + + if (xport->match_all(F_PEM | F_CHAIN)) { + while (crt && crt != oldcrt) { + crt->writeCert(file, true); + oldcrt = crt; + crt = crt->getSigner(); + } + } else if (xport->match_all(F_PEM)) { + foreach(crt, certs) + crt->writeCert(file, true); + } else if (xport->match_all(F_PEM | F_UNREVOKED)) { + foreach(pki_x509 *pki, Store.getAll()) + if (!pki->isRevoked()) + pki->writeCert(file, true); + } else if (xport->match_all(F_PEM | F_ALL)) { + foreach(pki_x509 *pki, Store.getAll()) + pki->writeCert(file, true); + } else if (xport->match_all(F_PEM | F_PRIVATE)) { + pki_evp *pkey = (pki_evp *)crt->getRefKey(); + if (!pkey || pkey->isPubKey()) + throw errorEx(tr("There was no key found for the Certificate: '%1'"). + arg(crt->getIntName())); + if (pkey->isToken()) + throw errorEx(tr("Not possible for a token key: '%1'"). + arg(crt->getIntName())); + if (xport->match_all(F_PKCS8)) { + pkey->writePKCS8(file, EVP_des_ede3_cbc(), + PwDialogCore::pwCallback, true); + } else { + pkey->writeKey(file, NULL, NULL, true); + } + crt->writeCert(file, true); + } else if (xport->match_all(F_PEM)) { + crt->writeCert(file, true); + } else if (xport->match_all(F_DER)) { + crt->writeCert(file, false); + } else if (xport->match_all(F_PKCS7)) { + writePKCS7(crt, file, xport->flags, list); + } else if (xport->match_all(F_PKCS12)) { + writePKCS12(crt, file, xport->match_all(F_CHAIN)); + } else if (xport->match_all(F_INDEX)) { + writeIndex(file, certs); + } else if (xport->match_all(F_CAL)) { + QStringList vcal; + foreach(crt, certs) { + vcal += xport->match_all(F_CHAIN) ? + crt->icsVEVENT_ca() : crt->icsVEVENT(); + } + writeVcalendar(file, vcal); } - pki_base::pem_comment = false; - delete dlg; } void db_x509::writeIndex(XFile &file, QList items) const @@ -700,7 +670,7 @@ void db_x509::writePKCS12(pki_x509 *cert, XFile &file, bool chain) const } void db_x509::writePKCS7(pki_x509 *cert, XFile &file, int flags, - QModelIndexList list) const + const QModelIndexList &list) const { pki_pkcs7 *p7 = new pki_pkcs7(QString()); @@ -712,17 +682,17 @@ void db_x509::writePKCS7(pki_x509 *cert, XFile &file, int flags, break; cert = cert->getSigner(); } - } else if (flags & F_SELECT) { - foreach(QModelIndex idx, list) { - cert = fromIndex(idx); - if (cert) - p7->append_item(cert); - } } else if (flags & (F_UNREVOKED | F_ALL)) { foreach(pki_x509 *cer, Store.getAll()) { if ((flags & F_ALL) || !cer->isRevoked()) p7->append_item(cer); } + } else if (flags) { + foreach(QModelIndex idx, list) { + cert = fromIndex(idx); + if (cert) + p7->append_item(cert); + } } else { p7->append_item(cert); } diff --git a/lib/db_x509.h b/lib/db_x509.h index 668e9110..c5a6490d 100644 --- a/lib/db_x509.h +++ b/lib/db_x509.h @@ -48,20 +48,21 @@ class db_x509: public db_x509super void newCert(pki_x509 *cert); void writePKCS12(pki_x509 *cert, XFile &file, bool chain) const; void writePKCS7(pki_x509 *cert, XFile &file, int flags, - QModelIndexList list) const; + const QModelIndexList &list) const; void fillContextMenu(QMenu *menu, const QModelIndex &index); void inToCont(pki_base *pki); a1int getUniqueSerial(pki_x509 *signer); void toToken(QModelIndex idx, bool alwaysSelect); void toRequest(QModelIndex idx); - void store(QModelIndex idx); - void store(QModelIndexList list); void updateCaProperties(pki_x509 *cert); void toCertificate(QModelIndex index); void certRenewal(QModelIndexList indexes); void revoke(QModelIndexList indexes); void do_revoke(QModelIndexList indexes, const x509rev &r); void unRevoke(QModelIndexList indexes); + int exportFlags(const QModelIndex &idx) const; + void exportItems(const QModelIndexList &indexes, + const pki_export *xport, XFile &file) const; public slots: void newItem(); diff --git a/lib/db_x509req.cpp b/lib/db_x509req.cpp index 5296fec1..c9c92afc 100644 --- a/lib/db_x509req.cpp +++ b/lib/db_x509req.cpp @@ -13,7 +13,6 @@ #warning drop UI dependencies #include "widgets/NewX509.h" -#include "widgets/ExportDialog.h" db_x509req::db_x509req() : db_x509super("requests") { @@ -100,33 +99,12 @@ void db_x509req::newItem(pki_temp *temp, pki_x509req *orig) } } -void db_x509req::store(QModelIndex index) +void db_x509req::exportItem(const QModelIndex &index, + const pki_export *xport, XFile &file) const { pki_x509req *req = fromIndex(index); - if (!req) - return; - - ExportDialog *dlg = new ExportDialog(NULL, - tr("Certificate request export"), - tr("Certificate request ( *.pem *.der *.csr )"), - req, QPixmap(":csrImg"), - pki_export::select(x509_req, 0), "csrexport"); - if (!dlg->exec()) { - delete dlg; - return; - } - try { - const pki_export *xport = dlg->export_type(); - XFile file(dlg->filename->text()); - pki_base::pem_comment = dlg->pemComment->isChecked(); - file.open_write(); + if (req) req->writeReq(file, xport->match_all(F_PEM)); - } - catch (errorEx &err) { - XCA_ERROR(err); - } - pki_base::pem_comment = false; - delete dlg; } void db_x509req::setSigned(QModelIndex index, bool signe) diff --git a/lib/db_x509req.h b/lib/db_x509req.h index 32038949..c3a5955f 100644 --- a/lib/db_x509req.h +++ b/lib/db_x509req.h @@ -25,10 +25,11 @@ class db_x509req: public db_x509super pki_base* insert(pki_base *item); pki_base *newPKI(enum pki_type type = none); void fillContextMenu(QMenu *menu, const QModelIndex &index); - void store(QModelIndex index); QList getAllRequests(); void resetX509count(); void setSigned(QModelIndex index, bool signe); + void exportItem(const QModelIndex &index, + const pki_export *xport, XFile &file) const; public slots: void newItem(pki_temp *temp, pki_x509req *orig = NULL); diff --git a/lib/db_x509super.cpp b/lib/db_x509super.cpp index ba9f4082..d0a370ca 100644 --- a/lib/db_x509super.cpp +++ b/lib/db_x509super.cpp @@ -15,10 +15,7 @@ #include "widgets/XcaDialog.h" #include "XcaWarningCore.h" -#include "ui_CertDetail.h" - -#include -#include +#include db_x509name::db_x509name(const char *classname) :db_base(classname) @@ -152,20 +149,6 @@ void db_x509super::extractPubkey(QModelIndex index) XCA_INFO(key->getMsg(pki_base::msg_import).arg(pki->getIntName())); } -void db_x509super::toOpenssl(QModelIndex index) const -{ - pki_x509super *pki = fromIndex(index); - QString fn = Settings["workingdir"] + pki->getUnderlinedName() + ".conf"; - QString fname = QFileDialog::getSaveFileName(NULL, - tr("Save as OpenSSL config"), fn, - tr("Config files ( *.conf *.cnf);; All files ( * )")); - if (fname.isEmpty()) - return; - - update_workingdir(fname); - pki->opensslConf(fname); -} - void db_x509super::toTemplate(QModelIndex index) { db_temp *temps = Database.model(); diff --git a/lib/db_x509super.h b/lib/db_x509super.h index 53104be3..74d0d6c8 100644 --- a/lib/db_x509super.h +++ b/lib/db_x509super.h @@ -36,7 +36,6 @@ class db_x509super: public db_x509name QList findByPubKey(pki_key *refkey); void extractPubkey(QModelIndex index); void toTemplate(QModelIndex index); - void toOpenssl(QModelIndex index) const; }; #endif diff --git a/lib/digest.cpp b/lib/digest.cpp index 89920051..35d35428 100644 --- a/lib/digest.cpp +++ b/lib/digest.cpp @@ -21,13 +21,13 @@ digest::digest(int nid) : md_nid(nid) { } -digest::digest(const EVP_MD *md) : md_nid(NID_undef) +digest::digest(const EVP_MD *md) : md_nid(default_md) { if (!OBJ_find_sigid_algs(EVP_MD_type(md), &md_nid, NULL)) md_nid = EVP_MD_type(md); } -digest::digest(const QString &name) : md_nid(NID_undef) +digest::digest(const QString &name) : md_nid(default_md) { QString s(name); md_nid = OBJ_txt2nid(CCHAR(s.remove(QChar(' ')))); diff --git a/lib/pki_crl.h b/lib/pki_crl.h index 409f50ea..e805ae60 100644 --- a/lib/pki_crl.h +++ b/lib/pki_crl.h @@ -45,6 +45,7 @@ class crljob { crlNumber++; } + crljob() = delete; }; class pki_crl: public pki_x509name diff --git a/lib/pki_evp.cpp b/lib/pki_evp.cpp index d786ba4a..fac4f4df 100644 --- a/lib/pki_evp.cpp +++ b/lib/pki_evp.cpp @@ -669,7 +669,7 @@ bool pki_evp::pem(BioByteArray &b) { EVP_PKEY *pkey; int keytype; - const pki_export *xport = pki_export::default_key_format(); + const pki_export *xport = pki_export::by_id(Settings["KeyFormat"]); if (xport->match_all(F_PEM | F_PRIVATE)) { pkey = decryptKey(); diff --git a/lib/pki_export.cpp b/lib/pki_export.cpp index 12dbc4f4..c4111468 100644 --- a/lib/pki_export.cpp +++ b/lib/pki_export.cpp @@ -6,7 +6,6 @@ */ #include "pki_export.h" -#include "settings.h" pki_export::pki_export(int i, enum pki_type p, const QString &e, const QString &d, int f, const QString &h) @@ -40,47 +39,41 @@ const pki_export *pki_export::by_id(int id) return NULL; } -const pki_export *pki_export::default_key_format() -{ - return by_id(Settings["KeyFormat"]); -} - QList pki_export::elements { -new pki_export( 1, x509, "crt", "PEM", F_PEM | F_USUAL, tr("PEM Text format with headers")), -new pki_export( 2, x509, "pem", tr("PEM chain"), F_PEM | F_USUAL | F_CHAIN, tr("Concatenated text format of the complete certificate chain in one PEM file")), -new pki_export( 3, x509, "pem", tr("PEM selected"), F_PEM | F_USUAL | F_SELECT, tr("Concatenated list of all selected items in one PEM text file")), -new pki_export( 4, x509, "pem", tr("PEM unrevoked"), F_PEM | F_UNREVOKED, tr("Concatenated text format of all unrevoked certificates in one PEM file")), -new pki_export( 5, x509, "pem", tr("PEM all"), F_PEM | F_MULTI | F_ALL, tr("Concatenated text format of all certificates in one PEM file")), -new pki_export( 6, x509, "pem", tr("PEM + key"), F_PEM | F_PLUSKEY | F_PRIVATE, tr("Concatenation of the certificate and the unencrypted private key in one PEM file")), +new pki_export( 1, x509, "crt", "PEM", F_PEM | F_USUAL | F_SINGLE, tr("PEM Text format with headers")), +new pki_export( 3, x509, "pem", "PEM", F_PEM | F_MULTI, tr("Concatenated list of all selected items in one PEM text file")), +new pki_export( 2, x509, "pem", tr("PEM chain"), F_PEM | F_USUAL | F_CHAIN | F_SINGLE, tr("Concatenated text format of the complete certificate chain in one PEM file")), +new pki_export( 6, x509, "pem", tr("PEM + key"), F_PEM | F_PLUSKEY | F_PRIVATE| F_SINGLE,tr("Concatenation of the certificate and the unencrypted private key in one PEM file")), new pki_export( 7, x509, "pem", "PEM + PKCS#8", F_PEM | F_PKCS8 | F_PRIVATE | F_CRYPT, tr("Concatenation of the certificate and the encrypted private key in PKCS#8 format in one file")), -new pki_export( 8, x509, "p7b", "PKCS #7", F_PKCS7 | F_USUAL, tr("PKCS#7 encoded single certificate")), -new pki_export( 9, x509, "p7b", tr("PKCS #7 all"), F_PKCS7 | F_USUAL | F_MULTI | F_ALL, tr("All selected certificates encoded in one PKCS#7 file")), -new pki_export(10, x509, "p7b", tr("PKCS #7 selected"), F_PKCS7 | F_USUAL | F_MULTI | F_SELECT, tr("All selected certificates encoded in one PKCS#7 file")), -new pki_export(11, x509, "p7b", tr("PKCS #7 unrevoked"), F_PKCS7 | F_MULTI | F_UNREVOKED, tr("All unrevoked certificates encoded in one PKCS#7 file")), -new pki_export(12, x509, "p7b", tr("PKCS #7 chain"), F_PKCS7 | F_USUAL | F_CHAIN, tr("PKCS#7 encoded complete certificate chain")), -new pki_export(13, x509, "cer", "DER", F_DER, tr("Binary DER encoded certificate")), -new pki_export(14, x509, "pfx", tr("PKCS #12 chain"),F_PKCS12 | F_USUAL | F_CHAIN | F_CRYPT | F_PRIVATE, tr("The complete certificate chain and the private key as encrypted PKCS#12 file")), -new pki_export(15, x509, "pfx", tr("PKCS #12"), F_PKCS12 | F_USUAL | F_CRYPT | F_PRIVATE, tr("The certificate and the private key as encrypted PKCS#12 file")), -new pki_export(16, x509, "txt", tr("Certificate Index file"), F_INDEX | F_CA, tr("OpenSSL specific Certificate Index file as created by the 'ca' command and required by the OCSP tool")), -new pki_export(17, x509, "ics", tr("vCalendar"), F_CAL, tr("vCalendar expiry reminder for the selected items")), -new pki_export(18, x509, "ics", tr("CA vCalendar"), F_CAL | F_CA, tr("vCalendar expiry reminder containing all issued, valid certificates, the CA itself and the latest CRL")), +new pki_export( 8, x509, "p7b", "PKCS #7", F_PKCS7 | F_USUAL | F_SINGLE, tr("PKCS#7 encoded single certificate")), +new pki_export(10, x509, "p7b", "PKCS #7", F_PKCS7 | F_USUAL | F_MULTI, tr("All selected certificates encoded in one PKCS#7 file")), +new pki_export(12, x509, "p7b", tr("PKCS #7 chain"), F_PKCS7 | F_USUAL | F_CHAIN | F_SINGLE, tr("PKCS#7 encoded complete certificate chain")), +new pki_export(13, x509, "cer", "DER", F_DER | F_SINGLE, tr("Binary DER encoded certificate")), +new pki_export(14, x509, "pfx", tr("PKCS #12 chain"),F_PKCS12 | F_USUAL | F_CHAIN | F_CRYPT | F_PRIVATE | F_SINGLE, tr("The complete certificate chain and the private key as encrypted PKCS#12 file")), +new pki_export(15, x509, "pfx", tr("PKCS #12"), F_PKCS12 | F_USUAL | F_CRYPT | F_PRIVATE | F_SINGLE, tr("The certificate and the private key as encrypted PKCS#12 file")), +new pki_export(16, x509, "txt", tr("Certificate Index file"), F_INDEX | F_CA, tr("OpenSSL specific Certificate Index file as created by the 'ca' command and required by the OCSP tool")), +new pki_export(17, x509, "ics", tr("vCalendar"), F_CAL, tr("vCalendar expiry reminder for the selected items")), +new pki_export(18, x509, "ics", tr("CA vCalendar"), F_CAL | F_CA, tr("vCalendar expiry reminder containing all issued, valid certificates, the CA itself and the latest CRL")), -new pki_export(19, asym_key, "pem", tr("PEM public"), F_PEM | F_CLIPBOARD, tr("Text format of the public key in one PEM file")), -new pki_export(20, asym_key, "pem", tr("PEM private"), F_PEM | F_PRIVATE | F_USUAL | F_CLIPBOARD, tr("Unencrypted private key in text format")), -new pki_export(21, asym_key, "pem", tr("PEM encrypted"), F_PEM | F_PRIVATE | F_CRYPT | F_CLIPBOARD, tr("OpenSSL specific encrypted private key in text format")), -new pki_export(22, asym_key, "priv",tr("SSH2 private"), F_PEM | F_PRIVATE | F_SSH2, tr("Unencrypted private key in text format")), -new pki_export(23, asym_key, "pub" ,tr("SSH2 public"), F_SSH2, tr("The public key encoded in SSH2 format")), -new pki_export(24, asym_key, "der", tr("DER public"), F_DER, tr("Binary DER format of the public key")), -new pki_export(25, asym_key, "der", tr("DER private"), F_DER | F_PRIVATE, tr("Unencrypted private key in binary DER format")), -new pki_export(26, asym_key, "pvk", tr("PVK private"), F_PVK | F_PRIVATE, tr("Private key in Microsoft PVK format not encrypted")), -new pki_export(27, asym_key, "pvk", tr("PVK encrypted"), F_PVK | F_PRIVATE | F_CRYPT, tr("Encrypted private key in Microsoft PVK format")), -new pki_export(28, asym_key, "pk8", tr("PKCS #8 encrypted"), F_PKCS8 | F_PRIVATE | F_CRYPT | F_USUAL | F_CLIPBOARD, tr("Encrypted private key in PKCS#8 text format")), -new pki_export(29, asym_key, "pk8", tr("PKCS #8"), F_PKCS8 | F_PRIVATE | F_CLIPBOARD, tr("Unencrypted private key in PKCS#8 text format")), +new pki_export(19, asym_key, "pem", tr("PEM public"), F_PEM | F_CLIPBOARD, tr("Text format of the public key in one PEM file")), +new pki_export(20, asym_key, "pem", tr("PEM private"), F_PEM | F_PRIVATE | F_USUAL | F_CLIPBOARD, tr("Unencrypted private key in text format")), +new pki_export(21, asym_key, "pem", tr("PEM encrypted"), F_PEM | F_PRIVATE | F_CRYPT | F_SINGLE, tr("OpenSSL specific encrypted private key in text format")), +new pki_export(22, asym_key, "priv",tr("SSH2 private"), F_PEM | F_PRIVATE | F_SSH2 | F_SINGLE, tr("Unencrypted private key in text format")), +new pki_export(23, asym_key, "pub" ,tr("SSH2 public"), F_SSH2, tr("The public key encoded in SSH2 format")), +new pki_export(24, asym_key, "der", tr("DER public"), F_DER | F_SINGLE, tr("Binary DER format of the public key")), +new pki_export(25, asym_key, "der", tr("DER private"), F_DER | F_PRIVATE | F_SINGLE, tr("Unencrypted private key in binary DER format")), +new pki_export(26, asym_key, "pvk", tr("PVK private"), F_PVK | F_PRIVATE | F_SINGLE, tr("Private key in Microsoft PVK format not encrypted")), +new pki_export(27, asym_key, "pvk", tr("PVK encrypted"), F_PVK | F_PRIVATE | F_CRYPT | F_SINGLE, tr("Encrypted private key in Microsoft PVK format")), +new pki_export(28, asym_key, "pk8", tr("PKCS #8 encrypted"), F_PKCS8 | F_PRIVATE | F_CRYPT | F_USUAL | F_SINGLE, tr("Encrypted private key in PKCS#8 text format")), +new pki_export(29, asym_key, "pk8", tr("PKCS #8"), F_PKCS8 | F_PRIVATE | F_CLIPBOARD | F_SINGLE, tr("Unencrypted private key in PKCS#8 text format")), -new pki_export(30, x509_req, "csr", "PEM", F_PEM, tr("PEM Text format with headers")), -new pki_export(31, x509_req, "der", "DER", F_DER, tr("Binary DER format of the certificate request")), +new pki_export(30, x509_req, "csr", "PEM", F_PEM, tr("PEM Text format with headers")), +new pki_export(31, x509_req, "der", "DER", F_DER | F_SINGLE, tr("Binary DER format of the certificate request")), -new pki_export(32, revocation, "pem", "PEM", F_PEM, tr("PEM Text format with headers")), -new pki_export(33, revocation, "der", "DER", F_DER, tr("Binary DER format of the revocation list")), -new pki_export(34, revocation, "ics", tr("vCalendar"), F_CAL, tr("vCalendar reminder for the CRL expiry date")), +new pki_export(32, revocation, "crl", "PEM", F_PEM, tr("PEM Text format with headers")), +new pki_export(33, revocation, "der", "DER", F_DER | F_SINGLE, tr("Binary DER format of the revocation list")), +new pki_export(34, revocation, "ics", tr("vCalendar"), F_CAL, tr("vCalendar reminder for the CRL expiry date")), + +new pki_export(35, tmpl, "xca", "PEM", F_PEM | F_SINGLE, tr("XCA template in PEM-like format")), +new pki_export(35, tmpl, "pem", "PEM", F_PEM | F_MULTI, tr("All selected XCA templates in PEM-like format")), }; diff --git a/lib/pki_export.h b/lib/pki_export.h index 85f9704a..4a96ba01 100644 --- a/lib/pki_export.h +++ b/lib/pki_export.h @@ -14,6 +14,7 @@ #include #define BIT(n) (1< select(enum pki_type, int); - static const pki_export *default_key_format(); static const pki_export *by_id(int id); bool match_all(int match_flags) const; diff --git a/lib/pki_key.cpp b/lib/pki_key.cpp index dd9333e4..14406602 100644 --- a/lib/pki_key.cpp +++ b/lib/pki_key.cpp @@ -125,7 +125,7 @@ void pki_key::write_SSH2_ed25519_private(BIO *b, bool pki_key::pem(BioByteArray &b) { - const pki_export *xport = pki_export::default_key_format(); + const pki_export *xport = pki_export::by_id(Settings["KeyFormat"]); if (xport->match_all(F_PRIVATE)) return false; diff --git a/lib/pki_scard.cpp b/lib/pki_scard.cpp index b1582ac5..a69470eb 100644 --- a/lib/pki_scard.cpp +++ b/lib/pki_scard.cpp @@ -18,10 +18,7 @@ #include "XcaWarningCore.h" -#warning Drop "widgets dependency" - #include -#include void pki_scard::init(void) { diff --git a/lib/settings.cpp b/lib/settings.cpp index 4493de3b..86c3be1b 100644 --- a/lib/settings.cpp +++ b/lib/settings.cpp @@ -3,6 +3,7 @@ #include "sql.h" #include "pki_key.h" #include "digest.h" +#include "pki_export.h" #include #include @@ -38,7 +39,7 @@ settings::settings() defaul["serial_len"] = "64"; defaul["fp_separator"] = ":"; defaul["fp_digits"] = "2"; - defaul["KeyFormat"] = "19"; // PEM public + defaul["KeyFormat"] = QString::number(DEFAULT_KEY_CLIPBOARD_TYPE); hostspecific << "pkcs11path" << "workingdir" << "mw_geometry"; } diff --git a/ui/MainWindow.ui b/ui/MainWindow.ui index e2c75ec5..5fb6bb24 100644 --- a/ui/MainWindow.ui +++ b/ui/MainWindow.ui @@ -525,7 +525,7 @@ newItem() load() - storeItems() + exportItems() showItems() deleteItems() @@ -599,7 +599,7 @@ BNexportKey clicked() keyView - storeItems() + exportItems() 526 @@ -663,7 +663,7 @@ BNexportReq clicked() reqView - storeItems() + exportItems() 489 @@ -743,7 +743,7 @@ BNexportCert clicked() certView - storeItems() + exportItems() 499 @@ -871,7 +871,7 @@ BNexportTemp clicked() tempView - storeItems() + exportItems() 488 @@ -887,7 +887,7 @@ BNexportCrl clicked() crlView - storeItems() + exportItems() 472 diff --git a/widgets/CertTreeView.cpp b/widgets/CertTreeView.cpp index 7a889809..040c584c 100644 --- a/widgets/CertTreeView.cpp +++ b/widgets/CertTreeView.cpp @@ -11,9 +11,11 @@ #include "XcaDialog.h" #include "MainWindow.h" #include "RevocationList.h" +#include "ExportDialog.h" #include "NewCrl.h" #include "lib/database_model.h" #include "lib/db_crl.h" +#include "lib/load_obj.h" #include #include @@ -232,3 +234,13 @@ void CertTreeView::load() load_cert c; load_default(&c); } + +ExportDialog *CertTreeView::exportDialog(const QModelIndexList &indexes) +{ + return new ExportDialog(this, + tr("Certificate export"), + tr("X509 Certificates ( *.pem *.cer *.crt *.p12 *.pfx *.p7b )"), + indexes, QPixmap(":certImg"), + pki_export::select(x509, basemodel->exportFlags(indexes)), + "certexport"); +} diff --git a/widgets/CertTreeView.h b/widgets/CertTreeView.h index 33c91145..a89386cc 100644 --- a/widgets/CertTreeView.h +++ b/widgets/CertTreeView.h @@ -24,6 +24,7 @@ class CertTreeView: public X509SuperTreeView CertTreeView(QWidget *parent) : X509SuperTreeView(parent) { } void fillContextMenu(QMenu *menu, QMenu *subExport, const QModelIndex &index, QModelIndexList indexes); + ExportDialog *exportDialog(const QModelIndexList &index); public slots: void changeView(); diff --git a/widgets/CrlTreeView.cpp b/widgets/CrlTreeView.cpp index 439ebe23..d7a86b03 100644 --- a/widgets/CrlTreeView.cpp +++ b/widgets/CrlTreeView.cpp @@ -12,9 +12,11 @@ #include "MainWindow.h" #include "ItemCombo.h" #include "XcaWarning.h" +#include "ExportDialog.h" #include "lib/db_crl.h" #include "lib/pki_x509.h" #include "lib/database_model.h" +#include "lib/load_obj.h" void CrlTreeView::showPki(pki_base *pki) { @@ -60,3 +62,11 @@ void CrlTreeView::load() load_crl l; load_default(&l); } + +ExportDialog *CrlTreeView::exportDialog(const QModelIndexList &indexes) +{ + return new ExportDialog(this, + tr("Revocation list export"), + tr("CRL ( *.pem *.der *.crl )"), indexes, QPixmap(":revImg"), + pki_export::select(revocation, basemodel->exportFlags(indexes))); +} diff --git a/widgets/CrlTreeView.h b/widgets/CrlTreeView.h index 699dd232..8c5c0607 100644 --- a/widgets/CrlTreeView.h +++ b/widgets/CrlTreeView.h @@ -25,6 +25,7 @@ class CrlTreeView: public XcaTreeView public: CrlTreeView(QWidget *parent) : XcaTreeView(parent) { } void showPki(pki_base *pki); + ExportDialog *exportDialog(const QModelIndexList &index); public slots: void newItem(pki_x509 *cert); diff --git a/widgets/ExportDialog.cpp b/widgets/ExportDialog.cpp index 71450c2c..f9aa64bf 100644 --- a/widgets/ExportDialog.cpp +++ b/widgets/ExportDialog.cpp @@ -20,25 +20,31 @@ #include ExportDialog::ExportDialog(QWidget *w, const QString &title, - const QString &filt, pki_base *pki, const QPixmap &img, - QList types, const QString &help_ctx) + const QString &filt, const QModelIndexList &indexes, + const QPixmap &img, QList types, + const QString &help_ctx) : QDialog(w ? w : mainwin) { QList usual, normal; + QString fname = "selected_items"; setupUi(this); setWindowTitle(XCA_TITLE); - if (pki) - descr->setText(pki->getIntName()); + if (indexes.size() == 1) { + pki_base *pki = db_base::fromIndex(indexes[0]); + if (pki) { + descr->setText(pki->getIntName()); + fname = pki->getUnderlinedName(); + } + } descr->setReadOnly(true); image->setPixmap(img); label->setText(title); mainwin->helpdlg->register_ctxhelp_button(this, help_ctx); - if (pki) { - QString fn = Settings["workingdir"] + - pki->getUnderlinedName() + "." + types[0]->extension; - filename->setText(nativeSeparator(fn)); - } + QString fn = Settings["workingdir"] + + fname + "." + types[0]->extension; + filename->setText(nativeSeparator(fn)); + filter = filt + ";;" + tr("All files ( * )"); foreach(const pki_export *t, types) { @@ -58,6 +64,11 @@ ExportDialog::ExportDialog(QWidget *w, const QString &title, on_exportFormat_highlighted(0); } +ExportDialog::~ExportDialog() +{ + pki_base::pem_comment = 0; +} + void ExportDialog::on_fileBut_clicked() { QString s = QFileDialog::getSaveFileName(this, QString(), @@ -102,6 +113,7 @@ bool ExportDialog::mayWriteFile(const QString &fname) void ExportDialog::accept() { QString fn = filename->text(); + pki_base::pem_comment = pemComment->isChecked(); if (!filename->isEnabled()) { QDialog::accept(); diff --git a/widgets/ExportDialog.h b/widgets/ExportDialog.h index 58a783fb..1a7b2715 100644 --- a/widgets/ExportDialog.h +++ b/widgets/ExportDialog.h @@ -10,6 +10,7 @@ #include "ui_ExportDialog.h" #include "lib/pki_export.h" +#include class QPixmap; class pki_base; @@ -23,9 +24,10 @@ class ExportDialog: public QDialog, public Ui::ExportDialog public: ExportDialog(QWidget *w, const QString &title, const QString &filt, - pki_base *pki, const QPixmap &img, + const QModelIndexList &indexes, const QPixmap &img, QList types, const QString &help_ctx = QString()); + ~ExportDialog(); static bool mayWriteFile(const QString &fname); const pki_export *export_type(int idx = -1) const; diff --git a/widgets/KeyTreeView.cpp b/widgets/KeyTreeView.cpp index e09a5743..2eb08bd2 100644 --- a/widgets/KeyTreeView.cpp +++ b/widgets/KeyTreeView.cpp @@ -6,10 +6,12 @@ */ #include "lib/pki_scard.h" +#include "lib/load_obj.h" #include "KeyTreeView.h" #include "MainWindow.h" #include "KeyDetail.h" #include "NewKey.h" +#include "ExportDialog.h" #include "XcaWarning.h" #include #include @@ -209,9 +211,6 @@ void KeyTreeView::newItem(const QString &name) void KeyTreeView::clipboardFormat(QAction *a) { - qWarning("pki_key::default_export_type: %d %d\n", - (int)Settings["KeyFormat"], a->data().toInt()); - Settings["KeyFormat"] = a->data().toInt(); } @@ -220,3 +219,17 @@ void KeyTreeView::load(void) load_key l; load_default(&l); } + +ExportDialog *KeyTreeView::exportDialog(const QModelIndexList &indexes) +{ + if (indexes.size() == 0) + return NULL; + pki_key *key = db_base::fromIndex(indexes[0]); + return new ExportDialog(this, + tr("Export public key [%1]").arg(key->getTypeString()), + tr("Private Keys ( *.pem *.der *.pk8 );; " + "SSH Public Keys ( *.pub )"), indexes, + QPixmap(key->isToken() ? ":scardImg" : ":keyImg"), + pki_export::select(asym_key, basemodel->exportFlags(indexes)), + "keyexport"); +} diff --git a/widgets/KeyTreeView.h b/widgets/KeyTreeView.h index ca6afe47..d822ed72 100644 --- a/widgets/KeyTreeView.h +++ b/widgets/KeyTreeView.h @@ -26,6 +26,7 @@ class KeyTreeView: public XcaTreeView void fillContextMenu(QMenu *menu, QMenu *subExport, const QModelIndex &index, QModelIndexList indexes); void showPki(pki_base *pki); + ExportDialog *exportDialog(const QModelIndexList &indexes); public slots: void resetOwnPass(); diff --git a/widgets/MainWindow.cpp b/widgets/MainWindow.cpp index f0c4b239..9a47ddc8 100644 --- a/widgets/MainWindow.cpp +++ b/widgets/MainWindow.cpp @@ -35,6 +35,7 @@ #include "lib/pki_multi.h" #include "lib/pki_scard.h" #include "lib/dhgen.h" +#include "lib/load_obj.h" #include "XcaDialog.h" #include "XcaWarning.h" diff --git a/widgets/Options.cpp b/widgets/Options.cpp index aa3e250f..6317c0a5 100644 --- a/widgets/Options.cpp +++ b/widgets/Options.cpp @@ -6,6 +6,7 @@ */ #include "lib/func.h" +#include "lib/load_obj.h" #include "Options.h" #include "SearchPkcs11.h" #include "XcaWarning.h" diff --git a/widgets/ReqTreeView.cpp b/widgets/ReqTreeView.cpp index 6135fcc0..ff5c806e 100644 --- a/widgets/ReqTreeView.cpp +++ b/widgets/ReqTreeView.cpp @@ -6,8 +6,10 @@ */ #include "lib/pki_x509req.h" +#include "lib/load_obj.h" #include "ReqTreeView.h" #include "MainWindow.h" +#include "ExportDialog.h" #include #include #include @@ -66,3 +68,13 @@ void ReqTreeView::load(void) load_req l; load_default(&l); } + +ExportDialog *ReqTreeView::exportDialog(const QModelIndexList &indexes) +{ + return new ExportDialog(this, + tr("Certificate request export"), + tr("Certificate request ( *.pem *.der *.csr )"), + indexes, QPixmap(":csrImg"), + pki_export::select(x509_req, basemodel->exportFlags(indexes)), + "csrexport"); +} diff --git a/widgets/ReqTreeView.h b/widgets/ReqTreeView.h index 242d6eb1..41a6aa14 100644 --- a/widgets/ReqTreeView.h +++ b/widgets/ReqTreeView.h @@ -24,6 +24,7 @@ class ReqTreeView: public X509SuperTreeView ReqTreeView(QWidget *parent) : X509SuperTreeView(parent) { } void fillContextMenu(QMenu *menu, QMenu *subExport, const QModelIndex &index, QModelIndexList indexes); + ExportDialog *exportDialog(const QModelIndexList &indexes); public slots: void toRequest(); diff --git a/widgets/TempTreeView.cpp b/widgets/TempTreeView.cpp index 8d55dda3..d9a190d4 100644 --- a/widgets/TempTreeView.cpp +++ b/widgets/TempTreeView.cpp @@ -6,7 +6,9 @@ */ #include "lib/pki_temp.h" +#include "lib/load_obj.h" #include "TempTreeView.h" +#include "ExportDialog.h" #include "NewX509.h" #include "XcaDialog.h" #include "MainWindow.h" @@ -113,3 +115,13 @@ void TempTreeView::load() load_temp l; load_default(&l); } + +ExportDialog *TempTreeView::exportDialog(const QModelIndexList &indexes) +{ + return new ExportDialog(this, + tr("Template export"), + tr("XCA Templates ( *.xca )"), + indexes, QPixmap(":tempImg"), + pki_export::select(tmpl, basemodel->exportFlags(indexes)), + "templateexport"); +} diff --git a/widgets/TempTreeView.h b/widgets/TempTreeView.h index 0147ed7e..99933d44 100644 --- a/widgets/TempTreeView.h +++ b/widgets/TempTreeView.h @@ -28,6 +28,7 @@ class TempTreeView: public XcaTreeView const QModelIndex &index, QModelIndexList indexes); void showPki(pki_base *pki); bool alterTemp(pki_temp *temp); + ExportDialog *exportDialog(const QModelIndexList &index); public slots: void certFromTemp(); diff --git a/widgets/X509SuperTreeView.cpp b/widgets/X509SuperTreeView.cpp index 9e0d53da..b95793d0 100644 --- a/widgets/X509SuperTreeView.cpp +++ b/widgets/X509SuperTreeView.cpp @@ -13,6 +13,7 @@ #include #include +#include #include void X509SuperTreeView::fillContextMenu(QMenu *menu, QMenu *subExport, @@ -52,8 +53,19 @@ void X509SuperTreeView::toOpenssl() { QModelIndex idx = currentIndex(); - if (idx.isValid() && basemodel) - x509super()->toOpenssl(idx); + if (!idx.isValid() || !basemodel) + return; + + pki_x509super *pki = db_base::fromIndex(idx); + QString fn = Settings["workingdir"] + pki->getUnderlinedName() + ".conf"; + QString fname = QFileDialog::getSaveFileName(NULL, + tr("Save as OpenSSL config"), fn, + tr("Config files ( *.conf *.cnf);; All files ( * )")); + if (fname.isEmpty()) + return; + + update_workingdir(fname); + pki->opensslConf(fname); } diff --git a/widgets/XcaDialog.h b/widgets/XcaDialog.h index 8efedde5..00e96388 100644 --- a/widgets/XcaDialog.h +++ b/widgets/XcaDialog.h @@ -5,8 +5,8 @@ * All rights reserved. */ -#ifndef __XCADIALOG_H -#define __XCADIALOG_H +#ifndef __XCADIALOG_H__ +#define __XCADIALOG_H__ #include #include "ui_XcaDialog.h" diff --git a/widgets/XcaTreeView.cpp b/widgets/XcaTreeView.cpp index ced2d421..48ed5c16 100644 --- a/widgets/XcaTreeView.cpp +++ b/widgets/XcaTreeView.cpp @@ -22,7 +22,9 @@ #include "XcaWarning.h" #include "XcaDialog.h" #include "XcaApplication.h" +#include "ExportDialog.h" #include "ImportMulti.h" +#include "lib/load_obj.h" #include "ui_ItemProperties.h" @@ -245,51 +247,9 @@ void XcaTreeView::deleteItems() TransCommit(); } -void XcaTreeView::storeItems() +void XcaTreeView::exportItems() { - storeItems(getSelectedIndexes()); -} - -void XcaTreeView::storeItems(QModelIndexList indexes) -{ - if (!basemodel || indexes.size() == 0) - return; - try { - if (indexes.size() == 1) { - basemodel->store(indexes[0]); - return; - } - - xcaWarningBox msg(NULL, - tr("How to export the %1 selected items"). - arg(indexes.size())); - msg.addButton(QMessageBox::Ok, tr("All in one PEM file")); - msg.addButton(QMessageBox::Apply, tr("Each item in one file")); - msg.addButton(QMessageBox::Cancel); - int ret = msg.exec(); - if (ret == QMessageBox::Apply) { - foreach(QModelIndex i, indexes) - basemodel->store(i); - return; - } else if (ret != QMessageBox::Ok) { - return; - } - - QString s = QFileDialog::getSaveFileName(NULL, - tr("Save %1 items in one file as").arg(indexes.size()), - Settings["workingdir"] + "export.pem", - tr("PEM files ( *.pem );; All files ( * )")); - if (s.isEmpty()) - return; - - update_workingdir(s); - QString pem = basemodel->pem2QString(indexes); - XFile file(s); - file.open_write(); - file.write(pem.toLatin1()); - } catch (errorEx &err) { - XCA_ERROR(err); - } + exportItems(getSelectedIndexes()); } void XcaTreeView::showItems() @@ -497,6 +457,36 @@ void XcaTreeView::changeView() show(); } +void XcaTreeView::exportItems(const QModelIndexList &indexes) +{ + if (!basemodel || indexes.empty()) + return; + + ExportDialog *dlg = exportDialog(indexes); + + if (dlg && dlg->exec()) { + try { + const pki_export *xport = dlg->export_type(); + XFile file(dlg->filename->text()); + + if (xport->match_all(F_PRIVATE)) + file.open_key(); + else + file.open_write(); + + basemodel->exportItems(indexes, xport, file); + } catch (errorEx &err) { + XCA_ERROR(err); + } + } + delete dlg; +} + +ExportDialog *XcaTreeView::exportDialog(const QModelIndexList &indexes) +{ + return NULL; +} + void XcaTreeView::showContextMenu(QContextMenuEvent *e, const QModelIndex &idx) { @@ -521,7 +511,7 @@ void XcaTreeView::showContextMenu(QContextMenuEvent *e, subExport = menu->addMenu(tr("Export")); subExport->addAction(tr("Clipboard"), this, SLOT(pem2clipboard()), QKeySequence::Copy); - subExport->addAction(tr("File"), this, SLOT(storeItems()), + subExport->addAction(tr("File"), this, SLOT(exportItems()), QKeySequence::Save); } @@ -550,7 +540,7 @@ void XcaTreeView::keyPressEvent(QKeyEvent *event) return; } if (event->matches(QKeySequence::Save)) { - storeItems(); + exportItems(); return; } if (event->matches(QKeySequence::Copy)) { diff --git a/widgets/XcaTreeView.h b/widgets/XcaTreeView.h index b21ffbbd..7e58a18d 100644 --- a/widgets/XcaTreeView.h +++ b/widgets/XcaTreeView.h @@ -23,6 +23,7 @@ class QKeyEvent; class QContextMenuEvent; class QMenu; class load_base; +class ExportDialog; class XcaTreeView: public QTreeView { @@ -58,8 +59,9 @@ class XcaTreeView: public QTreeView QMenu *parent = NULL, int sect = -1); void keyPressEvent(QKeyEvent *event); virtual void showPki(pki_base *) {}; - virtual void storeItems(QModelIndexList indexes); + virtual void exportItems(const QModelIndexList &indexes); virtual void load_default(load_base *load); + virtual ExportDialog *exportDialog(const QModelIndexList &indexes); public slots: void changeView(); @@ -69,7 +71,7 @@ class XcaTreeView: public QTreeView void editIdx(); void setFilter(const QString &pattern); void deleteItems(); - void storeItems(); + void exportItems(); void showItems(); void newItem(); void doubleClick(const QModelIndex &m); diff --git a/widgets/hashBox.cpp b/widgets/hashBox.cpp index 094bd6ad..dcab6bd5 100644 --- a/widgets/hashBox.cpp +++ b/widgets/hashBox.cpp @@ -13,7 +13,6 @@ hashBox::hashBox(QWidget *parent) :QComboBox(parent) { setupAllHashes(); - setDefaultHash(); } const digest hashBox::current() const @@ -45,7 +44,10 @@ void hashBox::setupHashes(QList nids) } setEnabled(count() > 0); setDefaultHash(); - setCurrent(digest(md)); + if (!md.isEmpty()) + setCurrent(digest(md)); + else + setDefaultHash(); } void hashBox::setupAllHashes()