Close #384: Quick view of certificates without trying to open XCA

The ImportMulti dialog does not show up if there is only
one item to display, but the item is displayed directly.

The displayed items have a new "Import" button to import
directly from the viewed item.

If XCA is called with certs, crls, keys etc. from the commandline
XCA only displays and optionally imports the item if a default
database is given. Afterwards XCA exits.
This commit is contained in:
Christian Hohnstaedt 2023-10-05 20:24:08 +02:00
parent ec9dd9ac18
commit 2333b02ddc
18 changed files with 242 additions and 136 deletions

View File

@ -518,35 +518,34 @@ Qt::ItemFlags db_base::flags(const QModelIndex &index) const
bool db_base::setData(const QModelIndex &index, const QVariant &value, int role)
{
QString on, nn;
QString newname;
pki_base *item;
if (index.isValid() && role == Qt::EditRole) {
nn = value.toString();
newname = value.toString();
item = fromIndex(index);
on = item->getIntName();
if (nn == on)
if (newname == item->getIntName())
return true;
updateItem(item, nn, item->getComment());
item->setIntName(newname);
updateItem(item);
return true;
}
return false;
}
void db_base::updateItem(pki_base *pki, const QString &name,
const QString &comment, bool force)
void db_base::updateItem(pki_base *pki)
{
XSqlQuery q;
QSqlError e;
if (name == pki->getIntName() && comment == pki->getComment() && !force)
if (!pki->getSqlItemId().isValid())
return;
Transaction;
TransThrow();
SQL_PREPARE(q, "UPDATE items SET name=?, comment=? WHERE id=?");
q.bindValue(0, name);
q.bindValue(1, comment);
q.bindValue(0, pki->getIntName());
q.bindValue(1, pki->getComment());
q.bindValue(2, pki->getSqlItemId());
q.exec();
e = q.lastError();
@ -554,8 +553,6 @@ void db_base::updateItem(pki_base *pki, const QString &name,
XCA_SQLERROR(e);
TransDone(e);
pki->setIntName(name);
pki->setComment(comment);
pki->recheckVisibility();
QModelIndex i, j;

View File

@ -48,8 +48,7 @@ class db_base: public QAbstractItemModel
public:
void restart_timer();
void updateItem(pki_base *pki, const QString &name,
const QString &comment, bool force = false);
void updateItem(pki_base *pki);
virtual pki_base *newPKI(enum pki_type type = none);
db_base(const char *classname);

View File

@ -99,7 +99,7 @@ bool db_temp::alterTemp(pki_temp *temp)
TransRollback();
return false;
}
updateItem(temp, temp->getIntName(), temp->getComment(), true);
updateItem(temp);
TransCommit();
return true;
}

View File

@ -561,17 +561,21 @@ int main(int argc, char *argv[])
mainwin = new MainWindow();
gui->setMainwin(mainwin);
read_cmdline(argc, argv, console_only);
mainwin->importMulti(cmdline_items, 1);
cmdline_items = NULL;
enum open_result r = open_abort;
if (!Database.isOpen())
r = mainwin->init_database(QString());
else
r = mainwin->setup_open_database();
qDebug() << "PWret" << r << pw_cancel << pw_ok;
if (r != pw_exit) {
mainwin->show();
gui->exec();
qDebug() << "CMD Items" << cmdline_items->get().size();
if (cmdline_items->get().size() > 0) {
mainwin->importMulti(cmdline_items, 1);
cmdline_items = nullptr;
} else {
enum open_result r = open_abort;
if (!Database.isOpen())
r = mainwin->init_database(QString());
else
r = mainwin->setup_open_database();
qDebug() << "PWret" << r << pw_cancel << pw_ok;
if (r != pw_exit) {
mainwin->show();
gui->exec();
}
}
} else {
read_cmdline(argc, argv, console_only);

View File

@ -84,7 +84,7 @@
</widget>
</item>
<item>
<widget class="QLineEdit" name="keyDesc">
<widget class="QLineEdit" name="descr">
<property name="toolTip">
<string>The internal name of the key used by xca</string>
</property>

View File

@ -25,8 +25,8 @@ MW_help.cpp TempTreeView.h v3ext.cpp
MW_menu.cpp X509SuperTreeView.cpp v3ext.h
MainWindow.cpp X509SuperTreeView.h validity.cpp
MainWindow.h XcaApplication.cpp validity.h
pkcs12EncBox.h
pkcs12EncBox.cpp
pkcs12EncBox.h XcaDetail.h
pkcs12EncBox.cpp XcaDetail.cpp
)
list(TRANSFORM xca_sources PREPEND ${PROJECT_SOURCE_DIR}/widgets/)

