xca/widgets/MainWindow.cpp
Christian Hohnstaedt 4b3ee2c705 Switch database format to SQL(ite)
This is a large squash of many small commits.

Allow porting data from the legacy format to SQL.
Store Binaries base64 encoded and use db->transaction
Update password hash to be 8000 x SHA512 with 8 byte Salt
Add revocations table and fixup CRL generation
Add comment and insertion date columns

Fix column saving, remove trust, add XcaDialog
Allow changing the internal name and comment in Cert/Req details view
Extend Comment functionality, Replace About.ui by XcaDialog.ui
2018-03-05 07:42:36 +01:00

993 lines
21 KiB
C++

/* vi: set sw=4 ts=4:
*
* Copyright (C) 2001 - 2015 Christian Hohnstaedt.
*
* All rights reserved.
*/
//#define MDEBUG
#include "MainWindow.h"
#include "ImportMulti.h"
#include "lib/Passwd.h"
#include "lib/entropy.h"
#include <openssl/rand.h>
#include <QApplication>
#include <QClipboard>
#include <QMessageBox>
#include <QLabel>
#include <QPushButton>
#include <QListView>
#include <QLineEdit>
#include <QTextBrowser>
#include <QStatusBar>
#include <QList>
#include <QTimer>
#include <QMimeData>
#include <QInputDialog>
#include "lib/exception.h"
#include "lib/pki_evp.h"
#include "lib/pki_scard.h"
#include "lib/pki_pkcs12.h"
#include "lib/pki_multi.h"
#include "lib/load_obj.h"
#include "lib/pass_info.h"
#include "lib/func.h"
#include "lib/pkcs11.h"
#include "lib/builtin_curves.h"
#include "XcaDialog.h"
#include "PwDialog.h"
QPixmap *MainWindow::keyImg = NULL, *MainWindow::csrImg = NULL,
*MainWindow::certImg = NULL, *MainWindow::tempImg = NULL,
*MainWindow::nsImg = NULL, *MainWindow::revImg = NULL,
*MainWindow::appIco = NULL, *MainWindow::scardImg = NULL,
*MainWindow::doneIco = NULL, *MainWindow::warnIco = NULL;
db_key *MainWindow::keys = NULL;
db_x509req *MainWindow::reqs = NULL;
db_x509 *MainWindow::certs = NULL;
db_temp *MainWindow::temps = NULL;
db_crl *MainWindow::crls = NULL;
NIDlist *MainWindow::eku_nid = NULL;
NIDlist *MainWindow::dn_nid = NULL;
QString MainWindow::mandatory_dn;
QString MainWindow::explicit_dn;
QString MainWindow::explicit_dn_default = QString("C,ST,L,O,OU,CN,emailAddress");
OidResolver *MainWindow::resolver = NULL;
void MainWindow::enableTokenMenu(bool enable)
{
foreach(QWidget *w, scardList) {
w->setEnabled(enable);
}
}
void MainWindow::load_engine()
{
try {
pkcs11::load_libs(pkcs11path, false);
} catch (errorEx &err) {
Error(err);
}
enableTokenMenu(pkcs11::loaded());
}
void MainWindow::initResolver()
{
bool shown = false;
QString search;
if (resolver) {
shown = resolver->isVisible();
search = resolver->input->text();
delete resolver;
}
resolver = new OidResolver(NULL);
resolver->setWindowTitle(XCA_TITLE);
if (shown)
resolver->searchOid(search);
}
MainWindow::MainWindow(QWidget *parent)
:QMainWindow(parent)
{
dbindex = new QLabel();
dbindex->setFrameStyle(QFrame::Plain | QFrame::NoFrame);
dbindex->setMargin(6);
dn_translations_setup();
statusBar()->addWidget(dbindex, 1);
setupUi(this);
setWindowTitle(XCA_TITLE);
initResolver();
wdList << keyButtons << reqButtons << certButtons <<
tempButtons << crlButtons;
QStringList drivers = QSqlDatabase::drivers();
foreach(QString driver, drivers) {
QSqlDatabase d = QSqlDatabase::addDatabase(driver, driver +"_C");
fprintf(stderr, "DB driver: '%s' LastInsertId: %s\n",
CCHAR(driver), d.driver()->
hasFeature(QSqlDriver::LastInsertId) ? "YES":"NO" );
}
#define POSTGRES 1
#ifndef POSTGRES
db = QSqlDatabase::addDatabase("QSQLITE");
#else
db = QSqlDatabase::addDatabase("QPSQL7");
#endif
historyMenu = NULL;
init_menu();
setItemEnabled(false);
init_images();
homedir = getHomeDir();
#ifdef MDEBUG
CRYPTO_malloc_debug_init();
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
fprintf(stderr, "malloc() debugging on.\n");
#endif
ERR_load_crypto_strings();
OpenSSL_add_all_algorithms();
EVP_add_digest_alias(SN_sha1,SN_ecdsa_with_SHA1);
EVP_add_digest_alias(SN_sha224,SN_ecdsa_with_SHA224);
EVP_add_digest_alias(SN_sha256,SN_ecdsa_with_SHA256);
EVP_add_digest_alias(SN_sha256,SN_dsa_with_SHA256);
EVP_add_digest_alias(SN_sha384,SN_ecdsa_with_SHA384);
EVP_add_digest_alias(SN_sha512,SN_ecdsa_with_SHA512);
/* read in all our own OIDs */
initOIDs();
eku_nid = read_nidlist("eku.txt");
dn_nid = read_nidlist("dn.txt");
setAcceptDrops(true);
searchEdit = new QLineEdit();
searchEdit->setPlaceholderText(tr("Search"));
keyView->setMainwin(this, searchEdit);
reqView->setMainwin(this, searchEdit);
certView->setMainwin(this, searchEdit);
tempView->setMainwin(this, searchEdit);
crlView->setMainwin(this, searchEdit);
}
void MainWindow::dropEvent(QDropEvent *event)
{
if (event->mimeData()->hasUrls()) {
QList<QUrl> urls = event->mimeData()->urls();
QUrl u;
QStringList files;
foreach(u, urls) {
QString s = u.toLocalFile();
files << s;
}
openURLs(files);
event->acceptProposedAction();
} else if (event->mimeData()->hasText()) {
event->acceptProposedAction();
pastePem(event->mimeData()->text());
}
}
void MainWindow::openURLs(QStringList &files)
{
urlsToOpen = files;
QTimer::singleShot(100, this, SLOT(openURLs()));
}
void MainWindow::openURLs()
{
QStringList failed;
QString s;
ImportMulti *dlgi = new ImportMulti(this);
foreach(s, urlsToOpen) {
pki_multi *pki = probeAnything(s);
if (pki && !pki->count())
failed << s;
dlgi->addItem(pki);
}
urlsToOpen.clear();
dlgi->execute(1, failed);
delete dlgi;
}
void MainWindow::dragEnterEvent(QDragEnterEvent *event)
{
if (event->mimeData()->hasFormat(X_XCA_DRAG_DATA))
return;
if (event->mimeData()->hasUrls() || event->mimeData()->hasText())
event->acceptProposedAction();
}
void MainWindow::setItemEnabled(bool enable)
{
foreach(QWidget *w, wdList) {
w->setEnabled(enable);
}
foreach(QWidget *w, wdMenuList) {
w->setEnabled(enable);
}
foreach(QAction *a, acList) {
a->setEnabled(enable);
}
enableTokenMenu(pkcs11::loaded());
}
/* creates a new nid list from the given filename */
NIDlist *MainWindow::read_nidlist(QString name)
{
NIDlist nl;
name = QDir::separator() + name;
/* first try $HOME/xca/ */
nl = readNIDlist(getUserSettingsDir() + name);
#if !defined(Q_OS_WIN32)
#if !defined(Q_OS_MAC)
if (nl.count() == 0){
/* next is /etx/xca/... */
nl = readNIDlist(QString(ETC) + name);
}
#endif
#endif
if (nl.count() == 0) {
/* look at /usr/(local/)share/xca/ */
nl = readNIDlist(getPrefix() + name);
}
return new NIDlist(nl);
}
void MainWindow::init_images()
{
keyImg = loadImg("bigkey.png");
csrImg = loadImg("bigcsr.png");
certImg = loadImg("bigcert.png");
tempImg = loadImg("bigtemp.png");
nsImg = loadImg("netscape.png");
revImg = loadImg("bigcrl.png");
scardImg = loadImg("bigscard.png");
appIco = loadImg("key.xpm");
doneIco = loadImg("done.png");
warnIco = loadImg("warn.png");
bigKey->setPixmap(*keyImg);
bigCsr->setPixmap(*csrImg);
bigCert->setPixmap(*certImg);
bigTemp->setPixmap(*tempImg);
bigRev->setPixmap(*revImg);
setWindowIcon(*appIco);
pki_evp::icon[0] = loadImg("key.png");
pki_evp::icon[1] = loadImg("halfkey.png");
pki_scard::icon[0] = loadImg("scard.png");
pki_x509req::icon[0] = loadImg("req.png");
pki_x509req::icon[1] = loadImg("reqkey.png");
pki_x509req::icon[2] = doneIco;
pki_x509::icon[0] = loadImg("validcert.png");
pki_x509::icon[1] = loadImg("validcertkey.png");
pki_x509::icon[2] = loadImg("invalidcert.png");
pki_x509::icon[3] = loadImg("invalidcertkey.png");
pki_x509::icon[4] = doneIco;
pki_temp::icon = loadImg("template.png");
pki_crl::icon = loadImg("crl.png");
}
void MainWindow::read_cmdline(int argc, char *argv[])
{
int cnt = 1, opt = 0, force_load = 0, export_index = 0;
char *arg = NULL;
exitApp = 0;
QStringList failed;
ImportMulti *dlgi = new ImportMulti(this);
while (cnt < argc) {
arg = argv[cnt];
if (arg[0] == '-') { // option
opt = 1;
switch (arg[1]) {
case 'c':
case 'r':
case 'k':
case 'p':
case '7':
case 'l':
case 't':
case 'P':
break;
case 'd':
force_load=1;
break;
case 'i':
export_index=1;
break;
case 'I':
export_index=2;
break;
case 'v':
cmd_version();
opt=0;
break;
case 'x':
exitApp = 1;
opt=0;
break;
case 'h':
cmd_help(NULL);
opt=0;
break;
default:
cmd_help(CCHAR(tr("no such option: %1").arg(arg)));
}
if (arg[2] != '\0' && opt==1) {
arg+=2;
} else {
cnt++;
continue;
}
}
QString file = filename2QString(arg);
if (force_load) {
if (changeDB(file) == 2)
exitApp = 1;
force_load = 0;
} else if (export_index) {
if (exportIndex(file, (export_index == 2)) == 2)
exitApp = 1;
export_index = 0;
} else {
int ret;
pki_multi *pki = probeAnything(file, &ret);
if (!pki && ret == 2)
exitApp = 1;
if (pki && !pki->count())
failed << file;
dlgi->addItem(pki);
}
cnt++;
}
dlgi->execute(1, failed); /* force showing of import dialog */
if (dlgi->result() == QDialog::Rejected)
exitApp = 1;
delete dlgi;
}
void MainWindow::loadPem()
{
load_pem l;
if (keys)
keys->load_default(l);
}
bool MainWindow::pastePem(QString text, bool silent)
{
bool success = false;
QByteArray pemdata = text.toLatin1();
if (pemdata.size() == 0)
return false;
pki_multi *pem = NULL;
ImportMulti *dlgi = NULL;
try {
pem = new pki_multi();
dlgi = new ImportMulti(this);
pem->fromPEMbyteArray(pemdata, QString("paste"));
success = pem->count() != 0;
dlgi->addItem(pem);
pem = NULL;
dlgi->execute(1);
}
catch (errorEx &err) {
if (!silent)
Error(err);
}
if (dlgi)
delete dlgi;
if (pem)
delete pem;
return success;
}
void MainWindow::pastePem()
{
QClipboard *cb = QApplication::clipboard();
QString text;
text = cb->text(QClipboard::Selection);
if (text.isEmpty())
text = cb->text(QClipboard::Clipboard);
if (!text.isEmpty())
if (pastePem(text, true))
return;
QTextEdit *textbox = new QTextEdit();
textbox->setPlainText(text);
XcaDialog *input = new XcaDialog(this, x509, textbox,
tr("Import PEM data"), QString());
input->noSpacer();
if (input->exec()) {
text = textbox->toPlainText();
if (!text.isEmpty())
pastePem(text);
}
delete input;
}
void MainWindow::initToken()
{
bool ok;
if (!pkcs11::loaded())
return;
try {
pkcs11 p11;
slotid slot;
Passwd pin;
int ret;
if (!p11.selectToken(&slot, this))
return;
tkInfo ti = p11.tokenInfo(slot);
QString slotname = QString("%1 (#%2)").
arg(ti.label()).arg(ti.serial());
pass_info p(XCA_TITLE,
tr("Please enter the original SO PIN (PUK) of the token '%1'").
arg(slotname) + "\n" + ti.pinInfo());
p.setPin();
if (ti.tokenInitialized()) {
ret = PwDialog::execute(&p, &pin, false);
} else {
p.setDescription(tr("Please enter the new SO PIN (PUK) for the token '%1'").
arg(slotname) + "\n" + ti.pinInfo());
ret = PwDialog::execute(&p, &pin, true);
}
if (ret != 1)
return;
QString label = QInputDialog::getText(this, XCA_TITLE,
tr("The new label of the token '%1'").
arg(slotname), QLineEdit::Normal, QString(), &ok);
if (!ok)
return;
p11.initToken(slot, pin.constUchar(), pin.size(), label);
} catch (errorEx &err) {
Error(err);
}
}
void MainWindow::changePin(bool so)
{
if (!pkcs11::loaded())
return;
try {
pkcs11 p11;
slotid slot;
if (!p11.selectToken(&slot, this))
return;
p11.changePin(slot, so);
} catch (errorEx &err) {
Error(err);
}
}
void MainWindow::changeSoPin()
{
changePin(true);
}
void MainWindow::initPin()
{
if (!pkcs11::loaded())
return;
try {
pkcs11 p11;
slotid slot;
if (!p11.selectToken(&slot, this))
return;
p11.initPin(slot);
} catch (errorEx &err) {
Error(err);
}
}
void MainWindow::manageToken()
{
pkcs11 p11;
slotid slot;
pki_scard *card = NULL;
pki_x509 *cert = NULL;
ImportMulti *dlgi = NULL;
if (!pkcs11::loaded())
return;
try {
if (!p11.selectToken(&slot, this))
return;
ImportMulti *dlgi = new ImportMulti(this);
dlgi->tokenInfo(slot);
QList<CK_OBJECT_HANDLE> objects;
QList<CK_MECHANISM_TYPE> ml = p11.mechanismList(slot);
if (ml.count() == 0)
ml << CKM_SHA1_RSA_PKCS;
pk11_attlist atts(pk11_attr_ulong(CKA_CLASS,
CKO_PUBLIC_KEY));
p11.startSession(slot);
p11.getRandom();
objects = p11.objectList(atts);
for (int j=0; j< objects.count(); j++) {
card = new pki_scard("");
try {
card->load_token(p11, objects[j]);
card->setMech_list(ml);
dlgi->addItem(card);
} catch (errorEx &err) {
Error(err);
delete card;
}
card = NULL;
}
atts.reset();
atts << pk11_attr_ulong(CKA_CLASS, CKO_CERTIFICATE) <<
pk11_attr_ulong(CKA_CERTIFICATE_TYPE,CKC_X_509);
objects = p11.objectList(atts);
for (int j=0; j< objects.count(); j++) {
cert = new pki_x509("");
try {
cert->load_token(p11, objects[j]);
dlgi->addItem(cert);
} catch (errorEx &err) {
Error(err);
delete cert;
}
cert = NULL;
}
if (dlgi->entries() == 0) {
tkInfo ti = p11.tokenInfo();
XCA_INFO(tr("The token '%1' did not contain any keys or certificates").arg(ti.label()));
} else {
dlgi->execute(true);
}
} catch (errorEx &err) {
Error(err);
}
if (card)
delete card;
if (cert)
delete cert;
if (dlgi)
delete dlgi;
}
MainWindow::~MainWindow()
{
close_database();
ERR_free_strings();
EVP_cleanup();
OBJ_cleanup();
if (eku_nid)
delete eku_nid;
if (dn_nid)
delete dn_nid;
delete dbindex;
#ifdef MDEBUG
fprintf(stderr, "Memdebug:\n");
CRYPTO_mem_leaks_fp(stderr);
#endif
}
void MainWindow::closeEvent(QCloseEvent *e)
{
if (resolver) {
delete resolver;
}
QMainWindow::closeEvent(e);
}
QString makeSalt(void)
{
QString s = "T";
unsigned char rand[8];
Entropy::get(rand, sizeof rand);
for (unsigned i=0; i< sizeof rand; i++)
s += QString("%1").arg(rand[i]);
return s;
}
int MainWindow::checkOldGetNewPass(Passwd &pass)
{
QString passHash = getSetting("pwhash");
if (!passHash.isEmpty()) {
pass_info p(tr("Current Password"),
tr("Please enter the current database password"), this);
/* Try empty password */
if (pki_evp::sha512passwT(pass, passHash) != passHash) {
/* Not the empty password, check it */
if (PwDialog::execute(&p, &pass, false) != 1)
return 0;
}
if (pki_evp::sha512passwT(pass, passHash) != passHash) {
XCA_WARN(tr("The entered password is wrong"));
return 0;
}
}
pass_info p(tr("New Password"), tr("Please enter the new password "
"to encrypt your private keys in the database-file"),
this);
return PwDialog::execute(&p, &pass, true) != 1 ? 0 : 1;
}
void MainWindow::changeDbPass()
{
Passwd pass;
XSqlQuery q;
if (!checkOldGetNewPass(pass))
return;
QString salt = makeSalt();
QString passhash = pki_evp::sha512passwT(pass, salt);
QList<pki_base*> key_list = keys->sqlSELECTpki(
"SELECT item FROM private_keys WHERE ownPass=0");
if (!db.transaction()) {
errorEx e(tr("Transaction start failed"));
Error(e);
return;
}
try {
foreach(pki_base *pki, key_list) {
pki_evp *key = static_cast<pki_evp*>(pki);
EVP_PKEY *evp = key->decryptKey();
key->set_evp_key(evp);
key->encryptKey(pass.constData());
key->sqlUpdatePrivateKey();
}
storeSetting("pwhash", passhash);
} catch (errorEx &e) {
Error(e);
db.rollback();
return;
}
db.commit();
pki_evp::passHash = passhash;
pki_evp::passwd = pass;
}
int MainWindow::initPass()
{
QString passhash = getSetting("pwhash");
return initPass(passhash);
}
int MainWindow::initPass(QString passhash)
{
pki_evp::passHash = QString();
QString salt, pass;
int ret;
pass_info p(tr("New Password"), tr("Please enter a password, "
"that will be used to encrypt your private keys "
"in the database file:\n%1").
arg(compressFilename(dbfile)), this);
pki_evp::passHash = passhash;
if (pki_evp::passHash.isEmpty()) {
ret = PwDialog::execute(&p, &pki_evp::passwd, true, true);
if (ret != 1)
return ret;
salt = makeSalt();
pki_evp::passHash =pki_evp::sha512passwT(pki_evp::passwd,salt);
storeSetting("pwhash", pki_evp::passHash);
} else {
ret = 0;
while (pki_evp::sha512passwT(pki_evp::passwd, pki_evp::passHash)
!= pki_evp::passHash)
{
if (ret)
XCA_WARN(
tr("Password verify error, please try again"));
p.setTitle(tr("Password"));
p.setDescription(tr("Please enter the password for unlocking the database:\n%1").arg(compressFilename(dbfile)));
ret = PwDialog::execute(&p, &pki_evp::passwd,
false, true);
if (ret != 1) {
pki_evp::passwd = QByteArray();
return ret;
}
if (pki_evp::passHash.startsWith("T")) {
/* Fine, current hash function used. */
continue;
}
/* Start automatic update from sha512 to sha512*8000
* if the password is correct. The old sha512 hash does
* start with 'S', while the new hash starts with T. */
/* Start automatic update from md5 to salted sha512
* if the password is correct. The md5 hash does not
* start with 'S' or 'T, but with a hex-digit */
if (pki_evp::sha512passwd(pki_evp::passwd,
pki_evp::passHash) == pki_evp::passHash ||
pki_evp::md5passwd(pki_evp::passwd) ==
pki_evp::passHash)
{
salt = makeSalt();
pki_evp::passHash = pki_evp::sha512passwT(
pki_evp::passwd, salt);
}
}
}
if (pki_evp::passwd.isNull())
pki_evp::passwd = "";
return 1;
}
void MainWindow::Error(errorEx &err)
{
if (err.isEmpty())
return;
QString msg = tr("The following error occurred:") + "\n" + err.getString();
xcaWarning box(NULL, msg);
box.addButton(QMessageBox::Apply)->setText(tr("Copy to Clipboard"));
box.addButton(QMessageBox::Ok);
if (box.exec() == QMessageBox::Apply) {
QClipboard *cb = QApplication::clipboard();
cb->setText(msg);
if (cb->supportsSelection())
cb->setText(msg, QClipboard::Selection);
}
}
QString MainWindow::getPath()
{
return workingdir;
}
void MainWindow::setPath(QString str)
{
workingdir = str;
storeSetting("workingdir", str);
}
void MainWindow::connNewX509(NewX509 *nx)
{
connect(nx, SIGNAL(genKey(QString)),
keys, SLOT(newItem(QString)));
connect(keys, SIGNAL(keyDone(pki_key*)),
nx, SLOT(newKeyDone(pki_key*)));
connect(nx, SIGNAL(showReq(pki_base*)),
reqs, SLOT(showPki(pki_base*)));
}
void MainWindow::importAnything(QString file)
{
ImportMulti *dlgi = new ImportMulti(this);
QStringList failed;
pki_multi *pki = probeAnything(file);
if (pki && !pki->count())
failed << file;
dlgi->addItem(pki);
dlgi->execute(1, failed);
delete dlgi;
}
pki_multi *MainWindow::probeAnything(QString file, int *ret)
{
(void)ret;
pki_multi *pki = new pki_multi();
try {
if (file.endsWith(".xdb")) {
#warning FIXME OPEN DATABASE
qDebug("FIXME OPEN DATABASE");
return pki;
}
pki->probeAnything(file);
} catch (errorEx &err) {
Error(err);
}
return pki;
}
void MainWindow::exportIndex()
{
exportIndex(NULL, false);
}
void MainWindow::exportIndexHierarchy()
{
exportIndex(NULL, true);
}
int MainWindow::exportIndex(QString fname, bool hierarchy)
{
if (fname == NULL || fname.isEmpty()) {
QString filter = tr("Certificate Index ( index.txt )") + ";;" + tr("All files ( * )");
fname = QFileDialog::getSaveFileName(this, QString(), fname, filter, NULL);
if (fname.isEmpty())
return 1;
nativeSeparator(fname);
}
if (certs == NULL) {
open_default_db();
if (certs == NULL)
return 2;
}
bool needChangeView = hierarchy && !certs->treeview;
if (needChangeView) {
certView->changeView();
}
certs->writeIndex(fname, hierarchy);
if (needChangeView) {
certView->changeView();
}
return 0;
}
void MainWindow::generateDHparam()
{
DH *dh = NULL;
FILE *fp = NULL;
QProgressBar *bar = NULL;
bool ok;
int num = QInputDialog::getDouble(this, XCA_TITLE, tr("Diffie-Hellman parameters are needed for different applications, but not handled by XCA.\nPlease enter the DH parameter bits"),
1024, 1024, 4096, 0, &ok);
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
BN_GENCB *cb = NULL;
#endif
if (!ok)
return;
/*
* 1024: 6 sec
* 2048: 38 sec
* 4096: 864 sec
*/
Entropy::seed_rng();
try {
QStatusBar *status = statusBar();
bar = new QProgressBar();
check_oom(bar);
bar->setMinimum(0);
bar->setMaximum(100);
status->addPermanentWidget(bar, 1);
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
cb = BN_GENCB_new();
if (!cb)
throw errorEx("");
BN_GENCB_set_old(cb, inc_progress_bar, bar);
dh = DH_new();
DH_generate_parameters_ex(dh, num, 2, cb);
#else
dh = DH_generate_parameters(num, 2, inc_progress_bar, bar);
#endif
status->removeWidget(bar);
openssl_error();
QString fname = QString("%1/dh%2.pem").arg(homedir).arg(num);
fname = QFileDialog::getSaveFileName(this, QString(),
fname, "All files ( * )", NULL);
if (fname == "")
throw errorEx("");
fp = fopen_write(fname);
if (fp == NULL) {
throw errorEx(tr("Error opening file: '%1': %2").
arg(fname).arg(strerror(errno)));
}
PEM_write_DHparams(fp, dh);
openssl_error();
} catch (errorEx &err) {
Error(err);
}
if (dh)
DH_free(dh);
if (fp)
fclose(fp);
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
if (cb)
BN_GENCB_free(cb);
#endif
if (bar)
delete bar;
}
void MainWindow::changeEvent(QEvent *event)
{
if (event->type() == QEvent::LanguageChange) {
QList<db_base*> models;
retranslateUi(this);
dn_translations_setup();
init_menu();
update_history_menu();
models << keys << reqs << certs << crls << temps;
foreach(db_base *model, models) {
if (model)
model->updateHeaders();
}
if (!dbfile.isEmpty())
dbindex->setText(tr("Database") + ": " + dbfile);
}
QMainWindow::changeEvent(event);
}
void MainWindow::keyPressEvent(QKeyEvent *e)
{
if (e->modifiers() != Qt::ControlModifier) {
QMainWindow::keyPressEvent(e);
return;
}
int siz = XCA_application::tableFont.pointSize();
QList<XcaTreeView*> views;
switch (e->key()) {
case Qt::Key_Plus:
XCA_application::tableFont.setPointSize(siz +1);
break;
case Qt::Key_Minus:
if (siz > 4) {
XCA_application::tableFont.setPointSize(siz -1);
}
break;
case Qt::Key_V:
if (e->modifiers() == Qt::ControlModifier) {
pastePem();
break;
}
/* FALLTHROUGH */
default:
QMainWindow::keyPressEvent(e);
return;
}
views << keyView << reqView << certView << crlView << tempView;
foreach(XcaTreeView *v, views) {
if (v) {
v->header()->resizeSections(
QHeaderView::ResizeToContents);
v->reset();
}
}
update();
}