mirror of
https://github.com/QuasarApp/qca.git
synced 2025-05-12 10:49:32 +00:00
selector dialog now complete, allow viewing certs, other cleanup
svn path=/trunk/kdesupport/qca/; revision=698089
This commit is contained in:
parent
c0f32502fa
commit
c8446b08b6
@ -1,30 +1,26 @@
|
||||
have a graphical busy indicator for:
|
||||
keystores are busy? (maybe a flashing thing in the status bar)
|
||||
sign operation in progress (maybe just use an endless QProgressBar)
|
||||
|
||||
app icon (may need different sizes of this?) (a pen?)
|
||||
|
||||
store icons
|
||||
system
|
||||
user
|
||||
application
|
||||
smart card
|
||||
pgp keyring
|
||||
|
||||
unknown store/entry icon (can use the same icon for both i think)
|
||||
animation rather than text for keystore busy?
|
||||
animation for signing in progress (maybe just use an endless QProgressBar?)
|
||||
integrated logger window? also allow setting the log level
|
||||
prompter should not call entrylist unless necessary. right now it starts
|
||||
async mode on all stores, even if there is no prompting or anything going
|
||||
on. qcatool has this problem also
|
||||
report all 3 kinds of diagnostic text somewhere
|
||||
plugin: plugin dialog invoked from file menu ? also show provider versions
|
||||
keystore: invoked from keyselectdlg ?
|
||||
secmessage: "details" button on error dialog?
|
||||
|
||||
further cleanup
|
||||
don't remember pkcs12 password if it was wrong
|
||||
when verifying a signature:
|
||||
if the key is valid, import it and ask the user for a friendly name and
|
||||
import into keyring
|
||||
if the key is self-signed, ask the user to verify the fingerprint. if
|
||||
validated, ask user for friendly name and import into keyring
|
||||
|
||||
ability to view CertItems, showing cert values and issuer hierarchy
|
||||
report all 3 kinds of diagnostic text somewhere (plugin, keystore, secmessage)
|
||||
integrated logger window? also allow setting the log level
|
||||
|
||||
items in loadstore ui should not be editable
|
||||
|
||||
don't show systemstore or pgpkeyrings
|
||||
|
||||
respect !usable state for items
|
||||
|
85
examples/cmssigner/certview.ui
Normal file
85
examples/cmssigner/certview.ui
Normal file
@ -0,0 +1,85 @@
|
||||
<ui version="4.0" >
|
||||
<class>CertView</class>
|
||||
<widget class="QDialog" name="CertView" >
|
||||
<property name="geometry" >
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle" >
|
||||
<string>View Certificate</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QComboBox" name="cb_chain" />
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="frame" >
|
||||
<property name="frameShape" >
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow" >
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="lb_info" >
|
||||
<property name="alignment" >
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons" >
|
||||
<set>QDialogButtonBox::Close</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>cb_chain</tabstop>
|
||||
<tabstop>buttonBox</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>CertView</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel" >
|
||||
<x>284</x>
|
||||
<y>278</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel" >
|
||||
<x>291</x>
|
||||
<y>299</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
166
examples/cmssigner/certviewdlg.cpp
Normal file
166
examples/cmssigner/certviewdlg.cpp
Normal file
@ -0,0 +1,166 @@
|
||||
/*
|
||||
Copyright (C) 2007 Justin Karneges <justin@affinix.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "certviewdlg.h"
|
||||
|
||||
#include <QtCore>
|
||||
#include <QtGui>
|
||||
#include <QtCrypto>
|
||||
#include "ui_certview.h"
|
||||
|
||||
// from qcatool
|
||||
class InfoType
|
||||
{
|
||||
public:
|
||||
QCA::CertificateInfoType type;
|
||||
QString varname;
|
||||
QString shortname;
|
||||
QString name;
|
||||
QString desc;
|
||||
|
||||
InfoType()
|
||||
{
|
||||
}
|
||||
|
||||
InfoType(QCA::CertificateInfoType _type, const QString &_varname, const QString &_shortname, const QString &_name, const QString &_desc) :
|
||||
type(_type),
|
||||
varname(_varname),
|
||||
shortname(_shortname),
|
||||
name(_name),
|
||||
desc(_desc)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
static QList<InfoType> makeInfoTypeList(bool legacyEmail = false)
|
||||
{
|
||||
QList<InfoType> out;
|
||||
out += InfoType(QCA::CommonName, "CommonName", "CN", CertViewDlg::tr("Common Name (CN)"), "Full name, domain, anything");
|
||||
out += InfoType(QCA::Email, "Email", "", CertViewDlg::tr("Email Address"), "");
|
||||
if(legacyEmail)
|
||||
out += InfoType(QCA::EmailLegacy, "EmailLegacy", "", CertViewDlg::tr("PKCS#9 Email Address"), "");
|
||||
out += InfoType(QCA::Organization, "Organization", "O", CertViewDlg::tr("Organization (O)"), "Company, group, etc");
|
||||
out += InfoType(QCA::OrganizationalUnit, "OrganizationalUnit", "OU", CertViewDlg::tr("Organizational Unit (OU)"), "Division/branch of organization");
|
||||
out += InfoType(QCA::Locality, "Locality", "", CertViewDlg::tr("Locality (L)"), "City, shire, part of a state");
|
||||
out += InfoType(QCA::State, "State", "", CertViewDlg::tr("State (ST)"), "State within the country");
|
||||
out += InfoType(QCA::Country, "Country", "C", CertViewDlg::tr("Country Code (C)"), "2-letter code");
|
||||
out += InfoType(QCA::IncorporationLocality, "IncorporationLocality", "", CertViewDlg::tr("Incorporation Locality"), "For EV certificates");
|
||||
out += InfoType(QCA::IncorporationState, "IncorporationState", "", CertViewDlg::tr("Incorporation State"), "For EV certificates");
|
||||
out += InfoType(QCA::IncorporationCountry, "IncorporationCountry", "", CertViewDlg::tr("Incorporation Country"), "For EV certificates");
|
||||
out += InfoType(QCA::URI, "URI", "", CertViewDlg::tr("URI"), "");
|
||||
out += InfoType(QCA::DNS, "DNS", "", CertViewDlg::tr("Domain Name"), "Domain (dnsName)");
|
||||
out += InfoType(QCA::IPAddress, "IPAddress", "", CertViewDlg::tr("IP Adddress"), "");
|
||||
out += InfoType(QCA::XMPP, "XMPP", "", CertViewDlg::tr("XMPP Address (JID)"), "From RFC 3920 (id-on-xmppAddr)");
|
||||
return out;
|
||||
}
|
||||
|
||||
static QString try_print_info(const QString &name, const QStringList &values)
|
||||
{
|
||||
QString out;
|
||||
if(!values.isEmpty())
|
||||
{
|
||||
QString value = values.join(", ");
|
||||
out = QString(" ") + CertViewDlg::tr("%1: %2").arg(name, value) + '\n';
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
static QString print_info(const QString &title, const QCA::CertificateInfo &info)
|
||||
{
|
||||
QString out;
|
||||
QList<InfoType> list = makeInfoTypeList();
|
||||
out += title + '\n';
|
||||
foreach(const InfoType &t, list)
|
||||
out += try_print_info(t.name, info.values(t.type));
|
||||
return out;
|
||||
}
|
||||
|
||||
static QString cert_info_string(const QCA::Certificate &cert)
|
||||
{
|
||||
QString out;
|
||||
out += CertViewDlg::tr("Serial Number: %1").arg(cert.serialNumber().toString()) + '\n';
|
||||
out += print_info(CertViewDlg::tr("Subject"), cert.subjectInfo());
|
||||
out += print_info(CertViewDlg::tr("Issuer"), cert.issuerInfo());
|
||||
out += CertViewDlg::tr("Validity") + '\n';
|
||||
out += QString(" ") + CertViewDlg::tr("Not before: %1").arg(cert.notValidBefore().toString()) + '\n';
|
||||
out += QString(" ") + CertViewDlg::tr("Not after: %1").arg(cert.notValidAfter().toString()) + '\n';
|
||||
return out;
|
||||
}
|
||||
|
||||
class CertViewDlg::Private : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CertViewDlg *q;
|
||||
Ui_CertView ui;
|
||||
QCA::CertificateChain chain;
|
||||
|
||||
Private(CertViewDlg *_q) :
|
||||
QObject(_q),
|
||||
q(_q)
|
||||
{
|
||||
ui.setupUi(q);
|
||||
connect(ui.cb_chain, SIGNAL(activated(int)), SLOT(cb_activated(int)));
|
||||
ui.lb_info->setTextInteractionFlags(Qt::TextSelectableByMouse);
|
||||
}
|
||||
|
||||
void update()
|
||||
{
|
||||
QStringList names = QCA::makeFriendlyNames(chain);
|
||||
ui.cb_chain->clear();
|
||||
foreach(const QString &s, names)
|
||||
ui.cb_chain->insertItem(ui.cb_chain->count(), s);
|
||||
updateInfo();
|
||||
}
|
||||
|
||||
void updateInfo()
|
||||
{
|
||||
int x = ui.cb_chain->currentIndex();
|
||||
if(x == -1)
|
||||
{
|
||||
ui.lb_info->setText("");
|
||||
return;
|
||||
}
|
||||
|
||||
ui.lb_info->setText(cert_info_string(chain[x]));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void cb_activated(int)
|
||||
{
|
||||
updateInfo();
|
||||
}
|
||||
};
|
||||
|
||||
CertViewDlg::CertViewDlg(const QCA::CertificateChain &chain, QWidget *parent) :
|
||||
QDialog(parent)
|
||||
{
|
||||
d = new Private(this);
|
||||
d->chain = chain;
|
||||
d->update();
|
||||
}
|
||||
|
||||
CertViewDlg::~CertViewDlg()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
#include "certviewdlg.moc"
|
@ -19,23 +19,26 @@
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MYLISTVIEW_H
|
||||
#define MYLISTVIEW_H
|
||||
#ifndef CERTVIEWDLG_H
|
||||
#define CERTVIEWDLG_H
|
||||
|
||||
#include <QListView>
|
||||
#include <QDialog>
|
||||
|
||||
class QAbstractListModel;
|
||||
namespace QCA
|
||||
{
|
||||
class CertificateChain;
|
||||
}
|
||||
|
||||
class MyListView : public QListView
|
||||
class CertViewDlg : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
MyListView(QWidget *parent = 0);
|
||||
CertViewDlg(const QCA::CertificateChain &chain, QWidget *parent = 0);
|
||||
~CertViewDlg();
|
||||
|
||||
QAbstractListModel *model;
|
||||
|
||||
protected:
|
||||
virtual void contextMenuEvent(QContextMenuEvent *event);
|
||||
private:
|
||||
class Private;
|
||||
Private *d;
|
||||
};
|
||||
|
||||
#endif
|
@ -5,8 +5,16 @@ QT += gui
|
||||
|
||||
include(pkcs11configdlg/pkcs11configdlg.pri)
|
||||
|
||||
HEADERS += prompter.h keyselectdlg.h mylistview.h keystoreview.h
|
||||
SOURCES += prompter.cpp keyselectdlg.cpp main.cpp
|
||||
HEADERS += \
|
||||
prompter.h \
|
||||
certviewdlg.h \
|
||||
keyselectdlg.h
|
||||
|
||||
FORMS += keyselect.ui mainwin.ui
|
||||
SOURCES += \
|
||||
prompter.cpp \
|
||||
certviewdlg.cpp \
|
||||
keyselectdlg.cpp \
|
||||
main.cpp
|
||||
|
||||
FORMS += certview.ui keyselect.ui mainwin.ui
|
||||
RESOURCES += cmssigner.qrc
|
||||
|
@ -27,27 +27,33 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="KeyStoreView" name="lv_stores" />
|
||||
<widget class="QTreeView" name="lv_stores" />
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
<layout class="QHBoxLayout" >
|
||||
<property name="margin" >
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="standardButtons" >
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
|
||||
<property name="spacing" >
|
||||
<number>6</number>
|
||||
</property>
|
||||
</widget>
|
||||
<item>
|
||||
<widget class="QLabel" name="lb_busy" />
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox" >
|
||||
<property name="orientation" >
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons" >
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>KeyStoreView</class>
|
||||
<extends>QTreeView</extends>
|
||||
<header>keystoreview.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>lv_stores</tabstop>
|
||||
<tabstop>buttonBox</tabstop>
|
||||
|
@ -26,21 +26,40 @@
|
||||
#include <QtCrypto>
|
||||
#include "ui_keyselect.h"
|
||||
|
||||
class KeyStoreModel : public QStandardItemModel
|
||||
#define ONLY_SHOW_KEYBUNDLE
|
||||
|
||||
typedef QMap<KeySelectDlg::IconType,QPixmap> KeyStoreIconset;
|
||||
|
||||
class KeyStoreItemShared
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QMap<KeySelectDlg::IconType,QPixmap> iconset;
|
||||
KeyStoreIconset iconset;
|
||||
QString notAvailableString;
|
||||
};
|
||||
|
||||
QCA::KeyStoreManager ksm;
|
||||
QList<QCA::KeyStore*> stores;
|
||||
QList<QStandardItem*> storeItems;
|
||||
QList< QList<QCA::KeyStoreEntry> > storeEntries;
|
||||
QList< QList<QStandardItem*> > storeEntryItems;
|
||||
class KeyStoreItem : public QStandardItem
|
||||
{
|
||||
public:
|
||||
enum Type
|
||||
{
|
||||
Store = UserType,
|
||||
Entry
|
||||
};
|
||||
|
||||
QPixmap entryTypeToIcon(QCA::KeyStoreEntry::Type type)
|
||||
enum Role
|
||||
{
|
||||
NameRole = Qt::UserRole,
|
||||
SubTypeRole,
|
||||
AvailabilityRole,
|
||||
PositionRole
|
||||
};
|
||||
|
||||
QPixmap entryTypeToIcon(QCA::KeyStoreEntry::Type type) const
|
||||
{
|
||||
QPixmap out;
|
||||
if(!_shared)
|
||||
return out;
|
||||
const KeyStoreIconset &iconset = _shared->iconset;
|
||||
switch(type)
|
||||
{
|
||||
case QCA::KeyStoreEntry::TypeKeyBundle: out = iconset[KeySelectDlg::IconKeyBundle]; break;
|
||||
@ -53,9 +72,89 @@ public:
|
||||
return out;
|
||||
}
|
||||
|
||||
Type _type;
|
||||
KeyStoreItemShared *_shared;
|
||||
|
||||
QCA::KeyStore *keyStore;
|
||||
QCA::KeyStoreEntry keyStoreEntry;
|
||||
|
||||
KeyStoreItem(Type type, KeyStoreItemShared *shared) :
|
||||
_type(type),
|
||||
_shared(shared)
|
||||
{
|
||||
setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
|
||||
}
|
||||
|
||||
void setStore(const QString &name, QCA::KeyStore::Type type)
|
||||
{
|
||||
setData(name, NameRole);
|
||||
setData((int)type, SubTypeRole);
|
||||
}
|
||||
|
||||
void setEntry(const QString &name, QCA::KeyStoreEntry::Type type, bool available, int pos)
|
||||
{
|
||||
setData(name, NameRole);
|
||||
setData((int)type, SubTypeRole);
|
||||
setData(available, AvailabilityRole);
|
||||
setData(pos, PositionRole);
|
||||
}
|
||||
|
||||
virtual QVariant data(int role) const
|
||||
{
|
||||
if(role == Qt::DisplayRole)
|
||||
{
|
||||
if(_type == Store)
|
||||
{
|
||||
return data(NameRole).toString();
|
||||
}
|
||||
else if(_type == Entry)
|
||||
{
|
||||
QString str = data(NameRole).toString();
|
||||
if(_shared && !data(AvailabilityRole).toBool())
|
||||
str += QString(" ") + _shared->notAvailableString;
|
||||
return str;
|
||||
}
|
||||
else
|
||||
return QStandardItem::data(role);
|
||||
}
|
||||
else if(role == Qt::DecorationRole)
|
||||
{
|
||||
if(_type == Entry)
|
||||
{
|
||||
QCA::KeyStoreEntry::Type type = (QCA::KeyStoreEntry::Type)data(SubTypeRole).toInt();
|
||||
return entryTypeToIcon(type);
|
||||
}
|
||||
else
|
||||
return QStandardItem::data(role);
|
||||
}
|
||||
else
|
||||
return QStandardItem::data(role);
|
||||
}
|
||||
|
||||
virtual int type() const
|
||||
{
|
||||
return _type;
|
||||
}
|
||||
|
||||
virtual QStandardItem *clone() const
|
||||
{
|
||||
return new KeyStoreItem(*this);
|
||||
}
|
||||
};
|
||||
|
||||
class KeyStoreModel : public QStandardItemModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
KeyStoreItemShared shared;
|
||||
|
||||
QCA::KeyStoreManager ksm;
|
||||
|
||||
KeyStoreModel(QObject *parent = 0) :
|
||||
QStandardItemModel(parent), ksm(this)
|
||||
{
|
||||
shared.notAvailableString = tr("(not available)");
|
||||
|
||||
// make sure keystores are started
|
||||
QCA::KeyStoreManager::start();
|
||||
|
||||
@ -63,6 +162,19 @@ public:
|
||||
QStringList list = ksm.keyStores();
|
||||
foreach(const QString &s, list)
|
||||
ks_available(s);
|
||||
|
||||
setSortRole(KeyStoreItem::PositionRole);
|
||||
}
|
||||
|
||||
KeyStoreItem *itemFromStore(QCA::KeyStore *ks) const
|
||||
{
|
||||
for(int n = 0; n < rowCount(); ++n)
|
||||
{
|
||||
KeyStoreItem *i = (KeyStoreItem *)item(n);
|
||||
if(i->keyStore == ks)
|
||||
return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private slots:
|
||||
@ -70,63 +182,114 @@ private slots:
|
||||
{
|
||||
QCA::KeyStore *ks = new QCA::KeyStore(keyStoreId, &ksm);
|
||||
|
||||
// TODO: only list non-pgp identity stores
|
||||
//if(!ks->holdsIdentities() || ks->type() == QCA::KeyStore::PGPKeyring)
|
||||
// return;
|
||||
#ifdef ONLY_SHOW_KEYBUNDLE
|
||||
// only list stores containing keybundles (non-pgp identities)
|
||||
if(!ks->holdsIdentities() || ks->type() == QCA::KeyStore::PGPKeyring)
|
||||
return;
|
||||
#endif
|
||||
|
||||
connect(ks, SIGNAL(updated()), SLOT(ks_updated()));
|
||||
connect(ks, SIGNAL(unavailable()), SLOT(ks_unavailable()));
|
||||
stores += ks;
|
||||
ks->startAsynchronousMode();
|
||||
|
||||
QStandardItem *item = new QStandardItem(ks->name());
|
||||
storeItems += item;
|
||||
storeEntries += QList<QCA::KeyStoreEntry>();
|
||||
storeEntryItems += QList<QStandardItem*>();
|
||||
appendRow(item);
|
||||
KeyStoreItem *store_item = new KeyStoreItem(KeyStoreItem::Store, &shared);
|
||||
store_item->setStore(ks->name(), ks->type());
|
||||
store_item->keyStore = ks;
|
||||
ks->startAsynchronousMode();
|
||||
appendRow(store_item);
|
||||
}
|
||||
|
||||
void ks_updated()
|
||||
{
|
||||
QCA::KeyStore *ks = (QCA::KeyStore *)sender();
|
||||
int at = stores.indexOf(ks);
|
||||
QList<QCA::KeyStoreEntry> entries = ks->entryList();
|
||||
KeyStoreItem *store_item = itemFromStore(ks);
|
||||
Q_ASSERT(store_item);
|
||||
|
||||
// TODO: only list keybundles
|
||||
/*for(int n = 0; n < entries.count(); ++n)
|
||||
QList<QCA::KeyStoreEntry> newEntries = ks->entryList();
|
||||
|
||||
#ifdef ONLY_SHOW_KEYBUNDLE
|
||||
// ignore entries that are not keybundles
|
||||
for(int n = 0; n < newEntries.count(); ++n)
|
||||
{
|
||||
if(entries[n].type() != QCA::KeyStoreEntry::TypeKeyBundle)
|
||||
if(newEntries[n].type() != QCA::KeyStoreEntry::TypeKeyBundle)
|
||||
{
|
||||
entries.removeAt(n);
|
||||
newEntries.removeAt(n);
|
||||
--n; // adjust position
|
||||
}
|
||||
}*/
|
||||
|
||||
storeEntries[at] = entries;
|
||||
storeEntryItems[at].clear();
|
||||
|
||||
// fake CRL, just to show off the icon
|
||||
/*if(ks->type() == QCA::KeyStore::System)
|
||||
{
|
||||
QStandardItem *item = new QStandardItem(entryTypeToIcon(QCA::KeyStoreEntry::TypeCRL), "Santa's Naughty List");
|
||||
storeEntryItems[at] += item;
|
||||
storeItems[at]->appendRow(item);
|
||||
}*/
|
||||
|
||||
foreach(const QCA::KeyStoreEntry &entry, entries)
|
||||
{
|
||||
QStandardItem *item = new QStandardItem(entryTypeToIcon(entry.type()), entry.name());
|
||||
storeEntryItems[at] += item;
|
||||
storeItems[at]->appendRow(item);
|
||||
}
|
||||
#endif
|
||||
|
||||
// update the store item itself
|
||||
store_item->setStore(ks->name(), ks->type());
|
||||
|
||||
// handle removed child entries
|
||||
for(int n = 0; n < store_item->rowCount(); ++n)
|
||||
{
|
||||
KeyStoreItem *i = (KeyStoreItem *)store_item->child(n);
|
||||
|
||||
// is the existing entry in the new list?
|
||||
bool found = false;
|
||||
foreach(const QCA::KeyStoreEntry &ne, newEntries)
|
||||
{
|
||||
if(ne.id() == i->keyStoreEntry.id())
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if not, remove it
|
||||
if(!found)
|
||||
{
|
||||
store_item->removeRow(n);
|
||||
--n; // adjust position
|
||||
}
|
||||
}
|
||||
|
||||
// handle added/updated child entries
|
||||
for(int n = 0; n < newEntries.count(); ++n)
|
||||
{
|
||||
const QCA::KeyStoreEntry &ne = newEntries[n];
|
||||
|
||||
// was this entry in the original list?
|
||||
KeyStoreItem *entry_item = 0;
|
||||
for(int k = 0; k < store_item->rowCount(); ++k)
|
||||
{
|
||||
KeyStoreItem *i = (KeyStoreItem *)store_item->child(k);
|
||||
if(i->keyStoreEntry.id() == ne.id())
|
||||
{
|
||||
entry_item = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// if not, add it
|
||||
if(!entry_item)
|
||||
{
|
||||
entry_item = new KeyStoreItem(KeyStoreItem::Entry, &shared);
|
||||
entry_item->keyStoreEntry = ne;
|
||||
entry_item->setEntry(newEntries[n].name(), newEntries[n].type(), newEntries[n].isAvailable(), n);
|
||||
store_item->appendRow(entry_item);
|
||||
}
|
||||
// if so, update it
|
||||
else
|
||||
{
|
||||
entry_item->keyStoreEntry = ne;
|
||||
entry_item->setEntry(newEntries[n].name(), newEntries[n].type(), newEntries[n].isAvailable(), n);
|
||||
}
|
||||
}
|
||||
|
||||
store_item->sortChildren(0);
|
||||
}
|
||||
|
||||
void ks_unavailable()
|
||||
{
|
||||
QCA::KeyStore *ks = (QCA::KeyStore *)sender();
|
||||
Q_UNUSED(ks);
|
||||
KeyStoreItem *store_item = itemFromStore(ks);
|
||||
Q_ASSERT(store_item);
|
||||
|
||||
// TODO: remove from internal list and display
|
||||
store_item->removeRows(0, store_item->rowCount());
|
||||
removeRow(store_item->row());
|
||||
delete ks;
|
||||
}
|
||||
};
|
||||
|
||||
@ -138,6 +301,7 @@ public:
|
||||
Ui_KeySelect ui;
|
||||
KeyStoreModel *model;
|
||||
QCA::KeyStoreEntry cur_entry;
|
||||
QAction *actionView;
|
||||
|
||||
Private(KeySelectDlg *_q) :
|
||||
QObject(_q),
|
||||
@ -146,51 +310,90 @@ public:
|
||||
ui.setupUi(q);
|
||||
|
||||
model = new KeyStoreModel(this);
|
||||
connect(&model->ksm, SIGNAL(busyStarted()), SLOT(ksm_busyStarted()));
|
||||
connect(&model->ksm, SIGNAL(busyFinished()), SLOT(ksm_busyFinished()));
|
||||
if(model->ksm.isBusy())
|
||||
ksm_busyStarted();
|
||||
|
||||
ui.lv_stores->header()->hide();
|
||||
ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
|
||||
ui.lv_stores->setModel(model);
|
||||
ui.lv_stores->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(ui.lv_stores->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), SLOT(stores_selectionChanged(const QItemSelection &, const QItemSelection &)));
|
||||
connect(ui.lv_stores, SIGNAL(customContextMenuRequested(const QPoint &)), SLOT(stores_customContextMenuRequested(const QPoint &)));
|
||||
|
||||
actionView = new QAction(tr("&View"), this);
|
||||
connect(actionView, SIGNAL(triggered()), SLOT(view()));
|
||||
actionView->setEnabled(false);
|
||||
}
|
||||
|
||||
private slots:
|
||||
void ksm_busyStarted()
|
||||
{
|
||||
ui.lb_busy->setText(tr("Looking for devices..."));
|
||||
}
|
||||
|
||||
void ksm_busyFinished()
|
||||
{
|
||||
ui.lb_busy->setText("");
|
||||
}
|
||||
|
||||
void stores_selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
|
||||
{
|
||||
Q_UNUSED(deselected);
|
||||
|
||||
bool valid = false;
|
||||
QCA::KeyStoreEntry entry;
|
||||
KeyStoreItem *i = 0;
|
||||
if(!selected.indexes().isEmpty())
|
||||
{
|
||||
QModelIndex index;
|
||||
if(!selected.indexes().isEmpty())
|
||||
index = selected.indexes().first();
|
||||
if(index.isValid())
|
||||
{
|
||||
QModelIndex pindex = index.parent();
|
||||
// are we clicking on an entry?
|
||||
if(pindex.isValid())
|
||||
{
|
||||
int store_at = pindex.row();
|
||||
int entry_at = index.row();
|
||||
QModelIndex index = selected.indexes().first();
|
||||
i = (KeyStoreItem *)model->itemFromIndex(index);
|
||||
}
|
||||
|
||||
entry = model->storeEntries[store_at][entry_at];
|
||||
if(entry.type() == QCA::KeyStoreEntry::TypeKeyBundle)
|
||||
valid = true;
|
||||
}
|
||||
bool viewable = false;
|
||||
bool choosable = false;
|
||||
if(i && i->type() == KeyStoreItem::Entry)
|
||||
{
|
||||
QCA::KeyStoreEntry entry = i->keyStoreEntry;
|
||||
if(entry.type() == QCA::KeyStoreEntry::TypeKeyBundle)
|
||||
{
|
||||
viewable = true;
|
||||
choosable = true;
|
||||
cur_entry = entry;
|
||||
}
|
||||
}
|
||||
|
||||
if(valid)
|
||||
cur_entry = entry;
|
||||
else
|
||||
if(!choosable)
|
||||
cur_entry = QCA::KeyStoreEntry();
|
||||
|
||||
actionView->setEnabled(viewable);
|
||||
|
||||
QPushButton *ok = ui.buttonBox->button(QDialogButtonBox::Ok);
|
||||
if(valid && !ok->isEnabled())
|
||||
if(choosable && !ok->isEnabled())
|
||||
ok->setEnabled(true);
|
||||
else if(!valid && ok->isEnabled())
|
||||
else if(!choosable && ok->isEnabled())
|
||||
ok->setEnabled(false);
|
||||
}
|
||||
|
||||
void stores_customContextMenuRequested(const QPoint &pos)
|
||||
{
|
||||
QItemSelection selection = ui.lv_stores->selectionModel()->selection();
|
||||
if(selection.indexes().isEmpty())
|
||||
return;
|
||||
|
||||
QModelIndex index = selection.indexes().first();
|
||||
KeyStoreItem *i = (KeyStoreItem *)model->itemFromIndex(index);
|
||||
if(i && i->type() == KeyStoreItem::Entry)
|
||||
{
|
||||
QMenu menu(q);
|
||||
menu.addAction(actionView);
|
||||
menu.exec(ui.lv_stores->viewport()->mapToGlobal(pos));
|
||||
}
|
||||
}
|
||||
|
||||
void view()
|
||||
{
|
||||
emit q->viewCertificate(cur_entry.keyBundle().certificateChain());
|
||||
}
|
||||
};
|
||||
|
||||
KeySelectDlg::KeySelectDlg(QWidget *parent) :
|
||||
@ -206,7 +409,7 @@ KeySelectDlg::~KeySelectDlg()
|
||||
|
||||
void KeySelectDlg::setIcon(IconType type, const QPixmap &icon)
|
||||
{
|
||||
d->model->iconset[type] = icon;
|
||||
d->model->shared.iconset[type] = icon;
|
||||
}
|
||||
|
||||
void KeySelectDlg::accept()
|
||||
|
@ -28,6 +28,7 @@ class QPixmap;
|
||||
|
||||
namespace QCA
|
||||
{
|
||||
class CertificateChain;
|
||||
class KeyStoreEntry;
|
||||
}
|
||||
|
||||
@ -51,12 +52,14 @@ public:
|
||||
|
||||
signals:
|
||||
void selected(const QCA::KeyStoreEntry &entry);
|
||||
void viewCertificate(const QCA::CertificateChain &chain);
|
||||
|
||||
protected slots:
|
||||
virtual void accept();
|
||||
|
||||
private:
|
||||
class Private;
|
||||
friend class Private;
|
||||
Private *d;
|
||||
};
|
||||
|
||||
|
@ -1,41 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2007 Justin Karneges <justin@affinix.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef KEYSTOREVIEW_H
|
||||
#define KEYSTOREVIEW_H
|
||||
|
||||
#include <QTreeView>
|
||||
|
||||
//class QAbstractListModel;
|
||||
|
||||
class KeyStoreView : public QTreeView
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
KeyStoreView(QWidget *parent = 0) : QTreeView(parent) {}
|
||||
|
||||
//QAbstractListModel *model;
|
||||
|
||||
/*protected:
|
||||
virtual void contextMenuEvent(QContextMenuEvent *event);*/
|
||||
};
|
||||
|
||||
#endif
|
@ -25,8 +25,8 @@
|
||||
|
||||
#include "ui_mainwin.h"
|
||||
#include "prompter.h"
|
||||
#include "certviewdlg.h"
|
||||
#include "keyselectdlg.h"
|
||||
#include "mylistview.h"
|
||||
#include "pkcs11configdlg/pkcs11configdlg.h"
|
||||
|
||||
#define VERSION "0.0.1"
|
||||
@ -219,7 +219,12 @@ public:
|
||||
return QVariant();
|
||||
|
||||
if(role == Qt::DisplayRole)
|
||||
return list[index.row()].name;
|
||||
{
|
||||
QString str = list[index.row()].name;
|
||||
if(!list[index.row()].usable)
|
||||
str += QString(" ") + tr("(not usable)");
|
||||
return str;
|
||||
}
|
||||
else if(role == Qt::EditRole)
|
||||
return list[index.row()].name;
|
||||
else if(role == Qt::DecorationRole && g_icons)
|
||||
@ -574,7 +579,7 @@ private slots:
|
||||
|
||||
QAction *actionView, *actionRename, *actionRemove;
|
||||
|
||||
MyListView::MyListView(QWidget *parent) :
|
||||
/*MyListView::MyListView(QWidget *parent) :
|
||||
QListView(parent)
|
||||
{
|
||||
}
|
||||
@ -590,7 +595,7 @@ void MyListView::contextMenuEvent(QContextMenuEvent *event)
|
||||
menu.addAction(actionRename);
|
||||
menu.addAction(actionRemove);
|
||||
menu.exec(event->globalPos());
|
||||
}
|
||||
}*/
|
||||
|
||||
class MyPrompter : public Prompter
|
||||
{
|
||||
@ -654,7 +659,7 @@ public:
|
||||
actionRemove = new QAction(tr("Rem&ove"), this);
|
||||
|
||||
// TODO
|
||||
actionView->setEnabled(false);
|
||||
//actionView->setEnabled(false);
|
||||
|
||||
connect(ui.actionLoadIdentityFile, SIGNAL(triggered()), SLOT(load_file()));
|
||||
connect(ui.actionLoadIdentityEntry, SIGNAL(triggered()), SLOT(load_device()));
|
||||
@ -665,7 +670,7 @@ public:
|
||||
connect(ui.pb_sign, SIGNAL(clicked()), SLOT(do_sign()));
|
||||
connect(ui.pb_verify, SIGNAL(clicked()), SLOT(do_verify()));
|
||||
|
||||
//connect(actionView, SIGNAL(triggered()), SLOT(item_view()));
|
||||
connect(actionView, SIGNAL(triggered()), SLOT(item_view()));
|
||||
connect(actionRename, SIGNAL(triggered()), SLOT(item_rename()));
|
||||
connect(actionRemove, SIGNAL(triggered()), SLOT(item_remove()));
|
||||
|
||||
@ -677,12 +682,15 @@ public:
|
||||
ui.lv_users->setModel(users);
|
||||
connect(ui.lv_users->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), SLOT(users_selectionChanged(const QItemSelection &, const QItemSelection &)));
|
||||
|
||||
ui.lv_users->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(ui.lv_users, SIGNAL(customContextMenuRequested(const QPoint &)), SLOT(users_customContextMenuRequested(const QPoint &)));
|
||||
|
||||
roots = new CertListModel(this);
|
||||
ui.lv_authorities->setModel(roots);
|
||||
|
||||
// FIXME: is this redundant?
|
||||
ui.lv_users->model = users;
|
||||
ui.lv_authorities->model = roots;
|
||||
//ui.lv_users->model = users;
|
||||
//ui.lv_authorities->model = roots;
|
||||
|
||||
cms = new QCA::CMS(this);
|
||||
|
||||
@ -750,6 +758,7 @@ private slots:
|
||||
w->setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
w->setWindowModality(Qt::WindowModal);
|
||||
connect(w, SIGNAL(selected(const QCA::KeyStoreEntry &)), SLOT(load_device_finished(const QCA::KeyStoreEntry &)));
|
||||
connect(w, SIGNAL(viewCertificate(const QCA::CertificateChain &)), SLOT(keyselect_viewCertificate(const QCA::CertificateChain &)));
|
||||
w->setIcon(KeySelectDlg::IconCert, g_icons->cert);
|
||||
w->setIcon(KeySelectDlg::IconCrl, g_icons->crl);
|
||||
w->setIcon(KeySelectDlg::IconKeyBundle, g_icons->keybundle);
|
||||
@ -856,31 +865,38 @@ private slots:
|
||||
{
|
||||
Q_UNUSED(deselected);
|
||||
|
||||
if(!selected.indexes().isEmpty() && !ui.pb_sign->isEnabled())
|
||||
int at = -1;
|
||||
if(!selected.indexes().isEmpty())
|
||||
{
|
||||
QModelIndex index = selected.indexes().first();
|
||||
at = index.row();
|
||||
}
|
||||
|
||||
if(at != -1 && users->list[at].usable && !ui.pb_sign->isEnabled())
|
||||
ui.pb_sign->setEnabled(true);
|
||||
else if(selected.indexes().isEmpty() && ui.pb_sign->isEnabled())
|
||||
else if(ui.pb_sign->isEnabled())
|
||||
ui.pb_sign->setEnabled(false);
|
||||
}
|
||||
|
||||
/*void item_view()
|
||||
void item_view()
|
||||
{
|
||||
if(ui.lv_identities->hasFocus())
|
||||
if(ui.lv_users->hasFocus())
|
||||
{
|
||||
QItemSelection selection = ui.lv_identities->selectionModel()->selection();
|
||||
QItemSelection selection = ui.lv_users->selectionModel()->selection();
|
||||
if(selection.indexes().isEmpty())
|
||||
return;
|
||||
QModelIndex index = selection.indexes().first();
|
||||
identity_view(index.row());
|
||||
users_view(index.row());
|
||||
}
|
||||
else // lv_known
|
||||
/*else // lv_authorities
|
||||
{
|
||||
QItemSelection selection = ui.lv_known->selectionModel()->selection();
|
||||
if(selection.indexes().isEmpty())
|
||||
return;
|
||||
QModelIndex index = selection.indexes().first();
|
||||
known_view(index.row());
|
||||
}
|
||||
}*/
|
||||
}*/
|
||||
}
|
||||
|
||||
void item_rename()
|
||||
{
|
||||
@ -927,6 +943,14 @@ private slots:
|
||||
printf("identity_view: %d\n", at);
|
||||
}*/
|
||||
|
||||
void users_view(int at)
|
||||
{
|
||||
CertItem &i = users->list[at];
|
||||
CertViewDlg *w = new CertViewDlg(i.chain, this);
|
||||
w->setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
w->show();
|
||||
}
|
||||
|
||||
void users_rename(int at)
|
||||
{
|
||||
QModelIndex index = users->index(at);
|
||||
@ -960,6 +984,27 @@ private slots:
|
||||
roots->removeItem(at);
|
||||
}
|
||||
|
||||
void keyselect_viewCertificate(const QCA::CertificateChain &chain)
|
||||
{
|
||||
// TODO: completion?
|
||||
CertViewDlg *w = new CertViewDlg(chain, (QWidget *)sender());
|
||||
w->setAttribute(Qt::WA_DeleteOnClose, true);
|
||||
w->show();
|
||||
}
|
||||
|
||||
void users_customContextMenuRequested(const QPoint &pos)
|
||||
{
|
||||
QItemSelection selection = ui.lv_users->selectionModel()->selection();
|
||||
if(selection.indexes().isEmpty())
|
||||
return;
|
||||
|
||||
QMenu menu(this);
|
||||
menu.addAction(actionView);
|
||||
menu.addAction(actionRename);
|
||||
menu.addAction(actionRemove);
|
||||
menu.exec(ui.lv_users->viewport()->mapToGlobal(pos));
|
||||
}
|
||||
|
||||
void do_sign()
|
||||
{
|
||||
QItemSelection selection = ui.lv_users->selectionModel()->selection();
|
||||
|
@ -37,7 +37,7 @@
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="MyListView" name="lv_users" />
|
||||
<widget class="QListView" name="lv_users" />
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
@ -53,7 +53,7 @@
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="MyListView" name="lv_authorities" />
|
||||
<widget class="QListView" name="lv_authorities" />
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
@ -210,13 +210,6 @@
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>MyListView</class>
|
||||
<extends>QListView</extends>
|
||||
<header>mylistview.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>tabWidget</tabstop>
|
||||
<tabstop>lv_users</tabstop>
|
||||
|
Loading…
x
Reference in New Issue
Block a user