diff --git a/src/commands/exportpaperkeycommand.cpp b/src/commands/exportpaperkeycommand.cpp index b39fce0ed..41b64a00c 100644 --- a/src/commands/exportpaperkeycommand.cpp +++ b/src/commands/exportpaperkeycommand.cpp @@ -1,128 +1,188 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/exportpaperkeycommand.cpp This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2016 Bundesamt für Sicherheit in der Informationstechnik SPDX-FileContributor: Intevation GmbH SPDX-License-Identifier: GPL-2.0-or-later */ #include #include "exportpaperkeycommand.h" +#include #include +#include + #include #include #include #include #include #include #include #include "command_p.h" #include "kleopatra_debug.h" using namespace Kleo; using namespace Kleo::Commands; using namespace GpgME; -ExportPaperKeyCommand::ExportPaperKeyCommand(QAbstractItemView *v, KeyListController *c) - : GnuPGProcessCommand(v, c) - , mParent(v) +class ExportPaperKeyCommand::Private : public Command::Private { - connect(&mPkProc, &QProcess::finished, this, &ExportPaperKeyCommand::pkProcFinished); - mPkProc.setProgram(paperKeyInstallPath()); - mPkProc.setArguments(QStringList() << QStringLiteral("--output-type=base16")); + friend class ::ExportPaperKeyCommand; + ExportPaperKeyCommand *q_func() const + { + return static_cast(q); + } - process()->setStandardOutputProcess(&mPkProc); - qCDebug(KLEOPATRA_LOG) << "Starting PaperKey process."; - mPkProc.start(); - setAutoDelete(false); +public: + explicit Private(ExportPaperKeyCommand *qq, KeyListController *c); + ~Private() override; + + void startPaperKey(const QByteArray &data); + +private: + QProcess pkProc; + QPointer job; +}; + +ExportPaperKeyCommand::Private::Private(ExportPaperKeyCommand *qq, KeyListController *c) + : Command::Private(qq, c) +{ +} + +ExportPaperKeyCommand::Private::~Private() +{ } -QStringList ExportPaperKeyCommand::arguments() const +ExportPaperKeyCommand::Private *ExportPaperKeyCommand::d_func() { - const Key key = d->key(); - QStringList result; + return static_cast(d.get()); +} +const ExportPaperKeyCommand::Private *ExportPaperKeyCommand::d_func() const +{ + return static_cast(d.get()); +} - result << gpgPath() << QStringLiteral("--batch"); - result << QStringLiteral("--export-secret-key"); - result << QLatin1StringView(key.primaryFingerprint()); +#define d d_func() +#define q q_func() - return result; +ExportPaperKeyCommand::ExportPaperKeyCommand(QAbstractItemView *v, KeyListController *c) + : Command(v, new Private(this, c)) +{ } -bool ExportPaperKeyCommand::preStartHook(QWidget *parent) const +void ExportPaperKeyCommand::doStart() { if (paperKeyInstallPath().isNull()) { - KMessageBox::error(parent, + KMessageBox::error(d->parentWidgetOrView(), xi18nc("@info", "Kleopatra uses " "PaperKey to create a minimized and" " printable version of your secret key." "Please make sure it is installed."), i18nc("@title", "Failed to find PaperKey executable.")); - return false; + finished(); + return; + } + const auto key = d->key(); + + if (key.isNull()) { + finished(); + return; + } + + std::unique_ptr exportJob{QGpgME::openpgp()->secretKeyExportJob(false)}; + connect(exportJob.get(), &QGpgME::ExportJob::result, this, [this](const GpgME::Error &err, const QByteArray &keyData) { + if (err.isCanceled()) { + finished(); + return; + } + + if (err) { + d->error(xi18nc("@info", + "An error occurred during export of the secret key:" + "%1", + Formatting::errorAsString(err)), + i18nc("@title:dialog", "Error Exporting Key")); + finished(); + return; + } + d->startPaperKey(keyData); + }); + + const GpgME::Error err = exportJob->start({QLatin1StringView{key.primaryFingerprint()}}); + if (err) { + d->error(xi18nc("@info", + "An error occurred during export of the secret key:" + "%1", + Formatting::errorAsString(err)), + i18nc("@title:dialog", "Error Exporting Key")); + return; } - return true; + + if (!exportJob) { + finished(); + return; + } + d->job = exportJob.release(); } -void ExportPaperKeyCommand::pkProcFinished(int code, QProcess::ExitStatus status) +void ExportPaperKeyCommand::Private::startPaperKey(const QByteArray &data) { - qCDebug(KLEOPATRA_LOG) << "Paperkey export finished: " << code << "status: " << status; + pkProc.setProgram(paperKeyInstallPath()); + pkProc.setArguments(QStringList() << QStringLiteral("--output-type=base16")); + + qCDebug(KLEOPATRA_LOG) << "Starting PaperKey process."; + pkProc.start(); + pkProc.write(data); + pkProc.closeWriteChannel(); + q->setAutoDelete(false); + pkProc.waitForFinished(); + + qCDebug(KLEOPATRA_LOG) << "Paperkey export finished: " << pkProc.exitCode() << "status: " << pkProc.exitStatus(); - if (status == QProcess::CrashExit || code) { + if (pkProc.exitStatus() == QProcess::CrashExit || pkProc.exitCode()) { qCDebug(KLEOPATRA_LOG) << "Aborting because paperkey failed"; - deleteLater(); + finished(); + q->deleteLater(); return; } QPrinter printer; - const Key key = d->key(); + const auto key = this->key(); printer.setDocName(QStringLiteral("0x%1-sec").arg(QString::fromLatin1(key.shortKeyID()))); - QPrintDialog printDialog(&printer, mParent); + QPrintDialog printDialog(&printer, parentWidgetOrView()); printDialog.setWindowTitle(i18nc("@title:window", "Print Secret Key")); if (printDialog.exec() != QDialog::Accepted) { qCDebug(KLEOPATRA_LOG) << "Printing aborted."; - deleteLater(); + finished(); + q->deleteLater(); return; } - QTextDocument doc(QString::fromLatin1(mPkProc.readAllStandardOutput())); + QTextDocument doc(QString::fromLatin1(pkProc.readAllStandardOutput())); doc.setDefaultFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); doc.print(&printer); - deleteLater(); -} - -QString ExportPaperKeyCommand::errorCaption() const -{ - return i18nc("@title:window", "Error printing secret key"); + q->deleteLater(); } -QString ExportPaperKeyCommand::crashExitMessage(const QStringList &args) const +void ExportPaperKeyCommand::doCancel() { - return xi18nc("@info", - "The GPG process that tried to export the secret key " - "ended prematurely because of an unexpected error." - "Please check the output of %1 for details.", - args.join(QLatin1Char(' '))); -} - -QString ExportPaperKeyCommand::errorExitMessage(const QStringList &args) const -{ - return xi18nc("@info", - "An error occurred while trying to export the secret key. " - "The output from %1 was: %2", - args[0], - errorString()); + if (d->job) { + d->job->slotCancel(); + } + d->job.clear(); } #include "moc_exportpaperkeycommand.cpp" diff --git a/src/commands/exportpaperkeycommand.h b/src/commands/exportpaperkeycommand.h index 206a2aba8..23e016ca4 100644 --- a/src/commands/exportpaperkeycommand.h +++ b/src/commands/exportpaperkeycommand.h @@ -1,55 +1,50 @@ /* -*- mode: c++; c-basic-offset:4 -*- commands/exportpaperkeycommand.h This file is part of Kleopatra, the KDE keymanager SPDX-FileCopyrightText: 2016 Bundesamt für Sicherheit in der Informationstechnik SPDX-FileContributor: Intevation GmbH SPDX-License-Identifier: GPL-2.0-or-later */ #pragma once #include +#include + +#include + #include #include class QWidget; namespace Kleo { namespace Commands { -class ExportPaperKeyCommand : public GnuPGProcessCommand +class ExportPaperKeyCommand : public Command { Q_OBJECT public: explicit ExportPaperKeyCommand(QAbstractItemView *view, KeyListController *parent); static Restrictions restrictions() { return OnlyOneKey | NeedSecretKeyData | MustBeOpenPGP; } -protected Q_SLOTS: - void pkProcFinished(int code, QProcess::ExitStatus status); - -private: - QStringList arguments() const override; - bool preStartHook(QWidget *parentWidget) const override; - - QString errorCaption() const override; - - QString crashExitMessage(const QStringList &) const override; - QString errorExitMessage(const QStringList &) const override; - private: - QWidget *const mParent; - QProcess mPkProc; + class Private; + inline Private *d_func(); + inline const Private *d_func() const; + void doStart() override; + void doCancel() override; }; } }