[Pkg-gnupg-commit] [gpgme] 29/412: Initial checkin of gpgmepp sources
Daniel Kahn Gillmor
dkg at fifthhorseman.net
Thu Sep 22 21:26:08 UTC 2016
This is an automated email from the git hooks/post-receive script.
dkg pushed a commit to branch master
in repository gpgme.
commit 0855a1296a1908016f011eb5e6552854ac53e63a
Author: Andre Heinecke <aheinecke at intevation.de>
Date: Mon Feb 22 18:28:08 2016 +0100
Initial checkin of gpgmepp sources
Based on git.kde.org/pim/gpgmepp rev. 0e3ebc02
* lang/cpp/src/assuanresult.cpp,
lang/cpp/src/assuanresult.h,
lang/cpp/src/callbacks.cpp,
lang/cpp/src/callbacks.h,
lang/cpp/src/configuration.cpp,
lang/cpp/src/configuration.h,
lang/cpp/src/context.cpp,
lang/cpp/src/context.h,
lang/cpp/src/context_glib.cpp,
lang/cpp/src/context_p.h,
lang/cpp/src/context_qt.cpp,
lang/cpp/src/context_vanilla.cpp,
lang/cpp/src/data.cpp,
lang/cpp/src/data.h,
lang/cpp/src/data_p.h,
lang/cpp/src/decryptionresult.cpp,
lang/cpp/src/decryptionresult.h,
lang/cpp/src/defaultassuantransaction.cpp,
lang/cpp/src/defaultassuantransaction.h,
lang/cpp/src/editinteractor.cpp,
lang/cpp/src/editinteractor.h,
lang/cpp/src/encryptionresult.cpp,
lang/cpp/src/encryptionresult.h,
lang/cpp/src/engineinfo.cpp,
lang/cpp/src/engineinfo.h,
lang/cpp/src/error.h,
lang/cpp/src/eventloopinteractor.cpp,
lang/cpp/src/eventloopinteractor.h,
lang/cpp/src/exception.cpp,
lang/cpp/src/exception.h,
lang/cpp/src/global.h,
lang/cpp/src/gpgadduserideditinteractor.cpp,
lang/cpp/src/gpgadduserideditinteractor.h,
lang/cpp/src/gpgagentgetinfoassuantransaction.cpp,
lang/cpp/src/gpgagentgetinfoassuantransaction.h,
lang/cpp/src/gpgmefw.h,
lang/cpp/src/gpgmepp_export.h,
lang/cpp/src/gpgsetexpirytimeeditinteractor.cpp,
lang/cpp/src/gpgsetexpirytimeeditinteractor.h,
lang/cpp/src/gpgsetownertrusteditinteractor.cpp,
lang/cpp/src/gpgsetownertrusteditinteractor.h,
lang/cpp/src/gpgsignkeyeditinteractor.cpp,
lang/cpp/src/gpgsignkeyeditinteractor.h,
lang/cpp/src/importresult.cpp,
lang/cpp/src/importresult.h,
lang/cpp/src/key.cpp,
lang/cpp/src/key.h,
lang/cpp/src/keygenerationresult.cpp,
lang/cpp/src/keygenerationresult.h,
lang/cpp/src/keylistresult.cpp,
lang/cpp/src/keylistresult.h,
lang/cpp/src/notation.h,
lang/cpp/src/result.h,
lang/cpp/src/result_p.h,
lang/cpp/src/scdgetinfoassuantransaction.cpp,
lang/cpp/src/scdgetinfoassuantransaction.h,
lang/cpp/src/signingresult.cpp,
lang/cpp/src/signingresult.h,
lang/cpp/src/trustitem.cpp,
lang/cpp/src/trustitem.h,
lang/cpp/src/util.h,
lang/cpp/src/verificationresult.cpp,
lang/cpp/src/verificationresult.h,
lang/cpp/src/vfsmountresult.cpp,
lang/cpp/src/vfsmountresult.h,
lang/cpp/src/interfaces/assuantransaction.h,
lang/cpp/src/interfaces/dataprovider.h,
lang/cpp/src/interfaces/passphraseprovider.h,
lang/cpp/src/interfaces/progressprovider.h: New.
---
lang/cpp/src/assuanresult.cpp | 98 ++
lang/cpp/src/assuanresult.h | 80 +
lang/cpp/src/callbacks.cpp | 187 +++
lang/cpp/src/callbacks.h | 45 +
lang/cpp/src/configuration.cpp | 1139 ++++++++++++++
lang/cpp/src/configuration.h | 297 ++++
lang/cpp/src/context.cpp | 1707 +++++++++++++++++++++
lang/cpp/src/context.h | 353 +++++
lang/cpp/src/context_glib.cpp | 44 +
lang/cpp/src/context_p.h | 84 +
lang/cpp/src/context_qt.cpp | 44 +
lang/cpp/src/context_vanilla.cpp | 35 +
lang/cpp/src/data.cpp | 199 +++
lang/cpp/src/data.h | 110 ++
lang/cpp/src/data_p.h | 40 +
lang/cpp/src/decryptionresult.cpp | 276 ++++
lang/cpp/src/decryptionresult.h | 131 ++
lang/cpp/src/defaultassuantransaction.cpp | 81 +
lang/cpp/src/defaultassuantransaction.h | 65 +
lang/cpp/src/editinteractor.cpp | 364 +++++
lang/cpp/src/editinteractor.h | 68 +
lang/cpp/src/encryptionresult.cpp | 161 ++
lang/cpp/src/encryptionresult.h | 113 ++
lang/cpp/src/engineinfo.cpp | 89 ++
lang/cpp/src/engineinfo.h | 70 +
lang/cpp/src/error.h | 78 +
lang/cpp/src/eventloopinteractor.cpp | 201 +++
lang/cpp/src/eventloopinteractor.h | 156 ++
lang/cpp/src/exception.cpp | 58 +
lang/cpp/src/exception.h | 68 +
lang/cpp/src/global.h | 156 ++
lang/cpp/src/gpgadduserideditinteractor.cpp | 189 +++
lang/cpp/src/gpgadduserideditinteractor.h | 67 +
lang/cpp/src/gpgagentgetinfoassuantransaction.cpp | 123 ++
lang/cpp/src/gpgagentgetinfoassuantransaction.h | 73 +
lang/cpp/src/gpgmefw.h | 70 +
lang/cpp/src/gpgmepp_export.h | 41 +
lang/cpp/src/gpgsetexpirytimeeditinteractor.cpp | 141 ++
lang/cpp/src/gpgsetexpirytimeeditinteractor.h | 49 +
lang/cpp/src/gpgsetownertrusteditinteractor.cpp | 151 ++
lang/cpp/src/gpgsetownertrusteditinteractor.h | 50 +
lang/cpp/src/gpgsignkeyeditinteractor.cpp | 322 ++++
lang/cpp/src/gpgsignkeyeditinteractor.h | 64 +
lang/cpp/src/importresult.cpp | 216 +++
lang/cpp/src/importresult.h | 134 ++
lang/cpp/src/interfaces/assuantransaction.h | 47 +
lang/cpp/src/interfaces/dataprovider.h | 53 +
lang/cpp/src/interfaces/passphraseprovider.h | 40 +
lang/cpp/src/interfaces/progressprovider.h | 40 +
lang/cpp/src/key.cpp | 847 ++++++++++
lang/cpp/src/key.h | 358 +++++
lang/cpp/src/keygenerationresult.cpp | 94 ++
lang/cpp/src/keygenerationresult.h | 82 +
lang/cpp/src/keylistresult.cpp | 109 ++
lang/cpp/src/keylistresult.h | 81 +
lang/cpp/src/notation.h | 84 +
lang/cpp/src/result.h | 58 +
lang/cpp/src/result_p.h | 43 +
lang/cpp/src/scdgetinfoassuantransaction.cpp | 156 ++
lang/cpp/src/scdgetinfoassuantransaction.h | 76 +
lang/cpp/src/signingresult.cpp | 267 ++++
lang/cpp/src/signingresult.h | 162 ++
lang/cpp/src/trustitem.cpp | 116 ++
lang/cpp/src/trustitem.h | 81 +
lang/cpp/src/util.h | 179 +++
lang/cpp/src/verificationresult.cpp | 590 +++++++
lang/cpp/src/verificationresult.h | 173 +++
lang/cpp/src/vfsmountresult.cpp | 98 ++
lang/cpp/src/vfsmountresult.h | 76 +
69 files changed, 12197 insertions(+)
diff --git a/lang/cpp/src/assuanresult.cpp b/lang/cpp/src/assuanresult.cpp
new file mode 100644
index 0000000..056aefb
--- /dev/null
+++ b/lang/cpp/src/assuanresult.cpp
@@ -0,0 +1,98 @@
+/*
+ assuanresult.cpp - wraps a gpgme assuan result
+ Copyright (C) 2009 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <config-gpgme++.h>
+
+#include <assuanresult.h>
+#include "result_p.h"
+
+#include <gpgme.h>
+
+#include <istream>
+
+using namespace GpgME;
+
+#ifdef HAVE_GPGME_ASSUAN_ENGINE
+class AssuanResult::Private
+{
+public:
+ explicit Private(const gpgme_assuan_result_t r)
+ {
+ if (!r) {
+ return;
+ }
+ error = r->err;
+ }
+
+ gpgme_error_t error;
+};
+#endif
+
+AssuanResult::AssuanResult(gpgme_ctx_t ctx, int error)
+ : Result(error), d()
+{
+ init(ctx);
+}
+
+AssuanResult::AssuanResult(gpgme_ctx_t ctx, const Error &error)
+ : Result(error), d()
+{
+ init(ctx);
+}
+
+void AssuanResult::init(gpgme_ctx_t ctx)
+{
+ (void)ctx;
+#ifdef HAVE_GPGME_ASSUAN_ENGINE
+ if (!ctx) {
+ return;
+ }
+ gpgme_assuan_result_t res = gpgme_op_assuan_result(ctx);
+ if (!res) {
+ return;
+ }
+ d.reset(new Private(res));
+#endif
+}
+
+make_standard_stuff(AssuanResult)
+
+Error AssuanResult::assuanError() const
+{
+#ifdef HAVE_GPGME_ASSUAN_ENGINE
+ if (d) {
+ return Error(d->error);
+ }
+#endif
+ return Error();
+}
+
+std::ostream &GpgME::operator<<(std::ostream &os, const AssuanResult &result)
+{
+ os << "GpgME::AssuanResult(";
+ if (!result.isNull()) {
+ os << "\n error: " << result.error()
+ << "\n assuanError: " << result.assuanError()
+ << "\n";
+ }
+ return os << ')';
+}
diff --git a/lang/cpp/src/assuanresult.h b/lang/cpp/src/assuanresult.h
new file mode 100644
index 0000000..e1dc73a
--- /dev/null
+++ b/lang/cpp/src/assuanresult.h
@@ -0,0 +1,80 @@
+/*
+ assuanresult.h - wraps a gpgme assuan result
+ Copyright (C) 2009 Klarälvdalens Datakonsult AB <info at kdab.com>
+ Author: Marc Mutz <marc at kdab.com>
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_ASSUANRESULT_H__
+#define __GPGMEPP_ASSUANRESULT_H__
+
+#include "gpgmefw.h"
+#include "result.h"
+#include "gpgmepp_export.h"
+
+#include <time.h>
+
+#include <boost/shared_ptr.hpp>
+
+#include <vector>
+#include <iosfwd>
+
+namespace GpgME
+{
+
+class Error;
+
+class GPGMEPP_EXPORT AssuanResult : public Result
+{
+public:
+ AssuanResult();
+ AssuanResult(gpgme_ctx_t ctx, int error);
+ AssuanResult(gpgme_ctx_t ctx, const Error &error);
+ explicit AssuanResult(const Error &err);
+
+ const AssuanResult &operator=(AssuanResult other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(AssuanResult &other)
+ {
+ Result::swap(other);
+ using std::swap;
+ swap(this->d, other.d);
+ }
+
+ bool isNull() const;
+
+ Error assuanError() const;
+
+ class Private;
+private:
+ void init(gpgme_ctx_t ctx);
+ boost::shared_ptr<Private> d;
+};
+
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const AssuanResult &result);
+
+}
+
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(AssuanResult)
+
+#endif // __GPGMEPP_ASSUANRESULT_H__
diff --git a/lang/cpp/src/callbacks.cpp b/lang/cpp/src/callbacks.cpp
new file mode 100644
index 0000000..091975d
--- /dev/null
+++ b/lang/cpp/src/callbacks.cpp
@@ -0,0 +1,187 @@
+/*
+ callbacks.cpp - callback targets for internal use:
+ Copyright (C) 2003,2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <config-gpgme++.h>
+
+#include "callbacks.h"
+#include "util.h"
+
+#include <interfaces/progressprovider.h>
+#include <interfaces/passphraseprovider.h>
+#include <interfaces/dataprovider.h>
+#include <error.h>
+
+#include <gpgme.h>
+#include <gpg-error.h>
+
+#include <cassert>
+#include <cerrno>
+#include <cstring>
+#include <unistd.h>
+#include <stdlib.h>
+
+#ifndef HAVE_GPGME_SSIZE_T
+# define gpgme_ssize_t ssize_t
+#endif
+
+#ifndef HAVE_GPGME_OFF_T
+# define gpgme_off_t off_t
+#endif
+
+static inline gpgme_error_t make_err_from_syserror()
+{
+#ifdef HAVE_GPGME_GPG_ERROR_WRAPPERS
+ return gpgme_error_from_syserror();
+#else
+ return gpg_error_from_syserror();
+#endif
+}
+
+using GpgME::ProgressProvider;
+using GpgME::PassphraseProvider;
+using GpgME::DataProvider;
+
+void progress_callback(void *opaque, const char *what,
+ int type, int current, int total)
+{
+ ProgressProvider *provider = static_cast<ProgressProvider *>(opaque);
+ if (provider) {
+ provider->showProgress(what, type, current, total);
+ }
+}
+
+/* To avoid that a compiler optimizes certain memset calls away, these
+ macros may be used instead. */
+#define wipememory2(_ptr,_set,_len) do { \
+ volatile char *_vptr=(volatile char *)(_ptr); \
+ size_t _vlen=(_len); \
+ while(_vlen) { *_vptr=(_set); _vptr++; _vlen--; } \
+ } while(0)
+#define wipememory(_ptr,_len) wipememory2(_ptr,0,_len)
+
+gpgme_error_t passphrase_callback(void *opaque, const char *uid_hint, const char *desc,
+ int prev_was_bad, int fd)
+{
+ PassphraseProvider *provider = static_cast<PassphraseProvider *>(opaque);
+ bool canceled = false;
+ gpgme_error_t err = GPG_ERR_NO_ERROR;
+ char *passphrase = provider ? provider->getPassphrase(uid_hint, desc, prev_was_bad, canceled) : 0 ;
+ if (canceled) {
+ err = make_error(GPG_ERR_CANCELED);
+ } else {
+ if (passphrase && *passphrase) {
+ size_t passphrase_length = std::strlen(passphrase);
+ size_t written = 0;
+ do {
+#ifdef HAVE_GPGME_IO_READWRITE
+ ssize_t now_written = gpgme_io_write(fd, passphrase + written, passphrase_length - written);
+#else
+ ssize_t now_written = write(fd, passphrase + written, passphrase_length - written);
+#endif
+ if (now_written < 0) {
+ err = make_err_from_syserror();
+ break;
+ }
+ written += now_written;
+ } while (written < passphrase_length);
+ }
+ }
+
+ if (passphrase && *passphrase) {
+ wipememory(passphrase, std::strlen(passphrase));
+ }
+ free(passphrase);
+#ifdef HAVE_GPGME_IO_READWRITE
+ gpgme_io_write(fd, "\n", 1);
+#else
+ write(fd, "\n", 1);
+#endif
+ return err;
+}
+
+static gpgme_ssize_t
+data_read_callback(void *opaque, void *buf, size_t buflen)
+{
+ DataProvider *provider = static_cast<DataProvider *>(opaque);
+ if (!provider) {
+#ifdef HAVE_GPGME_GPG_ERROR_WRAPPERS
+ gpgme_err_set_errno(gpgme_err_code_to_errno(GPG_ERR_EINVAL));
+#else
+ gpg_err_set_errno(gpgme_err_code_to_errno(GPG_ERR_EINVAL));
+#endif
+ return -1;
+ }
+ return (gpgme_ssize_t)provider->read(buf, buflen);
+}
+
+static gpgme_ssize_t
+data_write_callback(void *opaque, const void *buf, size_t buflen)
+{
+ DataProvider *provider = static_cast<DataProvider *>(opaque);
+ if (!provider) {
+#ifdef HAVE_GPGME_GPG_ERROR_WRAPPERS
+ gpgme_err_set_errno(gpgme_err_code_to_errno(GPG_ERR_EINVAL));
+#else
+ gpg_err_set_errno(gpgme_err_code_to_errno(GPG_ERR_EINVAL));
+#endif
+ return -1;
+ }
+ return (gpgme_ssize_t)provider->write(buf, buflen);
+}
+
+static gpgme_off_t
+data_seek_callback(void *opaque, gpgme_off_t offset, int whence)
+{
+ DataProvider *provider = static_cast<DataProvider *>(opaque);
+ if (!provider) {
+#ifdef HAVE_GPGME_GPG_ERROR_WRAPPERS
+ gpgme_err_set_errno(gpgme_err_code_to_errno(GPG_ERR_EINVAL));
+#else
+ gpg_err_set_errno(gpgme_err_code_to_errno(GPG_ERR_EINVAL));
+#endif
+ return -1;
+ }
+ if (whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END) {
+#ifdef HAVE_GPGME_GPG_ERROR_WRAPPERS
+ gpgme_err_set_errno(gpgme_err_code_to_errno(GPG_ERR_EINVAL));
+#else
+ gpg_err_set_errno(gpgme_err_code_to_errno(GPG_ERR_EINVAL));
+#endif
+ return -1;
+ }
+ return provider->seek((off_t)offset, whence);
+}
+
+static void data_release_callback(void *opaque)
+{
+ DataProvider *provider = static_cast<DataProvider *>(opaque);
+ if (provider) {
+ provider->release();
+ }
+}
+
+const gpgme_data_cbs GpgME::data_provider_callbacks = {
+ &data_read_callback,
+ &data_write_callback,
+ &data_seek_callback,
+ &data_release_callback
+};
diff --git a/lang/cpp/src/callbacks.h b/lang/cpp/src/callbacks.h
new file mode 100644
index 0000000..4206637
--- /dev/null
+++ b/lang/cpp/src/callbacks.h
@@ -0,0 +1,45 @@
+/*
+ callbacks.h - callback targets for internal use:
+ Copyright (C) 2003 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ This is an internal header file, subject to change without
+ notice. DO NOT USE.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_CALLBACKS_H__
+#define __GPGMEPP_CALLBACKS_H__
+
+#include <gpgme.h>
+
+extern "C" {
+
+ void progress_callback(void *opaque, const char *what,
+ int type, int current, int total);
+ gpgme_error_t passphrase_callback(void *opaque, const char *uid_hint,
+ const char *desc, int prev_was_bad, int fd);
+}
+
+namespace GpgME
+{
+extern const gpgme_data_cbs data_provider_callbacks;
+extern const gpgme_edit_cb_t edit_interactor_callback;
+}
+
+#endif // __GPGME_CALLBACKS_H__
diff --git a/lang/cpp/src/configuration.cpp b/lang/cpp/src/configuration.cpp
new file mode 100644
index 0000000..fc19020
--- /dev/null
+++ b/lang/cpp/src/configuration.cpp
@@ -0,0 +1,1139 @@
+/*
+ configuration.cpp - wraps gpgme configuration components
+ Copyright (C) 2010 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <config-gpgme++.h>
+
+#include "configuration.h"
+#include "error.h"
+#include "util.h"
+
+#include <gpgme.h>
+
+#include <boost/foreach.hpp>
+
+#include <iterator>
+#include <algorithm>
+#include <ostream>
+#include <cstring>
+
+using namespace GpgME;
+using namespace GpgME::Configuration;
+
+typedef boost::shared_ptr< boost::remove_pointer<gpgme_conf_opt_t>::type > shared_gpgme_conf_opt_t;
+typedef boost::weak_ptr< boost::remove_pointer<gpgme_conf_opt_t>::type > weak_gpgme_conf_opt_t;
+
+typedef boost::shared_ptr< boost::remove_pointer<gpgme_conf_arg_t>::type > shared_gpgme_conf_arg_t;
+typedef boost::weak_ptr< boost::remove_pointer<gpgme_conf_arg_t>::type > weak_gpgme_conf_arg_t;
+
+typedef boost::shared_ptr< boost::remove_pointer<gpgme_ctx_t>::type > shared_gpgme_ctx_t;
+typedef boost::weak_ptr< boost::remove_pointer<gpgme_ctx_t>::type > weak_gpgme_ctx_t;
+
+namespace
+{
+struct nodelete {
+ template <typename T> void operator()(T *) {}
+};
+}
+
+// static
+std::vector<Component> Component::load(Error &returnedError)
+{
+
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ //
+ // 1. get a context:
+ //
+ gpgme_ctx_t ctx_native = 0;
+ if (const gpgme_error_t err = gpgme_new(&ctx_native)) {
+ returnedError = Error(err);
+ return std::vector<Component>();
+ }
+ const shared_gpgme_ctx_t ctx(ctx_native, &gpgme_release);
+
+ //
+ // 2. load the config:
+ //
+ gpgme_conf_comp_t conf_list_native = 0;
+ if (const gpgme_error_t err = gpgme_op_conf_load(ctx_native, &conf_list_native)) {
+ returnedError = Error(err);
+ return std::vector<Component>();
+ }
+ shared_gpgme_conf_comp_t head(conf_list_native, &gpgme_conf_release);
+
+ //
+ // 3. convert to vector<Component>:
+ //
+ std::vector<Component> result;
+
+ while (head) {
+ // secure 'head->next' (if any) against memleaks:
+ shared_gpgme_conf_comp_t next;
+ if (head->next) {
+ next.reset(head->next, &gpgme_conf_release);
+ }
+
+ // now prevent double-free of next.get() and following:
+ head->next = 0;
+
+ // now add a new Component to 'result' (may throw):
+ result.resize(result.size() + 1);
+ result.back().comp.swap(head); // .comp = std::move( head );
+ head.swap(next); // head = std::move( next );
+ }
+
+ return result;
+#else
+ returnedError = Error(make_error(GPG_ERR_NOT_SUPPORTED));
+ return std::vector<Component>();
+#endif
+}
+
+Error Component::save() const
+{
+
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ if (isNull()) {
+ return Error(make_error(GPG_ERR_INV_ARG));
+ }
+
+ //
+ // 1. get a context:
+ //
+ gpgme_ctx_t ctx_native = 0;
+ if (const gpgme_error_t err = gpgme_new(&ctx_native)) {
+ return Error(err);
+ }
+ const shared_gpgme_ctx_t ctx(ctx_native, &gpgme_release);
+
+ //
+ // 2. save the config:
+ //
+ return Error(gpgme_op_conf_save(ctx.get(), comp.get()));
+#else
+ return Error(make_error(GPG_ERR_NOT_SUPPORTED));
+#endif
+}
+
+const char *Component::name() const
+{
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ return comp ? comp->name : 0 ;
+#else
+ return 0;
+#endif
+}
+
+const char *Component::description() const
+{
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ return comp ? comp->description : 0 ;
+#else
+ return 0;
+#endif
+}
+
+const char *Component::programName() const
+{
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ return comp ? comp->program_name : 0 ;
+#else
+ return 0;
+#endif
+}
+
+Option Component::option(unsigned int idx) const
+{
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ gpgme_conf_opt_t opt = 0;
+ if (comp) {
+ opt = comp->options;
+ }
+ while (opt && idx) {
+ opt = opt->next;
+ --idx;
+ }
+ if (opt) {
+ return Option(comp, opt);
+ } else {
+#endif
+ return Option();
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ }
+#endif
+}
+
+Option Component::option(const char *name) const
+{
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ gpgme_conf_opt_t opt = 0;
+ if (comp) {
+ opt = comp->options;
+ }
+ using namespace std; // for strcmp
+ while (opt && strcmp(name, opt->name) != 0) {
+ opt = opt->next;
+ }
+ if (opt) {
+ return Option(comp, opt);
+ } else {
+#endif
+ return Option();
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ }
+#endif
+}
+
+unsigned int Component::numOptions() const
+{
+ unsigned int result = 0;
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ for (gpgme_conf_opt_t opt = comp ? comp->options : 0 ; opt ; opt = opt->next) {
+ ++result;
+ }
+#endif
+ return result;
+}
+
+std::vector<Option> Component::options() const
+{
+ std::vector<Option> result;
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ for (gpgme_conf_opt_t opt = comp ? comp->options : 0 ; opt ; opt = opt->next) {
+ result.push_back(Option(comp, opt));
+ }
+#endif
+ return result;
+}
+
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+static gpgme_conf_arg_t mygpgme_conf_arg_copy(gpgme_conf_arg_t other, gpgme_conf_type_t type)
+{
+ gpgme_conf_arg_t result = 0, last = 0;
+ for (gpgme_conf_arg_t a = other ; a ; a = a->next) {
+ gpgme_conf_arg_t arg = 0;
+ const gpgme_error_t err
+ = gpgme_conf_arg_new(&arg, type,
+ a->no_arg ? 0 :
+ type == GPGME_CONF_STRING ? a->value.string :
+ /* else */ static_cast<void *>(&a->value));
+ if (err) {
+ gpgme_conf_arg_release(result, type);
+ return 0;
+ }
+ assert(arg);
+ if (result) {
+ last->next = arg;
+ } else {
+ result = arg;
+ }
+ last = arg;
+ }
+ return result;
+}
+#endif
+
+Component Option::parent() const
+{
+ return Component(comp.lock());
+}
+
+unsigned int Option::flags() const
+{
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ return isNull() ? 0 : opt->flags;
+#else
+ return 0;
+#endif
+}
+
+Level Option::level() const
+{
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ return isNull() ? Internal : static_cast<Level>(opt->level) ;
+#else
+ return Internal;
+#endif
+}
+
+const char *Option::name() const
+{
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ return isNull() ? 0 : opt->name ;
+#else
+ return 0;
+#endif
+}
+
+const char *Option::description() const
+{
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ return isNull() ? 0 : opt->description ;
+#else
+ return 0;
+#endif
+}
+
+const char *Option::argumentName() const
+{
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ return isNull() ? 0 : opt->argname ;
+#else
+ return 0;
+#endif
+}
+
+Type Option::type() const
+{
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ return isNull() ? NoType : static_cast<Type>(opt->type) ;
+#else
+ return NoType;
+#endif
+}
+
+Type Option::alternateType() const
+{
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ return isNull() ? NoType : static_cast<Type>(opt->alt_type) ;
+#else
+ return NoType;
+#endif
+}
+
+#if 0
+static Option::Variant argument_to_variant(gpgme_conf_type_t type, bool list, gpgme_conf_arg_t arg)
+{
+ assert(arg);
+ switch (type) {
+ case GPGME_CONF_NONE:
+ if (list) {
+ // return the count (number of times set):
+ return arg->value.count;
+ } else {
+ return none;
+ }
+ case GPGME_CONF_INT32:
+ if (list) {
+ std::vector<int> result;
+ for (gpgme_conf_arg_t a = arg ; a ; a = a->next) {
+ result.push_back(a->value.int32);
+ }
+ return result;
+ } else {
+ return arg->value.int32;
+ }
+ case GPGME_CONF_UINT32:
+ if (list) {
+ std::vector<unsigned int> result;
+ for (gpgme_conf_arg_t a = arg ; a ; a = a->next) {
+ result.push_back(a->value.uint32);
+ }
+ return result;
+ } else {
+ return arg->value.uint32;
+ }
+ case GPGME_CONF_FILENAME:
+ case GPGME_CONF_LDAP_SERVER:
+ case GPGME_CONF_KEY_FPR:
+ case GPGME_CONF_PUB_KEY:
+ case GPGME_CONF_SEC_KEY:
+ case GPGME_CONF_ALIAS_LIST:
+ // these should not happen in alt_type, but fall through
+ case GPGME_CONF_STRING:
+ if (list) {
+ std::vector<const char *> result;
+ for (gpgme_conf_arg_t a = arg ; a ; a = a->next) {
+ result.push_back(a->value.string);
+ }
+ return result;
+ } else {
+ return arg->value.string;
+ }
+ }
+ assert(!"Option: unknown alt_type!");
+ return Option::Variant();
+}
+
+namespace
+{
+inline const void *to_void_star(const char *s)
+{
+ return s;
+}
+inline const void *to_void_star(const std::string &s)
+{
+ return s.c_str();
+}
+inline const void *to_void_star(const int &i)
+{
+ return &i; // const-&: sic!
+}
+inline const void *to_void_star(const unsigned int &i)
+{
+ return &i; // const-&: sic!
+}
+
+struct VariantToArgumentVisitor : boost::static_visitor<gpgme_conf_arg_t> {
+ static gpgme_conf_arg_t make_argument(gpgme_conf_type_t type, const void *value)
+ {
+ gpgme_conf_arg_t arg = 0;
+#ifdef HAVE_GPGME_CONF_ARG_NEW_WITH_CONST_VALUE
+ if (const gpgme_error_t err = gpgme_conf_arg_new(&arg, type, value)) {
+ return 0;
+ }
+#else
+ if (const gpgme_error_t err = gpgme_conf_arg_new(&arg, type, const_cast<void *>(value))) {
+ return 0;
+ }
+#endif
+ else {
+ return arg;
+ }
+ }
+
+ gpgme_conf_arg_t operator()(bool v) const
+ {
+ return v ? make_argument(0) : 0 ;
+ }
+
+ gpgme_conf_arg_t operator()(const char *s) const
+ {
+ return make_argument(s ? s : "");
+ }
+
+ gpgme_conf_arg_t operator()(const std::string &s) const
+ {
+ return operator()(s.c_str());
+ }
+
+ gpgme_conf_arg_t operator()(int i) const
+ {
+ return make_argument(&i);
+ }
+
+ gpgme_conf_arg_t operator()(unsigned int i) const
+ {
+ return make_argument(&i);
+ }
+
+ template <typename T>
+ gpgme_conf_arg_t operator()(const std::vector<T> &value) const
+ {
+ gpgme_conf_arg_t result = 0;
+ gpgme_conf_arg_t last = 0;
+ for (typename std::vector<T>::const_iterator it = value.begin(), end = value.end() ; it != end ; ++it) {
+ if (gpgme_conf_arg_t arg = make_argument(to_void_star(*it))) {
+ if (last) {
+ last = last->next = arg;
+ } else {
+ result = last = arg;
+ }
+ }
+ }
+ return result;
+ }
+
+};
+}
+
+static gpgme_conf_arg_t variant_to_argument(const Option::Variant &value)
+{
+ VariantToArgumentVisitor v;
+ return apply_visitor(v, value);
+}
+
+optional<Option::Variant> Option::defaultValue() const
+{
+ if (isNull()) {
+ return optional<Variant>();
+ } else {
+ return argument_to_variant(opt->alt_type, opt->flags & GPGME_CONF_LIST, opt->default_value);
+ }
+}
+#endif
+
+Argument Option::defaultValue() const
+{
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ if (isNull()) {
+ return Argument();
+ } else {
+ return Argument(comp.lock(), opt, opt->default_value, false);
+ }
+#else
+ return Argument();
+#endif
+}
+
+const char *Option::defaultDescription() const
+{
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ return isNull() ? 0 : opt->default_description ;
+#else
+ return 0;
+#endif
+}
+
+Argument Option::noArgumentValue() const
+{
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ if (isNull()) {
+ return Argument();
+ } else {
+ return Argument(comp.lock(), opt, opt->no_arg_value, false);
+ }
+#else
+ return Argument();
+#endif
+}
+
+const char *Option::noArgumentDescription() const
+{
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ return isNull() ? 0 : opt->no_arg_description ;
+#else
+ return 0;
+#endif
+}
+
+Argument Option::activeValue() const
+{
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ if (isNull()) {
+ return Argument();
+ } else {
+ return Argument(comp.lock(), opt, opt->value, false);
+ }
+#else
+ return Argument();
+#endif
+}
+
+Argument Option::currentValue() const
+{
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ if (isNull()) {
+ return Argument();
+ }
+ const gpgme_conf_arg_t arg =
+ opt->change_value ? opt->new_value ? opt->new_value : opt->default_value :
+ opt->value ? opt->value :
+ /* else */ opt->default_value ;
+ return Argument(comp.lock(), opt, arg, false);
+#else
+ return Argument();
+#endif
+}
+
+Argument Option::newValue() const
+{
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ if (isNull()) {
+ return Argument();
+ } else {
+ return Argument(comp.lock(), opt, opt->new_value, false);
+ }
+#else
+ return Argument();
+#endif
+}
+
+bool Option::set() const
+{
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ if (isNull()) {
+ return false;
+ } else if (opt->change_value) {
+ return opt->new_value;
+ } else {
+ return opt->value;
+ }
+#else
+ return false;
+#endif
+}
+
+bool Option::dirty() const
+{
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ return !isNull() && opt->change_value ;
+#else
+ return false;
+#endif
+}
+
+Error Option::setNewValue(const Argument &argument)
+{
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ if (isNull()) {
+ return Error(make_error(GPG_ERR_INV_ARG));
+ } else if (argument.isNull()) {
+ return resetToDefaultValue();
+ } else if (const gpgme_conf_arg_t arg = mygpgme_conf_arg_copy(argument.arg, opt->alt_type)) {
+ return Error(gpgme_conf_opt_change(opt, 0, arg));
+ } else {
+ return Error(make_error(GPG_ERR_ENOMEM));
+ }
+#else
+ return Error(make_error(GPG_ERR_NOT_SUPPORTED));
+#endif
+}
+
+Error Option::resetToActiveValue()
+{
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ if (isNull()) {
+ return Error(make_error(GPG_ERR_INV_ARG));
+ } else {
+ return Error(gpgme_conf_opt_change(opt, 1, 0));
+ }
+#else
+ return Error(make_error(GPG_ERR_NOT_SUPPORTED));
+#endif
+}
+
+Error Option::resetToDefaultValue()
+{
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ if (isNull()) {
+ return Error(make_error(GPG_ERR_INV_ARG));
+ } else {
+ return Error(gpgme_conf_opt_change(opt, 0, 0));
+ }
+#else
+ return Error(make_error(GPG_ERR_NOT_SUPPORTED));
+#endif
+}
+
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+static gpgme_conf_arg_t make_argument(gpgme_conf_type_t type, const void *value)
+{
+ gpgme_conf_arg_t arg = 0;
+#ifdef HAVE_GPGME_CONF_ARG_NEW_WITH_CONST_VALUE
+ if (const gpgme_error_t err = gpgme_conf_arg_new(&arg, type, value)) {
+ return 0;
+ }
+#else
+ if (const gpgme_error_t err = gpgme_conf_arg_new(&arg, type, const_cast<void *>(value))) {
+ return 0;
+ }
+#endif
+ else {
+ return arg;
+ }
+}
+#endif
+
+Argument Option::createNoneArgument(bool set) const
+{
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ if (isNull() || alternateType() != NoType) {
+ return Argument();
+ } else {
+ if (set) {
+ return createNoneListArgument(1);
+ } else {
+#endif
+ return Argument();
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ }
+ }
+#endif
+}
+
+Argument Option::createStringArgument(const char *value) const
+{
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ if (isNull() || alternateType() != StringType) {
+ return Argument();
+ } else {
+ return Argument(comp.lock(), opt, make_argument(GPGME_CONF_STRING, value), true);
+ }
+#else
+ return Argument();
+#endif
+}
+
+Argument Option::createStringArgument(const std::string &value) const
+{
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ if (isNull() || alternateType() != StringType) {
+ return Argument();
+ } else {
+ return Argument(comp.lock(), opt, make_argument(GPGME_CONF_STRING, value.c_str()), true);
+ }
+#else
+ return Argument();
+#endif
+}
+
+Argument Option::createIntArgument(int value) const
+{
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ if (isNull() || alternateType() != IntegerType) {
+ return Argument();
+ } else {
+ return Argument(comp.lock(), opt, make_argument(GPGME_CONF_INT32, &value), true);
+ }
+#else
+ return Argument();
+#endif
+}
+
+Argument Option::createUIntArgument(unsigned int value) const
+{
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ if (isNull() || alternateType() != UnsignedIntegerType) {
+ return Argument();
+ } else {
+ return Argument(comp.lock(), opt, make_argument(GPGME_CONF_UINT32, &value), true);
+ }
+#else
+ return Argument();
+#endif
+}
+
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+namespace
+{
+const void *to_void_star(const char *s)
+{
+ return s;
+}
+const void *to_void_star(const std::string &s)
+{
+ return s.c_str();
+}
+const void *to_void_star(const int &i)
+{
+ return &i; // const-&: sic!
+}
+const void *to_void_star(const unsigned int &i)
+{
+ return &i; // const-&: sic!
+}
+
+template <typename T>
+gpgme_conf_arg_t make_argument(gpgme_conf_type_t type, const std::vector<T> &value)
+{
+ gpgme_conf_arg_t result = 0;
+ gpgme_conf_arg_t last = 0;
+ for (typename std::vector<T>::const_iterator it = value.begin(), end = value.end() ; it != end ; ++it) {
+ if (gpgme_conf_arg_t arg = make_argument(type, to_void_star(*it))) {
+ if (last) {
+ last = last->next = arg;
+ } else {
+ result = last = arg;
+ }
+ }
+ }
+ return result;
+}
+}
+#endif
+
+Argument Option::createNoneListArgument(unsigned int value) const
+{
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ if (value) {
+ return Argument(comp.lock(), opt, make_argument(GPGME_CONF_NONE, &value), true);
+ } else {
+#endif
+ return Argument();
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ }
+#endif
+}
+
+Argument Option::createStringListArgument(const std::vector<const char *> &value) const
+{
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ return Argument(comp.lock(), opt, make_argument(GPGME_CONF_STRING, value), true);
+#else
+ return Argument();
+#endif
+}
+
+Argument Option::createStringListArgument(const std::vector<std::string> &value) const
+{
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ return Argument(comp.lock(), opt, make_argument(GPGME_CONF_STRING, value), true);
+#else
+ return Argument();
+#endif
+}
+
+Argument Option::createIntListArgument(const std::vector<int> &value) const
+{
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ return Argument(comp.lock(), opt, make_argument(GPGME_CONF_INT32, value), true);
+#else
+ return Argument();
+#endif
+}
+
+Argument Option::createUIntListArgument(const std::vector<unsigned int> &value) const
+{
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ return Argument(comp.lock(), opt, make_argument(GPGME_CONF_UINT32, value), true);
+#else
+ return Argument();
+#endif
+}
+
+Argument::Argument(const shared_gpgme_conf_comp_t &comp, gpgme_conf_opt_t opt, gpgme_conf_arg_t arg, bool owns)
+ : comp(comp),
+ opt(opt),
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ arg(owns ? arg : mygpgme_conf_arg_copy(arg, opt ? opt->alt_type : GPGME_CONF_NONE))
+#else
+ arg(0)
+#endif
+{
+
+}
+
+#if 0
+Argument::Argument(const shared_gpgme_conf_comp_t &comp, gpgme_conf_opt_t opt, gpgme_conf_arg_t arg)
+ : comp(comp),
+ opt(opt),
+ arg(mygpgme_conf_arg_copy(arg, opt ? opt->alt_type : GPGME_CONF_NONE))
+{
+
+}
+#endif
+
+Argument::Argument(const Argument &other)
+ : comp(other.comp),
+ opt(other.opt),
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ arg(mygpgme_conf_arg_copy(other.arg, opt ? opt->alt_type : GPGME_CONF_NONE))
+#else
+ arg(0)
+#endif
+{
+
+}
+
+Argument::~Argument()
+{
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ gpgme_conf_arg_release(arg, opt ? opt->alt_type : GPGME_CONF_NONE);
+#endif
+}
+
+Option Argument::parent() const
+{
+ return Option(comp.lock(), opt);
+}
+
+bool Argument::boolValue() const
+{
+ return numberOfTimesSet();
+}
+
+unsigned int Argument::numElements() const
+{
+ if (isNull()) {
+ return 0;
+ }
+ unsigned int result = 0;
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ for (gpgme_conf_arg_t a = arg ; a ; a = a->next) {
+ ++result;
+ }
+#endif
+ return result;
+}
+
+const char *Argument::stringValue(unsigned int idx) const
+{
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ if (isNull() || opt->alt_type != GPGME_CONF_STRING) {
+ return 0;
+ }
+ gpgme_conf_arg_t a = arg;
+ while (a && idx) {
+ a = a->next;
+ --idx;
+ }
+ return a ? a->value.string : 0 ;
+#else
+ return 0;
+#endif
+}
+
+int Argument::intValue(unsigned int idx) const
+{
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ if (isNull() || opt->alt_type != GPGME_CONF_INT32) {
+ return 0;
+ }
+ gpgme_conf_arg_t a = arg;
+ while (a && idx) {
+ a = a->next;
+ --idx;
+ }
+ return a ? a->value.int32 : 0 ;
+#else
+ return 0;
+#endif
+}
+
+unsigned int Argument::uintValue(unsigned int idx) const
+{
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ if (isNull() || opt->alt_type != GPGME_CONF_UINT32) {
+ return 0;
+ }
+ gpgme_conf_arg_t a = arg;
+ while (a && idx) {
+ a = a->next;
+ --idx;
+ }
+ return a ? a->value.uint32 : 0 ;
+#else
+ return 0;
+#endif
+}
+
+unsigned int Argument::numberOfTimesSet() const
+{
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ if (isNull() || opt->alt_type != GPGME_CONF_NONE) {
+ return 0;
+ }
+ return arg->value.count;
+#else
+ return 0;
+#endif
+}
+
+std::vector<const char *> Argument::stringValues() const
+{
+ if (isNull() || opt->alt_type != GPGME_CONF_STRING) {
+ return std::vector<const char *>();
+ }
+ std::vector<const char *> result;
+ for (gpgme_conf_arg_t a = arg ; a ; a = a->next) {
+ result.push_back(a->value.string);
+ }
+ return result;
+}
+
+std::vector<int> Argument::intValues() const
+{
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ if (isNull() || opt->alt_type != GPGME_CONF_INT32) {
+ return std::vector<int>();
+ }
+#endif
+ std::vector<int> result;
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ for (gpgme_conf_arg_t a = arg ; a ; a = a->next) {
+ result.push_back(a->value.int32);
+ }
+#endif
+ return result;
+}
+
+std::vector<unsigned int> Argument::uintValues() const
+{
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ if (isNull() || opt->alt_type != GPGME_CONF_UINT32) {
+ return std::vector<unsigned int>();
+ }
+#endif
+ std::vector<unsigned int> result;
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ for (gpgme_conf_arg_t a = arg ; a ; a = a->next) {
+ result.push_back(a->value.uint32);
+ }
+#endif
+ return result;
+}
+
+std::ostream &Configuration::operator<<(std::ostream &os, Level level)
+{
+ switch (level) {
+ case Basic: return os << "Basic";
+ case Advanced: return os << "Advanced";
+ case Expert: return os << "Expert";
+ case Invisible: return os << "Invisible";
+ case Internal: return os << "Internal";
+ case NumLevels: ;
+ }
+ return os << "<unknown>";
+}
+
+std::ostream &Configuration::operator<<(std::ostream &os, Type type)
+{
+ switch (type) {
+ case NoType: return os << "None";
+ case StringType: return os << "String";
+ case IntegerType: return os << "Integer";
+ case UnsignedIntegerType: return os << "UnsignedInteger";
+ case FilenameType: return os << "Filename";
+ case LdapServerType: return os << "LdapServer";
+ case KeyFingerprintType: return os << "KeyFingerprint";
+ case PublicKeyType: return os << "PublicKey";
+ case SecretKeyType: return os << "SecretKey";
+ case AliasListType: return os << "AliasList";
+ case MaxType: ;
+ }
+ return os << "<unknown>";
+}
+
+std::ostream &Configuration::operator<<(std::ostream &os, Flag f)
+{
+ unsigned int flags = f;
+ std::vector<const char *> s;
+ if (flags & Group) {
+ s.push_back("Group");
+ }
+ if (flags & Optional) {
+ s.push_back("Optional");
+ }
+ if (flags & List) {
+ s.push_back("List");
+ }
+ if (flags & Runtime) {
+ s.push_back("Runtime");
+ }
+ if (flags & Default) {
+ s.push_back("Default");
+ }
+ if (flags & DefaultDescription) {
+ s.push_back("DefaultDescription");
+ }
+ if (flags & NoArgumentDescription) {
+ s.push_back("NoArgumentDescription");
+ }
+ if (flags & NoChange) {
+ s.push_back("NoChange");
+ }
+ flags &= ~(Group | Optional | List | Runtime | Default | DefaultDescription | NoArgumentDescription | NoChange);
+ if (flags) {
+ s.push_back("other flags(");
+ }
+ std::copy(s.begin(), s.end(),
+ std::ostream_iterator<const char *>(os, "|"));
+ if (flags) {
+ os << flags << ')';
+ }
+ return os;
+}
+
+std::ostream &Configuration::operator<<(std::ostream &os, const Component &c)
+{
+ os << "Component["
+ << "\n name : " << protect(c.name())
+ << "\n description: " << protect(c.description())
+ << "\n programName: " << protect(c.programName())
+ << "\n options : \n";
+ const std::vector<Option> options = c.options();
+ std::copy(options.begin(), options.end(),
+ std::ostream_iterator<Option>(os, "\n"));
+ os << "\n]";
+ return os;
+}
+
+std::ostream &Configuration::operator<<(std::ostream &os, const Option &o)
+{
+ return os << "Option["
+ << "\n name: : " << protect(o.name())
+ << "\n description : " << protect(o.description())
+ << "\n argName : " << protect(o.argumentName())
+ << "\n flags : " << static_cast<Flag>(o.flags())
+ << "\n level : " << o.level()
+ << "\n type : " << o.type()
+ << "\n alt_type : " << o.alternateType()
+ << "\n default_val : " << o.defaultValue()
+ << "\n default_desc: " << protect(o.defaultDescription())
+ << "\n no_arg_value: " << o.noArgumentValue()
+ << "\n no_arg_desc : " << protect(o.noArgumentDescription())
+ << "\n active_value: " << o.activeValue()
+ << "\n new_value : " << o.newValue()
+ << "\n --> cur_val : " << o.currentValue()
+ << "\n set : " << o.set()
+ << "\n dirty : " << o.dirty()
+ << "\n]"
+ ;
+}
+
+std::ostream &Configuration::operator<<(std::ostream &os, const Argument &a)
+{
+ const Option o = a.parent();
+ const bool list = o.flags() & List;
+ os << "Argument[";
+ if (a) {
+ switch (o.alternateType()) {
+ case NoType:
+ if (list) {
+ os << a.numberOfTimesSet() << 'x';
+ } else {
+ os << a.boolValue();
+ }
+ break;
+ default:
+ case StringType:
+ if (list) {
+ const std::vector<const char *> v = a.stringValues();
+ os << v.size() << ':';
+ // can't use std::copy + ostream_iterator here, since we need the protect() call
+ bool first = true;
+ BOOST_FOREACH(const char *s, v) {
+ if (first) {
+ first = false;
+ } else {
+ os << ',';
+ }
+ os << protect(s);
+ }
+ } else {
+ os << protect(a.stringValue());
+ }
+ break;
+ case IntegerType:
+ if (list) {
+ const std::vector<int> v = a.intValues();
+ os << v.size() << ':';
+ std::copy(v.begin(), v.end(),
+ std::ostream_iterator<int>(os, ","));
+ } else {
+ os << a.intValue();
+ }
+ break;
+ case UnsignedIntegerType:
+ if (list) {
+ const std::vector<unsigned int> v = a.uintValues();
+ os << v.size() << ':';
+ std::copy(v.begin(), v.end(),
+ std::ostream_iterator<unsigned int>(os, ","));
+ } else {
+ os << a.intValue();
+ }
+ break;
+ }
+ }
+ return os << ']';
+}
diff --git a/lang/cpp/src/configuration.h b/lang/cpp/src/configuration.h
new file mode 100644
index 0000000..e6e13db
--- /dev/null
+++ b/lang/cpp/src/configuration.h
@@ -0,0 +1,297 @@
+/*
+ configuration.h - wraps gpgme configuration components
+ Copyright (C) 2010 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+// -*- c++ -*-
+#ifndef __GPGMEPP_CONFIGURATION_H__
+#define __GPGMEPP_CONFIGURATION_H__
+
+#include "global.h"
+
+#include "gpgmefw.h"
+
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/type_traits/remove_pointer.hpp>
+#if 0
+#include <boost/variant.hpp>
+#include <boost/optional.hpp>
+#endif
+
+#include <iosfwd>
+#include <vector>
+#include <string>
+#include <algorithm>
+
+namespace GpgME
+{
+namespace Configuration
+{
+
+typedef boost::shared_ptr< boost::remove_pointer<gpgme_conf_comp_t>::type > shared_gpgme_conf_comp_t;
+typedef boost::weak_ptr< boost::remove_pointer<gpgme_conf_comp_t>::type > weak_gpgme_conf_comp_t;
+
+class Argument;
+class Option;
+class Component;
+
+enum Level {
+ Basic,
+ Advanced,
+ Expert,
+ Invisible,
+ Internal,
+
+ NumLevels
+};
+
+enum Type {
+ NoType,
+ StringType,
+ IntegerType,
+ UnsignedIntegerType,
+
+ FilenameType = 32,
+ LdapServerType,
+ KeyFingerprintType,
+ PublicKeyType,
+ SecretKeyType,
+ AliasListType,
+
+ MaxType
+};
+
+enum Flag {
+ Group = (1 << 0),
+ Optional = (1 << 1),
+ List = (1 << 2),
+ Runtime = (1 << 3),
+ Default = (1 << 4),
+ DefaultDescription = (1 << 5),
+ NoArgumentDescription = (1 << 6),
+ NoChange = (1 << 7),
+
+ LastFlag = NoChange
+};
+
+//
+// class Component
+//
+
+class GPGMEPP_EXPORT Component
+{
+public:
+ Component() : comp() {}
+ explicit Component(const shared_gpgme_conf_comp_t &comp)
+ : comp(comp) {}
+
+ // copy ctor is ok
+
+ const Component &operator=(const Component &other)
+ {
+ if (this != &other) {
+ Component(other).swap(*this);
+ }
+ return *this;
+ }
+
+ void swap(Component &other)
+ {
+ using std::swap;
+ swap(this->comp, other.comp);
+ }
+
+ bool isNull() const
+ {
+ return !comp;
+ }
+
+ static std::vector<Component> load(Error &err);
+ Error save() const;
+
+ const char *name() const;
+ const char *description() const;
+ const char *programName() const;
+
+ Option option(unsigned int index) const;
+ Option option(const char *name) const;
+
+ unsigned int numOptions() const;
+
+ std::vector<Option> options() const;
+
+ GPGMEPP_MAKE_SAFE_BOOL_OPERATOR(!isNull())
+private:
+ shared_gpgme_conf_comp_t comp;
+};
+
+//
+// class Option
+//
+
+class GPGMEPP_EXPORT Option
+{
+public:
+ Option() : comp(), opt(0) {}
+ Option(const shared_gpgme_conf_comp_t &comp, gpgme_conf_opt_t opt)
+ : comp(comp), opt(opt) {}
+
+ const Option &operator=(const Option &other)
+ {
+ if (this != &other) {
+ Option(other).swap(*this);
+ }
+ return *this;
+ }
+
+ void swap(Option &other)
+ {
+ using std::swap;
+ swap(this->comp, other.comp);
+ swap(this->opt, other.opt);
+ }
+
+ bool isNull() const
+ {
+ return comp.expired() || !opt;
+ }
+
+ Component parent() const;
+
+ unsigned int flags() const;
+
+ Level level() const;
+
+ const char *name() const;
+ const char *description() const;
+ const char *argumentName() const;
+
+ Type type() const;
+ Type alternateType() const;
+
+ Argument defaultValue() const;
+ const char *defaultDescription() const;
+
+ Argument noArgumentValue() const;
+ const char *noArgumentDescription() const;
+
+ /*! The value that is in the config file (or null, if it's not set). */
+ Argument activeValue() const;
+ /*! The value that is in this object, ie. either activeValue(), newValue(), or defaultValue() */
+ Argument currentValue() const;
+
+ Argument newValue() const;
+ bool set() const;
+ bool dirty() const;
+
+ Error setNewValue(const Argument &argument);
+ Error resetToDefaultValue();
+ Error resetToActiveValue();
+
+ Argument createNoneArgument(bool set) const;
+ Argument createStringArgument(const char *value) const;
+ Argument createStringArgument(const std::string &value) const;
+ Argument createIntArgument(int value) const;
+ Argument createUIntArgument(unsigned int value) const;
+
+ Argument createNoneListArgument(unsigned int count) const;
+ Argument createStringListArgument(const std::vector<const char *> &value) const;
+ Argument createStringListArgument(const std::vector<std::string> &value) const;
+ Argument createIntListArgument(const std::vector<int> &values) const;
+ Argument createUIntListArgument(const std::vector<unsigned int> &values) const;
+
+ GPGMEPP_MAKE_SAFE_BOOL_OPERATOR(!isNull())
+private:
+ weak_gpgme_conf_comp_t comp;
+ gpgme_conf_opt_t opt;
+};
+
+//
+// class Argument
+//
+
+class GPGMEPP_EXPORT Argument
+{
+ friend class ::GpgME::Configuration::Option;
+ Argument(const shared_gpgme_conf_comp_t &comp, gpgme_conf_opt_t opt, gpgme_conf_arg_t arg, bool owns);
+public:
+ Argument() : comp(), opt(0), arg(0) {}
+ //Argument( const shared_gpgme_conf_comp_t & comp, gpgme_conf_opt_t opt, gpgme_conf_arg_t arg );
+ Argument(const Argument &other);
+ ~Argument();
+
+ const Argument &operator=(const Argument &other)
+ {
+ if (this != &other) {
+ Argument(other).swap(*this);
+ }
+ return *this;
+ }
+
+ void swap(Argument &other)
+ {
+ using std::swap;
+ swap(this->comp, other.comp);
+ swap(this->opt, other.opt);
+ swap(this->arg, other.arg);
+ }
+
+ bool isNull() const
+ {
+ return comp.expired() || !opt || !arg;
+ }
+
+ Option parent() const;
+
+ unsigned int numElements() const;
+
+ bool boolValue() const;
+ const char *stringValue(unsigned int index = 0) const;
+ int intValue(unsigned int index = 0) const;
+ unsigned int uintValue(unsigned int index = 0) const;
+
+ unsigned int numberOfTimesSet() const;
+ std::vector<const char *> stringValues() const;
+ std::vector<int> intValues() const;
+ std::vector<unsigned int> uintValues() const;
+
+ GPGMEPP_MAKE_SAFE_BOOL_OPERATOR(!isNull())
+private:
+ weak_gpgme_conf_comp_t comp;
+ gpgme_conf_opt_t opt;
+ gpgme_conf_arg_t arg;
+};
+
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, Level level);
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, Type type);
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, Flag flag);
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const Component &component);
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const Option &option);
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const Argument &argument);
+
+} // namespace Configuration
+} // namespace GpgME
+
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(Configuration::Component)
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(Configuration::Option)
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(Configuration::Argument)
+
+#endif // __GPGMEPP_CONFIGURATION_H__
diff --git a/lang/cpp/src/context.cpp b/lang/cpp/src/context.cpp
new file mode 100644
index 0000000..ab633d7
--- /dev/null
+++ b/lang/cpp/src/context.cpp
@@ -0,0 +1,1707 @@
+/*
+ context.cpp - wraps a gpgme key context
+ Copyright (C) 2003, 2007 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "config-gpgme++.h"
+
+#include <context.h>
+#include <eventloopinteractor.h>
+#include <trustitem.h>
+#include <assuanresult.h>
+#include <keylistresult.h>
+#include <keygenerationresult.h>
+#include <importresult.h>
+#include <decryptionresult.h>
+#include <verificationresult.h>
+#include <signingresult.h>
+#include <encryptionresult.h>
+#include <engineinfo.h>
+#include <editinteractor.h>
+#include <vfsmountresult.h>
+
+#include <interfaces/assuantransaction.h>
+#include <defaultassuantransaction.h>
+
+#include "callbacks.h"
+#include "data_p.h"
+#include "context_p.h"
+#include "util.h"
+
+#include <gpgme.h>
+
+#include <boost/scoped_array.hpp>
+
+#include <istream>
+#ifndef NDEBUG
+#include <iostream>
+using std::cerr;
+using std::endl;
+#endif
+
+#include <cassert>
+
+#include <qglobal.h>
+
+namespace GpgME
+{
+
+static inline unsigned int xtoi_1(const char *str)
+{
+ const unsigned int ch = *str;
+ const unsigned int result =
+ ch <= '9' ? ch - '0' :
+ ch <= 'F' ? ch - 'A' + 10 :
+ /* else */ ch - 'a' + 10 ;
+ return result < 16 ? result : 0 ;
+}
+static inline int xtoi_2(const char *str)
+{
+ return xtoi_1(str) * 16U + xtoi_1(str + 1);
+}
+
+#ifdef HAVE_GPGME_ASSUAN_ENGINE
+static void percent_unescape(std::string &s, bool plus2space)
+{
+ std::string::iterator src = s.begin(), dest = s.begin(), end = s.end();
+ while (src != end) {
+ if (*src == '%' && end - src > 2) {
+ *dest++ = xtoi_2(&*++src);
+ src += 2;
+ } else if (*src == '+' && plus2space) {
+ *dest++ = ' ';
+ ++src;
+ } else {
+ *dest++ = *src++;
+ }
+ }
+ s.erase(dest, end);
+}
+#endif
+
+void initializeLibrary()
+{
+ gpgme_check_version(0);
+}
+
+Error initializeLibrary(int)
+{
+ if (gpgme_check_version(GPGME_VERSION)) {
+ return Error();
+ } else {
+ return Error::fromCode(GPG_ERR_USER_1);
+ }
+}
+
+static void format_error(gpgme_error_t err, std::string &str)
+{
+ char buffer[ 1024 ];
+ gpgme_strerror_r(err, buffer, sizeof buffer);
+ buffer[ sizeof buffer - 1 ] = '\0';
+ str = buffer;
+}
+
+const char *Error::source() const
+{
+ return gpgme_strsource((gpgme_error_t)mErr);
+}
+
+const char *Error::asString() const
+{
+ if (mMessage.empty()) {
+ format_error(static_cast<gpgme_error_t>(mErr), mMessage);
+ }
+ return mMessage.c_str();
+}
+
+int Error::code() const
+{
+ return gpgme_err_code(mErr);
+}
+
+int Error::sourceID() const
+{
+ return gpgme_err_source(mErr);
+}
+
+bool Error::isCanceled() const
+{
+ return code() == GPG_ERR_CANCELED;
+}
+
+int Error::toErrno() const
+{
+//#ifdef HAVE_GPGME_GPG_ERROR_WRAPPERS
+ return gpgme_err_code_to_errno(static_cast<gpgme_err_code_t>(code()));
+//#else
+// return gpg_err_code_to_errno( static_cast<gpg_err_code_t>( code() ) );
+//#endif
+}
+
+// static
+bool Error::hasSystemError()
+{
+#ifdef HAVE_GPGME_GPG_ERROR_WRAPPERS
+ return gpgme_err_code_from_syserror() == GPG_ERR_MISSING_ERRNO ;
+#else
+ return gpg_err_code_from_syserror() == GPG_ERR_MISSING_ERRNO ;
+#endif
+}
+
+// static
+void Error::setSystemError(gpg_err_code_t err)
+{
+ setErrno(gpgme_err_code_to_errno(err));
+}
+
+// static
+void Error::setErrno(int err)
+{
+#ifdef HAVE_GPGME_GPG_ERROR_WRAPPERS
+ gpgme_err_set_errno(err);
+#else
+ gpg_err_set_errno(err);
+#endif
+}
+
+// static
+Error Error::fromSystemError(unsigned int src)
+{
+#ifdef HAVE_GPGME_GPG_ERROR_WRAPPERS
+ return Error(gpgme_err_make(static_cast<gpgme_err_source_t>(src), gpgme_err_code_from_syserror()));
+#else
+ return Error(gpg_err_make(static_cast<gpg_err_source_t>(src), gpg_err_code_from_syserror()));
+#endif
+}
+
+// static
+Error Error::fromErrno(int err, unsigned int src)
+{
+//#ifdef HAVE_GPGME_GPG_ERROR_WRAPPERS
+ return Error(gpgme_err_make(static_cast<gpgme_err_source_t>(src), gpgme_err_code_from_errno(err)));
+//#else
+// return Error( gpg_err_make( static_cast<gpg_err_source_t>( src ), gpg_err_from_from_errno( err ) ) );
+//#endif
+}
+
+// static
+Error Error::fromCode(unsigned int err, unsigned int src)
+{
+//#ifdef HAVE_GPGME_GPG_ERROR_WRAPPERS
+ return Error(gpgme_err_make(static_cast<gpgme_err_source_t>(src), static_cast<gpgme_err_code_t>(err)));
+//#else
+// return Error( gpg_err_make( static_cast<gpg_err_source_t>( src ), static_cast<gpgme_err_code_t>( err ) ) );
+//#endif
+}
+
+std::ostream &operator<<(std::ostream &os, const Error &err)
+{
+ return os << "GpgME::Error(" << err.encodedError() << " (" << err.asString() << "))";
+}
+
+Context::Context(gpgme_ctx_t ctx) : d(new Private(ctx))
+{
+}
+
+Context::~Context()
+{
+ delete d;
+}
+
+Context *Context::createForProtocol(Protocol proto)
+{
+ gpgme_ctx_t ctx = 0;
+ if (gpgme_new(&ctx) != 0) {
+ return 0;
+ }
+
+ switch (proto) {
+ case OpenPGP:
+ if (gpgme_set_protocol(ctx, GPGME_PROTOCOL_OpenPGP) != 0) {
+ gpgme_release(ctx);
+ return 0;
+ }
+ break;
+ case CMS:
+ if (gpgme_set_protocol(ctx, GPGME_PROTOCOL_CMS) != 0) {
+ gpgme_release(ctx);
+ return 0;
+ }
+ break;
+ default:
+ return 0;
+ }
+
+ return new Context(ctx);
+}
+
+std::auto_ptr<Context> Context::createForEngine(Engine eng, Error *error)
+{
+ gpgme_ctx_t ctx = 0;
+ if (const gpgme_error_t err = gpgme_new(&ctx)) {
+ if (error) {
+ *error = Error(err);
+ }
+ return std::auto_ptr<Context>();
+ }
+
+ switch (eng) {
+ case AssuanEngine:
+#ifdef HAVE_GPGME_ASSUAN_ENGINE
+ if (const gpgme_error_t err = gpgme_set_protocol(ctx, GPGME_PROTOCOL_ASSUAN)) {
+ gpgme_release(ctx);
+ if (error) {
+ *error = Error(err);
+ }
+ return std::auto_ptr<Context>();
+ }
+ break;
+#else
+ if (error) {
+ *error = Error::fromCode(GPG_ERR_NOT_SUPPORTED);
+ }
+ return std::auto_ptr<Context>();
+#endif
+ case G13Engine:
+#ifdef HAVE_GPGME_G13_VFS
+ if (const gpgme_error_t err = gpgme_set_protocol(ctx, GPGME_PROTOCOL_G13)) {
+ gpgme_release(ctx);
+ if (error) {
+ *error = Error(err);
+ }
+ return std::auto_ptr<Context>();
+ }
+ break;
+#else
+ if (error) {
+ *error = Error::fromCode(GPG_ERR_NOT_SUPPORTED);
+ }
+ return std::auto_ptr<Context>();
+#endif
+ default:
+ if (error) {
+ *error = Error::fromCode(GPG_ERR_INV_ARG);
+ }
+ return std::auto_ptr<Context>();
+ }
+
+ if (error) {
+ *error = Error();
+ }
+
+ return std::auto_ptr<Context>(new Context(ctx));
+}
+
+//
+//
+// Context::Private
+//
+//
+
+Context::Private::Private(gpgme_ctx_t c)
+ : ctx(c),
+ iocbs(0),
+ lastop(None),
+ lasterr(GPG_ERR_NO_ERROR),
+ lastAssuanInquireData(Data::null),
+ lastAssuanTransaction(),
+ lastEditInteractor(),
+ lastCardEditInteractor()
+{
+
+}
+
+Context::Private::~Private()
+{
+ if (ctx) {
+ gpgme_release(ctx);
+ }
+ ctx = 0;
+ delete iocbs;
+}
+
+//
+//
+// Context attributes:
+//
+//
+
+Protocol Context::protocol() const
+{
+ gpgme_protocol_t p = gpgme_get_protocol(d->ctx);
+ switch (p) {
+ case GPGME_PROTOCOL_OpenPGP: return OpenPGP;
+ case GPGME_PROTOCOL_CMS: return CMS;
+ default: return UnknownProtocol;
+ }
+}
+
+void Context::setArmor(bool useArmor)
+{
+ gpgme_set_armor(d->ctx, int(useArmor));
+}
+bool Context::armor() const
+{
+ return gpgme_get_armor(d->ctx);
+}
+
+void Context::setTextMode(bool useTextMode)
+{
+ gpgme_set_textmode(d->ctx, int(useTextMode));
+}
+bool Context::textMode() const
+{
+ return gpgme_get_textmode(d->ctx);
+}
+
+void Context::setOffline(bool useOfflineMode)
+{
+#ifdef HAVE_GPGME_CTX_OFFLINE
+ gpgme_set_offline(d->ctx, int(useOfflineMode));
+#else
+ Q_UNUSED(useOfflineMode);
+#endif
+}
+bool Context::offline() const
+{
+#ifdef HAVE_GPGME_CTX_OFFLINE
+ return gpgme_get_offline(d->ctx);
+#else
+ return false;
+#endif
+}
+
+void Context::setIncludeCertificates(int which)
+{
+ if (which == DefaultCertificates) {
+#ifdef HAVE_GPGME_INCLUDE_CERTS_DEFAULT
+ which = GPGME_INCLUDE_CERTS_DEFAULT;
+#else
+ which = 1;
+#endif
+ }
+ gpgme_set_include_certs(d->ctx, which);
+}
+
+int Context::includeCertificates() const
+{
+ return gpgme_get_include_certs(d->ctx);
+}
+
+void Context::setKeyListMode(unsigned int mode)
+{
+ gpgme_set_keylist_mode(d->ctx, add_to_gpgme_keylist_mode_t(0, mode));
+}
+
+void Context::addKeyListMode(unsigned int mode)
+{
+ const unsigned int cur = gpgme_get_keylist_mode(d->ctx);
+ gpgme_set_keylist_mode(d->ctx, add_to_gpgme_keylist_mode_t(cur, mode));
+}
+
+unsigned int Context::keyListMode() const
+{
+ return convert_from_gpgme_keylist_mode_t(gpgme_get_keylist_mode(d->ctx));
+}
+
+void Context::setProgressProvider(ProgressProvider *provider)
+{
+ gpgme_set_progress_cb(d->ctx, provider ? &progress_callback : 0, provider);
+}
+ProgressProvider *Context::progressProvider() const
+{
+ void *pp = 0;
+ gpgme_progress_cb_t pcb = &progress_callback;
+ gpgme_get_progress_cb(d->ctx, &pcb, &pp);
+ return static_cast<ProgressProvider *>(pp);
+}
+
+void Context::setPassphraseProvider(PassphraseProvider *provider)
+{
+ gpgme_set_passphrase_cb(d->ctx, provider ? &passphrase_callback : 0, provider);
+}
+
+PassphraseProvider *Context::passphraseProvider() const
+{
+ void *pp = 0;
+ gpgme_passphrase_cb_t pcb = &passphrase_callback;
+ gpgme_get_passphrase_cb(d->ctx, &pcb, &pp);
+ return static_cast<PassphraseProvider *>(pp);
+}
+
+void Context::setManagedByEventLoopInteractor(bool manage)
+{
+ if (!EventLoopInteractor::instance()) {
+#ifndef NDEBUG
+ cerr << "Context::setManagedByEventLoopInteractor(): "
+ "You must create an instance of EventLoopInteractor "
+ "before using anything that needs one." << endl;
+#endif
+ return;
+ }
+ if (manage) {
+ EventLoopInteractor::instance()->manage(this);
+ } else {
+ EventLoopInteractor::instance()->unmanage(this);
+ }
+}
+bool Context::managedByEventLoopInteractor() const
+{
+ return d->iocbs != 0;
+}
+
+void Context::installIOCallbacks(gpgme_io_cbs *iocbs)
+{
+ if (!iocbs) {
+ uninstallIOCallbacks();
+ return;
+ }
+ gpgme_set_io_cbs(d->ctx, iocbs);
+ delete d->iocbs; d->iocbs = iocbs;
+}
+
+void Context::uninstallIOCallbacks()
+{
+ static gpgme_io_cbs noiocbs = { 0, 0, 0, 0, 0 };
+ // io.add == 0 means disable io callbacks:
+ gpgme_set_io_cbs(d->ctx, &noiocbs);
+ delete d->iocbs; d->iocbs = 0;
+}
+
+Error Context::setLocale(int cat, const char *val)
+{
+ return Error(d->lasterr = gpgme_set_locale(d->ctx, cat, val));
+}
+
+EngineInfo Context::engineInfo() const
+{
+#ifdef HAVE_GPGME_CTX_GETSET_ENGINE_INFO
+ return EngineInfo(gpgme_ctx_get_engine_info(d->ctx));
+#else
+ return EngineInfo();
+#endif
+}
+
+Error Context::setEngineFileName(const char *filename)
+{
+#ifdef HAVE_GPGME_CTX_GETSET_ENGINE_INFO
+ const char *const home_dir = engineInfo().homeDirectory();
+ return Error(gpgme_ctx_set_engine_info(d->ctx, gpgme_get_protocol(d->ctx), filename, home_dir));
+#else
+ return Error::fromCode(GPG_ERR_NOT_IMPLEMENTED);
+#endif
+}
+
+Error Context::setEngineHomeDirectory(const char *home_dir)
+{
+#ifdef HAVE_GPGME_CTX_GETSET_ENGINE_INFO
+ const char *const filename = engineInfo().fileName();
+ return Error(gpgme_ctx_set_engine_info(d->ctx, gpgme_get_protocol(d->ctx), filename, home_dir));
+#else
+ return Error::fromCode(GPG_ERR_NOT_IMPLEMENTED);
+#endif
+}
+
+//
+//
+// Key Management
+//
+//
+
+Error Context::startKeyListing(const char *pattern, bool secretOnly)
+{
+ d->lastop = Private::KeyList;
+ return Error(d->lasterr = gpgme_op_keylist_start(d->ctx, pattern, int(secretOnly)));
+}
+
+Error Context::startKeyListing(const char *patterns[], bool secretOnly)
+{
+ d->lastop = Private::KeyList;
+#ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN
+ if (!patterns || !patterns[0] || !patterns[1]) {
+ // max. one pattern -> use the non-ext version
+ return startKeyListing(patterns ? patterns[0] : 0, secretOnly);
+ }
+#endif
+ return Error(d->lasterr = gpgme_op_keylist_ext_start(d->ctx, patterns, int(secretOnly), 0));
+}
+
+Key Context::nextKey(GpgME::Error &e)
+{
+ d->lastop = Private::KeyList;
+ gpgme_key_t key;
+ e = Error(d->lasterr = gpgme_op_keylist_next(d->ctx, &key));
+ return Key(key, false);
+}
+
+KeyListResult Context::endKeyListing()
+{
+ d->lasterr = gpgme_op_keylist_end(d->ctx);
+ return keyListResult();
+}
+
+KeyListResult Context::keyListResult() const
+{
+ return KeyListResult(d->ctx, Error(d->lasterr));
+}
+
+Key Context::key(const char *fingerprint, GpgME::Error &e , bool secret /*, bool forceUpdate*/)
+{
+ d->lastop = Private::KeyList;
+ gpgme_key_t key;
+ e = Error(d->lasterr = gpgme_get_key(d->ctx, fingerprint, &key, int(secret)/*, int( forceUpdate )*/));
+ return Key(key, false);
+}
+
+KeyGenerationResult Context::generateKey(const char *parameters, Data &pubKey)
+{
+ d->lastop = Private::KeyGen;
+ Data::Private *const dp = pubKey.impl();
+ d->lasterr = gpgme_op_genkey(d->ctx, parameters, dp ? dp->data : 0, 0);
+ return KeyGenerationResult(d->ctx, Error(d->lasterr));
+}
+
+Error Context::startKeyGeneration(const char *parameters, Data &pubKey)
+{
+ d->lastop = Private::KeyGen;
+ Data::Private *const dp = pubKey.impl();
+ return Error(d->lasterr = gpgme_op_genkey_start(d->ctx, parameters, dp ? dp->data : 0, 0));
+}
+
+KeyGenerationResult Context::keyGenerationResult() const
+{
+ if (d->lastop & Private::KeyGen) {
+ return KeyGenerationResult(d->ctx, Error(d->lasterr));
+ } else {
+ return KeyGenerationResult();
+ }
+}
+
+Error Context::exportPublicKeys(const char *pattern, Data &keyData)
+{
+ d->lastop = Private::Export;
+ Data::Private *const dp = keyData.impl();
+ return Error(d->lasterr = gpgme_op_export(d->ctx, pattern, 0, dp ? dp->data : 0));
+}
+
+Error Context::exportPublicKeys(const char *patterns[], Data &keyData)
+{
+ d->lastop = Private::Export;
+#ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN
+ if (!patterns || !patterns[0] || !patterns[1]) {
+ // max. one pattern -> use the non-ext version
+ return exportPublicKeys(patterns ? patterns[0] : 0, keyData);
+ }
+#endif
+ Data::Private *const dp = keyData.impl();
+ return Error(d->lasterr = gpgme_op_export_ext(d->ctx, patterns, 0, dp ? dp->data : 0));
+}
+
+Error Context::startPublicKeyExport(const char *pattern, Data &keyData)
+{
+ d->lastop = Private::Export;
+ Data::Private *const dp = keyData.impl();
+ return Error(d->lasterr = gpgme_op_export_start(d->ctx, pattern, 0, dp ? dp->data : 0));
+}
+
+Error Context::startPublicKeyExport(const char *patterns[], Data &keyData)
+{
+ d->lastop = Private::Export;
+#ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN
+ if (!patterns || !patterns[0] || !patterns[1]) {
+ // max. one pattern -> use the non-ext version
+ return startPublicKeyExport(patterns ? patterns[0] : 0, keyData);
+ }
+#endif
+ Data::Private *const dp = keyData.impl();
+ return Error(d->lasterr = gpgme_op_export_ext_start(d->ctx, patterns, 0, dp ? dp->data : 0));
+}
+
+ImportResult Context::importKeys(const Data &data)
+{
+ d->lastop = Private::Import;
+ const Data::Private *const dp = data.impl();
+ d->lasterr = gpgme_op_import(d->ctx, dp ? dp->data : 0);
+ return ImportResult(d->ctx, Error(d->lasterr));
+}
+
+ImportResult Context::importKeys(const std::vector<Key> &kk)
+{
+ d->lastop = Private::Import;
+ d->lasterr = make_error(GPG_ERR_NOT_IMPLEMENTED);
+
+ bool shouldHaveResult = false;
+#ifdef HAVE_GPGME_OP_IMPORT_KEYS
+ const boost::scoped_array<gpgme_key_t> keys(new gpgme_key_t[ kk.size() + 1 ]);
+ gpgme_key_t *keys_it = &keys[0];
+ for (std::vector<Key>::const_iterator it = kk.begin(), end = kk.end() ; it != end ; ++it) {
+ if (it->impl()) {
+ *keys_it++ = it->impl();
+ }
+ }
+ *keys_it++ = 0;
+ d->lasterr = gpgme_op_import_keys(d->ctx, keys.get());
+ shouldHaveResult = true;
+#endif
+ if ((gpgme_err_code(d->lasterr) == GPG_ERR_NOT_IMPLEMENTED ||
+ gpgme_err_code(d->lasterr) == GPG_ERR_NOT_SUPPORTED) &&
+ protocol() == CMS) {
+ // ok, try the workaround (export+import):
+ std::vector<const char *> fprs;
+ for (std::vector<Key>::const_iterator it = kk.begin(), end = kk.end() ; it != end ; ++it) {
+ if (const char *fpr = it->primaryFingerprint()) {
+ if (*fpr) {
+ fprs.push_back(fpr);
+ }
+ } else if (const char *keyid = it->keyID()) {
+ if (*keyid) {
+ fprs.push_back(keyid);
+ }
+ }
+ }
+ fprs.push_back(0);
+ Data data;
+ Data::Private *const dp = data.impl();
+ const gpgme_keylist_mode_t oldMode = gpgme_get_keylist_mode(d->ctx);
+ gpgme_set_keylist_mode(d->ctx, GPGME_KEYLIST_MODE_EXTERN);
+ d->lasterr = gpgme_op_export_ext(d->ctx, &fprs[0], 0, dp ? dp->data : 0);
+ gpgme_set_keylist_mode(d->ctx, oldMode);
+ if (!d->lasterr) {
+ data.seek(0, SEEK_SET);
+ d->lasterr = gpgme_op_import(d->ctx, dp ? dp->data : 0);
+ shouldHaveResult = true;
+ }
+ }
+ if (shouldHaveResult) {
+ return ImportResult(d->ctx, Error(d->lasterr));
+ } else {
+ return ImportResult(Error(d->lasterr));
+ }
+}
+
+Error Context::startKeyImport(const Data &data)
+{
+ d->lastop = Private::Import;
+ const Data::Private *const dp = data.impl();
+ return Error(d->lasterr = gpgme_op_import_start(d->ctx, dp ? dp->data : 0));
+}
+
+Error Context::startKeyImport(const std::vector<Key> &kk)
+{
+ d->lastop = Private::Import;
+#ifdef HAVE_GPGME_OP_IMPORT_KEYS
+ const boost::scoped_array<gpgme_key_t> keys(new gpgme_key_t[ kk.size() + 1 ]);
+ gpgme_key_t *keys_it = &keys[0];
+ for (std::vector<Key>::const_iterator it = kk.begin(), end = kk.end() ; it != end ; ++it) {
+ if (it->impl()) {
+ *keys_it++ = it->impl();
+ }
+ }
+ *keys_it++ = 0;
+ return Error(d->lasterr = gpgme_op_import_keys_start(d->ctx, keys.get()));
+#else
+ (void)kk;
+ return Error(d->lasterr = make_error(GPG_ERR_NOT_IMPLEMENTED));
+#endif
+}
+
+ImportResult Context::importResult() const
+{
+ if (d->lastop & Private::Import) {
+ return ImportResult(d->ctx, Error(d->lasterr));
+ } else {
+ return ImportResult();
+ }
+}
+
+Error Context::deleteKey(const Key &key, bool allowSecretKeyDeletion)
+{
+ d->lastop = Private::Delete;
+ return Error(d->lasterr = gpgme_op_delete(d->ctx, key.impl(), int(allowSecretKeyDeletion)));
+}
+
+Error Context::startKeyDeletion(const Key &key, bool allowSecretKeyDeletion)
+{
+ d->lastop = Private::Delete;
+ return Error(d->lasterr = gpgme_op_delete_start(d->ctx, key.impl(), int(allowSecretKeyDeletion)));
+}
+
+Error Context::passwd(const Key &key)
+{
+ d->lastop = Private::Passwd;
+#ifdef HAVE_GPGME_OP_PASSWD
+ return Error(d->lasterr = gpgme_op_passwd(d->ctx, key.impl(), 0U));
+#else
+ (void)key;
+ return Error(d->lasterr = make_error(GPG_ERR_NOT_IMPLEMENTED));
+#endif
+}
+
+Error Context::startPasswd(const Key &key)
+{
+ d->lastop = Private::Passwd;
+#ifdef HAVE_GPGME_OP_PASSWD
+ return Error(d->lasterr = gpgme_op_passwd_start(d->ctx, key.impl(), 0U));
+#else
+ (void)key;
+ return Error(d->lasterr = make_error(GPG_ERR_NOT_IMPLEMENTED));
+#endif
+}
+
+Error Context::edit(const Key &key, std::auto_ptr<EditInteractor> func, Data &data)
+{
+ d->lastop = Private::Edit;
+ d->lastEditInteractor = func;
+ Data::Private *const dp = data.impl();
+ return Error(d->lasterr = gpgme_op_edit(d->ctx, key.impl(),
+ d->lastEditInteractor.get() ? edit_interactor_callback : 0,
+ d->lastEditInteractor.get() ? d->lastEditInteractor->d : 0,
+ dp ? dp->data : 0));
+}
+
+Error Context::startEditing(const Key &key, std::auto_ptr<EditInteractor> func, Data &data)
+{
+ d->lastop = Private::Edit;
+ d->lastEditInteractor = func;
+ Data::Private *const dp = data.impl();
+ return Error(d->lasterr = gpgme_op_edit_start(d->ctx, key.impl(),
+ d->lastEditInteractor.get() ? edit_interactor_callback : 0,
+ d->lastEditInteractor.get() ? d->lastEditInteractor->d : 0,
+ dp ? dp->data : 0));
+}
+
+EditInteractor *Context::lastEditInteractor() const
+{
+ return d->lastEditInteractor.get();
+}
+
+std::auto_ptr<EditInteractor> Context::takeLastEditInteractor()
+{
+ return d->lastEditInteractor;
+}
+
+Error Context::cardEdit(const Key &key, std::auto_ptr<EditInteractor> func, Data &data)
+{
+ d->lastop = Private::CardEdit;
+ d->lastCardEditInteractor = func;
+ Data::Private *const dp = data.impl();
+ return Error(d->lasterr = gpgme_op_card_edit(d->ctx, key.impl(),
+ d->lastCardEditInteractor.get() ? edit_interactor_callback : 0,
+ d->lastCardEditInteractor.get() ? d->lastCardEditInteractor->d : 0,
+ dp ? dp->data : 0));
+}
+
+Error Context::startCardEditing(const Key &key, std::auto_ptr<EditInteractor> func, Data &data)
+{
+ d->lastop = Private::CardEdit;
+ d->lastCardEditInteractor = func;
+ Data::Private *const dp = data.impl();
+ return Error(d->lasterr = gpgme_op_card_edit_start(d->ctx, key.impl(),
+ d->lastCardEditInteractor.get() ? edit_interactor_callback : 0,
+ d->lastCardEditInteractor.get() ? d->lastCardEditInteractor->d : 0,
+ dp ? dp->data : 0));
+}
+
+EditInteractor *Context::lastCardEditInteractor() const
+{
+ return d->lastCardEditInteractor.get();
+}
+
+std::auto_ptr<EditInteractor> Context::takeLastCardEditInteractor()
+{
+ return d->lastCardEditInteractor;
+}
+
+Error Context::startTrustItemListing(const char *pattern, int maxLevel)
+{
+ d->lastop = Private::TrustList;
+ return Error(d->lasterr = gpgme_op_trustlist_start(d->ctx, pattern, maxLevel));
+}
+
+TrustItem Context::nextTrustItem(Error &e)
+{
+ gpgme_trust_item_t ti = 0;
+ e = Error(d->lasterr = gpgme_op_trustlist_next(d->ctx, &ti));
+ return TrustItem(ti);
+}
+
+Error Context::endTrustItemListing()
+{
+ return Error(d->lasterr = gpgme_op_trustlist_end(d->ctx));
+}
+
+#ifdef HAVE_GPGME_ASSUAN_ENGINE
+static gpgme_error_t assuan_transaction_data_callback(void *opaque, const void *data, size_t datalen)
+{
+ assert(opaque);
+ AssuanTransaction *t = static_cast<AssuanTransaction *>(opaque);
+ return t->data(static_cast<const char *>(data), datalen).encodedError();
+}
+
+static gpgme_error_t assuan_transaction_inquire_callback(void *opaque, const char *name, const char *args, gpgme_data_t *r_data)
+{
+ assert(opaque);
+ Context::Private *p = static_cast<Context::Private *>(opaque);
+ AssuanTransaction *t = p->lastAssuanTransaction.get();
+ assert(t);
+ Error err;
+ if (name) {
+ p->lastAssuanInquireData = t->inquire(name, args, err);
+ } else {
+ p->lastAssuanInquireData = Data::null;
+ }
+ if (!p->lastAssuanInquireData.isNull()) {
+ *r_data = p->lastAssuanInquireData.impl()->data;
+ }
+ return err.encodedError();
+}
+
+static gpgme_error_t assuan_transaction_status_callback(void *opaque, const char *status, const char *args)
+{
+ assert(opaque);
+ AssuanTransaction *t = static_cast<AssuanTransaction *>(opaque);
+ std::string a = args;
+ percent_unescape(a, true); // ### why doesn't gpgme do this??
+ return t->status(status, a.c_str()).encodedError();
+}
+#endif
+
+AssuanResult Context::assuanTransact(const char *command)
+{
+ return assuanTransact(command, std::auto_ptr<AssuanTransaction>(new DefaultAssuanTransaction));
+}
+
+AssuanResult Context::assuanTransact(const char *command, std::auto_ptr<AssuanTransaction> transaction)
+{
+ d->lastop = Private::AssuanTransact;
+ d->lastAssuanTransaction = transaction;
+ if (!d->lastAssuanTransaction.get()) {
+ return AssuanResult(Error(d->lasterr = make_error(GPG_ERR_INV_ARG)));
+ }
+#ifdef HAVE_GPGME_ASSUAN_ENGINE
+ d->lasterr = gpgme_op_assuan_transact(d->ctx, command,
+ assuan_transaction_data_callback,
+ d->lastAssuanTransaction.get(),
+ assuan_transaction_inquire_callback,
+ d, // sic!
+ assuan_transaction_status_callback,
+ d->lastAssuanTransaction.get());
+#else
+ (void)command;
+ d->lasterr = make_error(GPG_ERR_NOT_SUPPORTED);
+#endif
+ return AssuanResult(d->ctx, d->lasterr);
+}
+
+Error Context::startAssuanTransaction(const char *command)
+{
+ return startAssuanTransaction(command, std::auto_ptr<AssuanTransaction>(new DefaultAssuanTransaction));
+}
+
+Error Context::startAssuanTransaction(const char *command, std::auto_ptr<AssuanTransaction> transaction)
+{
+ d->lastop = Private::AssuanTransact;
+ d->lastAssuanTransaction = transaction;
+ if (!d->lastAssuanTransaction.get()) {
+ return Error(d->lasterr = make_error(GPG_ERR_INV_ARG));
+ }
+#ifdef HAVE_GPGME_ASSUAN_ENGINE
+ return Error(d->lasterr = gpgme_op_assuan_transact_start(d->ctx, command,
+ assuan_transaction_data_callback,
+ d->lastAssuanTransaction.get(),
+ assuan_transaction_inquire_callback,
+ d, // sic!
+ assuan_transaction_status_callback,
+ d->lastAssuanTransaction.get()));
+#else
+ (void)command;
+ return Error(d->lasterr = make_error(GPG_ERR_NOT_SUPPORTED));
+#endif
+}
+
+AssuanResult Context::assuanResult() const
+{
+ if (d->lastop & Private::AssuanTransact) {
+ return AssuanResult(d->ctx, d->lasterr);
+ } else {
+ return AssuanResult();
+ }
+}
+
+AssuanTransaction *Context::lastAssuanTransaction() const
+{
+ return d->lastAssuanTransaction.get();
+}
+
+std::auto_ptr<AssuanTransaction> Context::takeLastAssuanTransaction()
+{
+ return d->lastAssuanTransaction;
+}
+
+DecryptionResult Context::decrypt(const Data &cipherText, Data &plainText)
+{
+ d->lastop = Private::Decrypt;
+ const Data::Private *const cdp = cipherText.impl();
+ Data::Private *const pdp = plainText.impl();
+ d->lasterr = gpgme_op_decrypt(d->ctx, cdp ? cdp->data : 0, pdp ? pdp->data : 0);
+ return DecryptionResult(d->ctx, Error(d->lasterr));
+}
+
+Error Context::startDecryption(const Data &cipherText, Data &plainText)
+{
+ d->lastop = Private::Decrypt;
+ const Data::Private *const cdp = cipherText.impl();
+ Data::Private *const pdp = plainText.impl();
+ return Error(d->lasterr = gpgme_op_decrypt_start(d->ctx, cdp ? cdp->data : 0, pdp ? pdp->data : 0));
+}
+
+DecryptionResult Context::decryptionResult() const
+{
+ if (d->lastop & Private::Decrypt) {
+ return DecryptionResult(d->ctx, Error(d->lasterr));
+ } else {
+ return DecryptionResult();
+ }
+}
+
+VerificationResult Context::verifyDetachedSignature(const Data &signature, const Data &signedText)
+{
+ d->lastop = Private::Verify;
+ const Data::Private *const sdp = signature.impl();
+ const Data::Private *const tdp = signedText.impl();
+ d->lasterr = gpgme_op_verify(d->ctx, sdp ? sdp->data : 0, tdp ? tdp->data : 0, 0);
+ return VerificationResult(d->ctx, Error(d->lasterr));
+}
+
+VerificationResult Context::verifyOpaqueSignature(const Data &signedData, Data &plainText)
+{
+ d->lastop = Private::Verify;
+ const Data::Private *const sdp = signedData.impl();
+ Data::Private *const pdp = plainText.impl();
+ d->lasterr = gpgme_op_verify(d->ctx, sdp ? sdp->data : 0, 0, pdp ? pdp->data : 0);
+ return VerificationResult(d->ctx, Error(d->lasterr));
+}
+
+Error Context::startDetachedSignatureVerification(const Data &signature, const Data &signedText)
+{
+ d->lastop = Private::Verify;
+ const Data::Private *const sdp = signature.impl();
+ const Data::Private *const tdp = signedText.impl();
+ return Error(d->lasterr = gpgme_op_verify_start(d->ctx, sdp ? sdp->data : 0, tdp ? tdp->data : 0, 0));
+}
+
+Error Context::startOpaqueSignatureVerification(const Data &signedData, Data &plainText)
+{
+ d->lastop = Private::Verify;
+ const Data::Private *const sdp = signedData.impl();
+ Data::Private *const pdp = plainText.impl();
+ return Error(d->lasterr = gpgme_op_verify_start(d->ctx, sdp ? sdp->data : 0, 0, pdp ? pdp->data : 0));
+}
+
+VerificationResult Context::verificationResult() const
+{
+ if (d->lastop & Private::Verify) {
+ return VerificationResult(d->ctx, Error(d->lasterr));
+ } else {
+ return VerificationResult();
+ }
+}
+
+std::pair<DecryptionResult, VerificationResult> Context::decryptAndVerify(const Data &cipherText, Data &plainText)
+{
+ d->lastop = Private::DecryptAndVerify;
+ const Data::Private *const cdp = cipherText.impl();
+ Data::Private *const pdp = plainText.impl();
+ d->lasterr = gpgme_op_decrypt_verify(d->ctx, cdp ? cdp->data : 0, pdp ? pdp->data : 0);
+ return std::make_pair(DecryptionResult(d->ctx, Error(d->lasterr)),
+ VerificationResult(d->ctx, Error(d->lasterr)));
+}
+
+Error Context::startCombinedDecryptionAndVerification(const Data &cipherText, Data &plainText)
+{
+ d->lastop = Private::DecryptAndVerify;
+ const Data::Private *const cdp = cipherText.impl();
+ Data::Private *const pdp = plainText.impl();
+ return Error(d->lasterr = gpgme_op_decrypt_verify_start(d->ctx, cdp ? cdp->data : 0, pdp ? pdp->data : 0));
+}
+
+#ifdef HAVE_GPGME_OP_GETAUDITLOG
+unsigned int to_auditlog_flags(unsigned int flags)
+{
+ unsigned int result = 0;
+ if (flags & Context::HtmlAuditLog) {
+ result |= GPGME_AUDITLOG_HTML;
+ }
+ if (flags & Context::AuditLogWithHelp) {
+ result |= GPGME_AUDITLOG_WITH_HELP;
+ }
+ return result;
+}
+#endif // HAVE_GPGME_OP_GETAUDITLOG
+
+Error Context::startGetAuditLog(Data &output, unsigned int flags)
+{
+ d->lastop = Private::GetAuditLog;
+#ifdef HAVE_GPGME_OP_GETAUDITLOG
+ Data::Private *const odp = output.impl();
+ return Error(d->lasterr = gpgme_op_getauditlog_start(d->ctx, odp ? odp->data : 0, to_auditlog_flags(flags)));
+#else
+ (void)output; (void)flags;
+ return Error(d->lasterr = make_error(GPG_ERR_NOT_IMPLEMENTED));
+#endif
+}
+
+Error Context::getAuditLog(Data &output, unsigned int flags)
+{
+ d->lastop = Private::GetAuditLog;
+#ifdef HAVE_GPGME_OP_GETAUDITLOG
+ Data::Private *const odp = output.impl();
+ return Error(d->lasterr = gpgme_op_getauditlog(d->ctx, odp ? odp->data : 0, to_auditlog_flags(flags)));
+#else
+ (void)output; (void)flags;
+ return Error(d->lasterr = make_error(GPG_ERR_NOT_IMPLEMENTED));
+#endif
+}
+
+void Context::clearSigningKeys()
+{
+ gpgme_signers_clear(d->ctx);
+}
+
+Error Context::addSigningKey(const Key &key)
+{
+ return Error(d->lasterr = gpgme_signers_add(d->ctx, key.impl()));
+}
+
+Key Context::signingKey(unsigned int idx) const
+{
+ gpgme_key_t key = gpgme_signers_enum(d->ctx, idx);
+ return Key(key, false);
+}
+
+std::vector<Key> Context::signingKeys() const
+{
+ std::vector<Key> result;
+ gpgme_key_t key;
+ for (unsigned int i = 0 ; (key = gpgme_signers_enum(d->ctx, i)) ; ++i) {
+ result.push_back(Key(key, false));
+ }
+ return result;
+}
+
+void Context::clearSignatureNotations()
+{
+#ifdef HAVE_GPGME_SIG_NOTATION_CLEARADDGET
+ gpgme_sig_notation_clear(d->ctx);
+#endif
+}
+
+GpgME::Error Context::addSignatureNotation(const char *name, const char *value, unsigned int flags)
+{
+#ifdef HAVE_GPGME_SIG_NOTATION_CLEARADDGET
+ return Error(gpgme_sig_notation_add(d->ctx, name, value, add_to_gpgme_sig_notation_flags_t(0, flags)));
+#else
+ (void)name; (void)value; (void)flags;
+ return Error(make_error(GPG_ERR_NOT_IMPLEMENTED));
+#endif
+}
+
+GpgME::Error Context::addSignaturePolicyURL(const char *url, bool critical)
+{
+#ifdef HAVE_GPGME_SIG_NOTATION_CLEARADDGET
+ return Error(gpgme_sig_notation_add(d->ctx, 0, url, critical ? GPGME_SIG_NOTATION_CRITICAL : 0));
+#else
+ (void)url; (void)critical;
+ return Error(make_error(GPG_ERR_NOT_IMPLEMENTED));
+#endif
+}
+
+const char *Context::signaturePolicyURL() const
+{
+#ifdef HAVE_GPGME_SIG_NOTATION_CLEARADDGET
+ for (gpgme_sig_notation_t n = gpgme_sig_notation_get(d->ctx) ; n ; n = n->next) {
+ if (!n->name) {
+ return n->value;
+ }
+ }
+#endif
+ return 0;
+}
+
+Notation Context::signatureNotation(unsigned int idx) const
+{
+#ifdef HAVE_GPGME_SIG_NOTATION_CLEARADDGET
+ for (gpgme_sig_notation_t n = gpgme_sig_notation_get(d->ctx) ; n ; n = n->next) {
+ if (n->name) {
+ if (idx-- == 0) {
+ return Notation(n);
+ }
+ }
+ }
+#endif
+ return Notation();
+}
+
+std::vector<Notation> Context::signatureNotations() const
+{
+ std::vector<Notation> result;
+#ifdef HAVE_GPGME_SIG_NOTATION_CLEARADDGET
+ for (gpgme_sig_notation_t n = gpgme_sig_notation_get(d->ctx) ; n ; n = n->next) {
+ if (n->name) {
+ result.push_back(Notation(n));
+ }
+ }
+#endif
+ return result;
+}
+
+static gpgme_sig_mode_t sigmode2sigmode(SignatureMode mode)
+{
+ switch (mode) {
+ default:
+ case NormalSignatureMode: return GPGME_SIG_MODE_NORMAL;
+ case Detached: return GPGME_SIG_MODE_DETACH;
+ case Clearsigned: return GPGME_SIG_MODE_CLEAR;
+ }
+}
+
+SigningResult Context::sign(const Data &plainText, Data &signature, SignatureMode mode)
+{
+ d->lastop = Private::Sign;
+ const Data::Private *const pdp = plainText.impl();
+ Data::Private *const sdp = signature.impl();
+ d->lasterr = gpgme_op_sign(d->ctx, pdp ? pdp->data : 0, sdp ? sdp->data : 0, sigmode2sigmode(mode));
+ return SigningResult(d->ctx, Error(d->lasterr));
+}
+
+Error Context::startSigning(const Data &plainText, Data &signature, SignatureMode mode)
+{
+ d->lastop = Private::Sign;
+ const Data::Private *const pdp = plainText.impl();
+ Data::Private *const sdp = signature.impl();
+ return Error(d->lasterr = gpgme_op_sign_start(d->ctx, pdp ? pdp->data : 0, sdp ? sdp->data : 0, sigmode2sigmode(mode)));
+}
+
+SigningResult Context::signingResult() const
+{
+ if (d->lastop & Private::Sign) {
+ return SigningResult(d->ctx, Error(d->lasterr));
+ } else {
+ return SigningResult();
+ }
+}
+
+static gpgme_encrypt_flags_t encryptflags2encryptflags(Context::EncryptionFlags flags)
+{
+ unsigned int result = 0;
+ if (flags & Context::AlwaysTrust) {
+ result |= GPGME_ENCRYPT_ALWAYS_TRUST;
+ }
+#ifdef HAVE_GPGME_ENCRYPT_NO_ENCRYPT_TO
+ if (flags & Context::NoEncryptTo) {
+ result |= GPGME_ENCRYPT_NO_ENCRYPT_TO;
+ }
+#endif
+ return static_cast<gpgme_encrypt_flags_t>(result);
+}
+
+EncryptionResult Context::encrypt(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags)
+{
+ d->lastop = Private::Encrypt;
+#ifndef HAVE_GPGME_ENCRYPT_NO_ENCRYPT_TO
+ if (flags & NoEncryptTo) {
+ return EncryptionResult(Error(d->lasterr = make_error(GPG_ERR_NOT_IMPLEMENTED)));
+ }
+#endif
+ const Data::Private *const pdp = plainText.impl();
+ Data::Private *const cdp = cipherText.impl();
+ gpgme_key_t *const keys = new gpgme_key_t[ recipients.size() + 1 ];
+ gpgme_key_t *keys_it = keys;
+ for (std::vector<Key>::const_iterator it = recipients.begin() ; it != recipients.end() ; ++it) {
+ if (it->impl()) {
+ *keys_it++ = it->impl();
+ }
+ }
+ *keys_it++ = 0;
+ d->lasterr = gpgme_op_encrypt(d->ctx, keys, encryptflags2encryptflags(flags),
+ pdp ? pdp->data : 0, cdp ? cdp->data : 0);
+ delete[] keys;
+ return EncryptionResult(d->ctx, Error(d->lasterr));
+}
+
+Error Context::encryptSymmetrically(const Data &plainText, Data &cipherText)
+{
+ d->lastop = Private::Encrypt;
+ const Data::Private *const pdp = plainText.impl();
+ Data::Private *const cdp = cipherText.impl();
+ return Error(d->lasterr = gpgme_op_encrypt(d->ctx, 0, (gpgme_encrypt_flags_t)0,
+ pdp ? pdp->data : 0, cdp ? cdp->data : 0));
+}
+
+Error Context::startEncryption(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags)
+{
+ d->lastop = Private::Encrypt;
+#ifndef HAVE_GPGME_ENCRYPT_NO_ENCRYPT_TO
+ if (flags & NoEncryptTo) {
+ return Error(d->lasterr = make_error(GPG_ERR_NOT_IMPLEMENTED));
+ }
+#endif
+ const Data::Private *const pdp = plainText.impl();
+ Data::Private *const cdp = cipherText.impl();
+ gpgme_key_t *const keys = new gpgme_key_t[ recipients.size() + 1 ];
+ gpgme_key_t *keys_it = keys;
+ for (std::vector<Key>::const_iterator it = recipients.begin() ; it != recipients.end() ; ++it) {
+ if (it->impl()) {
+ *keys_it++ = it->impl();
+ }
+ }
+ *keys_it++ = 0;
+ d->lasterr = gpgme_op_encrypt_start(d->ctx, keys, encryptflags2encryptflags(flags),
+ pdp ? pdp->data : 0, cdp ? cdp->data : 0);
+ delete[] keys;
+ return Error(d->lasterr);
+}
+
+EncryptionResult Context::encryptionResult() const
+{
+ if (d->lastop & Private::Encrypt) {
+ return EncryptionResult(d->ctx, Error(d->lasterr));
+ } else {
+ return EncryptionResult();
+ }
+}
+
+std::pair<SigningResult, EncryptionResult> Context::signAndEncrypt(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags)
+{
+ d->lastop = Private::SignAndEncrypt;
+ const Data::Private *const pdp = plainText.impl();
+ Data::Private *const cdp = cipherText.impl();
+ gpgme_key_t *const keys = new gpgme_key_t[ recipients.size() + 1 ];
+ gpgme_key_t *keys_it = keys;
+ for (std::vector<Key>::const_iterator it = recipients.begin() ; it != recipients.end() ; ++it) {
+ if (it->impl()) {
+ *keys_it++ = it->impl();
+ }
+ }
+ *keys_it++ = 0;
+ d->lasterr = gpgme_op_encrypt_sign(d->ctx, keys, encryptflags2encryptflags(flags),
+ pdp ? pdp->data : 0, cdp ? cdp->data : 0);
+ delete[] keys;
+ return std::make_pair(SigningResult(d->ctx, Error(d->lasterr)),
+ EncryptionResult(d->ctx, Error(d->lasterr)));
+}
+
+Error Context::startCombinedSigningAndEncryption(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags)
+{
+ d->lastop = Private::SignAndEncrypt;
+ const Data::Private *const pdp = plainText.impl();
+ Data::Private *const cdp = cipherText.impl();
+ gpgme_key_t *const keys = new gpgme_key_t[ recipients.size() + 1 ];
+ gpgme_key_t *keys_it = keys;
+ for (std::vector<Key>::const_iterator it = recipients.begin() ; it != recipients.end() ; ++it) {
+ if (it->impl()) {
+ *keys_it++ = it->impl();
+ }
+ }
+ *keys_it++ = 0;
+ d->lasterr = gpgme_op_encrypt_sign_start(d->ctx, keys, encryptflags2encryptflags(flags),
+ pdp ? pdp->data : 0, cdp ? cdp->data : 0);
+ delete[] keys;
+ return Error(d->lasterr);
+}
+
+Error Context::createVFS(const char *containerFile, const std::vector< Key > &recipients)
+{
+ d->lastop = Private::CreateVFS;
+#ifdef HAVE_GPGME_G13_VFS
+ gpgme_key_t *const keys = new gpgme_key_t[ recipients.size() + 1 ];
+ gpgme_key_t *keys_it = keys;
+ for (std::vector<Key>::const_iterator it = recipients.begin() ; it != recipients.end() ; ++it) {
+ if (it->impl()) {
+ *keys_it++ = it->impl();
+ }
+ }
+ *keys_it++ = 0;
+
+ gpgme_error_t op_err;
+ d->lasterr = gpgme_op_vfs_create(d->ctx, keys, containerFile, 0, &op_err);
+ delete[] keys;
+ Error error(d->lasterr);
+ if (error) {
+ return error;
+ }
+ return Error(d->lasterr = op_err);
+#else
+ Q_UNUSED(containerFile);
+ Q_UNUSED(recipients);
+ return Error(d->lasterr = make_error(GPG_ERR_NOT_SUPPORTED));
+#endif
+}
+
+VfsMountResult Context::mountVFS(const char *containerFile, const char *mountDir)
+{
+ d->lastop = Private::MountVFS;
+#ifdef HAVE_GPGME_G13_VFS
+ gpgme_error_t op_err;
+ d->lasterr = gpgme_op_vfs_mount(d->ctx, containerFile, mountDir, 0, &op_err);
+ return VfsMountResult(d->ctx, Error(d->lasterr), Error(op_err));
+#else
+ Q_UNUSED(containerFile);
+ Q_UNUSED(mountDir);
+ return VfsMountResult(d->ctx, Error(d->lasterr = make_error(GPG_ERR_NOT_SUPPORTED)), Error());
+#endif
+}
+
+Error Context::cancelPendingOperation()
+{
+#ifdef HAVE_GPGME_CANCEL_ASYNC
+ return Error(gpgme_cancel_async(d->ctx));
+#else
+ return Error(gpgme_cancel(d->ctx));
+#endif
+}
+
+bool Context::poll()
+{
+ gpgme_error_t e = GPG_ERR_NO_ERROR;
+ const bool finished = gpgme_wait(d->ctx, &e, 0);
+ if (finished) {
+ d->lasterr = e;
+ }
+ return finished;
+}
+
+Error Context::wait()
+{
+ gpgme_error_t e = GPG_ERR_NO_ERROR;
+ gpgme_wait(d->ctx, &e, 1);
+ return Error(d->lasterr = e);
+}
+
+Error Context::lastError() const
+{
+ return Error(d->lasterr);
+}
+
+std::ostream &operator<<(std::ostream &os, Protocol proto)
+{
+ os << "GpgME::Protocol(";
+ switch (proto) {
+ case OpenPGP:
+ os << "OpenPGP";
+ break;
+ case CMS:
+ os << "CMS";
+ break;
+ default:
+ case UnknownProtocol:
+ os << "UnknownProtocol";
+ break;
+ }
+ return os << ')';
+}
+
+std::ostream &operator<<(std::ostream &os, Engine eng)
+{
+ os << "GpgME::Engine(";
+ switch (eng) {
+ case GpgEngine:
+ os << "GpgEngine";
+ break;
+ case GpgSMEngine:
+ os << "GpgSMEngine";
+ break;
+ case GpgConfEngine:
+ os << "GpgConfEngine";
+ break;
+ case AssuanEngine:
+ os << "AssuanEngine";
+ break;
+ default:
+ case UnknownEngine:
+ os << "UnknownEngine";
+ break;
+ }
+ return os << ')';
+}
+
+std::ostream &operator<<(std::ostream &os, Context::CertificateInclusion incl)
+{
+ os << "GpgME::Context::CertificateInclusion(" << static_cast<int>(incl);
+ switch (incl) {
+ case Context::DefaultCertificates:
+ os << "(DefaultCertificates)";
+ break;
+ case Context::AllCertificatesExceptRoot:
+ os << "(AllCertificatesExceptRoot)";
+ break;
+ case Context::AllCertificates:
+ os << "(AllCertificates)";
+ break;
+ case Context::NoCertificates:
+ os << "(NoCertificates)";
+ break;
+ case Context::OnlySenderCertificate:
+ os << "(OnlySenderCertificate)";
+ break;
+ }
+ return os << ')';
+}
+
+std::ostream &operator<<(std::ostream &os, KeyListMode mode)
+{
+ os << "GpgME::KeyListMode(";
+#define CHECK( x ) if ( !(mode & (x)) ) {} else do { os << #x " "; } while (0)
+ CHECK(Local);
+ CHECK(Extern);
+ CHECK(Signatures);
+ CHECK(Validate);
+ CHECK(Ephemeral);
+#undef CHECK
+ return os << ')';
+}
+
+std::ostream &operator<<(std::ostream &os, SignatureMode mode)
+{
+ os << "GpgME::SignatureMode(";
+ switch (mode) {
+#define CHECK( x ) case x: os << #x; break
+ CHECK(NormalSignatureMode);
+ CHECK(Detached);
+ CHECK(Clearsigned);
+#undef CHECK
+ default:
+ os << "???" "(" << static_cast<int>(mode) << ')';
+ break;
+ }
+ return os << ')';
+}
+
+std::ostream &operator<<(std::ostream &os, Context::EncryptionFlags flags)
+{
+ os << "GpgME::Context::EncryptionFlags(";
+#define CHECK( x ) if ( !(flags & (Context::x)) ) {} else do { os << #x " "; } while (0)
+ CHECK(AlwaysTrust);
+#undef CHECK
+ return os << ')';
+}
+
+std::ostream &operator<<(std::ostream &os, Context::AuditLogFlags flags)
+{
+ os << "GpgME::Context::AuditLogFlags(";
+#define CHECK( x ) if ( !(flags & (Context::x)) ) {} else do { os << #x " "; } while (0)
+ CHECK(HtmlAuditLog);
+ CHECK(AuditLogWithHelp);
+#undef CHECK
+ return os << ')';
+}
+
+} // namespace GpgME
+
+GpgME::Error GpgME::setDefaultLocale(int cat, const char *val)
+{
+ return Error(gpgme_set_locale(0, cat, val));
+}
+
+GpgME::EngineInfo GpgME::engineInfo(GpgME::Protocol proto)
+{
+ gpgme_engine_info_t ei = 0;
+ if (gpgme_get_engine_info(&ei)) {
+ return EngineInfo();
+ }
+
+ const gpgme_protocol_t p = proto == CMS ? GPGME_PROTOCOL_CMS : GPGME_PROTOCOL_OpenPGP ;
+
+ for (gpgme_engine_info_t i = ei ; i ; i = i->next) {
+ if (i->protocol == p) {
+ return EngineInfo(i);
+ }
+ }
+
+ return EngineInfo();
+}
+
+GpgME::Error GpgME::checkEngine(GpgME::Protocol proto)
+{
+ const gpgme_protocol_t p = proto == CMS ? GPGME_PROTOCOL_CMS : GPGME_PROTOCOL_OpenPGP ;
+
+ return Error(gpgme_engine_check_version(p));
+}
+
+static const gpgme_protocol_t UNKNOWN_PROTOCOL = static_cast<gpgme_protocol_t>(255);
+
+static gpgme_protocol_t engine2protocol(const GpgME::Engine engine)
+{
+ switch (engine) {
+ case GpgME::GpgEngine: return GPGME_PROTOCOL_OpenPGP;
+ case GpgME::GpgSMEngine: return GPGME_PROTOCOL_CMS;
+ case GpgME::GpgConfEngine:
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ return GPGME_PROTOCOL_GPGCONF;
+#else
+ break;
+#endif
+ case GpgME::AssuanEngine:
+#ifdef HAVE_GPGME_ASSUAN_ENGINE
+ return GPGME_PROTOCOL_ASSUAN;
+#else
+ break;
+#endif
+ case GpgME::G13Engine:
+#ifdef HAVE_GPGME_G13_VFS
+ return GPGME_PROTOCOL_G13;
+#else
+ break;
+#endif
+ case GpgME::UnknownEngine:
+ ;
+ }
+ return UNKNOWN_PROTOCOL;
+}
+
+GpgME::EngineInfo GpgME::engineInfo(GpgME::Engine engine)
+{
+ gpgme_engine_info_t ei = 0;
+ if (gpgme_get_engine_info(&ei)) {
+ return EngineInfo();
+ }
+
+ const gpgme_protocol_t p = engine2protocol(engine);
+
+ for (gpgme_engine_info_t i = ei ; i ; i = i->next) {
+ if (i->protocol == p) {
+ return EngineInfo(i);
+ }
+ }
+
+ return EngineInfo();
+}
+
+GpgME::Error GpgME::checkEngine(GpgME::Engine engine)
+{
+ const gpgme_protocol_t p = engine2protocol(engine);
+
+ return Error(gpgme_engine_check_version(p));
+}
+
+static const unsigned long supported_features = 0
+ | GpgME::ValidatingKeylistModeFeature
+ | GpgME::CancelOperationFeature
+ | GpgME::WrongKeyUsageFeature
+#ifdef HAVE_GPGME_INCLUDE_CERTS_DEFAULT
+ | GpgME::DefaultCertificateInclusionFeature
+#endif
+#ifdef HAVE_GPGME_CTX_GETSET_ENGINE_INFO
+ | GpgME::GetSetEngineInfoFeature
+#endif
+#ifdef HAVE_GPGME_SIG_NOTATION_CLEARADDGET
+ | GpgME::ClearAddGetSignatureNotationsFeature
+#endif
+#ifdef HAVE_GPGME_DATA_SET_FILE_NAME
+ | GpgME::SetDataFileNameFeeature
+#endif
+#ifdef HAVE_GPGME_KEYLIST_MODE_SIG_NOTATIONS
+ | GpgME::SignatureNotationsKeylistModeFeature
+#endif
+#ifdef HAVE_GPGME_KEY_SIG_NOTATIONS
+ | GpgME::KeySignatureNotationsFeature
+#endif
+#ifdef HAVE_GPGME_KEY_T_IS_QUALIFIED
+ | GpgME::KeyIsQualifiedFeature
+#endif
+#ifdef HAVE_GPGME_SIG_NOTATION_CRITICAL
+ | GpgME::SignatureNotationsCriticalFlagFeature
+#endif
+#ifdef HAVE_GPGME_SIG_NOTATION_FLAGS_T
+ | GpgME::SignatureNotationsFlagsFeature
+#endif
+#ifdef HAVE_GPGME_SIG_NOTATION_HUMAN_READABLE
+ | GpgME::SignatureNotationsHumanReadableFlagFeature
+#endif
+#ifdef HAVE_GPGME_SUBKEY_T_IS_QUALIFIED
+ | GpgME::SubkeyIsQualifiedFeature
+#endif
+#ifdef HAVE_GPGME_ENGINE_INFO_T_HOME_DIR
+ | GpgME::EngineInfoHomeDirFeature
+#endif
+#ifdef HAVE_GPGME_DECRYPT_RESULT_T_FILE_NAME
+ | GpgME::DecryptionResultFileNameFeature
+#endif
+#ifdef HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS
+ | GpgME::DecryptionResultRecipientsFeature
+#endif
+#ifdef HAVE_GPGME_VERIFY_RESULT_T_FILE_NAME
+ | GpgME::VerificationResultFileNameFeature
+#endif
+#ifdef HAVE_GPGME_SIGNATURE_T_PKA_FIELDS
+ | GpgME::SignaturePkaFieldsFeature
+#endif
+#ifdef HAVE_GPGME_SIGNATURE_T_ALGORITHM_FIELDS
+ | GpgME::SignatureAlgorithmFieldsFeature
+#endif
+#ifdef HAVE_GPGME_GET_FDPTR
+ | GpgME::FdPointerFeature
+#endif
+#ifdef HAVE_GPGME_OP_GETAUDITLOG
+ | GpgME::AuditLogFeature
+#endif
+#ifdef HAVE_GPGME_PROTOCOL_GPGCONF
+ | GpgME::GpgConfEngineFeature
+#endif
+#ifdef HAVE_GPGME_CANCEL_ASYNC
+ | GpgME::CancelOperationAsyncFeature
+#endif
+#ifdef HAVE_GPGME_ENCRYPT_NO_ENCRYPT_TO
+ | GpgME::NoEncryptToEncryptionFlagFeature
+#endif
+#ifdef HAVE_GPGME_SUBKEY_T_IS_CARDKEY
+ | GpgME::CardKeyFeature
+#endif
+#ifdef HAVE_GPGME_ASSUAN_ENGINE
+ | GpgME::AssuanEngineFeature
+#endif
+#ifdef HAVE_GPGME_KEYLIST_MODE_EPHEMERAL
+ | GpgME::EphemeralKeylistModeFeature
+#endif
+#ifdef HAVE_GPGME_OP_IMPORT_KEYS
+ | GpgME::ImportFromKeyserverFeature
+#endif
+#ifdef HAVE_GPGME_G13_VFS
+ | GpgME::G13VFSFeature
+#endif
+#ifdef HAVE_GPGME_OP_PASSWD
+ | GpgME::PasswdFeature
+#endif
+ ;
+
+static const unsigned long supported_features2 = 0
+ ;
+
+bool GpgME::hasFeature(unsigned long features)
+{
+ return features == (features & supported_features);
+}
+
+bool GpgME::hasFeature(unsigned long features, unsigned long features2)
+{
+ return features == (features & supported_features)
+ && features2 == (features2 & supported_features2)
+ ;
+}
diff --git a/lang/cpp/src/context.h b/lang/cpp/src/context.h
new file mode 100644
index 0000000..ee4f847
--- /dev/null
+++ b/lang/cpp/src/context.h
@@ -0,0 +1,353 @@
+/*
+ context.h - wraps a gpgme key context
+ Copyright (C) 2003, 2007 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+// -*- c++ -*-
+#ifndef __GPGMEPP_CONTEXT_H__
+#define __GPGMEPP_CONTEXT_H__
+
+#include "global.h"
+
+#include "error.h"
+#include "verificationresult.h" // for Signature::Notation
+
+#include <memory>
+#include <vector>
+#include <utility>
+#include <iosfwd>
+
+namespace GpgME
+{
+
+class Key;
+class Data;
+class TrustItem;
+class ProgressProvider;
+class PassphraseProvider;
+class EventLoopInteractor;
+class EditInteractor;
+class AssuanTransaction;
+
+class AssuanResult;
+class KeyListResult;
+class KeyGenerationResult;
+class ImportResult;
+class DecryptionResult;
+class VerificationResult;
+class SigningResult;
+class EncryptionResult;
+class VfsMountResult;
+
+class EngineInfo;
+
+class GPGMEPP_EXPORT Context
+{
+ explicit Context(gpgme_ctx_t);
+public:
+ //using GpgME::Protocol;
+
+ //
+ // Creation and destruction:
+ //
+
+ static Context *createForProtocol(Protocol proto);
+ static std::auto_ptr<Context> createForEngine(Engine engine, Error *err = 0);
+ virtual ~Context();
+
+ //
+ // Context Attributes
+ //
+
+ Protocol protocol() const;
+
+ void setArmor(bool useArmor);
+ bool armor() const;
+
+ void setTextMode(bool useTextMode);
+ bool textMode() const;
+
+ void setOffline(bool useOfflineMode);
+ bool offline() const;
+
+ enum CertificateInclusion {
+ DefaultCertificates = -256,
+ AllCertificatesExceptRoot = -2,
+ AllCertificates = -1,
+ NoCertificates = 0,
+ OnlySenderCertificate = 1
+ };
+ void setIncludeCertificates(int which);
+ int includeCertificates() const;
+
+ //using GpgME::KeyListMode;
+ void setKeyListMode(unsigned int keyListMode);
+ void addKeyListMode(unsigned int keyListMode);
+ unsigned int keyListMode() const;
+
+ void setPassphraseProvider(PassphraseProvider *provider);
+ PassphraseProvider *passphraseProvider() const;
+
+ void setProgressProvider(ProgressProvider *provider);
+ ProgressProvider *progressProvider() const;
+
+ void setManagedByEventLoopInteractor(bool managed);
+ bool managedByEventLoopInteractor() const;
+
+ GpgME::Error setLocale(int category, const char *value);
+
+ EngineInfo engineInfo() const;
+ GpgME::Error setEngineFileName(const char *filename);
+ GpgME::Error setEngineHomeDirectory(const char *filename);
+
+private:
+ friend class ::GpgME::EventLoopInteractor;
+ void installIOCallbacks(gpgme_io_cbs *iocbs);
+ void uninstallIOCallbacks();
+
+public:
+ //
+ //
+ // Key Management
+ //
+ //
+
+ //
+ // Key Listing
+ //
+
+ GpgME::Error startKeyListing(const char *pattern = 0, bool secretOnly = false);
+ GpgME::Error startKeyListing(const char *patterns[], bool secretOnly = false);
+
+ Key nextKey(GpgME::Error &e);
+
+ KeyListResult endKeyListing();
+ KeyListResult keyListResult() const;
+
+ Key key(const char *fingerprint, GpgME::Error &e, bool secret = false);
+
+ //
+ // Key Generation
+ //
+
+ KeyGenerationResult generateKey(const char *parameters, Data &pubKey);
+ GpgME::Error startKeyGeneration(const char *parameters, Data &pubkey);
+ KeyGenerationResult keyGenerationResult() const;
+
+ //
+ // Key Export
+ //
+
+ GpgME::Error exportPublicKeys(const char *pattern, Data &keyData);
+ GpgME::Error exportPublicKeys(const char *pattern[], Data &keyData);
+ GpgME::Error startPublicKeyExport(const char *pattern, Data &keyData);
+ GpgME::Error startPublicKeyExport(const char *pattern[], Data &keyData);
+
+ //
+ // Key Import
+ //
+
+ ImportResult importKeys(const Data &data);
+ ImportResult importKeys(const std::vector<Key> &keys);
+ GpgME::Error startKeyImport(const Data &data);
+ GpgME::Error startKeyImport(const std::vector<Key> &keys);
+ ImportResult importResult() const;
+
+ //
+ // Key Deletion
+ //
+
+ GpgME::Error deleteKey(const Key &key, bool allowSecretKeyDeletion = false);
+ GpgME::Error startKeyDeletion(const Key &key, bool allowSecretKeyDeletion = false);
+
+ //
+ // Passphrase changing
+ //
+
+ GpgME::Error passwd(const Key &key);
+ GpgME::Error startPasswd(const Key &key);
+
+ //
+ // Key Editing
+ //
+
+ GpgME::Error edit(const Key &key, std::auto_ptr<EditInteractor> function, Data &out);
+ GpgME::Error startEditing(const Key &key, std::auto_ptr<EditInteractor> function, Data &out);
+
+ EditInteractor *lastEditInteractor() const;
+ std::auto_ptr<EditInteractor> takeLastEditInteractor();
+
+ //
+ // SmartCard Editing
+ //
+
+ GpgME::Error cardEdit(const Key &key, std::auto_ptr<EditInteractor> function, Data &out);
+ GpgME::Error startCardEditing(const Key &key, std::auto_ptr<EditInteractor> function, Data &out);
+
+ EditInteractor *lastCardEditInteractor() const;
+ std::auto_ptr<EditInteractor> takeLastCardEditInteractor();
+
+ //
+ // Trust Item Management
+ //
+
+ GpgME::Error startTrustItemListing(const char *pattern, int maxLevel);
+ TrustItem nextTrustItem(GpgME::Error &e);
+ GpgME::Error endTrustItemListing();
+
+ //
+ // Assuan Transactions
+ //
+
+ AssuanResult assuanTransact(const char *command, std::auto_ptr<AssuanTransaction> transaction);
+ AssuanResult assuanTransact(const char *command);
+ GpgME::Error startAssuanTransaction(const char *command, std::auto_ptr<AssuanTransaction> transaction);
+ GpgME::Error startAssuanTransaction(const char *command);
+ AssuanResult assuanResult() const;
+
+ AssuanTransaction *lastAssuanTransaction() const;
+ std::auto_ptr<AssuanTransaction> takeLastAssuanTransaction();
+
+ //
+ //
+ // Crypto Operations
+ //
+ //
+
+ //
+ // Decryption
+ //
+
+ DecryptionResult decrypt(const Data &cipherText, Data &plainText);
+ GpgME::Error startDecryption(const Data &cipherText, Data &plainText);
+ DecryptionResult decryptionResult() const;
+
+ //
+ // Signature Verification
+ //
+
+ VerificationResult verifyDetachedSignature(const Data &signature, const Data &signedText);
+ VerificationResult verifyOpaqueSignature(const Data &signedData, Data &plainText);
+ GpgME::Error startDetachedSignatureVerification(const Data &signature, const Data &signedText);
+ GpgME::Error startOpaqueSignatureVerification(const Data &signedData, Data &plainText);
+ VerificationResult verificationResult() const;
+
+ //
+ // Combined Decryption and Signature Verification
+ //
+
+ std::pair<DecryptionResult, VerificationResult> decryptAndVerify(const Data &cipherText, Data &plainText);
+ GpgME::Error startCombinedDecryptionAndVerification(const Data &cipherText, Data &plainText);
+ // use verificationResult() and decryptionResult() to retrieve the result objects...
+
+ //
+ // Signing
+ //
+
+ void clearSigningKeys();
+ GpgME::Error addSigningKey(const Key &signer);
+ Key signingKey(unsigned int index) const;
+ std::vector<Key> signingKeys() const;
+
+ void clearSignatureNotations();
+ GpgME::Error addSignatureNotation(const char *name, const char *value, unsigned int flags = 0);
+ GpgME::Error addSignaturePolicyURL(const char *url, bool critical = false);
+ const char *signaturePolicyURL() const;
+ Notation signatureNotation(unsigned int index) const;
+ std::vector<Notation> signatureNotations() const;
+
+ //using GpgME::SignatureMode;
+ SigningResult sign(const Data &plainText, Data &signature, SignatureMode mode);
+ GpgME::Error startSigning(const Data &plainText, Data &signature, SignatureMode mode);
+ SigningResult signingResult() const;
+
+ //
+ // Encryption
+ //
+
+ enum EncryptionFlags { None = 0, AlwaysTrust = 1, NoEncryptTo = 2 };
+ EncryptionResult encrypt(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags);
+ GpgME::Error encryptSymmetrically(const Data &plainText, Data &cipherText);
+ GpgME::Error startEncryption(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags);
+ EncryptionResult encryptionResult() const;
+
+ //
+ // Combined Signing and Encryption
+ //
+
+ std::pair<SigningResult, EncryptionResult> signAndEncrypt(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags);
+ GpgME::Error startCombinedSigningAndEncryption(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags);
+ // use encryptionResult() and signingResult() to retrieve the result objects...
+
+ //
+ //
+ // Audit Log
+ //
+ //
+ enum AuditLogFlags {
+ HtmlAuditLog = 1,
+ AuditLogWithHelp = 128
+ };
+ GpgME::Error startGetAuditLog(Data &output, unsigned int flags = 0);
+ GpgME::Error getAuditLog(Data &output, unsigned int flags = 0);
+
+ //
+ //
+ // G13 crypto container operations
+ //
+ //
+ GpgME::Error createVFS(const char *containerFile, const std::vector<Key> &recipients);
+ VfsMountResult mountVFS(const char *containerFile, const char *mountDir);
+
+ //
+ //
+ // Run Control
+ //
+ //
+
+ bool poll();
+ GpgME::Error wait();
+ GpgME::Error lastError() const;
+ GpgME::Error cancelPendingOperation();
+
+ class Private;
+ const Private *impl() const
+ {
+ return d;
+ }
+ Private *impl()
+ {
+ return d;
+ }
+private:
+ Private *const d;
+
+private: // disable...
+ Context(const Context &);
+ const Context &operator=(const Context &);
+};
+
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, Context::CertificateInclusion incl);
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, Context::EncryptionFlags flags);
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, Context::AuditLogFlags flags);
+
+} // namespace GpgME
+
+#endif // __GPGMEPP_CONTEXT_H__
diff --git a/lang/cpp/src/context_glib.cpp b/lang/cpp/src/context_glib.cpp
new file mode 100644
index 0000000..383b8eb
--- /dev/null
+++ b/lang/cpp/src/context_glib.cpp
@@ -0,0 +1,44 @@
+/*
+ context_glib.cpp - wraps a gpgme key context, gpgme-glib-specific functions
+ Copyright (C) 2007 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <config-gpgme++.h>
+
+#include <global.h>
+
+#ifdef HAVE_GPGME_GET_FDPTR
+extern "C" GIOChannel *gpgme_get_fdptr(int);
+#endif
+
+GIOChannel *GpgME::getGIOChannel(int fd)
+{
+#ifdef HAVE_GPGME_GET_FDPTR
+ return gpgme_get_fdptr(fd);
+#else
+ (void)fd;
+ return 0;
+#endif
+}
+
+QIODevice *GpgME::getQIODevice(int fd)
+{
+ return 0;
+}
diff --git a/lang/cpp/src/context_p.h b/lang/cpp/src/context_p.h
new file mode 100644
index 0000000..2991123
--- /dev/null
+++ b/lang/cpp/src/context_p.h
@@ -0,0 +1,84 @@
+/*
+ context_p.h - wraps a gpgme context (private part)
+ Copyright (C) 2003, 2007 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+// -*- c++ -*-
+#ifndef __GPGMEPP_CONTEXT_P_H__
+#define __GPGMEPP_CONTEXT_P_H__
+
+#include <context.h>
+#include <data.h>
+
+#include <gpgme.h>
+
+namespace GpgME
+{
+
+class Context::Private
+{
+public:
+ enum Operation {
+ None = 0,
+
+ Encrypt = 0x001,
+ Decrypt = 0x002,
+ Sign = 0x004,
+ Verify = 0x008,
+ DecryptAndVerify = Decrypt | Verify,
+ SignAndEncrypt = Sign | Encrypt,
+
+ Import = 0x010,
+ Export = 0x020, // no gpgme_export_result_t, but nevertheless...
+ Delete = 0x040, // no gpgme_delete_result_t, but nevertheless...
+
+ KeyGen = 0x080,
+ KeyList = 0x100,
+ TrustList = 0x200, // no gpgme_trustlist_result_t, but nevertheless...
+
+ Edit = 0x400, // no gpgme_edit_result_t, but nevertheless...
+ CardEdit = 0x800, // no gpgme_card_edit_result_t, but nevertheless...
+
+ GetAuditLog = 0x1000, // no gpgme_getauditlog_result_t, but nevertheless...
+
+ AssuanTransact = 0x2000,
+ Passwd = 0x4000, // no gpgme_passwd_result_t, but nevertheless...
+
+ CreateVFS = 0x4000,
+ MountVFS = 0x8000,
+
+ EndMarker
+ };
+
+ Private(gpgme_ctx_t c = 0);
+ ~Private();
+
+ gpgme_ctx_t ctx;
+ gpgme_io_cbs *iocbs;
+ Operation lastop;
+ gpgme_error_t lasterr;
+ Data lastAssuanInquireData;
+ std::auto_ptr<AssuanTransaction> lastAssuanTransaction;
+ std::auto_ptr<EditInteractor> lastEditInteractor, lastCardEditInteractor;
+};
+
+} // namespace GpgME
+
+#endif // __GPGMEPP_CONTEXT_P_H__
diff --git a/lang/cpp/src/context_qt.cpp b/lang/cpp/src/context_qt.cpp
new file mode 100644
index 0000000..e6d44fa
--- /dev/null
+++ b/lang/cpp/src/context_qt.cpp
@@ -0,0 +1,44 @@
+/*
+ context_qt.cpp - wraps a gpgme key context, gpgme-qt-specific functions
+ Copyright (C) 2007 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <config-gpgme++.h>
+
+#include <global.h>
+
+#ifdef HAVE_GPGME_GET_FDPTR
+extern "C" QIODevice *gpgme_get_fdptr(int);
+#endif
+
+GIOChannel *GpgME::getGIOChannel(int)
+{
+ return 0;
+}
+
+QIODevice *GpgME::getQIODevice(int fd)
+{
+#ifdef HAVE_GPGME_GET_FDPTR
+ return gpgme_get_fdptr(fd);
+#else
+ (void)fd;
+ return 0;
+#endif
+}
diff --git a/lang/cpp/src/context_vanilla.cpp b/lang/cpp/src/context_vanilla.cpp
new file mode 100644
index 0000000..30b18b4
--- /dev/null
+++ b/lang/cpp/src/context_vanilla.cpp
@@ -0,0 +1,35 @@
+/*
+ context_vanilla.cpp - wraps a gpgme key context, gpgme (vanilla)-specific functions
+ Copyright (C) 2007 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <config-gpgme++.h>
+
+#include <global.h>
+
+GIOChannel *GpgME::getGIOChannel(int)
+{
+ return 0;
+}
+
+QIODevice *GpgME::getQIODevice(int)
+{
+ return 0;
+}
diff --git a/lang/cpp/src/data.cpp b/lang/cpp/src/data.cpp
new file mode 100644
index 0000000..6b29aaf
--- /dev/null
+++ b/lang/cpp/src/data.cpp
@@ -0,0 +1,199 @@
+/*
+ data.cpp - wraps a gpgme data object
+ Copyright (C) 2003 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <config-gpgme++.h>
+
+#include "data_p.h"
+#include <error.h>
+#include <interfaces/dataprovider.h>
+
+#include <gpgme.h>
+
+#ifndef NDEBUG
+#include <iostream>
+#endif
+
+GpgME::Data::Private::~Private()
+{
+ if (data) {
+ gpgme_data_release(data);
+ }
+}
+
+const GpgME::Data::Null GpgME::Data::null;
+
+GpgME::Data::Data()
+{
+ gpgme_data_t data;
+ const gpgme_error_t e = gpgme_data_new(&data);
+ d.reset(new Private(e ? 0 : data));
+}
+
+GpgME::Data::Data(const Null &)
+ : d(new Private(0))
+{
+
+}
+
+GpgME::Data::Data(gpgme_data_t data)
+ : d(new Private(data))
+{
+
+}
+
+GpgME::Data::Data(const char *buffer, size_t size, bool copy)
+{
+ gpgme_data_t data;
+ const gpgme_error_t e = gpgme_data_new_from_mem(&data, buffer, size, int(copy));
+ d.reset(new Private(e ? 0 : data));
+}
+
+GpgME::Data::Data(const char *filename)
+{
+ gpgme_data_t data;
+ const gpgme_error_t e = gpgme_data_new(&data);
+ d.reset(new Private(e ? 0 : data));
+ if (!e) {
+ setFileName(filename);
+ }
+}
+
+GpgME::Data::Data(const char *filename, off_t offset, size_t length)
+{
+ gpgme_data_t data;
+ const gpgme_error_t e = gpgme_data_new_from_filepart(&data, filename, 0, offset, length);
+ d.reset(new Private(e ? 0 : data));
+}
+
+GpgME::Data::Data(FILE *fp)
+{
+ gpgme_data_t data;
+ const gpgme_error_t e = gpgme_data_new_from_stream(&data, fp);
+ d.reset(new Private(e ? 0 : data));
+}
+
+GpgME::Data::Data(FILE *fp, off_t offset, size_t length)
+{
+ gpgme_data_t data;
+ const gpgme_error_t e = gpgme_data_new_from_filepart(&data, 0, fp, offset, length);
+ d.reset(new Private(e ? 0 : data));
+}
+
+GpgME::Data::Data(int fd)
+{
+ gpgme_data_t data;
+ const gpgme_error_t e = gpgme_data_new_from_fd(&data, fd);
+ d.reset(new Private(e ? 0 : data));
+}
+
+GpgME::Data::Data(DataProvider *dp)
+{
+ d.reset(new Private);
+ if (!dp) {
+ return;
+ }
+ if (!dp->isSupported(DataProvider::Read)) {
+ d->cbs.read = 0;
+ }
+ if (!dp->isSupported(DataProvider::Write)) {
+ d->cbs.write = 0;
+ }
+ if (!dp->isSupported(DataProvider::Seek)) {
+ d->cbs.seek = 0;
+ }
+ if (!dp->isSupported(DataProvider::Release)) {
+ d->cbs.release = 0;
+ }
+ const gpgme_error_t e = gpgme_data_new_from_cbs(&d->data, &d->cbs, dp);
+ if (e) {
+ d->data = 0;
+ }
+#ifndef NDEBUG
+ //std::cerr << "GpgME::Data(): DataProvider supports: "
+ // << ( d->cbs.read ? "read" : "no read" ) << ", "
+ // << ( d->cbs.write ? "write" : "no write" ) << ", "
+ // << ( d->cbs.seek ? "seek" : "no seek" ) << ", "
+ // << ( d->cbs.release ? "release" : "no release" ) << std::endl;
+#endif
+}
+
+bool GpgME::Data::isNull() const
+{
+ return !d || !d->data;
+}
+
+GpgME::Data::Encoding GpgME::Data::encoding() const
+{
+ switch (gpgme_data_get_encoding(d->data)) {
+ case GPGME_DATA_ENCODING_NONE: return AutoEncoding;
+ case GPGME_DATA_ENCODING_BINARY: return BinaryEncoding;
+ case GPGME_DATA_ENCODING_BASE64: return Base64Encoding;
+ case GPGME_DATA_ENCODING_ARMOR: return ArmorEncoding;
+ }
+ return AutoEncoding;
+}
+
+GpgME::Error GpgME::Data::setEncoding(Encoding enc)
+{
+ gpgme_data_encoding_t ge = GPGME_DATA_ENCODING_NONE;
+ switch (enc) {
+ case AutoEncoding: ge = GPGME_DATA_ENCODING_NONE; break;
+ case BinaryEncoding: ge = GPGME_DATA_ENCODING_BINARY; break;
+ case Base64Encoding: ge = GPGME_DATA_ENCODING_BASE64; break;
+ case ArmorEncoding: ge = GPGME_DATA_ENCODING_ARMOR; break;
+ }
+ return Error(gpgme_data_set_encoding(d->data, ge));
+}
+
+char *GpgME::Data::fileName() const
+{
+#ifdef HAVE_GPGME_DATA_SET_FILE_NAME
+ return gpgme_data_get_file_name(d->data);
+#else
+ return 0;
+#endif
+}
+
+GpgME::Error GpgME::Data::setFileName(const char *name)
+{
+#ifdef HAVE_GPGME_DATA_SET_FILE_NAME
+ return Error(gpgme_data_set_file_name(d->data, name));
+#else
+ (void)name;
+ return Error();
+#endif
+}
+
+ssize_t GpgME::Data::read(void *buffer, size_t length)
+{
+ return gpgme_data_read(d->data, buffer, length);
+}
+
+ssize_t GpgME::Data::write(const void *buffer, size_t length)
+{
+ return gpgme_data_write(d->data, buffer, length);
+}
+
+off_t GpgME::Data::seek(off_t offset, int whence)
+{
+ return gpgme_data_seek(d->data, offset, whence);
+}
diff --git a/lang/cpp/src/data.h b/lang/cpp/src/data.h
new file mode 100644
index 0000000..c8a599e
--- /dev/null
+++ b/lang/cpp/src/data.h
@@ -0,0 +1,110 @@
+/*
+ data.h - wraps a gpgme data object
+ Copyright (C) 2003,2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_DATA_H__
+#define __GPGMEPP_DATA_H__
+
+#include "global.h"
+
+#include <boost/shared_ptr.hpp>
+
+#include <sys/types.h> // for size_t, off_t
+#include <cstdio> // FILE
+#include <algorithm>
+
+namespace GpgME
+{
+
+class DataProvider;
+class Error;
+
+class GPGMEPP_EXPORT Data
+{
+ struct Null {
+ Null() {}
+ };
+public:
+ /* implicit */ Data(const Null &);
+ Data();
+ explicit Data(gpgme_data_t data);
+
+ // Memory-Based Data Buffers:
+ Data(const char *buffer, size_t size, bool copy = true);
+ explicit Data(const char *filename);
+ Data(const char *filename, off_t offset, size_t length);
+ Data(std::FILE *fp, off_t offset, size_t length);
+ // File-Based Data Buffers:
+ explicit Data(std::FILE *fp);
+ explicit Data(int fd);
+ // Callback-Based Data Buffers:
+ explicit Data(DataProvider *provider);
+
+ static const Null null;
+
+ const Data &operator=(Data other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(Data &other)
+ {
+ using std::swap;
+ swap(this->d, other.d);
+ }
+
+ bool isNull() const;
+
+ enum Encoding {
+ AutoEncoding,
+ BinaryEncoding,
+ Base64Encoding,
+ ArmorEncoding
+ };
+ Encoding encoding() const;
+ Error setEncoding(Encoding encoding);
+
+ char *fileName() const;
+ Error setFileName(const char *name);
+
+ ssize_t read(void *buffer, size_t length);
+ ssize_t write(const void *buffer, size_t length);
+ off_t seek(off_t offset, int whence);
+
+ class Private;
+ Private *impl()
+ {
+ return d.get();
+ }
+ const Private *impl() const
+ {
+ return d.get();
+ }
+private:
+ boost::shared_ptr<Private> d;
+};
+
+}
+
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(Data)
+
+#endif // __GPGMEPP_DATA_H__
diff --git a/lang/cpp/src/data_p.h b/lang/cpp/src/data_p.h
new file mode 100644
index 0000000..38ba55a
--- /dev/null
+++ b/lang/cpp/src/data_p.h
@@ -0,0 +1,40 @@
+/*
+ data_p.h - wraps a gpgme data object, private part -*- c++ -*-
+ Copyright (C) 2003,2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_DATA_P_H__
+#define __GPGMEPP_DATA_P_H__
+
+#include <data.h>
+#include "callbacks.h"
+
+class GpgME::Data::Private
+{
+public:
+ explicit Private(gpgme_data_t d = 0)
+ : data(d), cbs(data_provider_callbacks) {}
+ ~Private();
+
+ gpgme_data_t data;
+ gpgme_data_cbs cbs;
+};
+
+#endif // __GPGMEPP_DATA_P_H__
diff --git a/lang/cpp/src/decryptionresult.cpp b/lang/cpp/src/decryptionresult.cpp
new file mode 100644
index 0000000..88e8567
--- /dev/null
+++ b/lang/cpp/src/decryptionresult.cpp
@@ -0,0 +1,276 @@
+/*
+ decryptionresult.cpp - wraps a gpgme keygen result
+ Copyright (C) 2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <config-gpgme++.h>
+
+#include <decryptionresult.h>
+#include "result_p.h"
+#include "util.h"
+
+#include <gpgme.h>
+
+#include <algorithm>
+#include <iterator>
+#include <cstring>
+#include <cstdlib>
+#include <istream>
+
+#include <string.h>
+
+class GpgME::DecryptionResult::Private
+{
+public:
+ explicit Private(const _gpgme_op_decrypt_result &r) : res(r)
+ {
+ if (res.unsupported_algorithm) {
+ res.unsupported_algorithm = strdup(res.unsupported_algorithm);
+ }
+#ifdef HAVE_GPGME_DECRYPT_RESULT_T_FILE_NAME
+ if (res.file_name) {
+ res.file_name = strdup(res.file_name);
+ }
+#endif
+#ifdef HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS
+ //FIXME: copying gpgme_recipient_t objects invalidates the keyid member,
+ //thus we use _keyid for now (internal API)
+ for (gpgme_recipient_t r = res.recipients ; r ; r = r->next) {
+ recipients.push_back(*r);
+ }
+ res.recipients = 0;
+#endif
+ }
+ ~Private()
+ {
+ if (res.unsupported_algorithm) {
+ std::free(res.unsupported_algorithm);
+ }
+ res.unsupported_algorithm = 0;
+#ifdef HAVE_GPGME_DECRYPT_RESULT_T_FILE_NAME
+ if (res.file_name) {
+ std::free(res.file_name);
+ }
+ res.file_name = 0;
+#endif
+ }
+
+ _gpgme_op_decrypt_result res;
+#ifdef HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS
+ std::vector<_gpgme_recipient> recipients;
+#endif
+};
+
+GpgME::DecryptionResult::DecryptionResult(gpgme_ctx_t ctx, int error)
+ : GpgME::Result(error), d()
+{
+ init(ctx);
+}
+
+GpgME::DecryptionResult::DecryptionResult(gpgme_ctx_t ctx, const Error &error)
+ : GpgME::Result(error), d()
+{
+ init(ctx);
+}
+
+void GpgME::DecryptionResult::init(gpgme_ctx_t ctx)
+{
+ if (!ctx) {
+ return;
+ }
+ gpgme_decrypt_result_t res = gpgme_op_decrypt_result(ctx);
+ if (!res) {
+ return;
+ }
+ d.reset(new Private(*res));
+}
+
+make_standard_stuff(DecryptionResult)
+
+const char *GpgME::DecryptionResult::unsupportedAlgorithm() const
+{
+ return d ? d->res.unsupported_algorithm : 0 ;
+}
+
+bool GpgME::DecryptionResult::isWrongKeyUsage() const
+{
+ return d && d->res.wrong_key_usage;
+}
+
+const char *GpgME::DecryptionResult::fileName() const
+{
+#ifdef HAVE_GPGME_DECRYPT_RESULT_T_FILE_NAME
+ return d ? d->res.file_name : 0 ;
+#else
+ return 0;
+#endif
+}
+
+unsigned int GpgME::DecryptionResult::numRecipients() const
+{
+#ifdef HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS
+ return d ? d->recipients.size() : 0 ;
+#else
+ return 0;
+#endif
+}
+
+GpgME::DecryptionResult::Recipient GpgME::DecryptionResult::recipient(unsigned int idx) const
+{
+#ifdef HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS
+ if (d && idx < d->recipients.size()) {
+ return Recipient(&d->recipients[idx]);
+ }
+#endif
+ return Recipient();
+}
+
+namespace
+{
+struct make_recipient {
+ GpgME::DecryptionResult::Recipient operator()(_gpgme_recipient &t)
+ {
+ return GpgME::DecryptionResult::Recipient(&t);
+ }
+};
+}
+
+std::vector<GpgME::DecryptionResult::Recipient> GpgME::DecryptionResult::recipients() const
+{
+ std::vector<Recipient> result;
+#ifdef HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS
+ if (d) {
+ result.reserve(d->recipients.size());
+ std::transform(d->recipients.begin(), d->recipients.end(),
+ std::back_inserter(result),
+ make_recipient());
+ }
+#endif
+ return result;
+}
+
+#ifdef HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS
+class GpgME::DecryptionResult::Recipient::Private : public _gpgme_recipient
+{
+public:
+ Private(gpgme_recipient_t reci) : _gpgme_recipient(*reci) {}
+};
+#endif
+
+GpgME::DecryptionResult::Recipient::Recipient()
+ : d()
+{
+
+}
+
+GpgME::DecryptionResult::Recipient::Recipient(gpgme_recipient_t r)
+ : d()
+{
+#ifdef HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS
+ if (r) {
+ d.reset(new Private(r));
+ }
+#endif
+}
+
+bool GpgME::DecryptionResult::Recipient::isNull() const
+{
+ return !d;
+}
+
+const char *GpgME::DecryptionResult::Recipient::keyID() const
+{
+#ifdef HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS
+ //_keyid is internal API, but the public keyid is invalid after copying (see above)
+ if (d) {
+ return d->_keyid;
+ }
+#endif
+ return 0;
+}
+
+const char *GpgME::DecryptionResult::Recipient::shortKeyID() const
+{
+#ifdef HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS
+ //_keyid is internal API, but the public keyid is invalid after copying (see above)
+ if (d) {
+ return d->_keyid + 8;
+ }
+#endif
+ return 0;
+}
+
+unsigned int GpgME::DecryptionResult::Recipient::publicKeyAlgorithm() const
+{
+#ifdef HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS
+ if (d) {
+ return d->pubkey_algo;
+ }
+#endif
+ return 0;
+}
+
+const char *GpgME::DecryptionResult::Recipient::publicKeyAlgorithmAsString() const
+{
+#ifdef HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS
+ if (d) {
+ return gpgme_pubkey_algo_name(d->pubkey_algo);
+ }
+#endif
+ return 0;
+}
+
+GpgME::Error GpgME::DecryptionResult::Recipient::status() const
+{
+#ifdef HAVE_GPGME_DECRYPT_RESULT_T_RECIPIENTS
+ if (d) {
+ return Error(d->status);
+ }
+#endif
+ return Error();
+}
+
+std::ostream &GpgME::operator<<(std::ostream &os, const DecryptionResult &result)
+{
+ os << "GpgME::DecryptionResult(";
+ if (!result.isNull()) {
+ os << "\n error: " << result.error()
+ << "\n fileName: " << protect(result.fileName())
+ << "\n unsupportedAlgorithm: " << protect(result.unsupportedAlgorithm())
+ << "\n isWrongKeyUsage: " << result.isWrongKeyUsage()
+ << "\n recipients:\n";
+ const std::vector<DecryptionResult::Recipient> recipients = result.recipients();
+ std::copy(recipients.begin(), recipients.end(),
+ std::ostream_iterator<DecryptionResult::Recipient>(os, "\n"));
+ }
+ return os << ')';
+}
+
+std::ostream &GpgME::operator<<(std::ostream &os, const DecryptionResult::Recipient &reci)
+{
+ os << "GpgME::DecryptionResult::Recipient(";
+ if (!reci.isNull()) {
+ os << "\n keyID: " << protect(reci.keyID())
+ << "\n shortKeyID: " << protect(reci.shortKeyID())
+ << "\n publicKeyAlgorithm: " << protect(reci.publicKeyAlgorithmAsString())
+ << "\n status: " << reci.status();
+ }
+ return os << ')';
+}
diff --git a/lang/cpp/src/decryptionresult.h b/lang/cpp/src/decryptionresult.h
new file mode 100644
index 0000000..2374cbb
--- /dev/null
+++ b/lang/cpp/src/decryptionresult.h
@@ -0,0 +1,131 @@
+/*
+ decryptionresult.h - wraps a gpgme keygen result
+ Copyright (C) 2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_DECRYPTIONRESULT_H__
+#define __GPGMEPP_DECRYPTIONRESULT_H__
+
+#include "gpgmefw.h"
+#include "result.h"
+#include "gpgmepp_export.h"
+
+#include <boost/shared_ptr.hpp>
+
+#include <vector>
+#include <algorithm>
+#include <iosfwd>
+
+namespace GpgME
+{
+
+class Error;
+
+class GPGMEPP_EXPORT DecryptionResult : public Result
+{
+public:
+ DecryptionResult();
+ DecryptionResult(gpgme_ctx_t ctx, int error);
+ DecryptionResult(gpgme_ctx_t ctx, const Error &err);
+ explicit DecryptionResult(const Error &err);
+
+ const DecryptionResult &operator=(DecryptionResult other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(DecryptionResult &other)
+ {
+ Result::swap(other);
+ using std::swap;
+ swap(this->d, other.d);
+ }
+
+ bool isNull() const;
+
+ GPGMEPP_DEPRECATED const char *unsupportedAlgortihm() const
+ {
+ return unsupportedAlgorithm();
+ }
+ const char *unsupportedAlgorithm() const;
+
+ GPGMEPP_DEPRECATED bool wrongKeyUsage() const
+ {
+ return isWrongKeyUsage();
+ }
+ bool isWrongKeyUsage() const;
+
+ const char *fileName() const;
+
+ class Recipient;
+
+ unsigned int numRecipients() const;
+ Recipient recipient(unsigned int idx) const;
+ std::vector<Recipient> recipients() const;
+
+private:
+ class Private;
+ void init(gpgme_ctx_t ctx);
+ boost::shared_ptr<Private> d;
+};
+
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const DecryptionResult &result);
+
+class GPGMEPP_EXPORT DecryptionResult::Recipient
+{
+public:
+ Recipient();
+ explicit Recipient(gpgme_recipient_t reci);
+
+ const Recipient &operator=(Recipient other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(Recipient &other)
+ {
+ using std::swap;
+ swap(this->d, other.d);
+ }
+
+ bool isNull() const;
+
+ const char *keyID() const;
+ const char *shortKeyID() const;
+
+ unsigned int publicKeyAlgorithm() const;
+ const char *publicKeyAlgorithmAsString() const;
+
+ Error status() const;
+
+private:
+ class Private;
+ boost::shared_ptr<Private> d;
+};
+
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const DecryptionResult::Recipient &reci);
+
+}
+
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(DecryptionResult)
+
+#endif // __GPGMEPP_DECRYPTIONRESULT_H__
diff --git a/lang/cpp/src/defaultassuantransaction.cpp b/lang/cpp/src/defaultassuantransaction.cpp
new file mode 100644
index 0000000..c51050c
--- /dev/null
+++ b/lang/cpp/src/defaultassuantransaction.cpp
@@ -0,0 +1,81 @@
+/*
+ defaultassuantransaction.cpp - default Assuan Transaction that just stores data and status lines
+ Copyright (C) 2009 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <config-gpgme++.h>
+
+#include "defaultassuantransaction.h"
+#include "error.h"
+#include "data.h"
+
+#include <sstream>
+
+using namespace GpgME;
+using namespace boost;
+
+DefaultAssuanTransaction::DefaultAssuanTransaction()
+ : AssuanTransaction(),
+ m_status(),
+ m_data()
+{
+
+}
+
+DefaultAssuanTransaction::~DefaultAssuanTransaction() {}
+
+Error DefaultAssuanTransaction::data(const char *data, size_t len)
+{
+ m_data.append(data, len);
+ return Error();
+}
+
+Data DefaultAssuanTransaction::inquire(const char *name, const char *args, Error &err)
+{
+ (void)name; (void)args; (void)err;
+ return Data::null;
+}
+
+Error DefaultAssuanTransaction::status(const char *status, const char *args)
+{
+ m_status.push_back(std::pair<std::string, std::string>(status, args));
+ return Error();
+}
+
+std::vector<std::string> DefaultAssuanTransaction::statusLine(const char *tag) const
+{
+ std::vector<std::string> result;
+ for (std::vector< std::pair<std::string, std::string> >::const_iterator it = m_status.begin(), end = m_status.end() ; it != end ; ++it) {
+ if (it->first == tag) {
+ result.push_back(it->second);
+ }
+ }
+ return result;
+}
+
+std::string DefaultAssuanTransaction::firstStatusLine(const char *tag) const
+{
+ for (std::vector< std::pair<std::string, std::string> >::const_iterator it = m_status.begin(), end = m_status.end() ; it != end ; ++it) {
+ if (it->first == tag) {
+ return it->second;
+ }
+ }
+ return std::string();
+}
diff --git a/lang/cpp/src/defaultassuantransaction.h b/lang/cpp/src/defaultassuantransaction.h
new file mode 100644
index 0000000..bf4b839
--- /dev/null
+++ b/lang/cpp/src/defaultassuantransaction.h
@@ -0,0 +1,65 @@
+/*
+ defaultassuantransaction.h - default Assuan Transaction that just stores data and status lines
+ Copyright (C) 2009 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_DEFAULTASSUANTRANSACTION_H__
+#define __GPGMEPP_DEFAULTASSUANTRANSACTION_H__
+
+#include <interfaces/assuantransaction.h>
+
+#include <string>
+#include <vector>
+#include <utility>
+
+namespace GpgME
+{
+
+class GPGMEPP_EXPORT DefaultAssuanTransaction : public AssuanTransaction
+{
+public:
+ explicit DefaultAssuanTransaction();
+ ~DefaultAssuanTransaction();
+
+ const std::vector< std::pair<std::string, std::string> > &statusLines() const
+ {
+ return m_status;
+ }
+ std::vector<std::string> statusLine(const char *tag) const;
+ std::string firstStatusLine(const char *tag) const;
+
+ const std::string &data() const
+ {
+ return m_data;
+ }
+
+private:
+ /* reimp */ Error data(const char *data, size_t datalen);
+ /* reimp */ Data inquire(const char *name, const char *args, Error &err);
+ /* reimp */ Error status(const char *status, const char *args);
+
+private:
+ std::vector< std::pair<std::string, std::string> > m_status;
+ std::string m_data;
+};
+
+} // namespace GpgME
+
+#endif // __GPGMEPP_DEFAULTASSUANTRANSACTION_H__
diff --git a/lang/cpp/src/editinteractor.cpp b/lang/cpp/src/editinteractor.cpp
new file mode 100644
index 0000000..0c5f778
--- /dev/null
+++ b/lang/cpp/src/editinteractor.cpp
@@ -0,0 +1,364 @@
+/*
+ editinteractor.cpp - Interface for edit interactors
+ Copyright (C) 2007 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <config-gpgme++.h>
+
+#include "editinteractor.h"
+#include "callbacks.h"
+#include "error.h"
+
+#ifdef HAVE_GPGME_GPG_ERROR_WRAPPERS
+#include <gpgme.h>
+#else
+#include <gpg-error.h>
+#endif
+
+#ifdef _WIN32
+# include <io.h>
+#include <windows.h>
+#else
+# include <unistd.h>
+#endif
+
+#include <cerrno>
+#include <cstring>
+
+using namespace GpgME;
+
+static const char *status_to_string(unsigned int status);
+static Error status_to_error(unsigned int status);
+
+class EditInteractor::Private
+{
+ friend class ::GpgME::EditInteractor;
+ friend class ::GpgME::CallbackHelper;
+ EditInteractor *const q;
+public:
+ explicit Private(EditInteractor *qq);
+ ~Private();
+
+private:
+ unsigned int state;
+ Error error;
+ std::FILE *debug;
+};
+
+class GpgME::CallbackHelper
+{
+private:
+ static int writeAll(int fd, const void *buf, size_t count)
+ {
+ size_t toWrite = count;
+ while (toWrite > 0) {
+#ifdef HAVE_GPGME_IO_READWRITE
+ const int n = gpgme_io_write(fd, buf, toWrite);
+#else
+# ifdef Q_OS_WIN
+ DWORD n;
+ if (!WriteFile((HANDLE)fd, buf, toWrite, &n, NULL)) {
+ return -1;
+ }
+# else
+ const int n = write(fd, buf, toWrite);
+# endif
+#endif
+ if (n < 0) {
+ return n;
+ }
+ toWrite -= n;
+ }
+ return count;
+ }
+
+public:
+ static int edit_interactor_callback_impl(void *opaque, gpgme_status_code_t status, const char *args, int fd)
+ {
+ EditInteractor::Private *ei = (EditInteractor::Private *)opaque;
+
+ Error err = status_to_error(status);
+
+ if (!err) {
+
+ // advance to next state based on input:
+ const unsigned int oldState = ei->state;
+ ei->state = ei->q->nextState(status, args, err);
+ if (ei->debug) {
+ std::fprintf(ei->debug, "EditInteractor: %u -> nextState( %s, %s ) -> %u\n",
+ oldState, status_to_string(status), args ? args : "<null>", ei->state);
+ }
+ if (err) {
+ ei->state = oldState;
+ goto error;
+ }
+
+ if (ei->state != oldState &&
+ // if there was an error from before, we stop here (### this looks weird, can this happen at all?)
+ ei->error.code() == GPG_ERR_NO_ERROR) {
+
+ // successful state change -> call action
+ if (const char *const result = ei->q->action(err)) {
+ if (err) {
+ goto error;
+ }
+ if (ei->debug) {
+ std::fprintf(ei->debug, "EditInteractor: action result \"%s\"\n", result);
+ }
+ // if there's a result, write it:
+ if (*result) {
+#ifdef HAVE_GPGME_GPG_ERROR_WRAPPERS
+ gpgme_err_set_errno(0);
+#else
+ gpg_err_set_errno(0);
+#endif
+ const ssize_t len = std::strlen(result);
+ if (writeAll(fd, result, len) != len) {
+ err = Error::fromSystemError();
+ if (ei->debug) {
+ std::fprintf(ei->debug, "EditInteractor: Could not write to fd %d (%s)\n", fd, err.asString());
+ }
+ goto error;
+ }
+ }
+#ifdef HAVE_GPGME_GPG_ERROR_WRAPPERS
+ gpgme_err_set_errno(0);
+#else
+ gpg_err_set_errno(0);
+#endif
+ if (writeAll(fd, "\n", 1) != 1) {
+ err = Error::fromSystemError();
+ if (ei->debug) {
+ std::fprintf(ei->debug, "EditInteractor: Could not write to fd %d (%s)\n", fd, err.asString());
+ }
+ goto error;
+ }
+ } else {
+ if (err) {
+ goto error;
+ }
+ if (ei->debug) {
+ std::fprintf(ei->debug, "EditInteractor: no action result\n");
+ }
+ }
+ } else {
+ if (ei->debug) {
+ std::fprintf(ei->debug, "EditInteractor: no action executed\n");
+ }
+ }
+ }
+
+ error:
+ if (err) {
+ ei->error = err;
+ ei->state = EditInteractor::ErrorState;
+ }
+
+ if (ei->debug) {
+ std::fprintf(ei->debug, "EditInteractor: error now %u (%s)\n",
+ ei->error.encodedError(), gpgme_strerror(ei->error.encodedError()));
+ }
+
+ return ei->error.encodedError();
+ }
+};
+
+static gpgme_error_t edit_interactor_callback(void *opaque, gpgme_status_code_t status, const char *args, int fd)
+{
+ return CallbackHelper::edit_interactor_callback_impl(opaque, status, args, fd);
+}
+
+const gpgme_edit_cb_t GpgME::edit_interactor_callback = ::edit_interactor_callback;
+
+EditInteractor::Private::Private(EditInteractor *qq)
+ : q(qq),
+ state(StartState),
+ error(),
+ debug(0)
+{
+
+}
+
+EditInteractor::Private::~Private() {}
+
+EditInteractor::EditInteractor()
+ : d(new Private(this))
+{
+
+}
+
+EditInteractor::~EditInteractor()
+{
+ delete d;
+}
+
+unsigned int EditInteractor::state() const
+{
+ return d->state;
+}
+
+Error EditInteractor::lastError() const
+{
+ return d->error;
+}
+
+bool EditInteractor::needsNoResponse(unsigned int status) const
+{
+ switch (status) {
+ case GPGME_STATUS_EOF:
+ case GPGME_STATUS_GOT_IT:
+ case GPGME_STATUS_NEED_PASSPHRASE:
+ case GPGME_STATUS_NEED_PASSPHRASE_SYM:
+ case GPGME_STATUS_GOOD_PASSPHRASE:
+ case GPGME_STATUS_BAD_PASSPHRASE:
+ case GPGME_STATUS_USERID_HINT:
+ case GPGME_STATUS_SIGEXPIRED:
+ case GPGME_STATUS_KEYEXPIRED:
+ return true;
+ default:
+ return false;
+ }
+}
+
+// static
+Error status_to_error(unsigned int status)
+{
+ switch (status) {
+ case GPGME_STATUS_MISSING_PASSPHRASE:
+ return Error::fromCode(GPG_ERR_NO_PASSPHRASE);
+ case GPGME_STATUS_ALREADY_SIGNED:
+ return Error::fromCode(GPG_ERR_ALREADY_SIGNED);
+ case GPGME_STATUS_KEYEXPIRED:
+ return Error::fromCode(GPG_ERR_CERT_EXPIRED);
+ case GPGME_STATUS_SIGEXPIRED:
+ return Error::fromCode(GPG_ERR_SIG_EXPIRED);
+ }
+ return Error();
+}
+
+void EditInteractor::setDebugChannel(std::FILE *debug)
+{
+ d->debug = debug;
+}
+
+static const char *const status_strings[] = {
+ "EOF",
+ /* mkstatus processing starts here */
+ "ENTER",
+ "LEAVE",
+ "ABORT",
+
+ "GOODSIG",
+ "BADSIG",
+ "ERRSIG",
+
+ "BADARMOR",
+
+ "RSA_OR_IDEA",
+ "KEYEXPIRED",
+ "KEYREVOKED",
+
+ "TRUST_UNDEFINED",
+ "TRUST_NEVER",
+ "TRUST_MARGINAL",
+ "TRUST_FULLY",
+ "TRUST_ULTIMATE",
+
+ "SHM_INFO",
+ "SHM_GET",
+ "SHM_GET_BOOL",
+ "SHM_GET_HIDDEN",
+
+ "NEED_PASSPHRASE",
+ "VALIDSIG",
+ "SIG_ID",
+ "ENC_TO",
+ "NODATA",
+ "BAD_PASSPHRASE",
+ "NO_PUBKEY",
+ "NO_SECKEY",
+ "NEED_PASSPHRASE_SYM",
+ "DECRYPTION_FAILED",
+ "DECRYPTION_OKAY",
+ "MISSING_PASSPHRASE",
+ "GOOD_PASSPHRASE",
+ "GOODMDC",
+ "BADMDC",
+ "ERRMDC",
+ "IMPORTED",
+ "IMPORT_OK",
+ "IMPORT_PROBLEM",
+ "IMPORT_RES",
+ "FILE_START",
+ "FILE_DONE",
+ "FILE_ERROR",
+
+ "BEGIN_DECRYPTION",
+ "END_DECRYPTION",
+ "BEGIN_ENCRYPTION",
+ "END_ENCRYPTION",
+
+ "DELETE_PROBLEM",
+ "GET_BOOL",
+ "GET_LINE",
+ "GET_HIDDEN",
+ "GOT_IT",
+ "PROGRESS",
+ "SIG_CREATED",
+ "SESSION_KEY",
+ "NOTATION_NAME",
+ "NOTATION_DATA",
+ "POLICY_URL",
+ "BEGIN_STREAM",
+ "END_STREAM",
+ "KEY_CREATED",
+ "USERID_HINT",
+ "UNEXPECTED",
+ "INV_RECP",
+ "NO_RECP",
+ "ALREADY_SIGNED",
+ "SIGEXPIRED",
+ "EXPSIG",
+ "EXPKEYSIG",
+ "TRUNCATED",
+ "ERROR",
+ "NEWSIG",
+ "REVKEYSIG",
+ "SIG_SUBPACKET",
+ "NEED_PASSPHRASE_PIN",
+ "SC_OP_FAILURE",
+ "SC_OP_SUCCESS",
+ "CARDCTRL",
+ "BACKUP_KEY_CREATED",
+ "PKA_TRUST_BAD",
+ "PKA_TRUST_GOOD",
+
+ "PLAINTEXT",
+};
+static const unsigned int num_status_strings = sizeof status_strings / sizeof * status_strings ;
+
+const char *status_to_string(unsigned int idx)
+{
+ if (idx < num_status_strings) {
+ return status_strings[idx];
+ } else {
+ return "(unknown)";
+ }
+}
diff --git a/lang/cpp/src/editinteractor.h b/lang/cpp/src/editinteractor.h
new file mode 100644
index 0000000..2122052
--- /dev/null
+++ b/lang/cpp/src/editinteractor.h
@@ -0,0 +1,68 @@
+/*
+ editinteractor.h - Interface for edit interactors
+ Copyright (C) 2007 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_EDITINTERACTOR_H__
+#define __GPGMEPP_EDITINTERACTOR_H__
+
+#include "gpgmepp_export.h"
+
+#include <cstdio>
+
+namespace GpgME
+{
+
+class Error;
+class Context;
+class CallbackHelper;
+
+class GPGMEPP_EXPORT EditInteractor
+{
+ friend class ::GpgME::Context;
+ friend class ::GpgME::CallbackHelper;
+ EditInteractor(const EditInteractor &);
+ EditInteractor &operator=(const EditInteractor &);
+public:
+ EditInteractor();
+ virtual ~EditInteractor();
+
+ enum {
+ StartState = 0,
+ ErrorState = 0xFFFFFFFF
+ };
+
+ virtual const char *action(Error &err) const = 0;
+ virtual unsigned int nextState(unsigned int statusCode, const char *args, Error &err) const = 0;
+
+ unsigned int state() const;
+ Error lastError() const;
+ bool needsNoResponse(unsigned int statusCode) const;
+
+ void setDebugChannel(std::FILE *file);
+
+private:
+ class Private;
+ Private *const d;
+};
+
+} // namespace GpgME
+
+#endif // __GPGMEPP_EDITINTERACTOR_H__
diff --git a/lang/cpp/src/encryptionresult.cpp b/lang/cpp/src/encryptionresult.cpp
new file mode 100644
index 0000000..25e3922
--- /dev/null
+++ b/lang/cpp/src/encryptionresult.cpp
@@ -0,0 +1,161 @@
+/*
+ encryptionresult.cpp - wraps a gpgme verify result
+ Copyright (C) 2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <config-gpgme++.h>
+
+#include <encryptionresult.h>
+#include "result_p.h"
+#include "util.h"
+
+#include <gpgme.h>
+
+#include <cstring>
+#include <cstdlib>
+#include <istream>
+#include <algorithm>
+#include <iterator>
+
+#include <string.h>
+
+class GpgME::EncryptionResult::Private
+{
+public:
+ explicit Private(const gpgme_encrypt_result_t r)
+ {
+ if (!r) {
+ return;
+ }
+ for (gpgme_invalid_key_t ik = r->invalid_recipients ; ik ; ik = ik->next) {
+ gpgme_invalid_key_t copy = new _gpgme_invalid_key(*ik);
+ if (ik->fpr) {
+ copy->fpr = strdup(ik->fpr);
+ }
+ copy->next = 0;
+ invalid.push_back(copy);
+ }
+ }
+ ~Private()
+ {
+ for (std::vector<gpgme_invalid_key_t>::iterator it = invalid.begin() ; it != invalid.end() ; ++it) {
+ std::free((*it)->fpr);
+ delete *it; *it = 0;
+ }
+ }
+
+ std::vector<gpgme_invalid_key_t> invalid;
+};
+
+GpgME::EncryptionResult::EncryptionResult(gpgme_ctx_t ctx, int error)
+ : GpgME::Result(error), d()
+{
+ init(ctx);
+}
+
+GpgME::EncryptionResult::EncryptionResult(gpgme_ctx_t ctx, const Error &error)
+ : GpgME::Result(error), d()
+{
+ init(ctx);
+}
+
+void GpgME::EncryptionResult::init(gpgme_ctx_t ctx)
+{
+ if (!ctx) {
+ return;
+ }
+ gpgme_encrypt_result_t res = gpgme_op_encrypt_result(ctx);
+ if (!res) {
+ return;
+ }
+ d.reset(new Private(res));
+}
+
+make_standard_stuff(EncryptionResult)
+
+unsigned int GpgME::EncryptionResult::numInvalidRecipients() const
+{
+ return d ? d->invalid.size() : 0 ;
+}
+
+GpgME::InvalidRecipient GpgME::EncryptionResult::invalidEncryptionKey(unsigned int idx) const
+{
+ return InvalidRecipient(d, idx);
+}
+
+std::vector<GpgME::InvalidRecipient> GpgME::EncryptionResult::invalidEncryptionKeys() const
+{
+ if (!d) {
+ return std::vector<GpgME::InvalidRecipient>();
+ }
+ std::vector<GpgME::InvalidRecipient> result;
+ result.reserve(d->invalid.size());
+ for (unsigned int i = 0 ; i < d->invalid.size() ; ++i) {
+ result.push_back(InvalidRecipient(d, i));
+ }
+ return result;
+}
+
+GpgME::InvalidRecipient::InvalidRecipient(const boost::shared_ptr<EncryptionResult::Private> &parent, unsigned int i)
+ : d(parent), idx(i)
+{
+
+}
+
+GpgME::InvalidRecipient::InvalidRecipient() : d(), idx(0) {}
+
+bool GpgME::InvalidRecipient::isNull() const
+{
+ return !d || idx >= d->invalid.size() ;
+}
+
+const char *GpgME::InvalidRecipient::fingerprint() const
+{
+ return isNull() ? 0 : d->invalid[idx]->fpr ;
+}
+
+GpgME::Error GpgME::InvalidRecipient::reason() const
+{
+ return Error(isNull() ? 0 : d->invalid[idx]->reason);
+}
+
+std::ostream &GpgME::operator<<(std::ostream &os, const EncryptionResult &result)
+{
+ os << "GpgME::EncryptionResult(";
+ if (!result.isNull()) {
+ os << "\n error: " << result.error()
+ << "\n invalid recipients:\n";
+ const std::vector<InvalidRecipient> ir = result.invalidEncryptionKeys();
+ std::copy(ir.begin(), ir.end(),
+ std::ostream_iterator<InvalidRecipient>(os, "\n"));
+ }
+ return os << ')';
+}
+
+std::ostream &GpgME::operator<<(std::ostream &os, const InvalidRecipient &ir)
+{
+ os << "GpgME::InvalidRecipient(";
+ if (!ir.isNull()) {
+ os << "\n fingerprint: " << protect(ir.fingerprint())
+ << "\n reason: " << ir.reason()
+ << '\n';
+ }
+ return os << ')';
+}
diff --git a/lang/cpp/src/encryptionresult.h b/lang/cpp/src/encryptionresult.h
new file mode 100644
index 0000000..1f5d16f
--- /dev/null
+++ b/lang/cpp/src/encryptionresult.h
@@ -0,0 +1,113 @@
+/*
+ encryptionresult.h - wraps a gpgme sign result
+ Copyright (C) 2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_ENCRYPTIONRESULT_H__
+#define __GPGMEPP_ENCRYPTIONRESULT_H__
+
+#include "gpgmefw.h"
+#include "result.h"
+#include "gpgmepp_export.h"
+
+#include <boost/shared_ptr.hpp>
+
+#include <vector>
+#include <iosfwd>
+
+namespace GpgME
+{
+
+class Error;
+class InvalidRecipient;
+
+class GPGMEPP_EXPORT EncryptionResult : public Result
+{
+public:
+ EncryptionResult();
+ EncryptionResult(gpgme_ctx_t ctx, int error);
+ EncryptionResult(gpgme_ctx_t ctx, const Error &error);
+ EncryptionResult(const Error &err);
+
+ const EncryptionResult &operator=(EncryptionResult other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(EncryptionResult &other)
+ {
+ Result::swap(other);
+ using std::swap;
+ swap(this->d, other.d);
+ }
+
+ bool isNull() const;
+
+ unsigned int numInvalidRecipients() const;
+
+ InvalidRecipient invalidEncryptionKey(unsigned int index) const;
+ std::vector<InvalidRecipient> invalidEncryptionKeys() const;
+
+ class Private;
+private:
+ void init(gpgme_ctx_t ctx);
+ boost::shared_ptr<Private> d;
+};
+
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const EncryptionResult &result);
+
+class GPGMEPP_EXPORT InvalidRecipient
+{
+ friend class ::GpgME::EncryptionResult;
+ InvalidRecipient(const boost::shared_ptr<EncryptionResult::Private> &parent, unsigned int index);
+public:
+ InvalidRecipient();
+
+ const InvalidRecipient &operator=(InvalidRecipient other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(InvalidRecipient &other)
+ {
+ using std::swap;
+ swap(this->d, other.d);
+ }
+
+ bool isNull() const;
+
+ const char *fingerprint() const;
+ Error reason() const;
+
+private:
+ boost::shared_ptr<EncryptionResult::Private> d;
+ unsigned int idx;
+};
+
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const InvalidRecipient &recipient);
+
+}
+
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(EncryptionResult)
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(InvalidRecipient)
+
+#endif // __GPGMEPP_ENCRYPTIONRESULT_H__
diff --git a/lang/cpp/src/engineinfo.cpp b/lang/cpp/src/engineinfo.cpp
new file mode 100644
index 0000000..eaff2bd
--- /dev/null
+++ b/lang/cpp/src/engineinfo.cpp
@@ -0,0 +1,89 @@
+/*
+ engineinfo.h
+ Copyright (C) 2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <config-gpgme++.h>
+
+#include "engineinfo.h"
+
+#include <gpgme.h>
+
+class GpgME::EngineInfo::Private
+{
+public:
+ Private(gpgme_engine_info_t engine = 0) : info(engine) {}
+ ~Private()
+ {
+ info = 0;
+ }
+
+ gpgme_engine_info_t info;
+};
+
+GpgME::EngineInfo::EngineInfo() : d() {}
+
+GpgME::EngineInfo::EngineInfo(gpgme_engine_info_t engine)
+ : d(new Private(engine))
+{
+
+}
+
+bool GpgME::EngineInfo::isNull() const
+{
+ return !d || !d->info;
+}
+
+GpgME::Protocol GpgME::EngineInfo::protocol() const
+{
+ if (isNull()) {
+ return UnknownProtocol;
+ }
+ switch (d->info->protocol) {
+ case GPGME_PROTOCOL_OpenPGP: return OpenPGP;
+ case GPGME_PROTOCOL_CMS: return CMS;
+ default:
+ return UnknownProtocol;
+ }
+}
+
+const char *GpgME::EngineInfo::fileName() const
+{
+ return isNull() ? 0 : d->info->file_name;
+}
+
+const char *GpgME::EngineInfo::version() const
+{
+ return isNull() ? 0 : d->info->version;
+}
+
+const char *GpgME::EngineInfo::requiredVersion() const
+{
+ return isNull() ? 0 : d->info->req_version;
+}
+
+const char *GpgME::EngineInfo::homeDirectory() const
+{
+#ifdef HAVE_GPGME_ENGINE_INFO_T_HOME_DIR
+ return isNull() ? 0 : d->info->home_dir;
+#else
+ return 0;
+#endif
+}
diff --git a/lang/cpp/src/engineinfo.h b/lang/cpp/src/engineinfo.h
new file mode 100644
index 0000000..94c52bd
--- /dev/null
+++ b/lang/cpp/src/engineinfo.h
@@ -0,0 +1,70 @@
+/*
+ engineinfo.h
+ Copyright (C) 2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_ENGINEINFO_H__
+#define __GPGMEPP_ENGINEINFO_H__
+
+#include "global.h"
+
+#include <boost/shared_ptr.hpp>
+
+#include <algorithm>
+
+namespace GpgME
+{
+
+class GPGMEPP_EXPORT EngineInfo
+{
+public:
+ EngineInfo();
+ explicit EngineInfo(gpgme_engine_info_t engine);
+
+ const EngineInfo &operator=(EngineInfo other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(EngineInfo &other)
+ {
+ using std::swap;
+ swap(this->d, other.d);
+ }
+
+ bool isNull() const;
+
+ Protocol protocol() const;
+ const char *fileName() const;
+ const char *version() const;
+ const char *requiredVersion() const;
+ const char *homeDirectory() const;
+
+private:
+ class Private;
+ boost::shared_ptr<Private> d;
+};
+
+}
+
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(EngineInfo)
+
+#endif // __GPGMEPP_ENGINEINFO_H__
diff --git a/lang/cpp/src/error.h b/lang/cpp/src/error.h
new file mode 100644
index 0000000..009fe20
--- /dev/null
+++ b/lang/cpp/src/error.h
@@ -0,0 +1,78 @@
+/*
+ error.h - wraps a gpgme error
+ Copyright (C) 2003, 2007 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+// -*- c++ -*-
+#ifndef __GPGMEPP_ERROR_H__
+#define __GPGMEPP_ERROR_H__
+
+#include "global.h"
+
+#include <string>
+#include <iosfwd>
+
+#include <gpg-error.h>
+
+#ifndef GPGMEPP_ERR_SOURCE_DEFAULT
+# define GPGMEPP_ERR_SOURCE_DEFAULT GPG_ERR_SOURCE_USER_1
+#endif
+
+namespace GpgME
+{
+
+class GPGMEPP_EXPORT Error
+{
+public:
+ Error() : mErr(0), mMessage() {}
+ explicit Error(unsigned int e) : mErr(e), mMessage() {}
+
+ const char *source() const;
+ const char *asString() const;
+
+ int code() const;
+ int sourceID() const;
+
+ bool isCanceled() const;
+
+ unsigned int encodedError() const
+ {
+ return mErr;
+ }
+ int toErrno() const;
+
+ static bool hasSystemError();
+ static Error fromSystemError(unsigned int src = GPGMEPP_ERR_SOURCE_DEFAULT);
+ static void setSystemError(gpg_err_code_t err);
+ static void setErrno(int err);
+ static Error fromErrno(int err, unsigned int src = GPGMEPP_ERR_SOURCE_DEFAULT);
+ static Error fromCode(unsigned int err, unsigned int src = GPGMEPP_ERR_SOURCE_DEFAULT);
+
+ GPGMEPP_MAKE_SAFE_BOOL_OPERATOR(mErr &&!isCanceled())
+private:
+ unsigned int mErr;
+ mutable std::string mMessage;
+};
+
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const Error &err);
+
+} // namespace GpgME
+
+#endif /* __GPGMEPP_ERROR_H__ */
diff --git a/lang/cpp/src/eventloopinteractor.cpp b/lang/cpp/src/eventloopinteractor.cpp
new file mode 100644
index 0000000..4718ddc
--- /dev/null
+++ b/lang/cpp/src/eventloopinteractor.cpp
@@ -0,0 +1,201 @@
+/*
+ eventloopinteractor.cpp
+ Copyright (C) 2003,2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <config-gpgme++.h>
+
+#include <eventloopinteractor.h>
+
+#include <context.h>
+#include "context_p.h"
+#include <key.h>
+#include <trustitem.h>
+
+#include <gpgme.h>
+
+#include <vector>
+using std::vector;
+#ifndef NDEBUG
+# include <iostream>
+#endif
+#include <cassert>
+
+namespace GpgME
+{
+
+//
+// EventLoopInteractor::Private Declaration
+//
+
+class EventLoopInteractor::Private
+{
+public:
+ struct OneFD {
+ OneFD(int aFd, int aDir, gpgme_io_cb_t aFnc,
+ void *aFncData, void *aExternalTag)
+ : fd(aFd), dir(aDir), fnc(aFnc),
+ fncData(aFncData), externalTag(aExternalTag) {}
+ int fd;
+ int dir;
+ gpgme_io_cb_t fnc;
+ void *fncData;
+ void *externalTag;
+ };
+
+ vector<OneFD *> mCallbacks;
+
+ static void removeIOCb(void *tag);
+ static gpgme_error_t registerIOCb(void *data, int fd, int dir,
+ gpgme_io_cb_t fnc, void *fnc_data,
+ void **r_tag);
+ static void eventIOCb(void *, gpgme_event_io_t type, void *type_data);
+
+ static const gpgme_io_cbs iocbs;
+};
+
+const gpgme_io_cbs EventLoopInteractor::Private::iocbs = {
+ &EventLoopInteractor::Private::registerIOCb,
+ 0,
+ &EventLoopInteractor::Private::removeIOCb,
+ &EventLoopInteractor::Private::eventIOCb,
+ 0
+};
+
+//
+// EventLoopInteractor::Private IO Callback Implementations
+//
+
+gpgme_error_t EventLoopInteractor::Private::registerIOCb(void *, int fd, int dir,
+ gpgme_io_cb_t fnc, void *fnc_data,
+ void **r_tag)
+{
+ assert(instance()); assert(instance()->d);
+ bool ok = false;
+ void *etag = instance()->registerWatcher(fd, dir ? Read : Write, ok);
+ if (!ok) {
+ return gpgme_error(GPG_ERR_GENERAL);
+ }
+ instance()->d->mCallbacks.push_back(new OneFD(fd, dir, fnc, fnc_data, etag));
+ if (r_tag) {
+ *r_tag = instance()->d->mCallbacks.back();
+ }
+ return GPG_ERR_NO_ERROR;
+}
+
+void EventLoopInteractor::Private::removeIOCb(void *tag)
+{
+
+ if (!instance() || !instance()->d) {
+ return;
+ }
+ for (vector<OneFD *>::iterator it = instance()->d->mCallbacks.begin();
+ it != instance()->d->mCallbacks.end() ; ++it) {
+ if (*it == tag) {
+ instance()->unregisterWatcher((*it)->externalTag);
+ delete *it; *it = 0;
+ instance()->d->mCallbacks.erase(it);
+ return;
+ }
+ }
+}
+
+void EventLoopInteractor::Private::eventIOCb(void *data, gpgme_event_io_t type, void *type_data)
+{
+ assert(instance());
+ Context *ctx = static_cast<Context *>(data);
+ switch (type) {
+ case GPGME_EVENT_START: {
+ instance()->operationStartEvent(ctx);
+ // TODO: what's in type_data?
+ }
+ break;
+ case GPGME_EVENT_DONE: {
+ gpgme_error_t e = *static_cast<gpgme_error_t *>(type_data);
+ if (ctx && ctx->impl()) {
+ ctx->impl()->lasterr = e;
+ }
+ instance()->operationDoneEvent(ctx, Error(e));
+ }
+ break;
+ case GPGME_EVENT_NEXT_KEY: {
+ gpgme_key_t key = static_cast<gpgme_key_t>(type_data);
+ instance()->nextKeyEvent(ctx, Key(key, false));
+ }
+ break;
+ case GPGME_EVENT_NEXT_TRUSTITEM: {
+ gpgme_trust_item_t item = static_cast<gpgme_trust_item_t>(type_data);
+ instance()->nextTrustItemEvent(ctx, TrustItem(item));
+ gpgme_trust_item_unref(item);
+ }
+ break;
+ default: // warn
+ ;
+ }
+}
+
+//
+// EventLoopInteractor Implementation
+//
+
+EventLoopInteractor *EventLoopInteractor::mSelf = 0;
+
+EventLoopInteractor::EventLoopInteractor() : d(new Private)
+{
+ assert(!mSelf);
+ mSelf = this;
+}
+
+EventLoopInteractor::~EventLoopInteractor()
+{
+ // warn if there are still callbacks registered
+ mSelf = 0;
+ delete d;
+}
+
+void EventLoopInteractor::manage(Context *context)
+{
+ if (!context || context->managedByEventLoopInteractor()) {
+ return;
+ }
+ gpgme_io_cbs *iocbs = new gpgme_io_cbs(Private::iocbs);
+ iocbs->event_priv = context;
+ context->installIOCallbacks(iocbs);
+}
+
+void EventLoopInteractor::unmanage(Context *context)
+{
+ if (context) {
+ context->uninstallIOCallbacks();
+ }
+}
+
+void EventLoopInteractor::actOn(int fd, Direction dir)
+{
+ for (vector<Private::OneFD *>::const_iterator it = d->mCallbacks.begin();
+ it != d->mCallbacks.end() ; ++it) {
+ if ((*it)->fd == fd && ((*it)->dir ? Read : Write) == dir) {
+ (*((*it)->fnc))((*it)->fncData, fd);
+ break;
+ }
+ }
+}
+
+} // namespace GpgME
diff --git a/lang/cpp/src/eventloopinteractor.h b/lang/cpp/src/eventloopinteractor.h
new file mode 100644
index 0000000..94821d6
--- /dev/null
+++ b/lang/cpp/src/eventloopinteractor.h
@@ -0,0 +1,156 @@
+/*
+ eventloopinteractor.h
+ Copyright (C) 2003,2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+// -*- c++ -*-
+#ifndef __GPGMEPP_EVENTLOOPINTERACTOR_H__
+#define __GPGMEPP_EVENTLOOPINTERACTOR_H__
+
+#include "gpgmepp_export.h"
+
+namespace GpgME
+{
+
+class Context;
+class Error;
+class TrustItem;
+class Key;
+
+/*! \file eventloopinteractor.h
+ \brief Abstract base class for gpgme's external event loop support
+
+ This class does most of the work involved with hooking GpgME++
+ up with external event loops, such as the GTK or Qt ones.
+
+ It actually provides two interfaces: An interface to the gpgme
+ IO Callback handling and one for gpgme events. The IO Callback
+ interface consists of the three methods \c actOn(), \c
+ registerWatcher() and \c unregisterWatcher(). The event
+ interface consists of the three methods \c nextTrustItemEvent(),
+ \c nextKeyEvent() and \c operationDoneEvent().
+
+ \sect General Usage
+
+ \c EventLoopInteractor is designed to be used as a
+ singleton. However, in order to make any use of it, you have to
+ subclass it and reimplement it's pure virtual methods (see
+ below). We suggest you keep the constructor protected and
+ provide a static \c instance() method that returns the single
+ instance. Alternatively, you can create an instance on the
+ stack, e.g. in \c main().
+
+ If you want \c EventLoopInteractor to manage a particular \c
+ Context, just call \c manage() on the \c Context. OTOH, if you
+ want to disable IO callbacks for a \c Context, use \c unmanage().
+
+ \sect IO Callback Interface
+
+ One part of this interface is represented by \c
+ registerWatcher() and \c unregisterWatcher(), both of which are
+ pure virtual. \c registerWatcher() should do anything necessary
+ to hook up watching of file descriptor \c fd for reading (\c dir
+ = \c Read) or writing (\c dir = Write) to the event loop you use
+ and return a tag identifying that particular watching process
+ uniquely. This could be the index into an array of objects you
+ use for that purpose or the address of such an object. E.g. in
+ Qt, you'd essentially just create a new \c QSocketNotifier:
+
+ \verbatim
+ void * registerWatcher( int fd, Direction dir ) {
+ return new QSocketNotifier( fd, dir == Read ? QSocketNotifier::Read : QSocketNotifier::Write );
+ // misses connecting to the activated() signal...
+ }
+ \endverbatim
+
+ which uses the address of the created object as unique tag. The
+ tag returned by \c registerWatcher is stored by \c
+ EventLoopInteractor and passed as argument to \c
+ unregisterWatcher(). So, in the picture above, you'd implement \c
+ unregisterWatcher() like this:
+
+ \verbatim
+ void unregisterWatcher( void * tag ) {
+ delete static_cast<QSocketNotifier*>( tag );
+ }
+ \endverbatim
+
+ The other part of the IO callback interface is \c actOn(), which
+ you should call if you receive notification from your event loop
+ about activity on file descriptor \c fd in direction \c dir. In
+ the picture above, you'd call this from the slot connected to
+ the socket notifier's \c activated() signal.
+
+ \note \c registerWatcher() as well as \c unregisterWatcher() may
+ be called from within \c actOn(), so be careful with
+ e.g. locking in threaded environments and keep in mind that the
+ object you used to find the \c fd and \c dir fo the \c actOn()
+ call might be deleted when \c actOn() returns!
+
+ \sect Event Handler Interface
+
+*/
+class GPGMEPP_EXPORT EventLoopInteractor
+{
+protected:
+ EventLoopInteractor();
+public:
+ virtual ~EventLoopInteractor();
+
+ static EventLoopInteractor *instance()
+ {
+ return mSelf;
+ }
+
+ void manage(Context *context);
+ void unmanage(Context *context);
+
+ enum Direction { Read, Write };
+protected:
+ //
+ // IO Notification Interface
+ //
+
+ /** Call this if your event loop detected activity on file
+ descriptor fd, with direction dir */
+ void actOn(int fd, Direction dir);
+
+ virtual void *registerWatcher(int fd, Direction dir, bool &ok) = 0;
+ virtual void unregisterWatcher(void *tag) = 0;
+
+ //
+ // Event Handler Interface
+ //
+
+ virtual void operationStartEvent(Context *context) = 0;
+ virtual void nextTrustItemEvent(Context *context, const TrustItem &item) = 0;
+ virtual void nextKeyEvent(Context *context, const Key &key) = 0;
+ virtual void operationDoneEvent(Context *context, const Error &e) = 0;
+
+private:
+ class Private;
+ friend class Private;
+ Private *const d;
+ static EventLoopInteractor *mSelf;
+};
+
+}
+
+#endif // __GPGMEPP_EVENTLOOPINTERACTOR_H__
diff --git a/lang/cpp/src/exception.cpp b/lang/cpp/src/exception.cpp
new file mode 100644
index 0000000..c687024
--- /dev/null
+++ b/lang/cpp/src/exception.cpp
@@ -0,0 +1,58 @@
+/*
+ exception.cpp - exception wrapping a gpgme error
+ Copyright (C) 2007 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+// -*- c++ -*-
+#include "exception.h"
+
+#include <gpgme.h>
+
+#include <sstream>
+
+using namespace GpgME;
+using namespace std; // only safe b/c it's so small a file!
+
+Exception::~Exception() throw() {}
+
+// static
+string Exception::make_message(const Error &err, const string &msg)
+{
+ return make_message(err, msg, NoOptions);
+}
+
+// static
+string Exception::make_message(const Error &err, const string &msg, Options opt)
+{
+ if (opt & MessageOnly) {
+ return msg;
+ }
+ char error_string[128];
+ error_string[0] = '\0';
+ gpgme_strerror_r(err.encodedError(), error_string, sizeof error_string);
+ error_string[sizeof error_string - 1] = '\0';
+ stringstream ss;
+ ss << gpgme_strsource(err.encodedError()) << ": ";
+ if (!msg.empty()) {
+ ss << msg << ": ";
+ }
+ ss << error_string << " (" << static_cast<unsigned long>(err.encodedError()) << ')';
+ return ss.str();
+}
diff --git a/lang/cpp/src/exception.h b/lang/cpp/src/exception.h
new file mode 100644
index 0000000..8f40b0e
--- /dev/null
+++ b/lang/cpp/src/exception.h
@@ -0,0 +1,68 @@
+/*
+ exception.h - exception wrapping a gpgme error
+ Copyright (C) 2007 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+// -*- c++ -*-
+#ifndef __GPGMEPP_EXCEPTION_H__
+#define __GPGMEPP_EXCEPTION_H__
+
+#include "error.h"
+
+#include <stdexcept>
+#include <string>
+
+namespace GpgME
+{
+
+class GPGMEPP_EXPORT Exception : public std::runtime_error
+{
+public:
+ enum Options {
+ NoOptions = 0x0,
+ MessageOnly = 0x1,
+
+ AllOptions = MessageOnly
+ };
+
+ explicit Exception(const GpgME::Error &err, const std::string &msg = std::string(), Options opt = NoOptions)
+ : std::runtime_error(make_message(err, msg, opt)), m_error(err), m_message(msg) {}
+
+ ~Exception() throw();
+
+ Error error() const
+ {
+ return m_error;
+ }
+ const std::string &message() const
+ {
+ return m_message;
+ }
+private:
+ static std::string make_message(const GpgME::Error &err, const std::string &msg);
+ static std::string make_message(const GpgME::Error &err, const std::string &msg, Options opt);
+private:
+ const GpgME::Error m_error;
+ const std::string m_message;
+};
+
+} // namespace GpgME
+
+#endif /* __GPGMEPP_EXCEPTION_H__ */
diff --git a/lang/cpp/src/global.h b/lang/cpp/src/global.h
new file mode 100644
index 0000000..f65503a
--- /dev/null
+++ b/lang/cpp/src/global.h
@@ -0,0 +1,156 @@
+/*
+ global.h - global gpgme functions and enums
+ Copyright (C) 2003, 2007 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+// -*- c++ -*-
+#ifndef __GPGMEPP_GLOBAL_H__
+#define __GPGMEPP_GLOBAL_H__
+
+#include "gpgmefw.h"
+#include "gpgmepp_export.h"
+
+#include <iosfwd>
+#include <QByteArray>
+
+namespace GpgME
+{
+class Error;
+class EngineInfo;
+class Context;
+}
+
+struct _GIOChannel;
+typedef struct _GIOChannel GIOChannel;
+class QIODevice;
+
+namespace GpgME
+{
+
+GPGMEPP_EXPORT void initializeLibrary();
+/*!
+ Initializes the library, returns Error::code() ==
+ GPG_ERR_USER_1 if underlying gpgme is too old.
+*/
+GPGMEPP_EXPORT Error initializeLibrary(int);
+
+enum Protocol { OpenPGP, CMS, UnknownProtocol };
+
+enum Engine { GpgEngine, GpgSMEngine, GpgConfEngine, UnknownEngine, AssuanEngine, G13Engine };
+
+enum KeyListMode {
+ Local = 0x1,
+ Extern = 0x2,
+ Signatures = 0x4,
+ SignatureNotations = 0x8,
+ Validate = 0x10,
+ Ephemeral = 0x20
+};
+
+enum SignatureMode { NormalSignatureMode, Detached, Clearsigned };
+
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, Protocol proto);
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, Engine eng);
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, KeyListMode mode);
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, SignatureMode mode);
+
+GPGMEPP_EXPORT Error setDefaultLocale(int category, const char *value);
+
+GPGMEPP_EXPORT Context *wait(Error &e, bool hang = true);
+typedef void (*IdleFunction)(void);
+GPGMEPP_EXPORT IdleFunction registerIdleFunction(IdleFunction idleFunction);
+
+typedef void (*IOCallback)(void *data, int fd);
+
+GPGMEPP_EXPORT EngineInfo engineInfo(Protocol proto);
+GPGMEPP_EXPORT EngineInfo engineInfo(Engine engine);
+
+GPGMEPP_EXPORT Error checkEngine(Protocol proto);
+GPGMEPP_EXPORT Error checkEngine(Engine engine);
+
+GPGMEPP_EXPORT GIOChannel *getGIOChannel(int fd);
+GPGMEPP_EXPORT QIODevice *getQIODevice(int fd);
+
+enum Feature {
+ ValidatingKeylistModeFeature = 0x00000001,
+ CancelOperationFeature = 0x00000002,
+ WrongKeyUsageFeature = 0x00000004,
+ DefaultCertificateInclusionFeature = 0x00000008,
+
+ GetSetEngineInfoFeature = 0x00000010,
+ EngineInfoHomeDirFeature = 0x00000020,
+ NoEncryptToEncryptionFlagFeature = 0x00000040,
+ EphemeralKeylistModeFeature = 0x00000080,
+
+ SetDataFileNameFeeature = 0x00000100,
+ VerificationResultFileNameFeature = 0x00000200,
+ DecryptionResultFileNameFeature = 0x00000400,
+ DecryptionResultRecipientsFeature = 0x00000800,
+
+ AuditLogFeature = 0x00001000,
+ GpgConfEngineFeature = 0x00002000,
+ CancelOperationAsyncFeature = 0x00004000,
+ AssuanEngineFeature = 0x00008000,
+
+ ClearAddGetSignatureNotationsFeature = 0x00010000,
+ SignatureNotationsKeylistModeFeature = 0x00020000,
+ KeySignatureNotationsFeature = 0x00040000,
+ SignatureNotationsFlagsFeature = 0x00080000,
+ SignatureNotationsCriticalFlagFeature = 0x00100000,
+ SignatureNotationsHumanReadableFlagFeature = 0x00200000,
+ CardKeyFeature = 0x00400000,
+ ImportFromKeyserverFeature = 0x00800000,
+
+ KeyIsQualifiedFeature = 0x01000200,
+ SubkeyIsQualifiedFeature = 0x02000000,
+ SignaturePkaFieldsFeature = 0x04000000,
+ SignatureAlgorithmFieldsFeature = 0x08000000,
+
+ FdPointerFeature = 0x10000000,
+ G13VFSFeature = 0x20000000,
+ PasswdFeature = 0x40000000, // gpgme >= 1.3.0
+ // unusable (max value)
+
+ FeatureMaxValue = 0x80000000
+};
+enum Feature2 {
+ Feature2MaxValue = 0x80000000
+};
+// use hasFeature( unsigned long, unsigned long ) instead
+GPGMEPP_DEPRECATED_EXPORT bool hasFeature(unsigned long feature);
+GPGMEPP_EXPORT bool hasFeature(unsigned long feature, unsigned long feature2);
+
+} // namespace GpgME
+
+# ifndef GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION
+# define GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION( Class ) \
+ namespace std { template <> inline void swap< GpgME::Class >( GpgME::Class & lhs, GpgME::Class & rhs ) { lhs.swap( rhs ); } }
+# endif
+
+# ifndef GPGMEPP_MAKE_SAFE_BOOL_OPERATOR
+# define GPGMEPP_MAKE_SAFE_BOOL_OPERATOR( Cond ) \
+ private: \
+ struct __safe_bool_dummy__ { void nonnull() {} }; \
+ typedef void ( __safe_bool_dummy__::*unspecified_bool_type )(); \
+ public: \
+ operator unspecified_bool_type() const { return ( Cond ) ? &__safe_bool_dummy__::nonnull : 0 ; }
+# endif
+
+#endif // __GPGMEPP_GLOBAL_H__
diff --git a/lang/cpp/src/gpgadduserideditinteractor.cpp b/lang/cpp/src/gpgadduserideditinteractor.cpp
new file mode 100644
index 0000000..43c8592
--- /dev/null
+++ b/lang/cpp/src/gpgadduserideditinteractor.cpp
@@ -0,0 +1,189 @@
+/*
+ gpgadduserideditinteractor.cpp - Edit Interactor to add a new UID to an OpenPGP key
+ Copyright (C) 2008 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "gpgadduserideditinteractor.h"
+
+#include "error.h"
+
+#include <gpgme.h>
+
+#include <cstring>
+
+using std::strcmp;
+
+// avoid conflict (msvc)
+#ifdef ERROR
+# undef ERROR
+#endif
+
+using namespace GpgME;
+
+GpgAddUserIDEditInteractor::GpgAddUserIDEditInteractor()
+ : EditInteractor(),
+ m_name(),
+ m_email(),
+ m_comment()
+{
+
+}
+
+GpgAddUserIDEditInteractor::~GpgAddUserIDEditInteractor() {}
+
+void GpgAddUserIDEditInteractor::setNameUtf8(const std::string &name)
+{
+ m_name = name;
+}
+
+void GpgAddUserIDEditInteractor::setEmailUtf8(const std::string &email)
+{
+ m_email = email;
+}
+
+void GpgAddUserIDEditInteractor::setCommentUtf8(const std::string &comment)
+{
+ m_comment = comment;
+}
+
+// work around --enable-final
+namespace GpgAddUserIDEditInteractor_Private
+{
+enum {
+ START = EditInteractor::StartState,
+ COMMAND,
+ NAME,
+ EMAIL,
+ COMMENT,
+ QUIT,
+ SAVE,
+
+ ERROR = EditInteractor::ErrorState
+};
+}
+
+const char *GpgAddUserIDEditInteractor::action(Error &err) const
+{
+
+ using namespace GpgAddUserIDEditInteractor_Private;
+
+ switch (state()) {
+ case COMMAND:
+ return "adduid";
+ case NAME:
+ return m_name.c_str();
+ case EMAIL:
+ return m_email.c_str();
+ case COMMENT:
+ return m_comment.c_str();
+ case QUIT:
+ return "quit";
+ case SAVE:
+ return "Y";
+ case START:
+ case ERROR:
+ return 0;
+ default:
+ err = Error::fromCode(GPG_ERR_GENERAL);
+ return 0;
+ }
+}
+
+unsigned int GpgAddUserIDEditInteractor::nextState(unsigned int status, const char *args, Error &err) const
+{
+
+ static const Error GENERAL_ERROR = Error::fromCode(GPG_ERR_GENERAL);
+ static const Error INV_NAME_ERROR = Error::fromCode(GPG_ERR_INV_NAME);
+ static const Error INV_EMAIL_ERROR = Error::fromCode(GPG_ERR_INV_USER_ID);
+ static const Error INV_COMMENT_ERROR = Error::fromCode(GPG_ERR_INV_USER_ID);
+
+ if (needsNoResponse(status)) {
+ return state();
+ }
+
+ using namespace GpgAddUserIDEditInteractor_Private;
+
+ switch (state()) {
+ case START:
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keyedit.prompt") == 0) {
+ return COMMAND;
+ }
+ err = GENERAL_ERROR;
+ return ERROR;
+ case COMMAND:
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keygen.name") == 0) {
+ return NAME;
+ }
+ err = GENERAL_ERROR;
+ return ERROR;
+ case NAME:
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keygen.email") == 0) {
+ return EMAIL;
+ }
+ err = GENERAL_ERROR;
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keygen.name") == 0) {
+ err = INV_NAME_ERROR;
+ }
+ return ERROR;
+ case EMAIL:
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keygen.comment") == 0) {
+ return COMMENT;
+ }
+ err = GENERAL_ERROR;
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keygen.email") == 0) {
+ err = INV_EMAIL_ERROR;
+ }
+ return ERROR;
+ case COMMENT:
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keyedit.prompt") == 0) {
+ return QUIT;
+ }
+ err = GENERAL_ERROR;
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keygen.comment") == 0) {
+ err = INV_COMMENT_ERROR;
+ }
+ return ERROR;
+ case QUIT:
+ if (status == GPGME_STATUS_GET_BOOL &&
+ strcmp(args, "keyedit.save.okay") == 0) {
+ return SAVE;
+ }
+ err = GENERAL_ERROR;
+ return ERROR;
+ case ERROR:
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keyedit.prompt") == 0) {
+ return QUIT;
+ }
+ err = lastError();
+ return ERROR;
+ default:
+ err = GENERAL_ERROR;
+ return ERROR;
+ }
+}
diff --git a/lang/cpp/src/gpgadduserideditinteractor.h b/lang/cpp/src/gpgadduserideditinteractor.h
new file mode 100644
index 0000000..12b6e46
--- /dev/null
+++ b/lang/cpp/src/gpgadduserideditinteractor.h
@@ -0,0 +1,67 @@
+/*
+ gpgadduserideditinteractor.h - Edit Interactor to add a new UID to an OpenPGP key
+ Copyright (C) 2008 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_GPGADDUSERIDEDITINTERACTOR_H__
+#define __GPGMEPP_GPGADDUSERIDEDITINTERACTOR_H__
+
+#include <editinteractor.h>
+
+#include <string>
+
+namespace GpgME
+{
+
+class GPGMEPP_EXPORT GpgAddUserIDEditInteractor : public EditInteractor
+{
+public:
+ explicit GpgAddUserIDEditInteractor();
+ ~GpgAddUserIDEditInteractor();
+
+ void setNameUtf8(const std::string &name);
+ const std::string &nameUtf8() const
+ {
+ return m_name;
+ }
+
+ void setEmailUtf8(const std::string &email);
+ const std::string &emailUtf8() const
+ {
+ return m_email;
+ }
+
+ void setCommentUtf8(const std::string &comment);
+ const std::string &commentUtf8() const
+ {
+ return m_comment;
+ }
+
+private:
+ /* reimp */ const char *action(Error &err) const;
+ /* reimp */ unsigned int nextState(unsigned int statusCode, const char *args, Error &err) const;
+
+private:
+ std::string m_name, m_email, m_comment;
+};
+
+} // namespace GpgME
+
+#endif // __GPGMEPP_GPGADDUSERIDEDITINTERACTOR_H__
diff --git a/lang/cpp/src/gpgagentgetinfoassuantransaction.cpp b/lang/cpp/src/gpgagentgetinfoassuantransaction.cpp
new file mode 100644
index 0000000..e07a856
--- /dev/null
+++ b/lang/cpp/src/gpgagentgetinfoassuantransaction.cpp
@@ -0,0 +1,123 @@
+/*
+ gpgagentgetinfoassuantransaction.cpp - Assuan Transaction to get information from gpg-agent
+ Copyright (C) 2009 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <config-gpgme++.h>
+
+#include "gpgagentgetinfoassuantransaction.h"
+#include "error.h"
+#include "data.h"
+#include "util.h"
+
+#include <boost/static_assert.hpp>
+
+#include <sstream>
+
+using namespace GpgME;
+using namespace boost;
+
+GpgAgentGetInfoAssuanTransaction::GpgAgentGetInfoAssuanTransaction(InfoItem item)
+ : AssuanTransaction(),
+ m_item(item),
+ m_command(),
+ m_data()
+{
+
+}
+
+GpgAgentGetInfoAssuanTransaction::~GpgAgentGetInfoAssuanTransaction() {}
+
+std::string GpgAgentGetInfoAssuanTransaction::version() const
+{
+ if (m_item == Version) {
+ return m_data;
+ } else {
+ return std::string();
+ }
+}
+
+unsigned int GpgAgentGetInfoAssuanTransaction::pid() const
+{
+ if (m_item == Pid) {
+ return to_pid(m_data);
+ } else {
+ return 0U;
+ }
+}
+
+std::string GpgAgentGetInfoAssuanTransaction::socketName() const
+{
+ if (m_item == SocketName) {
+ return m_data;
+ } else {
+ return std::string();
+ }
+}
+
+std::string GpgAgentGetInfoAssuanTransaction::sshSocketName() const
+{
+ if (m_item == SshSocketName) {
+ return m_data;
+ } else {
+ return std::string();
+ }
+}
+
+static const char *const gpgagent_getinfo_tokens[] = {
+ "version",
+ "pid",
+ "socket_name",
+ "ssh_socket_name",
+ "scd_running",
+};
+BOOST_STATIC_ASSERT((sizeof gpgagent_getinfo_tokens / sizeof * gpgagent_getinfo_tokens == GpgAgentGetInfoAssuanTransaction::LastInfoItem));
+
+void GpgAgentGetInfoAssuanTransaction::makeCommand() const
+{
+ assert(m_item >= 0);
+ assert(m_item < LastInfoItem);
+ m_command = "GETINFO ";
+ m_command += gpgagent_getinfo_tokens[m_item];
+}
+
+const char *GpgAgentGetInfoAssuanTransaction::command() const
+{
+ makeCommand();
+ return m_command.c_str();
+}
+
+Error GpgAgentGetInfoAssuanTransaction::data(const char *data, size_t len)
+{
+ m_data.append(data, len);
+ return Error();
+}
+
+Data GpgAgentGetInfoAssuanTransaction::inquire(const char *name, const char *args, Error &err)
+{
+ (void)name; (void)args; (void)err;
+ return Data::null;
+}
+
+Error GpgAgentGetInfoAssuanTransaction::status(const char *status, const char *args)
+{
+ (void)status; (void)args;
+ return Error();
+}
diff --git a/lang/cpp/src/gpgagentgetinfoassuantransaction.h b/lang/cpp/src/gpgagentgetinfoassuantransaction.h
new file mode 100644
index 0000000..9e3e958
--- /dev/null
+++ b/lang/cpp/src/gpgagentgetinfoassuantransaction.h
@@ -0,0 +1,73 @@
+/*
+ gpgagentgetinfoassuantransaction.h - Assuan Transaction to get information from gpg-agent
+ Copyright (C) 2009 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_GPGAGENTGETINFOASSUANTRANSACTION_H__
+#define __GPGMEPP_GPGAGENTGETINFOASSUANTRANSACTION_H__
+
+#include <interfaces/assuantransaction.h>
+
+#include <string>
+#include <vector>
+
+namespace GpgME
+{
+
+class GPGMEPP_EXPORT GpgAgentGetInfoAssuanTransaction : public AssuanTransaction
+{
+public:
+ enum InfoItem {
+ Version, // string
+ Pid, // unsigned long
+ SocketName, // string (path)
+ SshSocketName, // string (path)
+ ScdRunning, // (none, returns GPG_ERR_GENERAL when scdaemon isn't running)
+ //CommandHasOption, // not supported
+
+ LastInfoItem
+ };
+
+ explicit GpgAgentGetInfoAssuanTransaction(InfoItem item);
+ ~GpgAgentGetInfoAssuanTransaction();
+
+ std::string version() const;
+ unsigned int pid() const;
+ std::string socketName() const;
+ std::string sshSocketName() const;
+
+private:
+ /* reimp */ const char *command() const;
+ /* reimp */ Error data(const char *data, size_t datalen);
+ /* reimp */ Data inquire(const char *name, const char *args, Error &err);
+ /* reimp */ Error status(const char *status, const char *args);
+
+private:
+ void makeCommand() const;
+
+private:
+ InfoItem m_item;
+ mutable std::string m_command;
+ std::string m_data;
+};
+
+} // namespace GpgME
+
+#endif // __GPGMEPP_GPGAGENTGETINFOASSUANTRANSACTION_H__
diff --git a/lang/cpp/src/gpgmefw.h b/lang/cpp/src/gpgmefw.h
new file mode 100644
index 0000000..cbdd444
--- /dev/null
+++ b/lang/cpp/src/gpgmefw.h
@@ -0,0 +1,70 @@
+/*
+ gpgmefw.h - Forwards declarations for gpgme (0.3 and 0.4)
+ Copyright (C) 2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_GPGMEFW_H__
+#define __GPGMEPP_GPGMEFW_H__
+
+struct gpgme_context;
+typedef gpgme_context *gpgme_ctx_t;
+
+struct gpgme_data;
+typedef gpgme_data *gpgme_data_t;
+
+struct gpgme_io_cbs;
+
+struct _gpgme_key;
+typedef struct _gpgme_key *gpgme_key_t;
+
+struct _gpgme_trust_item;
+typedef struct _gpgme_trust_item *gpgme_trust_item_t;
+
+struct _gpgme_subkey;
+typedef struct _gpgme_subkey *gpgme_sub_key_t;
+
+struct _gpgme_user_id;
+typedef struct _gpgme_user_id *gpgme_user_id_t;
+
+struct _gpgme_key_sig;
+typedef struct _gpgme_key_sig *gpgme_key_sig_t;
+
+struct _gpgme_sig_notation;
+typedef struct _gpgme_sig_notation *gpgme_sig_notation_t;
+
+struct _gpgme_engine_info;
+typedef struct _gpgme_engine_info *gpgme_engine_info_t;
+
+struct _gpgme_op_keylist_result;
+typedef struct _gpgme_op_keylist_result *gpgme_keylist_result_t;
+
+struct _gpgme_recipient;
+typedef struct _gpgme_recipient *gpgme_recipient_t;
+
+struct gpgme_conf_opt;
+typedef struct gpgme_conf_opt *gpgme_conf_opt_t;
+
+struct gpgme_conf_comp;
+typedef struct gpgme_conf_comp *gpgme_conf_comp_t;
+
+struct gpgme_conf_arg;
+typedef struct gpgme_conf_arg *gpgme_conf_arg_t;
+
+#endif // __GPGMEPP_GPGMEFW_H__
diff --git a/lang/cpp/src/gpgmepp_export.h b/lang/cpp/src/gpgmepp_export.h
new file mode 100644
index 0000000..50a288d
--- /dev/null
+++ b/lang/cpp/src/gpgmepp_export.h
@@ -0,0 +1,41 @@
+
+#ifndef GPGMEPP_EXPORT_H
+#define GPGMEPP_EXPORT_H
+
+#ifdef GPGMEPP_STATIC_DEFINE
+# define GPGMEPP_EXPORT
+# define GPGMEPP_NO_EXPORT
+#else
+# ifndef GPGMEPP_EXPORT
+# ifdef KF5Gpgmepp_EXPORTS
+ /* We are building this library */
+# define GPGMEPP_EXPORT __attribute__((visibility("default")))
+# else
+ /* We are using this library */
+# define GPGMEPP_EXPORT __attribute__((visibility("default")))
+# endif
+# endif
+
+# ifndef GPGMEPP_NO_EXPORT
+# define GPGMEPP_NO_EXPORT __attribute__((visibility("hidden")))
+# endif
+#endif
+
+#ifndef GPGMEPP_DEPRECATED
+# define GPGMEPP_DEPRECATED __attribute__ ((__deprecated__))
+#endif
+
+#ifndef GPGMEPP_DEPRECATED_EXPORT
+# define GPGMEPP_DEPRECATED_EXPORT GPGMEPP_EXPORT GPGMEPP_DEPRECATED
+#endif
+
+#ifndef GPGMEPP_DEPRECATED_NO_EXPORT
+# define GPGMEPP_DEPRECATED_NO_EXPORT GPGMEPP_NO_EXPORT GPGMEPP_DEPRECATED
+#endif
+
+#define DEFINE_NO_DEPRECATED 0
+#if DEFINE_NO_DEPRECATED
+# define GPGMEPP_NO_DEPRECATED
+#endif
+
+#endif
diff --git a/lang/cpp/src/gpgsetexpirytimeeditinteractor.cpp b/lang/cpp/src/gpgsetexpirytimeeditinteractor.cpp
new file mode 100644
index 0000000..8af897c
--- /dev/null
+++ b/lang/cpp/src/gpgsetexpirytimeeditinteractor.cpp
@@ -0,0 +1,141 @@
+/*
+ gpgsetexpirytimeeditinteractor.cpp - Edit Interactor to change the expiry time of an OpenPGP key
+ Copyright (C) 2007 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "gpgsetexpirytimeeditinteractor.h"
+#include "error.h"
+
+#include <gpgme.h>
+
+#include <cstring>
+
+using std::strcmp;
+
+// avoid conflict (msvc)
+#ifdef ERROR
+# undef ERROR
+#endif
+
+using namespace GpgME;
+
+GpgSetExpiryTimeEditInteractor::GpgSetExpiryTimeEditInteractor(const std::string &t)
+ : EditInteractor(),
+ m_strtime(t)
+{
+
+}
+
+GpgSetExpiryTimeEditInteractor::~GpgSetExpiryTimeEditInteractor() {}
+
+// work around --enable-final
+namespace GpgSetExpiryTimeEditInteractor_Private
+{
+enum {
+ START = EditInteractor::StartState,
+ COMMAND,
+ DATE,
+ QUIT,
+ SAVE,
+
+ ERROR = EditInteractor::ErrorState
+};
+}
+
+const char *GpgSetExpiryTimeEditInteractor::action(Error &err) const
+{
+
+ using namespace GpgSetExpiryTimeEditInteractor_Private;
+
+ switch (state()) {
+ case COMMAND:
+ return "expire";
+ case DATE:
+ return m_strtime.c_str();
+ case QUIT:
+ return "quit";
+ case SAVE:
+ return "Y";
+ case START:
+ case ERROR:
+ return 0;
+ default:
+ err = Error::fromCode(GPG_ERR_GENERAL);
+ return 0;
+ }
+}
+
+unsigned int GpgSetExpiryTimeEditInteractor::nextState(unsigned int status, const char *args, Error &err) const
+{
+
+ static const Error GENERAL_ERROR = Error::fromCode(GPG_ERR_GENERAL);
+ static const Error INV_TIME_ERROR = Error::fromCode(GPG_ERR_INV_TIME);
+
+ if (needsNoResponse(status)) {
+ return state();
+ }
+
+ using namespace GpgSetExpiryTimeEditInteractor_Private;
+
+ switch (state()) {
+ case START:
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keyedit.prompt") == 0) {
+ return COMMAND;
+ }
+ err = GENERAL_ERROR;
+ return ERROR;
+ case COMMAND:
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keygen.valid") == 0) {
+ return DATE;
+ }
+ err = GENERAL_ERROR;
+ return ERROR;
+ case DATE:
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keyedit.prompt") == 0) {
+ return QUIT;
+ } else if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keygen.valid")) {
+ err = INV_TIME_ERROR;
+ return ERROR;
+ }
+ err = GENERAL_ERROR;
+ return ERROR;
+ case QUIT:
+ if (status == GPGME_STATUS_GET_BOOL &&
+ strcmp(args, "keyedit.save.okay") == 0) {
+ return SAVE;
+ }
+ err = GENERAL_ERROR;
+ return ERROR;
+ case ERROR:
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keyedit.prompt") == 0) {
+ return QUIT;
+ }
+ err = lastError();
+ return ERROR;
+ default:
+ err = GENERAL_ERROR;
+ return ERROR;
+ }
+}
diff --git a/lang/cpp/src/gpgsetexpirytimeeditinteractor.h b/lang/cpp/src/gpgsetexpirytimeeditinteractor.h
new file mode 100644
index 0000000..670b445
--- /dev/null
+++ b/lang/cpp/src/gpgsetexpirytimeeditinteractor.h
@@ -0,0 +1,49 @@
+/*
+ gpgsetexpirytimeeditinteractor.h - Edit Interactor to change the expiry time of an OpenPGP key
+ Copyright (C) 2007 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_GPGSETEXPIRYTIMEEDITINTERACTOR_H__
+#define __GPGMEPP_GPGSETEXPIRYTIMEEDITINTERACTOR_H__
+
+#include <editinteractor.h>
+
+#include <string>
+
+namespace GpgME
+{
+
+class GPGMEPP_EXPORT GpgSetExpiryTimeEditInteractor : public EditInteractor
+{
+public:
+ explicit GpgSetExpiryTimeEditInteractor(const std::string &timeString = "0");
+ ~GpgSetExpiryTimeEditInteractor();
+
+private:
+ /* reimp */ const char *action(Error &err) const;
+ /* reimp */ unsigned int nextState(unsigned int statusCode, const char *args, Error &err) const;
+
+private:
+ const std::string m_strtime;
+};
+
+} // namespace GpgME
+
+#endif // __GPGMEPP_GPGSETEXPIRYTIMEEDITINTERACTOR_H___
diff --git a/lang/cpp/src/gpgsetownertrusteditinteractor.cpp b/lang/cpp/src/gpgsetownertrusteditinteractor.cpp
new file mode 100644
index 0000000..15b1269
--- /dev/null
+++ b/lang/cpp/src/gpgsetownertrusteditinteractor.cpp
@@ -0,0 +1,151 @@
+/*
+ gpgsetownertrusteditinteractor.cpp - Edit Interactor to change the expiry time of an OpenPGP key
+ Copyright (C) 2007 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "gpgsetownertrusteditinteractor.h"
+#include "error.h"
+
+#include <gpgme.h>
+
+#include <cstring>
+
+using std::strcmp;
+
+// avoid conflict (msvc)
+#ifdef ERROR
+# undef ERROR
+#endif
+
+using namespace GpgME;
+
+GpgSetOwnerTrustEditInteractor::GpgSetOwnerTrustEditInteractor(Key::OwnerTrust ot)
+ : EditInteractor(),
+ m_ownertrust(ot)
+{
+
+}
+
+GpgSetOwnerTrustEditInteractor::~GpgSetOwnerTrustEditInteractor() {}
+
+// work around --enable-final
+namespace GpgSetOwnerTrustEditInteractor_Private
+{
+enum {
+ START = EditInteractor::StartState,
+ COMMAND,
+ VALUE,
+ REALLY_ULTIMATE,
+ QUIT,
+ SAVE,
+
+ ERROR = EditInteractor::ErrorState
+};
+}
+
+const char *GpgSetOwnerTrustEditInteractor::action(Error &err) const
+{
+ static const char truststrings[][2] = { "1", "1", "2", "3", "4", "5" };
+
+ using namespace GpgSetOwnerTrustEditInteractor_Private;
+
+ switch (state()) {
+ case COMMAND:
+ return "trust";
+ case VALUE:
+ return truststrings[m_ownertrust];
+ case REALLY_ULTIMATE:
+ return "Y";
+ case QUIT:
+ return "quit";
+ case SAVE:
+ return "Y";
+ case START:
+ case ERROR:
+ return 0;
+ default:
+ err = Error::fromCode(GPG_ERR_GENERAL);
+ return 0;
+ }
+}
+
+unsigned int GpgSetOwnerTrustEditInteractor::nextState(unsigned int status, const char *args, Error &err) const
+{
+
+ static const Error GENERAL_ERROR = Error::fromCode(GPG_ERR_GENERAL);
+ //static const Error INV_TIME_ERROR = Error::fromCode( GPG_ERR_INV_TIME );
+
+ if (needsNoResponse(status)) {
+ return state();
+ }
+
+ using namespace GpgSetOwnerTrustEditInteractor_Private;
+
+ switch (state()) {
+ case START:
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keyedit.prompt") == 0) {
+ return COMMAND;
+ }
+ err = GENERAL_ERROR;
+ return ERROR;
+ case COMMAND:
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "edit_ownertrust.value") == 0) {
+ return VALUE;
+ }
+ err = GENERAL_ERROR;
+ return ERROR;
+ case VALUE:
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keyedit.prompt") == 0) {
+ return QUIT;
+ } else if (status == GPGME_STATUS_GET_BOOL &&
+ strcmp(args, "edit_ownertrust.set_ultimate.okay") == 0) {
+ return REALLY_ULTIMATE;
+ }
+ err = GENERAL_ERROR;
+ return ERROR;
+ case REALLY_ULTIMATE:
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keyedit.prompt") == 0) {
+ return QUIT;
+ }
+ err = GENERAL_ERROR;
+ return ERROR;
+ case QUIT:
+ if (status == GPGME_STATUS_GET_BOOL &&
+ strcmp(args, "keyedit.save.okay") == 0) {
+ return SAVE;
+ }
+ err = GENERAL_ERROR;
+ return ERROR;
+ case ERROR:
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keyedit.prompt") == 0) {
+ return QUIT;
+ }
+ err = lastError();
+ return ERROR;
+ default:
+ err = GENERAL_ERROR;
+ return ERROR;
+ };
+}
diff --git a/lang/cpp/src/gpgsetownertrusteditinteractor.h b/lang/cpp/src/gpgsetownertrusteditinteractor.h
new file mode 100644
index 0000000..caf29ee
--- /dev/null
+++ b/lang/cpp/src/gpgsetownertrusteditinteractor.h
@@ -0,0 +1,50 @@
+/*
+ gpgsetownertrusteditinteractor.h - Edit Interactor to change the owner trust of an OpenPGP key
+ Copyright (C) 2007 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_GPGSETOWNERTRUSTEDITINTERACTOR_H__
+#define __GPGMEPP_GPGSETOWNERTRUSTEDITINTERACTOR_H__
+
+#include <editinteractor.h>
+#include <key.h>
+
+#include <string>
+
+namespace GpgME
+{
+
+class GPGMEPP_EXPORT GpgSetOwnerTrustEditInteractor : public EditInteractor
+{
+public:
+ explicit GpgSetOwnerTrustEditInteractor(Key::OwnerTrust ownertrust);
+ ~GpgSetOwnerTrustEditInteractor();
+
+private:
+ /* reimp */ const char *action(Error &err) const;
+ /* reimp */ unsigned int nextState(unsigned int statusCode, const char *args, Error &err) const;
+
+private:
+ const Key::OwnerTrust m_ownertrust;
+};
+
+} // namespace GpgME
+
+#endif // __GPGMEPP_GPGSETOWNERTRUSTEDITINTERACTOR_H__
diff --git a/lang/cpp/src/gpgsignkeyeditinteractor.cpp b/lang/cpp/src/gpgsignkeyeditinteractor.cpp
new file mode 100644
index 0000000..1950b2f
--- /dev/null
+++ b/lang/cpp/src/gpgsignkeyeditinteractor.cpp
@@ -0,0 +1,322 @@
+/*
+ gpgsignkeyeditinteractor.cpp - Edit Interactor to change the expiry time of an OpenPGP key
+ Copyright (C) 2007 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "gpgsignkeyeditinteractor.h"
+#include "error.h"
+#include "key.h"
+
+#include <gpgme.h>
+
+#include <boost/tuple/tuple.hpp>
+#include <boost/tuple/tuple_comparison.hpp>
+
+#include <map>
+#include <string>
+#include <sstream>
+
+#include <cassert>
+#include <cstring>
+
+using std::strcmp;
+
+// avoid conflict (msvc)
+#ifdef ERROR
+# undef ERROR
+#endif
+
+#ifdef _MSC_VER
+#undef snprintf
+#define snprintf _snprintf
+#endif
+
+using namespace boost;
+using namespace GpgME;
+
+class GpgSignKeyEditInteractor::Private
+{
+public:
+ Private();
+
+ std::string scratch;
+ bool started;
+ int options;
+ std::vector<unsigned int> userIDs;
+ std::vector<unsigned int>::const_iterator currentId, nextId;
+ unsigned int checkLevel;
+
+ const char *command() const
+ {
+ const bool local = (options & Exportable) == 0;
+ const bool nonRevoc = options & NonRevocable;
+ const bool trust = options & Trust;
+ //TODO: check if all combinations are valid
+ if (local && nonRevoc && trust) {
+ return "ltnrsign";
+ }
+ if (local && nonRevoc) {
+ return "lnrsign";
+ }
+ if (local && trust) {
+ return "ltsign";
+ }
+ if (local) {
+ return "lsign";
+ }
+ if (nonRevoc && trust) {
+ return "tnrsign";
+ }
+ if (nonRevoc) {
+ return "nrsign";
+ }
+ if (trust) {
+ return "tsign";
+ }
+ return "sign";
+ }
+
+ bool signAll() const
+ {
+ return userIDs.empty();
+ }
+ unsigned int nextUserID()
+ {
+ assert(nextId != userIDs.end());
+ currentId = nextId++;
+ return currentUserID();
+ }
+
+ bool allUserIDsListed() const
+ {
+ return nextId == userIDs.end();
+ }
+
+ unsigned int currentUserID() const
+ {
+ assert(currentId != userIDs.end());
+ return *currentId + 1;
+ }
+
+};
+
+GpgSignKeyEditInteractor::Private::Private()
+ :
+ started(false),
+ options(0),
+ userIDs(),
+ currentId(),
+ nextId(),
+ checkLevel(0)
+{
+}
+
+GpgSignKeyEditInteractor::GpgSignKeyEditInteractor()
+ : EditInteractor(), d(new Private)
+{
+
+}
+
+GpgSignKeyEditInteractor::~GpgSignKeyEditInteractor()
+{
+ delete d;
+}
+
+// work around --enable-final
+namespace GpgSignKeyEditInteractor_Private
+{
+enum SignKeyState {
+ START = EditInteractor::StartState,
+ COMMAND,
+ UIDS_ANSWER_SIGN_ALL,
+ UIDS_LIST_SEPARATELY,
+ // all these free slots belong to UIDS_LIST_SEPARATELY, too
+ // (we increase state() by one for each UID, so that action() is called)
+ UIDS_LIST_SEPARATELY_DONE = 1000000,
+ SET_EXPIRE,
+ SET_CHECK_LEVEL,
+ SET_TRUST_VALUE,
+ SET_TRUST_DEPTH,
+ SET_TRUST_REGEXP,
+ CONFIRM,
+ QUIT,
+ SAVE,
+ ERROR = EditInteractor::ErrorState
+};
+
+typedef std::map<tuple<SignKeyState, unsigned int, std::string>, SignKeyState> TransitionMap;
+
+}
+
+static const char *answer(bool b)
+{
+ return b ? "Y" : "N";
+}
+
+static GpgSignKeyEditInteractor_Private::TransitionMap makeTable()
+{
+ using namespace GpgSignKeyEditInteractor_Private;
+ TransitionMap tab;
+ const unsigned int GET_BOOL = GPGME_STATUS_GET_BOOL;
+ const unsigned int GET_LINE = GPGME_STATUS_GET_LINE;
+#define addEntry( s1, status, str, s2 ) tab[make_tuple( s1, status, str)] = s2
+ addEntry(START, GET_LINE, "keyedit.prompt", COMMAND);
+ addEntry(COMMAND, GET_BOOL, "keyedit.sign_all.okay", UIDS_ANSWER_SIGN_ALL);
+ addEntry(COMMAND, GET_BOOL, "sign_uid.okay", CONFIRM);
+ addEntry(UIDS_ANSWER_SIGN_ALL, GET_BOOL, "sign_uid.okay", CONFIRM);
+ addEntry(UIDS_ANSWER_SIGN_ALL, GET_LINE, "sign_uid.expire", SET_EXPIRE);
+ addEntry(UIDS_ANSWER_SIGN_ALL, GET_LINE, "sign_uid.class", SET_CHECK_LEVEL);
+ addEntry(SET_TRUST_VALUE, GET_LINE, "trustsign_prompt.trust_depth", SET_TRUST_DEPTH);
+ addEntry(SET_TRUST_DEPTH, GET_LINE, "trustsign_prompt.trust_regexp", SET_TRUST_REGEXP);
+ addEntry(SET_TRUST_REGEXP, GET_LINE, "sign_uid.okay", CONFIRM);
+ addEntry(SET_CHECK_LEVEL, GET_BOOL, "sign_uid.okay", CONFIRM);
+ addEntry(SET_EXPIRE, GET_BOOL, "sign_uid.class", SET_CHECK_LEVEL);
+ addEntry(CONFIRM, GET_BOOL, "sign_uid.local_promote_okay", CONFIRM);
+ addEntry(CONFIRM, GET_BOOL, "sign_uid.okay", CONFIRM);
+ addEntry(CONFIRM, GET_LINE, "keyedit.prompt", COMMAND);
+ addEntry(CONFIRM, GET_LINE, "trustsign_prompt.trust_value", SET_TRUST_VALUE);
+ addEntry(CONFIRM, GET_LINE, "sign_uid.expire", SET_EXPIRE);
+ addEntry(CONFIRM, GET_LINE, "sign_uid.class", SET_CHECK_LEVEL);
+ addEntry(UIDS_LIST_SEPARATELY_DONE, GET_BOOL, "sign_uid.local_promote_okay", CONFIRM);
+ addEntry(UIDS_LIST_SEPARATELY_DONE, GET_LINE, "keyedit.prompt", COMMAND);
+ addEntry(UIDS_LIST_SEPARATELY_DONE, GET_LINE, "trustsign_prompt.trust_value", SET_TRUST_VALUE);
+ addEntry(UIDS_LIST_SEPARATELY_DONE, GET_LINE, "sign_uid.expire", SET_EXPIRE);
+ addEntry(UIDS_LIST_SEPARATELY_DONE, GET_LINE, "sign_uid.class", SET_CHECK_LEVEL);
+ addEntry(UIDS_LIST_SEPARATELY_DONE, GET_BOOL, "sign_uid.okay", CONFIRM);
+ addEntry(CONFIRM, GET_LINE, "keyedit.prompt", QUIT);
+ addEntry(ERROR, GET_LINE, "keyedit.prompt", QUIT);
+ addEntry(QUIT, GET_BOOL, "keyedit.save.okay", SAVE);
+#undef addEntry
+ return tab;
+}
+
+const char *GpgSignKeyEditInteractor::action(Error &err) const
+{
+ static const char check_level_strings[][2] = { "0", "1", "2", "3" };
+ using namespace GpgSignKeyEditInteractor_Private;
+ using namespace std;
+
+ switch (const unsigned int st = state()) {
+ case COMMAND:
+ return d->command();
+ case UIDS_ANSWER_SIGN_ALL:
+ return answer(d->signAll());
+ case UIDS_LIST_SEPARATELY_DONE:
+ return d->command();
+ case SET_EXPIRE:
+ return answer(true);
+ case SET_TRUST_VALUE:
+ // TODO
+ case SET_TRUST_DEPTH:
+ //TODO
+ case SET_TRUST_REGEXP:
+ //TODO
+ return 0;
+ case SET_CHECK_LEVEL:
+ return check_level_strings[d->checkLevel];
+ case CONFIRM:
+ return answer(true);
+ case QUIT:
+ return "quit";
+ case SAVE:
+ return answer(true);
+ default:
+ if (st >= UIDS_LIST_SEPARATELY && st < UIDS_LIST_SEPARATELY_DONE) {
+ std::stringstream ss;
+ ss << d->nextUserID();
+ d->scratch = ss.str();
+ return d->scratch.c_str();
+ }
+ // fall through
+ case ERROR:
+ err = Error::fromCode(GPG_ERR_GENERAL);
+ return 0;
+ }
+}
+
+unsigned int GpgSignKeyEditInteractor::nextState(unsigned int status, const char *args, Error &err) const
+{
+ d->started = true;
+ using namespace GpgSignKeyEditInteractor_Private;
+ static const Error GENERAL_ERROR = Error::fromCode(GPG_ERR_GENERAL);
+ //static const Error INV_TIME_ERROR = Error::fromCode( GPG_ERR_INV_TIME );
+ static const TransitionMap table(makeTable());
+ if (needsNoResponse(status)) {
+ return state();
+ }
+
+ using namespace GpgSignKeyEditInteractor_Private;
+
+ //lookup transition in map
+ const TransitionMap::const_iterator it = table.find(boost::make_tuple(static_cast<SignKeyState>(state()), status, std::string(args)));
+ if (it != table.end()) {
+ return it->second;
+ }
+
+ //handle cases that cannot be handled via the map
+ switch (const unsigned int st = state()) {
+ case UIDS_ANSWER_SIGN_ALL:
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keyedit.prompt") == 0) {
+ if (!d->signAll()) {
+ return UIDS_LIST_SEPARATELY;
+ }
+ err = Error::fromCode(GPG_ERR_UNUSABLE_PUBKEY);
+ return ERROR;
+ }
+ break;
+ default:
+ if (st >= UIDS_LIST_SEPARATELY && st < UIDS_LIST_SEPARATELY_DONE) {
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keyedit.prompt") == 0) {
+ return d->allUserIDsListed() ? UIDS_LIST_SEPARATELY_DONE : st + 1 ;
+ }
+ }
+ break;
+ case CONFIRM:
+ case ERROR:
+ err = lastError();
+ return ERROR;
+ }
+
+ err = GENERAL_ERROR;
+ return ERROR;
+}
+
+void GpgSignKeyEditInteractor::setCheckLevel(unsigned int checkLevel)
+{
+ assert(!d->started);
+ assert(checkLevel <= 3);
+ d->checkLevel = checkLevel;
+}
+
+void GpgSignKeyEditInteractor::setUserIDsToSign(const std::vector<unsigned int> &userIDsToSign)
+{
+ assert(!d->started);
+ d->userIDs = userIDsToSign;
+ d->nextId = d->userIDs.begin();
+ d->currentId = d->userIDs.end();
+
+}
+void GpgSignKeyEditInteractor::setSigningOptions(int options)
+{
+ assert(!d->started);
+ d->options = options;
+}
diff --git a/lang/cpp/src/gpgsignkeyeditinteractor.h b/lang/cpp/src/gpgsignkeyeditinteractor.h
new file mode 100644
index 0000000..47ff8e5
--- /dev/null
+++ b/lang/cpp/src/gpgsignkeyeditinteractor.h
@@ -0,0 +1,64 @@
+/*
+ gpgsignkeyeditinteractor.h - Edit Interactor to change the owner trust of an OpenPGP key
+ Copyright (C) 2008 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_GPGSIGNKEYEDITINTERACTOR_H__
+#define __GPGMEPP_GPGSIGNKEYEDITINTERACTOR_H__
+
+#include <editinteractor.h>
+
+#include <string>
+#include <vector>
+
+namespace GpgME
+{
+
+class Key;
+class UserID;
+
+class GPGMEPP_EXPORT GpgSignKeyEditInteractor : public EditInteractor
+{
+public:
+ enum SignOption {
+ Exportable = 0x1,
+ NonRevocable = 0x2,
+ Trust = 0x4
+ };
+
+ GpgSignKeyEditInteractor();
+ ~GpgSignKeyEditInteractor();
+
+ void setCheckLevel(unsigned int checkLevel);
+ void setUserIDsToSign(const std::vector<unsigned int> &userIDsToSign);
+ void setSigningOptions(int options);
+
+private:
+ /* reimp */ const char *action(Error &err) const;
+ /* reimp */ unsigned int nextState(unsigned int statusCode, const char *args, Error &err) const;
+
+private:
+ class Private;
+ Private *const d;
+};
+
+} // namespace GpgME
+
+#endif // __GPGMEPP_GPGSIGNKEYEDITINTERACTOR_H__
diff --git a/lang/cpp/src/importresult.cpp b/lang/cpp/src/importresult.cpp
new file mode 100644
index 0000000..bd989d2
--- /dev/null
+++ b/lang/cpp/src/importresult.cpp
@@ -0,0 +1,216 @@
+/*
+ importresult.cpp - wraps a gpgme import result
+ Copyright (C) 2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <config-gpgme++.h>
+
+#include <importresult.h>
+#include "result_p.h"
+
+#include <gpgme.h>
+#include <cstdlib>
+#include <cstring>
+
+#include <string.h>
+
+class GpgME::ImportResult::Private
+{
+public:
+ Private(const _gpgme_op_import_result &r) : res(r)
+ {
+ // copy recursively, using compiler-generated copy ctor.
+ // We just need to handle the pointers in the structs:
+ for (gpgme_import_status_t is = r.imports ; is ; is = is->next) {
+ gpgme_import_status_t copy = new _gpgme_import_status(*is);
+ copy->fpr = strdup(is->fpr);
+ copy->next = 0;
+ imports.push_back(copy);
+ }
+ res.imports = 0;
+ }
+ ~Private()
+ {
+ for (std::vector<gpgme_import_status_t>::iterator it = imports.begin() ; it != imports.end() ; ++it) {
+ std::free((*it)->fpr);
+ delete *it; *it = 0;
+ }
+ }
+
+ _gpgme_op_import_result res;
+ std::vector<gpgme_import_status_t> imports;
+};
+
+GpgME::ImportResult::ImportResult(gpgme_ctx_t ctx, int error)
+ : GpgME::Result(error), d()
+{
+ init(ctx);
+}
+
+GpgME::ImportResult::ImportResult(gpgme_ctx_t ctx, const Error &error)
+ : GpgME::Result(error), d()
+{
+ init(ctx);
+}
+
+void GpgME::ImportResult::init(gpgme_ctx_t ctx)
+{
+ if (!ctx) {
+ return;
+ }
+ gpgme_import_result_t res = gpgme_op_import_result(ctx);
+ if (!res) {
+ return;
+ }
+ d.reset(new Private(*res));
+}
+
+make_standard_stuff(ImportResult)
+
+int GpgME::ImportResult::numConsidered() const
+{
+ return d ? d->res.considered : 0 ;
+}
+
+int GpgME::ImportResult::numKeysWithoutUserID() const
+{
+ return d ? d->res.no_user_id : 0 ;
+}
+
+int GpgME::ImportResult::numImported() const
+{
+ return d ? d->res.imported : 0 ;
+}
+
+int GpgME::ImportResult::numRSAImported() const
+{
+ return d ? d->res.imported_rsa : 0 ;
+}
+
+int GpgME::ImportResult::numUnchanged() const
+{
+ return d ? d->res.unchanged : 0 ;
+}
+
+int GpgME::ImportResult::newUserIDs() const
+{
+ return d ? d->res.new_user_ids : 0 ;
+}
+
+int GpgME::ImportResult::newSubkeys() const
+{
+ return d ? d->res.new_sub_keys : 0 ;
+}
+
+int GpgME::ImportResult::newSignatures() const
+{
+ return d ? d->res.new_signatures : 0 ;
+}
+
+int GpgME::ImportResult::newRevocations() const
+{
+ return d ? d->res.new_revocations : 0 ;
+}
+
+int GpgME::ImportResult::numSecretKeysConsidered() const
+{
+ return d ? d->res.secret_read : 0 ;
+}
+
+int GpgME::ImportResult::numSecretKeysImported() const
+{
+ return d ? d->res.secret_imported : 0 ;
+}
+
+int GpgME::ImportResult::numSecretKeysUnchanged() const
+{
+ return d ? d->res.secret_unchanged : 0 ;
+}
+
+int GpgME::ImportResult::notImported() const
+{
+ return d ? d->res.not_imported : 0 ;
+}
+
+GpgME::Import GpgME::ImportResult::import(unsigned int idx) const
+{
+ return Import(d, idx);
+}
+
+std::vector<GpgME::Import> GpgME::ImportResult::imports() const
+{
+ if (!d) {
+ return std::vector<Import>();
+ }
+ std::vector<Import> result;
+ result.reserve(d->imports.size());
+ for (unsigned int i = 0 ; i < d->imports.size() ; ++i) {
+ result.push_back(Import(d, i));
+ }
+ return result;
+}
+
+GpgME::Import::Import(const boost::shared_ptr<ImportResult::Private> &parent, unsigned int i)
+ : d(parent), idx(i)
+{
+
+}
+
+GpgME::Import::Import() : d(), idx(0) {}
+
+bool GpgME::Import::isNull() const
+{
+ return !d || idx >= d->imports.size() ;
+}
+
+const char *GpgME::Import::fingerprint() const
+{
+ return isNull() ? 0 : d->imports[idx]->fpr ;
+}
+
+GpgME::Error GpgME::Import::error() const
+{
+ return Error(isNull() ? 0 : d->imports[idx]->result);
+}
+
+GpgME::Import::Status GpgME::Import::status() const
+{
+ if (isNull()) {
+ return Unknown;
+ }
+ const unsigned int s = d->imports[idx]->status;
+ unsigned int result = Unknown;
+ if (s & GPGME_IMPORT_NEW) {
+ result |= NewKey;
+ }
+ if (s & GPGME_IMPORT_UID) {
+ result |= NewUserIDs;
+ }
+ if (s & GPGME_IMPORT_SIG) {
+ result |= NewSignatures;
+ }
+ if (s & GPGME_IMPORT_SUBKEY) {
+ result |= NewSubkeys;
+ }
+ if (s & GPGME_IMPORT_SECRET) {
+ result |= ContainedSecretKey;
+ }
+ return static_cast<Status>(result);
+}
diff --git a/lang/cpp/src/importresult.h b/lang/cpp/src/importresult.h
new file mode 100644
index 0000000..7dc0320
--- /dev/null
+++ b/lang/cpp/src/importresult.h
@@ -0,0 +1,134 @@
+/*
+ importresult.h - wraps a gpgme import result
+ Copyright (C) 2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_IMPORTRESULT_H__
+#define __GPGMEPP_IMPORTRESULT_H__
+
+#include "gpgmefw.h"
+#include "result.h"
+#include "gpgmepp_export.h"
+
+#include <boost/shared_ptr.hpp>
+
+#include <vector>
+
+namespace GpgME
+{
+
+class Error;
+class Import;
+
+class GPGMEPP_EXPORT ImportResult : public Result
+{
+public:
+ ImportResult();
+ ImportResult(gpgme_ctx_t ctx, int error);
+ ImportResult(gpgme_ctx_t ctx, const Error &error);
+ explicit ImportResult(const Error &error);
+
+ const ImportResult &operator=(ImportResult other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(ImportResult &other)
+ {
+ Result::swap(other);
+ using std::swap;
+ swap(this->d, other.d);
+ }
+
+ bool isNull() const;
+
+ int numConsidered() const;
+ int numKeysWithoutUserID() const;
+ int numImported() const;
+ int numRSAImported() const;
+ int numUnchanged() const;
+
+ int newUserIDs() const;
+ int newSubkeys() const;
+ int newSignatures() const;
+ int newRevocations() const;
+
+ int numSecretKeysConsidered() const;
+ int numSecretKeysImported() const;
+ int numSecretKeysUnchanged() const;
+
+ int notImported() const;
+
+ Import import(unsigned int idx) const;
+ std::vector<Import> imports() const;
+
+ class Private;
+private:
+ void init(gpgme_ctx_t ctx);
+ boost::shared_ptr<Private> d;
+};
+
+class GPGMEPP_EXPORT Import
+{
+ friend class ::GpgME::ImportResult;
+ Import(const boost::shared_ptr<ImportResult::Private> &parent, unsigned int idx);
+public:
+ Import();
+
+ const Import &operator=(Import other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(Import &other)
+ {
+ using std::swap;
+ swap(this->d, other.d);
+ swap(this->idx, other.idx);
+ }
+
+ bool isNull() const;
+
+ const char *fingerprint() const;
+ Error error() const;
+
+ enum Status {
+ Unknown = 0x0,
+ NewKey = 0x1,
+ NewUserIDs = 0x2,
+ NewSignatures = 0x4,
+ NewSubkeys = 0x8,
+ ContainedSecretKey = 0x10
+ };
+ Status status() const;
+
+private:
+ boost::shared_ptr<ImportResult::Private> d;
+ unsigned int idx;
+};
+
+}
+
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(ImportResult)
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(Import)
+
+#endif // __GPGMEPP_IMPORTRESULT_H__
diff --git a/lang/cpp/src/interfaces/assuantransaction.h b/lang/cpp/src/interfaces/assuantransaction.h
new file mode 100644
index 0000000..9acdf7d
--- /dev/null
+++ b/lang/cpp/src/interfaces/assuantransaction.h
@@ -0,0 +1,47 @@
+/*
+ assuantransaction.h - Interface for ASSUAN transactions
+ Copyright (C) 2009 Klarälvdalens Datakonsult AB <info at kdab.com>
+ Author: Marc Mutz <marc at kdab.com>
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_INTERFACES_ASSUANTRANSACTION_H__
+#define __GPGMEPP_INTERFACES_ASSUANTRANSACTION_H__
+
+#include "gpgmepp_export.h"
+
+namespace GpgME
+{
+
+class Error;
+class Data;
+
+class GPGMEPP_EXPORT AssuanTransaction
+{
+public:
+ virtual ~AssuanTransaction() {}
+
+ virtual Error data(const char *data, size_t datalen) = 0;
+ virtual Data inquire(const char *name, const char *args, Error &err) = 0;
+ virtual Error status(const char *status, const char *args) = 0;
+};
+
+} // namespace GpgME
+
+#endif // __GPGMEPP_INTERFACES_ASSUANTRANSACTION_H__
diff --git a/lang/cpp/src/interfaces/dataprovider.h b/lang/cpp/src/interfaces/dataprovider.h
new file mode 100644
index 0000000..166bb4e
--- /dev/null
+++ b/lang/cpp/src/interfaces/dataprovider.h
@@ -0,0 +1,53 @@
+/*
+ interface/dataprovider.h - Interface for data sources
+ Copyright (C) 2003 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_INTERFACES_DATAPROVIDER_H__
+#define __GPGMEPP_INTERFACES_DATAPROVIDER_H__
+
+#include <sys/types.h>
+
+#include "gpgmepp_export.h"
+
+#include <gpg-error.h>
+
+namespace GpgME
+{
+
+class GPGMEPP_EXPORT DataProvider
+{
+public:
+ virtual ~DataProvider() {}
+
+ enum Operation {
+ Read, Write, Seek, Release
+ };
+ virtual bool isSupported(Operation op) const = 0;
+
+ virtual ssize_t read(void *buffer, size_t bufSize) = 0;
+ virtual ssize_t write(const void *buffer, size_t bufSize) = 0;
+ virtual off_t seek(off_t offset, int whence) = 0;
+ virtual void release() = 0;
+};
+
+} // namespace GpgME
+
+#endif // __GPGMEPP_INTERFACES_DATAPROVIDER_H__
diff --git a/lang/cpp/src/interfaces/passphraseprovider.h b/lang/cpp/src/interfaces/passphraseprovider.h
new file mode 100644
index 0000000..5275e44
--- /dev/null
+++ b/lang/cpp/src/interfaces/passphraseprovider.h
@@ -0,0 +1,40 @@
+/*
+ interface/passphraseprovider.h - Interface for passphrase callbacks
+ Copyright (C) 2003,2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_INTERFACES_PASSPHRASEPROVIDER_H__
+#define __GPGMEPP_INTERFACES_PASSPHRASEPROVIDER_H__
+
+namespace GpgME
+{
+
+class PassphraseProvider
+{
+public:
+ virtual ~PassphraseProvider() {}
+
+ virtual char *getPassphrase(const char *useridHint, const char *description,
+ bool previousWasBad, bool &canceled) = 0;
+};
+
+} // namespace GpgME
+
+#endif // __GPGMEPP_INTERFACES_PASSPHRASEPROVIDER_H__
diff --git a/lang/cpp/src/interfaces/progressprovider.h b/lang/cpp/src/interfaces/progressprovider.h
new file mode 100644
index 0000000..78bbdd7
--- /dev/null
+++ b/lang/cpp/src/interfaces/progressprovider.h
@@ -0,0 +1,40 @@
+/*
+ interface/progressprovider.h - Interface for progress reports
+ Copyright (C) 2003 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_INTERFACES_PROGRESSPROVIDER_H__
+#define __GPGMEPP_INTERFACES_PROGRESSPROVIDER_H__
+
+namespace GpgME
+{
+
+class ProgressProvider
+{
+public:
+ virtual ~ProgressProvider() {}
+
+ virtual void showProgress(const char *what, int type,
+ int current, int total) = 0;
+};
+
+} // namespace GpgME
+
+#endif // __GPGMEPP_INTERFACES_PROGRESSPROVIDER_H__
diff --git a/lang/cpp/src/key.cpp b/lang/cpp/src/key.cpp
new file mode 100644
index 0000000..5eadbdd
--- /dev/null
+++ b/lang/cpp/src/key.cpp
@@ -0,0 +1,847 @@
+/*
+ key.cpp - wraps a gpgme key
+ Copyright (C) 2003, 2005 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "config-gpgme++.h"
+
+#include <key.h>
+
+#include "util.h"
+
+#include <gpgme.h>
+
+#include <string.h>
+
+const GpgME::Key::Null GpgME::Key::null;
+
+namespace GpgME
+{
+
+Key::Key() : key() {}
+
+Key::Key(const Null &) : key() {}
+
+Key::Key(const shared_gpgme_key_t &k) : key(k) {}
+
+Key::Key(gpgme_key_t k, bool ref)
+ : key(k
+ ? shared_gpgme_key_t(k, &gpgme_key_unref)
+ : shared_gpgme_key_t())
+{
+ if (ref && impl()) {
+ gpgme_key_ref(impl());
+ }
+}
+
+UserID Key::userID(unsigned int index) const
+{
+ return UserID(key, index);
+}
+
+Subkey Key::subkey(unsigned int index) const
+{
+ return Subkey(key, index);
+}
+
+unsigned int Key::numUserIDs() const
+{
+ if (!key) {
+ return 0;
+ }
+ unsigned int count = 0;
+ for (gpgme_user_id_t uid = key->uids ; uid ; uid = uid->next) {
+ ++count;
+ }
+ return count;
+}
+
+unsigned int Key::numSubkeys() const
+{
+ if (!key) {
+ return 0;
+ }
+ unsigned int count = 0;
+ for (gpgme_sub_key_t subkey = key->subkeys ; subkey ; subkey = subkey->next) {
+ ++count;
+ }
+ return count;
+}
+
+std::vector<UserID> Key::userIDs() const
+{
+ if (!key) {
+ return std::vector<UserID>();
+ }
+
+ std::vector<UserID> v;
+ v.reserve(numUserIDs());
+ for (gpgme_user_id_t uid = key->uids ; uid ; uid = uid->next) {
+ v.push_back(UserID(key, uid));
+ }
+ return v;
+}
+
+std::vector<Subkey> Key::subkeys() const
+{
+ if (!key) {
+ return std::vector<Subkey>();
+ }
+
+ std::vector<Subkey> v;
+ v.reserve(numSubkeys());
+ for (gpgme_sub_key_t subkey = key->subkeys ; subkey ; subkey = subkey->next) {
+ v.push_back(Subkey(key, subkey));
+ }
+ return v;
+}
+
+Key::OwnerTrust Key::ownerTrust() const
+{
+ if (!key) {
+ return Unknown;
+ }
+ switch (key->owner_trust) {
+ default:
+ case GPGME_VALIDITY_UNKNOWN: return Unknown;
+ case GPGME_VALIDITY_UNDEFINED: return Undefined;
+ case GPGME_VALIDITY_NEVER: return Never;
+ case GPGME_VALIDITY_MARGINAL: return Marginal;
+ case GPGME_VALIDITY_FULL: return Full;
+ case GPGME_VALIDITY_ULTIMATE: return Ultimate;
+ }
+}
+char Key::ownerTrustAsString() const
+{
+ if (!key) {
+ return '?';
+ }
+ switch (key->owner_trust) {
+ default:
+ case GPGME_VALIDITY_UNKNOWN: return '?';
+ case GPGME_VALIDITY_UNDEFINED: return 'q';
+ case GPGME_VALIDITY_NEVER: return 'n';
+ case GPGME_VALIDITY_MARGINAL: return 'm';
+ case GPGME_VALIDITY_FULL: return 'f';
+ case GPGME_VALIDITY_ULTIMATE: return 'u';
+ }
+}
+
+Protocol Key::protocol() const
+{
+ if (!key) {
+ return UnknownProtocol;
+ }
+ switch (key->protocol) {
+ case GPGME_PROTOCOL_CMS: return CMS;
+ case GPGME_PROTOCOL_OpenPGP: return OpenPGP;
+ default: return UnknownProtocol;
+ }
+}
+
+const char *Key::protocolAsString() const
+{
+ return key ? gpgme_get_protocol_name(key->protocol) : 0 ;
+}
+
+bool Key::isRevoked() const
+{
+ return key && key->revoked;
+}
+
+bool Key::isExpired() const
+{
+ return key && key->expired;
+}
+
+bool Key::isDisabled() const
+{
+ return key && key->disabled;
+}
+
+bool Key::isInvalid() const
+{
+ return key && key->invalid;
+}
+
+bool Key::hasSecret() const
+{
+ return key && key->secret;
+}
+
+bool Key::isRoot() const
+{
+ return key && key->subkeys && key->subkeys->fpr && key->chain_id &&
+ strcasecmp(key->subkeys->fpr, key->chain_id) == 0;
+}
+
+bool Key::canEncrypt() const
+{
+ return key && key->can_encrypt;
+}
+
+bool Key::canSign() const
+{
+#ifndef GPGME_CAN_SIGN_ON_SECRET_OPENPGP_KEYLISTING_NOT_BROKEN
+ if (key && key->protocol == GPGME_PROTOCOL_OpenPGP) {
+ return true;
+ }
+#endif
+ return canReallySign();
+}
+
+bool Key::canReallySign() const
+{
+ return key && key->can_sign;
+}
+
+bool Key::canCertify() const
+{
+ return key && key->can_certify;
+}
+
+bool Key::canAuthenticate() const
+{
+ return key && key->can_authenticate;
+}
+
+bool Key::isQualified() const
+{
+#ifdef HAVE_GPGME_KEY_T_IS_QUALIFIED
+ return key && key->is_qualified;
+#else
+ return false;
+#endif
+}
+
+const char *Key::issuerSerial() const
+{
+ return key ? key->issuer_serial : 0 ;
+}
+const char *Key::issuerName() const
+{
+ return key ? key->issuer_name : 0 ;
+}
+const char *Key::chainID() const
+{
+ return key ? key->chain_id : 0 ;
+}
+
+const char *Key::keyID() const
+{
+ return key && key->subkeys ? key->subkeys->keyid : 0 ;
+}
+
+const char *Key::shortKeyID() const
+{
+ if (!key || !key->subkeys || !key->subkeys->keyid) {
+ return 0;
+ }
+ const int len = strlen(key->subkeys->keyid);
+ if (len > 8) {
+ return key->subkeys->keyid + len - 8; // return the last 8 bytes (in hex notation)
+ } else {
+ return key->subkeys->keyid;
+ }
+}
+
+const char *Key::primaryFingerprint() const
+{
+ const char *fpr = key && key->subkeys ? key->subkeys->fpr : 0 ;
+ if (fpr) {
+ return fpr;
+ } else {
+ return keyID();
+ }
+}
+
+unsigned int Key::keyListMode() const
+{
+ return key ? convert_from_gpgme_keylist_mode_t(key->keylist_mode) : 0 ;
+}
+
+const Key &Key::mergeWith(const Key &other)
+{
+ // ### incomplete. Just merges has* and can*, nothing else atm
+ // ### detach also missing
+
+ if (!this->primaryFingerprint() ||
+ !other.primaryFingerprint() ||
+ strcasecmp(this->primaryFingerprint(), other.primaryFingerprint()) != 0) {
+ return *this; // only merge the Key object which describe the same key
+ }
+
+ const gpgme_key_t me = impl();
+ const gpgme_key_t him = other.impl();
+
+ if (!me || !him) {
+ return *this;
+ }
+
+ me->revoked |= him->revoked;
+ me->expired |= him->expired;
+ me->disabled |= him->disabled;
+ me->invalid |= him->invalid;
+ me->can_encrypt |= him->can_encrypt;
+ me->can_sign |= him->can_sign;
+ me->can_certify |= him->can_certify;
+ me->secret |= him->secret;
+ me->can_authenticate |= him->can_authenticate;
+#ifdef HAVE_GPGME_KEY_T_IS_QUALIFIED
+ me->is_qualified |= him->is_qualified;
+#endif
+ me->keylist_mode |= him->keylist_mode;
+
+#ifdef HAVE_GPGME_SUBKEY_T_IS_CARDKEY
+ // make sure the gpgme_sub_key_t::is_cardkey flag isn't lost:
+ for (gpgme_sub_key_t mysk = me->subkeys ; mysk ; mysk = mysk->next) {
+ for (gpgme_sub_key_t hissk = him->subkeys ; hissk ; hissk = hissk->next) {
+ if (strcmp(mysk->fpr, hissk->fpr) == 0) {
+ mysk->is_cardkey |= hissk->is_cardkey;
+ break;
+ }
+ }
+ }
+#endif
+
+ return *this;
+}
+
+//
+//
+// class Subkey
+//
+//
+
+gpgme_sub_key_t find_subkey(const shared_gpgme_key_t &key, unsigned int idx)
+{
+ if (key) {
+ for (gpgme_sub_key_t s = key->subkeys ; s ; s = s->next, --idx) {
+ if (idx == 0) {
+ return s;
+ }
+ }
+ }
+ return 0;
+}
+
+gpgme_sub_key_t verify_subkey(const shared_gpgme_key_t &key, gpgme_sub_key_t subkey)
+{
+ if (key) {
+ for (gpgme_sub_key_t s = key->subkeys ; s ; s = s->next) {
+ if (s == subkey) {
+ return subkey;
+ }
+ }
+ }
+ return 0;
+}
+
+Subkey::Subkey() : key(), subkey(0) {}
+
+Subkey::Subkey(const shared_gpgme_key_t &k, unsigned int idx)
+ : key(k), subkey(find_subkey(k, idx))
+{
+
+}
+
+Subkey::Subkey(const shared_gpgme_key_t &k, gpgme_sub_key_t sk)
+ : key(k), subkey(verify_subkey(k, sk))
+{
+
+}
+
+Key Subkey::parent() const
+{
+ return Key(key);
+}
+
+const char *Subkey::keyID() const
+{
+ return subkey ? subkey->keyid : 0 ;
+}
+
+const char *Subkey::fingerprint() const
+{
+ return subkey ? subkey->fpr : 0 ;
+}
+
+unsigned int Subkey::publicKeyAlgorithm() const
+{
+ return subkey ? subkey->pubkey_algo : 0 ;
+}
+
+const char *Subkey::publicKeyAlgorithmAsString() const
+{
+ return gpgme_pubkey_algo_name(subkey ? subkey->pubkey_algo : (gpgme_pubkey_algo_t)0);
+}
+
+bool Subkey::canEncrypt() const
+{
+ return subkey && subkey->can_encrypt;
+}
+
+bool Subkey::canSign() const
+{
+ return subkey && subkey->can_sign;
+}
+
+bool Subkey::canCertify() const
+{
+ return subkey && subkey->can_certify;
+}
+
+bool Subkey::canAuthenticate() const
+{
+ return subkey && subkey->can_authenticate;
+}
+
+bool Subkey::isQualified() const
+{
+#ifdef HAVE_GPGME_SUBKEY_T_IS_QUALIFIED
+ return subkey && subkey->is_qualified;
+#else
+ return false;
+#endif
+}
+
+bool Subkey::isCardKey() const
+{
+#ifdef HAVE_GPGME_SUBKEY_T_IS_CARDKEY
+ return subkey && subkey->is_cardkey;
+#else
+ return false;
+#endif
+}
+
+const char *Subkey::cardSerialNumber() const
+{
+#ifdef HAVE_GPGME_SUBKEY_T_IS_CARDKEY
+ return subkey ? subkey->card_number : 0 ;
+#else
+ return 0;
+#endif
+}
+
+bool Subkey::isSecret() const
+{
+ return subkey && subkey->secret;
+}
+
+unsigned int Subkey::length() const
+{
+ return subkey ? subkey->length : 0 ;
+}
+
+time_t Subkey::creationTime() const
+{
+ return static_cast<time_t>(subkey ? subkey->timestamp : 0);
+}
+
+time_t Subkey::expirationTime() const
+{
+ return static_cast<time_t>(subkey ? subkey->expires : 0);
+}
+
+bool Subkey::neverExpires() const
+{
+ return expirationTime() == time_t(0);
+}
+
+bool Subkey::isRevoked() const
+{
+ return subkey && subkey->revoked;
+}
+
+bool Subkey::isInvalid() const
+{
+ return subkey && subkey->invalid;
+}
+
+bool Subkey::isExpired() const
+{
+ return subkey && subkey->expired;
+}
+
+bool Subkey::isDisabled() const
+{
+ return subkey && subkey->disabled;
+}
+
+//
+//
+// class UserID
+//
+//
+
+gpgme_user_id_t find_uid(const shared_gpgme_key_t &key, unsigned int idx)
+{
+ if (key) {
+ for (gpgme_user_id_t u = key->uids ; u ; u = u->next, --idx) {
+ if (idx == 0) {
+ return u;
+ }
+ }
+ }
+ return 0;
+}
+
+gpgme_user_id_t verify_uid(const shared_gpgme_key_t &key, gpgme_user_id_t uid)
+{
+ if (key) {
+ for (gpgme_user_id_t u = key->uids ; u ; u = u->next) {
+ if (u == uid) {
+ return uid;
+ }
+ }
+ }
+ return 0;
+}
+
+UserID::UserID() : key(), uid(0) {}
+
+UserID::UserID(const shared_gpgme_key_t &k, gpgme_user_id_t u)
+ : key(k), uid(verify_uid(k, u))
+{
+
+}
+
+UserID::UserID(const shared_gpgme_key_t &k, unsigned int idx)
+ : key(k), uid(find_uid(k, idx))
+{
+
+}
+
+Key UserID::parent() const
+{
+ return Key(key);
+}
+
+UserID::Signature UserID::signature(unsigned int index) const
+{
+ return Signature(key, uid, index);
+}
+
+unsigned int UserID::numSignatures() const
+{
+ if (!uid) {
+ return 0;
+ }
+ unsigned int count = 0;
+ for (gpgme_key_sig_t sig = uid->signatures ; sig ; sig = sig->next) {
+ ++count;
+ }
+ return count;
+}
+
+std::vector<UserID::Signature> UserID::signatures() const
+{
+ if (!uid) {
+ return std::vector<Signature>();
+ }
+
+ std::vector<Signature> v;
+ v.reserve(numSignatures());
+ for (gpgme_key_sig_t sig = uid->signatures ; sig ; sig = sig->next) {
+ v.push_back(Signature(key, uid, sig));
+ }
+ return v;
+}
+
+const char *UserID::id() const
+{
+ return uid ? uid->uid : 0 ;
+}
+
+const char *UserID::name() const
+{
+ return uid ? uid->name : 0 ;
+}
+
+const char *UserID::email() const
+{
+ return uid ? uid->email : 0 ;
+}
+
+const char *UserID::comment() const
+{
+ return uid ? uid->comment : 0 ;
+}
+
+UserID::Validity UserID::validity() const
+{
+ if (!uid) {
+ return Unknown;
+ }
+ switch (uid->validity) {
+ default:
+ case GPGME_VALIDITY_UNKNOWN: return Unknown;
+ case GPGME_VALIDITY_UNDEFINED: return Undefined;
+ case GPGME_VALIDITY_NEVER: return Never;
+ case GPGME_VALIDITY_MARGINAL: return Marginal;
+ case GPGME_VALIDITY_FULL: return Full;
+ case GPGME_VALIDITY_ULTIMATE: return Ultimate;
+ }
+}
+
+char UserID::validityAsString() const
+{
+ if (!uid) {
+ return '?';
+ }
+ switch (uid->validity) {
+ default:
+ case GPGME_VALIDITY_UNKNOWN: return '?';
+ case GPGME_VALIDITY_UNDEFINED: return 'q';
+ case GPGME_VALIDITY_NEVER: return 'n';
+ case GPGME_VALIDITY_MARGINAL: return 'm';
+ case GPGME_VALIDITY_FULL: return 'f';
+ case GPGME_VALIDITY_ULTIMATE: return 'u';
+ }
+}
+
+bool UserID::isRevoked() const
+{
+ return uid && uid->revoked;
+}
+
+bool UserID::isInvalid() const
+{
+ return uid && uid->invalid;
+}
+
+//
+//
+// class Signature
+//
+//
+
+gpgme_key_sig_t find_signature(gpgme_user_id_t uid, unsigned int idx)
+{
+ if (uid) {
+ for (gpgme_key_sig_t s = uid->signatures ; s ; s = s->next, --idx) {
+ if (idx == 0) {
+ return s;
+ }
+ }
+ }
+ return 0;
+}
+
+gpgme_key_sig_t verify_signature(gpgme_user_id_t uid, gpgme_key_sig_t sig)
+{
+ if (uid) {
+ for (gpgme_key_sig_t s = uid->signatures ; s ; s = s->next) {
+ if (s == sig) {
+ return sig;
+ }
+ }
+ }
+ return 0;
+}
+
+UserID::Signature::Signature() : key(), uid(0), sig(0) {}
+
+UserID::Signature::Signature(const shared_gpgme_key_t &k, gpgme_user_id_t u, unsigned int idx)
+ : key(k), uid(verify_uid(k, u)), sig(find_signature(uid, idx))
+{
+
+}
+
+UserID::Signature::Signature(const shared_gpgme_key_t &k, gpgme_user_id_t u, gpgme_key_sig_t s)
+ : key(k), uid(verify_uid(k, u)), sig(verify_signature(uid, s))
+{
+
+}
+
+UserID UserID::Signature::parent() const
+{
+ return UserID(key, uid);
+}
+
+const char *UserID::Signature::signerKeyID() const
+{
+ return sig ? sig->keyid : 0 ;
+}
+
+const char *UserID::Signature::algorithmAsString() const
+{
+ return gpgme_pubkey_algo_name(sig ? sig->pubkey_algo : (gpgme_pubkey_algo_t)0);
+}
+
+unsigned int UserID::Signature::algorithm() const
+{
+ return sig ? sig->pubkey_algo : 0 ;
+}
+
+time_t UserID::Signature::creationTime() const
+{
+ return static_cast<time_t>(sig ? sig->timestamp : 0);
+}
+
+time_t UserID::Signature::expirationTime() const
+{
+ return static_cast<time_t>(sig ? sig->expires : 0);
+}
+
+bool UserID::Signature::neverExpires() const
+{
+ return expirationTime() == time_t(0);
+}
+
+bool UserID::Signature::isRevokation() const
+{
+ return sig && sig->revoked;
+}
+
+bool UserID::Signature::isInvalid() const
+{
+ return sig && sig->invalid;
+}
+
+bool UserID::Signature::isExpired() const
+{
+ return sig && sig->expired;
+}
+
+bool UserID::Signature::isExportable() const
+{
+ return sig && sig->exportable;
+}
+
+const char *UserID::Signature::signerUserID() const
+{
+ return sig ? sig->uid : 0 ;
+}
+
+const char *UserID::Signature::signerName() const
+{
+ return sig ? sig->name : 0 ;
+}
+
+const char *UserID::Signature::signerEmail() const
+{
+ return sig ? sig->email : 0 ;
+}
+
+const char *UserID::Signature::signerComment() const
+{
+ return sig ? sig->comment : 0 ;
+}
+
+unsigned int UserID::Signature::certClass() const
+{
+ return sig ? sig->sig_class : 0 ;
+}
+
+UserID::Signature::Status UserID::Signature::status() const
+{
+ if (!sig) {
+ return GeneralError;
+ }
+
+ switch (gpgme_err_code(sig->status)) {
+ case GPG_ERR_NO_ERROR: return NoError;
+ case GPG_ERR_SIG_EXPIRED: return SigExpired;
+ case GPG_ERR_KEY_EXPIRED: return KeyExpired;
+ case GPG_ERR_BAD_SIGNATURE: return BadSignature;
+ case GPG_ERR_NO_PUBKEY: return NoPublicKey;
+ default:
+ case GPG_ERR_GENERAL: return GeneralError;
+ }
+}
+
+std::string UserID::Signature::statusAsString() const
+{
+ if (!sig) {
+ return std::string();
+ }
+ char buf[ 1024 ];
+ gpgme_strerror_r(sig->status, buf, sizeof buf);
+ buf[ sizeof buf - 1 ] = '\0';
+ return std::string(buf);
+}
+
+GpgME::Notation UserID::Signature::notation(unsigned int idx) const
+{
+ if (!sig) {
+ return GpgME::Notation();
+ }
+#ifdef HAVE_GPGME_KEY_SIG_NOTATIONS
+ for (gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next) {
+ if (nota->name) {
+ if (idx-- == 0) {
+ return GpgME::Notation(nota);
+ }
+ }
+ }
+#endif
+ return GpgME::Notation();
+}
+
+unsigned int UserID::Signature::numNotations() const
+{
+ if (!sig) {
+ return 0;
+ }
+ unsigned int count = 0;
+#ifdef HAVE_GPGME_KEY_SIG_NOTATIONS
+ for (gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next) {
+ if (nota->name) {
+ ++count; // others are policy URLs...
+ }
+ }
+#endif
+ return count;
+}
+
+std::vector<Notation> UserID::Signature::notations() const
+{
+ if (!sig) {
+ return std::vector<GpgME::Notation>();
+ }
+ std::vector<GpgME::Notation> v;
+#ifdef HAVE_GPGME_KEY_SIG_NOTATIONS
+ v.reserve(numNotations());
+ for (gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next) {
+ if (nota->name) {
+ v.push_back(GpgME::Notation(nota));
+ }
+ }
+#endif
+ return v;
+}
+
+const char *UserID::Signature::policyURL() const
+{
+#ifdef HAVE_GPGME_KEY_SIG_NOTATIONS
+ if (!sig) {
+ return 0;
+ }
+ for (gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next) {
+ if (!nota->name) {
+ return nota->value;
+ }
+ }
+#endif
+ return 0;
+}
+
+} // namespace GpgME
diff --git a/lang/cpp/src/key.h b/lang/cpp/src/key.h
new file mode 100644
index 0000000..80bf4d1
--- /dev/null
+++ b/lang/cpp/src/key.h
@@ -0,0 +1,358 @@
+/*
+ key.h - wraps a gpgme key
+ Copyright (C) 2003, 2005 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+// -*- c++ -*-
+#ifndef __GPGMEPP_KEY_H__
+#define __GPGMEPP_KEY_H__
+
+#include "global.h"
+#include "notation.h"
+
+#include "gpgmefw.h"
+
+#include <boost/shared_ptr.hpp>
+#include <boost/type_traits/remove_pointer.hpp>
+
+#include <sys/time.h>
+
+#include <vector>
+#include <algorithm>
+#include <string>
+
+namespace GpgME
+{
+
+class Context;
+
+class Subkey;
+class UserID;
+
+typedef boost::shared_ptr< boost::remove_pointer<gpgme_key_t>::type > shared_gpgme_key_t;
+
+//
+// class Key
+//
+
+class GPGMEPP_EXPORT Key
+{
+ friend class ::GpgME::Context;
+ struct Null {
+ Null() {}
+ };
+public:
+ Key();
+ /* implicit */ Key(const Null &);
+ Key(const shared_gpgme_key_t &key);
+ Key(gpgme_key_t key, bool acquireRef);
+
+ static const Null null;
+
+ const Key &operator=(Key other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ const Key &mergeWith(const Key &other);
+
+ void swap(Key &other)
+ {
+ using std::swap;
+ swap(this->key, other.key);
+ }
+
+ bool isNull() const
+ {
+ return !key;
+ }
+
+ UserID userID(unsigned int index) const;
+ Subkey subkey(unsigned int index) const;
+
+ unsigned int numUserIDs() const;
+ unsigned int numSubkeys() const;
+
+ std::vector<UserID> userIDs() const;
+ std::vector<Subkey> subkeys() const;
+
+ bool isRevoked() const;
+ bool isExpired() const;
+ bool isDisabled() const;
+ bool isInvalid() const;
+
+ bool canEncrypt() const;
+ /*!
+ This function contains a workaround for old gpgme's: all secret
+ OpenPGP keys canSign() == true, which canReallySign() doesn't
+ have. I don't have time to find what breaks when I remove this
+ workaround, but since Kleopatra merges secret into public keys,
+ the workaround is not necessary there (and actively harms), I've
+ added a new function instead.
+ */
+ bool canSign() const;
+ bool canReallySign() const;
+ bool canCertify() const;
+ bool canAuthenticate() const;
+ bool isQualified() const;
+
+ bool hasSecret() const;
+ GPGMEPP_DEPRECATED bool isSecret() const
+ {
+ return hasSecret();
+ }
+
+ /*!
+ @return true if this is a X.509 root certificate (currently
+ equivalent to something like
+ strcmp( chainID(), subkey(0).fingerprint() ) == 0 )
+ */
+ bool isRoot() const;
+
+ enum OwnerTrust { Unknown = 0, Undefined = 1, Never = 2,
+ Marginal = 3, Full = 4, Ultimate = 5
+ };
+
+ OwnerTrust ownerTrust() const;
+ char ownerTrustAsString() const;
+
+ Protocol protocol() const;
+ const char *protocolAsString() const;
+
+ const char *issuerSerial() const;
+ const char *issuerName() const;
+ const char *chainID() const;
+
+ const char *keyID() const;
+ const char *shortKeyID() const;
+ const char *primaryFingerprint() const;
+
+ unsigned int keyListMode() const;
+
+private:
+ gpgme_key_t impl() const
+ {
+ return key.get();
+ }
+ shared_gpgme_key_t key;
+};
+
+//
+// class Subkey
+//
+
+class GPGMEPP_EXPORT Subkey
+{
+public:
+ Subkey();
+ Subkey(const shared_gpgme_key_t &key, gpgme_sub_key_t subkey);
+ Subkey(const shared_gpgme_key_t &key, unsigned int idx);
+
+ const Subkey &operator=(Subkey other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(Subkey &other)
+ {
+ using std::swap;
+ swap(this->key, other.key);
+ swap(this->subkey, other.subkey);
+ }
+
+ bool isNull() const
+ {
+ return !key || !subkey;
+ }
+
+ Key parent() const;
+
+ const char *keyID() const;
+ const char *fingerprint() const;
+
+ time_t creationTime() const;
+ time_t expirationTime() const;
+ bool neverExpires() const;
+
+ bool isRevoked() const;
+ bool isExpired() const;
+ bool isInvalid() const;
+ bool isDisabled() const;
+
+ bool canEncrypt() const;
+ bool canSign() const;
+ bool canCertify() const;
+ bool canAuthenticate() const;
+ bool isQualified() const;
+ bool isCardKey() const;
+
+ bool isSecret() const;
+
+ unsigned int publicKeyAlgorithm() const;
+ const char *publicKeyAlgorithmAsString() const;
+
+ unsigned int length() const;
+
+ const char *cardSerialNumber() const;
+
+private:
+ shared_gpgme_key_t key;
+ gpgme_sub_key_t subkey;
+};
+
+//
+// class UserID
+//
+
+class GPGMEPP_EXPORT UserID
+{
+public:
+ class Signature;
+
+ UserID();
+ UserID(const shared_gpgme_key_t &key, gpgme_user_id_t uid);
+ UserID(const shared_gpgme_key_t &key, unsigned int idx);
+
+ const UserID &operator=(UserID other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(UserID &other)
+ {
+ using std::swap;
+ swap(this->key, other.key);
+ swap(this->uid, other.uid);
+ }
+
+ bool isNull() const
+ {
+ return !key || !uid;
+ }
+
+ Key parent() const;
+
+ unsigned int numSignatures() const;
+ Signature signature(unsigned int index) const;
+ std::vector<Signature> signatures() const;
+
+ const char *id() const;
+ const char *name() const;
+ const char *email() const;
+ const char *comment() const;
+
+ enum Validity { Unknown = 0, Undefined = 1, Never = 2,
+ Marginal = 3, Full = 4, Ultimate = 5
+ };
+
+ Validity validity() const;
+ char validityAsString() const;
+
+ bool isRevoked() const;
+ bool isInvalid() const;
+
+private:
+ shared_gpgme_key_t key;
+ gpgme_user_id_t uid;
+};
+
+//
+// class UserID::Signature
+//
+
+class GPGMEPP_EXPORT UserID::Signature
+{
+public:
+ typedef GPGMEPP_DEPRECATED GpgME::Notation Notation;
+
+ Signature();
+ Signature(const shared_gpgme_key_t &key, gpgme_user_id_t uid, gpgme_key_sig_t sig);
+ Signature(const shared_gpgme_key_t &key, gpgme_user_id_t uid, unsigned int idx);
+
+ const Signature &operator=(Signature other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(Signature &other)
+ {
+ using std::swap;
+ swap(this->key, other.key);
+ swap(this->uid, other.uid);
+ swap(this->sig, other.sig);
+ }
+
+ bool isNull() const
+ {
+ return !sig || !uid || !key ;
+ }
+
+ UserID parent() const;
+
+ const char *signerKeyID() const;
+
+ const char *algorithmAsString() const;
+ unsigned int algorithm() const;
+ time_t creationTime() const;
+ time_t expirationTime() const;
+ bool neverExpires() const;
+
+ bool isRevokation() const;
+ bool isInvalid() const;
+ bool isExpired() const;
+ bool isExportable() const;
+
+ const char *signerUserID() const;
+ const char *signerName() const;
+ const char *signerEmail() const;
+ const char *signerComment() const;
+
+ unsigned int certClass() const;
+
+ enum Status { NoError = 0, SigExpired, KeyExpired,
+ BadSignature, NoPublicKey, GeneralError
+ };
+ Status status() const;
+ std::string statusAsString() const;
+
+ const char *policyURL() const;
+
+ unsigned int numNotations() const;
+ GpgME::Notation notation(unsigned int idx) const;
+ std::vector<GpgME::Notation> notations() const;
+
+private:
+ shared_gpgme_key_t key;
+ gpgme_user_id_t uid;
+ gpgme_key_sig_t sig;
+};
+
+} // namespace GpgME
+
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(Key)
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(Subkey)
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(UserID)
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(UserID::Signature)
+
+#endif // __GPGMEPP_KEY_H__
diff --git a/lang/cpp/src/keygenerationresult.cpp b/lang/cpp/src/keygenerationresult.cpp
new file mode 100644
index 0000000..f365e43
--- /dev/null
+++ b/lang/cpp/src/keygenerationresult.cpp
@@ -0,0 +1,94 @@
+/*
+ keygenerationresult.cpp - wraps a gpgme keygen result
+ Copyright (C) 2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <config-gpgme++.h>
+
+#include <keygenerationresult.h>
+#include "result_p.h"
+
+#include <gpgme.h>
+
+#include <cstring>
+#include <cstdlib>
+
+#include <string.h>
+
+class GpgME::KeyGenerationResult::Private
+{
+public:
+ Private(const _gpgme_op_genkey_result &r) : res(r)
+ {
+ if (res.fpr) {
+ res.fpr = strdup(res.fpr);
+ }
+ }
+ ~Private()
+ {
+ if (res.fpr) {
+ std::free(res.fpr);
+ }
+ res.fpr = 0;
+ }
+
+ _gpgme_op_genkey_result res;
+};
+
+GpgME::KeyGenerationResult::KeyGenerationResult(gpgme_ctx_t ctx, int error)
+ : GpgME::Result(error), d()
+{
+ init(ctx);
+}
+
+GpgME::KeyGenerationResult::KeyGenerationResult(gpgme_ctx_t ctx, const Error &error)
+ : GpgME::Result(error), d()
+{
+ init(ctx);
+}
+
+void GpgME::KeyGenerationResult::init(gpgme_ctx_t ctx)
+{
+ if (!ctx) {
+ return;
+ }
+ gpgme_genkey_result_t res = gpgme_op_genkey_result(ctx);
+ if (!res) {
+ return;
+ }
+ d.reset(new Private(*res));
+}
+
+make_standard_stuff(KeyGenerationResult)
+
+bool GpgME::KeyGenerationResult::isPrimaryKeyGenerated() const
+{
+ return d && d->res.primary;
+}
+
+bool GpgME::KeyGenerationResult::isSubkeyGenerated() const
+{
+ return d && d->res.sub;
+}
+
+const char *GpgME::KeyGenerationResult::fingerprint() const
+{
+ return d ? d->res.fpr : 0 ;
+}
diff --git a/lang/cpp/src/keygenerationresult.h b/lang/cpp/src/keygenerationresult.h
new file mode 100644
index 0000000..c4aaad1
--- /dev/null
+++ b/lang/cpp/src/keygenerationresult.h
@@ -0,0 +1,82 @@
+/*
+ keygenerationresult.h - wraps a gpgme keygen result
+ Copyright (C) 2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_KEYGENERATIONRESULT_H__
+#define __GPGMEPP_KEYGENERATIONRESULT_H__
+
+#include "gpgmefw.h"
+#include "result.h"
+#include "gpgmepp_export.h"
+
+#include <boost/shared_ptr.hpp>
+
+namespace GpgME
+{
+
+class Error;
+
+class GPGMEPP_EXPORT KeyGenerationResult : public Result
+{
+public:
+ KeyGenerationResult();
+ KeyGenerationResult(gpgme_ctx_t ctx, int error);
+ KeyGenerationResult(gpgme_ctx_t ctx, const Error &error);
+ explicit KeyGenerationResult(const Error &err);
+
+ const KeyGenerationResult &operator=(KeyGenerationResult other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(KeyGenerationResult &other)
+ {
+ Result::swap(other);
+ using std::swap;
+ swap(this->d, other.d);
+ }
+
+ bool isNull() const;
+
+ GPGMEPP_DEPRECATED bool primaryKeyGenerated() const
+ {
+ return isPrimaryKeyGenerated();
+ }
+ GPGMEPP_DEPRECATED bool subkeyGenerated() const
+ {
+ return isSubkeyGenerated();
+ }
+ bool isPrimaryKeyGenerated() const;
+ bool isSubkeyGenerated() const;
+ const char *fingerprint() const;
+
+private:
+ class Private;
+ void init(gpgme_ctx_t ctx);
+ boost::shared_ptr<Private> d;
+};
+
+}
+
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(KeyGenerationResult)
+
+#endif // __GPGMEPP_KEYGENERATIONRESULT_H__
diff --git a/lang/cpp/src/keylistresult.cpp b/lang/cpp/src/keylistresult.cpp
new file mode 100644
index 0000000..4aa3e11
--- /dev/null
+++ b/lang/cpp/src/keylistresult.cpp
@@ -0,0 +1,109 @@
+/*
+ keylistresult.cpp - wraps a gpgme keylist result
+ Copyright (C) 2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <config-gpgme++.h>
+
+#include <keylistresult.h>
+#include "result_p.h"
+
+#include <gpgme.h>
+
+#include <cstring>
+#include <cassert>
+
+class GpgME::KeyListResult::Private
+{
+public:
+ Private(const _gpgme_op_keylist_result &r) : res(r) {}
+ Private(const Private &other) : res(other.res) {}
+
+ _gpgme_op_keylist_result res;
+};
+
+GpgME::KeyListResult::KeyListResult(gpgme_ctx_t ctx, int error)
+ : GpgME::Result(error), d()
+{
+ init(ctx);
+}
+
+GpgME::KeyListResult::KeyListResult(gpgme_ctx_t ctx, const Error &error)
+ : GpgME::Result(error), d()
+{
+ init(ctx);
+}
+
+void GpgME::KeyListResult::init(gpgme_ctx_t ctx)
+{
+ if (!ctx) {
+ return;
+ }
+ gpgme_keylist_result_t res = gpgme_op_keylist_result(ctx);
+ if (!res) {
+ return;
+ }
+ d.reset(new Private(*res));
+}
+
+GpgME::KeyListResult::KeyListResult(const Error &error, const _gpgme_op_keylist_result &res)
+ : GpgME::Result(error), d(new Private(res))
+{
+
+}
+
+make_standard_stuff(KeyListResult)
+
+void GpgME::KeyListResult::detach()
+{
+ if (!d || d.unique()) {
+ return;
+ }
+ d.reset(new Private(*d));
+}
+
+void GpgME::KeyListResult::mergeWith(const KeyListResult &other)
+{
+ if (other.isNull()) {
+ return;
+ }
+ if (isNull()) { // just assign
+ operator=(other);
+ return;
+ }
+ // merge the truncated flag (try to keep detaching to a minimum):
+ if (other.isTruncated() && !this->isTruncated()) {
+ assert(other.d);
+ detach();
+ if (!d) {
+ d.reset(new Private(*other.d));
+ } else {
+ d->res.truncated = true;
+ }
+ }
+ if (! bool(error())) { // only merge the error when there was none yet.
+ Result::operator=(other);
+ }
+}
+
+bool GpgME::KeyListResult::isTruncated() const
+{
+ return d && d->res.truncated;
+}
diff --git a/lang/cpp/src/keylistresult.h b/lang/cpp/src/keylistresult.h
new file mode 100644
index 0000000..618573b
--- /dev/null
+++ b/lang/cpp/src/keylistresult.h
@@ -0,0 +1,81 @@
+/*
+ keylistresult.h - wraps a gpgme keylist result
+ Copyright (C) 2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_KEYLISTRESULT_H__
+#define __GPGMEPP_KEYLISTRESULT_H__
+
+#include "gpgmefw.h"
+#include "result.h"
+#include "gpgmepp_export.h"
+
+#include <boost/shared_ptr.hpp>
+
+namespace GpgME
+{
+
+class Error;
+
+class GPGMEPP_EXPORT KeyListResult : public Result
+{
+public:
+ KeyListResult();
+ KeyListResult(gpgme_ctx_t ctx, int error);
+ KeyListResult(gpgme_ctx_t ctx, const Error &error);
+ explicit KeyListResult(const Error &err);
+ KeyListResult(const Error &err, const _gpgme_op_keylist_result &res);
+
+ const KeyListResult &operator=(KeyListResult other)
+ {
+ swap(other);
+ return *this;
+ }
+ void swap(KeyListResult &other)
+ {
+ Result::swap(other);
+ using std::swap;
+ swap(this->d, other.d);
+ }
+
+ const KeyListResult &operator+=(const KeyListResult &other)
+ {
+ mergeWith(other);
+ return *this;
+ }
+
+ void mergeWith(const KeyListResult &other);
+
+ bool isNull() const;
+
+ bool isTruncated() const;
+
+private:
+ void detach();
+ void init(gpgme_ctx_t ctx);
+ class Private;
+ boost::shared_ptr<Private> d;
+};
+
+}
+
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(KeyListResult)
+
+#endif // __GPGMEPP_KEYLISTRESULT_H__
diff --git a/lang/cpp/src/notation.h b/lang/cpp/src/notation.h
new file mode 100644
index 0000000..c53237c
--- /dev/null
+++ b/lang/cpp/src/notation.h
@@ -0,0 +1,84 @@
+/*
+ notation.h - wraps a gpgme verify result
+ Copyright (C) 2004, 2007 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_NOTATION_H__
+#define __GPGMEPP_NOTATION_H__
+
+#include "gpgmefw.h"
+#include "verificationresult.h"
+#include "gpgmepp_export.h"
+
+#include <boost/shared_ptr.hpp>
+
+#include <iosfwd>
+
+namespace GpgME
+{
+
+class GPGMEPP_EXPORT Notation
+{
+ friend class ::GpgME::Signature;
+ Notation(const boost::shared_ptr<VerificationResult::Private> &parent, unsigned int sindex, unsigned int nindex);
+public:
+ Notation();
+ explicit Notation(gpgme_sig_notation_t nota);
+
+ const Notation &operator=(Notation other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(Notation &other)
+ {
+ using std::swap;
+ swap(this->d, other.d);
+ }
+
+ bool isNull() const;
+
+ const char *name() const;
+ const char *value() const;
+
+ enum Flags {
+ NoFlags = 0,
+ HumanReadable = 1,
+ Critical = 2
+ };
+ Flags flags() const;
+
+ bool isHumanReadable() const;
+ bool isCritical() const;
+
+private:
+ class Private;
+ boost::shared_ptr<Private> d;
+};
+
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const Notation ¬a);
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, Notation::Flags flags);
+
+}
+
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(Notation)
+
+#endif // __GPGMEPP_NOTATION_H__
diff --git a/lang/cpp/src/result.h b/lang/cpp/src/result.h
new file mode 100644
index 0000000..1eae5b1
--- /dev/null
+++ b/lang/cpp/src/result.h
@@ -0,0 +1,58 @@
+/*
+ result.h - base class for results
+ Copyright (C) 2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_RESULT_H__
+#define __GPGMEPP_RESULT_H__
+
+#include "gpgmefw.h"
+#include "error.h"
+
+#include <algorithm> // std::swap
+
+namespace GpgME
+{
+
+class GPGMEPP_EXPORT Result
+{
+protected:
+ explicit Result() : mError() {}
+ explicit Result(int error) : mError(error) {}
+ explicit Result(const Error &error) : mError(error) {}
+
+ void swap(Result &other)
+ {
+ std::swap(other.mError, mError);
+ }
+
+public:
+ const Error &error() const
+ {
+ return mError;
+ }
+
+protected:
+ Error mError;
+};
+
+}
+
+#endif // __GPGMEPP_RESULT_H__
diff --git a/lang/cpp/src/result_p.h b/lang/cpp/src/result_p.h
new file mode 100644
index 0000000..0cf73e4
--- /dev/null
+++ b/lang/cpp/src/result_p.h
@@ -0,0 +1,43 @@
+/*
+ result.h - base class for results
+ Copyright (C) 2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_RESULT_P_H__
+#define __GPGMEPP_RESULT_P_H__
+
+#define make_default_ctor(x) \
+ GpgME::x::x() : GpgME::Result(), d() {}
+
+#define make_error_ctor(x) \
+ GpgME::x::x( const Error & error ) \
+ : GpgME::Result( error ), d() \
+ { \
+ \
+ }
+
+#define make_isNull(x) bool GpgME::x::isNull() const { return !d && !bool(error()); }
+
+#define make_standard_stuff(x) \
+ make_default_ctor(x) \
+ make_error_ctor(x) \
+ make_isNull(x)
+
+#endif // __GPGMEPP_RESULT_P_H__
diff --git a/lang/cpp/src/scdgetinfoassuantransaction.cpp b/lang/cpp/src/scdgetinfoassuantransaction.cpp
new file mode 100644
index 0000000..d9b0f9d
--- /dev/null
+++ b/lang/cpp/src/scdgetinfoassuantransaction.cpp
@@ -0,0 +1,156 @@
+/*
+ scdgetinfoassuantransaction.cpp - Assuan Transaction to get information from scdaemon
+ Copyright (C) 2009 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <config-gpgme++.h>
+
+#include "scdgetinfoassuantransaction.h"
+#include "error.h"
+#include "data.h"
+#include "util.h"
+
+#include <boost/algorithm/string/split.hpp>
+#include <boost/algorithm/string/classification.hpp>
+#include <boost/static_assert.hpp>
+
+#include <sstream>
+
+using namespace GpgME;
+using namespace boost;
+
+ScdGetInfoAssuanTransaction::ScdGetInfoAssuanTransaction(InfoItem item)
+ : AssuanTransaction(),
+ m_item(item),
+ m_command(),
+ m_data()
+{
+
+}
+
+ScdGetInfoAssuanTransaction::~ScdGetInfoAssuanTransaction() {}
+
+static std::vector<std::string> to_reader_list(const std::string &s)
+{
+ std::vector<std::string> result;
+ return split(result, s, is_any_of("\n"), token_compress_on);
+}
+
+static std::vector<std::string> to_app_list(const std::string &s)
+{
+ return to_reader_list(s);
+}
+
+std::string ScdGetInfoAssuanTransaction::version() const
+{
+ if (m_item == Version) {
+ return m_data;
+ } else {
+ return std::string();
+ }
+}
+
+unsigned int ScdGetInfoAssuanTransaction::pid() const
+{
+ if (m_item == Pid) {
+ return to_pid(m_data);
+ } else {
+ return 0U;
+ }
+}
+
+std::string ScdGetInfoAssuanTransaction::socketName() const
+{
+ if (m_item == SocketName) {
+ return m_data;
+ } else {
+ return std::string();
+ }
+}
+
+char ScdGetInfoAssuanTransaction::status() const
+{
+ if (m_item == Status && !m_data.empty()) {
+ return m_data[0];
+ } else {
+ return '\0';
+ }
+}
+
+std::vector<std::string> ScdGetInfoAssuanTransaction::readerList() const
+{
+ if (m_item == ReaderList) {
+ return to_reader_list(m_data);
+ } else {
+ return std::vector<std::string>();
+ }
+}
+
+std::vector<std::string> ScdGetInfoAssuanTransaction::applicationList() const
+{
+ if (m_item == ApplicationList) {
+ return to_app_list(m_data);
+ } else {
+ return std::vector<std::string>();
+ }
+}
+
+static const char *const scd_getinfo_tokens[] = {
+ "version",
+ "pid",
+ "socket_name",
+ "status",
+ "reader_list",
+ "deny_admin",
+ "app_list",
+};
+BOOST_STATIC_ASSERT((sizeof scd_getinfo_tokens / sizeof * scd_getinfo_tokens == ScdGetInfoAssuanTransaction::LastInfoItem));
+
+void ScdGetInfoAssuanTransaction::makeCommand() const
+{
+ assert(m_item >= 0);
+ assert(m_item < LastInfoItem);
+ m_command = "SCD GETINFO ";
+ m_command += scd_getinfo_tokens[m_item];
+}
+
+const char *ScdGetInfoAssuanTransaction::command() const
+{
+ makeCommand();
+ return m_command.c_str();
+}
+
+Error ScdGetInfoAssuanTransaction::data(const char *data, size_t len)
+{
+ m_data.append(data, len);
+ return Error();
+}
+
+Data ScdGetInfoAssuanTransaction::inquire(const char *name, const char *args, Error &err)
+{
+ (void)name; (void)args; (void)err;
+ return Data::null;
+}
+
+Error ScdGetInfoAssuanTransaction::status(const char *status, const char *args)
+{
+ (void)status; (void)args;
+ return Error();
+}
diff --git a/lang/cpp/src/scdgetinfoassuantransaction.h b/lang/cpp/src/scdgetinfoassuantransaction.h
new file mode 100644
index 0000000..a22a0ff
--- /dev/null
+++ b/lang/cpp/src/scdgetinfoassuantransaction.h
@@ -0,0 +1,76 @@
+/*
+ scdgetinfoassuantransaction.h - Assuan Transaction to get information from scdaemon
+ Copyright (C) 2009 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_SCDGETINFOASSUANTRANSACTION_H__
+#define __GPGMEPP_SCDGETINFOASSUANTRANSACTION_H__
+
+#include <interfaces/assuantransaction.h>
+
+#include <string>
+#include <vector>
+
+namespace GpgME
+{
+
+class GPGMEPP_EXPORT ScdGetInfoAssuanTransaction : public AssuanTransaction
+{
+public:
+ enum InfoItem {
+ Version, // string
+ Pid, // unsigned long
+ SocketName, // string (path)
+ Status, // char (status)
+ ReaderList, // string list
+ DenyAdmin, // (none, returns GPG_ERR_GENERAL when admin commands are allowed)
+ ApplicationList, // string list
+
+ LastInfoItem
+ };
+
+ explicit ScdGetInfoAssuanTransaction(InfoItem item);
+ ~ScdGetInfoAssuanTransaction();
+
+ std::string version() const;
+ unsigned int pid() const;
+ std::string socketName() const;
+ char status() const;
+ std::vector<std::string> readerList() const;
+ std::vector<std::string> applicationList() const;
+
+private:
+ /* reimp */ const char *command() const;
+ /* reimp */ Error data(const char *data, size_t datalen);
+ /* reimp */ Data inquire(const char *name, const char *args, Error &err);
+ /* reimp */ Error status(const char *status, const char *args);
+
+private:
+ void makeCommand() const;
+
+private:
+ InfoItem m_item;
+ mutable std::string m_command;
+ std::string m_data;
+};
+
+} // namespace GpgME
+
+#endif // __GPGMEPP_SCDGETINFOASSUANTRANSACTION_H__
diff --git a/lang/cpp/src/signingresult.cpp b/lang/cpp/src/signingresult.cpp
new file mode 100644
index 0000000..f5f671b
--- /dev/null
+++ b/lang/cpp/src/signingresult.cpp
@@ -0,0 +1,267 @@
+/*
+ signingresult.cpp - wraps a gpgme verify result
+ Copyright (C) 2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <config-gpgme++.h>
+
+#include <signingresult.h>
+#include "result_p.h"
+#include "util.h"
+
+#include <gpgme.h>
+
+#include <cstring>
+#include <cstdlib>
+#include <algorithm>
+#include <istream>
+#include <iterator>
+
+#include <string.h>
+
+class GpgME::SigningResult::Private
+{
+public:
+ Private(const gpgme_sign_result_t r)
+ {
+ if (!r) {
+ return;
+ }
+ for (gpgme_new_signature_t is = r->signatures ; is ; is = is->next) {
+ gpgme_new_signature_t copy = new _gpgme_new_signature(*is);
+ if (is->fpr) {
+ copy->fpr = strdup(is->fpr);
+ }
+ copy->next = 0;
+ created.push_back(copy);
+ }
+ for (gpgme_invalid_key_t ik = r->invalid_signers ; ik ; ik = ik->next) {
+ gpgme_invalid_key_t copy = new _gpgme_invalid_key(*ik);
+ if (ik->fpr) {
+ copy->fpr = strdup(ik->fpr);
+ }
+ copy->next = 0;
+ invalid.push_back(copy);
+ }
+ }
+ ~Private()
+ {
+ for (std::vector<gpgme_new_signature_t>::iterator it = created.begin() ; it != created.end() ; ++it) {
+ std::free((*it)->fpr);
+ delete *it; *it = 0;
+ }
+ for (std::vector<gpgme_invalid_key_t>::iterator it = invalid.begin() ; it != invalid.end() ; ++it) {
+ std::free((*it)->fpr);
+ delete *it; *it = 0;
+ }
+ }
+
+ std::vector<gpgme_new_signature_t> created;
+ std::vector<gpgme_invalid_key_t> invalid;
+};
+
+GpgME::SigningResult::SigningResult(gpgme_ctx_t ctx, int error)
+ : GpgME::Result(error), d()
+{
+ init(ctx);
+}
+
+GpgME::SigningResult::SigningResult(gpgme_ctx_t ctx, const Error &error)
+ : GpgME::Result(error), d()
+{
+ init(ctx);
+}
+
+void GpgME::SigningResult::init(gpgme_ctx_t ctx)
+{
+ if (!ctx) {
+ return;
+ }
+ gpgme_sign_result_t res = gpgme_op_sign_result(ctx);
+ if (!res) {
+ return;
+ }
+ d.reset(new Private(res));
+}
+
+make_standard_stuff(SigningResult)
+
+GpgME::CreatedSignature GpgME::SigningResult::createdSignature(unsigned int idx) const
+{
+ return CreatedSignature(d, idx);
+}
+
+std::vector<GpgME::CreatedSignature> GpgME::SigningResult::createdSignatures() const
+{
+ if (!d) {
+ return std::vector<CreatedSignature>();
+ }
+ std::vector<CreatedSignature> result;
+ result.reserve(d->created.size());
+ for (unsigned int i = 0 ; i < d->created.size() ; ++i) {
+ result.push_back(CreatedSignature(d, i));
+ }
+ return result;
+}
+
+GpgME::InvalidSigningKey GpgME::SigningResult::invalidSigningKey(unsigned int idx) const
+{
+ return InvalidSigningKey(d, idx);
+}
+
+std::vector<GpgME::InvalidSigningKey> GpgME::SigningResult::invalidSigningKeys() const
+{
+ if (!d) {
+ return std::vector<GpgME::InvalidSigningKey>();
+ }
+ std::vector<GpgME::InvalidSigningKey> result;
+ result.reserve(d->invalid.size());
+ for (unsigned int i = 0 ; i < d->invalid.size() ; ++i) {
+ result.push_back(InvalidSigningKey(d, i));
+ }
+ return result;
+}
+
+GpgME::InvalidSigningKey::InvalidSigningKey(const boost::shared_ptr<SigningResult::Private> &parent, unsigned int i)
+ : d(parent), idx(i)
+{
+
+}
+
+GpgME::InvalidSigningKey::InvalidSigningKey() : d(), idx(0) {}
+
+bool GpgME::InvalidSigningKey::isNull() const
+{
+ return !d || idx >= d->invalid.size() ;
+}
+
+const char *GpgME::InvalidSigningKey::fingerprint() const
+{
+ return isNull() ? 0 : d->invalid[idx]->fpr ;
+}
+
+GpgME::Error GpgME::InvalidSigningKey::reason() const
+{
+ return Error(isNull() ? 0 : d->invalid[idx]->reason);
+}
+
+GpgME::CreatedSignature::CreatedSignature(const boost::shared_ptr<SigningResult::Private> &parent, unsigned int i)
+ : d(parent), idx(i)
+{
+
+}
+
+GpgME::CreatedSignature::CreatedSignature() : d(), idx(0) {}
+
+bool GpgME::CreatedSignature::isNull() const
+{
+ return !d || idx >= d->created.size() ;
+}
+
+const char *GpgME::CreatedSignature::fingerprint() const
+{
+ return isNull() ? 0 : d->created[idx]->fpr ;
+}
+
+time_t GpgME::CreatedSignature::creationTime() const
+{
+ return static_cast<time_t>(isNull() ? 0 : d->created[idx]->timestamp);
+}
+
+GpgME::SignatureMode GpgME::CreatedSignature::mode() const
+{
+ if (isNull()) {
+ return NormalSignatureMode;
+ }
+ switch (d->created[idx]->type) {
+ default:
+ case GPGME_SIG_MODE_NORMAL: return NormalSignatureMode;
+ case GPGME_SIG_MODE_DETACH: return Detached;
+ case GPGME_SIG_MODE_CLEAR: return Clearsigned;
+ }
+}
+
+unsigned int GpgME::CreatedSignature::publicKeyAlgorithm() const
+{
+ return isNull() ? 0 : d->created[idx]->pubkey_algo ;
+}
+
+const char *GpgME::CreatedSignature::publicKeyAlgorithmAsString() const
+{
+ return gpgme_pubkey_algo_name(isNull() ? (gpgme_pubkey_algo_t)0 : d->created[idx]->pubkey_algo);
+}
+
+unsigned int GpgME::CreatedSignature::hashAlgorithm() const
+{
+ return isNull() ? 0 : d->created[idx]->hash_algo ;
+}
+
+const char *GpgME::CreatedSignature::hashAlgorithmAsString() const
+{
+ return gpgme_hash_algo_name(isNull() ? (gpgme_hash_algo_t)0 : d->created[idx]->hash_algo);
+}
+
+unsigned int GpgME::CreatedSignature::signatureClass() const
+{
+ return isNull() ? 0 : d->created[idx]->sig_class ;
+}
+
+std::ostream &GpgME::operator<<(std::ostream &os, const SigningResult &result)
+{
+ os << "GpgME::SigningResult(";
+ if (!result.isNull()) {
+ os << "\n error: " << result.error()
+ << "\n createdSignatures:\n";
+ const std::vector<CreatedSignature> cs = result.createdSignatures();
+ std::copy(cs.begin(), cs.end(),
+ std::ostream_iterator<CreatedSignature>(os, "\n"));
+ os << " invalidSigningKeys:\n";
+ const std::vector<InvalidSigningKey> isk = result.invalidSigningKeys();
+ std::copy(isk.begin(), isk.end(),
+ std::ostream_iterator<InvalidSigningKey>(os, "\n"));
+ }
+ return os << ')';
+}
+
+std::ostream &GpgME::operator<<(std::ostream &os, const CreatedSignature &sig)
+{
+ os << "GpgME::CreatedSignature(";
+ if (!sig.isNull()) {
+ os << "\n fingerprint: " << protect(sig.fingerprint())
+ << "\n creationTime: " << sig.creationTime()
+ << "\n mode: " << sig.mode()
+ << "\n publicKeyAlgorithm: " << protect(sig.publicKeyAlgorithmAsString())
+ << "\n hashAlgorithm: " << protect(sig.hashAlgorithmAsString())
+ << "\n signatureClass: " << sig.signatureClass()
+ << '\n';
+ }
+ return os << ')';
+}
+
+std::ostream &GpgME::operator<<(std::ostream &os, const InvalidSigningKey &key)
+{
+ os << "GpgME::InvalidSigningKey(";
+ if (!key.isNull()) {
+ os << "\n fingerprint: " << protect(key.fingerprint())
+ << "\n reason: " << key.reason()
+ << '\n';
+ }
+ return os << ')';
+}
diff --git a/lang/cpp/src/signingresult.h b/lang/cpp/src/signingresult.h
new file mode 100644
index 0000000..1847fb0
--- /dev/null
+++ b/lang/cpp/src/signingresult.h
@@ -0,0 +1,162 @@
+/*
+ signingresult.h - wraps a gpgme sign result
+ Copyright (C) 2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_SIGNINGRESULT_H__
+#define __GPGMEPP_SIGNINGRESULT_H__
+
+#include "global.h"
+#include "result.h"
+
+#include <time.h>
+
+#include <boost/shared_ptr.hpp>
+
+#include <vector>
+#include <iosfwd>
+
+namespace GpgME
+{
+
+class Error;
+class CreatedSignature;
+class InvalidSigningKey;
+
+class GPGMEPP_EXPORT SigningResult : public Result
+{
+public:
+ SigningResult();
+ SigningResult(gpgme_ctx_t ctx, int error);
+ SigningResult(gpgme_ctx_t ctx, const Error &error);
+ explicit SigningResult(const Error &err);
+
+ const SigningResult &operator=(SigningResult other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(SigningResult &other)
+ {
+ Result::swap(other);
+ using std::swap;
+ swap(this->d, other.d);
+ }
+
+ bool isNull() const;
+
+ CreatedSignature createdSignature(unsigned int index) const;
+ std::vector<CreatedSignature> createdSignatures() const;
+
+ InvalidSigningKey invalidSigningKey(unsigned int index) const;
+ std::vector<InvalidSigningKey> invalidSigningKeys() const;
+
+ class Private;
+private:
+ void init(gpgme_ctx_t ctx);
+ boost::shared_ptr<Private> d;
+};
+
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const SigningResult &result);
+
+class GPGMEPP_EXPORT InvalidSigningKey
+{
+ friend class ::GpgME::SigningResult;
+ InvalidSigningKey(const boost::shared_ptr<SigningResult::Private> &parent, unsigned int index);
+public:
+ InvalidSigningKey();
+
+ const InvalidSigningKey &operator=(InvalidSigningKey other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(InvalidSigningKey &other)
+ {
+ using std::swap;
+ swap(this->d, other.d);
+ swap(this->idx, other.idx);
+ }
+
+ bool isNull() const;
+
+ const char *fingerprint() const;
+ Error reason() const;
+
+private:
+ boost::shared_ptr<SigningResult::Private> d;
+ unsigned int idx;
+};
+
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const InvalidSigningKey &key);
+
+class GPGMEPP_EXPORT CreatedSignature
+{
+ friend class ::GpgME::SigningResult;
+ CreatedSignature(const boost::shared_ptr<SigningResult::Private> &parent, unsigned int index);
+public:
+
+ CreatedSignature();
+
+ const CreatedSignature &operator=(CreatedSignature other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(CreatedSignature &other)
+ {
+ using std::swap;
+ swap(this->d, other.d);
+ swap(this->idx, other.idx);
+ }
+
+ bool isNull() const;
+
+ const char *fingerprint() const;
+
+ time_t creationTime() const;
+
+ SignatureMode mode() const;
+
+ unsigned int publicKeyAlgorithm() const;
+ const char *publicKeyAlgorithmAsString() const;
+
+ unsigned int hashAlgorithm() const;
+ const char *hashAlgorithmAsString() const;
+
+ unsigned int signatureClass() const;
+
+private:
+ boost::shared_ptr<SigningResult::Private> d;
+ unsigned int idx;
+};
+
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const CreatedSignature &sig);
+
+}
+
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(SigningResult)
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(InvalidSigningKey)
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(CreatedSignature)
+
+#endif // __GPGMEPP_SIGNINGRESULT_H__
diff --git a/lang/cpp/src/trustitem.cpp b/lang/cpp/src/trustitem.cpp
new file mode 100644
index 0000000..1abaf7e
--- /dev/null
+++ b/lang/cpp/src/trustitem.cpp
@@ -0,0 +1,116 @@
+/*
+ trustitem.cpp - wraps a gpgme trust item
+ Copyright (C) 2003 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <config-gpgme++.h>
+
+#include <trustitem.h>
+
+#include <gpgme.h>
+
+#include <cassert>
+
+namespace GpgME
+{
+
+class TrustItem::Private
+{
+public:
+ Private(gpgme_trust_item_t aItem)
+ : item(aItem)
+ {
+ }
+
+ gpgme_trust_item_t item;
+};
+
+TrustItem::TrustItem(gpgme_trust_item_t item)
+{
+ d = new Private(item);
+ if (d->item) {
+ gpgme_trust_item_ref(d->item);
+ }
+}
+
+TrustItem::TrustItem(const TrustItem &other)
+{
+ d = new Private(other.d->item);
+ if (d->item) {
+ gpgme_trust_item_ref(d->item);
+ }
+}
+
+TrustItem::~TrustItem()
+{
+ if (d->item) {
+ gpgme_trust_item_unref(d->item);
+ }
+ delete d; d = 0;
+}
+
+bool TrustItem::isNull() const
+{
+ return !d || !d->item;
+}
+
+gpgme_trust_item_t TrustItem::impl() const
+{
+ return d->item;
+}
+
+const char *TrustItem::keyID() const
+{
+ return d->item ? d->item->keyid : 0 ;
+}
+
+const char *TrustItem::userID() const
+{
+ return d->item ? d->item->name : 0 ;
+}
+
+const char *TrustItem::ownerTrustAsString() const
+{
+ return d->item ? d->item->owner_trust : 0 ;
+}
+
+const char *TrustItem::validityAsString() const
+{
+ return d->item ? d->item->validity : 0 ;
+}
+
+int TrustItem::trustLevel() const
+{
+ return d->item ? d->item->level : 0 ;
+}
+
+TrustItem::Type TrustItem::type() const
+{
+ if (!d->item) {
+ return Unknown;
+ } else {
+ return
+ d->item->type == 1 ? Key :
+ d->item->type == 2 ? UserID :
+ Unknown ;
+ }
+}
+
+} // namespace GpgME
diff --git a/lang/cpp/src/trustitem.h b/lang/cpp/src/trustitem.h
new file mode 100644
index 0000000..65f109c
--- /dev/null
+++ b/lang/cpp/src/trustitem.h
@@ -0,0 +1,81 @@
+/*
+ trustitem.h - wraps a gpgme trust item
+ Copyright (C) 2003 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+// -*- c++ -*-
+#ifndef __GPGMEPP_TRUSTITEM_H__
+#define __GPGMEPP_TRUSTITEM_H__
+
+#include "gpgmefw.h"
+#include <key.h>
+#include "gpgmepp_export.h"
+
+#include <algorithm>
+
+namespace GpgME
+{
+
+class Context;
+
+class GPGMEPP_EXPORT TrustItem
+{
+ friend class ::GpgME::Context;
+public:
+ explicit TrustItem(gpgme_trust_item_t item = 0);
+ TrustItem(const TrustItem &other);
+ virtual ~TrustItem();
+
+ const TrustItem &operator=(TrustItem other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(TrustItem &other)
+ {
+ using std::swap;
+ swap(this->d, other.d);
+ }
+
+ bool isNull() const;
+
+ const char *keyID() const;
+ const char *userID() const;
+
+ const char *ownerTrustAsString() const;
+ const char *validityAsString() const;
+
+ int trustLevel() const;
+
+ enum Type { Unknown = 0, Key = 1, UserID = 2 };
+ Type type() const;
+
+private:
+ gpgme_trust_item_t impl() const;
+ class Private;
+ Private *d;
+};
+
+} // namepace GpgME
+
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(TrustItem)
+
+#endif // __GPGMEPP_TRUSTITEM_H__
diff --git a/lang/cpp/src/util.h b/lang/cpp/src/util.h
new file mode 100644
index 0000000..ed526e1
--- /dev/null
+++ b/lang/cpp/src/util.h
@@ -0,0 +1,179 @@
+/*
+ util.h - some inline helper functions
+ Copyright (C) 2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+// -*- c++ -*-
+#ifndef __GPGMEPP_UTIL_H__
+#define __GPGMEPP_UTIL_H__
+
+#include "global.h"
+#include "notation.h"
+
+#include <gpgme.h>
+
+#ifndef NDEBUG
+#include <iostream>
+#endif
+#include <sstream>
+#include <string>
+
+static inline const char *protect(const char *s)
+{
+ return s ? s : "<null>" ;
+}
+
+static inline gpgme_error_t make_error(gpgme_err_code_t code)
+{
+ return gpgme_err_make((gpgme_err_source_t)22, code);
+}
+
+static inline unsigned long to_pid(const std::string &s)
+{
+ std::stringstream ss(s);
+ unsigned int result;
+ if (ss >> result) {
+ return result;
+ } else {
+ return 0U;
+ }
+}
+
+static inline gpgme_keylist_mode_t add_to_gpgme_keylist_mode_t(unsigned int oldmode, unsigned int newmodes)
+{
+ if (newmodes & GpgME::Local) {
+ oldmode |= GPGME_KEYLIST_MODE_LOCAL;
+ }
+ if (newmodes & GpgME::Extern) {
+ oldmode |= GPGME_KEYLIST_MODE_EXTERN;
+ }
+ if (newmodes & GpgME::Signatures) {
+ oldmode |= GPGME_KEYLIST_MODE_SIGS;
+ }
+ if (newmodes & GpgME::SignatureNotations) {
+#ifdef HAVE_GPGME_KEYLIST_MODE_SIG_NOTATIONS
+ oldmode |= GPGME_KEYLIST_MODE_SIG_NOTATIONS;
+#elif !defined(NDEBUG)
+ ;//std::cerr << "GpgME: ignoring SignatureNotations keylist flag (gpgme too old)." << std::endl;
+#endif
+ }
+ if (newmodes & GpgME::Ephemeral) {
+#ifdef HAVE_GPGME_KEYLIST_MODE_EPHEMERAL
+ oldmode |= GPGME_KEYLIST_MODE_EPHEMERAL;
+#elif !defined(NDEBUG)
+ ;//std::cerr << "GpgME: ignoring Ephemeral keylist flag (gpgme too old)." << std::endl;
+#endif
+ }
+ if (newmodes & GpgME::Validate) {
+ oldmode |= GPGME_KEYLIST_MODE_VALIDATE;
+ }
+#ifndef NDEBUG
+ if (newmodes & ~(GpgME::Local | GpgME::Extern | GpgME::Signatures | GpgME::SignatureNotations | GpgME::Ephemeral | GpgME::Validate)) {
+ //std::cerr << "GpgME::Context: keylist mode must be one of Local, "
+ //"Extern, Signatures, SignatureNotations, or Validate, or a combination thereof!" << std::endl;
+ }
+#endif
+ return static_cast<gpgme_keylist_mode_t>(oldmode);
+}
+
+static inline unsigned int convert_from_gpgme_keylist_mode_t(unsigned int mode)
+{
+ unsigned int result = 0;
+ if (mode & GPGME_KEYLIST_MODE_LOCAL) {
+ result |= GpgME::Local;
+ }
+ if (mode & GPGME_KEYLIST_MODE_EXTERN) {
+ result |= GpgME::Extern;
+ }
+ if (mode & GPGME_KEYLIST_MODE_SIGS) {
+ result |= GpgME::Signatures;
+ }
+#ifdef HAVE_GPGME_KEYLIST_MODE_SIG_NOTATIONS
+ if (mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS) {
+ result |= GpgME::SignatureNotations;
+ }
+#endif
+#ifdef HAVE_GPGME_KEYLIST_MODE_EPHEMERAL
+ if (mode & GPGME_KEYLIST_MODE_EPHEMERAL) {
+ result |= GpgME::Ephemeral;
+ }
+#endif
+ if (mode & GPGME_KEYLIST_MODE_VALIDATE) {
+ result |= GpgME::Validate;
+ }
+#ifndef NDEBUG
+ if (mode & ~(GPGME_KEYLIST_MODE_LOCAL |
+ GPGME_KEYLIST_MODE_EXTERN |
+#ifdef HAVE_GPGME_KEYLIST_MODE_SIG_NOTATIONS
+ GPGME_KEYLIST_MODE_SIG_NOTATIONS |
+#endif
+#ifdef HAVE_GPGME_KEYLIST_MODE_EPHEMERAL
+ GPGME_KEYLIST_MODE_EPHEMERAL |
+#endif
+ GPGME_KEYLIST_MODE_VALIDATE |
+ GPGME_KEYLIST_MODE_SIGS)) {
+ //std::cerr << "GpgME: WARNING: gpgme_get_keylist_mode() returned an unknown flag!" << std::endl;
+ }
+#endif // NDEBUG
+ return result;
+}
+
+static inline GpgME::Notation::Flags convert_from_gpgme_sig_notation_flags_t(unsigned int flags)
+{
+#ifdef HAVE_GPGME_SIG_NOTATION_FLAGS_T
+ unsigned int result = 0;
+#ifdef HAVE_GPGME_SIG_NOTATION_HUMAN_READABLE
+ if (flags & GPGME_SIG_NOTATION_HUMAN_READABLE) {
+ result |= GpgME::Notation::HumanReadable ;
+ }
+#endif
+#ifdef HAVE_GPGME_SIG_NOTATION_CRITICAL
+ if (flags & GPGME_SIG_NOTATION_CRITICAL) {
+ result |= GpgME::Notation::Critical ;
+ }
+#endif
+ return static_cast<GpgME::Notation::Flags>(result);
+#else
+ return GpgME::Notation::NoFlags;
+#endif
+}
+#ifdef HAVE_GPGME_SIG_NOTATION_FLAGS_T
+static inline gpgme_sig_notation_flags_t add_to_gpgme_sig_notation_flags_t(unsigned int oldflags, unsigned int newflags)
+{
+ unsigned int result = oldflags;
+ if (newflags & GpgME::Notation::HumanReadable) {
+#ifdef HAVE_GPGME_SIG_NOTATION_HUMAN_READABLE
+ result |= GPGME_SIG_NOTATION_HUMAN_READABLE;
+#elif !defined(NDEBUG)
+ //std::cerr << "GpgME::Context: ignoring HumanReadable signature notation flag (gpgme too old)" << std::endl;
+#endif
+ }
+ if (newflags & GpgME::Notation::Critical) {
+#ifdef HAVE_GPGME_SIG_NOTATION_CRITICAL
+ result |= GPGME_SIG_NOTATION_CRITICAL;
+#elif !defined(NDEBUG)
+ //std::cerr << "GpgME::Context: ignoring Critical signature notation flag (gpgme too old)" << std::endl;
+#endif
+ }
+ return static_cast<gpgme_sig_notation_flags_t>(result);
+}
+#endif
+
+#endif // __GPGMEPP_UTIL_H__
diff --git a/lang/cpp/src/verificationresult.cpp b/lang/cpp/src/verificationresult.cpp
new file mode 100644
index 0000000..42d5ad2
--- /dev/null
+++ b/lang/cpp/src/verificationresult.cpp
@@ -0,0 +1,590 @@
+/*
+ verificationresult.cpp - wraps a gpgme verify result
+ Copyright (C) 2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <config-gpgme++.h>
+#include <verificationresult.h>
+#include <notation.h>
+#include "result_p.h"
+#include "util.h"
+
+#include <gpgme.h>
+
+#include <istream>
+#include <algorithm>
+#include <iterator>
+#include <string>
+#include <cstring>
+#include <cstdlib>
+
+#include <string.h>
+
+class GpgME::VerificationResult::Private
+{
+public:
+ explicit Private(const gpgme_verify_result_t r)
+ {
+ if (!r) {
+ return;
+ }
+#ifdef HAVE_GPGME_VERIFY_RESULT_T_FILE_NAME
+ if (r->file_name) {
+ file_name = r->file_name;
+ }
+#endif
+ // copy recursively, using compiler-generated copy ctor.
+ // We just need to handle the pointers in the structs:
+ for (gpgme_signature_t is = r->signatures ; is ; is = is->next) {
+ gpgme_signature_t scopy = new _gpgme_signature(*is);
+ if (is->fpr) {
+ scopy->fpr = strdup(is->fpr);
+ }
+#ifdef HAVE_GPGME_SIGNATURE_T_PKA_FIELDS
+// PENDING(marc) why does this crash on Windows in strdup()?
+# ifndef _WIN32
+ if (is->pka_address) {
+ scopy->pka_address = strdup(is->pka_address);
+ }
+# else
+ scopy->pka_address = 0;
+# endif
+#endif
+ scopy->next = 0;
+ sigs.push_back(scopy);
+ // copy notations:
+ nota.push_back(std::vector<Nota>());
+ purls.push_back(0);
+ for (gpgme_sig_notation_t in = is->notations ; in ; in = in->next) {
+ if (!in->name) {
+ if (in->value) {
+ purls.back() = strdup(in->value); // policy url
+ }
+ continue;
+ }
+#ifdef HAVE_GPGME_SIG_NOTATION_FLAGS_T
+ Nota n = { 0, 0, in->flags };
+#else
+ Nota n = { 0, 0 };
+#endif
+ n.name = strdup(in->name);
+ if (in->value) {
+ n.value = strdup(in->value);
+ }
+ nota.back().push_back(n);
+ }
+ }
+ }
+ ~Private()
+ {
+ for (std::vector<gpgme_signature_t>::iterator it = sigs.begin() ; it != sigs.end() ; ++it) {
+ std::free((*it)->fpr);
+#ifdef HAVE_GPGME_SIGNATURE_T_PKA_FIELDS
+ std::free((*it)->pka_address);
+#endif
+ delete *it; *it = 0;
+ }
+ for (std::vector< std::vector<Nota> >::iterator it = nota.begin() ; it != nota.end() ; ++it) {
+ for (std::vector<Nota>::iterator jt = it->begin() ; jt != it->end() ; ++jt) {
+ std::free(jt->name); jt->name = 0;
+ std::free(jt->value); jt->value = 0;
+ }
+ }
+ std::for_each(purls.begin(), purls.end(), &std::free);
+ }
+
+ struct Nota {
+ char *name;
+ char *value;
+#ifdef HAVE_GPGME_SIG_NOTATION_FLAGS_T
+ gpgme_sig_notation_flags_t flags;
+#endif
+ };
+
+ std::vector<gpgme_signature_t> sigs;
+ std::vector< std::vector<Nota> > nota;
+ std::vector<char *> purls;
+ std::string file_name;
+};
+
+GpgME::VerificationResult::VerificationResult(gpgme_ctx_t ctx, int error)
+ : GpgME::Result(error), d()
+{
+ init(ctx);
+}
+
+GpgME::VerificationResult::VerificationResult(gpgme_ctx_t ctx, const Error &error)
+ : GpgME::Result(error), d()
+{
+ init(ctx);
+}
+
+void GpgME::VerificationResult::init(gpgme_ctx_t ctx)
+{
+ if (!ctx) {
+ return;
+ }
+ gpgme_verify_result_t res = gpgme_op_verify_result(ctx);
+ if (!res) {
+ return;
+ }
+ d.reset(new Private(res));
+}
+
+make_standard_stuff(VerificationResult)
+
+const char *GpgME::VerificationResult::fileName() const
+{
+ return d ? d->file_name.c_str() : 0 ;
+}
+
+unsigned int GpgME::VerificationResult::numSignatures() const
+{
+ return d ? d->sigs.size() : 0 ;
+}
+
+GpgME::Signature GpgME::VerificationResult::signature(unsigned int idx) const
+{
+ return Signature(d, idx);
+}
+
+std::vector<GpgME::Signature> GpgME::VerificationResult::signatures() const
+{
+ if (!d) {
+ return std::vector<Signature>();
+ }
+ std::vector<Signature> result;
+ result.reserve(d->sigs.size());
+ for (unsigned int i = 0 ; i < d->sigs.size() ; ++i) {
+ result.push_back(Signature(d, i));
+ }
+ return result;
+}
+
+GpgME::Signature::Signature(const boost::shared_ptr<VerificationResult::Private> &parent, unsigned int i)
+ : d(parent), idx(i)
+{
+}
+
+GpgME::Signature::Signature() : d(), idx(0) {}
+
+bool GpgME::Signature::isNull() const
+{
+ return !d || idx >= d->sigs.size() ;
+}
+
+GpgME::Signature::Summary GpgME::Signature::summary() const
+{
+ if (isNull()) {
+ return None;
+ }
+ gpgme_sigsum_t sigsum = d->sigs[idx]->summary;
+ unsigned int result = 0;
+ if (sigsum & GPGME_SIGSUM_VALID) {
+ result |= Valid;
+ }
+ if (sigsum & GPGME_SIGSUM_GREEN) {
+ result |= Green;
+ }
+ if (sigsum & GPGME_SIGSUM_RED) {
+ result |= Red;
+ }
+ if (sigsum & GPGME_SIGSUM_KEY_REVOKED) {
+ result |= KeyRevoked;
+ }
+ if (sigsum & GPGME_SIGSUM_KEY_EXPIRED) {
+ result |= KeyExpired;
+ }
+ if (sigsum & GPGME_SIGSUM_SIG_EXPIRED) {
+ result |= SigExpired;
+ }
+ if (sigsum & GPGME_SIGSUM_KEY_MISSING) {
+ result |= KeyMissing;
+ }
+ if (sigsum & GPGME_SIGSUM_CRL_MISSING) {
+ result |= CrlMissing;
+ }
+ if (sigsum & GPGME_SIGSUM_CRL_TOO_OLD) {
+ result |= CrlTooOld;
+ }
+ if (sigsum & GPGME_SIGSUM_BAD_POLICY) {
+ result |= BadPolicy;
+ }
+ if (sigsum & GPGME_SIGSUM_SYS_ERROR) {
+ result |= SysError;
+ }
+ return static_cast<Summary>(result);
+}
+
+const char *GpgME::Signature::fingerprint() const
+{
+ return isNull() ? 0 : d->sigs[idx]->fpr ;
+}
+
+GpgME::Error GpgME::Signature::status() const
+{
+ return Error(isNull() ? 0 : d->sigs[idx]->status);
+}
+
+time_t GpgME::Signature::creationTime() const
+{
+ return static_cast<time_t>(isNull() ? 0 : d->sigs[idx]->timestamp);
+}
+
+time_t GpgME::Signature::expirationTime() const
+{
+ return static_cast<time_t>(isNull() ? 0 : d->sigs[idx]->exp_timestamp);
+}
+
+bool GpgME::Signature::neverExpires() const
+{
+ return expirationTime() == (time_t)0;
+}
+
+bool GpgME::Signature::isWrongKeyUsage() const
+{
+ return !isNull() && d->sigs[idx]->wrong_key_usage;
+}
+
+bool GpgME::Signature::isVerifiedUsingChainModel() const
+{
+#ifdef HAVE_GPGME_SIGNATURE_T_CHAIN_MODEL
+ return !isNull() && d->sigs[idx]->chain_model;
+#else
+ return false;
+#endif
+}
+
+GpgME::Signature::PKAStatus GpgME::Signature::pkaStatus() const
+{
+#ifdef HAVE_GPGME_SIGNATURE_T_PKA_FIELDS
+ if (!isNull()) {
+ return static_cast<PKAStatus>(d->sigs[idx]->pka_trust);
+ }
+#endif
+ return UnknownPKAStatus;
+}
+
+const char *GpgME::Signature::pkaAddress() const
+{
+#ifdef HAVE_GPGME_SIGNATURE_T_PKA_FIELDS
+ if (!isNull()) {
+ return d->sigs[idx]->pka_address;
+ }
+#endif
+ return 0;
+}
+
+GpgME::Signature::Validity GpgME::Signature::validity() const
+{
+ if (isNull()) {
+ return Unknown;
+ }
+ switch (d->sigs[idx]->validity) {
+ default:
+ case GPGME_VALIDITY_UNKNOWN: return Unknown;
+ case GPGME_VALIDITY_UNDEFINED: return Undefined;
+ case GPGME_VALIDITY_NEVER: return Never;
+ case GPGME_VALIDITY_MARGINAL: return Marginal;
+ case GPGME_VALIDITY_FULL: return Full;
+ case GPGME_VALIDITY_ULTIMATE: return Ultimate;
+ }
+}
+
+char GpgME::Signature::validityAsString() const
+{
+ if (isNull()) {
+ return '?';
+ }
+ switch (d->sigs[idx]->validity) {
+ default:
+ case GPGME_VALIDITY_UNKNOWN: return '?';
+ case GPGME_VALIDITY_UNDEFINED: return 'q';
+ case GPGME_VALIDITY_NEVER: return 'n';
+ case GPGME_VALIDITY_MARGINAL: return 'm';
+ case GPGME_VALIDITY_FULL: return 'f';
+ case GPGME_VALIDITY_ULTIMATE: return 'u';
+ }
+}
+
+GpgME::Error GpgME::Signature::nonValidityReason() const
+{
+ return Error(isNull() ? 0 : d->sigs[idx]->validity_reason);
+}
+
+unsigned int GpgME::Signature::publicKeyAlgorithm() const
+{
+#ifdef HAVE_GPGME_SIGNATURE_T_ALGORITHM_FIELDS
+ if (!isNull()) {
+ return d->sigs[idx]->pubkey_algo;
+ }
+#endif
+ return 0;
+}
+
+const char *GpgME::Signature::publicKeyAlgorithmAsString() const
+{
+#ifdef HAVE_GPGME_SIGNATURE_T_ALGORITHM_FIELDS
+ if (!isNull()) {
+ return gpgme_pubkey_algo_name(d->sigs[idx]->pubkey_algo);
+ }
+#endif
+ return 0;
+}
+
+unsigned int GpgME::Signature::hashAlgorithm() const
+{
+#ifdef HAVE_GPGME_SIGNATURE_T_ALGORITHM_FIELDS
+ if (!isNull()) {
+ return d->sigs[idx]->hash_algo;
+ }
+#endif
+ return 0;
+}
+
+const char *GpgME::Signature::hashAlgorithmAsString() const
+{
+#ifdef HAVE_GPGME_SIGNATURE_T_ALGORITHM_FIELDS
+ if (!isNull()) {
+ return gpgme_hash_algo_name(d->sigs[idx]->hash_algo);
+ }
+#endif
+ return 0;
+}
+
+const char *GpgME::Signature::policyURL() const
+{
+ return isNull() ? 0 : d->purls[idx] ;
+}
+
+GpgME::Notation GpgME::Signature::notation(unsigned int nidx) const
+{
+ return GpgME::Notation(d, idx, nidx);
+}
+
+std::vector<GpgME::Notation> GpgME::Signature::notations() const
+{
+ if (isNull()) {
+ return std::vector<GpgME::Notation>();
+ }
+ std::vector<GpgME::Notation> result;
+ result.reserve(d->nota[idx].size());
+ for (unsigned int i = 0 ; i < d->nota[idx].size() ; ++i) {
+ result.push_back(GpgME::Notation(d, idx, i));
+ }
+ return result;
+}
+
+class GpgME::Notation::Private
+{
+public:
+ Private() : d(), sidx(0), nidx(0), nota(0) {}
+ Private(const boost::shared_ptr<VerificationResult::Private> &priv, unsigned int sindex, unsigned int nindex)
+ : d(priv), sidx(sindex), nidx(nindex), nota(0)
+ {
+
+ }
+ Private(gpgme_sig_notation_t n)
+ : d(), sidx(0), nidx(0), nota(n ? new _gpgme_sig_notation(*n) : 0)
+ {
+ if (nota && nota->name) {
+ nota->name = strdup(nota->name);
+ }
+ if (nota && nota->value) {
+ nota->value = strdup(nota->value);
+ }
+ }
+ Private(const Private &other)
+ : d(other.d), sidx(other.sidx), nidx(other.nidx), nota(other.nota)
+ {
+ if (nota) {
+ nota->name = strdup(nota->name);
+ nota->value = strdup(nota->value);
+ }
+ }
+ ~Private()
+ {
+ if (nota) {
+ std::free(nota->name); nota->name = 0;
+ std::free(nota->value); nota->value = 0;
+ delete nota;
+ }
+ }
+
+ boost::shared_ptr<VerificationResult::Private> d;
+ unsigned int sidx, nidx;
+ gpgme_sig_notation_t nota;
+};
+
+GpgME::Notation::Notation(const boost::shared_ptr<VerificationResult::Private> &parent, unsigned int sindex, unsigned int nindex)
+ : d(new Private(parent, sindex, nindex))
+{
+
+}
+
+GpgME::Notation::Notation(gpgme_sig_notation_t nota)
+ : d(new Private(nota))
+{
+
+}
+
+GpgME::Notation::Notation() : d() {}
+
+bool GpgME::Notation::isNull() const
+{
+ if (!d) {
+ return true;
+ }
+ if (d->d) {
+ return d->sidx >= d->d->nota.size() || d->nidx >= d->d->nota[d->sidx].size() ;
+ }
+ return !d->nota;
+}
+
+const char *GpgME::Notation::name() const
+{
+ return
+ isNull() ? 0 :
+ d->d ? d->d->nota[d->sidx][d->nidx].name :
+ d->nota ? d->nota->name : 0 ;
+}
+
+const char *GpgME::Notation::value() const
+{
+ return
+ isNull() ? 0 :
+ d->d ? d->d->nota[d->sidx][d->nidx].value :
+ d->nota ? d->nota->value : 0 ;
+}
+
+GpgME::Notation::Flags GpgME::Notation::flags() const
+{
+ return
+ convert_from_gpgme_sig_notation_flags_t(
+#ifdef HAVE_GPGME_SIG_NOTATION_FLAGS_T
+ isNull() ? 0 :
+ d->d ? d->d->nota[d->sidx][d->nidx].flags :
+ d->nota ? d->nota->flags : 0);
+#else
+ 0);
+#endif
+}
+
+bool GpgME::Notation::isHumanReadable() const
+{
+ return flags() & HumanReadable;
+}
+
+bool GpgME::Notation::isCritical() const
+{
+ return flags() & Critical;
+}
+
+std::ostream &GpgME::operator<<(std::ostream &os, const VerificationResult &result)
+{
+ os << "GpgME::VerificationResult(";
+ if (!result.isNull()) {
+ os << "\n error: " << result.error()
+ << "\n fileName: " << protect(result.fileName())
+ << "\n signatures:\n";
+ const std::vector<Signature> sigs = result.signatures();
+ std::copy(sigs.begin(), sigs.end(),
+ std::ostream_iterator<Signature>(os, "\n"));
+ }
+ return os << ')';
+}
+
+std::ostream &GpgME::operator<<(std::ostream &os, Signature::PKAStatus pkaStatus)
+{
+#define OUTPUT( x ) if ( !(pkaStatus & (GpgME::Signature:: x)) ) {} else do { os << #x " "; } while(0)
+ os << "GpgME::Signature::PKAStatus(";
+ OUTPUT(UnknownPKAStatus);
+ OUTPUT(PKAVerificationFailed);
+ OUTPUT(PKAVerificationSucceeded);
+#undef OUTPUT
+ return os << ')';
+}
+
+std::ostream &GpgME::operator<<(std::ostream &os, Signature::Summary summary)
+{
+#define OUTPUT( x ) if ( !(summary & (GpgME::Signature:: x)) ) {} else do { os << #x " "; } while(0)
+ os << "GpgME::Signature::Summary(";
+ OUTPUT(Valid);
+ OUTPUT(Green);
+ OUTPUT(Red);
+ OUTPUT(KeyRevoked);
+ OUTPUT(KeyExpired);
+ OUTPUT(SigExpired);
+ OUTPUT(KeyMissing);
+ OUTPUT(CrlMissing);
+ OUTPUT(CrlTooOld);
+ OUTPUT(BadPolicy);
+ OUTPUT(SysError);
+#undef OUTPUT
+ return os << ')';
+}
+
+std::ostream &GpgME::operator<<(std::ostream &os, const Signature &sig)
+{
+ os << "GpgME::Signature(";
+ if (!sig.isNull()) {
+ os << "\n Summary: " << sig.summary()
+ << "\n Fingerprint: " << protect(sig.fingerprint())
+ << "\n Status: " << sig.status()
+ << "\n creationTime: " << sig.creationTime()
+ << "\n expirationTime: " << sig.expirationTime()
+ << "\n isWrongKeyUsage: " << sig.isWrongKeyUsage()
+ << "\n isVerifiedUsingChainModel: " << sig.isVerifiedUsingChainModel()
+ << "\n pkaStatus: " << sig.pkaStatus()
+ << "\n pkaAddress: " << protect(sig.pkaAddress())
+ << "\n validity: " << sig.validityAsString()
+ << "\n nonValidityReason: " << sig.nonValidityReason()
+ << "\n publicKeyAlgorithm: " << protect(sig.publicKeyAlgorithmAsString())
+ << "\n hashAlgorithm: " << protect(sig.hashAlgorithmAsString())
+ << "\n policyURL: " << protect(sig.policyURL())
+ << "\n notations:\n";
+ const std::vector<Notation> nota = sig.notations();
+ std::copy(nota.begin(), nota.end(),
+ std::ostream_iterator<Notation>(os, "\n"));
+ }
+ return os << ')';
+}
+
+std::ostream &GpgME::operator<<(std::ostream &os, Notation::Flags flags)
+{
+ os << "GpgME::Notation::Flags(";
+#define OUTPUT( x ) if ( !(flags & (GpgME::Notation:: x)) ) {} else do { os << #x " "; } while(0)
+ OUTPUT(HumanReadable);
+ OUTPUT(Critical);
+#undef OUTPUT
+ return os << ')';
+}
+
+std::ostream &GpgME::operator<<(std::ostream &os, const Notation ¬a)
+{
+ os << "GpgME::Signature::Notation(";
+ if (!nota.isNull()) {
+ os << "\n name: " << protect(nota.name())
+ << "\n value: " << protect(nota.value())
+ << "\n flags: " << nota.flags()
+ << '\n';
+ }
+ return os << ")";
+}
diff --git a/lang/cpp/src/verificationresult.h b/lang/cpp/src/verificationresult.h
new file mode 100644
index 0000000..8372d88
--- /dev/null
+++ b/lang/cpp/src/verificationresult.h
@@ -0,0 +1,173 @@
+/*
+ verificationresult.h - wraps a gpgme verify result
+ Copyright (C) 2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_VERIFICATIONRESULT_H__
+#define __GPGMEPP_VERIFICATIONRESULT_H__
+
+#include "gpgmefw.h"
+#include "result.h"
+#include "gpgmepp_export.h"
+
+#include <time.h>
+
+#include <boost/shared_ptr.hpp>
+
+#include <vector>
+#include <iosfwd>
+
+namespace GpgME
+{
+
+class Error;
+class Signature;
+class Notation;
+
+class GPGMEPP_EXPORT VerificationResult : public Result
+{
+public:
+ VerificationResult();
+ VerificationResult(gpgme_ctx_t ctx, int error);
+ VerificationResult(gpgme_ctx_t ctx, const Error &error);
+ explicit VerificationResult(const Error &err);
+
+ const VerificationResult &operator=(VerificationResult other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(VerificationResult &other)
+ {
+ Result::swap(other);
+ using std::swap;
+ swap(this->d, other.d);
+ }
+
+ bool isNull() const;
+
+ const char *fileName() const;
+
+ unsigned int numSignatures() const;
+ Signature signature(unsigned int index) const;
+ std::vector<Signature> signatures() const;
+
+ class Private;
+private:
+ void init(gpgme_ctx_t ctx);
+ boost::shared_ptr<Private> d;
+};
+
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const VerificationResult &result);
+
+class GPGMEPP_EXPORT Signature
+{
+ friend class ::GpgME::VerificationResult;
+ Signature(const boost::shared_ptr<VerificationResult::Private> &parent, unsigned int index);
+public:
+ typedef GPGMEPP_DEPRECATED GpgME::Notation Notation;
+
+ Signature();
+
+ const Signature &operator=(Signature other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(Signature &other)
+ {
+ using std::swap;
+ swap(this->d, other.d);
+ swap(this->idx, other.idx);
+ }
+
+ bool isNull() const;
+
+ enum Summary {
+ None = 0x000,
+ Valid = 0x001,
+ Green = 0x002,
+ Red = 0x004,
+ KeyRevoked = 0x008,
+ KeyExpired = 0x010,
+ SigExpired = 0x020,
+ KeyMissing = 0x040,
+ CrlMissing = 0x080,
+ CrlTooOld = 0x100,
+ BadPolicy = 0x200,
+ SysError = 0x400
+ };
+ Summary summary() const;
+
+ const char *fingerprint() const;
+
+ Error status() const;
+
+ time_t creationTime() const;
+ time_t expirationTime() const;
+ bool neverExpires() const;
+
+ GPGMEPP_DEPRECATED bool wrongKeyUsage() const
+ {
+ return isWrongKeyUsage();
+ }
+ bool isWrongKeyUsage() const;
+ bool isVerifiedUsingChainModel() const;
+
+ enum PKAStatus {
+ UnknownPKAStatus, PKAVerificationFailed, PKAVerificationSucceeded
+ };
+ PKAStatus pkaStatus() const;
+ const char *pkaAddress() const;
+
+ enum Validity {
+ Unknown, Undefined, Never, Marginal, Full, Ultimate
+ };
+ Validity validity() const;
+ char validityAsString() const;
+ Error nonValidityReason() const;
+
+ unsigned int publicKeyAlgorithm() const;
+ const char *publicKeyAlgorithmAsString() const;
+
+ unsigned int hashAlgorithm() const;
+ const char *hashAlgorithmAsString() const;
+
+ const char *policyURL() const;
+ GpgME::Notation notation(unsigned int index) const;
+ std::vector<GpgME::Notation> notations() const;
+
+private:
+ boost::shared_ptr<VerificationResult::Private> d;
+ unsigned int idx;
+};
+
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const Signature &sig);
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, Signature::PKAStatus pkaStatus);
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, Signature::Summary summary);
+
+}
+
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(VerificationResult)
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(Signature)
+
+#endif // __GPGMEPP_VERIFICATIONRESULT_H__
diff --git a/lang/cpp/src/vfsmountresult.cpp b/lang/cpp/src/vfsmountresult.cpp
new file mode 100644
index 0000000..deca627
--- /dev/null
+++ b/lang/cpp/src/vfsmountresult.cpp
@@ -0,0 +1,98 @@
+/*
+ vfsmountresult.cpp - wraps a gpgme vfs mount result
+ Copyright (C) 2009 Klarälvdalens Datakonsult AB <info at kdab.com>
+ Author: Marc Mutz <marc at kdab.com>, Volker Krause <volker at kdab.com>
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <config-gpgme++.h>
+
+#include <vfsmountresult.h>
+#include "result_p.h"
+
+#include <gpgme.h>
+
+#include <istream>
+#include <string.h>
+
+using namespace GpgME;
+
+#ifdef HAVE_GPGME_G13_VFS
+class VfsMountResult::Private
+{
+public:
+ explicit Private(const gpgme_vfs_mount_result_t r) : mountDir(0)
+ {
+ if (r && r->mount_dir) {
+ mountDir = strdup(r->mount_dir);
+ }
+ }
+
+ ~Private()
+ {
+ std::free(mountDir);
+ }
+
+ char *mountDir;
+};
+#endif
+
+VfsMountResult::VfsMountResult(gpgme_ctx_t ctx, const Error &error, const Error &opError)
+ : Result(error ? error : opError), d()
+{
+ init(ctx);
+}
+
+void VfsMountResult::init(gpgme_ctx_t ctx)
+{
+ (void)ctx;
+#ifdef HAVE_GPGME_G13_VFS
+ if (!ctx) {
+ return;
+ }
+ gpgme_vfs_mount_result_t res = gpgme_op_vfs_mount_result(ctx);
+ if (!res) {
+ return;
+ }
+ d.reset(new Private(res));
+#endif
+}
+
+make_standard_stuff(VfsMountResult)
+
+const char *VfsMountResult::mountDir() const
+{
+#ifdef HAVE_GPGME_G13_VFS
+ if (d) {
+ return d->mountDir;
+ }
+#endif
+ return 0;
+}
+
+std::ostream &GpgME::operator<<(std::ostream &os, const VfsMountResult &result)
+{
+ os << "GpgME::VfsMountResult(";
+ if (!result.isNull()) {
+ os << "\n error: " << result.error()
+ << "\n mount dir: " << result.mountDir()
+ << "\n";
+ }
+ return os << ')';
+}
diff --git a/lang/cpp/src/vfsmountresult.h b/lang/cpp/src/vfsmountresult.h
new file mode 100644
index 0000000..0f06bd2
--- /dev/null
+++ b/lang/cpp/src/vfsmountresult.h
@@ -0,0 +1,76 @@
+/*
+ vfsmountresult.h - wraps a gpgme vfs mount result
+ Copyright (C) 2009 Klarälvdalens Datakonsult AB <info at kdab.com>
+ Author: Marc Mutz <marc at kdab.com>, Volker Krause <volker at kdab.com>
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_VFSMOUNTRESULT_H__
+#define __GPGMEPP_VFSMOUNTRESULT_H__
+
+#include "gpgmefw.h"
+#include "result.h"
+#include "gpgmepp_export.h"
+
+#include <boost/shared_ptr.hpp>
+
+#include <vector>
+#include <iosfwd>
+
+namespace GpgME
+{
+
+class Error;
+
+class GPGMEPP_EXPORT VfsMountResult : public Result
+{
+public:
+ VfsMountResult();
+ VfsMountResult(gpgme_ctx_t ctx, const Error &error, const Error &opError);
+ explicit VfsMountResult(const Error &err);
+
+ const VfsMountResult &operator=(VfsMountResult other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(VfsMountResult &other)
+ {
+ Result::swap(other);
+ using std::swap;
+ swap(this->d, other.d);
+ }
+
+ bool isNull() const;
+ const char *mountDir() const;
+
+ class Private;
+private:
+ void init(gpgme_ctx_t ctx);
+ boost::shared_ptr<Private> d;
+};
+
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const VfsMountResult &result);
+
+}
+
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(VfsMountResult)
+
+#endif // __GPGMEPP_ASSUANRESULT_H__
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-gnupg/gpgme.git
More information about the Pkg-gnupg-commit
mailing list