diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -53,10 +53,12 @@ add_definitions(-DGPG_ERR_SOURCE_DEFAULT=GPG_ERR_SOURCE_USER_1) endif() -ki18n_wrap_ui(_kleopatra_uiserver_SRCS crypto/gui/signingcertificateselectionwidget.ui) +ki18n_wrap_ui(_kleopatra_uiserver_SRCS + crypto/gui/signingcertificateselectionwidget.ui) set(_kleopatra_SRCS utils/gnupg-helper.cpp + utils/paperkey-helper.cpp utils/filesystemwatcher.cpp utils/filedialog.cpp utils/kdpipeiodevice.cpp @@ -115,6 +117,7 @@ dialogs/exportcertificatesdialog.cpp dialogs/deletecertificatesdialog.cpp dialogs/setinitialpindialog.cpp + dialogs/exportpaperkeydialog.cpp crypto/controller.cpp crypto/certificateresolver.cpp @@ -165,6 +168,7 @@ commands/command.cpp commands/gnupgprocesscommand.cpp + commands/paperkeyprocesscommand.cpp commands/detailscommand.cpp commands/exportcertificatecommand.cpp commands/importcertificatescommand.cpp @@ -198,6 +202,7 @@ commands/learncardkeyscommand.cpp commands/checksumcreatefilescommand.cpp commands/checksumverifyfilescommand.cpp + commands/exportpaperkeycommand.cpp ${_kleopatra_uiserver_files} @@ -215,7 +220,9 @@ main.cpp ) -ecm_qt_declare_logging_category(_kleopatra_SRCS HEADER kleopatra_debug.h IDENTIFIER KLEOPATRA_LOG CATEGORY_NAME log_kleopatra) +ecm_qt_declare_logging_category(_kleopatra_SRCS + HEADER kleopatra_debug.h IDENTIFIER KLEOPATRA_LOG CATEGORY_NAME + log_kleopatra) if(KLEO_MODEL_TEST) add_definitions(-DKLEO_MODEL_TEST) @@ -230,6 +237,7 @@ dialogs/selectchecklevelwidget.ui dialogs/selftestdialog.ui dialogs/exportsecretkeydialog.ui + dialogs/exportpaperkeydialog.ui dialogs/adduseriddialog.ui dialogs/certificatedetailsdialog.ui dialogs/setinitialpindialog.ui @@ -249,8 +257,10 @@ kcfg/smimevalidationpreferences.kcfgc ) -file(GLOB ICONS_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/icons/*-apps-kleopatra.png") -ecm_add_app_icon(_kleopatra_SRCS ICONS ${ICONS_SRCS}) + +file( + GLOB ICONS_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/icons/*-apps-kleopatra.png") + ecm_add_app_icon(_kleopatra_SRCS ICONS ${ICONS_SRCS}) qt5_add_resources(_kleopatra_SRCS kleopatra.qrc) @@ -278,7 +288,9 @@ PROGRAMS data/org.kde.kleopatra.desktop data/kleopatra_import.desktop DESTINATION ${KDE_INSTALL_APPDIR} ) -install(FILES data/org.kde.kleopatra.appdata.xml DESTINATION ${KDE_INSTALL_METAINFODIR}) +install( + FILES data/org.kde.kleopatra.appdata.xml + DESTINATION ${KDE_INSTALL_METAINFODIR}) install( FILES data/kleopatra_signencryptfiles.desktop data/kleopatra_signencryptfolders.desktop diff --git a/src/commands/command.h b/src/commands/command.h --- a/src/commands/command.h +++ b/src/commands/command.h @@ -86,6 +86,9 @@ MustBeTrustedRoot = 1024 | MustBeRoot, MustBeUntrustedRoot = 2048 | MustBeRoot, + //Programm Dependencies + PaperKeyInstalled = 4096, + _AllRestrictions_Helper, AllRestrictions = 2 * (_AllRestrictions_Helper - 1) - 1 }; diff --git a/src/commands/exportpaperkeycommand.h b/src/commands/exportpaperkeycommand.h new file mode 100644 --- /dev/null +++ b/src/commands/exportpaperkeycommand.h @@ -0,0 +1,108 @@ +/* -*- mode: c++; c-basic-offset:4 -*- + commands/exportsecretkeycommand.h + + This file is part of Kleopatra, the KDE keymanager + Copyright (c) 2016 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. +*/ + +#ifndef __KLEOPATRA_COMMMANDS_EXPORTPAPERKEYCOMMAND_H__ +#define __KLEOPATRA_COMMMANDS_EXPORTPAPERKEYCOMMAND_H__ + +#include + +#include +#include + +namespace Kleo +{ +namespace Commands +{ + +class ExportPaperKeyCommand : public PaperKeyProcessCommand +{ + + Q_OBJECT +public: + explicit ExportPaperKeyCommand( QAbstractItemView *view, + KeyListController *parent); + explicit ExportPaperKeyCommand(KeyListController *parent); + explicit ExportPaperKeyCommand(const GpgME::Key &key); + ~ExportPaperKeyCommand(); + + void setFileName(const QString &fileName); + QString fileName() const + { + return m_filename; + } + + void setOutputType(const QString &outputType); + QString outputType() const + { + return m_outputType; + } + + void setOutputWidth (int outputWidth); + int outputWidth() const + { + return m_outputWidth; + } + void setIgnoreCRCError(bool ignoreCRCError); + bool ignoreCRCError() const + { + return m_ignoreCRCError; + } + + /* reimp */ static Restrictions restrictions() + { + return PaperKeyInstalled | OnlyOneKey | NeedSecretKey; + } + +private: + bool preStartHook(QWidget *) const Q_DECL_OVERRIDE; + + QStringList arguments() const Q_DECL_OVERRIDE; + + QString errorCaption() const Q_DECL_OVERRIDE; + QString successCaption() const Q_DECL_OVERRIDE; + + QString crashExitMessage(const QStringList &) const Q_DECL_OVERRIDE; + QString errorExitMessage(const QStringList &) const Q_DECL_OVERRIDE; + QString successMessage(const QStringList &) const Q_DECL_OVERRIDE; + +private: + mutable QString m_filename; + mutable QString m_outputType; + mutable int m_outputWidth; + mutable bool m_ignoreCRCError; + +}; + +} +} + +#endif // __KLEOPATRA_COMMMANDS_EXPORTPAPERKEYCOMMAND_H__ diff --git a/src/commands/exportpaperkeycommand.cpp b/src/commands/exportpaperkeycommand.cpp new file mode 100644 --- /dev/null +++ b/src/commands/exportpaperkeycommand.cpp @@ -0,0 +1,180 @@ +/* -*- mode: c++; c-basic-offset:4 -*- + commands/exportsecretkeycommand.cpp + + This file is part of Kleopatra, the KDE keymanager + Copyright (c) 2016 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 + +#include "exportpaperkeycommand.h" + +#include "command_p.h" + +#include + +#include + +#include + +#include + +#include + +#include + +#include + +using namespace Kleo; +using namespace Kleo::Commands; +using namespace Kleo::Dialogs; +using namespace GpgME; + + +ExportPaperKeyCommand::ExportPaperKeyCommand(KeyListController *c) + : PaperKeyProcessCommand(c) +{ +} + +ExportPaperKeyCommand::ExportPaperKeyCommand(QAbstractItemView *v, KeyListController *c) + : PaperKeyProcessCommand(v, c) +{ +} + +ExportPaperKeyCommand::ExportPaperKeyCommand(const Key &key) + : PaperKeyProcessCommand(key) +{ +} + +ExportPaperKeyCommand::~ExportPaperKeyCommand() {} + +void ExportPaperKeyCommand::setFileName(const QString &fileName) +{ + m_filename = fileName; +} + +void ExportPaperKeyCommand::setOutputType(const QString &outputType) +{ + m_outputType = outputType; +} + +void ExportPaperKeyCommand::setIgnoreCRCError(bool ignoreCRCError) +{ + m_ignoreCRCError = ignoreCRCError; +} + +bool ExportPaperKeyCommand::preStartHook(QWidget *parent) const +{ + if (!m_filename.isEmpty()) { + return true; + } + + ExportPaperKeyDialog dlg(parent); + dlg.setKey(d->key()); + if (!dlg.exec()) { + return false; + } + + m_filename = dlg.fileName(); + m_ignoreCRCError = dlg.ignoreCRCError(); + if (dlg.outputTypeRaw()) + { + m_outputType = "raw"; + } else + { + m_outputType = "base16"; + } + m_outputWidth = dlg.outputWidth(); + return true; +} + +QStringList ExportPaperKeyCommand::arguments() const +{ + const Key key = d->key(); + QStringList result; + + if (key.protocol() == OpenPGP) { + result << gpgPath() << QStringLiteral("--batch"); + } + result << QStringLiteral("--export-secret-key"); + result << QLatin1String(key.primaryFingerprint()); + + result << QStringLiteral("|"); + result << paperKeyPath(); + + if (m_ignoreCRCError) { + result << QStringLiteral("--ignore-crc-error"); + } + if (!m_outputType.isEmpty()) { + result << QStringLiteral("--output-type") << m_outputType; + } + if (m_outputWidth<50) { + m_outputWidth=80; + } + + result << QStringLiteral("--output-width"); + result << QString::number(m_outputWidth); + + result << QStringLiteral("--output"); + result << m_filename; + + return result; +} + +QString ExportPaperKeyCommand::errorCaption() const +{ + return i18nc("@title:window", "Paper Key Export Error"); +} + +QString ExportPaperKeyCommand::successCaption() const +{ + return i18nc("@title:window", "Paper Key Export Finished"); +} + +QString ExportPaperKeyCommand::crashExitMessage(const QStringList &args) const +{ + return xi18nc("@info", + "The GPG or GpgSM 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(QStringLiteral(" "))); +} + +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()); +} + +QString ExportPaperKeyCommand::successMessage(const QStringList &) const +{ + return i18nc("@info", "Paper key successfully exported."); +} diff --git a/src/commands/paperkeyprocesscommand.h b/src/commands/paperkeyprocesscommand.h new file mode 100644 --- /dev/null +++ b/src/commands/paperkeyprocesscommand.h @@ -0,0 +1,94 @@ +/* -*- mode: c++; c-basic-offset:4 -*- + commands/gnupgprocesscommand.h + + This file is part of Kleopatra, the KDE keymanager + Copyright (c) 2016 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. +*/ + +#ifndef __KLEOPATRA_COMMMANDS_PAPERKEYPROCESSCOMMAND_H__ +#define __KLEOPATRA_COMMMANDS_PAPERKEYPROCESSCOMMAND_H__ + +#include + +class QStringList; +class QString; + +namespace Kleo +{ +namespace Commands +{ + +class PaperKeyProcessCommand : public Command +{ + Q_OBJECT +protected: + explicit PaperKeyProcessCommand(QAbstractItemView *view, KeyListController *parent); + explicit PaperKeyProcessCommand(KeyListController *parent); + explicit PaperKeyProcessCommand(const GpgME::Key &key); + ~PaperKeyProcessCommand(); + +public: + QDialog *dialog() const; + +private: + virtual bool preStartHook(QWidget *parentWidget) const; + + virtual QStringList arguments() const = 0; + + virtual QString errorCaption() const = 0; + virtual QString successCaption() const = 0; + + virtual QString crashExitMessage(const QStringList &args) const = 0; + virtual QString errorExitMessage(const QStringList &args) const = 0; + virtual QString successMessage(const QStringList &args) const = 0; + + virtual void postSuccessHook(QWidget *parentWidget); + +protected: + QString errorString() const; + void setIgnoresSuccessOrFailure(bool ignore); + bool ignoresSuccessOrFailure() const; + void setShowsOutputWindow(bool show); + bool showsOutputWindow() const; + +private: + void doStart() Q_DECL_OVERRIDE; + void doCancel() Q_DECL_OVERRIDE; + +private: + class Private; + inline Private *d_func(); + inline const Private *d_func() const; + Q_PRIVATE_SLOT(d_func(), void slotProcessFinished(int, QProcess::ExitStatus)) + Q_PRIVATE_SLOT(d_func(), void slotProcessReadyReadStandardError()) +}; + +} +} + +#endif // __KLEOPATRA_COMMMANDS_PAPERKEYPROCESSCOMMAND_H__ diff --git a/src/commands/paperkeyprocesscommand.cpp b/src/commands/paperkeyprocesscommand.cpp new file mode 100644 --- /dev/null +++ b/src/commands/paperkeyprocesscommand.cpp @@ -0,0 +1,426 @@ +/* -*- mode: c++; c-basic-offset:4 -*- + commands/gnupgprocesscommand.cpp + + This file is part of Kleopatra, the KDE keymanager + Copyright (c) 2016 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 + +#include "paperkeyprocesscommand.h" + +#include "command_p.h" + +#include + +#include "kleopatra_debug.h" +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const int PROCESS_TERMINATE_TIMEOUT = 5000; // milliseconds + +using namespace Kleo; +using namespace Kleo::Commands; + +namespace +{ + +class OutputDialog : public QDialog +{ + Q_OBJECT +public: + explicit OutputDialog(QWidget *parent = Q_NULLPTR) + : QDialog(parent), + vlay(this), + logTextWidget(this), + buttonBox(QDialogButtonBox::Cancel | QDialogButtonBox::Close, Qt::Horizontal, this) + { + KDAB_SET_OBJECT_NAME(vlay); + KDAB_SET_OBJECT_NAME(logTextWidget); + KDAB_SET_OBJECT_NAME(buttonBox); + + logTextWidget.setMinimumVisibleLines(20); + logTextWidget.setMinimumVisibleColumns(80); + + vlay.addWidget(&logTextWidget, 1); + vlay.addWidget(&buttonBox); + + connect(closeButton(), &QAbstractButton::clicked, this, &QWidget::close); + connect(cancelButton(), &QAbstractButton::clicked, this, &OutputDialog::slotCancelClicked); + } + +Q_SIGNALS: + void cancelRequested(); + +public Q_SLOTS: + void message(const QString &s) + { + logTextWidget.message(s); + } + void setComplete(bool complete) + { + cancelButton()->setVisible(!complete); + } + +private Q_SLOTS: + void slotCancelClicked() + { + cancelButton()->hide(); + Q_EMIT cancelRequested(); + } + +private: + QAbstractButton *closeButton() const + { + return buttonBox.button(QDialogButtonBox::Close); + } + QAbstractButton *cancelButton() const + { + return buttonBox.button(QDialogButtonBox::Cancel); + } + +private: + QVBoxLayout vlay; + KDLogTextWidget logTextWidget; + QDialogButtonBox buttonBox; +}; + +} + +class PaperKeyProcessCommand::Private : Command::Private +{ + friend class ::Kleo::Commands::PaperKeyProcessCommand; + PaperKeyProcessCommand *q_func() const + { + return static_cast(q); + } +public: + explicit Private(PaperKeyProcessCommand *qq, KeyListController *c); + ~Private(); + +private: + void init(); + void ensureDialogCreated() + { + if (!showsOutputWindow) { + return; + } + if (!dialog) { + dialog = new OutputDialog; + dialog->setAttribute(Qt::WA_DeleteOnClose); + applyWindowID(dialog); + connect(dialog.data(), &OutputDialog::cancelRequested, q, &Command::cancel); + dialog->setWindowTitle(i18n("Subprocess Diagnostics")); + } + } + void ensureDialogVisible() + { + if (!showsOutputWindow) { + return; + } + ensureDialogCreated(); + if (dialog->isVisible()) { + dialog->raise(); + } else { + dialog->show(); + } +#ifdef Q_OS_WIN + KWindowSystem::forceActiveWindow(dialog->winId()); +#endif + } + void message(const QString &msg) + { + if (dialog) { + dialog->message(msg); + } else { + qCDebug(KLEOPATRA_LOG) << msg; + } + } + +private: + void slotProcessFinished(int, QProcess::ExitStatus); + void slotProcessReadyReadStandardError(); + +private: + QProcess process1; + QProcess process2; + QPointer dialog; + QStringList arguments1; + QStringList arguments2; + QByteArray errorBuffer; + bool ignoresSuccessOrFailure; + bool showsOutputWindow; + bool canceled; +}; + +PaperKeyProcessCommand::Private *PaperKeyProcessCommand::d_func() +{ + return static_cast(d.get()); +} +const PaperKeyProcessCommand::Private *PaperKeyProcessCommand::d_func() const +{ + return static_cast(d.get()); +} + +#define d d_func() +#define q q_func() + +PaperKeyProcessCommand::Private::Private(PaperKeyProcessCommand *qq, KeyListController *c) + : Command::Private(qq, c), + process1(), + process2(), + dialog(), + errorBuffer(), + ignoresSuccessOrFailure(false), + showsOutputWindow(false), + canceled(false) +{ + process1.setStandardOutputProcess(&process2); +} + +PaperKeyProcessCommand::Private::~Private() {} + +PaperKeyProcessCommand::PaperKeyProcessCommand(KeyListController *c) + : Command(new Private(this, c)) +{ + d->init(); +} + +PaperKeyProcessCommand::PaperKeyProcessCommand(QAbstractItemView *v, KeyListController *c) + : Command(v, new Private(this, c)) +{ + d->init(); +} + +PaperKeyProcessCommand::PaperKeyProcessCommand(const GpgME::Key &key) + : Command(key, new Private(this, 0)) +{ + d->init(); +} + +void PaperKeyProcessCommand::Private::init() +{ + connect(&process1, SIGNAL(readyReadStandardError()), + q, SLOT(slotProcessReadyReadStandardError())); + connect(&process2, SIGNAL(finished(int,QProcess::ExitStatus)), + q, SLOT(slotProcessFinished(int,QProcess::ExitStatus))); + connect(&process2, SIGNAL(readyReadStandardError()), + q, SLOT(slotProcessReadyReadStandardError())); +} + +PaperKeyProcessCommand::~PaperKeyProcessCommand() {} + +QDialog *PaperKeyProcessCommand::dialog() const +{ + return d->dialog; +} + +bool PaperKeyProcessCommand::preStartHook(QWidget *) const +{ + return true; +} + +void PaperKeyProcessCommand::postSuccessHook(QWidget *) +{ + +} + +void PaperKeyProcessCommand::doStart() +{ + + if (!preStartHook(d->parentWidgetOrView())) { + d->finished(); + return; + } + + QStringList args1; + QStringList args2; + + bool secondProcess = false; + foreach (const QString &str, arguments()) { + if (str == "|" || str == "&&") { + secondProcess = true; + } + if (str != "|" && str != "&&") { + if (!secondProcess) { + args1 << str; + } else { + args2 << str; + } + } + } + + d->arguments1 = args1; + d->arguments2 = args2; + + d->process1.start(d->arguments1.join(QStringLiteral(" "))); + d->message(i18n("Starting %1...", d->arguments1.join(QStringLiteral(" ")))); + d->process2.start(d->arguments2.join(QStringLiteral(" "))); + d->message(i18n("Starting %1...", d->arguments2.join(QStringLiteral(" ")))); + + d->process2.setProcessChannelMode(QProcess::ForwardedChannels); + + if (!d->process1.waitForStarted()) { + d->error(i18n("Unable to start process %1. " + "Please check your installation.", d->arguments1[0]), + errorCaption()); + d->finished(); + return; + } + if (!d->process2.waitForStarted()) { + d->error(i18n("Unable to start process %1. " + "Please check your installation.", d->arguments2[0]), + errorCaption()); + d->finished(); + } + QByteArray buffer; + buffer.append(d->process2.readAll()); + + d->message(buffer); + d->ensureDialogVisible(); +} + +void PaperKeyProcessCommand::doCancel() +{ + d->canceled = true; + if (d->process1.state() != QProcess::NotRunning) { + d->process1.terminate(); + QTimer::singleShot(PROCESS_TERMINATE_TIMEOUT, &d->process1, &QProcess::kill); + } + if (d->process2.state() != QProcess::NotRunning) { + d->process2.terminate(); + QTimer::singleShot(PROCESS_TERMINATE_TIMEOUT, &d->process2, &QProcess::kill); + } +} + +void PaperKeyProcessCommand::Private::slotProcessFinished(int code, QProcess::ExitStatus status) +{ + if (!canceled) { + if (status == QProcess::CrashExit) { + error( "Process1: " + q->errorExitMessage(arguments1) + + " - Process2: " + q->errorExitMessage(arguments2), q->errorCaption()); + } else if (ignoresSuccessOrFailure) { + if (dialog) { + message(i18n("Process finished")); + } else { + ; + } + } else if (code) { + error( "Process1: " + q->errorExitMessage(arguments1) + + " - Process2: " + q->errorExitMessage(arguments2), q->errorCaption()); + } else { + q->postSuccessHook(parentWidgetOrView()); + const QString successMessage = "Paperkey Sucessfully exported!"; + if (dialog) { + message(successMessage); + } else { + information(successMessage, q->successCaption()); + } + } + } + + if (dialog) { + dialog->setComplete(true); + } + finished(); +} + +void PaperKeyProcessCommand::Private::slotProcessReadyReadStandardError() +{ + while (process1.canReadLine()) { + QByteArray ba = process1.readLine(); + errorBuffer += ba; + while (ba.endsWith('\n') || ba.endsWith('\r')) { + ba.chop(1); + } + message(QString::fromLocal8Bit(ba.constData(), ba.size())); + } + while (process2.canReadLine()) { + QByteArray ba = process2.readLine(); + errorBuffer += ba; + while (ba.endsWith('\n') || ba.endsWith('\r')) { + ba.chop(1); + } + message(QString::fromLocal8Bit(ba.constData(), ba.size())); + } + +} + +QString PaperKeyProcessCommand::errorString() const +{ + return QString::fromLocal8Bit(d->errorBuffer); +} + +void PaperKeyProcessCommand::setIgnoresSuccessOrFailure(bool ignores) +{ + d->ignoresSuccessOrFailure = ignores; +} + +bool PaperKeyProcessCommand::ignoresSuccessOrFailure() const +{ + return d->ignoresSuccessOrFailure; +} + +void PaperKeyProcessCommand::setShowsOutputWindow(bool show) +{ + if (show == d->showsOutputWindow) { + return; + } + d->showsOutputWindow = show; + if (show) { + d->ensureDialogCreated(); + } else { + if (d->dialog) { + d->dialog->deleteLater(); + } + d->dialog = 0; + } +} + +bool PaperKeyProcessCommand::showsOutputWindow() const +{ + return d->showsOutputWindow; +} + +#undef d +#undef q + +#include "moc_paperkeyprocesscommand.cpp" +#include "paperkeyprocesscommand.moc" diff --git a/src/dialogs/exportpaperkeydialog.h b/src/dialogs/exportpaperkeydialog.h new file mode 100644 --- /dev/null +++ b/src/dialogs/exportpaperkeydialog.h @@ -0,0 +1,87 @@ +/* -*- mode: c++; c-basic-offset:4 -*- + dialogs/exportsecretkeydialog.h + + This file is part of Kleopatra, the KDE keymanager + Copyright (c) 2016 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. +*/ + +#ifndef __KLEOPATRA_DIALOGS_EXPORTPAPERKEYDIALOG_H__ +#define __KLEOPATRA_DIALOGS_EXPORTPAPERKEYDIALOG_H__ + +#include + +#include + +namespace GpgME +{ +class Key; +} + +namespace Kleo +{ +namespace Dialogs +{ + +class ExportPaperKeyDialog : public QDialog +{ + Q_OBJECT +public: + explicit ExportPaperKeyDialog(QWidget *parent = Q_NULLPTR); + ~ExportPaperKeyDialog(); + + void setKey(const GpgME::Key &key); + GpgME::Key key() const; + + void setFileName(const QString &fileName); + QString fileName() const; + + void setIgnoreCRCError(bool on); + bool ignoreCRCError() const; + + void setOutputWidth(int outputWidth); + int outputWidth() const; + + void setOutputType(bool raw); + bool outputTypeRaw() const; + bool outputTypeBase16() const; + +protected Q_SLOTS: + void accept() Q_DECL_OVERRIDE; + +private: + class Private; + kdtools::pimpl_ptr d; + Q_PRIVATE_SLOT(d, void updateFileName()) +}; + +} +} + +#endif /* __KLEOPATRA_DIALOGS_EXPORTPAPERKEYDIALOG_H__ */ + diff --git a/src/dialogs/exportpaperkeydialog.cpp b/src/dialogs/exportpaperkeydialog.cpp new file mode 100644 --- /dev/null +++ b/src/dialogs/exportpaperkeydialog.cpp @@ -0,0 +1,234 @@ +/* -*- mode: c++; c-basic-offset:4 -*- + dialogs/exportsecretkeydialog.cpp + + This file is part of Kleopatra, the KDE keymanager + Copyright (c) 2016 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 + +#include "exportpaperkeydialog.h" + +#include "ui_exportpaperkeydialog.h" + +#include + +#include + +#include +#include + +#include + +using namespace Kleo; +using namespace Kleo::Dialogs; +using namespace GpgME; + +// This comes from gnupg's sources, agent/minip12.c +// In fact, any charset supported by iconv would work, but we don't +//link to iconv directly... +static const char *charsets[] = { + "utf8", + "iso-8859-1", + "iso-8859-15", + "iso-8859-2", + "iso-8859-3", + "iso-8859-4", + "iso-8859-5", + "iso-8859-6", + "iso-8859-7", + "iso-8859-8", + "iso-8859-9", + "koi8-r", + "ibm437", + "ibm850", + "euc-jp", + "big5", +}; +static const unsigned int numCharsets = sizeof charsets / sizeof * charsets; + +class ExportPaperKeyDialog::Private +{ + friend class ::Kleo::Dialogs::ExportPaperKeyDialog; + ExportPaperKeyDialog *const q; +public: + explicit Private(ExportPaperKeyDialog *qq) + : q(qq), + ui(q) + { + + } + +private: + void updateWidgets() + { + } + + void updateFileName() + { + + static const char *extensions[] = { + ".txt" + }; + const unsigned int idx = 0; + const char *const extension = extensions[idx]; + + const QString nf = i18n("Paper Key Files") + + QLatin1String(" ") + + QLatin1String(extensions[0]); + ui.outputFileFR->setNameFilter(nf); + + QString fn = q->fileName(); + if (fn.isEmpty()) { + return; + } + + bool found = false; + for (unsigned int i = 0; i < sizeof extensions / sizeof * extensions; ++i) + if (fn.endsWith(QLatin1String(extensions[i]), Qt::CaseInsensitive)) { + fn.chop(4); + found = true; + break; + } + if (found) { + q->setFileName(fn + QLatin1String(extension)); + } + } + + void updateLabel() + { + ui.descriptionLB->setText(i18nc("@info", + "Please select export options for %1:", + Formatting::formatForComboBox(key))); + } +private: + Key key; + + struct UI : public Ui_ExportPaperKeyDialog { + explicit UI(Dialogs::ExportPaperKeyDialog *qq) + : Ui_ExportPaperKeyDialog() + { + setupUi(qq); + + outputFileFR->setExistingOnly(false); + outputFileFR->setFilter(QDir::Files); + outputFileFR->setNameFilter(i18n("Paper Key Files (*.txt)")); + + } + } ui; +}; + +ExportPaperKeyDialog::ExportPaperKeyDialog(QWidget *p) + : QDialog(p), d(new Private(this)) +{ + +} + +ExportPaperKeyDialog::~ExportPaperKeyDialog() {} + +void ExportPaperKeyDialog::setKey(const Key &key) +{ + if (qstricmp(key.primaryFingerprint(), d->key.primaryFingerprint()) == 0) { + return; + } + d->key = key; + d->updateWidgets(); + d->updateLabel(); + d->updateFileName(); +} + +Key ExportPaperKeyDialog::key() const +{ + return d->key; +} + +void ExportPaperKeyDialog::setFileName(const QString &fileName) +{ + d->ui.outputFileFR->setFileName(fileName); +} + +QString ExportPaperKeyDialog::fileName() const +{ + return d->ui.outputFileFR->fileName(); +} + +void ExportPaperKeyDialog::setIgnoreCRCError(bool on) +{ + d->ui.ignoreCRCErrorCB->setChecked(on); +} + +bool ExportPaperKeyDialog::ignoreCRCError() const +{ + return d->ui.ignoreCRCErrorCB->isChecked(); +} + +void ExportPaperKeyDialog::setOutputWidth(int outputWidth) +{ + d->ui.outputWidthTB->clear(); + d->ui.outputWidthTB->insert(QString::number(outputWidth)); +} + +int ExportPaperKeyDialog::outputWidth() const +{ + return d->ui.outputWidthTB->text().toInt(); +} + +void ExportPaperKeyDialog::setOutputType(bool raw) +{ + d->ui.outputTypeRawRB->setChecked(raw); + d->ui.outputTypeBase16RB->setChecked(!raw); +} + +bool ExportPaperKeyDialog::outputTypeRaw() const +{ + return d->ui.outputTypeRawRB->isChecked(); +} + +bool ExportPaperKeyDialog::outputTypeBase16() const +{ + return d->ui.outputTypeBase16RB->isChecked(); +} + +void ExportPaperKeyDialog::accept() +{ + d->updateFileName(); + const QString fn = fileName(); + if (fn.isEmpty()) { + KMessageBox::information(this, i18nc("@info", + "You have to enter an output filename."), + i18nc("@title", "Incomplete data")); + d->ui.outputFileFR->setFocus(); + return; + } + + QDialog::accept(); +} + +#include "moc_exportpaperkeydialog.cpp" + diff --git a/src/dialogs/exportpaperkeydialog.ui b/src/dialogs/exportpaperkeydialog.ui new file mode 100644 --- /dev/null +++ b/src/dialogs/exportpaperkeydialog.ui @@ -0,0 +1,186 @@ + + ExportPaperKeyDialog + + + + 0 + 0 + 372 + 194 + + + + Export Paper Certificate + + + + + + true + + + + + + + Output file: + + + outputFileFR + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + Ingore CRC Errors + + + + + + + Output Text Length: + + + + + + + 80 + + + + + + + Output Type + + + + + + base16 + + + + + + + raw + + + + + + + + + + Qt::Vertical + + + + 0 + 0 + + + + + + + + + + + + Kleo::FileNameRequester + QWidget +
libkleo/filenamerequester.h
+ 1 + + fileNameChanged(QString) + +
+
+ + + + buttonBox + accepted() + ExportPaperKeyDialog + accept() + + + 227 + 165 + + + 157 + 193 + + + + + buttonBox + rejected() + ExportPaperKeyDialog + reject() + + + 295 + 171 + + + 286 + 193 + + + + + ignoreCRCErrorCB + toggled(bool) + ExportPaperKeyDialog + updateFileName() + + + 77 + 83 + + + 69 + 131 + + + + + outputFileFR + fileNameChanged(QString) + ExportPaperKeyDialog + updateFileName() + + + 267 + 53 + + + 159 + 131 + + + + + + updateFileName() + +
diff --git a/src/kleopatra.rc b/src/kleopatra.rc --- a/src/kleopatra.rc +++ b/src/kleopatra.rc @@ -11,6 +11,7 @@ + @@ -110,6 +111,7 @@ + diff --git a/src/missing-icons.txt b/src/missing-icons.txt --- a/src/missing-icons.txt +++ b/src/missing-icons.txt @@ -4,10 +4,12 @@ file_export_certificate file_export_certifictes_to_server file_export_secret_keys +file_export_paper_key file_lookup_certificates (from server) file_import_certificates file_decrypt_verify_files (use same in gpgex) file_sign_encrypt_files (use same in gpgex) +view-paperkey-export view_certificate_details certificates_delete diff --git a/src/utils/action_data.cpp b/src/utils/action_data.cpp --- a/src/utils/action_data.cpp +++ b/src/utils/action_data.cpp @@ -72,7 +72,8 @@ return a; } -QAction *Kleo::make_action_from_data_with_collection(const action_data &ad, KActionCollection *coll) +QAction *Kleo::make_action_from_data_with_collection( const action_data &ad, + KActionCollection *coll) { QAction *const a = createAction(ad, coll); @@ -89,9 +90,11 @@ } } -void Kleo::make_actions_from_data(const action_data *ads, unsigned int size, KActionCollection *coll) +void Kleo::make_actions_from_data(const action_data *ads, + unsigned int size, KActionCollection *coll) { for (unsigned int i = 0; i < size; ++i) { - coll->addAction(QLatin1String(ads[i].name), make_action_from_data_with_collection(ads[i], coll)); + coll->addAction(QLatin1String(ads[i].name), + make_action_from_data_with_collection(ads[i], coll)); } } diff --git a/src/utils/paperkey-helper.h b/src/utils/paperkey-helper.h new file mode 100644 --- /dev/null +++ b/src/utils/paperkey-helper.h @@ -0,0 +1,52 @@ +/* -*- mode: c++; c-basic-offset:4 -*- + utils/gnupg-helper.h + + This file is part of Kleopatra, the KDE keymanager + Copyright (c) 2016 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. +*/ + +#ifndef __KLEOPATRA_PAPERKEYHELPER_H__ +#define __KLEOPATRA_PAPERKEYHELPER_H__ + +#include + +class QString; +class QStringList; + +namespace Kleo +{ + + bool paperKeyInstalled(); + + QString paperKeyInstallationPath(); + + QString paperKeyPath(); +} + + +#endif // __KLEOPATRA_PAPERKEYHELPER_H__ diff --git a/src/utils/paperkey-helper.cpp b/src/utils/paperkey-helper.cpp new file mode 100644 --- /dev/null +++ b/src/utils/paperkey-helper.cpp @@ -0,0 +1,59 @@ +/* -*- mode: c++; c-basic-offset:4 -*- + utils/gnupg-helper.cpp + + This file is part of Kleopatra, the KDE keymanager + Copyright (c) 2016 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 "paperkey-helper.h" + +#include +#include + +bool Kleo::paperKeyInstalled() +{ + + if (!paperKeyInstallationPath().isEmpty()) { + return true; + } else { + return true; + } + +} + +QString Kleo::paperKeyInstallationPath() +{ + + QStringList path; + return QStandardPaths::findExecutable("paperkey", path); +} + +QString Kleo::paperKeyPath() +{ + return paperKeyInstallationPath(); +} diff --git a/src/view/keylistcontroller.cpp b/src/view/keylistcontroller.cpp --- a/src/view/keylistcontroller.cpp +++ b/src/view/keylistcontroller.cpp @@ -42,6 +42,7 @@ #include #include +#include #include "tooltippreferences.h" #include "kleopatra_debug.h" @@ -70,6 +71,7 @@ #include "commands/newcertificatecommand.h" #include "commands/checksumverifyfilescommand.h" #include "commands/checksumcreatefilescommand.h" +#include "commands/exportpaperkeycommand.h" #include @@ -380,6 +382,10 @@ "file_export_secret_keys", i18n("Export Secret Keys..."), QString(), "view-certificate-export-secret", 0, 0, QString(), false, true }, + { + "file_export_paper_key", i18n("Export Paper Key..."), QString(), + "view-paperkey-export", 0, 0, QString(), false, true + }, { "file_lookup_certificates", i18n("Lookup Certificates on Server..."), QString(), "edit-find", 0, 0, QStringLiteral("Shift+Ctrl+I"), false, true @@ -419,7 +425,7 @@ }, // Certificate menu { - "certificates_delete", i18n("Delete"), QString()/*i18n("Delete selected certificates")*/, + "certificates_delete", i18n("Delete"), QString()/*i18n("Delete selected certifi^:cates")*/, "edit-delete", 0, 0, QStringLiteral("Delete"), false, true }, { @@ -495,6 +501,7 @@ //--- registerActionForCommand(coll->action(QStringLiteral("file_export_certificates"))); registerActionForCommand(coll->action(QStringLiteral("file_export_secret_keys"))); + registerActionForCommand(coll->action(QStringLiteral("file_export_paper_key"))); registerActionForCommand(coll->action(QStringLiteral("file_export_certificates_to_server"))); //--- registerActionForCommand(coll->action(QStringLiteral("file_decrypt_verify_files"))); @@ -724,6 +731,10 @@ Command::Restrictions result = Command::NeedSelection; + if (paperKeyInstalled()) { + result |= Command::PaperKeyInstalled; + } + if (keys.size() == 1) { result |= Command::OnlyOneKey; }