Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F34381570
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
34 KB
Subscribers
None
View Options
diff --git a/src/view/netkeywidget.cpp b/src/view/netkeywidget.cpp
index 6c5465e3b..f05a2aa3f 100644
--- a/src/view/netkeywidget.cpp
+++ b/src/view/netkeywidget.cpp
@@ -1,238 +1,240 @@
/* view/netkeywidget.cpp
This file is part of Kleopatra, the KDE keymanager
Copyright (c) 2017 Intevation GmbH
Kleopatra is free software; you can redistribute it and/or modify
it under the terms of 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.
Kleopatra is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
In addition, as a special exception, the copyright holders give
permission to link the code of this program with any edition of
the Qt library by Trolltech AS, Norway (or with modified versions
of Qt that use the same license as Qt), and distribute linked
combinations including the two. You must obey the GNU General
Public License in all respects for all of the code used other than
Qt. If you modify this file, you may extend this exception to
your version of the file, but you are not obligated to do so. If
you do not wish to do so, delete this exception statement from
your version.
*/
#include "netkeywidget.h"
#include "nullpinwidget.h"
#include "keytreeview.h"
#include "kleopatra_debug.h"
#include "smartcard/netkeycard.h"
#include "smartcard/readerstatus.h"
#include "commands/learncardkeyscommand.h"
#include "commands/detailscommand.h"
#include <Libkleo/KeyListModel>
#include <QLabel>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QScrollArea>
#include <QPushButton>
#include <QTreeView>
#include <KLocalizedString>
#include <KMessageBox>
using namespace Kleo;
using namespace Kleo::SmartCard;
using namespace Kleo::Commands;
NetKeyWidget::NetKeyWidget() :
mSerialNumber(new QLabel),
mVersionLabel(new QLabel),
mLearnKeysLabel(new QLabel),
mErrorLabel(new QLabel),
mNullPinWidget(new NullPinWidget()),
mLearnKeysBtn(new QPushButton),
mChangeNKSPINBtn(new QPushButton),
mChangeSigGPINBtn(new QPushButton),
mTreeView(new KeyTreeView(this)),
mArea(new QScrollArea)
{
auto vLay = new QVBoxLayout;
// Set up the scroll are
mArea->setFrameShape(QFrame::NoFrame);
mArea->setWidgetResizable(true);
auto mAreaWidget = new QWidget;
mAreaWidget->setLayout(vLay);
mArea->setWidget(mAreaWidget);
auto scrollLay = new QVBoxLayout(this);
scrollLay->addWidget(mArea);
// Add general widgets
mVersionLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
vLay->addWidget(mVersionLabel, 0, Qt::AlignLeft);
mSerialNumber->setTextInteractionFlags(Qt::TextBrowserInteraction);
auto hLay1 = new QHBoxLayout;
hLay1->addWidget(new QLabel(i18n("Serial number:")));
hLay1->addWidget(mSerialNumber);
hLay1->addStretch(1);
vLay->addLayout(hLay1);
vLay->addWidget(mNullPinWidget);
auto line1 = new QFrame();
line1->setFrameShape(QFrame::HLine);
vLay->addWidget(line1);
vLay->addWidget(new QLabel(QStringLiteral("<b>%1</b>").arg(i18n("Certificates:"))), 0, Qt::AlignLeft);
mLearnKeysLabel = new QLabel(i18n("There are unknown certificates on this card."));
mLearnKeysBtn->setText(i18nc("@action", "Load Certificates"));
connect(mLearnKeysBtn, &QPushButton::clicked, this, [this] () {
mLearnKeysBtn->setEnabled(false);
auto cmd = new LearnCardKeysCommand(GpgME::CMS);
cmd->setParentWidget(this);
cmd->start();
connect(cmd, &Command::finished, this, [] () {
ReaderStatus::mutableInstance()->updateStatus();
});
});
auto hLay2 = new QHBoxLayout;
hLay2->addWidget(mLearnKeysLabel);
hLay2->addWidget(mLearnKeysBtn);
hLay2->addStretch(1);
vLay->addLayout(hLay2);
mErrorLabel->setVisible(false);
vLay->addWidget(mErrorLabel);
// The certificate view
mTreeView->setHierarchicalModel(AbstractKeyListModel::createHierarchicalKeyListModel(mTreeView));
mTreeView->setHierarchicalView(true);
connect(mTreeView->view(), &QAbstractItemView::doubleClicked, this, [this] (const QModelIndex &idx) {
const auto klm = dynamic_cast<KeyListModelInterface *> (mTreeView->view()->model());
if (!klm) {
qCDebug(KLEOPATRA_LOG) << "Unhandled Model: " << mTreeView->view()->model()->metaObject()->className();
return;
}
auto cmd = new DetailsCommand(klm->key(idx), nullptr);
cmd->setParentWidget(this);
cmd->start();
});
vLay->addWidget(mTreeView);
// The action area
auto line2 = new QFrame();
line2->setFrameShape(QFrame::HLine);
vLay->addWidget(line2);
vLay->addWidget(new QLabel(QStringLiteral("<b>%1</b>").arg(i18n("Actions:"))), 0, Qt::AlignLeft);
mChangeNKSPINBtn->setText(i18nc("NKS is an identifier for a type of keys on a NetKey card", "Change NKS PIN"));
mChangeSigGPINBtn->setText(i18nc("SigG is an identifier for a type of keys on a NetKey card", "Change SigG PIN"));
connect(mChangeNKSPINBtn, &QPushButton::clicked, this, [this] () {
mChangeNKSPINBtn->setEnabled(false);
doChangePin(false);
});
connect(mChangeSigGPINBtn, &QPushButton::clicked, this, [this] () {
mChangeSigGPINBtn->setEnabled(false);
doChangePin(true);
});
auto hLay3 = new QHBoxLayout();
hLay3->addWidget(mChangeNKSPINBtn);
hLay3->addWidget(mChangeSigGPINBtn);
hLay3->addStretch(1);
vLay->addLayout(hLay3);
+ vLay->addStretch(1);
}
void NetKeyWidget::setCard(const NetKeyCard* card)
{
mVersionLabel->setText(i18nc("1 is a Version number", "NetKey v%1 Card", card->appVersion()));
mSerialNumber->setText(QString::fromStdString(card->serialNumber()));
/* According to users of NetKey Cards it is fairly uncommon
* to use SigG Certificates at all. So it should be optional to set the pins. */
mNullPinWidget->setVisible(card->hasNKSNullPin() /*|| card->hasSigGNullPin()*/);
mNullPinWidget->setSigGVisible(false/*card->hasSigGNullPin()*/);
mNullPinWidget->setNKSVisible(card->hasNKSNullPin());
mChangeNKSPINBtn->setEnabled(!card->hasNKSNullPin());
if (card->hasSigGNullPin()) {
mChangeSigGPINBtn->setText(i18nc("SigG is an identifier for a type of keys on a NetKey card",
"Set SigG PIN"));
} else {
mChangeSigGPINBtn->setText(i18nc("SigG is an identifier for a type of keys on a NetKey card",
"Change SigG PIN"));
}
mLearnKeysBtn->setEnabled(true);
mLearnKeysBtn->setVisible(card->canLearnKeys());
+ mTreeView->setVisible(!card->canLearnKeys());
mLearnKeysLabel->setVisible(card->canLearnKeys());
const auto errMsg = card->errorMsg();
if (!errMsg.isEmpty()) {
mErrorLabel->setText(QStringLiteral("<b>%1:</b> %2").arg(i18n("Error")).arg(errMsg));
mErrorLabel->setVisible(true);
} else {
mErrorLabel->setVisible(false);
}
const auto keys = card->keys();
mTreeView->setKeys(keys);
}
void NetKeyWidget::handleResult(const GpgME::Error &err, QPushButton *btn)
{
btn->setEnabled(true);
if (err.isCanceled()) {
return;
}
if (err) {
KMessageBox::error(this, i18nc("@info",
"Failed to set PIN: %1", err.asString()),
i18nc("@title", "Error"));
return;
}
}
void NetKeyWidget::setSigGPinSettingResult(const GpgME::Error &err)
{
handleResult(err, mChangeSigGPINBtn);
}
void NetKeyWidget::setNksPinSettingResult(const GpgME::Error &err)
{
handleResult(err, mChangeNKSPINBtn);
}
void NetKeyWidget::doChangePin(bool sigG)
{
if (sigG) {
ReaderStatus::mutableInstance()
->startSimpleTransaction("SCD PASSWD PW1.CH.SIG",
this, "setSigGPinSettingResult");
} else {
ReaderStatus::mutableInstance()
->startSimpleTransaction("SCD PASSWD PW1.CH",
this, "setNksPinSettingResult");
}
}
diff --git a/src/view/pgpcardwidget.cpp b/src/view/pgpcardwidget.cpp
index 504fc1ec6..541317056 100644
--- a/src/view/pgpcardwidget.cpp
+++ b/src/view/pgpcardwidget.cpp
@@ -1,504 +1,506 @@
/* view/pgpcardwiget.cpp
This file is part of Kleopatra, the KDE keymanager
Copyright (c) 2017 by Bundesamt für Sicherheit in der Informationstechnik
Software engineering by Intevation GmbH
Kleopatra is free software; you can redistribute it and/or modify
it under the terms of 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.
Kleopatra is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
In addition, as a special exception, the copyright holders give
permission to link the code of this program with any edition of
the Qt library by Trolltech AS, Norway (or with modified versions
of Qt that use the same license as Qt), and distribute linked
combinations including the two. You must obey the GNU General
Public License in all respects for all of the code used other than
Qt. If you modify this file, you may extend this exception to
your version of the file, but you are not obligated to do so. If
you do not wish to do so, delete this exception statement from
your version.
*/
#include "pgpcardwidget.h"
#include "kleopatra_debug.h"
#include "smartcard/openpgpcard.h"
#include "smartcard/readerstatus.h"
#include "dialogs/gencardkeydialog.h"
#include <QProgressDialog>
#include <QThread>
#include <QScrollArea>
#include <QInputDialog>
#include <QFileDialog>
#include <QFileInfo>
#include <QGridLayout>
#include <QPushButton>
#include <QLabel>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <KLocalizedString>
#include <KMessageBox>
#include <Libkleo/KeyCache>
#include <Libkleo/Formatting>
#include <gpgme++/gpgmepp_version.h>
#include <gpgme++/data.h>
#include <gpgme++/context.h>
#include <QGpgME/DataProvider>
#if GPGMEPP_VERSION > 0x10801 // 1.8.1
// TODO remove ifdef once > 1.8.1 is required
#include <gpgme++/gpggencardkeyinteractor.h>
# define GPGME_CAN_GENCARDKEY
#endif
using namespace Kleo;
using namespace Kleo::SmartCard;
namespace {
#ifdef GPGME_CAN_GENCARDKEY
class GenKeyThread: public QThread
{
Q_OBJECT
public:
explicit GenKeyThread(const GenCardKeyDialog::KeyParams ¶ms, const std::string &serial):
mSerial(serial),
mParams(params)
{
}
GpgME::Error error()
{
return mErr;
}
std::string bkpFile()
{
return mBkpFile;
}
protected:
void run() override {
GpgME::GpgGenCardKeyInteractor *ei = new GpgME::GpgGenCardKeyInteractor(mSerial);
ei->setKeySize(mParams.keysize);
ei->setNameUtf8(mParams.name.toStdString());
ei->setEmailUtf8(mParams.email.toStdString());
ei->setDoBackup(mParams.backup);
const auto ctx = std::shared_ptr<GpgME::Context> (GpgME::Context::createForProtocol(GpgME::OpenPGP));
QGpgME::QByteArrayDataProvider dp;
GpgME::Data data(&dp);
mErr = ctx->cardEdit(GpgME::Key(), std::unique_ptr<GpgME::EditInteractor> (ei), data);
mBkpFile = ei->backupFileName();
}
private:
GpgME::Error mErr;
std::string mSerial;
GenCardKeyDialog::KeyParams mParams;
std::string mBkpFile;
};
#endif
} // Namespace
PGPCardWidget::PGPCardWidget():
mSerialNumber(new QLabel),
mCardHolderLabel(new QLabel),
mVersionLabel(new QLabel),
mSigningKey(new QLabel),
mEncryptionKey(new QLabel),
mAuthKey(new QLabel),
mUrlLabel(new QLabel),
mCardIsEmpty(false)
{
auto grid = new QGridLayout;
int row = 0;
// Set up the scroll are
auto area = new QScrollArea;
area->setFrameShape(QFrame::NoFrame);
area->setWidgetResizable(true);
auto areaWidget = new QWidget;
- areaWidget->setLayout(grid);
+ auto areaVLay = new QVBoxLayout(areaWidget);
+ areaVLay->addLayout(grid);
+ areaVLay->addStretch(1);
area->setWidget(areaWidget);
auto myLayout = new QVBoxLayout(this);
myLayout->addWidget(area);
// Version and Serialnumber
grid->addWidget(mVersionLabel, row++, 0, 1, 2);
mVersionLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
grid->addWidget(new QLabel(i18n("Serial number:")), row, 0);
grid->addWidget(mSerialNumber, row++, 1);
mSerialNumber->setTextInteractionFlags(Qt::TextBrowserInteraction);
// Cardholder Row
grid->addWidget(new QLabel(i18nc("The owner of a smartcard. GnuPG refers to this as cardholder.",
"Cardholder:")), row, 0);
grid->addWidget(mCardHolderLabel, row, 1);
mCardHolderLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
auto nameButtton = new QPushButton;
nameButtton->setIcon(QIcon::fromTheme("cell_edit"));
nameButtton->setToolTip(i18n("Change"));
grid->addWidget(nameButtton, row++, 2);
connect(nameButtton, &QPushButton::clicked, this, &PGPCardWidget::changeNameRequested);
// URL Row
grid->addWidget(new QLabel(i18nc("The URL under which a public key that "
"corresponds to a smartcard can be downloaded",
"Pubkey URL:")), row, 0);
grid->addWidget(mUrlLabel, row, 1);
mUrlLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
auto urlButtton = new QPushButton;
urlButtton->setIcon(QIcon::fromTheme("cell_edit"));
urlButtton->setToolTip(i18n("Change"));
grid->addWidget(urlButtton, row++, 2);
connect(urlButtton, &QPushButton::clicked, this, &PGPCardWidget::changeUrlRequested);
// The keys
auto line1 = new QFrame();
line1->setFrameShape(QFrame::HLine);
grid->addWidget(line1, row++, 0, 1, 4);
grid->addWidget(new QLabel(QStringLiteral("<b>%1</b>").arg(i18n("Keys:"))), row++, 0);
grid->addWidget(new QLabel(i18n("Signature:")), row, 0);
grid->addWidget(mSigningKey, row++, 1);
mSigningKey->setTextInteractionFlags(Qt::TextBrowserInteraction);
grid->addWidget(new QLabel(i18n("Encryption:")), row, 0);
grid->addWidget(mEncryptionKey, row++, 1);
mEncryptionKey->setTextInteractionFlags(Qt::TextBrowserInteraction);
grid->addWidget(new QLabel(i18n("Authentication:")), row, 0);
grid->addWidget(mAuthKey, row++, 1);
mAuthKey->setTextInteractionFlags(Qt::TextBrowserInteraction);
auto line2 = new QFrame();
line2->setFrameShape(QFrame::HLine);
grid->addWidget(line2, row++, 0, 1, 4);
grid->addWidget(new QLabel(QStringLiteral("<b>%1</b>").arg(i18n("Actions:"))), row++, 0);
auto actionLayout = new QHBoxLayout;
#ifdef GPGME_CAN_GENCARDKEY
auto generateButton = new QPushButton(i18n("Generate new Keys"));
generateButton->setToolTip(i18n("Create a new primary key and generate subkeys on the card."));
actionLayout->addWidget(generateButton);
connect(generateButton, &QPushButton::clicked, this, &PGPCardWidget::genkeyRequested);
#endif
auto pinButtton = new QPushButton(i18n("Change PIN"));
pinButtton->setToolTip(i18n("Change the PIN required to unblock the smartcard."));
actionLayout->addWidget(pinButtton);
connect(pinButtton, &QPushButton::clicked, this, [this] () {doChangePin(1);});
auto pukButton = new QPushButton(i18n("Change Admin PIN"));
pukButton->setToolTip(i18n("Change the PIN required to unlock the smartcard."));
actionLayout->addWidget(pukButton);
connect(pukButton, &QPushButton::clicked, this, [this] () {doChangePin(3);});
auto resetCodeButton = new QPushButton(i18n("Change Reset Code"));
pukButton->setToolTip(i18n("Change the PIN required to reset the smartcard to an empty state."));
actionLayout->addWidget(resetCodeButton);
connect(resetCodeButton, &QPushButton::clicked, this, [this] () {doChangePin(2);});
actionLayout->addStretch(-1);
grid->addLayout(actionLayout, row++, 0, 1, 4);
grid->setColumnStretch(4, -1);
}
void PGPCardWidget::setCard(const OpenPGPCard *card)
{
const QString version = QString::fromStdString(card->cardVersion());
mIs21 = version == "2.1";
mVersionLabel->setText(i18nc("First placeholder is manufacturer, second placeholder is a version number",
"%1 OpenPGP v%2 card", QString::fromStdString(card->manufacturer()),
version));
const QString sn = QString::fromStdString(card->serialNumber()).mid(16, 12);
mSerialNumber->setText(sn);
mRealSerial = card->serialNumber();
const auto holder = QString::fromStdString(card->cardHolder());
const auto url = QString::fromStdString(card->pubkeyUrl());
mCardHolderLabel->setText(holder.isEmpty() ? i18n("not set") : holder);
mUrl = url;
mUrlLabel->setText(url.isEmpty() ? i18n("not set") :
QStringLiteral("<a href=\"%1\">%1</a>").arg(url.toHtmlEscaped()));
mUrlLabel->setOpenExternalLinks(true);
updateKey(mSigningKey, card->sigFpr());
updateKey(mEncryptionKey, card->encFpr());
updateKey(mAuthKey, card->authFpr());
mCardIsEmpty = card->authFpr().empty() && card->sigFpr().empty() && card->encFpr().empty();
}
void PGPCardWidget::doChangePin(int slot)
{
ReaderStatus::mutableInstance()
->startSimpleTransaction(QStringLiteral("SCD PASSWD %1").arg(slot).toUtf8().constData(),
this, "changePinResult");
}
#ifdef GPGME_CAN_GENCARDKEY
void PGPCardWidget::doGenKey(GenCardKeyDialog *dlg)
{
const auto params = dlg->getKeyParams();
delete dlg;
auto progress = new QProgressDialog(this, Qt::CustomizeWindowHint | Qt::WindowTitleHint | Qt::Dialog);
progress->setAutoClose(true);
progress->setMinimumDuration(0);
progress->setMaximum(0);
progress->setMinimum(0);
progress->setModal(true);
progress->setCancelButton(nullptr);
progress->setWindowTitle(i18n("Generating keys"));
progress->setLabel(new QLabel(i18n("This may take several minutes...")));
GenKeyThread *workerThread = new GenKeyThread(params, mRealSerial);
connect(workerThread, &QThread::finished, this, [this, workerThread, progress] {
progress->accept();
delete progress;
genKeyDone(workerThread->error(), workerThread->bkpFile());
delete workerThread;
});
workerThread->start();
progress->exec();
}
void PGPCardWidget::genKeyDone(const GpgME::Error &err, const std::string &backup)
{
if (err) {
KMessageBox::error(this, i18nc("@info",
"Failed to generate new key: %1", err.asString()),
i18nc("@title", "Error"));
return;
}
if (err.isCanceled()) {
return;
}
if (!backup.empty()) {
const auto bkpFile = QString::fromStdString(backup);
QFileInfo fi(bkpFile);
const auto target = QFileDialog::getSaveFileName(this, i18n("Save backup of encryption key"),
fi.fileName(),
QStringLiteral("%1 (*.gpg)").arg(i18n("Backup Key")));
if (!target.isEmpty() && !QFile::copy(bkpFile, target)) {
KMessageBox::error(this, i18nc("@info",
"Failed to move backup. The backup key is still stored under: %1", bkpFile),
i18nc("@title", "Error"));
} else if (!target.isEmpty()) {
QFile::remove(bkpFile);
}
}
KMessageBox::information(this, i18nc("@info",
"Successfully generated a new key for this card."),
i18nc("@title", "Success"));
}
#else
void PGPCardWidget::doGenKey(GenCardKeyDialog *) {}
void PGPCardWidget::genKeyDone(const GpgME::Error &, const std::string &) {}
#endif
void PGPCardWidget::genkeyRequested()
{
if (!mCardIsEmpty) {
auto ret = KMessageBox::warningContinueCancel(this,
i18n("The existing keys on this card will be <b>deleted</b> "
"and replaced by new keys.") + QStringLiteral("<br/><br/>") +
i18n("It will no longer be possible to decrypt past communication "
"encrypted for the existing key."),
i18n("Secret Key Deletion"),
KStandardGuiItem::guiItem(KStandardGuiItem::Delete),
KStandardGuiItem::cancel(), QString(), KMessageBox::Notify | KMessageBox::Dangerous);
if (ret != KMessageBox::Continue) {
return;
}
}
GenCardKeyDialog *dlg = new GenCardKeyDialog(this);
std::vector <int> sizes;
sizes.push_back(1024);
sizes.push_back(2048);
sizes.push_back(3072);
// There is probably a better way to check for capabilities
if (mIs21) {
sizes.push_back(4096);
}
dlg->setSupportedSizes(sizes);
connect(dlg, &QDialog::accepted, this, [this, dlg] () {doGenKey(dlg);});
connect(dlg, &QDialog::rejected, dlg, &QObject::deleteLater);
dlg->setModal(true);
dlg->show();
}
void PGPCardWidget::changePinResult(const GpgME::Error &err)
{
if (err) {
KMessageBox::error(this, i18nc("@info",
"PIN change failed: %1", err.asString()),
i18nc("@title", "Error"));
return;
}
if (!err.isCanceled()) {
KMessageBox::information(this, i18nc("@info",
"Code successfully changed."),
i18nc("@title", "Success"));
}
}
void PGPCardWidget::changeNameRequested()
{
QString text = mCardHolderLabel->text();
while (true) {
bool ok = false;
text = QInputDialog::getText(this, i18n("Change cardholder"),
i18n("New name:"), QLineEdit::Normal,
text, &ok, Qt::WindowFlags(),
Qt::ImhLatinOnly);
if (!ok) {
return;
}
// Some additional restrictions imposed by gnupg
if (text.contains("<")) {
KMessageBox::error(this, i18nc("@info",
"The \"<\" character may not be used."),
i18nc("@title", "Error"));
continue;
}
if (text.contains(" ")) {
KMessageBox::error(this, i18nc("@info",
"Double spaces are not allowed"),
i18nc("@title", "Error"));
continue;
}
if (text.size() > 38) {
KMessageBox::error(this, i18nc("@info",
"The size of the name may not exceed 38 characters."),
i18nc("@title", "Error"));
}
break;
}
auto parts = text.split(' ');
const auto lastName = parts.takeLast();
const auto formatted = lastName + QStringLiteral("<<") + parts.join('<');
ReaderStatus::mutableInstance()
->startSimpleTransaction(QStringLiteral("SCD SETATTR DISP-NAME %1").arg(formatted).toUtf8().constData(),
this, "changeNameResult");
}
void PGPCardWidget::changeNameResult(const GpgME::Error &err)
{
if (err) {
KMessageBox::error(this, i18nc("@info",
"Name change failed: %1", err.asString()),
i18nc("@title", "Error"));
return;
}
if (!err.isCanceled()) {
KMessageBox::information(this, i18nc("@info",
"Name successfully changed."),
i18nc("@title", "Success"));
ReaderStatus::mutableInstance()->updateStatus();
}
}
void PGPCardWidget::changeUrlRequested()
{
QString text = mUrl;
while (true) {
bool ok = false;
text = QInputDialog::getText(this, i18n("Change the URL where the pubkey can be found"),
i18n("New pubkey URL:"), QLineEdit::Normal,
text, &ok, Qt::WindowFlags(),
Qt::ImhLatinOnly);
if (!ok) {
return;
}
// Some additional restrictions imposed by gnupg
if (text.size() > 254) {
KMessageBox::error(this, i18nc("@info",
"The size of the URL may not exceed 254 characters."),
i18nc("@title", "Error"));
}
break;
}
ReaderStatus::mutableInstance()
->startSimpleTransaction(QStringLiteral("SCD SETATTR PUBKEY-URL %1").arg(text).toUtf8().constData(),
this, "changeUrlResult");
}
void PGPCardWidget::changeUrlResult(const GpgME::Error &err)
{
if (err) {
KMessageBox::error(this, i18nc("@info",
"URL change failed: %1", err.asString()),
i18nc("@title", "Error"));
return;
}
if (!err.isCanceled()) {
KMessageBox::information(this, i18nc("@info",
"URL successfully changed."),
i18nc("@title", "Success"));
ReaderStatus::mutableInstance()->updateStatus();
}
}
void PGPCardWidget::updateKey(QLabel *label, const std::string &fpr)
{
label->setText(fpr.c_str());
if (fpr.empty()) {
label->setText(i18n("Slot empty"));
return;
}
std::vector<std::string> vec;
std::string keyid = fpr;
keyid.erase(0, keyid.size() - 16);
vec.push_back(keyid);
const auto subkeys = KeyCache::instance()->findSubkeysByKeyID(vec);
if (subkeys.empty() || subkeys[0].isNull()) {
label->setToolTip(i18n("Public key not found."));
return;
}
QStringList toolTips;
for (const auto &sub: subkeys) {
// Yep you can have one subkey associated with mutliple
// primary keys.
toolTips << Formatting::toolTip(sub.parent(), Formatting::Validity |
Formatting::StorageLocation |
Formatting::ExpiryDates |
Formatting::UserIDs |
Formatting::Fingerprint);
}
label->setToolTip(toolTips.join("<br/>"));
return;
}
#include "pgpcardwidget.moc"
diff --git a/src/view/smartcardwidget.cpp b/src/view/smartcardwidget.cpp
index 84928507d..923d261b8 100644
--- a/src/view/smartcardwidget.cpp
+++ b/src/view/smartcardwidget.cpp
@@ -1,163 +1,162 @@
/* view/smartcardwidget.cpp
This file is part of Kleopatra, the KDE keymanager
Copyright (c) 2017 by Bundesamt für Sicherheit in der Informationstechnik
Software engineering by Intevation GmbH
Kleopatra is free software; you can redistribute it and/or modify
it under the terms of 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.
Kleopatra is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
In addition, as a special exception, the copyright holders give
permission to link the code of this program with any edition of
the Qt library by Trolltech AS, Norway (or with modified versions
of Qt that use the same license as Qt), and distribute linked
combinations including the two. You must obey the GNU General
Public License in all respects for all of the code used other than
Qt. If you modify this file, you may extend this exception to
your version of the file, but you are not obligated to do so. If
you do not wish to do so, delete this exception statement from
your version.
*/
#include "smartcardwidget.h"
#include "smartcard/readerstatus.h"
#include "smartcard/openpgpcard.h"
#include "smartcard/netkeycard.h"
#include "view/pgpcardwidget.h"
#include "view/netkeywidget.h"
#include "kleopatra_debug.h"
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>
+#include <QStackedWidget>
#include <KLocalizedString>
using namespace Kleo;
using namespace Kleo::SmartCard;
namespace {
class PlaceHolderWidget: public QWidget
{
Q_OBJECT
public:
PlaceHolderWidget()
{
auto lay = new QVBoxLayout;
lay->addStretch(-1);
const QStringList supported = QStringList() << QStringLiteral("OpenPGP v2.0 - v3.3")
<< QStringLiteral("Gnuk")
<< QStringLiteral("NetKey v3");
lay->addWidget(new QLabel(QStringLiteral("\t\t<h3>") +
i18n("Please insert a compatible smartcard.") + QStringLiteral("</h3>")));
lay->addSpacing(10);
lay->addWidget(new QLabel(QStringLiteral("\t\t") +
i18n("Kleopatra currently supports the following card types:") +
QStringLiteral("<ul><li>") + supported.join(QStringLiteral("</li><li>")) +
QStringLiteral("</li></ul>")));
lay->addSpacing(10);
lay->addWidget(new QLabel(i18n("Refresh the view (F5) to update the smartcard status.")));
lay->addStretch(-1);
auto hLay = new QHBoxLayout(this);
hLay->addStretch(-1);
hLay->addLayout(lay);
hLay->addStretch(-1);
+ lay->addStretch(-1);
}
};
} // namespace
class SmartCardWidget::Private
{
public:
Private(SmartCardWidget *qq) : q(qq)
{
QPushButton *backBtn = new QPushButton(QIcon::fromTheme("arrow-left"), i18n("Back"));
QHBoxLayout *backH = new QHBoxLayout;
backH->addWidget(backBtn);
backH->addWidget(new QLabel(QStringLiteral("<h2>") + i18n("Smartcard Management") +
QStringLiteral("</h2>")));
backH->addStretch(-1);
QVBoxLayout *vLay = new QVBoxLayout(q);
+
connect(backBtn, &QPushButton::clicked, q, [this] () {Q_EMIT (q->backRequested());});
vLay->addLayout(backH);
+ mStack = new QStackedWidget;
+ vLay->addWidget(mStack);
+
mPGPCardWidget = new PGPCardWidget;
- mPGPCardWidget->setVisible(false);
- vLay->addWidget(mPGPCardWidget);
+ mStack->addWidget(mPGPCardWidget);
mNetKeyWidget = new NetKeyWidget;
- mNetKeyWidget->setVisible(false);
- vLay->addWidget(mNetKeyWidget);
+ mStack->addWidget(mNetKeyWidget);
mPlaceHolderWidget = new PlaceHolderWidget;
- vLay->addWidget(mPlaceHolderWidget);
- vLay->addStretch(-1);
+ mStack->addWidget(mPlaceHolderWidget);
+ mStack->setCurrentWidget(mPlaceHolderWidget);
connect (ReaderStatus::instance(), &ReaderStatus::cardChanged, q, [this] (unsigned int /*slot*/) {
const auto cards = ReaderStatus::instance()->getCards();
if (!cards.size()) {
setCard(std::shared_ptr<Card>(new Card()));
} else {
// No support for multiple reader / cards currently
setCard(cards[0]);
}
});
}
void setCard(std::shared_ptr<Card> card)
{
if (card->appType() == Card::OpenPGPApplication) {
mPGPCardWidget->setCard(static_cast<OpenPGPCard *> (card.get()));
- mPGPCardWidget->setVisible(true);
- mPlaceHolderWidget->setVisible(false);
- mNetKeyWidget->setVisible(false);
+ mStack->setCurrentWidget(mPGPCardWidget);
} else if (card->appType() == Card::NksApplication) {
mNetKeyWidget->setCard(static_cast<NetKeyCard *> (card.get()));
- mNetKeyWidget->setVisible(true);
- mPlaceHolderWidget->setVisible(false);
- mPGPCardWidget->setVisible(false);
+ mStack->setCurrentWidget(mNetKeyWidget);
} else {
- mPlaceHolderWidget->setVisible(true);
- mPGPCardWidget->setVisible(false);
- mNetKeyWidget->setVisible(false);
+ mStack->setCurrentWidget(mPlaceHolderWidget);
}
}
private:
SmartCardWidget *q;
NetKeyWidget *mNetKeyWidget;
PGPCardWidget *mPGPCardWidget;
PlaceHolderWidget *mPlaceHolderWidget;
+ QStackedWidget *mStack;
};
SmartCardWidget::SmartCardWidget(QWidget *parent):
QWidget(parent),
d(new Private(this))
{
}
void SmartCardWidget::reload()
{
ReaderStatus::mutableInstance()->updateStatus();
}
#include "smartcardwidget.moc"
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Jan 3, 11:41 PM (9 h, 32 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
89/eb/751ab86f5ab2863893cef395b8e2
Attached To
rKLEOPATRA Kleopatra
Event Timeline
Log In to Comment