diff --git a/src/conf/kleopageconfigdialog.cpp b/src/conf/kleopageconfigdialog.cpp index 6a35dd8ba..586710ab7 100644 --- a/src/conf/kleopageconfigdialog.cpp +++ b/src/conf/kleopageconfigdialog.cpp @@ -1,250 +1,254 @@ /* kleopageconfigdialog.cpp This file is part of Kleopatra SPDX-FileCopyrightText: 2016 Bundesamt für Sicherheit in der Informationstechnik SPDX-FileContributor: Intevation GmbH SPDX-License-Identifier: GPL-2.0-only It is derived from KCMultidialog which is: SPDX-FileCopyrightText: 2000 Matthias Elter SPDX-FileCopyrightText: 2003 Daniel Molkentin SPDX-FileCopyrightText: 2003, 2006 Matthias Kretz SPDX-FileCopyrightText: 2004 Frans Englich SPDX-FileCopyrightText: 2006 Tobias Koenig SPDX-License-Identifier: LGPL-2.0-or-later */ #include #include "kleopageconfigdialog.h" #include #include #include #include #include #include #include #include #include #include #include "kleopatra_debug.h" KleoPageConfigDialog::KleoPageConfigDialog(QWidget *parent) : KPageDialog(parent) { setModal(false); QDialogButtonBox *buttonBox = new QDialogButtonBox(this); buttonBox->setStandardButtons(QDialogButtonBox::Help | QDialogButtonBox::RestoreDefaults | QDialogButtonBox::Cancel | QDialogButtonBox::Apply | QDialogButtonBox::Ok | QDialogButtonBox::Reset); KGuiItem::assign(buttonBox->button(QDialogButtonBox::Ok), KStandardGuiItem::ok()); KGuiItem::assign(buttonBox->button(QDialogButtonBox::Cancel), KStandardGuiItem::cancel()); KGuiItem::assign(buttonBox->button(QDialogButtonBox::RestoreDefaults), KStandardGuiItem::defaults()); KGuiItem::assign(buttonBox->button(QDialogButtonBox::Apply), KStandardGuiItem::apply()); KGuiItem::assign(buttonBox->button(QDialogButtonBox::Reset), KStandardGuiItem::reset()); KGuiItem::assign(buttonBox->button(QDialogButtonBox::Help), KStandardGuiItem::help()); buttonBox->button(QDialogButtonBox::Reset)->setEnabled(false); buttonBox->button(QDialogButtonBox::Apply)->setEnabled(false); connect(buttonBox->button(QDialogButtonBox::Apply), &QAbstractButton::clicked, this, &KleoPageConfigDialog::slotApplyClicked); connect(buttonBox->button(QDialogButtonBox::Ok), &QAbstractButton::clicked, this, &KleoPageConfigDialog::slotOkClicked); connect(buttonBox->button(QDialogButtonBox::RestoreDefaults), &QAbstractButton::clicked, this, &KleoPageConfigDialog::slotDefaultClicked); connect(buttonBox->button(QDialogButtonBox::Help), &QAbstractButton::clicked, this, &KleoPageConfigDialog::slotHelpClicked); connect(buttonBox->button(QDialogButtonBox::Reset), &QAbstractButton::clicked, this, &KleoPageConfigDialog::slotUser1Clicked); setButtonBox(buttonBox); connect(this, &KPageDialog::currentPageChanged, this, &KleoPageConfigDialog::slotCurrentPageChanged); } void KleoPageConfigDialog::slotCurrentPageChanged(KPageWidgetItem *current, KPageWidgetItem *previous) { if (!previous) { return; } blockSignals(true); setCurrentPage(previous); KCModule *previousModule = qobject_cast(previous->widget()); bool canceled = false; if (previousModule && mChangedModules.contains(previousModule)) { const int queryUser = KMessageBox::warningYesNoCancel( this, i18n("The settings of the current module have changed.\n" "Do you want to apply the changes or discard them?"), i18n("Apply Settings"), KStandardGuiItem::apply(), KStandardGuiItem::discard(), KStandardGuiItem::cancel()); if (queryUser == KMessageBox::Yes) { previousModule->save(); } else if (queryUser == KMessageBox::No) { previousModule->load(); } canceled = queryUser == KMessageBox::Cancel; } if (!canceled) { mChangedModules.removeAll(previousModule); setCurrentPage(current); } blockSignals(false); clientChanged(); } void KleoPageConfigDialog::apply() { QPushButton *applyButton = buttonBox()->button(QDialogButtonBox::Apply); applyButton->setFocus(); for (KCModule *module : mChangedModules) { module->save(); } mChangedModules.clear(); Q_EMIT configCommitted(); clientChanged(); } void KleoPageConfigDialog::slotDefaultClicked() { const KPageWidgetItem *item = currentPage(); if (!item) { return; } KCModule *module = qobject_cast(item->widget()); if (!module) { return; } module->defaults(); clientChanged(); } void KleoPageConfigDialog::slotUser1Clicked() { const KPageWidgetItem *item = currentPage(); if (!item) { return; } KCModule *module = qobject_cast(item->widget()); if (!module) { return; } module->load(); mChangedModules.removeAll(module); clientChanged(); } void KleoPageConfigDialog::slotApplyClicked() { apply(); } void KleoPageConfigDialog::slotOkClicked() { apply(); accept(); } void KleoPageConfigDialog::slotHelpClicked() { const KPageWidgetItem *item = currentPage(); if (!item) { return; } - const QString docPath = mHelpUrls.value(item->name()); + const QString name = item->name(); + auto it = std::find_if(mHelpUrls.cbegin(), mHelpUrls.cend(), [&name](const HelpUrlInfo &info) { + return info.name == name; + }); + const QString docPath = it != mHelpUrls.cend() ? it->docPath : QString{}; QUrl docUrl; #ifdef Q_OS_WIN docUrl = QUrl(QLatin1String("https://docs.kde.org/index.php?branch=stable5&language=") + QLocale().name() + QLatin1String("&application=kleopatra")); #else docUrl = QUrl(QStringLiteral("help:/")).resolved(QUrl(docPath)); // same code as in KHelpClient::invokeHelp #endif if (docUrl.scheme() == QLatin1String("help") || docUrl.scheme() == QLatin1String("man") || docUrl.scheme() == QLatin1String("info")) { const QString exec = QStandardPaths::findExecutable(QStringLiteral("khelpcenter")); if (exec.isEmpty()) { qCWarning(KLEOPATRA_LOG) << "Could not find khelpcenter in PATH."; } else { QProcess::startDetached(QStringLiteral("khelpcenter"), QStringList() << docUrl.toString()); } } else { QDesktopServices::openUrl(docUrl); } } void KleoPageConfigDialog::addModule(const QString &name, const QString &docPath, const QString &icon, KCModule *module) { mModules << module; KPageWidgetItem *item = addPage(module, name); item->setIcon(QIcon::fromTheme(icon)); connect(module, SIGNAL(changed(bool)), this, SLOT(moduleChanged(bool))); - mHelpUrls.insert(name, docPath); + mHelpUrls.push_back({name, docPath}); } void KleoPageConfigDialog::moduleChanged(bool state) { KCModule *module = qobject_cast(sender()); qCDebug(KLEOPATRA_LOG) << "Module changed: " << state << " mod " << module; if (mChangedModules.contains(module)) { if (!state) { mChangedModules.removeAll(module); } else { return; } } if (state) { mChangedModules << module; } clientChanged(); } void KleoPageConfigDialog::clientChanged() { const KPageWidgetItem *item = currentPage(); if (!item) { return; } KCModule *module = qobject_cast(item->widget()); if (!module) { return; } qCDebug(KLEOPATRA_LOG) << "Client changed: " << " mod " << module; bool change = mChangedModules.contains(module); QPushButton *resetButton = buttonBox()->button(QDialogButtonBox::Reset); if (resetButton) { resetButton->setEnabled(change); } QPushButton *applyButton = buttonBox()->button(QDialogButtonBox::Apply); if (applyButton) { applyButton->setEnabled(change); } } diff --git a/src/conf/kleopageconfigdialog.h b/src/conf/kleopageconfigdialog.h index adbec42d3..2af0db33e 100644 --- a/src/conf/kleopageconfigdialog.h +++ b/src/conf/kleopageconfigdialog.h @@ -1,50 +1,54 @@ /* kleopageconfigdialog.h.h This file is part of Kleopatra SPDX-FileCopyrightText: 2016 Bundesamt für Sicherheit in der Informationstechnik SPDX-FileContributor: Intevation GmbH SPDX-License-Identifier: GPL-2.0-only */ #pragma once #include #include class KPageWidgetItem; class KCModule; /** * KPageDialog based config dialog to be used when * KCMUtils are not available. */ class KleoPageConfigDialog : public KPageDialog { Q_OBJECT public: explicit KleoPageConfigDialog(QWidget *parent = nullptr); void addModule(const QString &name, const QString &docPath, const QString &icon, KCModule *module); Q_SIGNALS: void configCommitted(); protected Q_SLOTS: void slotDefaultClicked(); void slotUser1Clicked(); void slotApplyClicked(); void slotOkClicked(); void slotHelpClicked(); void slotCurrentPageChanged(KPageWidgetItem *current, KPageWidgetItem *previous); void moduleChanged(bool value); private: void clientChanged(); void apply(); QList mModules; QList mChangedModules; - QMap mHelpUrls; + struct HelpUrlInfo { + QString name; + QString docPath; + }; + std::vector mHelpUrls; }; diff --git a/src/dialogs/certificateselectiondialog.cpp b/src/dialogs/certificateselectiondialog.cpp index 94ae2e7d5..424bc8fe3 100644 --- a/src/dialogs/certificateselectiondialog.cpp +++ b/src/dialogs/certificateselectiondialog.cpp @@ -1,484 +1,485 @@ /* -*- mode: c++; c-basic-offset:4 -*- dialogs/certificateselectiondialog.cpp This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2008 Klarälvdalens Datakonsult AB SPDX-License-Identifier: GPL-2.0-or-later */ #include #include "certificateselectiondialog.h" #include "settings.h" #include "conf/groupsconfigdialog.h" #include #include #include #include "utils/tags.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace Kleo; using namespace Kleo::Dialogs; using namespace Kleo::Commands; using namespace GpgME; CertificateSelectionDialog::Option CertificateSelectionDialog::optionsFromProtocol(Protocol proto) { switch (proto) { case OpenPGP: return CertificateSelectionDialog::OpenPGPFormat; case CMS: return CertificateSelectionDialog::CMSFormat; default: return CertificateSelectionDialog::AnyFormat; } } namespace { auto protocolFromOptions(CertificateSelectionDialog::Options options) { switch (options & CertificateSelectionDialog::AnyFormat) { case CertificateSelectionDialog::OpenPGPFormat: return GpgME::OpenPGP; case CertificateSelectionDialog::CMSFormat: return GpgME::CMS; default: return GpgME::UnknownProtocol; } } } class CertificateSelectionDialog::Private { friend class ::Kleo::Dialogs::CertificateSelectionDialog; CertificateSelectionDialog *const q; public: explicit Private(CertificateSelectionDialog *qq); private: void reload() { Command *const cmd = new ReloadKeysCommand(nullptr); cmd->setParentWidget(q); cmd->start(); } void create() { auto cmd = new NewCertificateCommand(nullptr); cmd->setParentWidget(q); cmd->setProtocol(protocolFromOptions(options)); cmd->start(); } void lookup() { const auto cmd = new LookupCertificatesCommand(nullptr); cmd->setParentWidget(q); cmd->setProtocol(protocolFromOptions(options)); cmd->start(); } void manageGroups() { KConfigDialog *dialog = KConfigDialog::exists(GroupsConfigDialog::dialogName()); if (dialog) { // reparent the dialog to ensure it's shown on top of the modal CertificateSelectionDialog dialog->setParent(q, Qt::Dialog); } else { dialog = new GroupsConfigDialog(q); } dialog->show(); } void slotKeysMayHaveChanged(); void slotCurrentViewChanged(QAbstractItemView *newView); void slotSelectionChanged(); void slotDoubleClicked(const QModelIndex &idx); private: bool acceptable(const std::vector &keys, const std::vector &groups) { return !keys.empty() || !groups.empty(); } void updateLabelText() { ui.label.setText(!customLabelText.isEmpty() ? customLabelText : (options & MultiSelection) ? i18n("Please select one or more of the following certificates:") : i18n("Please select one of the following certificates:")); } private: - QSet connectedViews; + std::vector connectedViews; QString customLabelText; Options options = AnyCertificate | AnyFormat; struct UI { QLabel label; SearchBar searchBar; TabWidget tabWidget; QDialogButtonBox buttonBox; } ui; void setUpUI(CertificateSelectionDialog *q) { KDAB_SET_OBJECT_NAME(ui.label); KDAB_SET_OBJECT_NAME(ui.searchBar); KDAB_SET_OBJECT_NAME(ui.tabWidget); KDAB_SET_OBJECT_NAME(ui.buttonBox); auto vlay = new QVBoxLayout(q); vlay->addWidget(&ui.label); vlay->addWidget(&ui.searchBar); vlay->addWidget(&ui.tabWidget, 1); vlay->addWidget(&ui.buttonBox); QPushButton *const okButton = ui.buttonBox.addButton(QDialogButtonBox::Ok); okButton->setEnabled(false); ui.buttonBox.addButton(QDialogButtonBox::Close); QPushButton *const reloadButton = ui.buttonBox.addButton(i18n("Reload"), QDialogButtonBox::ActionRole); reloadButton->setToolTip(i18nc("@info:tooltip", "Refresh certificate list")); QPushButton *const importButton = ui.buttonBox.addButton(i18n("Import..."), QDialogButtonBox::ActionRole); importButton->setToolTip(i18nc("@info:tooltip", "Import certificate from file")); importButton->setAccessibleName(i18n("Import certificate")); QPushButton *const lookupButton = ui.buttonBox.addButton(i18n("Lookup..."), QDialogButtonBox::ActionRole); lookupButton->setToolTip(i18nc("@info:tooltip", "Look up certificate on server")); lookupButton->setAccessibleName(i18n("Look up certificate")); QPushButton *const createButton = ui.buttonBox.addButton(i18n("New..."), QDialogButtonBox::ActionRole); createButton->setToolTip(i18nc("@info:tooltip", "Create a new certificate")); createButton->setAccessibleName(i18n("Create certificate")); QPushButton *const groupsButton = ui.buttonBox.addButton(i18n("Groups..."), QDialogButtonBox::ActionRole); groupsButton->setToolTip(i18nc("@info:tooltip", "Manage certificate groups")); groupsButton->setAccessibleName(i18n("Manage groups")); groupsButton->setVisible(Settings().groupsEnabled()); connect(&ui.buttonBox, &QDialogButtonBox::accepted, q, &CertificateSelectionDialog::accept); connect(&ui.buttonBox, &QDialogButtonBox::rejected, q, &CertificateSelectionDialog::reject); connect(reloadButton, &QPushButton::clicked, q, [this] () { reload(); }); connect(lookupButton, &QPushButton::clicked, q, [this] () { lookup(); }); connect(createButton, &QPushButton::clicked, q, [this] () { create(); }); connect(groupsButton, &QPushButton::clicked, q, [this] () { manageGroups(); }); connect(KeyCache::instance().get(), &KeyCache::keysMayHaveChanged, q, [this] () { slotKeysMayHaveChanged(); }); connect(importButton, &QPushButton::clicked, q, [importButton, q] () { importButton->setEnabled(false); auto cmd = new Kleo::ImportCertificateFromFileCommand(); connect(cmd, &Kleo::ImportCertificateFromFileCommand::finished, q, [importButton]() { importButton->setEnabled(true); }); cmd->setParentWidget(q); cmd->start(); }); } }; CertificateSelectionDialog::Private::Private(CertificateSelectionDialog *qq) : q(qq) { setUpUI(q); ui.tabWidget.setFlatModel(AbstractKeyListModel::createFlatKeyListModel(q)); ui.tabWidget.setHierarchicalModel(AbstractKeyListModel::createHierarchicalKeyListModel(q)); const auto tagKeys = Tags::tagKeys(); ui.tabWidget.flatModel()->setRemarkKeys(tagKeys); ui.tabWidget.hierarchicalModel()->setRemarkKeys(tagKeys); ui.tabWidget.connectSearchBar(&ui.searchBar); connect(&ui.tabWidget, &TabWidget::currentViewChanged, q, [this] (QAbstractItemView *view) { slotCurrentViewChanged(view); }); updateLabelText(); q->setWindowTitle(i18nc("@title:window", "Certificate Selection")); } CertificateSelectionDialog::CertificateSelectionDialog(QWidget *parent) : QDialog(parent), d(new Private(this)) { const KSharedConfig::Ptr config = KSharedConfig::openConfig(QStringLiteral("kleopatracertificateselectiondialogrc")); d->ui.tabWidget.loadViews(config.data()); const KConfigGroup geometry(config, "Geometry"); resize(geometry.readEntry("size", size())); d->slotKeysMayHaveChanged(); } CertificateSelectionDialog::~CertificateSelectionDialog() {} void CertificateSelectionDialog::setCustomLabelText(const QString &txt) { if (txt == d->customLabelText) { return; } d->customLabelText = txt; d->updateLabelText(); } QString CertificateSelectionDialog::customLabelText() const { return d->customLabelText; } void CertificateSelectionDialog::setOptions(Options options) { Q_ASSERT((options & CertificateSelectionDialog::AnyCertificate) != 0); Q_ASSERT((options & CertificateSelectionDialog::AnyFormat) != 0); if (d->options == options) { return; } d->options = options; d->ui.tabWidget.setMultiSelection(options & MultiSelection); d->slotKeysMayHaveChanged(); d->updateLabelText(); } CertificateSelectionDialog::Options CertificateSelectionDialog::options() const { return d->options; } void CertificateSelectionDialog::setStringFilter(const QString &filter) { d->ui.tabWidget.setStringFilter(filter); } void CertificateSelectionDialog::setKeyFilter(const std::shared_ptr &filter) { d->ui.tabWidget.setKeyFilter(filter); } namespace { void selectRows(const QAbstractItemView *view, const QModelIndexList &indexes) { if (!view) { return; } QItemSelectionModel *const sm = view->selectionModel(); Q_ASSERT(sm); for (const QModelIndex &idx : std::as_const(indexes)) { if (idx.isValid()) { sm->select(idx, QItemSelectionModel::Select | QItemSelectionModel::Rows); } } } QModelIndexList getGroupIndexes(const KeyListModelInterface *model, const std::vector &groups) { QModelIndexList indexes; indexes.reserve(groups.size()); std::transform(groups.begin(), groups.end(), std::back_inserter(indexes), [model] (const KeyGroup &group) { return model->index(group); }); indexes.erase(std::remove_if(indexes.begin(), indexes.end(), [] (const QModelIndex &index) { return !index.isValid(); }), indexes.end()); return indexes; } } void CertificateSelectionDialog::selectCertificates(const std::vector &keys) { const auto *const model = d->ui.tabWidget.currentModel(); Q_ASSERT(model); selectRows(d->ui.tabWidget.currentView(), model->indexes(keys)); } void CertificateSelectionDialog::selectCertificate(const Key &key) { selectCertificates(std::vector(1, key)); } void CertificateSelectionDialog::selectGroups(const std::vector &groups) { const auto *const model = d->ui.tabWidget.currentModel(); Q_ASSERT(model); selectRows(d->ui.tabWidget.currentView(), getGroupIndexes(model, groups)); } namespace { QModelIndexList getSelectedRows(const QAbstractItemView *view) { if (!view) { return {}; } const QItemSelectionModel *const sm = view->selectionModel(); Q_ASSERT(sm); return sm->selectedRows(); } std::vector getGroups(const KeyListModelInterface *model, const QModelIndexList &indexes) { std::vector groups; groups.reserve(indexes.size()); std::transform(indexes.begin(), indexes.end(), std::back_inserter(groups), [model](const QModelIndex &idx) { return model->group(idx); }); groups.erase(std::remove_if(groups.begin(), groups.end(), std::mem_fn(&Kleo::KeyGroup::isNull)), groups.end()); return groups; } } std::vector CertificateSelectionDialog::selectedCertificates() const { const KeyListModelInterface *const model = d->ui.tabWidget.currentModel(); Q_ASSERT(model); return model->keys(getSelectedRows(d->ui.tabWidget.currentView())); } Key CertificateSelectionDialog::selectedCertificate() const { const std::vector keys = selectedCertificates(); return keys.empty() ? Key() : keys.front(); } std::vector CertificateSelectionDialog::selectedGroups() const { const KeyListModelInterface *const model = d->ui.tabWidget.currentModel(); Q_ASSERT(model); return getGroups(model, getSelectedRows(d->ui.tabWidget.currentView())); } void CertificateSelectionDialog::hideEvent(QHideEvent *e) { KSharedConfig::Ptr config = KSharedConfig::openConfig(QStringLiteral("kleopatracertificateselectiondialogrc")); d->ui.tabWidget.saveViews(config.data()); KConfigGroup geometry(config, "Geometry"); geometry.writeEntry("size", size()); QDialog::hideEvent(e); } void CertificateSelectionDialog::Private::slotKeysMayHaveChanged() { q->setEnabled(true); std::vector keys = (options & SecretKeys) ? KeyCache::instance()->secretKeys() : KeyCache::instance()->keys(); q->filterAllowedKeys(keys, options); const std::vector groups = (options & IncludeGroups) ? KeyCache::instance()->groups() : std::vector(); const std::vector selectedKeys = q->selectedCertificates(); const std::vector selectedGroups = q->selectedGroups(); if (AbstractKeyListModel *const model = ui.tabWidget.flatModel()) { model->setKeys(keys); model->setGroups(groups); } if (AbstractKeyListModel *const model = ui.tabWidget.hierarchicalModel()) { model->setKeys(keys); model->setGroups(groups); } q->selectCertificates(selectedKeys); q->selectGroups(selectedGroups); } void CertificateSelectionDialog::filterAllowedKeys(std::vector &keys, int options) { auto end = keys.end(); switch (options & AnyFormat) { case OpenPGPFormat: end = std::remove_if(keys.begin(), end, [](const Key &key) { return key.protocol() != OpenPGP; }); break; case CMSFormat: end = std::remove_if(keys.begin(), end, [](const Key &key) { return key.protocol() != CMS; }); break; default: case AnyFormat: ; } switch (options & AnyCertificate) { case SignOnly: end = std::remove_if(keys.begin(), end, [](const Key &key) { return !key.canReallySign(); }); break; case EncryptOnly: end = std::remove_if(keys.begin(), end, [](const Key &key) { return !key.canEncrypt(); }); break; default: case AnyCertificate: ; } if (options & SecretKeys) { end = std::remove_if(keys.begin(), end, [](const Key &key) { return !key.hasSecret(); }); } keys.erase(end, keys.end()); } void CertificateSelectionDialog::Private::slotCurrentViewChanged(QAbstractItemView *newView) { - if (!connectedViews.contains(newView)) { - connectedViews.insert(newView); + auto it = std::find(connectedViews.cbegin(), connectedViews.cend(), newView); + if (it == connectedViews.cend()) { + connectedViews.push_back(newView); connect(newView, &QAbstractItemView::doubleClicked, q, [this] (const QModelIndex &index) { slotDoubleClicked(index); }); Q_ASSERT(newView->selectionModel()); connect(newView->selectionModel(), &QItemSelectionModel::selectionChanged, q, [this] (const QItemSelection &, const QItemSelection &) { slotSelectionChanged(); }); } slotSelectionChanged(); } void CertificateSelectionDialog::Private::slotSelectionChanged() { if (QPushButton *const pb = ui.buttonBox.button(QDialogButtonBox::Ok)) { pb->setEnabled(acceptable(q->selectedCertificates(), q->selectedGroups())); } } void CertificateSelectionDialog::Private::slotDoubleClicked(const QModelIndex &idx) { QAbstractItemView *const view = ui.tabWidget.currentView(); Q_ASSERT(view); const auto *const model = ui.tabWidget.currentModel(); Q_ASSERT(model); Q_UNUSED(model) QItemSelectionModel *const sm = view->selectionModel(); Q_ASSERT(sm); sm->select(idx, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); QMetaObject::invokeMethod(q, [this]() {q->accept();}, Qt::QueuedConnection); } void CertificateSelectionDialog::accept() { if (d->acceptable(selectedCertificates(), selectedGroups())) { QDialog::accept(); } } #include "moc_certificateselectiondialog.cpp" diff --git a/src/smartcard/openpgpcard.cpp b/src/smartcard/openpgpcard.cpp index cf3c14c71..d317164de 100644 --- a/src/smartcard/openpgpcard.cpp +++ b/src/smartcard/openpgpcard.cpp @@ -1,105 +1,112 @@ /* smartcard/openpgpcard.cpp This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2017 Bundesamt für Sicherheit in der Informationstechnik SPDX-FileContributor: Intevation GmbH SPDX-FileCopyrightText: 2020 g10 Code GmbH SPDX-FileContributor: Ingo Klöcker SPDX-License-Identifier: GPL-2.0-or-later */ /* Code in this file is partly based on the GNU Privacy Assistant * (cm-openpgp.c) git rev. 0a78795146661234070681737b3e08228616441f * * Whis is: * SPDX-FileCopyrightText: 2008, 2009 g 10 Code GmbH * * And may be licensed under the GNU General Public License * as published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. */ #include "openpgpcard.h" #include #include "kleopatra_debug.h" using namespace Kleo; using namespace Kleo::SmartCard; // static const std::string OpenPGPCard::AppName = "openpgp"; OpenPGPCard::OpenPGPCard(const Card &card) : Card(card) { setAppName(AppName); setInitialKeyInfos(OpenPGPCard::supportedKeys()); } // static std::string OpenPGPCard::pgpSigKeyRef() { return std::string("OPENPGP.1"); } // static std::string OpenPGPCard::pgpEncKeyRef() { return std::string("OPENPGP.2"); } // static std::string OpenPGPCard::pgpAuthKeyRef() { return std::string("OPENPGP.3"); } // static std::string OpenPGPCard::pinKeyRef() { return std::string("OPENPGP.1"); } // static std::string OpenPGPCard::adminPinKeyRef() { return std::string("OPENPGP.3"); } // static std::string OpenPGPCard::resetCodeKeyRef() { return std::string("OPENPGP.2"); } // static const std::vector & OpenPGPCard::supportedKeys() { static const std::vector keyInfos = { {OpenPGPCard::pgpSigKeyRef(), "", "sc", "", ""}, {OpenPGPCard::pgpEncKeyRef(), "", "e", "", ""}, {OpenPGPCard::pgpAuthKeyRef(), "", "a", "", ""} }; return keyInfos; } // static QString OpenPGPCard::keyDisplayName(const std::string &keyRef) { - static const QMap displayNames = { + struct KeyInfo { + std::string name; + QString displayName; + }; + static const std::array displayNames = {{ { OpenPGPCard::pgpSigKeyRef(), i18n("Signature") }, { OpenPGPCard::pgpEncKeyRef(), i18n("Encryption") }, { OpenPGPCard::pgpAuthKeyRef(), i18n("Authentication") } - }; + }}; - return displayNames.value(keyRef); + auto it = std::find_if(displayNames.cbegin(), displayNames.cend(), [&keyRef](const KeyInfo &info) { + return info.name == keyRef; + }); + return it != displayNames.cend() ? it->displayName : QString{}; } std::string OpenPGPCard::pubkeyUrl() const { return cardInfo("PUBKEY-URL"); } diff --git a/src/smartcard/pivcard.cpp b/src/smartcard/pivcard.cpp index c285203b5..0bf816454 100644 --- a/src/smartcard/pivcard.cpp +++ b/src/smartcard/pivcard.cpp @@ -1,135 +1,142 @@ /* smartcard/pivcard.cpp This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2020 g10 Code GmbH SPDX-FileContributor: Ingo Klöcker SPDX-License-Identifier: GPL-2.0-or-later */ #include "pivcard.h" #include "keypairinfo.h" #include #include "kleopatra_debug.h" using namespace Kleo; using namespace Kleo::SmartCard; // static const std::string PIVCard::AppName = "piv"; PIVCard::PIVCard(const Card &card) : Card(card) { setAppName(AppName); setInitialKeyInfos(PIVCard::supportedKeys()); } // static std::string PIVCard::pivAuthenticationKeyRef() { return std::string("PIV.9A"); } // static std::string PIVCard::cardAuthenticationKeyRef() { return std::string("PIV.9E"); } // static std::string PIVCard::digitalSignatureKeyRef() { return std::string("PIV.9C"); } // static std::string PIVCard::keyManagementKeyRef() { return std::string("PIV.9D"); } // static std::string PIVCard::pinKeyRef() { return std::string("PIV.80"); } // static std::string PIVCard::pukKeyRef() { return std::string("PIV.81"); } // static const std::vector & PIVCard::supportedKeys() { static const std::vector keyInfos = { {PIVCard::pivAuthenticationKeyRef(), "", "a", "", ""}, {PIVCard::cardAuthenticationKeyRef(), "", "a", "", ""}, {PIVCard::digitalSignatureKeyRef(), "", "sc", "", ""}, {PIVCard::keyManagementKeyRef(), "", "e", "", ""} }; return keyInfos; } // static QString PIVCard::keyDisplayName(const std::string &keyRef) { - static const QMap displayNames = { + struct KeyInfo { + std::string name; + QString displayName; + }; + static const std::array displayNames = {{ { PIVCard::pivAuthenticationKeyRef(), i18n("PIV Authentication Key") }, { PIVCard::cardAuthenticationKeyRef(), i18n("Card Authentication Key") }, { PIVCard::digitalSignatureKeyRef(), i18n("Digital Signature Key") }, { PIVCard::keyManagementKeyRef(), i18n("Key Management Key") }, - }; + }}; - return displayNames.value(keyRef); + auto it = std::find_if(displayNames.cbegin(), displayNames.cend(), [&keyRef](const KeyInfo &info) { + return info.name == keyRef; + }); + return it != displayNames.cend() ? it->displayName : QString{}; } // static std::vector< std::pair > PIVCard::supportedAlgorithms(const std::string &keyRef) { if (keyRef == PIVCard::keyManagementKeyRef()) { return { { "rsa2048", i18n("RSA key transport (2048 bits)") }, { "nistp256", i18n("ECDH (Curve P-256)") }, { "nistp384", i18n("ECDH (Curve P-384)") } }; } else if (keyRef == PIVCard::digitalSignatureKeyRef()) { return { { "rsa2048", i18n("RSA (2048 bits)") }, { "nistp256", i18n("ECDSA (Curve P-256)") }, { "nistp384", i18n("ECDSA (Curve P-384)") } }; } // NIST SP 800-78-4 does not allow Curve P-384 for PIV Authentication key or Card Authentication key return { { "rsa2048", i18n("RSA (2048 bits)") }, { "nistp256", i18n("ECDSA (Curve P-256)") }, }; } std::string PIVCard::keyAlgorithm(const std::string &keyRef) const { return cardInfo("KLEO-KEYALGO-" + keyRef); } void PIVCard::setKeyAlgorithm(const std::string &keyRef, const std::string &algorithm) { addCardInfo("KLEO-KEYALGO-" + keyRef, algorithm); } std::string PIVCard::certificateData(const std::string &keyRef) const { return cardInfo("KLEO-CERTIFICATE-" + keyRef); } void PIVCard::setCertificateData(const std::string &keyRef, const std::string &data) { addCardInfo("KLEO-CERTIFICATE-" + keyRef, data); }