Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F34123805
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
18 KB
Subscribers
None
View Options
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 += " " + 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
Details
Attached
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
Attached To
rGTO Gpg4win-Tools
Event Timeline
Log In to Comment