Skip to content

Commit

Permalink
Close #395: Flexible Clipboard Export
Browse files Browse the repository at this point in the history
Generalize the Clipboard format selection
and extend it to certificates.

Certificates may now be exported as chain
or together with private key.

The clipboard format selection also
affects the Drag&Drop content.

The Export->Clipboard men now also shows the
currently selected format export.
  • Loading branch information
chris2511 committed Apr 23, 2024
1 parent e1914d3 commit 2060d75
Show file tree
Hide file tree
Showing 9 changed files with 76 additions and 36 deletions.
8 changes: 4 additions & 4 deletions lib/pki_export.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,12 @@ void pki_export::init_elements()
free_elements();
elements = QList<pki_export*> {

new pki_export( 1, x509, "crt", "PEM", F_PEM | F_USUAL | F_SINGLE, tr("PEM Text format with headers")),
new pki_export( 1, x509, "crt", "PEM", F_PEM | F_USUAL | F_SINGLE | F_CLIPBOARD, 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( 2, x509, "pem", tr("PEM chain"), F_PEM | F_USUAL | F_CHAIN | F_SINGLE | F_CLIPBOARD, tr("Concatenated text format of the complete certificate chain in one PEM file")),
new pki_export( 4, x509, "ovpn","OpenVPN", F_PEM | F_OVPN | F_CHAIN | F_PRIVATE | F_SINGLE, tr("The complete certificate chain and the private key of the selected certificate with tags usable in OpenVPN configuration files")),
new pki_export( 6, x509, "pem", tr("PEM + key"), F_PEM | 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( 6, x509, "pem", tr("PEM + key"), F_PEM | F_PRIVATE| F_SINGLE | F_CLIPBOARD, 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 | F_CLIPBOARD, 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 | 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")),
Expand Down
1 change: 1 addition & 0 deletions lib/pki_export.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

#define BIT(n) (1<<n)
#define DEFAULT_KEY_CLIPBOARD_TYPE 19
#define DEFAULT_CERT_CLIPBOARD_TYPE 1

enum pki_type {
none,
Expand Down
22 changes: 20 additions & 2 deletions lib/pki_x509.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -717,15 +717,33 @@ QString pki_x509::getIndexEntry()

bool pki_x509::pem(BioByteArray &b)
{
return PEM_write_bio_X509(b, cert);
const pki_export *xport = pki_export::by_id(Settings["CertFormat"]);

if (xport->match_all(F_PEM | F_CHAIN)) {
pki_x509 *iss, *prev;
for (iss = this, prev = nullptr; iss && iss != prev;
prev = iss, iss = iss->getSigner())
{
qDebug() << "Exporting to ClipBoard" << iss->getIntName();
if (!PEM_write_bio_X509(b, iss->cert))
return false;
}
} else if (xport->match_all(F_PEM | F_PRIVATE)) {
pki_key *key = getRefKey();
if (!key || !PEM_write_bio_X509(b, cert))
return false;
return key->pem(b, xport);
} else {
return PEM_write_bio_X509(b, cert);
}
return true;
}

bool pki_x509::cmpIssuerAndSerial(pki_x509 *refcert)
{
bool ret = X509_issuer_and_serial_cmp(cert, refcert->cert);
pki_openssl_error();
return ret;

}

bool pki_x509::verify_only(const pki_x509 *signer) const
Expand Down
1 change: 1 addition & 0 deletions lib/settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ settings::settings()
defaul["fp_separator"] = ":";
defaul["fp_digits"] = "2";
defaul["KeyFormat"] = QString::number(DEFAULT_KEY_CLIPBOARD_TYPE);
defaul["CertFormat"] = QString::number(DEFAULT_CERT_CLIPBOARD_TYPE);

hostspecific << "pkcs11path" << "workingdir" << "mw_geometry";
}
Expand Down
6 changes: 5 additions & 1 deletion widgets/CertTreeView.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,11 @@ class CertTreeView: public X509SuperTreeView
}

public:
CertTreeView(QWidget *parent) : X509SuperTreeView(parent) { }
CertTreeView(QWidget *parent) : X509SuperTreeView(parent)
{
ClipboardSettings = "CertFormat";
ClipboardPki_type = x509;
}
void fillContextMenu(QMenu *menu, QMenu *subExport,
const QModelIndex &index, QModelIndexList indexes);
ExportDialog *exportDialog(const QModelIndexList &index);
Expand Down
26 changes: 0 additions & 26 deletions widgets/KeyTreeView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,35 +14,14 @@
#include "ExportDialog.h"
#include "XcaWarning.h"
#include <QAbstractItemView>
#include <QActionGroup>
#include <QMenu>

void KeyTreeView::fillContextMenu(QMenu *menu, QMenu *subExport,
const QModelIndex &index, QModelIndexList indexes)
{
QMenu *clipboard;
QAction *a;
bool multi = indexes.size() > 1;
QActionGroup *group = new QActionGroup(menu);

pki_key *key = db_base::fromIndex<pki_key>(index);
int exp_type = Settings["KeyFormat"];
const pki_export *x;

clipboard = menu->addMenu(tr("Clipboard format"));
foreach(x, pki_export::select(asym_key, 0)) {
if (!(x->flags & F_CLIPBOARD))
continue;
a = clipboard->addAction(x->desc);
a->setData(x->id);
a->setCheckable(true);
a->setChecked(exp_type == x->id);
group->addAction(a);
}

connect(group, SIGNAL(triggered(QAction*)),
this, SLOT(clipboardFormat(QAction*)));

if (indexes.size() == 0 || !key)
return;

Expand Down Expand Up @@ -209,11 +188,6 @@ void KeyTreeView::newItem(const QString &name)
delete dlg;
}

void KeyTreeView::clipboardFormat(QAction *a)
{
Settings["KeyFormat"] = a->data().toInt();
}

void KeyTreeView::load(void)
{
load_key l;
Expand Down
7 changes: 5 additions & 2 deletions widgets/KeyTreeView.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ class KeyTreeView: public XcaTreeView
}

public:
KeyTreeView(QWidget *parent) : XcaTreeView(parent) { }
KeyTreeView(QWidget *parent) : XcaTreeView(parent)
{
ClipboardSettings = "KeyFormat";
ClipboardPki_type = asym_key;
}
void fillContextMenu(QMenu *menu, QMenu *subExport,
const QModelIndex &index, QModelIndexList indexes);
void showPki(pki_base *pki);
Expand All @@ -38,6 +42,5 @@ class KeyTreeView: public XcaTreeView
void newItem();
void load();
void newItem(const QString &name);
void clipboardFormat(QAction*);
};
#endif
35 changes: 34 additions & 1 deletion widgets/XcaTreeView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <QRegularExpression>
#include <QFileDialog>
#include <QClipboard>
#include <QActionGroup>

#include "OidResolver.h"
#include "XcaHeaderView.h"
Expand Down Expand Up @@ -531,12 +532,16 @@ void XcaTreeView::showContextMenu(QContextMenuEvent *e,
menu->addAction(tr("Delete"), this, SLOT(deleteItems()))->
setShortcut(QKeySequence::Delete);
subExport = menu->addMenu(tr("Export"));
subExport->addAction(tr("Clipboard"), this,
const pki_export *xport = pki_export::by_id(Settings[ClipboardSettings]);
subExport->addAction(QString("%1 (%2)")
.arg(tr("Clipboard")).arg(xport->desc), this,
SLOT(pem2clipboard()))->setShortcut(QKeySequence::Copy);
subExport->addAction(tr("File"), this, SLOT(exportItems()))->
setShortcut(QKeySequence::Save);
}

clipboardFormatMenu(menu);

fillContextMenu(menu, subExport, index, indexes);

contextMenu(e, menu, -1);
Expand Down Expand Up @@ -585,3 +590,31 @@ void XcaTreeView::changeEvent(QEvent *event)
}
QTreeView::changeEvent(event);
}

void XcaTreeView::clipboardFormatMenu(QMenu *menu)
{
if (!ClipboardSettings || !ClipboardPki_type)
return;
int exp_type = Settings[ClipboardSettings];

QActionGroup *group = new QActionGroup(menu);
QMenu *clipboard = menu->addMenu(tr("Clipboard format"));
foreach(const pki_export *x, pki_export::select(ClipboardPki_type, 0)) {
if (!(x->flags & F_CLIPBOARD))
continue;
QAction *a = clipboard->addAction(x->desc);
a->setData(x->id);
a->setCheckable(true);
a->setChecked(exp_type == x->id);
group->addAction(a);
}

connect(group, SIGNAL(triggered(QAction*)),
this, SLOT(clipboardFormat(QAction*)));
}

void XcaTreeView::clipboardFormat(QAction *a)
{
if (ClipboardSettings)
Settings[ClipboardSettings] = a->data().toInt();
}
6 changes: 6 additions & 0 deletions widgets/XcaTreeView.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
#include <QSortFilterProxyModel>
#include <QTimer>

#include "lib/pki_export.h"

class database_model;
class MainWindow;
class db_base;
Expand All @@ -36,6 +38,9 @@ class XcaTreeView: public QTreeView
db_base *basemodel{};
QSortFilterProxyModel *proxy{};
MainWindow *mainwin{};
const char *ClipboardSettings{};
enum pki_type ClipboardPki_type{ none };
void clipboardFormatMenu(QMenu *menu);

public:
XcaTreeView(QWidget *parent = nullptr);
Expand Down Expand Up @@ -85,5 +90,6 @@ class XcaTreeView: public QTreeView
void showItem(const QModelIndex &index);
void showItem(const QString &name);
void itemSelectionChanged(const QModelIndex &m, const QModelIndex &);
void clipboardFormat(QAction*);
};
#endif

0 comments on commit 2060d75

Please sign in to comment.