View File

@ -20,16 +20,9 @@
#include <QLineEdit>
#include <QMessageBox>
CertDetail::CertDetail(QWidget *w)
: QDialog(w ? w : mainwin), keySqlId(), issuerSqlId(), thisSqlId()
CertDetail::CertDetail(QWidget *w) : XcaDetail(w)
{
setupUi(this);
setWindowTitle(XCA_TITLE);
showConf = false;
myPubKey = NULL;
tmpPubKey = NULL;
Database.connectToDbChangeEvt(this, SLOT(itemChanged(pki_base*)));
}
void CertDetail::on_showExt_clicked()
@ -51,6 +44,7 @@ void CertDetail::setX509super(pki_x509super *x)
descr->setText(x->getIntName());
thisSqlId = x->getSqlItemId();
connect_pki(x);
// examine the key
myPubKey = x->getRefKey();
if (myPubKey) {
@ -108,9 +102,8 @@ void CertDetail::setCert(pki_x509 *cert)
{
if (!cert)
return;
image->setPixmap(QPixmap(":certImg"));
init("certdetail", ":certImg");
headerLabel->setText(tr("Details of the Certificate"));
mainwin->helpdlg->register_ctxhelp_button(this, "certdetail");
try {
// No attributes
tabwidget->removeTab(3);
@ -180,6 +173,7 @@ void CertDetail::setReq(pki_x509req *req)
{
if (!req)
return;
init("csrdetail", ":csrImg");
image->setPixmap(QPixmap(":csrImg"));
headerLabel->setText(tr("Details of the certificate signing request"));
mainwin->helpdlg->register_ctxhelp_button(this, "csrdetail");
@ -288,20 +282,9 @@ void CertDetail::showCert(QWidget *parent, pki_x509super *x)
if (!x)
return;
CertDetail *dlg = new CertDetail(parent);
if (!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;
dlg->exec();
delete dlg;
}
CertDetail::~CertDetail()

View File

@ -11,10 +11,11 @@
#include "ui_CertDetail.h"
#include "lib/pki_x509req.h"
#include "lib/pki_x509.h"
#include "XcaDetail.h"
class pki_x509;
class CertDetail: public QDialog, public Ui::CertDetail
class CertDetail: public XcaDetail, public Ui::CertDetail
{
Q_OBJECT
@ -34,7 +35,7 @@ class CertDetail: public QDialog, public Ui::CertDetail
private slots:
void on_showExt_clicked();
void itemChanged(pki_base *pki);
void itemChanged(pki_base *pki) override;
void showPubKey();
void showIssuer();
};

View File

@ -20,15 +20,10 @@
#include <QTextEdit>
#include <QLineEdit>
CrlDetail::CrlDetail(QWidget *w)
: QDialog(w ? w : mainwin), issuerSqlId(), crlSqlId()
CrlDetail::CrlDetail(QWidget *w) : XcaDetail(w), issuerSqlId(), crlSqlId()
{
setupUi(this);
setWindowTitle(XCA_TITLE);
mainwin->helpdlg->register_ctxhelp_button(this, "crldetail");
image->setPixmap(QPixmap(":revImg"));
Database.connectToDbChangeEvt(this, SLOT(itemChanged(pki_base*)));
init("crldetail", ":revImg");
}
void CrlDetail::setCrl(pki_crl *crl)
@ -36,6 +31,7 @@ void CrlDetail::setCrl(pki_crl *crl)
pki_x509 *iss;
x509v3ext e1, e2;
connect_pki(crl);
iss = crl->getIssuer();
crlSqlId = crl->getSqlItemId();
@ -99,20 +95,10 @@ void CrlDetail::showIssuer()
void CrlDetail::showCrl(QWidget *parent, pki_crl *crl)
{
CrlDetail *dlg = new CrlDetail(parent);
if (!dlg)
if (!crl)
return;
CrlDetail *dlg = new CrlDetail(parent);
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());
}
}
dlg->exec();
delete dlg;
}

View File

@ -9,11 +9,12 @@
#define __CRLDETAIL_H
#include "ui_CrlDetail.h"
#include "XcaDetail.h"
class pki_crl;
class pki_base;
class CrlDetail: public QDialog, public Ui::CrlDetail
class CrlDetail: public XcaDetail, public Ui::CrlDetail
{
Q_OBJECT
@ -24,7 +25,7 @@ class CrlDetail: public QDialog, public Ui::CrlDetail
void setCrl(pki_crl *crl);
static void showCrl(QWidget *parent, pki_crl *crl);
public slots:
void itemChanged(pki_base *pki);
void itemChanged(pki_base *pki) override;
void showIssuer();
};
#endif

View File

@ -29,8 +29,8 @@
#include <QMimeData>
#include <typeinfo>
ImportMulti::ImportMulti(QWidget *parent)
: QDialog(parent ? parent : mainwin)
ImportMulti::ImportMulti(QWidget *)
: QDialog()
{
setupUi(this);
setWindowTitle(XCA_TITLE);
@ -221,11 +221,10 @@ void ImportMulti::on_renameToken_clicked()
QItemSelectionModel *selectionModel = listView->selectionModel();
QModelIndexList indexes = selectionModel->selectedIndexes();
QModelIndex index;
QString items;
foreach(index, indexes) {
if (index.column() != 0)
continue;
foreach(index, indexes) {
if (index.column() != 0)
continue;
listView->edit(index);
break;
}
@ -233,19 +232,24 @@ void ImportMulti::on_renameToken_clicked()
pki_base *ImportMulti::import(const QModelIndex &idx)
{
pki_base *pki = mcont->fromIndex(idx);
return idx.column() == 0 ? import(mcont->fromIndex(idx)) : nullptr;
}
if (idx.column() != 0)
return NULL;
for (int i = 0; i < mcont->rowCount(idx); i++)
import(mcont->index(i, 0, idx));
if (!pki)
pki_base *ImportMulti::import(pki_base *pki)
{
QModelIndex idx = mcont->index(pki);
if (!pki || pki->getSqlItemId().isValid())
return NULL;
mcont->remFromCont(idx);
if (!Database.isOpen()) {
try {
Database.open_default();
} catch(...) {
XCA_INFO(tr("Could not open the default database"));
};
}
if (!Database.isOpen()) {
delete pki;
return NULL;
@ -256,17 +260,19 @@ pki_base *ImportMulti::import(const QModelIndex &idx)
void ImportMulti::on_butDetails_clicked()
{
QItemSelectionModel *selectionModel = listView->selectionModel();
QModelIndex index;
if (!selectionModel->selectedIndexes().count())
return;
if (selectionModel->selectedIndexes().count())
showDetail(selectionModel->selectedIndexes().first());
}
index = selectionModel->selectedIndexes().first();
pki_base *pki = db_base::fromIndex(index);
void ImportMulti::showDetail(const QModelIndex &idx)
{
showDetail(db_base::fromIndex(idx));
}
if (!pki)
return;
try {
void ImportMulti::showDetail(pki_base *pki)
{
if (pki) try {
pki_x509super *pki_super = dynamic_cast<pki_x509super*>(pki);
if (pki_super) {
CertDetail::showCert(this, pki_super);
@ -335,13 +341,17 @@ void ImportMulti::execute(int force, QStringList failed)
return;
}
/* if there is only 1 item and force is 0 import it silently */
if (entries() == 1 && force == 0 && openDB()) {
if (entries() == 1) {
QModelIndex idx = mcont->index(0, 0, QModelIndex());
pki_base *pki = import(idx);
if (pki && !Settings["suppress_messages"])
XCA_INFO(pki->getMsg(pki_base::msg_import).
arg(pki->getIntName()));
accept();
if (force == 0 && openDB()) {
pki_base *pki = import(idx);
if (pki && !Settings["suppress_messages"])
XCA_INFO(pki->getMsg(pki_base::msg_import).
arg(pki->getIntName()));
} else {
showDetail(idx);
}
return;
}
/* the behaviour for more than one item */

View File

@ -31,6 +31,7 @@ class ImportMulti: public QDialog, private Ui::ImportMulti
void addItem(pki_base *pki);
pki_base *getSelected();
pki_base *import(const QModelIndex &idx);
pki_base *import(pki_base *pki);
void importIndexes(const QModelIndexList &indexes);
void execute(int force=0, QStringList failed = QStringList());
int entries();
@ -38,6 +39,8 @@ class ImportMulti: public QDialog, private Ui::ImportMulti
void dragEnterEvent(QDragEnterEvent *event);
void dropEvent(QDropEvent *event);
bool openDB() const;
void showDetail(pki_base *pki);
void showDetail(const QModelIndex &idx);
public slots:
void on_butRemove_clicked();

View File

@ -22,18 +22,13 @@
#include <QPushButton>
#include <QLineEdit>
KeyDetail::KeyDetail(QWidget *w)
: QDialog(w ? w : mainwin) , keySqlId()
KeyDetail::KeyDetail(QWidget *w) : XcaDetail(w) , 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*)));
init("keydetail", ":keyImg");
}
#ifndef OPENSSL_NO_EC
@ -80,8 +75,9 @@ void KeyDetail::setupFingerprints(pki_key *key)
void KeyDetail::setKey(pki_key *key)
{
keySqlId = key->getSqlItemId();
keyDesc->setText(key->getIntName());
descr->setText(key->getIntName());
keyLength->setText(key->length());
connect_pki(key);
keyPrivEx->disableToolTip();
if (!key->isToken())
@ -152,7 +148,7 @@ void KeyDetail::setKey(pki_key *key)
void KeyDetail::itemChanged(pki_base *pki)
{
if (pki->getSqlItemId() == keySqlId)
keyDesc->setText(pki->getIntName());
descr->setText(pki->getIntName());
}
void KeyDetail::showKey(QWidget *parent, pki_key *key, bool ro)
@ -160,20 +156,10 @@ void KeyDetail::showKey(QWidget *parent, pki_key *key, bool ro)
if (!key)
return;
KeyDetail *dlg = new KeyDetail(parent);
if (!dlg)
return;
dlg->setKey(key);
dlg->keyDesc->setReadOnly(ro);
dlg->descr->setReadOnly(ro);
dlg->comment->setReadOnly(ro);
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;
dlg->exec();
delete dlg;
}

View File

@ -9,23 +9,24 @@
#define __KEYDETAIL_H
#include "ui_KeyDetail.h"
#include "XcaDetail.h"
class pki_key;
class pki_base;
class KeyDetail: public QDialog, public Ui::KeyDetail
class KeyDetail: public XcaDetail, public Ui::KeyDetail
{
Q_OBJECT
QVariant keySqlId;
public:
public:
KeyDetail(QWidget *w = nullptr);
void setKey(pki_key *key);
void setupFingerprints(pki_key *key);
static void showKey(QWidget *parent, pki_key *keyi, bool ro = false);
public slots:
void itemChanged(pki_base *pki);
public slots:
void itemChanged(pki_base *pki) override;
};
#endif

View File

@ -193,10 +193,10 @@ bool XcaApplication::notify(QObject* receiver, QEvent* event)
return QApplication::notify(receiver, event);
} catch (errorEx &err) {
XCA_ERROR(err);
} catch (...) {
} catch (...) {
qWarning() << QString("Event exception: ")
<< receiver << event;
}
}
return false;
}

97
widgets/XcaDetail.cpp Normal file
View File

@ -0,0 +1,97 @@
/* vi: set sw=4 ts=4:
*
* Copyright (C) 2023 Christian Hohnstaedt.
*
* All rights reserved.
*/
#include <QLabel>
#include <QTextEdit>
#include <QLineEdit>
#include <QDialogButtonBox>
#include <QDialog>
#include "MainWindow.h"
#include "XcaDetail.h"
#include "Help.h"
#include "ImportMulti.h"
#include "lib/pki_base.h"
#include "lib/database_model.h"
XcaDetail::XcaDetail(QWidget *w) : QDialog(), pki(nullptr)
{
importmulti = dynamic_cast<ImportMulti *>(w);
setWindowTitle(XCA_TITLE);
Database.connectToDbChangeEvt(this, SLOT(itemChanged(pki_base*)));
}
void XcaDetail::init(const char *helpctx, const char *img)
{
mainwin->helpdlg->register_ctxhelp_button(this, helpctx);
QLabel *image = findChild<QLabel*>("image");
if (image)
image->setPixmap(QPixmap(img));
}
void XcaDetail::itemChanged(pki_base *)
{
}
void XcaDetail::connect_pki(pki_base *p)
{
QDialogButtonBox *buttonBox = findChild<QDialogButtonBox*>("buttonBox");
pki = p;
if (buttonBox && pki && pki->getSqlItemId() == QVariant()) {
importbut = buttonBox->addButton(tr("Import"), QDialogButtonBox::ApplyRole);
connect(importbut, SIGNAL(clicked(bool)), this, SLOT(import()));
}
QPushButton *but = buttonBox->button(QDialogButtonBox::Ok);
if (but)
connect(but, SIGNAL(clicked(bool)), this, SLOT(accept()));
}
void XcaDetail::updateNameComment()
{
if (!pki)
return;
QLineEdit *descr = findChild<QLineEdit*>("descr");
if (descr)
pki->setIntName(descr->text());
QTextEdit *comment = findChild<QTextEdit*>("comment");
if (comment)
pki->setComment(comment->toPlainText());
}
void XcaDetail::import()
{
updateNameComment();
qDebug() << "ImportMulti" << importmulti;
if (pki)
pki = importmulti ? importmulti->import(pki) : Database.insert(pki);
if (pki && !Settings["suppress_messages"])
XCA_INFO(pki->getMsg(pki_base::msg_import).arg(pki->getIntName()));
QDialogButtonBox *buttonBox = findChild<QDialogButtonBox*>("buttonBox");
if (buttonBox && !pki && importbut) {
buttonBox->removeButton(importbut);
importbut = nullptr;
QLineEdit *descr = findChild<QLineEdit*>("descr");
if (descr)
descr->setReadOnly(true);
QTextEdit *comment = findChild<QTextEdit*>("comment");
if (comment)
comment->setReadOnly(true);
}
}
void XcaDetail::accept()
{
db_base *db = Database.modelForPki(pki);
updateNameComment();
if (pki && pki->getSqlItemId().isValid() && db)
db->updateItem(pki);
QDialog::accept();
}

36
widgets/XcaDetail.h Normal file
View File

@ -0,0 +1,36 @@
/* vi: set sw=4 ts=4:
*
* Copyright (C) 2023 Christian Hohnstaedt.
*
* All rights reserved.
*/
#ifndef __XCADETAIL_H
#define __XCADETAIL_H
#include <QDialog>
class pki_base;
class ImportMulti;
class XcaDetail: public QDialog
{
Q_OBJECT
protected:
pki_base *pki;
ImportMulti *importmulti;
QPushButton *importbut;
void updateNameComment();
public:
XcaDetail(QWidget *w);
void init(const char *help, const char *img);
void connect_pki(pki_base *p);
public slots:
void accept();
void import();
virtual void itemChanged(pki_base*);
};
#endif

View File

@ -330,9 +330,11 @@ void XcaTreeView::editComment()
prop->insertionDate->setText(item->getInsertionDate().toPretty());
XcaDialog *d = new XcaDialog(this, item->getType(), w,
tr("Item properties"), QString(), "itemproperties");
if (d->exec())
basemodel->updateItem(item, prop->name->text(),
prop->comment->toPlainText());
if (d->exec()) {
item->setIntName(prop->name->text());
item->setComment(prop->comment->toPlainText());
basemodel->updateItem(item);
}
delete d;
}