diff options
Diffstat (limited to 'libtdenetwork/gpgmepp')
47 files changed, 6288 insertions, 0 deletions
diff --git a/libtdenetwork/gpgmepp/CMakeLists.txt b/libtdenetwork/gpgmepp/CMakeLists.txt new file mode 100644 index 000000000..cf4efc7f7 --- /dev/null +++ b/libtdenetwork/gpgmepp/CMakeLists.txt @@ -0,0 +1,54 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +add_subdirectory( interfaces ) + +include_directories( + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/libtdenetwork + ${CMAKE_SOURCE_DIR}/libtdepim + ${TDE_INCLUDE_DIR} + ${TQT_INCLUDE_DIRS} + ${GPGME_INCLUDE_DIRS} +) + +link_directories( + ${TQT_LIBRARY_DIRS} +) + + +##### headers ################################### + +install( FILES + context.h key.h trustitem.h eventloopinteractor.h + data.h gpgmefw.h result.h keylistresult.h + keygenerationresult.h importresult.h decryptionresult.h + verificationresult.h signingresult.h encryptionresult.h + engineinfo.h + DESTINATION ${INCLUDE_INSTALL_DIR}/kde/gpgme++ ) + + +##### gpgme++ (shared) ########################## + +tde_add_library( gpgme++ SHARED + SOURCES + context.cpp key.cpp trustitem.cpp data.cpp + callbacks.cpp eventloopinteractor.cpp + keylistresult.cpp keygenerationresult.cpp + importresult.cpp decryptionresult.cpp + verificationresult.cpp signingresult.cpp + encryptionresult.cpp engineinfo.cpp + VERSION 0.4.0 + LINK ${TQT_LIBRARIES} ${GPGME_LIBRARIES} + DESTINATION ${LIB_INSTALL_DIR} +) diff --git a/libtdenetwork/gpgmepp/Makefile.am b/libtdenetwork/gpgmepp/Makefile.am new file mode 100644 index 000000000..d4ebfde99 --- /dev/null +++ b/libtdenetwork/gpgmepp/Makefile.am @@ -0,0 +1,52 @@ +KDE_OPTIONS = foreign +#AM_CXXFLAGS = -Wno-deprecated-declarations + +SUBDIRS = interfaces . + +INCLUDES = -I$(top_srcdir)/libtdenetwork -I$(top_srcdir)/libtdenetwork/gpgmepp \ + $(GPGME_CFLAGS) $(all_includes) + +gpgmeppdir = $(includedir)/gpgme++ +gpgmepp_HEADERS = context.h \ + key.h \ + trustitem.h \ + eventloopinteractor.h \ + data.h \ + gpgmefw.h \ + result.h \ + keylistresult.h \ + keygenerationresult.h \ + importresult.h \ + decryptionresult.h \ + verificationresult.h \ + signingresult.h \ + encryptionresult.h \ + engineinfo.h + +noinst_HEADERS = context_p.h data_p.h shared.h callbacks.h gpgme-0-3-compat.h result_p.h util.h + +lib_LTLIBRARIES = libgpgme++.la +libgpgme___la_SOURCES = context.cpp \ + key.cpp \ + trustitem.cpp \ + data.cpp \ + callbacks.cpp \ + eventloopinteractor.cpp \ + keylistresult.cpp \ + keygenerationresult.cpp \ + importresult.cpp \ + decryptionresult.cpp \ + verificationresult.cpp \ + signingresult.cpp \ + encryptionresult.cpp \ + engineinfo.cpp + +# --version-info CURRENT:REVISION:AGE +# (Code changed: REVISION++) +# (Interfaces added/removed/changed: CURRENT++, REVISION=0) +# (Interfaces added: AGE++) +# (Interfaces removed/changed: AGE=0) +libgpgme___la_LDFLAGS = -no-undefined -version-info 4:0:4 +libgpgme___la_LIBADD = $(GPGME_LIBS) +libgpgme___la_DEPENDENCIES = $(GPGME_LIBS_DEP) + diff --git a/libtdenetwork/gpgmepp/README.gpgme++ b/libtdenetwork/gpgmepp/README.gpgme++ new file mode 100644 index 000000000..ecda2c9ac --- /dev/null +++ b/libtdenetwork/gpgmepp/README.gpgme++ @@ -0,0 +1,82 @@ + GpgME++ - C++ bindings/wrapper for gpgme + ------------------------------------ + Version 0.0.1 + + Copyright (c) 2003, 2004 Klar�lvdalens Datakonsult AB + + This file is free software; as a special exception the author gives + unlimited permission to copy and/or distribute it, with or without + modifications, as long as this notice is preserved. + + This file is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY, to the extent permitted by law; without even the + implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + + + Overview + -------- + + GpgME++ is a C++ wrapper (or C++ bindings) for the GnuPG project's + gpgme (GnuPG Made Easy) library, version 0.4.4 and later. + + It is fairly complete, with some minor things still missing (in + particular, the key edit interface). It is mostly tested using + external event loops, for which its design is optimised. + + The design principles of this library are as follows: + + 1. A value-based interface (most clases are implicitly shared) + 2. Callbacks are replaced by C++ interfaces (classes with only + abstract methods). + 3. No exceptions are thrown + 4. There is (as yet) no explicit support for multi-threaded use + (other than what gpgme itself provides; most notably the + refcounting for implicit sharing is not thread-safe) + 5. To avoid binary incompatible interface changes, we make + extensive use of the d-pointer pattern and avoid virtual + methods; any polymorphism present is already provided by gpgme + itself, anyway (see e.g. Data). A notable exception of the + no-virtuals rule is the use of abstract classes to cover + C-callbacks. + + The authors hope that once there are more users of this library, + the GnuPG project will include it as the official C++ binding for + gpgme. Currently, this is not the case, since it was felt that C++ + bindings can be provided with different design decisions, and that + it is not clear that the decisions made for GpgME++ are broad + enough to be universally applicable (e.g. a pivotal design + decision was to not use exceptions to wrap gpgme_error_t). + + GpgME++ depends on gpgme, which in turn depends on libgpg-error, both + of which must be installed correctly before GpgME++ is to be + built. Furthermore, GpgME++ should be recompiled if the underlying + gpgme is changed. This is to allow closer integration and to + abstract away possible interface changes. Therefore, once this + libray becomes stable, we intend to follow gpgme's versioning. + + Currently, we use the KDE CVS repository to develop our code, + basically because GpgME++ is used in KMail and Kleopatra. However, + the library is in no way dependant on KDE or Qt libraries, and you + are free to use it in your own projects, provided you follow the + license. If you _do_ want to use GpgME++ in Qt/KDE applications, + have a look at QGpgME, which provides integration with QEventLoop + and some Qt datatypes (e.g. QByteArray). + + + Mailing List + ------------ + + Discussion of this library and questions regarding it's use and + design should happen on [email protected] or [email protected]. + + + License + ------- + + This library is licensed under the GNU General Public License + (GPL), just as gpgme is. We feel that using a different license + than the one gpgme itself uses doesn't make sense. OTOH, we shall + relicense this library to the GNU Lesser General Public License + (LGPL) should gpgme itself be made available under this license at + any time in the future. diff --git a/libtdenetwork/gpgmepp/callbacks.cpp b/libtdenetwork/gpgmepp/callbacks.cpp new file mode 100644 index 000000000..b352515d0 --- /dev/null +++ b/libtdenetwork/gpgmepp/callbacks.cpp @@ -0,0 +1,138 @@ +/* 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 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GPGME; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "callbacks.h" + +#include <gpgmepp/interfaces/progressprovider.h> +#include <gpgmepp/interfaces/passphraseprovider.h> +#include <gpgmepp/interfaces/dataprovider.h> +#include <gpgmepp/context.h> // for Error + +#include <cassert> +#include <cerrno> +#include <unistd.h> +#include <cstdlib> +#include <string.h> +#include <cstdlib> + +static inline gpg_error_t makeErrorFromErrno() { + return gpg_err_make_from_errno( (gpg_err_source_t)22, errno ); +} +static inline gpg_error_t makeError( gpg_err_code_t code ) { + return gpg_err_make( (gpg_err_source_t)22, code ); +} + +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 ); +} + +static void wipe( char * buf, size_t len ) { + for ( size_t i = 0 ; i < len ; ++i ) + buf[i] = '\0'; +} + +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 = makeError( GPG_ERR_CANCELED ); + else + if ( passphrase && *passphrase ) { + size_t passphrase_length = strlen( passphrase ); + size_t written = 0; + do { + ssize_t now_written = write( fd, passphrase + written, passphrase_length - written ); + if ( now_written < 0 ) { + err = makeErrorFromErrno(); + break; + } + written += now_written; + } while ( written < passphrase_length ); + } + + if ( passphrase && *passphrase ) + wipe( passphrase, strlen( passphrase ) ); + free( passphrase ); + write( fd, "\n", 1 ); + return err; +} + + + +static ssize_t +data_read_callback( void * opaque, void * buf, size_t buflen ) { + DataProvider * provider = static_cast<DataProvider*>( opaque ); + if ( !provider ) { + errno = EINVAL; + return -1; + } + return provider->read( buf, buflen ); +} + +static ssize_t +data_write_callback( void * opaque, const void * buf, size_t buflen ) { + DataProvider * provider = static_cast<DataProvider*>( opaque ); + if ( !provider ) { + errno = EINVAL; + return -1; + } + return provider->write( buf, buflen ); +} + +static off_t +data_seek_callback( void * opaque, off_t offset, int whence ) { + DataProvider * provider = static_cast<DataProvider*>( opaque ); + if ( !provider ) { + errno = EINVAL; + return -1; + } + if ( whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END ) { + errno = EINVAL; + return -1; + } + return provider->seek( offset, whence ); +} + +static void data_release_callback( void * opaque ) { + DataProvider * provider = static_cast<DataProvider*>( opaque ); + if ( provider ) + provider->release(); +} + +gpgme_data_cbs data_provider_callbacks = { + &data_read_callback, + &data_write_callback, + &data_seek_callback, + &data_release_callback +}; + diff --git a/libtdenetwork/gpgmepp/callbacks.h b/libtdenetwork/gpgmepp/callbacks.h new file mode 100644 index 000000000..cc5b93552 --- /dev/null +++ b/libtdenetwork/gpgmepp/callbacks.h @@ -0,0 +1,39 @@ +/* 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 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GPGME++; 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 ); +} + +extern gpgme_data_cbs data_provider_callbacks; + +#endif // __GPGME_CALLBACKS_H__ diff --git a/libtdenetwork/gpgmepp/configure.in.bot b/libtdenetwork/gpgmepp/configure.in.bot new file mode 100644 index 000000000..e4b1a8842 --- /dev/null +++ b/libtdenetwork/gpgmepp/configure.in.bot @@ -0,0 +1,10 @@ +if test -z "$GPGME_LIBS" || test -n "$tdepim_needs_gpgme_copy" ; then + echo + echo "You are missing gpgme 0.4.5 or higher." + echo "Gpgme will be built statically from libtdenetwork/libgpgme-copy." + echo "If you are a packager, we most strongly recommend to build against" + echo "the system's shared gpgme." + echo "Consider downloading gpgme >= 0.4.5 from ftp://ftp.gnupg.org/gcrypt/alpha/gpgme" + echo "or use the --with-gpgme-prefix=/path/where/gpgme/is/installed option." + echo +fi diff --git a/libtdenetwork/gpgmepp/configure.in.in b/libtdenetwork/gpgmepp/configure.in.in new file mode 100644 index 000000000..6361be451 --- /dev/null +++ b/libtdenetwork/gpgmepp/configure.in.in @@ -0,0 +1,193 @@ +dnl BEGIN inline of gpgme.m4 from gpgme 0.4.4 +dnl remaned from AM_PATH_GPGME to TDEPIM_PATH_GPGME and inlined here +dnl to not require aclocal fiddling... + +dnl Autoconf macros for libgpgme +dnl Id: gpgme.m4,v 1.6 2003/09/03 01:15:56 marcus Exp + +AC_DEFUN([_TDEPIM_PATH_GPGME_CONFIG], +[ AC_ARG_WITH(gpgme-prefix, + AC_HELP_STRING([--with-gpgme-prefix=PFX], + [prefix where GPGME is installed (optional)]), + gpgme_config_prefix="$withval", gpgme_config_prefix="") + if test "x$gpgme_config_prefix" != x ; then + gpgme_config_path="$gpgme_config_prefix/bin" + else + gpgme_config_path="$PATH:/usr/local/bin" + fi + AC_PATH_PROG(GPGME_CONFIG, gpgme-config, no, $gpgme_config_path) + + if test "x$GPGME_CONFIG" != "xno" ; then + gpgme_version=`$GPGME_CONFIG --version` + gpgme_version_major=`echo $gpgme_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\1/'` + gpgme_version_minor=`echo $gpgme_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\2/'` + gpgme_version_micro=`echo $gpgme_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\).*/\3/'` + fi +]) + +dnl AM_PATH_GPGME([MINIMUM-VERSION, +dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND ]]]) +dnl Test for libgpgme and define GPGME_CFLAGS and GPGME_LIBS. +dnl +AC_DEFUN([TDEPIM_PATH_GPGME], +[ AC_REQUIRE([_TDEPIM_PATH_GPGME_CONFIG])dnl + min_gpgme_version=ifelse([$1], ,0.4.2,$1) + AC_MSG_CHECKING(for GPGME - version >= $min_gpgme_version) + ok=no + if test "$GPGME_CONFIG" != "no" ; then + req_major=`echo $min_gpgme_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\1/'` + req_minor=`echo $min_gpgme_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\2/'` + req_micro=`echo $min_gpgme_version | \ + sed 's/\([[0-9]]*\)\.\([[0-9]]*\)\.\([[0-9]]*\)/\3/'` + if test "$gpgme_version_major" -gt "$req_major"; then + ok=yes + else + if test "$gpgme_version_major" -eq "$req_major"; then + if test "$gpgme_version_minor" -gt "$req_minor"; then + ok=yes + else + if test "$gpgme_version_minor" -eq "$req_minor"; then + if test "$gpgme_version_micro" -ge "$req_micro"; then + ok=yes + fi + fi + fi + fi + fi + fi + if test $ok = yes; then + GPGME_CFLAGS=`$GPGME_CONFIG --cflags` + GPGME_LIBS=`$GPGME_CONFIG --libs` + if test "x$GPGME_LIBS" != x ; then + if test "x`echo $GPGME_LIBS | grep lgpg-error`" = x ; then + GPGME_LIBS="$GPGME_LIBS -lgpg-error" + fi + fi + AC_MSG_RESULT([yes]) + ifelse([$2], , :, [$2]) + else + GPGME_CFLAGS="" + GPGME_LIBS="" + AC_MSG_RESULT([no, will use local libgpgme-copy]) + ifelse([$3], , :, [$3]) + fi + AC_SUBST(GPGME_CFLAGS) + AC_SUBST(GPGME_LIBS) +]) + +dnl +dnl snip AM_PATH_GPGME_{PTH,PTHREAD} +dnl + +dnl END inline of gpgme.m4 + +# The minimum required gpgme version is 0.4.5. +# It was the first useable one for C++ (class keyword) and KDE (largefile support). +# If you change this minimum version here, update also configure.in.bot + +tdepim_needs_gpgme_copy="" +TDEPIM_PATH_GPGME(0.4.5,[ + AC_LANG_SAVE + AC_LANG_C + tdepim_gpgmepp_save_cflags="$CFLAGS" + tdepim_gpgmepp_save_libs="$LIBS" + CFLAGS="$GPGME_CFLAGS" + LIBS="$GPGME_LIBS" + + AC_MSG_CHECKING([if gpgme has GPGME_KEYLIST_MODE_VALIDATE]) + AC_TRY_COMPILE([#include <gpgme.h>], [ + gpgme_keylist_mode_t mode = GPGME_KEYLIST_MODE_VALIDATE; + ], [ + AC_DEFINE(HAVE_GPGME_KEYLIST_MODE_VALIDATE, 1, [Define to 1 if your gpgme supports GPGME_KEYLIST_MODE_VALIDATE]) + AC_MSG_RESULT([yes]) + ], [ + AC_MSG_RESULT([no]) + ]) + + AC_MSG_CHECKING([if gpgme has gpgme_cancel]) + AC_TRY_LINK([#include <gpgme.h>], [ + gpgme_ctx_t ctx = 0; + gpgme_error_t e = gpgme_cancel( ctx ); + ], [ + AC_DEFINE(HAVE_GPGME_CANCEL, 1, [Define to 1 if your gpgme supports gpgme_cancel()]) + AC_MSG_RESULT([yes]) + ], [ + AC_MSG_RESULT([no]) + ]) + + AC_MSG_CHECKING([if gpgme has gpgme_key_t->keylist_mode]) + AC_TRY_COMPILE([#include <gpgme.h>], [ + gpgme_key_t key = 0; + key->keylist_mode = 0; + ], [ + AC_DEFINE(HAVE_GPGME_KEY_T_KEYLIST_MODE, 1, [Define to 1 if your gpgme's gpgme_key_t has the keylist_mode member]) + AC_MSG_RESULT([yes]) + ], [ + AC_MSG_RESULT([no]) + ]) + + AC_MSG_CHECKING([if gpgme has gpgme_decrypt_result_t->wrong_key_usage]) + AC_TRY_COMPILE([#include <gpgme.h>], [ + gpgme_decrypt_result_t res; + unsigned int wku = res->wrong_key_usage; + ], [ + AC_DEFINE(HAVE_GPGME_WRONG_KEY_USAGE, 1, [Define to 1 if your gpgme's gpgme_decrypt_result_t has the wrong_key_usage member]) + AC_MSG_RESULT([yes]) + ], [ + AC_MSG_RESULT([no]) + ]) + + AC_MSG_CHECKING([if gpgme has GPGME_INCLUDE_CERTS_DEFAULT]) + AC_TRY_COMPILE([#include <gpgme.h>], [ + int i = GPGME_INCLUDE_CERTS_DEFAULT; + ], [ + AC_DEFINE(HAVE_GPGME_INCLUDE_CERTS_DEFAULT, 1, [Define to 1 if your gpgme has the GPGME_INCLUDE_CERTS_DEFAULT macro]) + AC_MSG_RESULT([yes]) + ], [ + AC_MSG_RESULT([no]) + ]) + + AC_MSG_CHECKING([if gpgme has gpgme_op_getauditlog]) + AC_TRY_LINK([#include <gpgme.h>], [ + gpgme_ctx_t ctx = 0; + gpgme_data_t data = 0; + unsigned int flags = 0; + gpgme_error_t e = gpgme_op_getauditlog( ctx, data, flags ); + ], [ + AC_DEFINE(HAVE_GPGME_OP_GETAUDITLOG, 1, [Define to 1 if your gpgme supports gpgme_op_getauditlog]) + AC_MSG_RESULT([yes]) + ], [ + AC_MSG_RESULT([no]) + ]) + + CFLAGS="$tdepim_gpgmepp_save_cflags" + LIBS="$tdepim_gpgmepp_save_libs" + AC_LANG_RESTORE + +],[ + tdepim_needs_gpgme_copy="true" + GPGME_CFLAGS='-I$(top_srcdir)/libtdenetwork/libgpgme-copy/gpgme -I$(top_srcdir)/libtdenetwork/libgpg-error-copy -I$(top_builddir)/libtdenetwork/libgpg-error-copy' + GPGME_LIBS='$(top_builddir)/libtdenetwork/libgpgme-copy/gpgme/libgpgme.la' + GPGME_LIBS_DEP='$(GPGME_LIBS)' + # All of this is in gpgme-copy + AC_DEFINE(HAVE_GPGME_KEYLIST_MODE_VALIDATE, 1, [Define to 1 if your gpgme supports GPGME_KEYLIST_MODE_VALIDATE]) + AC_DEFINE(HAVE_GPGME_KEY_T_KEYLIST_MODE, 1, [Define to 1 if your gpgme's gpgme_key_t has the keylist_mode member]) + AC_DEFINE(HAVE_GPGME_CANCEL, 1, [Define to 1 if your gpgme supports gpgme_cancel()]) +]) + +AC_SUBST(GPGME_LIBS_DEP) + +AM_CONDITIONAL(needs_gpgme_copy, test -n "$tdepim_needs_gpgme_copy") + +dnl Always true - either from the local copy or from the system lib. +dnl Still used in gpgmepp/gpgmefw.h for some reason. +AC_DEFINE(HAVE_GPGME_0_4_BRANCH, 1, [Always set since we use gpgme-copy if gpgme isn't available]) + +dnl Used by Makefile.am +AC_PROG_AWK + diff --git a/libtdenetwork/gpgmepp/context.cpp b/libtdenetwork/gpgmepp/context.cpp new file mode 100644 index 000000000..547adde95 --- /dev/null +++ b/libtdenetwork/gpgmepp/context.cpp @@ -0,0 +1,763 @@ +/* context.cpp - wraps a gpgme key context + 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 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GPGME++; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gpgmepp/context.h> +#include <gpgmepp/eventloopinteractor.h> +#include <gpgmepp/trustitem.h> +#include <gpgmepp/keylistresult.h> +#include <gpgmepp/keygenerationresult.h> +#include <gpgmepp/importresult.h> +#include <gpgmepp/decryptionresult.h> +#include <gpgmepp/verificationresult.h> +#include <gpgmepp/signingresult.h> +#include <gpgmepp/encryptionresult.h> +#include <gpgmepp/engineinfo.h> + +#include "callbacks.h" +#include "data_p.h" +#include "context_p.h" +#include "util.h" + +#include <gpgme.h> +#include <gpg-error.h> + +//#include <string> +//using std::string; +#include <istream> +#ifndef NDEBUG +#include <iostream> +using std::cerr; +using std::endl; +#endif + +#include <cassert> + +namespace GpgME { + + void initializeLibrary() { + gpgme_check_version( 0 ); + } + + const char * Error::source() const { + return gpgme_strsource( (gpgme_error_t)mErr ); + } + + const char * Error::asString() const { + return gpgme_strerror( (gpgme_error_t)mErr ); + } + + 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; + } + + std::ostream & operator<<( std::ostream & os, Error err ) { + return os << "GpgME::Error(" << err.operator int() << " (" << err.asString() << "))"; + } + + Context::Context( gpgme_ctx_t ctx ) { + d = new Private( ctx ); + } + + Context::~Context() { + delete d; d = 0; + } + + 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 ); + } + + // + // + // Context attributes: + // + // + + Context::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 Unknown; + } + } + + + 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::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 d->lasterr = gpgme_set_locale( d->ctx, cat, val ); + } + + // + // + // Key Management + // + // + + Error Context::startKeyListing( const char * pattern, bool secretOnly ) { + d->lastop = Private::KeyList; + return d->lasterr = gpgme_op_keylist_start( d->ctx, pattern, int( secretOnly ) ); + } + + Error Context::startKeyListing( const char * patterns[], bool secretOnly ) { + d->lastop = Private::KeyList; + return 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 = d->lasterr = gpgme_op_keylist_next( d->ctx, &key ); + return Key( key, false, keyListMode() ); + } + + KeyListResult Context::endKeyListing() { + d->lasterr = gpgme_op_keylist_end( d->ctx ); + return keyListResult(); + } + + KeyListResult Context::keyListResult() const { + return KeyListResult( d->ctx, d->lasterr ); + } + + Key Context::key( const char * fingerprint, GpgME::Error & e , bool secret /*, bool forceUpdate*/ ) { + d->lastop = Private::KeyList; + gpgme_key_t key; + e = d->lasterr = gpgme_get_key( d->ctx, fingerprint, &key, int( secret )/*, int( forceUpdate )*/ ); + return Key( key, false, keyListMode() ); + } + + KeyGenerationResult Context::generateKey( const char * parameters, Data & pubKey ) { + d->lastop = Private::KeyGen; + Data::Private * dp = pubKey.impl(); + d->lasterr = gpgme_op_genkey( d->ctx, parameters, dp ? dp->data : 0, 0 ); + return KeyGenerationResult( d->ctx, d->lasterr ); + } + + Error Context::startKeyGeneration( const char * parameters, Data & pubKey ) { + d->lastop = Private::KeyGen; + Data::Private * dp = pubKey.impl(); + return 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, d->lasterr ); + else + return KeyGenerationResult(); + } + + Error Context::exportPublicKeys( const char * pattern, Data & keyData ) { + d->lastop = Private::Export; + Data::Private * dp = keyData.impl(); + return 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; + Data::Private * dp = keyData.impl(); + return 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 * dp = keyData.impl(); + return 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; + Data::Private * dp = keyData.impl(); + return 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; + Data::Private * dp = data.impl(); + d->lasterr = gpgme_op_import( d->ctx, dp ? dp->data : 0 ); + return ImportResult( d->ctx, d->lasterr ); + } + + Error Context::startKeyImport( const Data & data ) { + d->lastop = Private::Import; + Data::Private * dp = data.impl(); + return d->lasterr = gpgme_op_import_start( d->ctx, dp ? dp->data : 0 ); + } + + ImportResult Context::importResult() const { + if ( d->lastop & Private::Import ) + return ImportResult( d->ctx, d->lasterr ); + else + return ImportResult(); + } + + Error Context::deleteKey( const Key & key, bool allowSecretKeyDeletion ) { + d->lastop = Private::Delete; + return d->lasterr = gpgme_op_delete( d->ctx, key.impl(), int( allowSecretKeyDeletion ) ); + } + + Error Context::startKeyDeletion( const Key & key, bool allowSecretKeyDeletion ) { + d->lastop = Private::Delete; + return d->lasterr = gpgme_op_delete_start( d->ctx, key.impl(), int( allowSecretKeyDeletion ) ); + } + + Error Context::startTrustItemListing( const char * pattern, int maxLevel ) { + d->lastop = Private::TrustList; + return d->lasterr = gpgme_op_trustlist_start( d->ctx, pattern, maxLevel ); + } + + TrustItem Context::nextTrustItem( Error & e ) { + gpgme_trust_item_t ti = 0; + e = d->lasterr = gpgme_op_trustlist_next( d->ctx, &ti ); + return ti; + } + + Error Context::endTrustItemListing() { + return d->lasterr = gpgme_op_trustlist_end( d->ctx ); + } + + DecryptionResult Context::decrypt( const Data & cipherText, Data & plainText ) { + d->lastop = Private::Decrypt; + Data::Private * cdp = cipherText.impl(); + Data::Private * pdp = plainText.impl(); + d->lasterr = gpgme_op_decrypt( d->ctx, cdp ? cdp->data : 0, pdp ? pdp->data : 0 ); + return DecryptionResult( d->ctx, d->lasterr ); + } + + Error Context::startDecryption( const Data & cipherText, Data & plainText ) { + d->lastop = Private::Decrypt; + Data::Private * cdp = cipherText.impl(); + Data::Private * pdp = plainText.impl(); + return 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, d->lasterr ); + else + return DecryptionResult(); + } + + + + VerificationResult Context::verifyDetachedSignature( const Data & signature, const Data & signedText ) { + d->lastop = Private::Verify; + Data::Private * sdp = signature.impl(); + Data::Private * tdp = signedText.impl(); + d->lasterr = gpgme_op_verify( d->ctx, sdp ? sdp->data : 0, tdp ? tdp->data : 0, 0 ); + return VerificationResult( d->ctx, d->lasterr ); + } + + VerificationResult Context::verifyOpaqueSignature( const Data & signedData, Data & plainText ) { + d->lastop = Private::Verify; + Data::Private * sdp = signedData.impl(); + Data::Private * pdp = plainText.impl(); + d->lasterr = gpgme_op_verify( d->ctx, sdp ? sdp->data : 0, 0, pdp ? pdp->data : 0 ); + return VerificationResult( d->ctx, d->lasterr ); + } + + Error Context::startDetachedSignatureVerification( const Data & signature, const Data & signedText ) { + d->lastop = Private::Verify; + Data::Private * sdp = signature.impl(); + Data::Private * tdp = signedText.impl(); + return 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; + Data::Private * sdp = signedData.impl(); + Data::Private * pdp = plainText.impl(); + return 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, d->lasterr ); + else + return VerificationResult(); + } + + + std::pair<DecryptionResult,VerificationResult> Context::decryptAndVerify( const Data & cipherText, Data & plainText ) { + d->lastop = Private::DecryptAndVerify; + Data::Private * cdp = cipherText.impl(); + Data::Private * 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, d->lasterr ), + VerificationResult( d->ctx, d->lasterr ) ); + } + + Error Context::startCombinedDecryptionAndVerification( const Data & cipherText, Data & plainText ) { + d->lastop = Private::DecryptAndVerify; + Data::Private * cdp = cipherText.impl(); + Data::Private * pdp = plainText.impl(); + return 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 = gpg_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 = gpg_error( GPG_ERR_NOT_IMPLEMENTED ) ); +#endif + } + + void Context::clearSigningKeys() { + gpgme_signers_clear( d->ctx ); + } + + Error Context::addSigningKey( const Key & key ) { + return 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, keyListMode() ); + } + + + static gpgme_sig_mode_t sigmode2sigmode( Context::SignatureMode mode ) { + switch ( mode ) { + default: + case Context::Normal: return GPGME_SIG_MODE_NORMAL; + case Context::Detached: return GPGME_SIG_MODE_DETACH; + case Context::Clearsigned: return GPGME_SIG_MODE_CLEAR; + } + } + + SigningResult Context::sign( const Data & plainText, Data & signature, SignatureMode mode ) { + d->lastop = Private::Sign; + Data::Private * pdp = plainText.impl(); + Data::Private * sdp = signature.impl(); + d->lasterr = gpgme_op_sign( d->ctx, pdp ? pdp->data : 0, sdp ? sdp->data : 0, sigmode2sigmode( mode ) ); + return SigningResult( d->ctx, d->lasterr ); + } + + + Error Context::startSigning( const Data & plainText, Data & signature, SignatureMode mode ) { + d->lastop = Private::Sign; + Data::Private * pdp = plainText.impl(); + Data::Private * sdp = signature.impl(); + return 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, d->lasterr ); + else + return SigningResult(); + } + + + EncryptionResult Context::encrypt( const std::vector<Key> & recipients, const Data & plainText, Data & cipherText, EncryptionFlags flags ) { + d->lastop = Private::Encrypt; + Data::Private * pdp = plainText.impl(); + Data::Private * cdp = cipherText.impl(); + gpgme_key_t * 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, + flags & AlwaysTrust ? GPGME_ENCRYPT_ALWAYS_TRUST : (gpgme_encrypt_flags_t)0, + pdp ? pdp->data : 0, cdp ? cdp->data : 0 ); + delete[] keys; + return EncryptionResult( d->ctx, d->lasterr ); + } + + Error Context::encryptSymmetrically( const Data & plainText, Data & cipherText ) { + d->lastop = Private::Encrypt; + Data::Private * pdp = plainText.impl(); + Data::Private * cdp = cipherText.impl(); + return 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; + Data::Private * pdp = plainText.impl(); + Data::Private * cdp = cipherText.impl(); + gpgme_key_t * 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, + flags & AlwaysTrust ? GPGME_ENCRYPT_ALWAYS_TRUST : (gpgme_encrypt_flags_t)0, + pdp ? pdp->data : 0, cdp ? cdp->data : 0 ); + delete[] keys; + return d->lasterr; + } + + EncryptionResult Context::encryptionResult() const { + if ( d->lastop & Private::Encrypt ) + return EncryptionResult( d->ctx, 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; + Data::Private * pdp = plainText.impl(); + Data::Private * cdp = cipherText.impl(); + gpgme_key_t * 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, + flags & AlwaysTrust ? GPGME_ENCRYPT_ALWAYS_TRUST : (gpgme_encrypt_flags_t)0, + pdp ? pdp->data : 0, cdp ? cdp->data : 0 ); + delete[] keys; + return std::make_pair( SigningResult( d->ctx, d->lasterr ), + EncryptionResult( d->ctx, d->lasterr ) ); + } + + Error Context::startCombinedSigningAndEncryption( const std::vector<Key> & recipients, const Data & plainText, Data & cipherText, EncryptionFlags flags ) { + d->lastop = Private::SignAndEncrypt; + Data::Private * pdp = plainText.impl(); + Data::Private * cdp = cipherText.impl(); + gpgme_key_t * 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, + flags & AlwaysTrust ? GPGME_ENCRYPT_ALWAYS_TRUST : (gpgme_encrypt_flags_t)0, + pdp ? pdp->data : 0, cdp ? cdp->data : 0 ); + delete[] keys; + return d->lasterr; + } + + + Error Context::cancelPendingOperation() { +#ifdef HAVE_GPGME_CANCEL + return gpgme_cancel( d->ctx ); +#else + return 0; +#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 d->lasterr = e; + } + + Error Context::lastError() const { + return d->lasterr; + } + + std::ostream & operator<<( std::ostream & os, Context::Protocol proto ) { + os << "GpgME::Context::Protocol("; + switch ( proto ) { + case Context::OpenPGP: + os << "OpenPGP"; + break; + case Context::CMS: + os << "CMS"; + break; + default: + case Context::Unknown: + os << "Unknown"; + 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, Context::KeyListMode mode ) { + os << "GpgME::Context::KeyListMode("; +#define CHECK( x ) if ( !(mode & (Context::x)) ) {} else do { os << #x " "; } while (0) + CHECK( Local ); + CHECK( Extern ); + CHECK( Signatures ); + CHECK( Validate ); +#undef CHECK + return os << ')'; + } + + std::ostream & operator<<( std::ostream & os, Context::SignatureMode mode ) { + os << "GpgME::Context::SignatureMode("; + switch ( mode ) { +#define CHECK( x ) case Context::x: os << #x; break + CHECK( Normal ); + 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 gpgme_set_locale( 0, cat, val ); +} + +GpgME::EngineInfo GpgME::engineInfo( Context::Protocol proto ) { + gpgme_engine_info_t ei = 0; + if ( gpgme_get_engine_info( &ei ) ) + return EngineInfo(); + + gpgme_protocol_t p = proto == Context::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( Context::Protocol proto ) { + gpgme_protocol_t p = proto == Context::CMS ? GPGME_PROTOCOL_CMS : GPGME_PROTOCOL_OpenPGP ; + + return gpgme_engine_check_version( p ); +} + +static const unsigned long supported_features = 0 +#ifdef HAVE_GPGME_KEYLIST_MODE_VALIDATE + | GpgME::ValidatingKeylistModeFeature +#endif +#ifdef HAVE_GPGME_CANCEL + | GpgME::CancelOperationFeature +#endif +#ifdef HAVE_GPGME_WRONG_KEY_USAGE + | GpgME::WrongKeyUsageFeature +#endif +#ifdef HAVE_GPGME_OP_GETAUDITLOG + | GpgME::AuditLogFeature +#endif + ; + +bool GpgME::hasFeature( unsigned long features ) { + return features == ( features & supported_features ); +} diff --git a/libtdenetwork/gpgmepp/context.h b/libtdenetwork/gpgmepp/context.h new file mode 100644 index 000000000..054f8bee7 --- /dev/null +++ b/libtdenetwork/gpgmepp/context.h @@ -0,0 +1,328 @@ +/* context.h - wraps a gpgme key context + 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 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GPGME++; 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 <gpgmepp/gpgmefw.h> + +#include <vector> +#include <utility> +#include <iosfwd> + +#include <tdepimmacros.h> + +namespace GpgME { + + class Key; + class Data; + class TrustItem; + class ProgressProvider; + class PassphraseProvider; + class EventLoopInteractor; + + class KeyListResult; + class KeyGenerationResult; + class ImportResult; + class DecryptionResult; + class VerificationResult; + class SigningResult; + class EncryptionResult; + + class EngineInfo; + + class KDE_EXPORT Error { + public: + Error( int e=0 ) : mErr( e ) {} + + const char * source() const; + const char * asString() const; + + int code() const; + int sourceID() const; + + bool isCanceled() const; + + operator int() const { return mErr; } + operator bool() const { return mErr && !isCanceled(); } + private: + int mErr; + }; + + KDE_EXPORT std::ostream & operator<<( std::ostream & os, Error err ); + + class KDE_EXPORT Context { + Context( gpgme_ctx_t ); + public: + enum Protocol { OpenPGP, CMS, Unknown }; + + // + // Creation and destruction: + // + + static Context * createForProtocol( Protocol proto ); + virtual ~Context(); + + // + // Context Attributes + // + + Protocol protocol() const; + + void setArmor( bool useArmor ); + bool armor() const; + + void setTextMode( bool useTextMode ); + bool textMode() const; + + enum CertificateInclusion { + DefaultCertificates = -256, + AllCertificatesExceptRoot = -2, + AllCertificates = -1, + NoCertificates = 0, + OnlySenderCertificate = 1 + }; + void setIncludeCertificates( int which ); + int includeCertificates() const; + + enum KeyListMode { + Local = 0x1, + Extern = 0x2, + Signatures = 0x4, + Validate = 0x10 + }; + 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 ); + + private: + friend class 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 ); + GpgME::Error startKeyImport( const Data & data ); + ImportResult importResult() const; + + // + // Key Deletion + // + + GpgME::Error deleteKey( const Key & key, bool allowSecretKeyDeletion=false ); + GpgME::Error startKeyDeletion( const Key & key, bool allowSecretKeyDeletion=false ); + + // + // Trust Item Management + // + + GpgME::Error startTrustItemListing( const char * pattern, int maxLevel ); + TrustItem nextTrustItem( GpgME::Error & e ); + GpgME::Error endTrustItemListing(); + + // + // + // 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; + + enum SignatureMode { Normal, Detached, Clearsigned }; + 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 }; + 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 ); + + // + // + // Run Control + // + // + + bool poll(); + GpgME::Error wait(); + GpgME::Error lastError() const; + GpgME::Error cancelPendingOperation(); + + class Private; + Private * impl() const { return d; } + private: + Private * d; + + private: // disable... + Context( const Context & ); + const Context & operator=( const Context & ); + }; + + KDE_EXPORT std::ostream & operator<<( std::ostream & os, Context::Protocol proto ); + KDE_EXPORT std::ostream & operator<<( std::ostream & os, Context::CertificateInclusion incl ); + KDE_EXPORT std::ostream & operator<<( std::ostream & os, Context::KeyListMode mode ); + KDE_EXPORT std::ostream & operator<<( std::ostream & os, Context::SignatureMode mode ); + KDE_EXPORT std::ostream & operator<<( std::ostream & os, Context::EncryptionFlags flags ); + KDE_EXPORT std::ostream & operator<<( std::ostream & os, Context::AuditLogFlags flags ); + + // + // + // Globals + // + // + + KDE_EXPORT void initializeLibrary(); + + KDE_EXPORT GpgME::Error setDefaultLocale( int category, const char * value ); + + KDE_EXPORT Context * wait( GpgME::Error & e, bool hang=true ); + typedef void (*IdleFunction)(void); + KDE_EXPORT IdleFunction registerIdleFunction( IdleFunction idleFunction ); + + typedef void (*IOCallback)( void * data, int fd ); + + KDE_EXPORT EngineInfo engineInfo( Context::Protocol proto ); + + KDE_EXPORT GpgME::Error checkEngine( Context::Protocol proto ); + + enum Feature { + ValidatingKeylistModeFeature = 0x00000001, + CancelOperationFeature = 0x00000002, + WrongKeyUsageFeature = 0x00000004, + + AuditLogFeature = 0x00001000, + + FeatureMaxValue = 0x80000000 + }; + KDE_EXPORT bool hasFeature( unsigned long feature ); + +} // namespace GpgME + +#endif // __GPGMEPP_CONTEXT_H__ diff --git a/libtdenetwork/gpgmepp/context_p.h b/libtdenetwork/gpgmepp/context_p.h new file mode 100644 index 000000000..dfff58634 --- /dev/null +++ b/libtdenetwork/gpgmepp/context_p.h @@ -0,0 +1,76 @@ +/* context_p.h - wraps a gpgme key context (private part) + 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 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GPGME; 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 <gpgmepp/context.h> + +#include <gpgme.h> + +namespace GpgME { + + + struct Context::Private { + 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, // gpgme_trustlist_result_t, but nevertheless... + + GetAuditLog = 0x1000 // no gpgme_getauditlog_result_t, but nevertheless... + }; + + Private( gpgme_ctx_t c=0 ) + : ctx( c ), + iocbs( 0 ), + lastop( None ), + lasterr( GPG_ERR_NO_ERROR ) {} + ~Private() { + if ( ctx ) { + gpgme_release( ctx ); + ctx = 0; + } + delete iocbs; + } + + gpgme_ctx_t ctx; + gpgme_io_cbs * iocbs; + //EditInteractor * edit; + Operation lastop; + gpgme_error_t lasterr; + }; + +} // namespace GpgME + +#endif // __GPGMEPP_CONTEXT_P_H__ diff --git a/libtdenetwork/gpgmepp/data.cpp b/libtdenetwork/gpgmepp/data.cpp new file mode 100644 index 000000000..52471be9b --- /dev/null +++ b/libtdenetwork/gpgmepp/data.cpp @@ -0,0 +1,160 @@ +/* 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 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GPGME++; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gpgmepp/context.h> // Error +#include <gpgmepp/interfaces/dataprovider.h> +#include "data_p.h" + +#include <gpgme.h> + +#ifndef NDEBUG +#include <iostream> +#endif + +GpgME::Data::Private::~Private() { + if ( data ) + gpgme_data_release( data ); +} + +GpgME::Data GpgME::Data::null( (gpgme_data_t)0 ); + +GpgME::Data::Data() { + gpgme_data_t data; + const gpgme_error_t e = gpgme_data_new( &data ); + d = new Private( e ? 0 : data ); + d->ref(); +} + +GpgME::Data::Data( gpgme_data_t data ) { + d = new Private( data ); + d->ref(); +} + +GpgME::Data::Data( const Data & other ) + : d( other.d ) +{ + d->ref(); +} + +GpgME::Data::~Data() { + d->unref(); d = 0; +} + + +const GpgME::Data & GpgME::Data::operator=( const Data & other ) { + if ( this->d == other.d ) return *this; + + if ( other.d ) + other.d->ref(); + if ( this->d ) + this->d->unref(); + this->d = other.d; + + return *this; +} + +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 = new Private( e ? 0 : data ); + d->ref(); +} + +GpgME::Data::Data( const char * filename ) { + gpgme_data_t data; + const gpgme_error_t e = gpgme_data_new_from_file( &data, filename, 1 ); + d = new Private( e ? 0 : data ); + d->ref(); +} + +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 = new Private( e ? 0 : data ); + d->ref(); +} + +GpgME::Data::Data( FILE * fp ) { + gpgme_data_t data; + const gpgme_error_t e = gpgme_data_new_from_stream( &data, fp ); + d = new Private( e ? 0 : data ); + d->ref(); +} + +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 = new Private( e ? 0 : data ); + d->ref(); +} + +GpgME::Data::Data( int fd ) { + gpgme_data_t data; + const gpgme_error_t e = gpgme_data_new_from_fd( &data, fd ); + d = new Private( e ? 0 : data ); + d->ref(); +} + +GpgME::Data::Data( DataProvider * dp ) { + d = new Private(); + d->ref(); + 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; +} + +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/libtdenetwork/gpgmepp/data.h b/libtdenetwork/gpgmepp/data.h new file mode 100644 index 000000000..e12064729 --- /dev/null +++ b/libtdenetwork/gpgmepp/data.h @@ -0,0 +1,72 @@ +/* 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 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GPGME++; 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 <gpgmepp/gpgmefw.h> + +#include <sys/types.h> // for size_t, off_t +#include <cstdio> // FILE +#include <tdepimmacros.h> + +namespace GpgME { + + class DataProvider; + class Error; + + class KDE_EXPORT Data { + public: + Data(); + Data( gpgme_data_t data ); + Data( const Data & other ); + + // Memory-Based Data Buffers: + Data( const char * buffer, size_t size, bool copy=true ); + Data( const char * filename ); + Data( const char * filename, off_t offset, size_t length ); + Data( FILE * fp, off_t offset, size_t length ); + // File-Based Data Buffers: + Data( FILE * fp ); + Data( int fd ); + // Callback-Based Data Buffers: + Data( DataProvider * provider ); + + virtual ~Data(); + + static Data null; + + const Data & operator=( const Data & other ); + + bool isNull() const; + + 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() const { return d; } + private: + Private * d; + }; + +} + +#endif // __GPGMEPP_DATA_H__ diff --git a/libtdenetwork/gpgmepp/data_p.h b/libtdenetwork/gpgmepp/data_p.h new file mode 100644 index 000000000..38981cce9 --- /dev/null +++ b/libtdenetwork/gpgmepp/data_p.h @@ -0,0 +1,39 @@ +/* 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 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GPGME++; 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 <gpgmepp/data.h> +#include "shared.h" +#include "callbacks.h" + +class GpgME::Data::Private : public GpgME::Shared { +public: + Private( gpgme_data_t d=0 ) + : Shared(), data( d ), cbs( data_provider_callbacks ) {} + ~Private(); + + gpgme_data_t data; + gpgme_data_cbs cbs; +}; + + +#endif // __GPGMEPP_DATA_P_H__ diff --git a/libtdenetwork/gpgmepp/decryptionresult.cpp b/libtdenetwork/gpgmepp/decryptionresult.cpp new file mode 100644 index 000000000..2efcc67d9 --- /dev/null +++ b/libtdenetwork/gpgmepp/decryptionresult.cpp @@ -0,0 +1,85 @@ +/* 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 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GPGME++; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gpgmepp/decryptionresult.h> +#include "shared.h" +#include "result_p.h" +#include "util.h" + +#include <gpgme.h> + +#include <cstring> +#include <cstdlib> +#include <istream> + +class GpgME::DecryptionResult::Private : public GpgME::Shared { +public: + Private( const _gpgme_op_decrypt_result & r ) : Shared(), res( r ) { + if ( res.unsupported_algorithm ) + res.unsupported_algorithm = strdup( res.unsupported_algorithm ); + } + ~Private() { + if ( res.unsupported_algorithm ) + std::free( res.unsupported_algorithm ); + res.unsupported_algorithm = 0; + } + + _gpgme_op_decrypt_result res; +}; + +GpgME::DecryptionResult::DecryptionResult( gpgme_ctx_t ctx, int error ) + : GpgME::Result( error ), d( 0 ) +{ + if ( error || !ctx ) + return; + gpgme_decrypt_result_t res = gpgme_op_decrypt_result( ctx ); + if ( !res ) + return; + d = new Private( *res ); + d->ref(); +} + +make_standard_stuff(DecryptionResult) + +const char * GpgME::DecryptionResult::unsupportedAlgortihm() const { + return d ? d->res.unsupported_algorithm : 0 ; +} + +bool GpgME::DecryptionResult::wrongKeyUsage() const { +#ifdef HAVE_GPGME_WRONG_KEY_USAGE + if ( d ) + return d->res.wrong_key_usage; +#endif + return false; +} + +std::ostream & GpgME::operator<<( std::ostream & os, const DecryptionResult & result ) { + os << "GpgME::DecryptionResult("; + if ( !result.isNull() ) + os << "\n error: " << result.error() + << "\n unsupportedAlgortihm: " << protect( result.unsupportedAlgortihm() ) + << "\n wrongKeyUsage: " << result.wrongKeyUsage() + << '\n'; + return os << ')'; +} diff --git a/libtdenetwork/gpgmepp/decryptionresult.h b/libtdenetwork/gpgmepp/decryptionresult.h new file mode 100644 index 000000000..da4833bbd --- /dev/null +++ b/libtdenetwork/gpgmepp/decryptionresult.h @@ -0,0 +1,59 @@ +/* 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 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GPGME++; 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 <gpgmepp/gpgmefw.h> +#include <gpgmepp/result.h> + +#include <iosfwd> + +#include <tdepimmacros.h> + +namespace GpgME { + + class Error; + + class KDE_EXPORT DecryptionResult : public Result { + public: + DecryptionResult( gpgme_ctx_t ctx=0, int error=0 ); + explicit DecryptionResult( const Error & err ); + DecryptionResult( const DecryptionResult & other ); + ~DecryptionResult(); + + const DecryptionResult & operator=( const DecryptionResult & other ); + + bool isNull() const; + + const char * unsupportedAlgortihm() const; + + bool wrongKeyUsage() const; + + private: + class Private; + Private * d; + }; + + KDE_EXPORT std::ostream & operator<<( std::ostream & os, const DecryptionResult & result ); + +} + +#endif // __GPGMEPP_DECRYPTIONRESULT_H__ diff --git a/libtdenetwork/gpgmepp/encryptionresult.cpp b/libtdenetwork/gpgmepp/encryptionresult.cpp new file mode 100644 index 000000000..f827ca839 --- /dev/null +++ b/libtdenetwork/gpgmepp/encryptionresult.cpp @@ -0,0 +1,165 @@ +/* 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 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GPGME++; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gpgmepp/encryptionresult.h> +#include "shared.h" +#include "result_p.h" +#include "util.h" + +#include <gpgme.h> + +#include <cstring> +#include <cstdlib> +#include <istream> +#include <algorithm> +#include <iterator> + +class GpgME::EncryptionResult::Private : public GpgME::Shared { +public: + Private( const gpgme_encrypt_result_t r ) : Shared() { + 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( 0 ) +{ + if ( error || !ctx ) + return; + gpgme_encrypt_result_t res = gpgme_op_encrypt_result( ctx ); + if ( !res ) + return; + d = new Private( res ); + d->ref(); +} + +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( EncryptionResult::Private * parent, unsigned int i ) + : d( parent ), idx( i ) +{ + if ( d ) + d->ref(); +} + +GpgME::InvalidRecipient::InvalidRecipient() : d( 0 ), idx( 0 ) {} + +GpgME::InvalidRecipient::InvalidRecipient( const InvalidRecipient & other ) + : d( other.d ), idx( other.idx ) +{ + if ( d ) + d->ref(); +} + +GpgME::InvalidRecipient::~InvalidRecipient() { + if ( d ) + d->unref(); +} + +const GpgME::InvalidRecipient & GpgME::InvalidRecipient::operator=( const InvalidRecipient & other ) { + if ( this->d != other.d ) { + if ( other.d ) + other.d->ref(); + if ( this->d ) + this->d->unref(); + this->d = other.d; + } + + this->idx = other.idx; + return *this; +} + + +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 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/libtdenetwork/gpgmepp/encryptionresult.h b/libtdenetwork/gpgmepp/encryptionresult.h new file mode 100644 index 000000000..4339bef56 --- /dev/null +++ b/libtdenetwork/gpgmepp/encryptionresult.h @@ -0,0 +1,84 @@ +/* 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 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GPGME++; 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 <gpgmepp/gpgmefw.h> +#include <gpgmepp/result.h> + +#include <vector> +#include <iosfwd> + +#include <tdepimmacros.h> + +namespace GpgME { + + class Error; + class InvalidRecipient; + + class KDE_EXPORT EncryptionResult : public Result { + public: + EncryptionResult( gpgme_ctx_t ctx=0, int error=0 ); + explicit EncryptionResult( const Error & err ); + EncryptionResult( const EncryptionResult & other ); + ~EncryptionResult(); + + const EncryptionResult & operator=( const EncryptionResult & other ); + + bool isNull() const; + + unsigned int numInvalidRecipients() const; + + InvalidRecipient invalidEncryptionKey( unsigned int index ) const; + std::vector<InvalidRecipient> invalidEncryptionKeys() const; + + class Private; + private: + Private * d; + }; + + KDE_EXPORT std::ostream & operator<<( std::ostream & os, const EncryptionResult & result ); + + class KDE_EXPORT InvalidRecipient { + friend class EncryptionResult; + InvalidRecipient( EncryptionResult::Private * parent, unsigned int index ); + public: + InvalidRecipient(); + InvalidRecipient( const InvalidRecipient & other ); + ~InvalidRecipient(); + + const InvalidRecipient & operator=( const InvalidRecipient & other ); + + bool isNull() const; + + const char * fingerprint() const; + Error reason() const; + + private: + EncryptionResult::Private * d; + unsigned int idx; + }; + + KDE_EXPORT std::ostream & operator<<( std::ostream & os, const InvalidRecipient & recipient ); + +} + +#endif // __GPGMEPP_ENCRYPTIONRESULT_H__ diff --git a/libtdenetwork/gpgmepp/engineinfo.cpp b/libtdenetwork/gpgmepp/engineinfo.cpp new file mode 100644 index 000000000..461a61db3 --- /dev/null +++ b/libtdenetwork/gpgmepp/engineinfo.cpp @@ -0,0 +1,99 @@ +/* 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 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GPGME++; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "engineinfo.h" +#include "shared.h" + +#include <gpgme.h> + +struct GpgME::EngineInfo::Private : public GpgME::Shared { + Private( gpgme_engine_info_t engine=0 ) : Shared(), info( engine ) {} + ~Private() { info = 0; } + + gpgme_engine_info_t info; +}; + + +GpgME::EngineInfo::EngineInfo() : d(0) {} + +GpgME::EngineInfo::EngineInfo( gpgme_engine_info_t engine ) + : d(0) +{ + d = new Private( engine ); + d->ref(); +} + +GpgME::EngineInfo::EngineInfo( const EngineInfo & other ) + : d( other.d ) +{ + if ( d ) + d->ref(); +} + + +GpgME::EngineInfo::~EngineInfo() { + if ( d ) + d->deref(); +} + +const GpgME::EngineInfo & GpgME::EngineInfo::operator=( const GpgME::EngineInfo & other ) { + if ( this->d == other.d ) + return *this; + + if ( other.d ) + other.d->ref(); + if ( this->d ) + this->d->unref(); + + this->d = other.d; + return *this; +} + +bool GpgME::EngineInfo::isNull() const { + return !d || !d->info; +} + +GpgME::Context::Protocol GpgME::EngineInfo::protocol() const { + if ( isNull() ) + return Context::Unknown; + switch( d->info->protocol ) { + case GPGME_PROTOCOL_OpenPGP: return Context::OpenPGP; + case GPGME_PROTOCOL_CMS: return Context::CMS; + default: + return Context::Unknown; + } +} + +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; +} + diff --git a/libtdenetwork/gpgmepp/engineinfo.h b/libtdenetwork/gpgmepp/engineinfo.h new file mode 100644 index 000000000..c07d2817a --- /dev/null +++ b/libtdenetwork/gpgmepp/engineinfo.h @@ -0,0 +1,53 @@ +/* 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 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GPGME++; 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 <gpgmepp/gpgmefw.h> +#include <gpgmepp/context.h> + +#include <tdepimmacros.h> + +namespace GpgME { + + class KDE_EXPORT EngineInfo { + public: + EngineInfo(); + EngineInfo( gpgme_engine_info_t engine ); + EngineInfo( const EngineInfo & other ); + ~EngineInfo(); + + const EngineInfo & operator=( const EngineInfo & other ); + + bool isNull() const; + + Context::Protocol protocol() const; + const char * fileName() const; + const char * version() const; + const char * requiredVersion() const; + private: + class Private; + Private * d; + }; + +} + +#endif // __GPGMEPP_ENGINEINFO_H__ diff --git a/libtdenetwork/gpgmepp/eventloopinteractor.cpp b/libtdenetwork/gpgmepp/eventloopinteractor.cpp new file mode 100644 index 000000000..cdac7d567 --- /dev/null +++ b/libtdenetwork/gpgmepp/eventloopinteractor.cpp @@ -0,0 +1,185 @@ +/* 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 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GPGME; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gpgmepp/eventloopinteractor.h> + +#include <gpgmepp/context.h> +#include "context_p.h" +#include <gpgmepp/key.h> +#include <gpgmepp/trustitem.h> + +#include <gpgme.h> + +#include <vector> +using std::vector; +#ifndef NDEBUG +# include <iostream> +#endif +#include <cassert> + +namespace GpgME { + + // + // EventLoopInteractor::Private Declaration + // + + struct EventLoopInteractor::Private { + 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 gpgme_io_cbs iocbs; + }; + + 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 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 ) { + assert( instance() ); assert( instance()->d ); + + 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: + { + // hmmm, what to do here? + } + 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, e ); + } + break; + case GPGME_EVENT_NEXT_KEY: + { + gpgme_key_t key = static_cast<gpgme_key_t>( type_data ); + instance()->nextKeyEvent( ctx, Key( key, false, ctx ? ctx->keyListMode() : 0 ) ); + } + 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() { + assert( !mSelf ); + d = new Private(); + mSelf = this; + } + + EventLoopInteractor::~EventLoopInteractor() { + // warn if there are still callbacks registered + mSelf = 0; + delete d; d = 0; + } + + 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/libtdenetwork/gpgmepp/eventloopinteractor.h b/libtdenetwork/gpgmepp/eventloopinteractor.h new file mode 100644 index 000000000..c3688833c --- /dev/null +++ b/libtdenetwork/gpgmepp/eventloopinteractor.h @@ -0,0 +1,148 @@ +/* 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 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GPGME; 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 <tdepimmacros.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 TQt 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 + TQt, you'd essentially just create a new \c TQSocketNotifier: + + \verbatim + void * registerWatcher( int fd, Direction dir ) { + return new TQSocketNotifier( fd, dir == Read ? TQSocketNotifier::Read : TQSocketNotifier::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<TQSocketNotifier*>( 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 KDE_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 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 * d; + static EventLoopInteractor * mSelf; + }; + +} + +#endif // __GPGMEPP_EVENTLOOPINTERACTOR_H__ diff --git a/libtdenetwork/gpgmepp/gpgme-0-3-compat.h b/libtdenetwork/gpgmepp/gpgme-0-3-compat.h new file mode 100644 index 000000000..5f8c5b616 --- /dev/null +++ b/libtdenetwork/gpgmepp/gpgme-0-3-compat.h @@ -0,0 +1,49 @@ +/* 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 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GPGME++; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifndef __GPGMEPP_GPGME_0_3_COMPAT_H__ +#define __GPGMEPP_GPGME_0_3_COMPAT_H__ + +#include <gpgme.h> + +#ifndef HAVE_GPGME_0_4_BRANCH +// make gpgme-0.4 names available even if we have only 0.3: +typedef GpgmeError gpgme_error_t; +typedef GpgmeIOCb gpgme_io_cb_t; +typedef GpgmeIOCbs gpgme_io_cbs; +typedef GpgmeEventIO gpgme_event_io_t; +typedef GpgmeEventIOCb gpgme_event_io_cb_t; +typedef GpgmeRegisterIOCb gpgme_register_io_cb_t; +typedef GpgmeRemoveIOCb gpgme_remove_io_cb_t; +typedef GpgmeSigStat gpgme_sig_stat_t; +typedef GpgmeAttr gpgme_attr_t; +typedef GpgmeTrustItem gpgme_trust_item_t; +typedef GpgmeCtx gpgme_ctx_t; +typedef GpgmeProtocol gpgme_protocol_t; +typedef GpgmeData gpgme_data_t; +typedef GpgmeKey gpgme_key_t; + +#define GPG_ERR_GENERAL GPGME_General_Error +#define GPG_ERR_NO_ERROR GPGME_No_Error +#define GPG_ERR_EOF GPGME_EOF +#define gpg_err_code(x) (x) +#endif + +#endif // __GPGMEPP_GPGME_0_3_COMPAT_H__ diff --git a/libtdenetwork/gpgmepp/gpgmefw.h b/libtdenetwork/gpgmepp/gpgmefw.h new file mode 100644 index 000000000..8fe43746e --- /dev/null +++ b/libtdenetwork/gpgmepp/gpgmefw.h @@ -0,0 +1,60 @@ +/* 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 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GPGME++; 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__ + +#ifndef HAVE_GPGME_0_4_BRANCH +#error You need gpgme 0.4.x, x >= 4, to compile gpgme++ +#endif + +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; + +#endif // __GPGMEPP_GPGMEFW_H__ diff --git a/libtdenetwork/gpgmepp/importresult.cpp b/libtdenetwork/gpgmepp/importresult.cpp new file mode 100644 index 000000000..3b4b713c7 --- /dev/null +++ b/libtdenetwork/gpgmepp/importresult.cpp @@ -0,0 +1,204 @@ +/* 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 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GPGME++; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gpgmepp/importresult.h> +#include "shared.h" +#include "result_p.h" + +#include <gpgme.h> +#include <cstring> +#include <cstdlib> +#include <cstdlib> + +class GpgME::ImportResult::Private : public GpgME::Shared { +public: + Private( const _gpgme_op_import_result & r ) : Shared(), 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( 0 ) +{ + if ( error || !ctx ) + return; + gpgme_import_result_t res = gpgme_op_import_result( ctx ); + if ( !res ) + return; + d = new Private( *res ); + d->ref(); +} + +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( ImportResult::Private * parent, unsigned int i ) + : d( parent ), idx( i ) +{ + if ( d ) + d->ref(); +} + +GpgME::Import::Import() : d( 0 ), idx( 0 ) {} + +GpgME::Import::Import( const Import & other ) + : d( other.d ), idx( other.idx ) +{ + if ( d ) + d->ref(); +} + +GpgME::Import::~Import() { + if ( d ) + d->unref(); +} + +const GpgME::Import & GpgME::Import::operator=( const Import & other ) { + if ( this->d != other.d ) { + if ( other.d ) + other.d->ref(); + if ( this->d ) + this->d->unref(); + this->d = other.d; + } + + this->idx = other.idx; + return *this; +} + + +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 isNull() ? 0 : d->imports[idx]->result ; +} + +GpgME::Import::tqStatus GpgME::Import::status() const { + if ( isNull() ) + return Unknown; + 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<tqStatus>( result ); +} diff --git a/libtdenetwork/gpgmepp/importresult.h b/libtdenetwork/gpgmepp/importresult.h new file mode 100644 index 000000000..61675a299 --- /dev/null +++ b/libtdenetwork/gpgmepp/importresult.h @@ -0,0 +1,103 @@ +/* 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 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GPGME++; 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 <gpgmepp/gpgmefw.h> +#include <gpgmepp/result.h> + +#include <vector> +#include <tdepimmacros.h> + +namespace GpgME { + + class Error; + class Import; + + class KDE_EXPORT ImportResult : public Result { + public: + ImportResult( gpgme_ctx_t ctx=0, int error=0 ); + explicit ImportResult( const Error & error ); + ImportResult( const ImportResult & other ); + ~ImportResult(); + + const ImportResult & operator=( const ImportResult & other ); + + 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: + Private * d; + }; + + class KDE_EXPORT Import { + friend class ImportResult; + Import( ImportResult::Private * parent, unsigned int idx ); + public: + Import(); + Import( const Import & other ); + ~Import(); + + const Import & operator=( const Import & other ); + + bool isNull() const; + + const char * fingerprint() const; + Error error() const; + + enum tqStatus { + Unknown = 0x0, + NewKey = 0x1, + NewUserIDs = 0x2, + NewSignatures = 0x4, + NewSubkeys = 0x8, + ContainedSecretKey = 0x10 + }; + tqStatus status() const; + + private: + ImportResult::Private * d; + unsigned int idx; + }; + +} + +#endif // __GPGMEPP_IMPORTRESULT_H__ diff --git a/libtdenetwork/gpgmepp/interfaces/CMakeLists.txt b/libtdenetwork/gpgmepp/interfaces/CMakeLists.txt new file mode 100644 index 000000000..db5b88ee8 --- /dev/null +++ b/libtdenetwork/gpgmepp/interfaces/CMakeLists.txt @@ -0,0 +1,14 @@ +################################################# +# +# (C) 2010-2011 Serghei Amelian +# serghei (DOT) amelian (AT) gmail.com +# +# Improvements and feedback are welcome +# +# This file is released under GPL >= 2 +# +################################################# + +install( FILES + editinteractor.h passphraseprovider.h progressprovider.h + DESTINATION ${INCLUDE_INSTALL_DIR}/gpgme++/interfaces ) diff --git a/libtdenetwork/gpgmepp/interfaces/Makefile.am b/libtdenetwork/gpgmepp/interfaces/Makefile.am new file mode 100644 index 000000000..ad2f79e42 --- /dev/null +++ b/libtdenetwork/gpgmepp/interfaces/Makefile.am @@ -0,0 +1,3 @@ +gpgmeppinterfacesdir = $(includedir)/gpgme++/interfaces +gpgmeppinterfaces_HEADERS = editinteractor.h \ + passphraseprovider.h progressprovider.h diff --git a/libtdenetwork/gpgmepp/interfaces/dataprovider.h b/libtdenetwork/gpgmepp/interfaces/dataprovider.h new file mode 100644 index 000000000..34dd4a7e1 --- /dev/null +++ b/libtdenetwork/gpgmepp/interfaces/dataprovider.h @@ -0,0 +1,48 @@ +/* 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 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GPGME; 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 <tdepimmacros.h> + +namespace GpgME { + + class KDE_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/libtdenetwork/gpgmepp/interfaces/editinteractor.h b/libtdenetwork/gpgmepp/interfaces/editinteractor.h new file mode 100644 index 000000000..e1f31eed1 --- /dev/null +++ b/libtdenetwork/gpgmepp/interfaces/editinteractor.h @@ -0,0 +1,35 @@ +/* interface/editinteractor.h - Interface for key edit functions + 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 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GPGME; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifndef __GPGMEPP_INTERFACES_EDITINTERACTOR_H__ +#define __GPGMEPP_INTERFACES_EDITINTERACTOR_H__ + +namespace GpgME { + + class EditInteractor { + public: + virtual ~EditInteractor() {} + + virtual bool interactiveEdit( int status, const char * args, const char ** reply ) = 0; + }; + +} // namespace GpgME + +#endif // __GPGMEPP_INTERFACES_EDITINTERACTOR_H__ diff --git a/libtdenetwork/gpgmepp/interfaces/passphraseprovider.h b/libtdenetwork/gpgmepp/interfaces/passphraseprovider.h new file mode 100644 index 000000000..37ff6a8bc --- /dev/null +++ b/libtdenetwork/gpgmepp/interfaces/passphraseprovider.h @@ -0,0 +1,38 @@ +/* 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 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GPGME; 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__ + +#include <string> + +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/libtdenetwork/gpgmepp/interfaces/progressprovider.h b/libtdenetwork/gpgmepp/interfaces/progressprovider.h new file mode 100644 index 000000000..b51765b74 --- /dev/null +++ b/libtdenetwork/gpgmepp/interfaces/progressprovider.h @@ -0,0 +1,36 @@ +/* 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 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GPGME; 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/libtdenetwork/gpgmepp/key.cpp b/libtdenetwork/gpgmepp/key.cpp new file mode 100644 index 000000000..13cd0a7ee --- /dev/null +++ b/libtdenetwork/gpgmepp/key.cpp @@ -0,0 +1,926 @@ +/* key.cpp - wraps a gpgme key + 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 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GPGME; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gpgmepp/key.h> + +#include "util.h" + +#include <gpgme.h> + +#include <string.h> + +GpgME::Key GpgME::Key::null; + +namespace GpgME { + + using std::vector; + + struct Key::Private { + Private( gpgme_key_t aKey, unsigned int aMode ) + : key( aKey ), +#ifdef HAVE_GPGME_KEY_T_KEYLIST_MODE + mode( 0 ) +#else + mode( aMode ) +#endif + {} + gpgme_key_t key; + unsigned int mode; + }; + + Key::Key() { + d = new Private( 0, 0 ); + } + + Key::Key( gpgme_key_t key, bool ref, unsigned int mode ) { + d = new Private( key, mode ); + if ( ref && d->key ) + gpgme_key_ref( d->key ); + } + + Key::Key( const Key & other ) { + d = new Private( other.d->key, other.d->mode ); + if ( d->key ) + gpgme_key_ref( d->key ); + } + + Key::~Key() { + if ( d->key ) + gpgme_key_unref( d->key ); + delete d; d = 0; + } + + const Key & Key::operator=( const Key & other ) { + if ( d == other.d ) return *this; + + if ( other.d->key ) + gpgme_key_ref( other.d->key ); + if ( d->key ) + gpgme_key_unref( d->key ); + *d = *other.d; + return *this; + } + + bool Key::isNull() const { + return d->key == 0; + } + + gpgme_key_t Key::impl() const { + return d->key; + } + + + + UserID Key::userID( unsigned int index ) const { + return UserID( d->key, index ); + } + + Subkey Key::subkey( unsigned int index ) const { + return Subkey( d->key, index ); + } + + + unsigned int Key::numUserIDs() const { + if ( !d->key ) + return 0; + unsigned int count = 0; + for ( gpgme_user_id_t uid = d->key->uids ; uid ; uid = uid->next ) + ++count; + return count; + } + + unsigned int Key::numSubkeys() const { + if ( !d->key ) + return 0; + unsigned int count = 0; + for ( gpgme_sub_key_t subkey = d->key->subkeys ; subkey ; subkey = subkey->next ) + ++count; + return count; + } + + vector<UserID> Key::userIDs() const { + if ( !d->key ) + return vector<UserID>(); + + vector<UserID> v; + v.reserve( numUserIDs() ); + for ( gpgme_user_id_t uid = d->key->uids ; uid ; uid = uid->next ) + v.push_back( UserID( d->key, uid ) ); + return v; + } + + vector<Subkey> Key::subkeys() const { + if ( !d->key ) + return vector<Subkey>(); + + vector<Subkey> v; + v.reserve( numSubkeys() ); + for ( gpgme_sub_key_t subkey = d->key->subkeys ; subkey ; subkey = subkey->next ) + v.push_back( Subkey( d->key, subkey ) ); + return v; + } + + Key::OwnerTrust Key::ownerTrust() const { + if ( !d->key ) + return Unknown; + switch ( d->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 ( !d->key ) + return '?'; + switch ( d->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'; + } + } + + Context::Protocol Key::protocol() const { + if ( !d->key ) + return Context::Unknown; + switch ( d->key->protocol ) { + case GPGME_PROTOCOL_CMS: return Context::CMS; + case GPGME_PROTOCOL_OpenPGP: return Context::OpenPGP; + default: return Context::Unknown; + } + } + + const char * Key::protocolAsString() const { + return d->key ? gpgme_get_protocol_name( d->key->protocol ) : 0 ; + } + + bool Key::isRevoked() const { + return d->key && d->key->revoked; + } + + bool Key::isExpired() const { + return d->key && d->key->expired; + } + + bool Key::isDisabled() const { + return d->key && d->key->disabled; + } + + bool Key::isInvalid() const { + return d->key && d->key->invalid; + } + + bool Key::hasSecret() const { + return d->key && d->key->secret; + } + + bool Key::isRoot() const { + return d->key && d->key->subkeys && d->key->subkeys->fpr && d->key->chain_id && + strcasecmp( d->key->subkeys->fpr, d->key->chain_id ) == 0; + } + + bool Key::canEncrypt() const { + return d->key && d->key->can_encrypt; + } + + bool Key::canSign() const { +#ifndef GPGME_CAN_SIGN_ON_SECRET_OPENPGP_KEYLISTING_NOT_BROKEN + if ( d->key && d->key->protocol == GPGME_PROTOCOL_OpenPGP ) + return true; +#endif + return d->key && d->key->can_sign; + } + + bool Key::canCertify() const { + return d->key && d->key->can_certify; + } + + bool Key::canAuthenticate() const { + return d->key && d->key->can_authenticate; + } + + const char * Key::issuerSerial() const { + return d->key ? d->key->issuer_serial : 0 ; + } + const char * Key::issuerName() const { + return d->key ? d->key->issuer_name : 0 ; + } + const char * Key::chainID() const { + return d->key ? d->key->chain_id : 0 ; + } + + const char * Key::keyID() const { +#ifdef HAVE_GPGME_KEY_T_KEYID + return d->key ? d->key->keyid : 0 ; +#else + if ( !d->key || !d->key->subkeys || !d->key->subkeys->fpr ) + return 0; + const int len = strlen( d->key->subkeys->fpr ); + if ( len < 16 ) + return 0; + return d->key->subkeys->fpr + len - 16; // return the last 8 bytes (in hex notation) +#endif + } + + const char * Key::shortKeyID() const { + if ( const char * keyid = keyID() ) + return keyid + 8 ; + else + return 0; + } + + const char * Key::primaryFingerprint() const { +#ifdef HAVE_GPGME_KEY_T_FPR + return d->key ? d->key->fpr : 0 ; +#else + return d->key && d->key->subkeys ? d->key->subkeys->fpr : 0 ; +#endif + } + + unsigned int Key::keyListMode() const { +#ifdef HAVE_GPGME_KEY_T_KEYLIST_MODE + return d->key ? convert_from_gpgme_keylist_mode_t( d->key->keylist_mode ) : 0 ; +#else + return d ? d->mode : 0 ; +#endif + } + + // + // + // class Subkey + // + // + + struct Subkey::Private { + Private( gpgme_key_t aKey, unsigned int idx ) + : key( aKey ), subkey( 0 ) + { + if ( key ) + for ( gpgme_sub_key_t s = key->subkeys ; s ; s = s->next, --idx ) + if ( idx == 0 ) { + subkey = s; + break; + } + if ( !subkey ) + key = 0; + } + + Private( gpgme_key_t aKey, gpgme_sub_key_t aSubkey ) + : key( aKey ), subkey( 0 ) + { + if ( key ) + for ( gpgme_sub_key_t s = key->subkeys ; s ; s = s->next ) + if ( s == aSubkey ) { // verify this subkey really belongs to this key + subkey = aSubkey; + break; + } + if ( !subkey ) + key = 0; + } + + gpgme_key_t key; + gpgme_sub_key_t subkey; + }; + + Subkey::Subkey( gpgme_key_t key, unsigned int idx ) { + d = new Private( key, idx ); + if ( d->key ) + gpgme_key_ref( d->key ); + } + + Subkey::Subkey( gpgme_key_t key, gpgme_sub_key_t subkey ) { + d = new Private( key, subkey ); + if ( d->key ) + gpgme_key_ref( d->key ); + } + + Subkey::Subkey( const Subkey & other ) { + d = new Private( other.d->key, other.d->subkey ); + if ( d->key ) + gpgme_key_ref( d->key ); + } + + Subkey::~Subkey() { + if ( d->key ) + gpgme_key_unref( d->key ); + delete d; d = 0; + } + + const Subkey & Subkey::operator=( const Subkey & other ) { + if ( &other == this ) return *this; + + if ( other.d->key ) + gpgme_key_ref( other.d->key ); + if ( d->key ) + gpgme_key_unref( d->key ); + *d = *other.d; + return *this; + } + + bool Subkey::isNull() const { + return !d || !d->key || !d->subkey; + } + + Key Subkey::parent() const { + return Key( d->key, true ); + } + + const char * Subkey::keyID() const { + return d->subkey ? d->subkey->keyid : 0 ; + } + + const char * Subkey::fingerprint() const { + return d->subkey ? d->subkey->fpr : 0 ; + } + + unsigned int Subkey::publicKeyAlgorithm() const { + return d->subkey ? d->subkey->pubkey_algo : 0 ; + } + + const char * Subkey::publicKeyAlgorithmAsString() const { + return gpgme_pubkey_algo_name( d->subkey ? d->subkey->pubkey_algo : (gpgme_pubkey_algo_t)0 ); + } + + bool Subkey::canEncrypt() const { + return d->subkey && d->subkey->can_encrypt; + } + + bool Subkey::canSign() const { + return d->subkey && d->subkey->can_sign; + } + + bool Subkey::canCertify() const { + return d->subkey && d->subkey->can_certify; + } + + bool Subkey::canAuthenticate() const { + return d->subkey && d->subkey->can_authenticate; + } + + bool Subkey::isSecret() const { + return d->subkey && d->subkey->secret; + } + + unsigned int Subkey::length() const { + return d->subkey ? d->subkey->length : 0 ; + } + + time_t Subkey::creationTime() const { + return static_cast<time_t>( d->subkey ? d->subkey->timestamp : 0 ); + } + + time_t Subkey::expirationTime() const { + return static_cast<time_t>( d->subkey ? d->subkey->expires : 0 ); + } + + bool Subkey::neverExpires() const { + return expirationTime() == time_t(0); + } + + bool Subkey::isRevoked() const { + return d->subkey && d->subkey->revoked; + } + + bool Subkey::isInvalid() const { + return d->subkey && d->subkey->invalid; + } + + bool Subkey::isExpired() const { + return d->subkey && d->subkey->expired; + } + + bool Subkey::isDisabled() const { + return d->subkey && d->subkey->disabled; + } + + // + // + // class UserID + // + // + + struct UserID::Private { + Private( gpgme_key_t aKey, unsigned int idx ) + : key( aKey ), uid( 0 ) + { + if ( key ) + for ( gpgme_user_id_t u = key->uids ; u ; u = u->next, --idx ) + if ( idx == 0 ) { + uid = u; + break; + } + if ( !uid ) + key = 0; + } + + Private( gpgme_key_t aKey, gpgme_user_id_t aUid ) + : key( aKey ), uid( 0 ) + { + if ( key ) + for ( gpgme_user_id_t u = key->uids ; u ; u = u->next ) + if ( u == aUid ) { + uid = u; + break; + } + if ( !uid ) + key = 0; + } + + gpgme_key_t key; + gpgme_user_id_t uid; + }; + + UserID::UserID( gpgme_key_t key, gpgme_user_id_t uid ) { + d = new Private( key, uid ); + if ( d->key ) + gpgme_key_ref( d->key ); + } + + UserID::UserID( gpgme_key_t key, unsigned int idx ) { + d = new Private( key, idx ); + if ( d->key ) + gpgme_key_ref( d->key ); + } + + UserID::UserID( const UserID & other ) { + d = new Private( other.d->key, other.d->uid ); + if ( d->key ) + gpgme_key_ref( d->key ); + } + + UserID::~UserID() { + if ( d->key ) + gpgme_key_unref( d->key ); + delete d; d = 0; + } + + const UserID & UserID::operator=( const UserID & other ) { + if ( &other == this ) return *this; + + if ( other.d->key ) + gpgme_key_ref( other.d->key ); + if ( d->key ) + gpgme_key_unref( d->key ); + *d = *other.d; + return *this; + } + + bool UserID::isNull() const { + return !d || !d->key || !d->uid; + } + + Key UserID::parent() const { + return Key( d->key, true ); + } + + UserID::Signature UserID::signature( unsigned int index ) const { + return Signature( d->key, d->uid, index ); + } + + unsigned int UserID::numSignatures() const { + if ( !d->uid ) + return 0; + unsigned int count = 0; + for ( gpgme_key_sig_t sig = d->uid->signatures ; sig ; sig = sig->next ) + ++count; + return count; + } + + vector<UserID::Signature> UserID::signatures() const { + if ( !d->uid ) + return vector<Signature>(); + + vector<Signature> v; + v.reserve( numSignatures() ); + for ( gpgme_key_sig_t sig = d->uid->signatures ; sig ; sig = sig->next ) + v.push_back( Signature( d->key, d->uid, sig ) ); + return v; + } + + const char * UserID::id() const { + return d->uid ? d->uid->uid : 0 ; + } + + const char * UserID::name() const { + return d->uid ? d->uid->name : 0 ; + } + + const char * UserID::email() const { + return d->uid ? d->uid->email : 0 ; + } + + const char * UserID::comment() const { + return d->uid ? d->uid->comment : 0 ; + } + + UserID::Validity UserID::validity() const { + if ( !d->uid ) + return Unknown; + switch ( d->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 ( !d->uid ) + return '?'; + switch ( d->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 d->uid && d->uid->revoked; + } + + bool UserID::isInvalid() const { + return d->uid && d->uid->invalid; + } + + // + // + // class Signature + // + // + + struct UserID::Signature::Private { + Private( gpgme_key_t aKey, gpgme_user_id_t aUid, unsigned int idx ) + : key( aKey ), uid( 0 ), sig( 0 ) + { + if ( key ) + for ( gpgme_user_id_t u = key->uids ; u ; u = u->next ) + if ( u == aUid ) { + uid = u; + for ( gpgme_key_sig_t s = uid->signatures ; s ; s = s->next, --idx ) + if ( idx == 0 ) { + sig = s; + break; + } + break; + } + if ( !uid || !sig ) { + uid = 0; + sig = 0; + key = 0; + } + } + + Private( gpgme_key_t aKey, gpgme_user_id_t aUid, gpgme_key_sig_t aSig ) + : key( aKey ), uid( 0 ), sig( 0 ) + { + if ( key ) + for ( gpgme_user_id_t u = key->uids ; u ; u = u->next ) + if ( u == aUid ) { + uid = u; + for ( gpgme_key_sig_t s = uid->signatures ; s ; s = s->next ) + if ( s == aSig ) { + sig = s; + break; + } + break; + } + if ( !uid || !sig ) { + uid = 0; + sig = 0; + key = 0; + } + } + + gpgme_key_t key; + gpgme_user_id_t uid; + gpgme_key_sig_t sig; + }; + + UserID::Signature::Signature( gpgme_key_t key, gpgme_user_id_t uid, unsigned int idx ) { + d = new Private( key, uid, idx ); + if ( d->key ) + gpgme_key_ref( d->key ); + } + + UserID::Signature::Signature( gpgme_key_t key, gpgme_user_id_t uid, gpgme_key_sig_t sig ) { + d = new Private( key, uid, sig ); + if ( d->key ) + gpgme_key_ref( d->key ); + } + + UserID::Signature::Signature( const Signature & other ) { + d = new Private( other.d->key, other.d->uid, other.d->sig ); + if ( d->key ) + gpgme_key_ref( d->key ); + } + + UserID::Signature::~Signature() { + if ( d->key ) + gpgme_key_unref( d->key ); + delete d; d = 0; + } + + const UserID::Signature & UserID::Signature::operator=( const Signature & other ) { + if ( &other == this ) return *this; + + if ( other.d->key ) + gpgme_key_ref( other.d->key ); + if ( d->key ) + gpgme_key_unref( d->key ); + *d = *other.d; + return *this; + } + + bool UserID::Signature::isNull() const { + return !d || !d->key || !d->uid || !d->sig; + } + + UserID UserID::Signature::parent() const { + return UserID( d->key, d->uid ); + } + + const char * UserID::Signature::signerKeyID() const { + return d->sig ? d->sig->keyid : 0 ; + } + + const char * UserID::Signature::algorithmAsString() const { + return gpgme_pubkey_algo_name( d->sig ? d->sig->pubkey_algo : (gpgme_pubkey_algo_t)0 ); + } + + unsigned int UserID::Signature::algorithm() const { + return d->sig ? d->sig->pubkey_algo : 0 ; + } + + time_t UserID::Signature::creationTime() const { + return static_cast<time_t>( d->sig ? d->sig->timestamp : 0 ); + } + + time_t UserID::Signature::expirationTime() const { + return static_cast<time_t>( d->sig ? d->sig->expires : 0 ); + } + + bool UserID::Signature::neverExpires() const { + return expirationTime() == time_t(0); + } + + bool UserID::Signature::isRevokation() const { + return d->sig && d->sig->revoked; + } + + bool UserID::Signature::isInvalid() const { + return d->sig && d->sig->invalid; + } + + bool UserID::Signature::isExpired() const { + return d->sig && d->sig->expired; + } + + bool UserID::Signature::isExportable() const { + return d->sig && d->sig->exportable; + } + + const char * UserID::Signature::signerUserID() const { + return d->sig ? d->sig->uid : 0 ; + } + + const char * UserID::Signature::signerName() const { + return d->sig ? d->sig->name : 0 ; + } + + const char * UserID::Signature::signerEmail() const { + return d->sig ? d->sig->email : 0 ; + } + + const char * UserID::Signature::signerComment() const { + return d->sig ? d->sig->comment : 0 ; + } + + unsigned int UserID::Signature::certClass() const { + return d->sig ? d->sig->sig_class : 0 ; + } + + UserID::Signature::tqStatus UserID::Signature::status() const { + if ( !d->sig ) + return GeneralError; + + switch ( gpgme_err_code(d->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; + } + } + + const char * UserID::Signature::statusAsString() const { + return d->sig ? gpgme_strerror( d->sig->status ) : 0 ; + } + + UserID::Signature::Notation UserID::Signature::notation( unsigned int idx ) const { + return Notation( d->key, d->uid, d->sig, idx ); + } + + unsigned int UserID::Signature::numNotations() const { + if ( !d->sig ) + return 0; + unsigned int count = 0; +#ifdef HAVE_GPGME_KEY_SIG_NOTATIONS + for ( gpgme_sig_notation_t nota = d->sig->notations ; nota ; nota = nota->next ) + if ( nota->name ) ++count; // others are policy URLs... +#endif + return count; + } + + vector<UserID::Signature::Notation> UserID::Signature::notations() const { + if ( !d->sig ) + return vector<Notation>(); + vector<Notation> v; +#ifdef HAVE_GPGME_KEY_SIG_NOTATIONS + v.reserve( numNotations() ); + for ( gpgme_sig_notation_t nota = d->sig->notations ; nota ; nota = nota->next ) + if ( nota->name ) + v.push_back( Notation( d->key, d->uid, d->sig, nota ) ); +#endif + return v; + } + + const char * UserID::Signature::policyURL() const { +#ifdef HAVE_GPGME_KEY_SIG_NOTATIONS + if ( !d->sig ) + return 0; + for ( gpgme_sig_notation_t nota = d->sig->notations ; nota ; nota = nota->next ) + if ( !nota->name ) + return nota->value; +#endif + return 0; + } + + + + // + // + // class Notation + // + // + + struct UserID::Signature::Notation::Private { + Private( gpgme_key_t aKey, gpgme_user_id_t aUid, + gpgme_key_sig_t aSig, unsigned int idx ) + : key( aKey ), uid( 0 ), sig( 0 ), nota( 0 ) + { + if ( key ) + for ( gpgme_user_id_t u = key->uids ; u ; u = u->next ) + if ( u == aUid ) { + uid = u; + for ( gpgme_key_sig_t s = uid->signatures ; s ; s = s->next ) + if ( s == aSig ) { + sig = s; +#ifdef HAVE_GPGME_KEY_SIG_NOTATIONS + for ( gpgme_sig_notation_t n = sig->notations ; n ; n = n->next, --idx ) + if ( n == aNota ) { + nota = n; + break; + } +#else + (void)idx; +#endif + break; + } + break; + } + if ( !uid || !sig || !nota ) { + uid = 0; + sig = 0; + key = 0; + nota = 0; + } + } + + Private( gpgme_key_t aKey, gpgme_user_id_t aUid, + gpgme_key_sig_t aSig, gpgme_sig_notation_t aNota ) + : key( aKey ), uid( 0 ), sig( 0 ), nota( 0 ) + { + if ( key ) + for ( gpgme_user_id_t u = key->uids ; u ; u = u->next ) + if ( u == aUid ) { + uid = u; + for ( gpgme_key_sig_t s = uid->signatures ; s ; s = s->next ) + if ( s == aSig ) { + sig = s; +#ifdef HAVE_GPGME_KEY_SIG_NOTATIONS + for ( gpgme_sig_notation_t n = sig->notations ; n ; n = n->next ) + if ( n == aNota ) { + nota = n; + break; + } +#else + (void)aNota; +#endif + break; + } + break; + } + if ( !uid || !sig || !nota ) { + uid = 0; + sig = 0; + key = 0; + nota = 0; + } + } + + gpgme_key_t key; + gpgme_user_id_t uid; + gpgme_key_sig_t sig; + gpgme_sig_notation_t nota; + }; + + UserID::Signature::Notation::Notation( gpgme_key_t key, gpgme_user_id_t uid, + gpgme_key_sig_t sig, unsigned int idx ) { + d = new Private( key, uid, sig, idx ); + if ( d->key ) + gpgme_key_ref( d->key ); + } + + UserID::Signature::Notation::Notation( gpgme_key_t key, gpgme_user_id_t uid, + gpgme_key_sig_t sig, gpgme_sig_notation_t nota ) { + d = new Private( key, uid, sig, nota ); + if ( d->key ) + gpgme_key_ref( d->key ); + } + + UserID::Signature::Notation::Notation( const Notation & other ) { + d = new Private( other.d->key, other.d->uid, other.d->sig, other.d->nota ); + if ( d->key ) + gpgme_key_ref( d->key ); + } + + UserID::Signature::Notation::~Notation() { + if ( d->key ) + gpgme_key_unref( d->key ); + delete d; d = 0; + } + + const UserID::Signature::Notation & UserID::Signature::Notation::operator=( const Notation & other ) { + if ( &other == this ) return *this; + + if ( other.d->key ) + gpgme_key_ref( other.d->key ); + if ( d->key ) + gpgme_key_unref( d->key ); + *d = *other.d; + return *this; + } + + bool UserID::Signature::Notation::isNull() const { + return !d || !d->key || !d->uid || !d->sig || !d->nota; + } + + UserID::Signature UserID::Signature::Notation::parent() const { + return Signature( d->key, d->uid, d->sig ); + } + + const char * UserID::Signature::Notation::name() const { + return d->nota ? d->nota->name : 0 ; + } + + const char * UserID::Signature::Notation::value() const { + return d->nota ? d->nota->value : 0 ; + } + +} // namespace GpgME diff --git a/libtdenetwork/gpgmepp/key.h b/libtdenetwork/gpgmepp/key.h new file mode 100644 index 000000000..15d09371e --- /dev/null +++ b/libtdenetwork/gpgmepp/key.h @@ -0,0 +1,285 @@ +/* key.h - wraps a gpgme key + 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 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GPGME; 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 <gpgmepp/gpgmefw.h> +#include <gpgmepp/context.h> + +#include <sys/time.h> + +#include <vector> +#include <tdepimmacros.h> + +namespace GpgME { + + class Subkey; + class UserID; + + // + // class Key + // + + class KDE_EXPORT Key { + friend class Context; + public: + Key(); + Key( gpgme_key_t key, bool acquireRef, unsigned int keyListMode=0 ); + Key( const Key & key ); + ~Key(); + + static Key null; + + const Key & operator=( const Key & other ); + + bool isNull() const; + + 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; + bool canSign() const; + bool canCertify() const; + bool canAuthenticate() const; + + bool hasSecret() const; + 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; + + typedef Context::Protocol Protocol; + 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; + + typedef Context::KeyListMode KeyListMode; + unsigned int keyListMode() const; + + private: + gpgme_key_t impl() const; + class Private; + Private * d; + }; + + // + // class Subkey + // + + class KDE_EXPORT Subkey { + public: + Subkey( gpgme_key_t key=0, gpgme_sub_key_t subkey=0 ); + Subkey( gpgme_key_t key, unsigned int idx ); + Subkey( const Subkey & other ); + ~Subkey(); + + const Subkey & operator=( const Subkey & other ); + + bool isNull() const; + + 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 isSecret() const; + + unsigned int publicKeyAlgorithm() const; + const char * publicKeyAlgorithmAsString() const; + + unsigned int length() const; + + private: + class Private; + Private * d; + }; + + // + // class UserID + // + + class KDE_EXPORT UserID { + public: + class Signature; + + UserID( gpgme_key_t key=0, gpgme_user_id_t uid=0 ); + UserID( gpgme_key_t key, unsigned int idx ); + UserID( const UserID & other ); + ~UserID(); + + const UserID & operator=( const UserID & other ); + + bool isNull() const; + + 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: + class Private; + Private * d; + }; + + // + // class UserID::Signature + // + + class KDE_EXPORT UserID::Signature { + public: + class Notation; + + Signature( gpgme_key_t key=0, gpgme_user_id_t uid=0, gpgme_key_sig_t sig=0 ); + Signature( gpgme_key_t key, gpgme_user_id_t uid, unsigned int idx ); + Signature( const Signature & other ); + ~Signature(); + + const Signature & operator=( const Signature & other ); + + bool isNull() const; + + 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 tqStatus { NoError = 0, SigExpired, KeyExpired, + BadSignature, NoPublicKey, GeneralError }; + tqStatus status() const; + const char * statusAsString() const; + + const char * policyURL() const; + + unsigned int numNotations() const; + Notation notation( unsigned int idx ) const; + std::vector<Notation> notations() const; + + private: + class Private; + Private * d; + }; + + // + // + // class UserID::Signature::Notation + // + // + + class KDE_EXPORT UserID::Signature::Notation { + public: + Notation( gpgme_key_t key=0, gpgme_user_id_t uid=0, + gpgme_key_sig_t sig=0, gpgme_sig_notation_t nota=0 ); + Notation( gpgme_key_t key, gpgme_user_id_t uid, + gpgme_key_sig_t sig, unsigned int idx ); + Notation( const Notation & other ); + ~Notation(); + + const Notation & operator=( const Notation & other ); + + bool isNull() const; + + Signature parent() const; + + const char * name() const; + const char * value() const; + + private: + class Private; + Private * d; + }; + +} // namespace GpgME + +#endif // __GPGMEPP_KEY_H__ diff --git a/libtdenetwork/gpgmepp/keygenerationresult.cpp b/libtdenetwork/gpgmepp/keygenerationresult.cpp new file mode 100644 index 000000000..76045ee29 --- /dev/null +++ b/libtdenetwork/gpgmepp/keygenerationresult.cpp @@ -0,0 +1,73 @@ +/* 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 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GPGME++; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gpgmepp/keygenerationresult.h> +#include "shared.h" +#include "result_p.h" + +#include <gpgme.h> + +#include <cstring> +#include <cstdlib> + +class GpgME::KeyGenerationResult::Private : public GpgME::Shared { +public: + Private( const _gpgme_op_genkey_result & r ) : Shared(), 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( 0 ) +{ + if ( error || !ctx ) + return; + gpgme_genkey_result_t res = gpgme_op_genkey_result( ctx ); + if ( !res ) + return; + d = new Private( *res ); + d->ref(); +} + +make_standard_stuff(KeyGenerationResult) + +bool GpgME::KeyGenerationResult::primaryKeyGenerated() const { + return d && d->res.primary; +} + +bool GpgME::KeyGenerationResult::subkeyGenerated() const { + return d && d->res.sub; +} + +const char * GpgME::KeyGenerationResult::fingerprint() const { + return d ? d->res.fpr : 0 ; +} diff --git a/libtdenetwork/gpgmepp/keygenerationresult.h b/libtdenetwork/gpgmepp/keygenerationresult.h new file mode 100644 index 000000000..7b2d98e84 --- /dev/null +++ b/libtdenetwork/gpgmepp/keygenerationresult.h @@ -0,0 +1,53 @@ +/* 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 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GPGME++; 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 <gpgmepp/gpgmefw.h> +#include <gpgmepp/result.h> +#include <tdepimmacros.h> +namespace GpgME { + + class Error; + + class KDE_EXPORT KeyGenerationResult : public Result { + public: + KeyGenerationResult( gpgme_ctx_t ctx=0, int error=0 ); + explicit KeyGenerationResult( const Error & err ); + KeyGenerationResult( const KeyGenerationResult & other ); + ~KeyGenerationResult(); + + const KeyGenerationResult & operator=( const KeyGenerationResult & other ); + + bool isNull() const; + + bool primaryKeyGenerated() const; + bool subkeyGenerated() const; + const char * fingerprint() const; + + private: + class Private; + Private * d; + }; + +} + +#endif // __GPGMEPP_KEYGENERATIONRESULT_H__ diff --git a/libtdenetwork/gpgmepp/keylistresult.cpp b/libtdenetwork/gpgmepp/keylistresult.cpp new file mode 100644 index 000000000..17dc3a46d --- /dev/null +++ b/libtdenetwork/gpgmepp/keylistresult.cpp @@ -0,0 +1,92 @@ +/* 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 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GPGME++; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gpgmepp/keylistresult.h> +#include "shared.h" +#include "result_p.h" + +#include <gpgme.h> + +#include <cstring> +#include <cassert> + +class GpgME::KeyListResult::Private : public GpgME::Shared { +public: + Private( const _gpgme_op_keylist_result & r ) : Shared(), res( r ) {} + Private( const Private & other ) : Shared(), res( other.res ) {} + + _gpgme_op_keylist_result res; +}; + +GpgME::KeyListResult::KeyListResult( gpgme_ctx_t ctx, int error ) + : GpgME::Result( error ), d( 0 ) +{ + if ( error || !ctx ) + return; + gpgme_keylist_result_t res = gpgme_op_keylist_result( ctx ); + if ( !res ) + return; + d = new Private( *res ); + d->ref(); +} + +GpgME::KeyListResult::KeyListResult( const Error & error, const _gpgme_op_keylist_result & res ) + : GpgME::Result( error ), d( 0 ) +{ + d = new Private( res ); + d->ref(); +} + +make_standard_stuff(KeyListResult) + +void GpgME::KeyListResult::detach() { + if ( !d || d->refCount() <= 1 ) + return; + d->unref(); + d = 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 = new Private( *other.d ); + else + d->res.truncated = true; + } + if ( !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/libtdenetwork/gpgmepp/keylistresult.h b/libtdenetwork/gpgmepp/keylistresult.h new file mode 100644 index 000000000..068210c02 --- /dev/null +++ b/libtdenetwork/gpgmepp/keylistresult.h @@ -0,0 +1,62 @@ +/* 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 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GPGME++; 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 <gpgmepp/gpgmefw.h> +#include <gpgmepp/result.h> +#include <tdepimmacros.h> + +namespace GpgME { + + class Context; + class Error; + + class KDE_EXPORT KeyListResult : public Result { + public: + KeyListResult( gpgme_ctx_t ctx=0, int error=0 ); + explicit KeyListResult( const Error & err ); + KeyListResult( const Error & err, const _gpgme_op_keylist_result & res ); + KeyListResult( const KeyListResult & other ); + ~KeyListResult(); + + const KeyListResult & operator=( const KeyListResult & other ); + + const KeyListResult & operator+=( const KeyListResult & other ) { + mergeWith( other ); + return *this; + } + + void mergeWith( const KeyListResult & other ); + + bool isNull() const; + + bool isTruncated() const; + + private: + void detach(); + class Private; + Private * d; + }; + +} + +#endif // __GPGMEPP_KEYLISTRESULT_H__ diff --git a/libtdenetwork/gpgmepp/result.h b/libtdenetwork/gpgmepp/result.h new file mode 100644 index 000000000..aa91cf984 --- /dev/null +++ b/libtdenetwork/gpgmepp/result.h @@ -0,0 +1,47 @@ +/* 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 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GPGME++; 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 <gpgmepp/gpgmefw.h> +#include <gpgmepp/context.h> + +namespace GpgME { + + class Result { + public: + Result( int error=0 ) : mError( error ) {} + Result( const Result & other ) : mError( other.error() ) {} + + const Result & operator=( const Result & other ) { + mError = other.mError; + return *this; + } + + const Error & error() const { return mError; } + + private: + Error mError; + }; + +} + +#endif // __GPGMEPP_RESULT_H__ diff --git a/libtdenetwork/gpgmepp/result_p.h b/libtdenetwork/gpgmepp/result_p.h new file mode 100644 index 000000000..cc1d2793f --- /dev/null +++ b/libtdenetwork/gpgmepp/result_p.h @@ -0,0 +1,69 @@ +/* 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 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GPGME++; 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_copy_ctor(x) \ +GpgME::x::x( const x & other ) \ + : GpgME::Result( other ), d( other.d ) \ +{ \ + if ( d ) \ + d->ref(); \ +} + +#define make_error_ctor(x) \ +GpgME::x::x( const Error & error ) \ + : GpgME::Result( error ), d( 0 ) \ +{ \ + \ +} + +#define make_assignment_operator(x) \ +const GpgME::x & GpgME::x::operator=( const x & other ) { \ + if ( other.d ) \ + other.d->ref(); \ + if ( this->d ) \ + this->d->unref(); \ + this->d = other.d; \ + \ + Result::operator=( other ); \ + \ + return *this; \ +} + +#define make_dtor(x) \ +GpgME::x::~x() { \ + if ( d ) \ + d->unref(); \ + d = 0; \ +} + +#define make_isNull(x) bool GpgME::x::isNull() const { return !d && !error(); } + +#define make_standard_stuff(x) \ +make_copy_ctor(x) \ +make_error_ctor(x) \ +make_assignment_operator(x) \ +make_isNull(x) \ +make_dtor(x) + + +#endif // __GPGMEPP_RESULT_P_H__ diff --git a/libtdenetwork/gpgmepp/shared.h b/libtdenetwork/gpgmepp/shared.h new file mode 100644 index 000000000..f9c79e0cc --- /dev/null +++ b/libtdenetwork/gpgmepp/shared.h @@ -0,0 +1,54 @@ +/* shared.h - internal tool for refcounting -*- c++ -*- + 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 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GPGME; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifndef __GPGMEPP_SHARED_H__ +#define __GPGMEPP_SHARED_H__ + +#include <cassert> + +namespace GpgME { + + class Shared { + protected: + Shared() : mRefCount( 0 ) {} + virtual ~Shared() { + assert( mRefCount <= 0 ); + } + + public: + int ref() { return ++mRefCount; } + int deref() { return unref(); } + int unref() { + if ( --mRefCount <= 0 ) { + delete this; + return 0; + } + return mRefCount; + } + int refCount() { return mRefCount; } + + private: + int mRefCount; + }; + +} + + +#endif // __GPGMEPP_SHARED_H__ diff --git a/libtdenetwork/gpgmepp/signingresult.cpp b/libtdenetwork/gpgmepp/signingresult.cpp new file mode 100644 index 000000000..6996eef7a --- /dev/null +++ b/libtdenetwork/gpgmepp/signingresult.cpp @@ -0,0 +1,283 @@ +/* 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 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GPGME++; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gpgmepp/signingresult.h> +#include "shared.h" +#include "result_p.h" +#include "util.h" + +#include <gpgme.h> + +#include <cstring> +#include <cstdlib> +#include <algorithm> +#include <istream> +#include <iterator> + +class GpgME::SigningResult::Private : public GpgME::Shared { +public: + Private( const gpgme_sign_result_t r ) : Shared() { + 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( 0 ) +{ + if ( error || !ctx ) + return; + gpgme_sign_result_t res = gpgme_op_sign_result( ctx ); + if ( !res ) + return; + d = new Private( res ); + d->ref(); +} + +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( SigningResult::Private * parent, unsigned int i ) + : d( parent ), idx( i ) +{ + if ( d ) + d->ref(); +} + +GpgME::InvalidSigningKey::InvalidSigningKey() : d( 0 ), idx( 0 ) {} + +GpgME::InvalidSigningKey::InvalidSigningKey( const InvalidSigningKey & other ) + : d( other.d ), idx( other.idx ) +{ + if ( d ) + d->ref(); +} + +GpgME::InvalidSigningKey::~InvalidSigningKey() { + if ( d ) + d->unref(); +} + +const GpgME::InvalidSigningKey & GpgME::InvalidSigningKey::operator=( const InvalidSigningKey & other ) { + if ( this->d != other.d ) { + if ( other.d ) + other.d->ref(); + if ( this->d ) + this->d->unref(); + this->d = other.d; + } + + this->idx = other.idx; + return *this; +} + + +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 isNull() ? 0 : d->invalid[idx]->reason ; +} + + + +GpgME::CreatedSignature::CreatedSignature( SigningResult::Private * parent, unsigned int i ) + : d( parent ), idx( i ) +{ + if ( d ) + d->ref(); +} + +GpgME::CreatedSignature::CreatedSignature() : d( 0 ), idx( 0 ) {} + +GpgME::CreatedSignature::CreatedSignature( const CreatedSignature & other ) + : d( other.d ), idx( other.idx ) +{ + if ( d ) + d->ref(); +} + +GpgME::CreatedSignature::~CreatedSignature() { + if ( d ) + d->unref(); +} + +const GpgME::CreatedSignature & GpgME::CreatedSignature::operator=( const CreatedSignature & other ) { + if ( this->d != other.d ) { + if ( other.d ) + other.d->ref(); + if ( this->d ) + this->d->unref(); + this->d = other.d; + } + + this->idx = other.idx; + return *this; +} + + +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::Context::SignatureMode GpgME::CreatedSignature::mode() const { + if ( isNull() ) + return Context::Normal; + switch ( d->created[idx]->type ) { + default: + case GPGME_SIG_MODE_NORMAL: return Context::Normal; + case GPGME_SIG_MODE_DETACH: return Context::Detached; + case GPGME_SIG_MODE_CLEAR: return Context::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/libtdenetwork/gpgmepp/signingresult.h b/libtdenetwork/gpgmepp/signingresult.h new file mode 100644 index 000000000..1ee7a8def --- /dev/null +++ b/libtdenetwork/gpgmepp/signingresult.h @@ -0,0 +1,124 @@ +/* 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 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GPGME++; 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 <gpgmepp/gpgmefw.h> +#include <gpgmepp/result.h> +#include <gpgmepp/context.h> + +#include <time.h> + +#include <vector> +#include <iosfwd> + +#include <tdepimmacros.h> + +namespace GpgME { + + class Error; + class CreatedSignature; + class InvalidSigningKey; + + class KDE_EXPORT SigningResult : public Result { + public: + SigningResult( gpgme_ctx_t ctx=0, int error=0 ); + explicit SigningResult( const Error & err ); + SigningResult( const SigningResult & other ); + ~SigningResult(); + + const SigningResult & operator=( const SigningResult & other ); + + 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: + Private * d; + }; + + KDE_EXPORT std::ostream & operator<<( std::ostream & os, const SigningResult & result ); + + class KDE_EXPORT InvalidSigningKey { + friend class SigningResult; + InvalidSigningKey( SigningResult::Private * parent, unsigned int index ); + public: + InvalidSigningKey(); + InvalidSigningKey( const InvalidSigningKey & other ); + ~InvalidSigningKey(); + + const InvalidSigningKey & operator=( const InvalidSigningKey & other ); + + bool isNull() const; + + const char * fingerprint() const; + Error reason() const; + + private: + SigningResult::Private * d; + unsigned int idx; + }; + + KDE_EXPORT std::ostream & operator<<( std::ostream & os, const InvalidSigningKey & key ); + + class KDE_EXPORT CreatedSignature { + friend class SigningResult; + CreatedSignature( SigningResult::Private * parent, unsigned int index ); + public: + class Notation; + + CreatedSignature(); + CreatedSignature( const CreatedSignature & other ); + ~CreatedSignature(); + + const CreatedSignature & operator=( const CreatedSignature & other ); + + bool isNull() const; + + const char * fingerprint() const; + + time_t creationTime() const; + + Context::SignatureMode mode() const; + + unsigned int publicKeyAlgorithm() const; + const char * publicKeyAlgorithmAsString() const; + + unsigned int hashAlgorithm() const; + const char * hashAlgorithmAsString() const; + + unsigned int signatureClass() const; + + private: + SigningResult::Private * d; + unsigned int idx; + }; + + KDE_EXPORT std::ostream & operator<<( std::ostream & os, const CreatedSignature & sig ); + +} + +#endif // __GPGMEPP_SIGNINGRESULT_H__ diff --git a/libtdenetwork/gpgmepp/trustitem.cpp b/libtdenetwork/gpgmepp/trustitem.cpp new file mode 100644 index 000000000..59840ebb6 --- /dev/null +++ b/libtdenetwork/gpgmepp/trustitem.cpp @@ -0,0 +1,109 @@ +/* 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 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GPGME; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gpgmepp/trustitem.h> + +#include <gpgme.h> + +#include <cassert> + +namespace GpgME { + + struct TrustItem::Private { + 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 ); + } + + const TrustItem & TrustItem::operator=( const TrustItem & other ) { + if ( &other == this ) return *this; + + if ( other.d->item ) + gpgme_trust_item_ref( other.d->item ); + if ( d->item ) + gpgme_trust_item_unref( d->item ); + *d = *other.d; + return *this; + } + + 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/libtdenetwork/gpgmepp/trustitem.h b/libtdenetwork/gpgmepp/trustitem.h new file mode 100644 index 000000000..61c74617b --- /dev/null +++ b/libtdenetwork/gpgmepp/trustitem.h @@ -0,0 +1,61 @@ +/* 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 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GPGME; 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 <gpgmepp/gpgmefw.h> +#include <gpgmepp/key.h> + +namespace GpgME { + + class Context; + + class TrustItem { + friend class Context; + public: + TrustItem( gpgme_trust_item_t item=0 ); + TrustItem( const TrustItem & other ); + virtual ~TrustItem(); + + const TrustItem & operator=( const TrustItem & other ); + + 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 + +#endif // __GPGMEPP_TRUSTITEM_H__ diff --git a/libtdenetwork/gpgmepp/util.h b/libtdenetwork/gpgmepp/util.h new file mode 100644 index 000000000..8246cfc32 --- /dev/null +++ b/libtdenetwork/gpgmepp/util.h @@ -0,0 +1,75 @@ +/* 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 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GPGME; 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 <gpgme.h> +#include <context.h> + +#ifndef NDEBUG +#include <iostream> +#endif + +static inline const char * protect( const char * s ) { + return s ? s : "<null>" ; +} + +static inline gpgme_keylist_mode_t add_to_gpgme_keylist_mode_t( unsigned int oldmode, unsigned int newmodes ) { + if ( newmodes & GpgME::Context::Local ) oldmode |= GPGME_KEYLIST_MODE_LOCAL; + if ( newmodes & GpgME::Context::Extern ) oldmode |= GPGME_KEYLIST_MODE_EXTERN; + if ( newmodes & GpgME::Context::Signatures ) oldmode |= GPGME_KEYLIST_MODE_SIGS; + if ( newmodes & GpgME::Context::Validate ) { +#ifdef HAVE_GPGME_KEYLIST_MODE_VALIDATE + oldmode |= GPGME_KEYLIST_MODE_VALIDATE; +#elif !defined(NDEBUG) + std::cerr << "GpgME::Context: ignoring Valdidate keylist flag (gpgme too old)." << std::endl; +#endif + } +#ifndef NDEBUG + if ( newmodes & ~(GpgME::Context::Local|GpgME::Context::Extern|GpgME::Context::Signatures|GpgME::Context::Validate) ) + std::cerr << "GpgME::Context: keylist mode must be one of Local, " + "Extern, Signatures, 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::Context::Local; + if ( mode & GPGME_KEYLIST_MODE_EXTERN ) result |= GpgME::Context::Extern; + if ( mode & GPGME_KEYLIST_MODE_SIGS ) result |= GpgME::Context::Signatures; +#ifdef HAVE_GPGME_KEYLIST_MODE_VALIDATE + if ( mode & GPGME_KEYLIST_MODE_VALIDATE ) result |= GpgME::Context::Validate; +#endif +#ifndef NDEBUG + if ( mode & ~(GPGME_KEYLIST_MODE_LOCAL| + GPGME_KEYLIST_MODE_EXTERN| +#ifdef HAVE_GPGME_KEYLIST_MODE_VALIDATE + GPGME_KEYLIST_MODE_VALIDATE| +#endif + GPGME_KEYLIST_MODE_SIGS) ) + std::cerr << "GpgME::Context: WARNING: gpgme_get_keylist_mode() returned an unknown flag!" << std::endl; +#endif // NDEBUG + return result; +} + + +#endif // __GPGMEPP_UTIL_H__ diff --git a/libtdenetwork/gpgmepp/verificationresult.cpp b/libtdenetwork/gpgmepp/verificationresult.cpp new file mode 100644 index 000000000..abf30d96c --- /dev/null +++ b/libtdenetwork/gpgmepp/verificationresult.cpp @@ -0,0 +1,357 @@ +/* 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 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GPGME++; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gpgmepp/verificationresult.h> +#include "shared.h" +#include "result_p.h" +#include "util.h" + +#include <gpgme.h> + +#include <istream> +#include <algorithm> +#include <iterator> +#include <cstring> +#include <cstdlib> + +class GpgME::VerificationResult::Private : public GpgME::Shared { +public: + Private( const gpgme_verify_result_t r ) : Shared() { + if ( !r ) + return; + // 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 ); + 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; + } + Nota n = { 0, 0 }; + 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 ); + 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; + }; + + std::vector<gpgme_signature_t> sigs; + std::vector< std::vector<Nota> > nota; + std::vector<char*> purls; +}; + +GpgME::VerificationResult::VerificationResult( gpgme_ctx_t ctx, int error ) + : GpgME::Result( error ), d( 0 ) +{ + if ( error || !ctx ) + return; + gpgme_verify_result_t res = gpgme_op_verify_result( ctx ); + if ( !res ) + return; + d = new Private( res ); + d->ref(); +} + +make_standard_stuff(VerificationResult) + +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( VerificationResult::Private * parent, unsigned int i ) + : d( parent ), idx( i ) +{ + if ( d ) + d->ref(); +} + +GpgME::Signature::Signature() : d( 0 ), idx( 0 ) {} + +GpgME::Signature::Signature( const Signature & other ) + : d( other.d ), idx( other.idx ) +{ + if ( d ) + d->ref(); +} + +GpgME::Signature::~Signature() { + if ( d ) + d->unref(); +} + +const GpgME::Signature & GpgME::Signature::operator=( const Signature & other ) { + if ( this->d != other.d ) { + if ( other.d ) + other.d->ref(); + if ( this->d ) + this->d->unref(); + this->d = other.d; + } + + this->idx = other.idx; + return *this; +} + + +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 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::wrongKeyUsage() const { + return !isNull() && d->sigs[idx]->wrong_key_usage; +} + +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 isNull() ? 0 : d->sigs[idx]->validity_reason ; +} + + +GpgME::Signature::Notation GpgME::Signature::notation( unsigned int nidx ) const { + return Notation( d, idx, nidx ); +} + +std::vector<GpgME::Signature::Notation> GpgME::Signature::notations() const { + if ( isNull() ) + return std::vector<Notation>(); + std::vector<Notation> result; + result.reserve( d->nota[idx].size() ); + for ( unsigned int i = 0 ; i < d->nota[idx].size() ; ++i ) + result.push_back( Notation( d, idx, i ) ); + return result; +} + + +GpgME::Signature::Notation::Notation( VerificationResult::Private * parent, unsigned int sindex, unsigned int nindex ) + : d( parent ), sidx( sindex ), nidx( nindex ) +{ + if ( d ) + d->ref(); +} + +GpgME::Signature::Notation::Notation() + : d( 0 ), sidx( 0 ), nidx( 0 ) {} + +GpgME::Signature::Notation::Notation( const Notation & other ) + : d( other.d ), sidx( other.sidx ), nidx( other.nidx ) +{ + if ( d ) + d->ref(); +} + +GpgME::Signature::Notation::~Notation() { + if ( d ) + d->unref(); +} + +const GpgME::Signature::Notation & GpgME::Signature::Notation::operator=( const Notation & other ) { + if ( this->d != other.d ) { + if ( other.d ) + other.d->ref(); + if ( this->d ) + this->d->ref(); + this->d = other.d; + } + + sidx = other.sidx; + nidx = other.nidx; + return *this; +} + +bool GpgME::Signature::Notation::isNull() const { + return !d || sidx >= d->nota.size() || nidx >= d->nota[sidx].size() ; +} + + +const char * GpgME::Signature::Notation::name() const { + return isNull() ? 0 : d->nota[sidx][nidx].name ; +} + +const char * GpgME::Signature::Notation::value() const { + return isNull() ? 0 : d->nota[sidx][nidx].value ; +} + + +std::ostream & GpgME::operator<<( std::ostream & os, const VerificationResult & result ) { + os << "GpgME::VerificationResult("; + if ( !result.isNull() ) { + os << "\n error: " << result.error() + << "\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::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 wrongKeyUsage: " << sig.wrongKeyUsage() + << "\n validity: " << sig.validityAsString() + << "\n nonValidityReason: " << sig.nonValidityReason() + << "\n notations:\n"; + const std::vector<Signature::Notation> nota = sig.notations(); + std::copy( nota.begin(), nota.end(), + std::ostream_iterator<Signature::Notation>( os, "\n" ) ); + } + return os << ')'; +} + +std::ostream & GpgME::operator<<( std::ostream & os, const Signature::Notation & nota ) { + return os << "GpgME::Signature::Notation( \"" << protect( nota.name() ) << "\", \"" << protect( nota.value() ) << "\")"; +} diff --git a/libtdenetwork/gpgmepp/verificationresult.h b/libtdenetwork/gpgmepp/verificationresult.h new file mode 100644 index 000000000..e572ecfee --- /dev/null +++ b/libtdenetwork/gpgmepp/verificationresult.h @@ -0,0 +1,144 @@ +/* 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 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 + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GPGME++; 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 <gpgmepp/gpgmefw.h> +#include <gpgmepp/result.h> + +#include <time.h> + +#include <vector> +#include <iosfwd> + +#include <tdepimmacros.h> + +namespace GpgME { + + class Error; + class Signature; + + class KDE_EXPORT VerificationResult : public Result { + public: + VerificationResult( gpgme_ctx_t ctx=0, int error=0 ); + explicit VerificationResult( const Error & err ); + VerificationResult( const VerificationResult & other ); + ~VerificationResult(); + + const VerificationResult & operator=( const VerificationResult & other ); + + bool isNull() const; + + Signature signature( unsigned int index ) const; + std::vector<Signature> signatures() const; + + class Private; + private: + Private * d; + }; + + KDE_EXPORT std::ostream & operator<<( std::ostream & os, const VerificationResult & result ); + + class KDE_EXPORT Signature { + friend class VerificationResult; + Signature( VerificationResult::Private * parent, unsigned int index ); + public: + class Notation; + + Signature(); + Signature( const Signature & other ); + ~Signature(); + + const Signature & operator=( const Signature & other ); + + 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; + + bool wrongKeyUsage() const; + + enum Validity { + Unknown, Undefined, Never, Marginal, Full, Ultimate + }; + Validity validity() const; + char validityAsString() const; + Error nonValidityReason() const; + + Notation notation( unsigned int index ) const; + std::vector<Notation> notations() const; + + private: + VerificationResult::Private * d; + unsigned int idx; + }; + + KDE_EXPORT std::ostream & operator<<( std::ostream & os, const Signature & sig ); + KDE_EXPORT std::ostream & operator<<( std::ostream & os, Signature::Summary summary ); + + class KDE_EXPORT Signature::Notation { + friend class Signature; + Notation( VerificationResult::Private * parent, unsigned int sindex, unsigned int nindex ); + public: + Notation(); + Notation( const Notation & other ); + ~Notation(); + + const Notation & operator=( const Notation & other ); + + bool isNull() const; + + const char * name() const; + const char * value() const; + + private: + VerificationResult::Private * d; + unsigned int sidx; + unsigned int nidx; + }; + + KDE_EXPORT std::ostream & operator<<( std::ostream & os, const Signature::Notation & nota ); + +} + +#endif // __GPGMEPP_VERIFICATIONRESULT_H__ |