35class MyPrompter :
public Prompter
39 QMap<QString, QCA::SecureArray> known;
40 QMap<QString, QCA::SecureArray> maybe;
48 void fileSuccess(
const QString &fileName)
50 if (maybe.contains(fileName)) {
51 known[fileName] = maybe[fileName];
52 maybe.remove(fileName);
56 void fileFailed(
const QString &fileName)
58 maybe.remove(fileName);
59 known.remove(fileName);
63 virtual QCA::SecureArray knownPassword(
const QCA::Event &
event)
66 return known.value(
event.fileName());
68 return QCA::SecureArray();
71 virtual void userSubmitted(
const QCA::SecureArray &password,
const QCA::Event &
event)
74 maybe[
event.fileName()] = password;
84 for (
int n = 0; n < in.
length(); ++n) {
87 else if (in[n] ==
':')
89 else if (in[n] ==
'\n')
100 for (
int n = 0; n < in.
length(); ++n) {
102 if (n + 1 < in.
length()) {
106 else if (in[n] ==
'c')
108 else if (in[n] ==
'n')
121 QCA::CertificateChain chain;
123 StorageType storageType;
127 QCA::KeyStoreEntry keyStoreEntry;
128 QString keyStoreEntryString;
137 QString toString()
const
143 foreach (
const QCA::Certificate &cert, chain)
144 parts += QCA::Base64().arrayToString(cert.
toDER());
147 if (storageType == File) {
148 parts +=
"privateFile";
152 parts +=
"privateEntry";
153 if (!keyStoreEntry.isNull())
154 parts += keyStoreEntry.toString();
156 parts += keyStoreEntryString;
160 for (
int n = 0; n < parts.
count(); ++n)
161 parts[n] = escape(parts[n]);
162 return parts.
join(
":");
165 bool fromString(
const QString &in)
167 const QStringList parts = in.
split(
':');
168 for (
int n = 0; n < parts.
count(); ++n)
169 parts[n] = unescape(parts[n]);
171 if (parts.
count() < 3)
175 int chainCount = parts[1].toInt();
176 if (chainCount < 1 || chainCount > parts.
count() - 2)
179 for (
int n = 0; n < chainCount; ++n) {
185 int at = chain.count() + 2;
187 if (at < parts.
count()) {
191 if (parts[at] ==
"privateFile") {
193 fileName = parts[at + 1];
196 }
else if (parts[at] ==
"privateEntry") {
197 storageType = KeyStore;
198 keyStoreEntryString = parts[at + 1];
199 keyStoreEntry = QCA::KeyStoreEntry(keyStoreEntryString);
200 if (!keyStoreEntry.isNull())
214CertItem::CertItem(
const CertItem &from)
223CertItem &CertItem::operator=(
const CertItem &from)
239bool CertItem::havePrivate()
const
241 return d->havePrivate;
244CertItem::StorageType CertItem::storageType()
const
246 return d->storageType;
249bool CertItem::isUsable()
const
257static MyPrompter *g_prompter = 0;
258static int g_prompter_refs = 0;
260class CertItemStorePrivate :
public QObject
265 MyPrompter *prompter;
266 QList<CertItem> list;
268 CertItemIconset iconset;
276 QCA::KeyLoader *keyLoader;
280 QList<LoaderItem> loaders;
282 CertItemStorePrivate(CertItemStore *_q)
289 g_prompter =
new MyPrompter;
294 prompter = g_prompter;
297 ~CertItemStorePrivate()
299 foreach (
const LoaderItem &i, loaders)
303 if (g_prompter_refs == 0) {
309 QString getUniqueName(
const QString &name)
317 tryname =
name + QString(
" (%1)").
arg(num);
320 foreach (
const CertItem &i, list) {
321 if (i.name() == tryname) {
340 str =
tr(
"Incorrect passphrase.");
342 str =
tr(
"Unable to open or read file.");
345 str =
tr(
"Unable to decode format.");
351 void loader_finished()
353 QCA::KeyLoader *keyLoader = (QCA::KeyLoader *)
sender();
355 for (
int n = 0; n < loaders.count(); ++n) {
356 if (loaders[n].keyLoader == keyLoader) {
363 int req_id = loaders[at].req_id;
364 QString fileName = loaders[at].fileName;
370 prompter->fileFailed(fileName);
374 tr(
"Error importing certificate and private key.\nReason: %1").arg(convertErrorToString(r)));
375 emit q->addFailed(req_id);
379 prompter->fileSuccess(fileName);
381 QCA::KeyBundle kb = keyLoader->
keyBundle();
385 QCA::Certificate cert = chain.
primary();
390 i.d =
new CertItem::Private;
393 i.d->havePrivate =
true;
394 i.d->storageType = CertItem::File;
396 i.d->fileName = fileName;
400 q->beginInsertRows(QModelIndex(), list.size(), list.size());
405 emit q->addSuccess(req_id,
id);
409CertItemStore::CertItemStore(
QObject *parent)
412 d =
new CertItemStorePrivate(
this);
415CertItemStore::~CertItemStore()
420int CertItemStore::idFromRow(
int row)
const
422 return d->idList[row];
425int CertItemStore::rowFromId(
int id)
const
427 for (
int n = 0; n < d->idList.count(); ++n) {
428 if (d->idList[n] ==
id)
434CertItem CertItemStore::itemFromId(
int id)
const
436 return d->list[rowFromId(
id)];
439CertItem CertItemStore::itemFromRow(
int row)
const
452 foreach (
const CertItem &i, d->list)
453 out += i.d->toString();
459 QList<CertItem> addList;
460 QList<int> addIdList;
461 foreach (
const QString &s,
in) {
463 i.d =
new CertItem::Private;
464 if (i.d->fromString(s)) {
466 addIdList += d->next_id++;
475 d->idList += addIdList;
481int CertItemStore::addFromFile(
const QString &fileName)
483 CertItemStorePrivate::LoaderItem i;
484 i.req_id = d->next_req_id++;
485 i.keyLoader =
new QCA::KeyLoader(d);
486 i.fileName = fileName;
487 connect(i.keyLoader, SIGNAL(finished()), d, SLOT(loader_finished()));
498 QCA::Certificate cert = chain.
primary();
500 QString
name = d->getUniqueName(entry.
name());
503 i.d =
new CertItem::Private;
506 i.d->havePrivate =
true;
507 i.d->storageType = CertItem::KeyStore;
509 i.d->keyStoreEntry = entry;
511 int id = d->next_id++;
518 int req_id = d->next_req_id++;
525 QCA::Certificate cert = chain.
primary();
530 i.d =
new CertItem::Private;
534 int id = d->next_id++;
541 int req_id = d->next_req_id++;
548 int at = rowFromId(
id);
549 d->list[at].d->chain = chain;
552void CertItemStore::removeItem(
int id)
554 int at = rowFromId(
id);
557 d->list.removeAt(at);
558 d->idList.removeAt(at);
562void CertItemStore::setIcon(IconType type,
const QPixmap &icon)
564 d->iconset[
type] = icon;
567int CertItemStore::rowCount(
const QModelIndex &parent)
const
570 return d->list.count();
575 if (!
index.isValid())
578 int at =
index.row();
579 QList<CertItem> &
list = d->list;
585 QString str =
list[at].name();
586 if (list[at].havePrivate() && !list[at].isUsable())
587 str += QString(
" ") +
tr(
"(not usable)");
590 return list[at].name();
592 if (list[at].havePrivate())
593 return d->iconset[CertItemStore::IconKeyBundle];
595 return d->iconset[CertItemStore::IconCert];
602 if (!
index.isValid())
612 d->list[
index.row()].d->name = str;
622class CertItemPrivateLoaderPrivate :
public QObject
626 CertItemPrivateLoader *q;
627 CertItemStore *store;
628 QCA::KeyLoader *loader;
632 CertItemPrivateLoaderPrivate(CertItemPrivateLoader *_q)
639 void loader_finished()
645 store->d->prompter->fileFailed(fileName);
649 tr(
"Error accessing private key.\nReason: %1").arg(CertItemStorePrivate::convertErrorToString(r)));
654 store->d->prompter->fileSuccess(fileName);
656 key = loader->keyBundle().privateKey();
663CertItemPrivateLoader::CertItemPrivateLoader(CertItemStore *store,
QObject *parent)
666 d =
new CertItemPrivateLoaderPrivate(
this);
670CertItemPrivateLoader::~CertItemPrivateLoader()
675void CertItemPrivateLoader::start(
int id)
677 CertItem i = d->store->itemFromId(
id);
679 if (i.storageType() == CertItem::KeyStore) {
680 d->key = i.d->keyStoreEntry.keyBundle().privateKey();
685 d->key = QCA::PrivateKey();
686 d->fileName = i.d->fileName;
687 d->loader =
new QCA::KeyLoader(d);
688 connect(d->loader, SIGNAL(finished()), d, SLOT(loader_finished()));
689 d->loader->loadKeyBundleFromFile(d->fileName);
697#include "certitem.moc"
A chain of related Certificates.
const Certificate & primary() const
Return the primary (end-user) Certificate.
QString commonName() const
The common name of the subject of the certificate.
static Certificate fromDER(const QByteArray &a, ConvertResult *result=nullptr, const QString &provider=QString())
Import the certificate from DER.
bool isNull() const
Test if the certificate is empty (null)
QByteArray toDER() const
Export the Certificate into a DER format.
@ Data
File or bytearray generated the event.
CertificateChain certificateChain() const
The public certificate part of this bundle.
void loadKeyBundleFromFile(const QString &fileName)
Initiate an asynchronous loading of a KeyBundle from a file.
ConvertResult convertResult() const
The result of the loading process.
KeyBundle keyBundle() const
The key bundle that has been loaded.
Single entry in a KeyStore.
KeyBundle keyBundle() const
If a KeyBundle is stored in this object, return that bundle.
QString name() const
The name associated with the key stored in this object.
VehicleSection::Type type(QStringView coachNumber, QStringView coachClassification)
KIOCORE_EXPORT QStringList list(const QString &fileClass)
QString name(StandardAction id)
ConvertResult
Return value from a format conversion.
@ ErrorFile
Failure because of incorrect file.
@ ErrorPassphrase
Failure because of incorrect passphrase.
@ ConvertGood
Conversion succeeded, results should be valid.
@ ErrorDecode
General failure in the decode stage.
void beginInsertRows(const QModelIndex &parent, int first, int last)
void beginRemoveRows(const QModelIndex &parent, int first, int last)
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QList< int > &roles)
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const const=0
virtual QModelIndex parent(const QModelIndex &index) const const=0
bool exists() const const
qsizetype count() const const
bool isEmpty() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
virtual bool event(QEvent *e)
QObject * parent() const const
QObject * sender() const const
QString tr(const char *sourceText, const char *disambiguation, int n)
QString arg(Args &&... args) const const
qsizetype length() const const
QString number(double n, char format, int precision)
QString & removeAt(qsizetype pos)
QStringList split(QChar sep, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
QString join(QChar separator) const const
QString toString() const const