Page MenuHome GnuPG

No OneTemporary

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index e6c3800..abe8f96 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,15 +1,16 @@
# Copyright (C) 2018 Intevation GmbH <info@intevation.de>
#
# This file is Free Software under the GNU GPL (v>=2)
# and comes with ABSOLUTELY NO WARRANTY!
# See LICENSE.txt for details.
include_directories(${Qt5Core_INCLUDE_DIRS})
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
include_directories(util)
add_subdirectory(resolver)
add_subdirectory(overlayer)
add_subdirectory(gpgolconfig)
+add_subdirectory(gpgolkeyadder)
diff --git a/src/gpgolkeyadder/CMakeLists.txt b/src/gpgolkeyadder/CMakeLists.txt
new file mode 100644
index 0000000..8800fea
--- /dev/null
+++ b/src/gpgolkeyadder/CMakeLists.txt
@@ -0,0 +1,36 @@
+# Copyright (C) 2018 Intevation GmbH <info@intevation.de>
+#
+# This file is Free Software under the GNU GPL (v>=2)
+# and comes with ABSOLUTELY NO WARRANTY!
+# See LICENSE.txt for details.
+
+set(EXECUTABLE_NAME "gpgolkeyadder")
+
+set(EXECUTABLE_SRC
+ main.cpp
+ gpgolkeyadder-options.h
+ gpgolkeyadder.cpp
+ stdinreader.cpp
+ ${CMAKE_SOURCE_DIR}/src/img/icon.rc
+ ${CMAKE_SOURCE_DIR}/src/util/strhelp.c
+ ${CMAKE_SOURCE_DIR}/src/util/w32-util.cpp
+ ${CMAKE_SOURCE_DIR}/src/util/w32-gettext.c
+)
+
+qt5_add_resources(EXECUTABLE_SRC gpgolkeyadder.qrc)
+
+add_executable(${EXECUTABLE_NAME}
+ ${_add_executable_params}
+ ${EXECUTABLE_SRC}
+)
+
+target_link_libraries(${EXECUTABLE_NAME}
+ Qt5::Widgets
+ Gpgmepp
+)
+
+if (WIN32)
+ set_target_properties(${EXECUTABLE_NAME} PROPERTIES LINK_FLAGS "-municode")
+endif(WIN32)
+
+install(TARGETS ${EXECUTABLE_NAME} DESTINATION bin)
diff --git a/src/gpgolkeyadder/gpgolkeyadder-options.h b/src/gpgolkeyadder/gpgolkeyadder-options.h
new file mode 100644
index 0000000..038e411
--- /dev/null
+++ b/src/gpgolkeyadder/gpgolkeyadder-options.h
@@ -0,0 +1,37 @@
+#ifndef GPGOLKEYADDER_OPTIONS
+#define GPGOLKEYADDER_OPTIONS
+/* Copyright (C) 2018 by Intevation GmbH <info@intevation.de>
+ *
+ * This file is Free Software under the GNU GPL (v>=2)
+ * and comes with ABSOLUTELY NO WARRANTY!
+ * See LICENSE.txt for details.
+ */
+
+#include <QCommandLineParser>
+#include <QList>
+
+/** @file Commandline options*/
+static void options(QCommandLineParser &parser)
+{
+ QList<QCommandLineOption> options;
+
+ options
+ << QCommandLineOption(QStringList() << QStringLiteral("debug"),
+ QStringLiteral("Print debug output."))
+ << QCommandLineOption(QStringLiteral("hwnd"),
+ QStringLiteral("Parent Window"),
+ QStringLiteral("windows window handle"))
+ << QCommandLineOption(QStringLiteral("username"),
+ QStringLiteral("Name"),
+ QStringLiteral("username"))
+ << QCommandLineOption(QStringLiteral("lang"),
+ QStringLiteral("Language"),
+ QStringLiteral("Language to be used e.g. de_DE"));
+
+ for (const auto &opt: options) {
+ parser.addOption(opt);
+ }
+ parser.addVersionOption();
+ parser.addHelpOption();
+}
+#endif
diff --git a/src/gpgolkeyadder/gpgolkeyadder.cpp b/src/gpgolkeyadder/gpgolkeyadder.cpp
new file mode 100644
index 0000000..ea7159e
--- /dev/null
+++ b/src/gpgolkeyadder/gpgolkeyadder.cpp
@@ -0,0 +1,239 @@
+/* Copyright (C) 2018 by Intevation GmbH <info@intevation.de>
+ *
+ * This file is Free Software under the GNU GPL (v>=2)
+ * and comes with ABSOLUTELY NO WARRANTY!
+ * See LICENSE.txt for details.
+ */
+
+#include "gpgolkeyadder.h"
+#include "w32-gettext.h"
+#include "w32-util.h"
+#include "stdinreader.h"
+
+#include <QLabel>
+#include <QWidget>
+#include <QVBoxLayout>
+#include <QDialogButtonBox>
+#include <QPushButton>
+#include <QCommandLineParser>
+#include <QDebug>
+#include <QTextEdit>
+#include <QFont>
+#include <QFontMetrics>
+#include <QMessageBox>
+#include <QDateTime>
+#include <QLocale>
+
+#include <gpgme++/data.h>
+#include <gpgme++/key.h>
+
+#include <iostream>
+
+GpgOLKeyAdder::GpgOLKeyAdder(const QCommandLineParser &parser):
+ QDialog(nullptr),
+ mEdit(new QTextEdit)
+{
+ setWindowFlags(windowFlags() & (~Qt::WindowContextHelpButtonHint));
+
+ mName = parser.value(QStringLiteral("username"));
+
+ setWindowTitle(_("GpgOL") + QStringLiteral(" - ") + _("Configure key for:") +
+ QStringLiteral(" ") + mName);
+
+ setWindowIcon(QIcon(":/gpgol-icon.svg"));
+
+ const auto hwnd = parser.value(QStringLiteral("hwnd"));
+ if (!hwnd.isEmpty()) {
+ bool ok;
+ WId id = (WId) hwnd.toInt(&ok);
+ if (!ok) {
+ qDebug() << "invalid hwnd value";
+ } else {
+ W32::setupForeignParent(id, this, true);
+ setModal(true);
+ }
+ }
+
+ setupGUI();
+
+ // Deletes itself
+ auto reader = new StdinReader;
+
+ connect (reader, &StdinReader::stdinRead, this, [this] (const QByteArray &data) {
+ if (data.size()) {
+ mEdit->setPlainText(QString::fromUtf8(data));
+ }
+ });
+ reader->start();
+}
+
+void GpgOLKeyAdder::setupGUI()
+{
+ /* Setup Edit */
+ auto fixedFont = QFont("Monospace", 10);
+ fixedFont.setStyleHint(QFont::TypeWriter);
+
+ mEdit->setFont(fixedFont);
+ resize(QFontMetrics(fixedFont).averageCharWidth() * 80,
+ QFontMetrics(fixedFont).height() * 40);
+
+ mEdit->setPlaceholderText(QString::fromUtf8(_("Paste a public key export here. It should look like:")) +
+ QStringLiteral("\n\n-----BEGIN PGP PUBLIC KEY BLOCK-----\n\n"
+ "mQENBEzJavsBCADG/guWL6AxGgngUxp/DcmoitJjaJMqcJkBtD3uKrW81Pbnm3LI\n"
+ "...\n"
+ "dCl8hHggB9x2\n"
+ "=oShe\n"
+ "-----END PGP PUBLIC KEY BLOCK-----"));
+ mEdit->setUndoRedoEnabled(true);
+ /* Setup buttons */
+ QDialogButtonBox *buttonBox = new QDialogButtonBox();
+ buttonBox->setStandardButtons(QDialogButtonBox::Cancel |
+ QDialogButtonBox::Ok);
+
+ connect(buttonBox->button(QDialogButtonBox::Ok), &QAbstractButton::clicked,
+ this, [this] () {
+ checkAccept();
+ });
+ connect(buttonBox->button(QDialogButtonBox::Cancel), &QAbstractButton::clicked,
+ this, [this] () {
+ qApp->quit();
+ });
+
+ auto okBtn = buttonBox->button(QDialogButtonBox::Ok);
+ okBtn->setEnabled(false);
+ connect(mEdit, &QTextEdit::textChanged, this, [this, okBtn] () {
+ const auto text = mEdit->toPlainText().trimmed().toUtf8();
+ GpgME::Data data(text.constData(), text.size(), false);
+
+ okBtn->setEnabled(data.type() == GpgME::Data::PGPKey);
+ });
+
+ /* Setup layout */
+ auto layout = new QVBoxLayout;
+ setLayout(layout);
+ layout->addWidget(mEdit);
+ layout->addWidget(buttonBox);
+}
+
+void GpgOLKeyAdder::save(const QByteArray &data)
+{
+ std::cout << data.constData() << std::endl;
+ qApp->quit();
+}
+
+static QString prettyNameAndEMail(const QString &id, const QString &name, const QString &email, const QString &comment)
+{
+ if (name.isEmpty()) {
+ if (email.isEmpty()) {
+ return QString();
+ } else if (comment.isEmpty()) {
+ return QStringLiteral("<%1>").arg(email);
+ } else {
+ return QStringLiteral("(%2) <%1>").arg(email, comment);
+ }
+ }
+ if (email.isEmpty()) {
+ if (comment.isEmpty()) {
+ return name;
+ } else {
+ return QStringLiteral("%1 (%2)").arg(name, comment);
+ }
+ }
+ if (comment.isEmpty()) {
+ return QStringLiteral("%1 <%2>").arg(name, email);
+ } else {
+ return QStringLiteral("%1 (%3) <%2>").arg(name, email, comment);
+ }
+ return QString();
+}
+
+static QString prettyNameAndEMail(const char *id, const char *name_, const std::string &email_, const char *comment_)
+{
+ return prettyNameAndEMail(QString::fromUtf8(id), QString::fromUtf8(name_), QString::fromStdString(email_),
+ QString::fromUtf8(comment_));
+}
+
+static QString prettyNameAndEMail(const GpgME::UserID &uid)
+{
+ qDebug() << "UserID: " << uid.id();
+ return prettyNameAndEMail(uid.id(), uid.name(), uid.addrSpec(), uid.comment());
+}
+
+static QString time_t2string(time_t t)
+{
+ QDateTime dt;
+ dt.setTime_t(t);
+ return QLocale().toString(dt, QLocale::ShortFormat);
+}
+
+void GpgOLKeyAdder::checkAccept()
+{
+ const auto text = mEdit->toPlainText().trimmed().toUtf8();
+
+ if (text.isEmpty()) {
+ save(text);
+ // Save exits
+ return;
+ }
+
+ GpgME::Data data(text.constData(), text.size(), false);
+
+ const auto keys = data.toKeys();
+
+ if (!keys.size()) {
+ QMessageBox::warning(this, QString::fromUtf8 (_("Error")),
+ QStringLiteral("<b>%1</b><br/><br/>").arg(QString::fromUtf8(_("Failed to parse any public key."))));
+ return;
+ }
+
+ QStringList keyInfos;
+
+ for (const auto &key: keys) {
+ if (key.isNull() || !key.numSubkeys()) {
+ qDebug() << "Null key?";
+ continue;
+ }
+
+
+ if (key.hasSecret()) {
+ QMessageBox::warning(this, QString::fromUtf8 (_("Error")),
+ QStringLiteral("<b>%1</b><br/><br/>").arg(QString::fromUtf8(_("Secret key detected."))) +
+ QString::fromUtf8(_("You can only configure public keys in Outlook."
+ " Import secret keys with Kleopatra.")));
+ return;
+ }
+ if (key.isRevoked() || key.isExpired() || key.isInvalid() || key.isDisabled() || !key.canEncrypt()) {
+ QMessageBox::warning(this, QString::fromUtf8 (_("Error")),
+ QStringLiteral("<b>%1</b><br/><br/>%2<br/><br/>").arg(QString::fromUtf8(_("Invalid key detected."))).arg(
+ key.primaryFingerprint()) +
+ QString::fromUtf8(_("The key is unusable for Outlook."
+ " Please check Kleopatra for more information.")));
+ return;
+ }
+ const auto subkey = key.subkey(0);
+ QString info = QString::fromLatin1(key.primaryFingerprint()) + "<br/>" +
+ QString::fromUtf8(_("Created:")) + " " + time_t2string(subkey.creationTime()) + "<br/>" +
+ QString::fromUtf8(_("User Ids:")) + "<br/>";
+
+ for (const auto &uid: key.userIDs()) {
+ if (uid.isNull() || uid.isRevoked() || uid.isInvalid()) {
+ continue;
+ }
+ info += "&nbsp;&nbsp;" + prettyNameAndEMail(uid).toHtmlEscaped() + "<br/>";
+ }
+ keyInfos << info;
+ }
+
+ QString msg = QString::fromUtf8(_("You are about to configure the following %1 for:")).arg(
+ (keyInfos.size() > 1 ? QString::fromUtf8(_("keys")) : QString::fromUtf8(_("key")))) +
+ QStringLiteral("<br/>\t\"%1\"<br/><br/>").arg(mName.toHtmlEscaped()) +
+ keyInfos.join("<br/><br/>");
+
+ msg += "<br/><br/>" + QString::fromUtf8 (_("Continue?"));
+ const auto ret = QMessageBox::question(this, QString::fromUtf8(_("Confirm keys")), msg,
+ QMessageBox::Yes | QMessageBox::Abort, QMessageBox::Yes);
+ if (ret == QMessageBox::Yes) {
+ save(text);
+ return;
+ }
+}
diff --git a/src/gpgolkeyadder/gpgolkeyadder.h b/src/gpgolkeyadder/gpgolkeyadder.h
new file mode 100644
index 0000000..f64401c
--- /dev/null
+++ b/src/gpgolkeyadder/gpgolkeyadder.h
@@ -0,0 +1,34 @@
+#ifndef GPGOLKEYADDER_H
+#define GPGOLKEYADDER_H
+/* Copyright (C) 2018 by Intevation GmbH <info@intevation.de>
+ *
+ * This file is Free Software under the GNU GPL (v>=2)
+ * and comes with ABSOLUTELY NO WARRANTY!
+ * See LICENSE.txt for details.
+ */
+
+#include <QDialog>
+#include <QString>
+
+class QCommandLineParser;
+class QTextEdit;
+
+class GpgOLKeyAdder: public QDialog
+{
+ Q_OBJECT
+
+public:
+ GpgOLKeyAdder(const QCommandLineParser &parser);
+
+protected:
+ /** @brief UI setup */
+ void setupGUI();
+
+private:
+ void checkAccept();
+ void save(const QByteArray &data);
+
+ QTextEdit *mEdit;
+ QString mName;
+};
+#endif // GPGOLKEYADDER_H
diff --git a/src/gpgolkeyadder/gpgolkeyadder.qrc b/src/gpgolkeyadder/gpgolkeyadder.qrc
new file mode 100644
index 0000000..7fb3841
--- /dev/null
+++ b/src/gpgolkeyadder/gpgolkeyadder.qrc
@@ -0,0 +1,5 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file alias="gpgol-icon.svg">../img/lock.svg</file>
+</qresource>
+</RCC>
diff --git a/src/gpgolkeyadder/main.cpp b/src/gpgolkeyadder/main.cpp
new file mode 100644
index 0000000..715f976
--- /dev/null
+++ b/src/gpgolkeyadder/main.cpp
@@ -0,0 +1,163 @@
+/* Copyright (C) 2018 by Intevation GmbH
+ *
+ * This file is Free Software under the GNU GPL (v>=2)
+ * and comes with ABSOLUTELY NO WARRANTY!
+ * See LICENSE.txt for details.
+ */
+
+/** @file Main entry point for the application.
+ */
+#include "strhelp.h"
+#include "gpgolkeyadder-options.h"
+#include "w32-gettext.h"
+#include "w32-util.h"
+#include "gpgolkeyadder.h"
+
+#include <gpgme++/global.h>
+#include <gpgme++/error.h>
+
+#include <iostream>
+
+#include <QApplication>
+#include <QDebug>
+#include <QTextCodec>
+#include <QTimer>
+#include <QMessageBox>
+
+#ifdef Q_OS_WIN
+ #include <windows.h>
+ #include <shlobj.h>
+#endif
+
+#ifndef APPNAME
+#define APPNAME "GpgOL"
+#endif
+
+#ifndef VERSION
+#define VERSION "0.0"
+#endif
+
+bool g_debug = false;
+
+QtMessageHandler g_default_msg_handler = NULL;
+
+void filterDebugOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
+{
+ if (!g_debug && type == QtDebugMsg) {
+ return;
+ }
+
+ if (g_default_msg_handler) {
+ (*g_default_msg_handler)(type, context, msg);
+ }
+}
+
+int realMain(int argc, char **argv);
+
+#if defined(WIN32) && defined(UNICODE)
+
+/** @brief Unicode entry point.
+ *
+ * Converts arguments to UTF-8 and executes the real
+ * entry point realMain.
+ */
+int wmain(int argc, wchar_t **argv, wchar_t **envp)
+{
+ char **utf8args = NULL;
+
+ utf8args = (char**) xmalloc0 ((argc + 1) * sizeof(char*));
+
+ for (int i = 0; i < argc; i++) {
+ utf8args[i] = wchar_to_utf8(argv[i], wcslen(argv[i]));
+ if (utf8args[i] == NULL) {
+ printf ("Fatal: could not convert arguments to UTF-8.\n");
+ exit(-1);
+ }
+ }
+ int ret = realMain(argc, utf8args);
+ strv_free(utf8args);
+
+ return ret;
+}
+#else
+int main(int argc, char **argv)
+{
+ return realMain(argc, argv);
+}
+#endif
+
+/** @brief The real entry point to the application.
+ *
+ * @param [in] argc the count of the arguments.
+ * @param [in] argv On GNU/Linux this function expects argv to be in the
+ * native system encoding. On Windows the arguments
+ * shall be UTF-8
+ *
+ * @returns 0 on success an error code otherwise. */
+int realMain(int argc, char **argv)
+{
+ /* QApplication setup */
+ QApplication app(argc, argv);
+ QApplication::setOrganizationName(QStringLiteral(APPNAME));
+ QApplication::setApplicationName(QStringLiteral(APPNAME));
+ QApplication::setApplicationVersion(QStringLiteral(VERSION));
+
+#if 0
+ /* Setup translations */
+ QTranslator translator;
+ if (QLocale::system().name() == "C") {
+ /* Useful for testing / development as the primary target is german */
+ translator.load(":/l10n/main_de_DE");
+ } else {
+ translator.load(":/l10n/main_" + QLocale::system().name());
+ }
+ app.installTranslator(&translator);
+#endif
+
+ /* Parse the command line */
+ QCommandLineParser parser;
+ options(parser);
+
+#ifdef Q_OS_WIN
+ auto oldCodec = QTextCodec::codecForLocale();
+ QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
+#endif
+ parser.process(app);
+#ifdef Q_OS_WIN
+ QTextCodec::setCodecForLocale(oldCodec);
+#endif
+
+ g_debug = parser.isSet("debug");
+ g_default_msg_handler = qInstallMessageHandler(filterDebugOutput);
+
+ const auto lang = parser.value("lang");
+
+ if (!lang.isEmpty()) {
+ qputenv("LANG", lang.toUtf8());
+ }
+
+ // Initialize GpgME
+ const GpgME::Error gpgmeInitError = GpgME::initializeLibrary(0);
+
+ if (gpgmeInitError) {
+ QMessageBox::critical(nullptr, QObject::tr("Installation Error"),
+ QObject::tr("Could not initialize GPGME.") + "<br/>" +
+ QObject::tr("Please reinstall") + " " APPNAME ".");
+ return EXIT_FAILURE;
+ }
+
+ // Initialize w32-gettext
+ const auto localeDir = W32::getGpg4winLocaleDir();
+ if (!localeDir.empty()) {
+ i18n_init("gpgol", localeDir.c_str());
+ } else {
+ qDebug() << "No locale dir.";
+ }
+
+ GpgOLKeyAdder mainWin(parser);
+ mainWin.show();
+
+ app.exec();
+
+ return EXIT_SUCCESS;
+}
diff --git a/src/gpgolkeyadder/stdinreader.cpp b/src/gpgolkeyadder/stdinreader.cpp
new file mode 100644
index 0000000..5faf582
--- /dev/null
+++ b/src/gpgolkeyadder/stdinreader.cpp
@@ -0,0 +1,35 @@
+/* Copyright (C) 2018 by Intevation GmbH <info@intevation.de>
+ *
+ * This file is Free Software under the GNU GPL (v>=2)
+ * and comes with ABSOLUTELY NO WARRANTY!
+ * See LICENSE.txt for details.
+ */
+
+#include "stdinreader.h"
+#include <iostream>
+
+#include <QApplication>
+static void
+rtrim(std::string &s) {
+ s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) {
+ return !std::isspace(ch);
+ }).base(), s.end());
+}
+
+void StdinReader::run()
+{
+ std::string line;
+ while (true) {
+ std::getline(std::cin, line);
+ // Normalize line endings
+ rtrim(line);
+ line += "\n";
+
+ mData += QByteArray::fromStdString(line);
+ if (std::cin.eof()) {
+ Q_EMIT stdinRead(mData);
+ deleteLater();
+ return;
+ }
+ }
+}
diff --git a/src/gpgolkeyadder/stdinreader.h b/src/gpgolkeyadder/stdinreader.h
new file mode 100644
index 0000000..50fde47
--- /dev/null
+++ b/src/gpgolkeyadder/stdinreader.h
@@ -0,0 +1,27 @@
+#ifndef STDINREADER_H
+#define STDINREADER_H
+/* Copyright (C) 2018 by Intevation GmbH <info@intevation.de>
+ *
+ * This file is Free Software under the GNU GPL (v>=2)
+ * and comes with ABSOLUTELY NO WARRANTY!
+ * See LICENSE.txt for details.
+ */
+
+#include <QThread>
+#include <QByteArray>
+
+class StdinReader: public QThread
+{
+ Q_OBJECT;
+
+Q_SIGNALS:
+ void stdinRead(const QByteArray &data);
+
+protected:
+ virtual void run() override;
+
+private:
+ QByteArray mData;
+};
+
+#endif // STDINREADER_H

File Metadata

Mime Type
text/x-diff
Expires
Sat, Dec 6, 11:54 PM (1 d, 4 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
d1/65/9951853553f78f2f37ae535382d7

Event Timeline